@@ -90,7 +90,7 @@ static int usbh_match_classes(struct usbh_context *const ctx,
90
90
/* Step 1: Find first IAD or interface descriptor from start_addr */
91
91
mask = BIT (USB_DESC_INTERFACE ) | BIT (USB_DESC_INTERFACE_ASSOC );
92
92
93
- desc = usbh_desc_get_by_type (start_addr , end_addr , mask );
93
+ desc = usbh_desc_get_by_type (start_addr , desc_buf_end , mask );
94
94
if (desc == NULL ) {
95
95
LOG_ERR ("No IAD or interface descriptor found - error condition" );
96
96
break ;
@@ -99,6 +99,7 @@ static int usbh_match_classes(struct usbh_context *const ctx,
99
99
100
100
if (desc -> bDescriptorType == USB_DESC_INTERFACE_ASSOC ) {
101
101
found_iad = true;
102
+ iad_desc = desc ;
102
103
}
103
104
104
105
if (desc -> bDescriptorType == USB_DESC_INTERFACE ) {
@@ -111,11 +112,11 @@ static int usbh_match_classes(struct usbh_context *const ctx,
111
112
}
112
113
113
114
/* Step 2: Continue searching for subsequent descriptors to determine end_addr */
114
- start_addr += ((struct usb_desc_header * )start_addr )-> bLength ;
115
+ uint8_t * search_start = start_addr + ((struct usb_desc_header * )start_addr )-> bLength ;
115
116
116
117
/* Find next IAD */
117
118
mask = BIT (USB_DESC_INTERFACE_ASSOC );
118
- desc = usbh_desc_get_by_type (start_addr , end_addr , mask );
119
+ desc = usbh_desc_get_by_type (search_start , desc_buf_end , mask );
119
120
next_iad_addr = (uint8_t * )desc ;
120
121
121
122
/* Handle different cases and determine end_addr and device_info. */
@@ -130,11 +131,10 @@ static int usbh_match_classes(struct usbh_context *const ctx,
130
131
} else if (found_iad && next_iad_addr ) {
131
132
/* Case 2c: Found IAD in step 1, found new IAD in subsequent descriptors */
132
133
end_addr = next_iad_addr ;
133
- start_addr += iad_desc -> bLength ;
134
134
135
135
/* Get class code from first interface after IAD */
136
- mask = BIT (USB_DESC_INTERFACE_ASSOC );
137
- desc = usbh_desc_get_by_type (start_addr , end_addr , mask );
136
+ mask = BIT (USB_DESC_INTERFACE );
137
+ desc = usbh_desc_get_by_type (search_start , end_addr , mask );
138
138
if (desc != NULL ) {
139
139
struct usb_if_descriptor * if_desc = (void * )desc ;
140
140
@@ -145,28 +145,33 @@ static int usbh_match_classes(struct usbh_context *const ctx,
145
145
} else if (found_iad && !next_iad_addr ) {
146
146
/* Case 2d: Found IAD in step 1, no new IAD in subsequent descriptors */
147
147
/* Get class code from first interface after IAD */
148
- start_addr += iad_desc -> bLength ;
149
148
mask = BIT (USB_DESC_INTERFACE );
150
- desc = usbh_desc_get_by_type (start_addr , end_addr , mask );
149
+ desc = usbh_desc_get_by_type (search_start , desc_buf_end , mask );
151
150
if (desc != NULL ) {
152
- struct usb_if_descriptor * if_desc = (void * )start_addr ;
151
+ struct usb_if_descriptor * if_desc = (void * )desc ;
153
152
154
153
device_info .code_triple .dclass = if_desc -> bInterfaceClass ;
155
154
device_info .code_triple .sub = if_desc -> bInterfaceSubClass ;
156
155
device_info .code_triple .proto = if_desc -> bInterfaceProtocol ;
157
- }
158
-
159
- /* Search for interface descriptor with different class code after IAD */
160
- start_addr += iad_desc -> bLength ;
161
- mask = BIT (USB_DESC_INTERFACE );
162
- desc = usbh_desc_get_by_type (start_addr , desc_buf_end , mask );
163
- if (desc != NULL ) {
164
- struct usb_if_descriptor * if_desc = (void * )desc ;
165
156
166
- /* Only compare class code */
167
- if (if_desc -> bInterfaceClass != device_info .code_triple .dclass ) {
157
+ /* Search for interface descriptor with different class code after IAD */
158
+ uint8_t * next_search = (uint8_t * )desc + desc -> bLength ;
159
+ mask = BIT (USB_DESC_INTERFACE );
160
+ desc = usbh_desc_get_by_type (next_search , desc_buf_end , mask );
161
+ if (desc != NULL ) {
162
+ struct usb_if_descriptor * if_desc = (void * )desc ;
163
+
164
+ /* Only compare class code */
165
+ if (if_desc -> bInterfaceClass != device_info .code_triple .dclass ) {
166
+ end_addr = (uint8_t * )desc ;
167
+ } else {
168
+ end_addr = desc_buf_end ;
169
+ }
170
+ } else {
168
171
end_addr = desc_buf_end ;
169
172
}
173
+ } else {
174
+ end_addr = desc_buf_end ;
170
175
}
171
176
}
172
177
@@ -185,7 +190,7 @@ static int usbh_match_classes(struct usbh_context *const ctx,
185
190
cdata -> name , device_info .code_triple .dclass );
186
191
187
192
/* Step 4: Call connected handler */
188
- int ret = usbh_class_connected (cdata , start_addr , end_addr );
193
+ int ret = usbh_class_connected (udev , cdata , start_addr , end_addr );
189
194
if (ret == 0 ) {
190
195
LOG_INF ("Class driver %s successfully claimed device" , cdata -> name );
191
196
matched = true;
@@ -256,6 +261,22 @@ static void dev_connected_handler(struct usbh_context *const ctx,
256
261
static void dev_removed_handler (struct usbh_context * const ctx )
257
262
{
258
263
if (ctx -> root != NULL ) {
264
+ LOG_DBG ("Device removed - notifying class drivers" );
265
+
266
+ /* Notify all relevant class drivers that device is disconnected */
267
+ struct usbh_class_data * cdata ;
268
+ SYS_SLIST_FOR_EACH_CONTAINER (& ctx -> class_list , cdata , node ) {
269
+ LOG_DBG ("Calling disconnected for class driver: %s" , cdata -> name );
270
+ int ret = usbh_class_removed (ctx -> root , cdata );
271
+ if (ret != 0 ) {
272
+ LOG_WRN ("Class driver %s disconnected callback failed: %d" ,
273
+ cdata -> name , ret );
274
+ } else {
275
+ LOG_INF ("Class driver %s successfully disconnected" , cdata -> name );
276
+ }
277
+ }
278
+
279
+ /* Free device resources */
259
280
usbh_device_free (ctx -> root );
260
281
ctx -> root = NULL ;
261
282
LOG_DBG ("Device removed" );
0 commit comments