Skip to content

Commit 54e472e

Browse files
Josuah DemangeonAidenHu
andcommitted
usb: host: implement class filtering and descriptor browsing
Add utilities to filter a class and search the next descriptor of a given type. This can be used to in combination to seek device information from the USB descriptors and try to match a host class instance given a set of filters. Co-authored-by: Aiden Hu <[email protected]> Signed-off-by: Josuah Demangeon <[email protected]>
1 parent b9717c5 commit 54e472e

File tree

6 files changed

+123
-20
lines changed

6 files changed

+123
-20
lines changed

include/zephyr/usb/usbh.h

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
2-
* Copyright (c) 2022 Nordic Semiconductor ASA
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
* Copyright 2025 NXP
34
*
45
* SPDX-License-Identifier: Apache-2.0
56
*/
@@ -74,18 +75,6 @@ struct usbh_context {
7475
.addr_ba = &ba_##device_name, \
7576
}
7677

77-
/**
78-
* @brief USB Class Code triple
79-
*/
80-
struct usbh_code_triple {
81-
/** Device Class Code */
82-
uint8_t dclass;
83-
/** Class Subclass Code */
84-
uint8_t sub;
85-
/** Class Protocol Code */
86-
uint8_t proto;
87-
};
88-
8978
struct usbh_class_data;
9079

9180
/**
@@ -126,8 +115,8 @@ struct usbh_class_data {
126115
const char *name;
127116
/** Pointer to USB host stack context structure */
128117
struct usbh_context *uhs_ctx;
129-
/** Class code supported by this instance */
130-
struct usbh_code_triple code;
118+
/** System linked list node for registered classes */
119+
sys_snode_t node;
131120
/** Pointer to host support class API */
132121
struct usbh_class_api *api;
133122
/** Pointer to private data */

subsys/usb/host/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ zephyr_library_sources(
99
usbh_ch9.c
1010
usbh_class.c
1111
usbh_core.c
12+
usbh_desc.c
1213
usbh_device.c
1314
)
1415

