Bug 251784 - USB_DO_REQUEST ERR#5 'Input/output error' for 0x0b05:0x18f3 ASUS AURA LED Controller
Summary: USB_DO_REQUEST ERR#5 'Input/output error' for 0x0b05:0x18f3 ASUS AURA LED Con...
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: usb (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Only Me
Assignee: Hans Petter Selasky
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-12-12 15:02 UTC by Val Packett
Modified: 2020-12-28 12:40 UTC (History)
1 user (show)

See Also:


Attachments
aura-openrgb.usbdump (4.43 KB, application/octet-stream)
2020-12-12 15:02 UTC, Val Packett
no flags Details
aura-hid.usbdump (800 bytes, application/octet-stream)
2020-12-12 15:03 UTC, Val Packett
no flags Details
aura-openrgb-windows.pcapng (6.70 KB, application/x-pcapng)
2020-12-12 15:06 UTC, Val Packett
no flags Details
aura-reset.usbdump (10.73 KB, application/octet-stream)
2020-12-12 21:56 UTC, Val Packett
no flags Details
aura-usblyzer.jpg (217.08 KB, image/jpeg)
2020-12-12 22:02 UTC, Val Packett
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Val Packett 2020-12-12 15:02:14 UTC
Created attachment 220490 [details]
aura-openrgb.usbdump

Somehow FreeBSD's usb stack doesn't seem to like this device:

ugen0.3: <AsusTek Computer Inc. AURA LED Controller> at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (16mA)

The HID descriptors are readable, but communication fails.

https://gitlab.com/CalcProgrammer1/OpenRGB (uses hidapi->libusb) does not manage to enumerate it (get firmware revision):

openat(AT_FDCWD,"/dev/ugen0.3",O_RDWR,00)        = 5 (0x5)
…
ioctl(5,USB_DO_REQUEST,0x7fffdfdfc708)           ERR#5 'Input/output error'
poll({ 3/POLLIN 6/POLLIN|POLLOUT|POLLRDNORM },2,-1) = 1 (0x1)
read(3,0x7fffdf9faf0f,1)                         ERR#35 'Resource temporarily unavailable'
ioctl(6,USB_FS_COMPLETE,0x7fffdf9fae78)          = 0 (0x0)
ioctl(6,USB_FS_COMPLETE,0x7fffdf9fae78)          ERR#16 'Device busy'
ioctl(6,USB_FS_START,0x7fffdf9fadb0)             = 0 (0x0)

Looking at the usbdump, after we send the firmware version query (shows up as packet number 20 in wireshark, length 220, data with the EC 82 00 00 00 .. bunch of zeros), what we get back is Error: Stalled, so that is why the I/O error.
Comment 1 Val Packett 2020-12-12 15:03:41 UTC
Created attachment 220491 [details]
aura-hid.usbdump

Same thing with a tiny example using hidraw (https://github.com/wulf7/iichid) like this:

	int fd = open("/dev/hidraw1", O_RDWR);
	unsigned char usb_buf[65] = {0};
	memset(usb_buf, 0x00, sizeof(usb_buf));

	usb_buf[0x00]   = 0xEC;
	usb_buf[0x01]   = 0x82;

	fprintf(stderr, "wr %ld\n", write(fd, usb_buf, 65));
	fprintf(stderr, "rd %ld\n", read(fd, usb_buf, 65));
Comment 2 Val Packett 2020-12-12 15:06:29 UTC
Created attachment 220492 [details]
aura-openrgb-windows.pcapng

Same device on the same machine does enumerate in OpenRGB on Windows 10.

Capture format is pretty different with USBpcap, but we see the EC 82 00 00 .. data in the SET_REPORT Request, then there is a blank successful "SET_REPORT Response" and the data in "URB_INTERRUPT in".
Comment 3 Hans Petter Selasky freebsd_committer freebsd_triage 2020-12-12 20:03:08 UTC
Hi,

STALLED means that the USB device does not support the command in question.

Can you capture the full enumeration sequence. 

I.E. start usbdump before plugging the device.

Also please compare the two traces. I cannot find that the windows driver issues the following control request at all:

14:42:27.838608 usbus0.3 SUBM-CTRL-EP=00000000,SPD=FULL,NFR=2,SLEN=76,IVAL=0
 frame[0] WRITE 8 bytes
 0000  21 09 00 02 02 00 41 00  -- -- -- -- -- -- -- --  |!.....A.        |

The 8 bytes are the 8 bytes of the so-called SETUP packet.

Does this device work with webcamd in FreeBSD ports, if you attach it manually?

--HPS
Comment 4 Val Packett 2020-12-12 21:56:10 UTC
Created attachment 220515 [details]
aura-reset.usbdump

(In reply to Hans Petter Selasky from comment #3)

> before plugging the device

That's not possible, the device is an embedded microcontroller soldered to the PC's mainboard :)

Here's a dump started before `usbconfig -d ugen0.3 reset`, and with no iichid/uhid/anything attaching *at all*, ugen only.

> webcamd

What would webcamd do? This is *not* an actual input device, this is custom protocol over HID, which is why I mention hidapi->libusb and hidraw.

> the following control request

Hm. In the windows pcap, in the SET_REPORT Request, there is somewhat similar data indeed before the EC 82 00 00.

We have this

 0000  21 09 EC 02 01 00 41 00  -- -- -- -- -- -- -- --  |!.....A.        |

and Windows has

0000   21 09 ec 02 02 00 41 00

this is parsed in Wireshark as the Setup Data fields, and the EC 82 00 00 .. "frame" is in the Windows pcap as the Data Fragment under the Setup Data.

Now, the field with the difference (02 00 vs 01 00) is recognized by Wireshark as "wIndex".

From a quick search in iichid code, wIndex for HID SET_REPORT is the USB interface number (uaa->info.bIfaceNum).

usbconfig dump_all_desc recognizes Interface 0 as Vendor Specific, and Interface 1 as HID.
(Indexes and numbers match: bInterfaceNumber = 0x0001 for Interface 1, similarly with zero.)

So Windows is actually detecting HID as Interface 2.

Did… did FreeBSD's USB descriptor parser *miss* a whole interface?

Can I easily dump the raw binary that gets parsed into the dump_all_desc output? (I guess I'll do this in Windows first)
Comment 5 Val Packett 2020-12-12 22:02:03 UTC
Created attachment 220516 [details]
aura-usblyzer.jpg

Oh no it didn't. But the HID interface does actually have number 2 instead of 1, because ASUS is awesome :/

USBlyzer highlights that field in red and says "Should be smaller than the total number of interfaces for the configuration". (See screenshot.)

But Windows still reports the actual interface number reported by the device instead of "correcting" it into a value that won't work.
Comment 6 Val Packett 2020-12-12 22:08:51 UTC
(And judging by the fact that nobody complained about this not working on Linux in the OpenRGB bug tracker, unless this bug was added in a very recent firmware update, Linux tolerates this brokenness too.)
Comment 7 Val Packett 2020-12-12 22:30:21 UTC
So, turns out libusb does its own descriptor parsing, I can fix this in libusb:

--- i/lib/libusb/libusb20_desc.c
+++ w/lib/libusb/libusb20_desc.c
@@ -208,10 +208,9 @@ libusb20_parse_config_desc(const void *config_desc)
 			}
 			/*
 			 * Sometimes USB devices have corrupt interface
-			 * descriptors and we need to overwrite the provided
-			 * interface number!
+			 * descriptors. Do not overwrite the provided
+			 * interface number though!
 			 */
-			last_if->desc.bInterfaceNumber = niface - 1;
 			last_if->extra.ptr = LIBUSB20_ADD_BYTES(ptr, ptr[0]);
 			last_if->extra.len = 0;
 			last_if->extra.type = LIBUSB20_ME_IS_RAW;

…aaand huh. This changes the number in usbconfig dump_all_desc too.
TIL usbconfig uses libusb :)

Now, this shouldn't fix it for uhid/hidraw usage (and I'd like to eventually get hidapi-hidraw working maybe) I guess?

