EEVblog Electronics Community Forum

Products => Computers => Programming => Topic started by: DiTBho on June 12, 2022, 11:47:43 pm

Title: Libusb-v1 (linux) && URB_CONTROL_VENDOR_OR_CLASS_REQUEST
Post by: DiTBho on June 12, 2022, 11:47:43 pm
I am reverse engineering a USB device on a Windows XP machine with USBtrace-v3
And on the USB-packet sniffer I see a lot of transfers like this
Code: [Select]
URB_FUNCTION_VENDOR_DEVICE

Length: 0x50
USBD Status: USBD_STATUS_UNKNOWN (0x8861FC88)
TransferFlags: 0x0 ( USBD_TRANSFER_DIRECTION_OUT )
TransferBufferLength: 0x26
TransferBuffer: 0xBA50F904
TransferBufferMDL: 0x0
UrbLink: 0x0
RequestTypeReservedBits: 0x0
Request: 0xA0
Value: 0x240A
Index: 0x0

** Data **
C1 0A C1 0B C1 0C 01 14 00 01 11 00 C1 09 01 0A 00 02 15 00 00 C1 0D 02 0B 00 00 01 17 00 ...
(host to device, send FPGA firmware, max 64 byte per packet)

URB_FUNCTION_VENDOR_DEVICE means _URB_CONTROL_VENDOR_OR_CLASS_REQUEST, which uses a special structure to issue a vendor or class-specific command to a device, interface, endpoint, or other device-defined target.
Code: [Select]
struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
{
  struct _URB_HEADER   Hdr;
  PVOID                Reserved;
  ULONG                TransferFlags;
  ULONG                TransferBufferLength;
  PVOID                TransferBuffer;
  PMDL                 TransferBufferMDL;
  struct _URB          *UrbLink;
  struct _URB_HCD_AREA hca;
  UCHAR                RequestTypeReservedBits;
  UCHAR                Request;
  USHORT               Value;
  USHORT               Index;
  USHORT               Reserved1;
};
(I see this struct reported by USBsnif v3)

On Linux, with libusb I only have these functions
/*
 * USB SYNCHRONOUS I/O
 * ====================
 *
 * int libusb_control_transfer
 * int libusb_bulk_transfer
 * int libusb_interrupt_transfer
 */

Once programmed by the Windows XP driver, I can use libusb_control_transfer to monitor the device, and it works great, unfortunately it seems the USB-target can only receive the FPGA firmware via URB_CONTROL_VENDOR_OR_CLASS_REQUEST, and I don't know how to replicate it.

Any hints?  :-//
Title: Re: Libusb-v1 (linux) && URB_CONTROL_VENDOR_OR_CLASS_REQUEST
Post by: SiliconWizard on June 12, 2022, 11:50:45 pm
Would the device happen to use a Cypress FX1 or FX2 for USB interfacing?
Title: Re: Libusb-v1 (linux) && URB_CONTROL_VENDOR_OR_CLASS_REQUEST
Post by: DiTBho on June 12, 2022, 11:53:34 pm
I forgot to tell:

- I plug the USB-device into a Window-XP laptop
- the Windows XP laptop sends the firmware to the FPGA
- The USB-device gets programmed
- The USB-device is powered by a 5V adapter
- so you can unplug and move to a Linux laptop without loosing its setup

I am already able to monitor its USB protocol in run mode by issuing specific packets created with libusb_control_transfer.
Title: Re: Libusb-v1 (linux) && URB_CONTROL_VENDOR_OR_CLASS_REQUEST
Post by: DiTBho on June 12, 2022, 11:54:41 pm
Would the device happen to use a Cypress FX1 or FX2 for USB interfacing?

it's something weird, based on Infineon-CY7C68013A  :o :o :o
Title: Re: Libusb-v1 (linux) && URB_CONTROL_VENDOR_OR_CLASS_REQUEST
Post by: SiliconWizard on June 13, 2022, 01:00:52 am
Would the device happen to use a Cypress FX1 or FX2 for USB interfacing?

it's something weird, based on Infineon-CY7C68013A  :o :o :o

It's not weird. Infineon bought Cypress. But this part is indeed a Cypress FX2LP as I suspected.
Title: Re: Libusb-v1 (linux) && URB_CONTROL_VENDOR_OR_CLASS_REQUEST
Post by: gslick on June 13, 2022, 02:46:50 am

Once programmed by the Windows XP driver, I can use libusb_control_transfer to monitor the device, and it works great, unfortunately it seems the USB-target can only receive the FPGA firmware via URB_CONTROL_VENDOR_OR_CLASS_REQUEST, and I don't know how to replicate it.

Any hints?  :-//

In Windows these URB Functions all use the _URB_CONTROL_VENDOR_OR_CLASS_REQUEST data structure:

URB_FUNCTION_VENDOR_DEVICE
URB_FUNCTION_VENDOR_INTERFACE
URB_FUNCTION_VENDOR_ENDPOINT
URB_FUNCTION_VENDOR_OTHER

URB_FUNCTION_CLASS_DEVICE
URB_FUNCTION_CLASS_INTERFACE
URB_FUNCTION_CLASS_ENDPOINT
URB_FUNCTION_CLASS_OTHER

The only difference between these URB function is the values of the Type and Recipient bit fields that get set in the bmRequestType of the Control transfer Setup packet.

Code: [Select]
Universal Serial Bus Specification Revision 2.0
9.3 USB Device Requests
Table 9-2. Format of Setup Data

bmRequestType:

D7: Data transfer direction
0 = Host-to-device
1 = Device-to-host

D6...5: Type
0 = Standard
1 = Class
2 = Vendor
3 = Reserved

D4...0: Recipient
0 = Device
1 = Interface
2 = Endpoint
3 = Other


If the libusb_control_transfer() function lets you specify whatever value you want for the bmRequestType byte of a Control transfer Setup packet, then you can map those URB Functions listed above from your packet sniffing trace into libusb_control_transfer() function calls with the appropriate bmRequestType Type and Recipient bit fields.

For example, URB_FUNCTION_VENDOR_DEVICE:
bmRequestType: D6...5 Type = 2 (Vendor); D4...0: Recipient = 0 (Device)

For USBD_TRANSFER_DIRECTION_OUT:
bmRequestType: D7: 0

For USBD_TRANSFER_DIRECTION_IN:
bmRequestType: D7: 1


I have never used libusb and know nothing about it. 10 years ago I used to know almost everything there was to know about Windows USB device drivers when that was my day job for 15 years. I've forgotten a lot of it by now.