Skip to content

Commit 052870f

Browse files
author
Josuah Demangeon
committed
usb: host: introduce wrappers to access the class function pointers
Add API wrappers around the function pointers in struct usbh_class_api, while also documenting the USB host class internal API. Signed-off-by: Josuah Demangeon <[email protected]>
1 parent 6bff671 commit 052870f

File tree

3 files changed

+312
-16
lines changed

3 files changed

+312
-16
lines changed

include/zephyr/usb/usbh.h

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -92,23 +92,30 @@ struct usbh_class_data;
9292
* @brief USB host class instance API
9393
*/
9494
struct usbh_class_api {
95-
/** Initialization of the class implementation */
96-
int (*init)(struct usbh_class_data *cdata);
95+
/** Host init handler, before any device is connected */
96+
int (*init)(struct usbh_class_data *const c_data,
97+
struct usbh_context *const uhs_ctx);
9798
/** Request completion event handler */
98-
int (*request)(struct usbh_class_data *cdata,
99-
struct uhc_transfer *const xfer, int err);
100-
/** Device connected handler */
101-
int (*connected)(struct usbh_class_data *cdata,
102-
void *desc_start_addr,
103-
void *desc_end_addr);
104-
/** Device removed handler */
105-
int (*removed)(struct usbh_class_data *cdata);
106-
/** Bus remote wakeup handler */
107-
int (*rwup)(struct usbh_class_data *cdata);
108-
/** Bus suspended handler */
109-
int (*suspended)(struct usbh_class_data *cdata);
110-
/** Bus resumed handler */
111-
int (*resumed)(struct usbh_class_data *cdata);
99+
int (*completion_cb)(struct usbh_class_data *const c_data,
100+
struct usb_device *const udev,
101+
struct uhc_transfer *const xfer);
102+
/** Device connection handler */
103+
int (*probe)(struct usbh_class_data *const c_data,
104+
struct usb_device *const udev,
105+
void *const desc_start_addr,
106+
void *const desc_end_addr);
107+
/** Device removal handler */
108+
int (*removed)(struct usbh_class_data *const c_data,
109+
struct usb_device *const udev);
110+
/** Bus remote wakeup handler */
111+
int (*rwup)(struct usbh_class_data *const c_data,
112+
struct usb_device *const udev);
113+
/** Bus suspended handler */
114+
int (*suspended)(struct usbh_class_data *const c_data,
115+
struct usb_device *const udev);
116+
/** Bus resumed handler */
117+
int (*resumed)(struct usbh_class_data *const c_data,
118+
struct usb_device *const udev);
112119
};
113120