subsys/usb/host/usbh_class.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,13 @@ bool usbh_class_is_matching(struct usbh_class_filter *const filters, size_t n_fi
6464
for (int i = 0; i < n_filters; i++) {
6565
const struct usbh_class_filter *filt = &filters[i];
6666

67-
if (filt->flags & USBH_CLASS_FILTER_VID) {
67+
if (filt->flags & USBH_CLASS_MATCH_VID) {
6868
if (desc->idVendor != filt->vid) {
6969
continue;
7070
}
7171
}
7272

73-
if (filt->flags & USBH_CLASS_FILTER_PID) {
73+
if (filt->flags & USBH_CLASS_MATCH_PID) {
7474
if (desc->idProduct != filt->pid) {
7575
continue;
7676
}
@@ -83,7 +83,7 @@ bool usbh_class_is_matching(struct usbh_class_filter *const filters, size_t n_fi
8383
}
8484

8585
if (filt->flags & USBH_CLASS_MATCH_SUB) {
86-
if (desc->bDeviceSubclass != filt->sub) {
86+
if (desc->bDeviceSubClass != filt->sub) {
8787
continue;
8888
}
8989
}

subsys/usb/host/usbh_class.h

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,63 @@
1010

1111
#include <zephyr/usb/usbh.h>
1212

13+
/**
14+
* @brief Information about a device, which is relevant for matching a particular class.
15+
*/
16+
struct usbh_class_filter {
17+
/** Vendor ID */
18+
uint16_t vid;
19+
/** Product ID */
20+
uint16_t pid;
21+
/** Device Class Code */
22+
uint8_t dclass;
23+
/** Class Subclass Code */
24+
uint8_t sub;
25+
/** Class Protocol Code */
26+
uint8_t proto;
27+
/** Flags that tell which field to match */
28+
uint8_t flags;
29+
};
30+
1331
/**
1432
* @brief Auto-register all compile-time defined class drivers
1533
*/
16-
int usbh_register_all_classes(struct usbh_context *uhs_ctx);
34+
int usbh_register_all_classes(struct usbh_context *const uhs_ctx);
1735

1836
/**
1937
* @brief Initialize registered class drivers
2038
*/
21-
int usbh_init_registered_classes(struct usbh_context *uhs_ctx);
39+
int usbh_init_registered_classes(struct usbh_context *const uhs_ctx);
40+
41+
/** Match a device's vendor ID */
42+
#define USBH_CLASS_MATCH_VID BIT(1)
43+
44+
/** Match a device's product ID */
45+
#define USBH_CLASS_MATCH_PID BIT(2)
46+
47+
/** Match a class code */
48+
#define USBH_CLASS_MATCH_DCLASS BIT(3)
49+
50+
/** Match a subclass code */
51+
#define USBH_CLASS_MATCH_SUB BIT(4)
52+
53+
/** Match a protocol code */
54+
#define USBH_CLASS_MATCH_PROTO BIT(5)
55+
56+
/** Match a code triple */
57+
#define USBH_CLASS_MATCH_CODE_TRIPLE \
58+
(USBH_CLASS_MATCH_DCLASS | USBH_CLASS_MATCH_SUB | USBH_CLASS_MATCH_PROTO)
59+
60+
/**
61+
* @brief Check if information about a device matches the .
62+
*
63+
* @param filters Array of filters to match the class against.
64+
* @param n_filters Number of filters in the array.
65+
* @param desc Device descriptor with information to match against the filters.
66+
*
67+
* @return true if matched, false otherwise
68+
*/
69+
bool usbh_class_is_matching(struct usbh_class_filter *const filters, size_t n_filters,
70+
struct usb_device_descriptor *const desc);
2271

2372
#endif /* ZEPHYR_INCLUDE_USBD_CLASS_H */

subsys/usb/host/usbh_desc.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
* Copyright NXP
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
#include "usbh_desc.h"
9+
10+
struct usb_desc_header *usbh_desc_get_by_type(const uint8_t *const start_addr,
11+
const uint8_t *const end_addr,
12+
uint32_t type_mask)
13+
{
14+
const uint8_t *curr_addr = start_addr;
15+
16+
while (curr_addr < end_addr) {
17+
struct usb_desc_header *desc = (void *)curr_addr;
18+
19+
if (desc->bLength == 0) {
20+
break;
21+
}
22+
23+
if ((BIT(desc->bDescriptorType) & type_mask) != 0) {
24+
return desc;
25+
}
26+
}
27+
28+
return NULL;
29+
}

subsys/usb/host/usbh_desc.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/**
8+
* @file
9+
* @brief Descriptor matching and searching utilities
10+
*
11+
* This file contains utilities to browse USB descriptors returned by a device
12+
* according to the USB Specification 2.0 Chapter 9.
13+
*/
14+
15+
#ifndef ZEPHYR_INCLUDE_USBH_DESC_H
16+
#define ZEPHYR_INCLUDE_USBH_DESC_H
17+
18+
#include <stdint.h>
19+
20+
#include <zephyr/usb/usbh.h>
21+
22+
/**
23+
* @brief Search the first descriptor matching the selected type(s).
24+
*
25+
* @param[in] start_addr Pointer to the beginning of the descriptor array; to search
26+
* @param[in] end_addr Pointer after the end of the descriptor array to search
27+
* @param[in] type_mask Bitmask of bDescriptorType values to match
28+
*
29+
* @return A pointer to the first descriptor matching
30+
*/
31+
struct usb_desc_header *usbh_desc_get_by_type(const uint8_t *const start_addr,
32+
const uint8_t *const end_addr,
33+
uint32_t type_mask);
34+
35+
#endif /* ZEPHYR_INCLUDE_USBH_DESC_H */

0 commit comments

Comments
 (0)