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.
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));
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".
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
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)
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.
(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.)
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?
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
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
(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..)
No, the kernel does not use this code. --HPS
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
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(-)
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(-)