Skip to content

Commit a871c39

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 1c5825a commit a871c39

File tree

3 files changed

+236
-14
lines changed

3 files changed

+236
-14
lines changed

include/zephyr/usb/usbh.h

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -90,23 +90,26 @@ struct usbh_class_data;
9090
* @brief USB host class instance API
9191
*/
9292
struct usbh_class_api {
93-
/** Initialization of the class implementation */
94-
int (*init)(struct usbh_class_data *const c_data);
93+
/** Host init handler, before any device is connected */
94+
int (*init)(struct usbh_class_data *const c_data,
95+
struct usbh_context *const uhs_ctx);
9596
/** Request completion event handler */
96-
int (*request)(struct usbh_class_data *const c_data,
97-
struct uhc_transfer *const xfer, int err);
98-
/** Device connected handler */
99-
int (*connected)(struct usbh_class_data *const c_data,
100-
void *const desc_start_addr,
101-
void *const desc_end_addr);
102-
/** Device removed handler */
103-
int (*removed)(struct usbh_class_data *const c_data);
104-
/** Bus remote wakeup handler */
105-
int (*rwup)(struct usbh_class_data *const c_data);
97+
int (*completion_cb)(struct usbh_class_data *const c_data,
98+
struct usb_device *const udev,
99+
struct uhc_transfer *const xfer);
100+
/** Device connection handler */
101+
int (*probe)(struct usbh_class_data *const c_data,
102+
struct usb_device *const udev,
103+
const uint8_t iface);
104+
/** Device removal handler */
105+
int (*removed)(struct usbh_class_data *const c_data,
106+
struct usb_device *const udev);
106107
/** Bus suspended handler */
107-
int (*suspended)(struct usbh_class_data *const c_data);
108+
int (*suspended)(struct usbh_class_data *const c_data,
109+
struct usb_device *const udev);
108110
/** Bus resumed handler */
109-
int (*resumed)(struct usbh_class_data *const c_data);
111+
int (*resumed)(struct usbh_class_data *const c_data,
112+
struct usb_device *const udev);
110113
};
111114

112115
/**

subsys/usb/host/usbh_class.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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+
bool usbh_class_is_matching(struct usbh_class_filter *const filters, size_t n_filters,
17+
struct usb_device_descriptor *const desc)
18+
{
19+
for (int i = 0; i < n_filters; i++) {
20+
const struct usbh_class_filter *filt = &filters[i];
21+
22+
if (filt->flags & USBH_CLASS_MATCH_VID) {
23+
if (desc->idVendor != filt->vid) {
24+
continue;
25+
}
26+
}
27+
28+
if (filt->flags & USBH_CLASS_MATCH_PID) {
29+
if (desc->idProduct != filt->pid) {
30+
continue;
31+
}
32+
}
33+
34+
if (filt->flags & USBH_CLASS_MATCH_DCLASS) {
35+
if (desc->bDeviceClass != filt->dclass) {
36+
continue;
37+
}
38+
}
39+
40+
if (filt->flags & USBH_CLASS_MATCH_SUB) {
41+
if (desc->bDeviceSubClass != filt->sub) {
42+
continue;
43+
}
44+
}
45+
46+
if (filt->flags & USBH_CLASS_MATCH_PROTO) {
47+
if (desc->bDeviceProtocol != filt->proto) {
48+
continue;
49+
}
50+
}
51+
52+
/* All the selected filters did match */
53+
return true;
54+
}
55+
56+
/* At the end of the filter table and still no match */
57+
return false;
58+
}

subsys/usb/host/usbh_class_api.h

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
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_cb(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 for every device.
71+
*
72+
* @param[in] c_data Pointer to USB host class data
73+
* @param[in] udev USB device connected
74+
* @param[in] iface The @c bInterfaceNumber or @c bFirstInterface of this class
75+
*
76+
* @return 0 on success, negative error code on failure.
77+
* @return -ENOTSUP if the class is not matching
78+
*/
79+
static inline int usbh_class_probe(struct usbh_class_data *const c_data,
80+
struct usb_device *const udev,
81+
const uint8_t iface)
82+
{
83+
const struct usbh_class_api *api = c_data->api;
84+
85+
if (api->probe != NULL) {
86+
return api->probe(c_data, udev, iface);
87+
}
88+
89+
return -ENOTSUP;
90+
}
91+
92+
/**
93+
* @brief Device removed handler
94+
*
95+
* Called when the device is removed from the bus
96+
* and it matches the class filters of this instance.
97+
*
98+
* @param[in] c_data Pointer to USB host class data
99+
* @param[in] udev USB device connected
100+
*
101+
* @return 0 on success, negative error code on failure.
102+
*/
103+
static inline int usbh_class_removed(struct usbh_class_data *const c_data,
104+
struct usb_device *const udev)
105+
{
106+
const struct usbh_class_api *api = c_data->api;
107+
108+
if (api->removed != NULL) {
109+
return api->removed(c_data, udev);
110+
}
111+
112+
return -ENOTSUP;
113+
}
114+
115+
/**
116+
* @brief Bus suspended handler
117+
*
118+
* Called when the host has suspending the bus.
119+
* It can be used to suspend underlying systems.
120+
*
121+
* @param[in] c_data Pointer to USB host class data
122+
* @param[in] udev USB device connected
123+
*
124+
* @return 0 on success, negative error code on failure.
125+
*/
126+
static inline int usbh_class_suspended(struct usbh_class_data *const c_data,
127+
struct usb_device *const udev)
128+
{
129+
const struct usbh_class_api *api = c_data->api;
130+
131+
if (api->suspended != NULL) {
132+
return api->suspended(c_data, udev);
133+
}
134+
135+
return -ENOTSUP;
136+
}
137+
138+
/**
139+
* @brief Bus resumed handler
140+
*
141+
* Called when the host resumes the activity on a bus.
142+
* It can be used to wake-up underlying systems.
143+
*
144+
* @param[in] c_data Pointer to USB host class data
145+
* @param[in] udev USB device connected
146+
*
147+
* @return 0 on success, negative error code on failure.
148+
*/
149+
static inline int usbh_class_resumed(struct usbh_class_data *const c_data,
150+
struct usb_device *const udev)
151+
{
152+
const struct usbh_class_api *api = c_data->api;
153+
154+
if (api->resumed != NULL) {
155+
return api->resumed(c_data, udev);
156+
}
157+
158+
return -ENOTSUP;
159+
}
160+
161+
#endif /* ZEPHYR_INCLUDE_USBD_CLASS_API_H */

0 commit comments

Comments
 (0)