114121
/**

subsys/usb/host/usbh_class.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
* Copyright 2025 NXP
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
#include <zephyr/usb/usbh.h>
9+
#include <zephyr/logging/log.h>
10+
11+
#include "usbh_class.h"
12+
#include "usbh_class_api.h"
13+
14+
LOG_MODULE_REGISTER(usbh_class, CONFIG_USBH_LOG_LEVEL);
15+
16+
int usbh_register_all_classes(struct usbh_context *uhs_ctx)
17+
{
18+
int registered_count = 0;
19+
20+
STRUCT_SECTION_FOREACH(usbh_class_data, c_data_existing) {
21+
struct usbh_class_data *c_data_registered;
22+
bool already_registered = false;
23+
24+
/* Check if already registered */
25+
SYS_SLIST_FOR_EACH_CONTAINER(&uhs_ctx->class_list, c_data_registered, node) {
26+
if (c_data_existing == c_data_registered) {
27+
already_registered = true;
28+
break;
29+
}
30+
}
31+
32+
if (!already_registered) {
33+
sys_slist_append(&uhs_ctx->class_list, &c_data_existing->node);
34+
registered_count++;
35+
LOG_DBG("Auto-registered class: %s", c_data_existing->name);
36+
}
37+
}
38+
39+
LOG_INF("Auto-registered %d classes to controller %s",
40+
registered_count, uhs_ctx->name);
41+
42+
return 0;
43+
}
44+
45+
int usbh_init_registered_classes(struct usbh_context *uhs_ctx)
46+
{
47+
struct usbh_class_data *c_data;
48+
int ret;
49+
50+
SYS_SLIST_FOR_EACH_CONTAINER(&uhs_ctx->class_list, c_data, node) {
51+
ret = usbh_class_init(c_data, uhs_ctx);
52+
if (ret != 0) {
53+
LOG_ERR("Failed to initialize class instance");
54+
return ret;
55+
}
56+
}
57+
58+
return 0;
59+
}
60+
61+
bool usbh_class_is_matching(struct usbh_class_filter *const filters, size_t n_filters,
62+
struct usb_device_descriptor *const desc)
63+
{
64+
for (int i = 0; i < n_filters; i++) {
65+
const struct usbh_class_filter *filt = &filters[i];
66+
67+
if (filt->flags & USBH_CLASS_FILTER_VID) {
68+
if (desc->idVendor != filt->vid) {
69+
continue;
70+
}
71+
}
72+
73+
if (filt->flags & USBH_CLASS_FILTER_PID) {
74+
if (desc->idProduct != filt->pid) {
75+
continue;
76+
}
77+
}
78+
79+
if (filt->flags & USBH_CLASS_MATCH_DCLASS) {
80+
if (desc->bDeviceClass != filt->dclass) {
81+
continue;
82+
}
83+
}
84+
85+
if (filt->flags & USBH_CLASS_MATCH_SUB) {
86+
if (desc->bDeviceSubclass != filt->sub) {
87+
continue;
88+
}
89+
}
90+
91+
if (filt->flags & USBH_CLASS_MATCH_PROTO) {
92+
if (desc->bDeviceProtocol != filt->proto) {
93+
continue;
94+
}
95+
}
96+
97+
/* All the selected filters did match */
98+
return true;
99+
}
100+
101+
/* At the end of the filter table and still no match */
102+
return false;
103+
}

