Failed control transfer

From: Daniel O'Connor <darius_at_dons.net.au>
Date: Tue, 11 Oct 2022 04:18:57 UTC
Hi,
I am trying to fix a bug in xc3sprog whereby it can't read the hardware ID (serial number) from the Xilinx programming tool.

It works fine on MacOS and Linux but on FreBSD it fails with ENODEV, eg..
In [1]: import usb.core
In [2]: d = usb.core.find(idVendor = 0x03fd, idProduct = 0x0008)
In [4]: d.ctrl_transfer(0xc0, 176, 0x42, 0, 8, 1000)
---------------------------------------------------------------------------
USBError                                  Traceback (most recent call last)
<snip>
USBError: [Errno 19] No device

Other control commands work fine:
In [5]: d.ctrl_transfer(0xc0, 176, 0x50, 258, 2, 100)
Out[5]: array('B', [5, 0])

On MacOS it looks like:
In [4]: d.ctrl_transfer(0xc0, 176, 0x42, 0, 8, 1000)
Out[4]: array('B', [1, 191, 125, 103, 18, 0, 0, 140])

(I did the tests in Python as it's easier for isolation)

Also, the device works fine for programming FPGAs and the like so it seems quite peculiar that only this command fails.

I had a dig through the USB kernel stack and libusb code (the Python code is using libusb.so.3 FWIW) but I could not find anywhere relevant that set errno to ENODEV.

Output of sudo usbdump -d 0.4 -s 65535 -v -v:

04:15:17.243800 usbus0.4 SUBM-CTRL-EP=00000080,SPD=HIGH,NFR=2,SLEN=8,IVAL=0
 frame[0] WRITE 8 bytes
 0000  C0 B0 42 00 00 00 08 00  -- -- -- -- -- -- -- --  |..B.....        |
 frame[1] READ 8 bytes
 flags 0x2 <SHORT_XFER_OK|0>
04:15:17.246029 usbus0.4 DONE-CTRL-EP=00000080,SPD=HIGH,NFR=2,SLEN=0,IVAL=0,ERR=STALLED
 frame[0] WRITE 8 bytes
 frame[1] READ 0 bytes
 flags 0x2 <SHORT_XFER_OK|0>

I ran usbmon on Linux and this is the Wireshark output of the request:
Frame 13: 64 bytes on wire (512 bits), 64 bytes captured (512 bits)
USB URB
    [Source: host]
    [Destination: 1.5.0]
    URB id: 0xffff9d9103b47440
    URB type: URB_SUBMIT ('S')
    URB transfer type: URB_CONTROL (0x02)
    Endpoint: 0x80, Direction: IN
    Device: 5
    URB bus id: 1
    Device setup request: relevant ('\0')
    Data: not present ('<')
    URB sec: 1665455649
    URB usec: 867346
    URB status: Operation now in progress (-EINPROGRESS) (-115)
    URB length [bytes]: 8
    Data length [bytes]: 0
    [Response in: 14]
    Interval: 0
    Start frame: 0
    Copy of Transfer Flags: 0x00000200, Dir IN
    Number of ISO descriptors: 0
    [bInterfaceClass: Unknown (0xffff)]
Setup Data
    bmRequestType: 0xc0
    bRequest: 176
    wValue: 0x0042
    wIndex: 0 (0x0000)
    wLength: 8

And the reply:
Frame 14: 72 bytes on wire (576 bits), 72 bytes captured (576 bits)
USB URB
    [Source: 1.5.0]
    [Destination: host]
    URB id: 0xffff9d9103b47440
    URB type: URB_COMPLETE ('C')
    URB transfer type: URB_CONTROL (0x02)
    Endpoint: 0x80, Direction: IN
    Device: 5
    URB bus id: 1
    Device setup request: not relevant ('-')
    Data: present ('\0')
    URB sec: 1665455649
    URB usec: 879077
    URB status: Success (0)
    URB length [bytes]: 8
    Data length [bytes]: 8
    [Request in: 13]
    [Time from request: 0.011731000 seconds]
    Unused Setup Header
    Interval: 0
    Start frame: 0
    Copy of Transfer Flags: 0x00000200, Dir IN
    Number of ISO descriptors: 0
    [bInterfaceClass: Unknown (0xffff)]
CONTROL response data: 01bf7d671200008c

Unfortunately I can't find any reason why it works on MacOS and Linux but not FreeBSD.. Does anyone have any suggestions?

Thanks.

--
Daniel O'Connor
"The nice thing about standards is that there
are so many of them to choose from."
-- Andrew Tanenbaum