But I can't find 'bInterfaceNumber =' in kernel code at all. Who assigns that?
Comment 8 Hans Petter Selasky freebsd_committer freebsd_triage 2020-12-13 09:06:36 UTC
That value comes from the device itself :-)

I need to think a bit about changing this value to something else. It affects many parts of the kernel making assumptions about this field.

See:
https://www.spinics.net/lists/linux-usb-devel/msg11325.html

--HPS
Comment 9 Hans Petter Selasky freebsd_committer freebsd_triage 2020-12-13 18:34:51 UTC
After looking at clients like webcamd, I see the change you propose won't cause any serious harm. Do you want me to push a fix?

--HPS
Comment 10 Val Packett 2020-12-14 11:03:56 UTC
(In reply to Hans Petter Selasky from comment #9)

Sure, that would be nice.

(Also, does the kernel use this code too or something? Still can't find anything else that fills out this field..)
Comment 11 Hans Petter Selasky freebsd_committer freebsd_triage 2020-12-14 11:07:01 UTC
No, the kernel does not use this code.

--HPS
Comment 12 commit-hook freebsd_committer freebsd_triage 2020-12-14 11:57:03 UTC
A commit references this bug:

Author: hselasky
Date: Mon Dec 14 11:56:17 UTC 2020
New revision: 368632
URL: https://svnweb.freebsd.org/changeset/base/368632

Log:
  Be bug compatible with other operating systems by allowing non-sequential
  interface numbering for USB descriptors in userspace. Else certain USB
  control requests using the interface number, won't be recognized by the
  USB firmware.

  Refer to section 9.2.3 in the USB 2.0 specification:
  Interfaces are numbered from zero to one less than the number of concurrent interfaces
  supported by the configuration.

  PR:		251784
  MFC after:	1 week
  Sponsored by:	Mellanox Technologies // NVIDIA Networking

Changes:
  head/lib/libusb/libusb20_desc.c
Comment 13 commit-hook freebsd_committer freebsd_triage 2020-12-28 12:39:11 UTC
A commit in branch stable/11 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=1952bc128c9903a1a2985063685268522e995c14

commit 1952bc128c9903a1a2985063685268522e995c14
Author:     Hans Petter Selasky <hselasky@FreeBSD.org>
AuthorDate: 2020-12-14 11:56:16 +0000
Commit:     Hans Petter Selasky <hselasky@FreeBSD.org>
CommitDate: 2020-12-28 12:38:06 +0000

    MFC r368632:
    Be bug compatible with other operating systems by allowing non-sequential
    interface numbering for USB descriptors in userspace. Else certain USB
    control requests using the interface number, won't be recognized by the
    USB firmware.

    Refer to section 9.2.3 in the USB 2.0 specification:
    Interfaces are numbered from zero to one less than the number of concurrent interfaces
    supported by the configuration.

    PR:             251784
    Sponsored by:   Mellanox Technologies // NVIDIA Networking

 lib/libusb/libusb20_desc.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)
Comment 14 commit-hook freebsd_committer freebsd_triage 2020-12-28 12:40:12 UTC
A commit in branch stable/12 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=931b121469a940147e34279783be6ac7343a980c

commit 931b121469a940147e34279783be6ac7343a980c
Author:     Hans Petter Selasky <hselasky@FreeBSD.org>
AuthorDate: 2020-12-14 11:56:16 +0000
Commit:     Hans Petter Selasky <hselasky@FreeBSD.org>
CommitDate: 2020-12-28 12:39:04 +0000

    MFC r368632:
    Be bug compatible with other operating systems by allowing non-sequential
    interface numbering for USB descriptors in userspace. Else certain USB
    control requests using the interface number, won't be recognized by the
    USB firmware.

    Refer to section 9.2.3 in the USB 2.0 specification:
    Interfaces are numbered from zero to one less than the number of concurrent interfaces
    supported by the configuration.

    PR:             251784
    Sponsored by:   Mellanox Technologies // NVIDIA Networking

 lib/libusb/libusb20_desc.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)