subsys/usb/host/usbh_class_api.h

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/**
8+
* @file
9+
* @brief USB host stack class instances API
10+
*
11+
* This file contains the USB host stack class instances API.
12+
*/
13+
14+
#ifndef ZEPHYR_INCLUDE_USBH_CLASS_API_H
15+
#define ZEPHYR_INCLUDE_USBH_CLASS_API_H
16+
17+
#include <zephyr/usb/usbh.h>
18+
19+
/**
20+
* @brief Initialization of the class implementation
21+
*
22+
* This is called for each instance during the initialization phase,
23+
* for every registered class.
24+
* It can be used to initialize underlying systems.
25+
*
26+
* @param[in] c_data Pointer to USB host class data
27+
* @param[in] uhs_ctx USB host context to assign to this class
28+
*
29+
* @return 0 on success, negative error code on failure.
30+
*/
31+
static inline int usbh_class_init(struct usbh_class_data *const c_data,
32+
struct usbh_context *const uhs_ctx)
33+
{
34+
const struct usbh_class_api *api = c_data->api;
35+
36+
if (api->init != NULL) {
37+
return api->init(c_data, uhs_ctx);
38+
}
39+
40+
return -ENOTSUP;
41+
}
42+
43+
/**
44+
* @brief Request completion event handler
45+
*
46+
* Called upon completion of a request made by the host to this class.
47+
*
48+
* @param[in] c_data Pointer to USB host class data
49+
* @param[in] udev USB device connected
50+
* @param[in] xfer Completed transfer
51+
*
52+
* @return 0 on success, negative error code on failure.
53+
*/
54+
static inline int usbh_class_completion(struct usbh_class_data *const c_data,
55+
struct usb_device *const udev,
56+
struct uhc_transfer *const xfer)
57+
{
58+
const struct usbh_class_api *api = c_data->api;
59+
60+
if (api->completion_cb != NULL) {
61+
return api->completion_cb(c_data, udev, xfer);
62+
}
63+
64+
return -ENOTSUP;
65+
}
66+
67+
/**
68+
* @brief Device initialization handler
69+
*
70+
* Called when a device is connected to the bus
71+
* and it matches the class filters of this instance.
72+
*
73+
* @param[in] c_data Pointer to USB host class data
74+
* @param[in] udev USB device connected
75+
* @param[in] desc_beg Pointer to the first byte of the descriptor
76+
* @param[in] desc_end Pointer after the last byte of the USB descriptor
77+
*
78+
* @return 0 on success, negative error code on failure.
79+
*/
80+
static inline int usbh_class_probe(struct usbh_class_data *const c_data,
81+
struct usb_device *const udev,
82+
void *const desc_beg,
83+
void *const desc_end)
84+
{
85+
const struct usbh_class_api *api = c_data->api;
86+
87+
if (api->probe != NULL) {
88+
return api->probe(c_data, udev, desc_beg, desc_end);
89+
}
90+
91+
return -ENOTSUP;
92+
}
93+
94+
/**
95+
* @brief Device removed handler
96+
*
97+
* Called when the device is removed from the bus
98+
* and it matches the class filters of this instance.
99+
*
100+
* @param[in] c_data Pointer to USB host class data
101+
* @param[in] udev USB device connected
102+
*
103+
* @return 0 on success, negative error code on failure.
104+
*/
105+
static inline int usbh_class_removed(struct usbh_class_data *const c_data,
106+
struct usb_device *const udev)
107+
{
108+
const struct usbh_class_api *api = c_data->api;
109+
110+
if (api->removed != NULL) {
111+
return api->removed(c_data, udev);
112+
}
113+
114+
return -ENOTSUP;
115+
}
116+
117+
/**
118+
* @brief Bus remote wakeup handler
119+
*
120+
* Called when the device trigger a remote wakeup to the host.
121+
* and it matches the class filters.
122+
*
123+
* @param[in] c_data Pointer to USB host class data
124+
* @param[in] udev USB device connected
125+
*
126+
* @return 0 on success, negative error code on failure.
127+
*/
128+
static inline int usbh_class_rwup(struct usbh_class_data *const c_data,
129+
struct usb_device *const udev)
130+
{
131+
const struct usbh_class_api *api = c_data->api;
132+
133+
if (api->rwup != NULL) {
134+
return api->rwup(c_data, udev);
135+
}
136+
137+
return -ENOTSUP;
138+
}
139+
140+
/**
141+
* @brief Bus suspended handler
142+
*
143+
* Called when the host has suspending the bus.
144+
* It can be used to suspend underlying systems.
145+
*
146+
* @param[in] c_data Pointer to USB host class data
147+
* @param[in] udev USB device connected
148+
*
149+
* @return 0 on success, negative error code on failure.
150+
*/
151+
static inline int usbh_class_suspended(struct usbh_class_data *const c_data,
152+
struct usb_device *const udev)
153+
{
154+
const struct usbh_class_api *api = c_data->api;
155+
156+
if (api->suspended != NULL) {
157+
return api->suspended(c_data, udev);
158+
}
159+
160+
return -ENOTSUP;
161+
}
162+
163+
/**
164+
* @brief Bus resumed handler
165+
*
166+
* Called when the host resumes the activity on a bus.
167+
* It can be used to wake-up underlying systems.
168+
*
169+
* @param[in] c_data Pointer to USB host class data
170+
* @param[in] udev USB device connected
171+
*
172+
* @return 0 on success, negative error code on failure.
173+
*/
174+
static inline int usbh_class_resumed(struct usbh_class_data *const c_data,
175+
struct usb_device *const udev)
176+
{
177+
const struct usbh_class_api *api = c_data->api;
178+
179+
if (api->resumed != NULL) {
180+
return api->resumed(c_data, udev);
181+
}
182+
183+
return -ENOTSUP;
184+
}
185+
186+
#endif /* ZEPHYR_INCLUDE_USBD_CLASS_API_H */

0 commit comments

Comments
 (0)