-
Notifications
You must be signed in to change notification settings - Fork 474
There is an example device for hidraw from umockdev project. Maybe we can integrate it for CI under Linux.
https://github.com/martinpitt/umockdev/tree/main/devices/hidraw
All reactions
-
👍 2
Replies: 50 comments
Ref: libusb project uses umockdev for Linux testing using a container.
https://github.com/libusb/libusb/blob/master/tests/umockdev.c
https://github.com/libusb/libusb/blob/master/.github/workflows/linux.yml
All reactions
The alternative: uhid.
In one of the issues there was a sample. The sample implementation actually has several issues/bugs, but the overall aproach is fine.
All reactions
-
👍 1
I am not so sure if this is possible or not.
https://github.com/vpelletier/python-functionfs
All reactions
BTW, other than CI, it is also good to see if we have some known good HID device or FW to test HIDAPI.
For libusb, here is the reference, it can be the same for USB HID device development. But for Bluetooth/BLE and even I2C/SPI HID device, we need different tools.
https://github.com/libusb/libusb/wiki/FAQ#do-you-have-a-list-of-known-good-devices-to-test-libusb
- Highly recommended -- Cypress FX3 SuperSpeed Explorer Kit or other FX3 based boards https://www.cypress.com/documentation/development-kitsboards/cyusb3kit-003-ez-usb-fx3-superspeed-explorer-kit
- Cypress FX2LP
- Arm Cortex M MCU based development board like ST STM32 (eg: Bluepill and Blackpill, Discovery or Nucleo boards), Microchip SAM MCU, Raspberry Pi Pico, etc
- Other USB MCU like Microhip PIC or AVR, TI MSP 430, etc
- Linux USB Gadget devices (eg: using Raspberry Pi Zero or Raspberry Pi 4B/400)
- libusb-1.0.26 has the umockdev based testing under Linux
Other than vendor provided USB stacks (sometimes with proprietary licenses), there are also Opensource MCU USB stacks.
- tinyusb - https://github.com/hathach/tinyusb
- cherryusb - https://github.com/sakumisu/CherryUSB
- lufa - https://github.com/abcminiuser/lufa
- m-stack for PIC16/18/24/32 - https://github.com/signal11/m-stack.git
- libopencm3 for ARM Cortex-M3 - http://libopencm3.org/
- libusb_stm32 - https://github.com/dmitrystu/libusb_stm32.git
- PIC16/18 USB stack - https://github.com/johnnydrazzi/USB-Stack
- fx2lib for EZUSB FX2LP - https://github.com/djmuhlestein/fx2lib
Just wondering what is the test device you are using to test HIDAPI?
For me I usually use whatever HID device I have with me like the following for general test using hidtest.
- Logitech USB Receiver
- Plantronics USB Headset
- My laptop has built-in I2C HID device (Synaptics Touch Pad)
- USB Mouse/Keyboard
- Bluetooth Mouse (Microsoft 3600 and maybe others)
- Logitech Dual Action USB Gamepad
- Wireless Xbox Gamepad (old version)
- ESP32S based BLE HID example
For more real tests with hidapitester or simple test codes. I do not know much about the FW development other than simple modifications of the USB PIC USB codes and maybe a little bit with USB AVRs.
- Microchip PIC18F87J50 with custom HID FW (8 bit USB PIC18 MCU). I have USB PIC24 and PIC32 board as well but seldom use them.
- Cypress EZ-USB FX2LP breadout board
- Arduino Leonardo and Pro Micro based HID example (8 bit USB AVR MCU)
- Arduino M0 clone (Atmel SAMD21)
- Teensy 2.0 and 2.0+ based HID example (8 bit USB AVR MCU)
- Various STM32 MCU demo boards
- Raspberry Pi Pico using C++ or MicroPython or CircuitPython
- ESP32C3/S2/S3 based boards using C or MicroPython or CircuitPython
- BBC Micro:bit v2 (Nordic nRF52833) using C or MicroPython or CircuitPython
Then I use some HID devices to test hidapi indirectly using avrdude and OpenOCD (CMSIS DAP v1 compliant adapters).
All reactions
Unfortunately I don't have any devices dedicated for testing, only a few of my peripherals, and a few devices from my employer (I'm under NDA not to disclose what those are), which have a few fixed input/output/interrupt reports, that I usually use for some sanity testing.
All reactions
-
👍 1
Yeah, would be great to have 1-2 FW samples for some well known simple/cheap device to be able to test most (all?) of the HIDAPI.
All reactions
-
👍 1
@todbot has some test firmware for hidapitester which can be used for hidapi testing as well.
https://github.com/todbot/hidapitester/tree/master/test_hardware
- ProMicroRawHID -- USB AVR Atmega32U4
- TeensyRawHID -- can be used by different Teensy boards (USB AVR and Arm Cortex M MCUs)
- two tinyusb examples which can be used by many ARM core MCU development boards including STM32 and Raspberry Pi Pico, as well as non-ARM core MCUs like ESP32 S2/S3 or MSP430
TinyUSB
https://github.com/hathach/tinyusb
node-hid has some examples as well.
https://github.com/node-hid/node-hid#examples
All reactions
Jan Axelson has quite some HID examples for things like Cypress EZ-USB FX2LP and Microchip USB PIC.
http://janaxelson.com/hidpage.htm
All reactions
Simple test for Jan Axelson FX2HID example (0925:1234) -- loop back of Input/Output report (no report ID) using hidapitest.
For this FW, I have to explicitly send output report ID 0.
PS C:\work\hid\hidapitester> .\hidapitester --vidpid 0925:1234 --list-detail
0925/1234: CYPRESS - EZ-USB FX2 HID USBHIDIO
vendorId: 0x0925
productId: 0x1234
usagePage: 0xFFA0
usage: 0x0001
serial_number:
interface: 0
path: \\?\HID#VID_0925&PID_1234#7&21072e4a&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
PS C:\work\hid\hidapitester> .\hidapitester --vidpid 0925:1234 --open --send-output 0,8,9 --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 64-bytes...wrote 3 bytes:
00 08 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Reading 64-byte input report 0, 250 msec timeout...read 2 bytes:
08 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Closing device
PS C:\work\hid\hidapitester> .\hidapitester --vidpid 0925:1234 --open -l 3 --send-output 0,8,9 --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 3-bytes...wrote 3 bytes:
00 08 09
Reading 3-byte input report 0, 250 msec timeout...read 2 bytes:
08 09 00
Closing device
Her USB PIC generic HID example has feature report loopback as well.
PS C:\work\hid\hidapitester> .\hidapitester --vidpid 0925:7001 --list-detail
0925/7001: Microchip Technology Inc. - Generic HID
vendorId: 0x0925
productId: 0x7001
usagePage: 0xFFA0
usage: 0x0001
serial_number:
interface: 0
path: \\?\HID#VID_0925&PID_7001#7&1e741593&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
PS C:\work\hid\hidapitester> .\hidapitester --vidpid 0925:7001 --open -l 3 --send-output 0,1,2 --read-input
Opening device, vid/pid: 0x0925/0x7001
Writing output report of 3-bytes...wrote 3 bytes:
00 01 02
Reading 3-byte input report 0, 250 msec timeout...read 2 bytes:
01 02 00
Closing device
S C:\work\hid\hidapitester> .\hidapitester --vidpid 0925:7001 --open -l 3 --send-feature 0,1,2 --read-feature 0
Opening device, vid/pid: 0x0925/0x7001
Writing 3-byte feature report...wrote 3 bytes:
00 01 02
Reading 3-byte feature report, report_id 0...read 3 bytes:
00 01 02
Closing device
I have done the modification of the generic HID FW to add report ID (Input 1, Output 2, Feature OUT 3, Feature IN 4). I used that to test libusb Windows HID backend many year ago during the initial stage of the libusb Windows backend development.
PS C:\work\hid\hidapitester> .\hidapitester --vidpid 0925:7001 --open -l 3 --send-output 2,8,9 --read-input 1
Opening device, vid/pid: 0x0925/0x7001
Writing output report of 3-bytes...wrote 3 bytes:
02 08 09
Reading 3-byte input report 0, 250 msec timeout...read 3 bytes:
01 08 09
Closing device
PS C:\work\hid\hidapitester> .\hidapitester --vidpid 0925:7001 --open -l 3 --send-feature 3,6,7 --read-feature 4
Opening device, vid/pid: 0x0925/0x7001
Writing 3-byte feature report...wrote 3 bytes:
03 06 07
Reading 3-byte feature report, report_id 4...read 3 bytes:
04 06 07
Closing device
All reactions
Simple test using hidapitester for the Microchip Simple HID demo (which is the base for the FW used in hidtest). I am using the mla version for the 8bit/16bit USB PICs.
1) toggle LED
PS C:\work\hid\hidapitester> .\hidapitester --vidpid 04d8:003f --open -l 2 --send-output 0x01,0x80
Opening device, vid/pid: 0x04D8/0x003F
Writing output report of 2-bytes...wrote 65 bytes:
01 80
Closing device
2) read button status
PS C:\work\hid\hidapitester> .\hidapitester --vidpid 04d8:003f --open -l 2 --send-output 0x01,0x81 --read-input
Opening device, vid/pid: 0x04D8/0x003F
Writing output report of 2-bytes...wrote 65 bytes:
01 81
Reading 2-byte input report 0, 250 msec timeout...read 2 bytes:
81 01
Closing device
All reactions
For libusb testing, I usually recommend Cypress EZ-USB FX3 (SuperSpeed). Then EZ-USB FX2LP (High-Speed).
https://github.com/libusb/libusb/wiki/FAQ#do-you-have-a-list-of-known-good-devices-to-test-libusb
I think for HIDAPI testing, maybe FX3 is a bit overkill but you may want to get cheap EZ-USB FX2LP breakout from online marketplace like AliExpress at about US5ドル. For example, I have the following board.
1PCS-EZ-USB-FX2LP-CY7C68013A-USB-logic-analyzer-core-board jpg_Q90 jpg_
I just did a simple modification of Jan Axelson's fx2hid example to extend the Input/Output report size to 64 bytes.
PS C:\work\hid\hidapitester> .\hidapitester --vidpid 0925:1234 --open -l 65 --send-output 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64 --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 65-bytes...wrote 65 bytes:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40
Reading 65-byte input report 0, 250 msec timeout...read 64 bytes:
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40
00
Closing device
Edit: take note that in order to develop high speed HID USB device using FX2LP with wMaxPacketSize > 64 Bytes, we can not use EP1IN or EP1OUT, as their buf size is only 64 bytes. We should probably use EP2 and EP6 (buffer size equals to 512 Bytes or 1024 Bytes). So the modification is not as simple. But if we just need to get report size >64 bytes, then it is still possible to use EP1 IN and EP1 OUT. We need to handle the fragamentation in firmware.
All reactions
For EZ-USB FX2LP, previous examples are using Keil UV2 and Keil C51 toolchain (the FW is rather small so the free 4K version bundled will work).
Lastes from Cypress (now part of Infineon) is using Eclipse based IDE with Open Source SDCC toolchain.
https://community.infineon.com/t5/Knowledge-Base-Articles/FX2-FX2LP-SDCC-Eclipse-Project-Interrupt-not-Serviced-KBA231372/ta-p/250672
Then there are quite some open source FW library available, using sdcc.
https://github.com/djmuhlestein/fx2lib
https://github.com/whitequark/libfx2
All reactions
It should be a device, where you can program any HID ReportDescriptor, PhysicalDescriptor and StringDescriptor on low-level (byte-wise). Not something where you configure everything on high-level, because for testing it makes a difference how we order the items in the ReportDescriptor.
All reactions
-
👍 1
It should be a device, where you can program any HID ReportDescriptor, PhysicalDescriptor and StringDescriptor on low-level (byte-wise). Not something where you configure everything on high-level, because for testing it makes a difference how we order the items in the ReportDescriptor.
I believe most of the MCU development board will allow this, including the EZ-USB FX2LP (actually the example code from Jan Axelson uses assembly language for the descriptor, same for examples from Cypress).
Unfortunately I am not a programmer so I can only carry out minor modification of existing FW codes.
All reactions
But if we just need to get report size >64 bytes, then it is still possible to use EP1 IN and EP1 OUT. We need to handle the fragmentation in firmware.
I need to check but the following FX2LP FW seems to work, EP1 IN and EP1 OUT have wMacPacketSize = 64 bytes, but INPUT/OUTPUT report size are both 128 bytes.
PS C:\work\hid\hidapitester> .\hidapitester --vidpid 0925:1234 --open --buflen 256 -l 129 --send-output 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128 --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 129-bytes...wrote 129 bytes:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80
Reading 129-byte input report 0, 250 msec timeout...read 128 bytes:
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40
41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60
61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80
00
Closing device
fx2hid_128bytes_report.zip
Target.zip
Similar thing for 512Bytes report.
C:\work\libusb\hidapitester [master ≡ +3 ~0 -0 !]> .\hidapitester --vidpid 0925:1234 --open -l 513 --send-output 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,2,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,3,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,4,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128 --read-input
Opening device, vid/pid: 0x0925/0x1234
Writing output report of 513-bytes...wrote 513 bytes:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80 02 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80 03 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80 04 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
80
Reading 513-byte input report 0, 250 msec timeout...read 512 bytes:
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40
41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60
61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80
02 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40
41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60
61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80
03 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40
41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60
61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80
04 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40
41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60
61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80
00
Closing device
All reactions
FYI as well. I believe libusb/libusb#1217 is incorrect.
All reactions
Unfortunately I've never had good test device(s) to check all: input/output/feature/interrupt, with and w/o report ID and with different lengths.
All being said, I think we need to focus to make the behavior (e.g. in terms of the return length, etc.) be consistent on all platforms, specifically to match the documentation.
Please take a look when you got the time. Thanks.
I'm a little lost in the context and worst of all - cannot properly check it locally...
All reactions
-
👍 1
Unfortunately I've never had good test device(s) to check all: input/output/feature/interrupt, with and w/o report ID and with different lengths.
I will recommend the following devices which will work with the examples here. They are of relative low cost from online stores like AliExpress.
https://github.com/todbot/hidapitester/tree/master/test_hardware
- Arduino Micro or Leonardo clone (ATmega32U4)
- Raspeberry Pico (official or from 3rd parties)
- Microchip/Atmel SAM D21 Mini breakout boards
All being said, I think we need to focus to make the behavior (e.g. in terms of the return length, etc.) be consistent on all platforms, specifically to match the documentation.
Yes I agree.
Please take a look when you got the time. Thanks.
I'm a little lost in the context and worst of all - cannot properly check it locally...
I understand. I will try to summarize and create another issue. And hopefully you can get one or two of the test devices without too much difficulties.
All reactions
-
👍 1
Arduino Micro or Leonardo clone
Hm, I actually have an Arduino somewhere. Haven't used it for years. Maybe I could use it.
Now it is only the question if finding fime for it.
All reactions
Arduino Micro or Leonardo clone
Hm, I actually have an Arduino somewhere. Haven't used it for years. Maybe I could use it. Now it is only the question if finding fime for it.
No problem, take your time.
The Arduino Uno and Maga 2560 (official version and some clones) come with ATmega16U2. It is a bit tricky to get the rawhid example working.
https://github.com/NicoHood/HID/wiki/RawHID-API
https://github.com/NicoHood/HoodLoader2
Arduino Leonardo or Arduino Micro or Pro Micro or clones come with ATmega32U4 and then you should have no issues to get rawhid example working.
https://github.com/todbot/hidapitester/tree/master/test_hardware/ProMicroRawHID
All reactions
I am going to move this to discussion and create a new issue to make this one clean. Sorry I have put too much info here and people may get confused.
All reactions
I was puzzled that I do not see ways to send Feature report to the host using the following example.
https://github.com/todbot/hidapitester/tree/master/test_hardware/ProMicroRawHID
Then I find out that the underlying HID library (https://github.com/NicoHood/HID) does not support Get_Report for Input Report and Feature Report. I have created a new issue there.
All reactions
The fx2hid examples are very useful in testing the following two PRs.
All reactions
Revisting this example: looping back the data of Output report (Report ID 2) to Input Report (Report ID 1)
It is working up to 63 bytes probabbly due to CircuitPython HID library limitations.
Tested using Raspberry Pi Poco 2 and latest CircuitPython version and latest Adafruit_HID library
# rawhid_code.py
import time
import usb_hid
import adafruit_hid
custom_device = adafruit_hid.find_device(usb_hid.devices, usage_page=0xff00, usage=0x01)
print("custom_device: %04x %04x" % (custom_device.usage_page, custom_device.usage) )
while True:
out_report = custom_device.get_last_received_report(2) # out from computer
if out_report:
print("len:",len(out_report),["%02x" % x for x in out_report])
time.sleep(0.5)
print("sending copy on reportid 1")
in_report = bytearray(out_report) # copy in case we want to modify
custom_device.send_report(in_report, 1); # in to computer
# rawhid_boot.py --
# any changes here only reflected after board reset
import usb_hid
REPORT_COUNT = 63 # size of report in bytes
CUSTOM_REPORT_DESCRIPTOR = bytes((
0x06, 0x00, 0xff, # Usage page (Vendor Defined Page1)
0x09, 0x01, # Usage (Vendor Page 1)
0xA1, 0x01, # Collection (Application)
0x85, 0x01, # Report ID (1)
0x09, 0x00, # Usage Page (Undefined)
0x15, 0x00, # Logical Minimum (0)
0x26, 0xFF, 0x00, # Logical Maximum (255)
0x75, 0x08, # Report Size (8 bits)
0x95, REPORT_COUNT, # Report Count (64 fields)
0x82, 0x02, 0x01, # Input (Data,Var,Abs,Buf)
0x85, 0x02, # Report ID (2)
0x09, 0x00, # Usage (Undefined)
0x09, 0x00, # Usage Page (Undefined)
0x15, 0x00, # Logical Minimum (0)
0x26, 0xFF, 0x00, # Logical Maximum (255)
0x75, 0x08, # Report Size (8 bits)
0x95, REPORT_COUNT, # Report Count (64 fields)
0x92, 0x02, 0x01, # Output (Data,Var,Abs,Buf)
0xC0, # End Collection
))
custom_device = usb_hid.Device(
report_descriptor=CUSTOM_REPORT_DESCRIPTOR,
usage_page=0xff00, # Vendor defined
usage=0x01, # Vendor page 1
report_ids=(1, 2),
in_report_lengths=(REPORT_COUNT,0),
out_report_lengths=(0, REPORT_COUNT),
)
usb_hid.enable( (custom_device,) )
PS C:\work\libusb\hidapitester> .\hidapitester_git_winapi.exe --usagePage 0xff00 --usage 1 --open -l 64 --send-output 2,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63 --timeout 2000 --read-input 1
Opening device, vid/pid:0x0000/0x0000, usagePage/usage: FF00/1
Device opened
Writing output report of 64-bytes...wrote 64 bytes:
02 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
Reading up to 64-byte input report, 2000 msec timeout...read 64 bytes:
01 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
Closing device
PS C:\work\libusb\hidapitester> .\hidapitester_git_winapi.exe --usagePage 0xff00 --usage 1 --open -l 65 --send-output 2,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64 --timeout 1000 --read-input 1
Opening device, vid/pid:0x0000/0x0000, usagePage/usage: FF00/1
Device opened
Writing output report of 65-bytes...wrote 64 bytes:
02 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40
Reading up to 65-byte input report, 1000 msec timeout...read 64 bytes:
01 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
00
Closing device
All reactions
There is a bug in the fx2hid example as per the following comments.
Modified version of the fx2hid firmware modifications.
fx2hid.zip
fx2hid_64bytes.zip
fx2hid_128bytes_report.zip
fx2hid_512bytes_packet.zip
fx2hid_512bytes_report.zip
fx2hid_1024bytes_packet.zip
Target.zip
All reactions
Some issues with Infineon website and Cy3684/CY3689 development kit files cannot be downloaded.
https://www.infineon.com/products/universal-serial-bus/usb-2-0-peripheral-controllers/ez-usb-fx2lp-fx2g2-usb-2-0
Screenshot 2026年05月22日 093309
CY3689 archive.
infineon-cy3689-ez-usb-fx2lp-discovery-kit.zip-developmenttools-en.zip
All reactions
CY3684 archive is too big to put here.
Important files for firmware building: Keil Uv2 C51 4K evaluation version and Firmware Library/Examples.
Firmware_Target.zip
uV2_4k.zip
All reactions
For the Microchip PIC geneic HID examples, you need to use legacy Microchip MPLAB, legacy C18 and legacy MLA.
https://www.microchip.com/en-us/tools-resources/archives/mplab-ecosystem
MPLAB 8.92
https://ww1.microchip.com/downloads/en/DeviceDoc/MPLAB_IDE_8_92.zip
C18 3.48 full evaluation
https://www.microchip.com/content/dam/mchp/documents/DEV/ProductDocuments/SoftwareTools/mplabc18-v3.48-windows-full-installer.exe
Legacy MLA v2013-06-15
https://ww1.microchip.com/downloads/en/softwarelibrary/microchip-libraries-for-applications-v2013-06-15-windows-installer.exe
BTW, hidapi hidtest example firmware device is based on Microchip Basic HID example but with some modifications. Alan Ott has not released the firmware though. Maybe I should do it another time. Not so useful though.
All reactions
hidapitester hidtest examples (Arduino + TinyUSB) have been upgraded to support Raspberry Pico MCUs.
https://github.com/todbot/hidapitester/tree/main/test_hardware
CircuitPython Generic HID support
All reactions
My experiment to use AI coding agent to modify fx2hid FW.
First experiment using Google Antigravity CLI seems to be good.
https://github.com/mcuee/fx2hid_mod/tree/main/fx2hid_agy
$ ./test_host.exe
Usage: C:\work\ai-coding\sdcc\fx2hid_agy\build\test_host.exe <vid>:<pid> <num_bytes> <pattern> [start_value] [options]
Patterns:
inc - Increasing bytes starting from [start_value] (default 0)
dec - Decreasing bytes starting from [start_value] + payload_len - 1
rand - Random bytes
Options:
-i, --in-id <id> Expected IN Report ID (default: 0 for none)
-o, --out-id <id> OUT Report ID to prepend (default: 0 for none)
-t, --truncate Truncate output hex dumps to first 64 bytes (default: print full)
Examples:
C:\work\ai-coding\sdcc\fx2hid_agy\build\test_host.exe 0925:1234 1024 inc 0x00
C:\work\ai-coding\sdcc\fx2hid_agy\build\test_host.exe 0925:1234 1024 rand -o 0x02 -i 0x01
$ ./test_host.exe 0925:1234 1024 rand -o 2 -i 1
Loopback Test Configuration:
Target Device: VID 0x0925, PID 0x1234
Total Bytes: 1024
Pattern: rand
OUT Report ID: 0x02 (Prepend)
IN Report ID: 0x01 (Verify)
Truncate Out: No
Successfully opened HID device!
Sent Report (including OUT ID) (total 1024 bytes):
02 C7 B3 C3 85 1B B6 FF 47 B5 89 E8 AA 71 E6 5D
E2 45 3A 2A 5B 77 08 DA 45 0D 88 CD 50 86 95 8A
B4 C7 C6 55 75 58 DA 05 E5 D0 59 10 6A 8E 78 E8
81 AA 3D 8A 03 2B E5 53 A8 7B 83 16 C9 18 E9 6D
6A 8B CB 4C 77 9E 22 DC 4E CA CF 86 7E EF 81 4D
CE 48 D8 62 82 9D CB F2 D9 BA 47 43 DA 21 18 FF
50 FC 0D D0 14 55 57 2C 8A 89 33 73 6E FA C9 37
D1 05 53 DA 5E 34 81 5F E2 B4 1C 7A 0C 09 EB E9
71 00 D3 07 D2 E5 41 9F A2 F7 CD FE C3 19 17 4C
91 CA F5 1C 21 57 D1 41 CA 4F 4C E3 E5 38 27 D3
D2 80 64 1C 3C B7 A8 DB 9D FB E4 50 04 B3 34 34
16 80 08 4D 52 70 81 41 9A 75 1E A8 EF 16 97 64
7D 65 09 35 D7 31 54 88 83 7C C1 90 B9 2F E9 98
68 0D D2 98 7A E6 5A 06 59 0D D9 EE B2 0C 02 45
79 95 0A 7B 2D BC 0D 4F 5D 64 AD E7 6B F7 FC 20
90 5B 9C 23 20 21 24 39 0F FF C6 E0 B5 80 2F 1E
CE FA AF 15 C5 C1 9A D8 32 9A EE 7D A1 72 35 73
95 50 AD 16 CC 89 A7 81 C5 33 2D A3 80 DB E7 96
85 7B 40 2B 27 A6 C4 CA 0A 06 CC 79 E3 08 5E 3A
7F D6 4F 9A 07 86 AA 87 82 90 56 62 9B 86 F2 55
A4 FF 04 E7 DC D5 53 CD ED 90 91 03 B9 21 3D 1C
56 D4 C8 D7 57 80 F7 F2 4E 00 88 43 8F E7 18 04
36 70 44 6F 6B B4 0F 8B E4 20 83 45 AC 25 9C C2
23 31 61 F4 47 DF 54 6B 31 6B 0C 6E E2 68 21 4B
40 B5 48 EB 5C AD BF A9 F6 9E EC 64 43 7C 41 D3
EE D7 62 19 5C 0B 8A 9A 34 B7 2B 0C 1F 70 D4 D1
CC B6 58 84 38 26 2D D2 2C F2 12 8B 07 8F F4 F8
BD AD 13 70 20 6C 61 26 5E CD 2A 45 CB 66 FA 3F
E1 5B BC 61 85 89 1F AC 8C 04 3E E0 7E C4 7F D9
9A 9B BB 1E 1A 6A A0 B8 B8 95 54 40 70 B4 5B 3C
88 8C BB AC CE 3D 5E DF 21 BC B7 8B 32 84 A9 1D
8C 89 A4 4E D2 6E 11 F7 48 F7 F0 26 95 C1 BF 71
C8 31 9E 8A 98 AA B2 14 F0 03 C7 B5 AB 38 39 6D
9C 5F 14 26 D1 DE 7A 8C 18 DC 45 1E C3 F5 EE 85
A9 32 AE 25 6D 38 E2 F3 03 BF B4 86 6F 46 F8 70
D0 05 54 CE 9E 24 A4 1E 30 2A 9C 51 81 B8 AF 21
33 77 30 A5 D4 4F B8 23 61 DA C7 25 08 18 AE CF
32 64 AC 6F C1 A6 57 56 96 CB 3D E7 57 72 CC ED
6F E8 6F 32 56 57 FA 4D 12 3A 48 BB FE 14 22 31
CA 62 63 31 C3 CE 5A DC 54 A5 70 07 CD 8B 0B 90
64 6E B2 F2 7A B8 71 18 1F C9 7F 6F D7 A4 1E 3F
9E E8 C3 3B 2B 03 77 57 72 A2 7D D9 6C 6B 35 B3
1A EF 40 10 C8 DA E5 2D 8F 6D B3 6A 1D 2F 68 A1
B9 DF 12 B6 81 AC 74 6F F6 A9 AB 86 BB 7B 12 FD
9A 54 62 B2 C8 26 1E 33 6A 10 2E D3 57 1D C9 FE
20 2D 99 C9 4E 33 1A CD EA A1 44 36 43 21 69 17
EB 86 60 01 03 02 E3 D3 B8 99 36 D3 0E D5 09 FE
DD BC A0 9D 18 FF 31 19 55 74 8E 10 8A C6 03 A8
15 6C 82 24 00 D7 FD B5 82 F0 14 92 C9 C1 F0 4A
F6 72 6F 59 6A 78 81 FA 40 09 D2 3D 1A D3 A9 59
21 ED 10 43 47 0E 35 80 D0 FD 10 37 10 48 46 8A
76 39 4D 26 C9 06 D1 19 B2 48 57 E5 7B AE 21 D2
16 F3 51 88 61 0D 51 DC A8 A8 71 EB 6B D2 D2 65
62 F8 84 2C BF 11 EB 1E B3 19 67 2E 33 C1 33 BA
FC 65 8E 19 D5 3E 19 73 14 D9 81 D5 63 C7 5D 84
C4 97 5A 92 D3 01 95 B0 4B 64 48 43 CC 73 A9 BA
DC 2A 0F 1E 2B 08 57 EA 1B 78 86 1E 7F 90 AF 8F
A3 FD 18 81 8E 3E 98 77 83 11 43 4A CE 2B 4A 79
BD 2C 1C C0 EC D2 D1 EC C5 6D C9 ED 48 93 90 2D
08 14 05 20 76 30 BC 1D 62 08 A0 6C BF 53 DD A0
A7 52 FD 26 9F 06 50 1F 1B A0 92 6B 45 39 C8 06
FA C3 6B 98 15 40 C8 47 F1 32 A7 D0 29 52 2B D6
A2 84 F9 7A CC 0B 9C 2B 24 F9 29 BF FE EA 1E C3
81 F2 90 10 F3 D4 86 9F 37 75 A0 9F 93 90 FC C4
Sending OUT report...
hid_write wrote 1024 bytes (including Report ID byte).
Waiting for loopback IN report...
Received IN report of 1024 bytes.
Received Report (including IN ID) (total 1024 bytes):
01 C7 B3 C3 85 1B B6 FF 47 B5 89 E8 AA 71 E6 5D
E2 45 3A 2A 5B 77 08 DA 45 0D 88 CD 50 86 95 8A
B4 C7 C6 55 75 58 DA 05 E5 D0 59 10 6A 8E 78 E8
81 AA 3D 8A 03 2B E5 53 A8 7B 83 16 C9 18 E9 6D
6A 8B CB 4C 77 9E 22 DC 4E CA CF 86 7E EF 81 4D
CE 48 D8 62 82 9D CB F2 D9 BA 47 43 DA 21 18 FF
50 FC 0D D0 14 55 57 2C 8A 89 33 73 6E FA C9 37
D1 05 53 DA 5E 34 81 5F E2 B4 1C 7A 0C 09 EB E9
71 00 D3 07 D2 E5 41 9F A2 F7 CD FE C3 19 17 4C
91 CA F5 1C 21 57 D1 41 CA 4F 4C E3 E5 38 27 D3
D2 80 64 1C 3C B7 A8 DB 9D FB E4 50 04 B3 34 34
16 80 08 4D 52 70 81 41 9A 75 1E A8 EF 16 97 64
7D 65 09 35 D7 31 54 88 83 7C C1 90 B9 2F E9 98
68 0D D2 98 7A E6 5A 06 59 0D D9 EE B2 0C 02 45
79 95 0A 7B 2D BC 0D 4F 5D 64 AD E7 6B F7 FC 20
90 5B 9C 23 20 21 24 39 0F FF C6 E0 B5 80 2F 1E
CE FA AF 15 C5 C1 9A D8 32 9A EE 7D A1 72 35 73
95 50 AD 16 CC 89 A7 81 C5 33 2D A3 80 DB E7 96
85 7B 40 2B 27 A6 C4 CA 0A 06 CC 79 E3 08 5E 3A
7F D6 4F 9A 07 86 AA 87 82 90 56 62 9B 86 F2 55
A4 FF 04 E7 DC D5 53 CD ED 90 91 03 B9 21 3D 1C
56 D4 C8 D7 57 80 F7 F2 4E 00 88 43 8F E7 18 04
36 70 44 6F 6B B4 0F 8B E4 20 83 45 AC 25 9C C2
23 31 61 F4 47 DF 54 6B 31 6B 0C 6E E2 68 21 4B
40 B5 48 EB 5C AD BF A9 F6 9E EC 64 43 7C 41 D3
EE D7 62 19 5C 0B 8A 9A 34 B7 2B 0C 1F 70 D4 D1
CC B6 58 84 38 26 2D D2 2C F2 12 8B 07 8F F4 F8
BD AD 13 70 20 6C 61 26 5E CD 2A 45 CB 66 FA 3F
E1 5B BC 61 85 89 1F AC 8C 04 3E E0 7E C4 7F D9
9A 9B BB 1E 1A 6A A0 B8 B8 95 54 40 70 B4 5B 3C
88 8C BB AC CE 3D 5E DF 21 BC B7 8B 32 84 A9 1D
8C 89 A4 4E D2 6E 11 F7 48 F7 F0 26 95 C1 BF 71
C8 31 9E 8A 98 AA B2 14 F0 03 C7 B5 AB 38 39 6D
9C 5F 14 26 D1 DE 7A 8C 18 DC 45 1E C3 F5 EE 85
A9 32 AE 25 6D 38 E2 F3 03 BF B4 86 6F 46 F8 70
D0 05 54 CE 9E 24 A4 1E 30 2A 9C 51 81 B8 AF 21
33 77 30 A5 D4 4F B8 23 61 DA C7 25 08 18 AE CF
32 64 AC 6F C1 A6 57 56 96 CB 3D E7 57 72 CC ED
6F E8 6F 32 56 57 FA 4D 12 3A 48 BB FE 14 22 31
CA 62 63 31 C3 CE 5A DC 54 A5 70 07 CD 8B 0B 90
64 6E B2 F2 7A B8 71 18 1F C9 7F 6F D7 A4 1E 3F
9E E8 C3 3B 2B 03 77 57 72 A2 7D D9 6C 6B 35 B3
1A EF 40 10 C8 DA E5 2D 8F 6D B3 6A 1D 2F 68 A1
B9 DF 12 B6 81 AC 74 6F F6 A9 AB 86 BB 7B 12 FD
9A 54 62 B2 C8 26 1E 33 6A 10 2E D3 57 1D C9 FE
20 2D 99 C9 4E 33 1A CD EA A1 44 36 43 21 69 17
EB 86 60 01 03 02 E3 D3 B8 99 36 D3 0E D5 09 FE
DD BC A0 9D 18 FF 31 19 55 74 8E 10 8A C6 03 A8
15 6C 82 24 00 D7 FD B5 82 F0 14 92 C9 C1 F0 4A
F6 72 6F 59 6A 78 81 FA 40 09 D2 3D 1A D3 A9 59
21 ED 10 43 47 0E 35 80 D0 FD 10 37 10 48 46 8A
76 39 4D 26 C9 06 D1 19 B2 48 57 E5 7B AE 21 D2
16 F3 51 88 61 0D 51 DC A8 A8 71 EB 6B D2 D2 65
62 F8 84 2C BF 11 EB 1E B3 19 67 2E 33 C1 33 BA
FC 65 8E 19 D5 3E 19 73 14 D9 81 D5 63 C7 5D 84
C4 97 5A 92 D3 01 95 B0 4B 64 48 43 CC 73 A9 BA
DC 2A 0F 1E 2B 08 57 EA 1B 78 86 1E 7F 90 AF 8F
A3 FD 18 81 8E 3E 98 77 83 11 43 4A CE 2B 4A 79
BD 2C 1C C0 EC D2 D1 EC C5 6D C9 ED 48 93 90 2D
08 14 05 20 76 30 BC 1D 62 08 A0 6C BF 53 DD A0
A7 52 FD 26 9F 06 50 1F 1B A0 92 6B 45 39 C8 06
FA C3 6B 98 15 40 C8 47 F1 32 A7 D0 29 52 2B D6
A2 84 F9 7A CC 0B 9C 2B 24 F9 29 BF FE EA 1E C3
81 F2 90 10 F3 D4 86 9F 37 75 A0 9F 93 90 FC C4
>>> SUCCESS: Loopback matches perfectly! <<<