Last active
August 25, 2022 14:22
-
-
Save Swyter/26c754c6f04b13ecb8a7cf145878d045 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# swy: install pyusb (pacman -S python-pyusb) and run python3 as sudo | |
import usb.core, usb.control, usb.util, binascii | |
dev = usb.core.find(idVendor=0x0079, idProduct=0x0006) | |
print('[* dumping]', dev) | |
print('DESC_TYPE_DEVICE 0', binascii.hexlify(usb.control.get_descriptor(dev, 0x400, usb.util.DESC_TYPE_DEVICE, 0))) # b'120100010000000879000600070101020001' | |
print('DESC_TYPE_CONFIG 0', binascii.hexlify(usb.control.get_descriptor(dev, 0x400, usb.util.DESC_TYPE_CONFIG, 0))) # b'0902290001010080fa0904000002030000000921100121012265000705810308000a0705010308000a' | |
print('DESC_TYPE_STRING 0', binascii.hexlify(usb.control.get_descriptor(dev, 0x400, usb.util.DESC_TYPE_STRING, 0))) # b'04030904' | |
print('DESC_TYPE_STRING 1', binascii.hexlify(usb.control.get_descriptor(dev, 0x400, usb.util.DESC_TYPE_STRING, 1))) # b'240344007200610067006f006e005200690073006500200049006e0063002e0020002000' | |
print('DESC_TYPE_STRING 2', binascii.hexlify(usb.control.get_descriptor(dev, 0x400, usb.util.DESC_TYPE_STRING, 2))) # b'3403470065006e006500720069006300200020002000550053004200200020004a006f00790073007400690063006b0020002000' | |
print('DESC_TYPE_STRING 3', binascii.hexlify(usb.control.get_descriptor(dev, 0x400, usb.util.DESC_TYPE_STRING, 3))) # b'120100010000000879000600070101020001ffffffffffff0902290001010080fa0904000002030000000921100121012265000705810308000a0705010308000affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04030904ffffffff240344007200610067006f006e005200690073006500200049006e0063002e0020002000ffffffffffffffffffffffff3403470065006e006500720069006300200020002000550053004200200020004a006f00790073007400690063006b0020002000ffffffffffffffffffffffff05010904a101a10275089505150026ff00350046ff00093009310932093209358102750495012507463b0165140939814265007501950c2501450105091901290c81020600ff750195082501450109018102c0a1027508950746ff0026ff0009029102c0c0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff120100010000000879000600070101020001ffffffffffff0902290001010080fa0904000002030000000921100121012265000705810308000a0705010308000affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04030904ffffffff240344007200610067006f006e005200690073006500200049006e0063002e0020002000ffffffffffffffffffffffff3403470065006e006500720069006300200020002000550053004200200020004a006f00790073007400690063006b0020002000ffffffffffffffffffffffff05010904a101a10275089505150026ff00350046ff00093009310932093209358102750495012507463b0165140939814265007501950c2501450105091901290c81020600ff750195082501450109018102c0a1027508950746ff0026ff0009029102c0c0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' | |
# https://wuffs.org/blog/mouse-adventures-part-5 | |
# http://eleccelerator.com/usbdescreqparser/ | |
# 0x12, // bLength | |
# 0x01, // bDescriptorType (Device) | |
# 0x00, 0x01, // bcdUSB 1.00 | |
# 0x00, // bDeviceClass (Use class information in the Interface Descriptors) | |
# 0x00, // bDeviceSubClass | |
# 0x00, // bDeviceProtocol | |
# 0x08, // bMaxPacketSize0 8 | |
# 0x79, 0x00, // idVendor 0x79 | |
# 0x06, 0x00, // idProduct 0x06 | |
# 0x07, 0x01, // bcdDevice 2.07 | |
# 0x01, // iManufacturer (String Index) | |
# 0x02, // iProduct (String Index) | |
# 0x00, // iSerialNumber (String Index) | |
# 0x01, // bNumConfigurations 1 | |
# // 18 bytes | |
# // best guess: USB Standard Descriptor | |
# 0x09, // bLength | |
# 0x02, // bDescriptorType (Configuration) | |
# 0x29, 0x00, // wTotalLength 41 | |
# 0x01, // bNumInterfaces 1 | |
# 0x01, // bConfigurationValue | |
# 0x00, // iConfiguration (String Index) | |
# 0x80, // bmAttributes | |
# 0xFA, // bMaxPower 500mA | |
# 0x09, // bLength | |
# 0x04, // bDescriptorType (Interface) | |
# 0x00, // bInterfaceNumber 0 | |
# 0x00, // bAlternateSetting | |
# 0x02, // bNumEndpoints 2 | |
# 0x03, // bInterfaceClass | |
# 0x00, // bInterfaceSubClass | |
# 0x00, // bInterfaceProtocol | |
# 0x00, // iInterface (String Index) | |
# 0x09, // bLength | |
# 0x21, // bDescriptorType (HID) | |
# 0x10, 0x01, // bcdHID 1.10 | |
# 0x21, // bCountryCode | |
# 0x01, // bNumDescriptors | |
# 0x22, // bDescriptorType[0] (HID) | |
# 0x65, 0x00, // wDescriptorLength[0] 101 | |
# 0x07, // bLength | |
# 0x05, // bDescriptorType (Endpoint) | |
# 0x81, // bEndpointAddress (IN/D2H) | |
# 0x03, // bmAttributes (Interrupt) | |
# 0x08, 0x00, // wMaxPacketSize 8 | |
# 0x0A, // bInterval 10 (unit depends on device speed) | |
# 0x07, // bLength | |
# 0x05, // bDescriptorType (Endpoint) | |
# 0x01, // bEndpointAddress (OUT/H2D) | |
# 0x03, // bmAttributes (Interrupt) | |
# 0x08, 0x00, // wMaxPacketSize 8 | |
# 0x0A, // bInterval 10 (unit depends on device speed) | |
# // 41 bytes | |
# // best guess: USB Standard Descriptor | |
# sudo usbhid-dump --model 0079:0006 | |
# 004:002:000:DESCRIPTOR 1658298926.755106 | |
# 05 01 09 04 A1 01 A1 02 75 08 95 05 15 00 26 FF | |
# 00 35 00 46 FF 00 09 30 09 31 09 32 09 32 09 35 | |
# 81 02 75 04 95 01 25 07 46 3B 01 65 14 09 39 81 | |
# 42 65 00 75 01 95 0C 25 01 45 01 05 09 19 01 29 | |
# 0C 81 02 06 00 FF 75 01 95 08 25 01 45 01 09 01 | |
# 81 02 C0 A1 02 75 08 95 07 46 FF 00 26 FF 00 09 | |
# 02 91 02 C0 C0 | |
# 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) | |
# 0x09, 0x04, // Usage (Joystick) | |
# 0xA1, 0x01, // Collection (Application) | |
# 0xA1, 0x02, // Collection (Logical) | |
# 0x75, 0x08, // Report Size (8) | |
# 0x95, 0x05, // Report Count (5) | |
# 0x15, 0x00, // Logical Minimum (0) | |
# 0x26, 0xFF, 0x00, // Logical Maximum (255) | |
# 0x35, 0x00, // Physical Minimum (0) | |
# 0x46, 0xFF, 0x00, // Physical Maximum (255) | |
# 0x09, 0x30, // Usage (X) | |
# 0x09, 0x31, // Usage (Y) | |
# 0x09, 0x32, // Usage (Z) | |
# 0x09, 0x32, // Usage (Z) | |
# 0x09, 0x35, // Usage (Rz) | |
# 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | |
# 0x75, 0x04, // Report Size (4) | |
# 0x95, 0x01, // Report Count (1) | |
# 0x25, 0x07, // Logical Maximum (7) | |
# 0x46, 0x3B, 0x01, // Physical Maximum (315) | |
# 0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter) | |
# 0x09, 0x39, // Usage (Hat switch) | |
# 0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State) | |
# 0x65, 0x00, // Unit (None) | |
# 0x75, 0x01, // Report Size (1) | |
# 0x95, 0x0C, // Report Count (12) | |
# 0x25, 0x01, // Logical Maximum (1) | |
# 0x45, 0x01, // Physical Maximum (1) | |
# 0x05, 0x09, // Usage Page (Button) | |
# 0x19, 0x01, // Usage Minimum (0x01) | |
# 0x29, 0x0C, // Usage Maximum (0x0C) | |
# 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | |
# 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) | |
# 0x75, 0x01, // Report Size (1) | |
# 0x95, 0x08, // Report Count (8) | |
# 0x25, 0x01, // Logical Maximum (1) | |
# 0x45, 0x01, // Physical Maximum (1) | |
# 0x09, 0x01, // Usage (0x01) | |
# 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | |
# 0xC0, // End Collection | |
# 0xA1, 0x02, // Collection (Logical) | |
# 0x75, 0x08, // Report Size (8) | |
# 0x95, 0x07, // Report Count (7) | |
# 0x46, 0xFF, 0x00, // Physical Maximum (255) | |
# 0x26, 0xFF, 0x00, // Logical Maximum (255) | |
# 0x09, 0x02, // Usage (0x02) | |
# 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) | |
# 0xC0, // End Collection | |
# 0x0C, // Unknown (bTag: 0x00, bType: 0x03) | |
# // 101 bytes | |
# // best guess: USB HID Report Descriptor |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ sudo usbhid-dump --model 0079:0006 | |
003:003:000:DESCRIPTOR 1661429402.541419 | |
05 01 09 04 A1 01 A1 02 75 08 95 05 15 00 26 FF | |
00 35 00 46 FF 00 09 30 09 31 09 32 09 32 09 35 | |
81 02 75 04 95 01 25 07 46 3B 01 65 14 09 39 81 | |
42 65 00 75 01 95 0C 25 01 45 01 05 09 19 01 29 | |
0C 81 02 06 00 FF 75 01 95 08 25 01 45 01 09 01 | |
81 02 C0 A1 02 75 08 95 07 46 FF 00 26 FF 00 09 | |
02 91 02 C0 C0 | |
$ sudo lsusb -vvvvvd 0079:0006 | |
Bus 003 Device 003: ID 0079:0006 DragonRise Inc. PC TWIN SHOCK Gamepad | |
Device Descriptor: | |
bLength 18 | |
bDescriptorType 1 | |
bcdUSB 1.00 | |
bDeviceClass 0 | |
bDeviceSubClass 0 | |
bDeviceProtocol 0 | |
bMaxPacketSize0 8 | |
idVendor 0x0079 DragonRise Inc. | |
idProduct 0x0006 PC TWIN SHOCK Gamepad | |
bcdDevice 1.07 | |
iManufacturer 1 DragonRise Inc. | |
iProduct 2 Generic USB Joystick | |
iSerial 0 | |
bNumConfigurations 1 | |
Configuration Descriptor: | |
bLength 9 | |
bDescriptorType 2 | |
wTotalLength 0x0029 | |
bNumInterfaces 1 | |
bConfigurationValue 1 | |
iConfiguration 0 | |
bmAttributes 0x80 | |
(Bus Powered) | |
MaxPower 500mA | |
Interface Descriptor: | |
bLength 9 | |
bDescriptorType 4 | |
bInterfaceNumber 0 | |
bAlternateSetting 0 | |
bNumEndpoints 2 | |
bInterfaceClass 3 Human Interface Device | |
bInterfaceSubClass 0 | |
bInterfaceProtocol 0 | |
iInterface 0 | |
HID Device Descriptor: | |
bLength 9 | |
bDescriptorType 33 | |
bcdHID 1.10 | |
bCountryCode 33 US | |
bNumDescriptors 1 | |
bDescriptorType 34 Report | |
wDescriptorLength 101 | |
Report Descriptors: | |
** UNAVAILABLE ** | |
Endpoint Descriptor: | |
bLength 7 | |
bDescriptorType 5 | |
bEndpointAddress 0x81 EP 1 IN | |
bmAttributes 3 | |
Transfer Type Interrupt | |
Synch Type None | |
Usage Type Data | |
wMaxPacketSize 0x0008 1x 8 bytes | |
bInterval 10 | |
Endpoint Descriptor: | |
bLength 7 | |
bDescriptorType 5 | |
bEndpointAddress 0x01 EP 1 OUT | |
bmAttributes 3 | |
Transfer Type Interrupt | |
Synch Type None | |
Usage Type Data | |
wMaxPacketSize 0x0008 1x 8 bytes | |
bInterval 10 | |
can't get debug descriptor: Resource temporarily unavailable | |
Device Status: 0x0000 | |
(Bus Powered) | |
$ sudo python3 | |
Python 3.10.6 (main, Aug 3 2022, 17:39:45) [GCC 12.1.1 20220730] on linux | |
Type "help", "copyright", "credits" or "license" for more information. | |
>>> import usb.core, usb.control, usb.util, binascii | |
>>> dev = usb.core.find(idVendor=0x0079, idProduct=0x0006) | |
>>> print('[* dumping]', dev) | |
[* dumping] DEVICE ID 0079:0006 on Bus 003 Address 003 ================= | |
bLength : 0x12 (18 bytes) | |
bDescriptorType : 0x1 Device | |
bcdUSB : 0x100 USB 1.0 | |
bDeviceClass : 0x0 Specified at interface | |
bDeviceSubClass : 0x0 | |
bDeviceProtocol : 0x0 | |
bMaxPacketSize0 : 0x8 (8 bytes) | |
idVendor : 0x0079 | |
idProduct : 0x0006 | |
bcdDevice : 0x107 Device 1.07 | |
iManufacturer : 0x1 DragonRise Inc. | |
iProduct : 0x2 Generic USB Joystick | |
iSerialNumber : 0x0 | |
bNumConfigurations : 0x1 | |
CONFIGURATION 1: 500 mA ================================== | |
bLength : 0x9 (9 bytes) | |
bDescriptorType : 0x2 Configuration | |
wTotalLength : 0x29 (41 bytes) | |
bNumInterfaces : 0x1 | |
bConfigurationValue : 0x1 | |
iConfiguration : 0x0 | |
bmAttributes : 0x80 Bus Powered | |
bMaxPower : 0xfa (500 mA) | |
INTERFACE 0: Human Interface Device ==================== | |
bLength : 0x9 (9 bytes) | |
bDescriptorType : 0x4 Interface | |
bInterfaceNumber : 0x0 | |
bAlternateSetting : 0x0 | |
bNumEndpoints : 0x2 | |
bInterfaceClass : 0x3 Human Interface Device | |
bInterfaceSubClass : 0x0 | |
bInterfaceProtocol : 0x0 | |
iInterface : 0x0 | |
ENDPOINT 0x81: Interrupt IN ========================== | |
bLength : 0x7 (7 bytes) | |
bDescriptorType : 0x5 Endpoint | |
bEndpointAddress : 0x81 IN | |
bmAttributes : 0x3 Interrupt | |
wMaxPacketSize : 0x8 (8 bytes) | |
bInterval : 0xa | |
ENDPOINT 0x1: Interrupt OUT ========================== | |
bLength : 0x7 (7 bytes) | |
bDescriptorType : 0x5 Endpoint | |
bEndpointAddress : 0x1 OUT | |
bmAttributes : 0x3 Interrupt | |
wMaxPacketSize : 0x8 (8 bytes) | |
bInterval : 0xa | |
>>> print('DESC_TYPE_DEVICE 0', binascii.hexlify(usb.control.get_descriptor(dev, 0x400, usb.util.DESC_TYPE_DEVICE, 0))) # b'120100010000000879000600070101020001' | |
DESC_TYPE_DEVICE 0 b'120100010000000879000600070101020001' | |
>>> print('DESC_TYPE_CONFIG 0', binascii.hexlify(usb.control.get_descriptor(dev, 0x400, usb.util.DESC_TYPE_CONFIG, 0))) # b'0902290001010080fa0904000002030000000921100121012265000705810308000a0705010308000a' | |
DESC_TYPE_CONFIG 0 b'0902290001010080fa0904000002030000000921100121012265000705810308000a0705010308000a' | |
>>> print('DESC_TYPE_STRING 0', binascii.hexlify(usb.control.get_descriptor(dev, 0x400, usb.util.DESC_TYPE_STRING, 0))) # b'04030904' | |
DESC_TYPE_STRING 0 b'04030904' | |
>>> print('DESC_TYPE_STRING 1', binascii.hexlify(usb.control.get_descriptor(dev, 0x400, usb.util.DESC_TYPE_STRING, 1))) # b'240344007200610067006f006e005200690073006500200049006e0063002e0020002000' | |
DESC_TYPE_STRING 1 b'240344007200610067006f006e005200690073006500200049006e0063002e0020002000' | |
>>> print('DESC_TYPE_STRING 2', binascii.hexlify(usb.control.get_descriptor(dev, 0x400, usb.util.DESC_TYPE_STRING, 2))) # b'3403470065006e006500720069006300200020002000550053004200200020004a006f00790073007400690063006b0020002000' | |
DESC_TYPE_STRING 2 b'3403470065006e006500720069006300200020002000550053004200200020004a006f00790073007400690063006b0020002000' | |
>>> print('DESC_TYPE_STRING 3', binascii.hexlify(usb.control.get_descriptor(dev, 0x400, usb.util.DESC_TYPE_STRING, 3))) # b'120100010000000879000600070101020001ffffffffffff0902290001010080fa0904000002030000000921100121012265000705810308000a0705010308000affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04030904ffffffff240344007200610067006f006e005200690073006500200049006e0063002e0020002000ffffffffffffffffffffffff3403470065006e006500720069006300200020002000550053004200200020004a006f00790073007400690063006b0020002000ffffffffffffffffffffffff05010904a101a10275089505150026ff00350046ff00093009310932093209358102750495012507463b0165140939814265007501950c2501450105091901290c81020600ff750195082501450109018102c0a1027508950746ff0026ff0009029102c0c0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff120100010000000879000600070101020001ffffffffffff0902290001010080fa0904000002030000000921100121012265000705810308000a0705010308000affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04030904ffffffff240344007200610067006f006e005200690073006500200049006e0063002e0020002000ffffffffffffffffffffffff3403470065006e006500720069006300200020002000550053004200200020004a006f00790073007400690063006b0020002000ffffffffffffffffffffffff05010904a101a10275089505150026ff00350046ff00093009310932093209358102750495012507463b0165140939814265007501950c2501450105091901290c81020600ff750195082501450109018102c0a1027508950746ff0026ff0009029102c0c0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' | |
DESC_TYPE_STRING 3 b'120100010000000879000600070101020001ffffffffffff0902290001010080fa0904000002030000000921100121012265000705810308000a0705010308000affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04030904ffffffff240344007200610067006f006e005200690073006500200049006e0063002e0020002000ffffffffffffffffffffffff3403470065006e006500720069006300200020002000550053004200200020004a006f00790073007400690063006b0020002000ffffffffffffffffffffffff05010904a101a10275089505150026ff00350046ff00093009310932093209358102750495012507463b0165140939814265007501950c2501450105091901290c81020600ff750195082501450109018102c0a1027508950746ff0026ff0009029102c0c0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff120100010000000879000600070101020001ffffffffffff0902290001010080fa0904000002030000000921100121012265000705810308000a0705010308000affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04030904ffffffff240344007200610067006f006e005200690073006500200049006e0063002e0020002000ffffffffffffffffffffffff3403470065006e006500720069006300200020002000550053004200200020004a006f00790073007400690063006b0020002000ffffffffffffffffffffffff05010904a101a10275089505150026ff00350046ff00093009310932093209358102750495012507463b0165140939814265007501950c2501450105091901290c81020600ff750195082501450109018102c0a1027508950746ff0026ff0009029102c0c0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' | |
>>> | |
--- | |
DIR=/sys/bus/usb/devices/$(ls -R /sys/bus/usb/devices/* | grep js$1 | cut -d$'\n' -f2 | cut -d: -f1 | awk -F/ '{print $NF}') | |
IMANUFACTURER=$(cat $DIR/manufacturer) | |
IPRODUCT=$(cat $DIR/product) | |
ISERIAL=$(cat $DIR/serial) | |
IVERSION=$(cat $DIR/version | xargs) | |
SIGNATURE="$IMANUFACTURER:$IPRODUCT:$ISERIAL:$IVERSION" | |
echo $SIGNATURE | |
cat: /sys/bus/usb/devices/3-5/serial: No existe el fichero o el directorio | |
DragonRise Inc. :Generic USB Joystick ::1.00 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
sudo lsusb -vvvvvd 0079:0006
sudo usbhid-dump --model 0079:0006
Parsed version of the above using the tool here: http://eleccelerator.com/usbdescreqparser/