Skip to content

Commit 696d3da

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 4921e0f commit 696d3da

File tree

6 files changed

+139
-3
lines changed

6 files changed

+139
-3
lines changed

include/zephyr/usb/usbh.h

Lines changed: 27 additions & 3 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
*/
@@ -111,6 +112,29 @@ struct usbh_class_api {
111112
int (*resumed)(struct usbh_class_data *cdata);
112113
};
113114

115+
/** Match a class code triple */
116+
#define USBH_CLASS_FILTER_CODE_TRIPLE BIT(0)
117+
118+
/** Match a device's vendor ID */
119+
#define USBH_CLASS_FILTER_VID BIT(1)
120+
121+
/** Match a device's product ID */
122+
#define USBH_CLASS_FILTER_PID BIT(2)
123+
124+
/**
125+
* @brief Filter rule for matching a host class instance to a device class
126+
*/
127+
struct usbh_class_filter {
128+
/** Mask of match types for selecting which rules to apply */
129+
uint32_t flags;
130+
/** The device's class code, subclass code, protocol code. */
131+
struct usbh_code_triple code_triple;
132+
/** Vendor ID */
133+
uint16_t vid;
134+
/** Product ID */
135+
uint16_t pid;
136+
};
137+
114138
/**
115139
* @brief USB host class instance data
116140
*/
@@ -121,8 +145,8 @@ struct usbh_class_data {
121145
struct usbh_context *uhs_ctx;
122146
/** System linked list node for registered classes */
123147
sys_snode_t node;
124-
/** Class code supported by this instance */
125-
struct usbh_code_triple code;
148+
/** Table of filter rules used to match device classes */
149+
const struct usbh_class_filter *filters;
126150
/** Pointer to host support class API */
127151
struct usbh_class_api *api;
128152
/** 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: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,39 @@ int usbh_init_registered_classes(struct usbh_context *uhs_ctx)
5757

5858
return 0;
5959
}
60+
61+
bool usbh_class_is_matching(struct usbh_class_data *cdata,
62+
struct usbh_class_filter *device_info)
63+
{
64+
/* Traverse the filter table until a terminator (empty flags) is found */
65+
for (int i = 0; cdata->filters[i].flags != 0; i++) {
66+
const struct usbh_class_filter *filter = &cdata->filters[i];
67+
68+
if (filter->flags & USBH_CLASS_FILTER_VID) {
69+
if (filter->vid != device_info->vid) {
70+
continue;
71+
}
72+
}
73+
74+
if (filter->flags & USBH_CLASS_FILTER_VID) {
75+
if (filter->vid == device_info->vid) {
76+
continue;
77+
}
78+
}
79+
80+
if (filter->flags & USBH_CLASS_FILTER_CODE_TRIPLE) {
81+
if (filter->code_triple.dclass != device_info->code_triple.dclass ||
82+
(filter->code_triple.sub != 0xFF &&
83+
filter->code_triple.sub != device_info->code_triple.sub) ||
84+
(filter->code_triple.proto != 0x00 &&
85+
filter->code_triple.proto != device_info->code_triple.proto)) {
86+
continue;
87+
}
88+
}
89+
90+
/* All the filters enabled did match */
91+
return true;
92+
}
93+
94+
return false;
95+
}

subsys/usb/host/usbh_class.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,15 @@ int usbh_register_all_classes(struct usbh_context *uhs_ctx);
2020
*/
2121
int usbh_init_registered_classes(struct usbh_context *uhs_ctx);
2222

23+
/**
24+
* @brief Check if a device's descriptor information matches a host class instance
25+
*
26+
* @param cdata Pointer to class driver data
27+
* @param device_info Information from the device descriptors
28+
*
29+
* @return true if matched, false otherwise
30+
*/
31+
bool usbh_class_is_matching(struct usbh_class_data *cdata,
32+
struct usbh_class_filter *device_info);
33+
2334
#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)