-
Notifications
You must be signed in to change notification settings - Fork 9.1k
usb: host: fix HS device enumeration and interface probing #106802
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -560,31 +560,31 @@ int usbh_device_init(struct usb_device *const udev) | |
| goto error; | ||
| } | ||
|
|
||
| err = usbh_req_desc_dev(udev, sizeof(udev->dev_desc), &udev->dev_desc); | ||
| err = alloc_device_address(udev, &new_addr); | ||
|
tmon-nordic marked this conversation as resolved.
|
||
| if (err) { | ||
| LOG_ERR("Failed to read device descriptor"); | ||
| LOG_ERR("Failed to allocate device address"); | ||
| goto error; | ||
| } | ||
|
|
||
| if (!udev->dev_desc.bNumConfigurations) { | ||
| LOG_ERR("Device has no configurations, bNumConfigurations %d", | ||
| udev->dev_desc.bNumConfigurations); | ||
| err = usbh_device_set_address(udev, new_addr); | ||
| if (err) { | ||
| goto error; | ||
| } | ||
|
|
||
| err = alloc_device_address(udev, &new_addr); | ||
| LOG_INF("New device with address %u state %u", udev->addr, udev->state); | ||
|
|
||
| err = usbh_req_desc_dev(udev, sizeof(udev->dev_desc), &udev->dev_desc); | ||
|
Comment on lines
+569
to
+576
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
What does it return on third and fourth GET_DESCRIPTOR request?
There will be another non-compliant USB device that fails with new request order tomorrow. What will we change it to then? This absolutely does not seem like the right solution to me.
More compatible to what?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tested repeated GET_DESCRIPTOR at address 0 as requested: Quectel EG916Q-GL (modem): ECM dongle: The modem transfer completes with no error but consistently Verified the reorder does not break the ECM dongle: ECM dongle (with reorder): Quectel modem (with reorder): Both devices enumerate correctly with the reorder.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Again, strictly more compatible to what? How I see it, it does not really "matches the enumeration sequence used by Linux". So what does it mean "more compatible"?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated the commit message. Removed the "Linux (hub_port_init) and xHCI" comparison and the "strictly more compatible" framing. The reorder addresses an enumeration failure on the Quectel EG916Q-GL (returns bNumConfigurations=0 on the 18-byte GET_DESCRIPTOR at address 0); ECM dongle continues to enumerate correctly with the new order. |
||
| if (err) { | ||
| LOG_ERR("Failed to allocate device address"); | ||
| LOG_ERR("Failed to read device descriptor"); | ||
| goto error; | ||
| } | ||
|
|
||
| err = usbh_device_set_address(udev, new_addr); | ||
| if (err) { | ||
| if (!udev->dev_desc.bNumConfigurations) { | ||
| LOG_ERR("Device has no configurations, bNumConfigurations %d", | ||
| udev->dev_desc.bNumConfigurations); | ||
| goto error; | ||
| } | ||
|
|
||
| LOG_INF("New device with address %u state %u", udev->addr, udev->state); | ||
|
|
||
| err = usbh_device_set_configuration(udev, 1); | ||
| if (err) { | ||
| LOG_ERR("Failed to configure new device with address %u", udev->addr); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why incorrectly? I think that is what usbh_desc_get_next_function() should do. @josuah ?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Boot log WITH skip_num=1 (current code):
Claimed 2c7c:6007 iface 0
Claimed 2c7c:6007 iface 2
not matching interface 4
Interfaces 1, 3 never appear - completely skipped.
Boot log WITHOUT skip_num=1 (this fix):
Claimed 2c7c:6007 iface 0
Claimed 2c7c:6007 iface 1
Claimed 2c7c:6007 iface 2
Claimed 2c7c:6007 iface 3
not matching interface 4
All vendor-class interfaces probed.
The issue is that usbh_desc_get_next() already advances
past the current descriptor before the while loop runs.
When called with interface 0:
Interface 1 is skipped because skip_num consumes the
NEXT interface instead of the current one. For IADs this
logic is correct since bInterfaceCount covers grouped
interfaces. For plain interfaces there is nothing to skip.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the long wait.
I see how this is a bug and how it was not visible until a class with only one descriptor per interface triggers it.