Skip to content

HIDAPI testing device with known good firmware, including using Virtual HID device for CI Testing #478

Closed

Description

@mcuee

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

Activity

  1. added
    build system/CIAnything related to building the project or running on CI
    on Oct 31, 2022
  2. mcuee commented on Oct 31, 2022

    @mcuee
    MemberAuthor
  3. Youw commented on Mar 12, 2023

    @Youw
    Member

    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.

  4. changed the title [-]Consider using umockdev hidraw device for testing under Linux[/-] [+]Consider using umockdev or uhid hidraw device for testing under Linux[/+] on May 11, 2023
  5. changed the title [-]Consider using umockdev or uhid hidraw device for testing under Linux[/-] [+]Using Virtual HID device for CI Testing -- using umockdev or uhid hidraw or others under Linux[/+] on May 14, 2023
  6. mcuee commented on May 14, 2023

    @mcuee
    MemberAuthor

    I am not so sure if this is possible or not.
    https://github.com/vpelletier/python-functionfs

  7. mcuee commented on May 14, 2023

    @mcuee
    MemberAuthor

    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.

    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.

    1. Logitech USB Receiver
    2. Plantronics USB Headset
    3. My laptop has built-in I2C HID device (Synaptics Touch Pad)
    4. USB Mouse/Keyboard
    5. Bluetooth Mouse (Microsoft 3600 and maybe others)
    6. Logitech Dual Action USB Gamepad
    7. Wireless Xbox Gamepad (old version)
    8. 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.

    1. Microchip PIC18F87J50 with custom HID FW (8 bit USB PIC18 MCU). I have USB PIC24 and PIC32 board as well but seldom use them.
    2. Cypress EZ-USB FX2LP breadout board
    3. Arduino Leonardo and Pro Micro based HID example (8 bit USB AVR MCU)
    4. Arduino M0 clone (Atmel SAMD21)
    5. Teensy 2.0 and 2.0+ based HID example (8 bit USB AVR MCU)
    6. Various STM32 MCU demo boards
    7. Raspberry Pi Pico using C++ or MicroPython or CircuitPython
    8. ESP32C3/S2/S3 based boards using C or MicroPython or CircuitPython
    9. 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).

  8. Youw commented on May 14, 2023

    @Youw
    Member

    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.

  9. Youw commented on May 14, 2023

    @Youw
    Member

    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.

  10. changed the title [-]Using Virtual HID device for CI Testing -- using umockdev or uhid hidraw or others under Linux[/-] [+]HIDAPI testing device with known good firmware, including using Virtual HID device for CI Testing[/+] on May 14, 2023
  11. mcuee commented on May 14, 2023

    @mcuee
    MemberAuthor

    @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

    1. ProMicroRawHID -- USB AVR Atmega32U4
    2. TeensyRawHID -- can be used by different Teensy boards (USB AVR and Arm Cortex M MCUs)
    3. 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

  12. mcuee commented on May 14, 2023

    @mcuee
    MemberAuthor

    Jan Axelson has quite some HID examples for things like Cypress EZ-USB FX2LP and Microchip USB PIC.
    http://janaxelson.com/hidpage.htm

  13. mcuee commented on May 14, 2023

    @mcuee
    MemberAuthor

    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
    
  14. mcuee commented on May 14, 2023

    @mcuee
    MemberAuthor

    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
    
  15. mcuee commented on May 14, 2023

    @mcuee
    MemberAuthor

    @Youw

    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 US$5. 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
    

    fx2hid_64bytes.zip
    Target.zip

    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.

  16. 17 remaining items

  17. mcuee commented on Jun 11, 2023

    @mcuee
    MemberAuthor

    @todbot

    Yes you are right. The following works.

    usb_hid.enable( (custom_device,) )
    

    Relevant discussion here.

  18. todbot commented on Jun 14, 2023

    @todbot
    Contributor

    I have had problems with 64-byte reports with report IDs. Not sure if this is a MCU buffer limitation (which is 64 bytes usually), an issue with hidapi, or something else.

    Here is a modified set of above code that does work, up to 63 byte reports:

    # 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,) )

    And running hidapitester:

    ./hidapitester --usagePage 0xff00 --usage 1 --open -l 64 --send-output 2,3,4,5 --timeout 1000 --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 03 04 05 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, 1000 msec timeout...read 64 bytes:
     01 03 04 05 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

    Note that hidapitester is given -l 64 to make a report that is REPORT_COUNT+1 long.

    When run, the CircuitPython device outputs this on its REPL:

    custom_device: ff00 0001
    len: 63 ['03', '04', '05', '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']
    sending copy on reportid 1
    
  19. mcuee commented on Jun 14, 2023

    @mcuee
    MemberAuthor

    I have had problems with 64-byte reports with report IDs. Not sure if this is a MCU buffer limitation (which is 64 bytes usually), an issue with hidapi, or something else.

    @todbot

    Thanks a lot for the help.

    Interesting and this is exactly the same problem I have with my USB PIC using Jan Axelson's generic HID example as well. 63 bytes works but not 64 bytes.
    Firmware_generic_hid4_63B.zip

    I think there are a few potential reasons.

    1. MCU FW problem, one possible cause is ZLP related issues.
    2. hidapitester issue (see below)
    3. hidapi issue
    4. combination of the above, espeically 1) and 2).

    Note that hidapitester is given -l 64 to make a report that is REPORT_COUNT+1 long.

    This is one potential issue of hidapitester I would like to check with you and @Youw. I am thinking this should be worked-around inside hidapitest for Windows (report ID 0 needs to be in the buffer but not really appear in the USB BUS. That is probably why we need one more bytes of bufer than the length of report size. I believe this is not necessary for Linux and Windows. I could be wrong though.

  20. todbot commented on Jun 15, 2023

    @todbot
    Contributor

    Note that hidapitester is given -l 64 to make a report that is REPORT_COUNT+1 long.

    This is one potential issue of hidapitester I would like to check with you and @Youw.

    This reflects how hidapi works, where the first byte of the send buffer is the reportId if it exists, which I believe came from how libusb works. It's always bugged me and has led to so much confusion, but I'm not sure how we could get around it.

  21. mcuee commented on Jun 15, 2023

    @mcuee
    MemberAuthor

    This reflects how hidapi works, where the first byte of the send buffer is the reportId if it exists, which I believe came from how libusb works. It's always bugged me and has led to so much confusion, but I'm not sure how we could get around it.

    @Youw

    Please take a look when you got the time. Thanks.

  22. mcuee commented on Jun 15, 2023

    @mcuee
    MemberAuthor

    @Youw and @todbot and @JoergAtGithub

    I think we have gone through this report length previously. Maybe we have to revisit them.

    I think the following PR fixes the issue for reading back the input report and it is correct.

    I think we need to revisit for Feature report. I think the following commit is kind of correct if we look at from Windows driver point of view.
    https://sourceforge.net/p/libusb/mailman/message/37303650/

    But from a cross-platform API point of view, we may need to revist to align with Linux and macOS, which means we need to focus on the data on the USB bus and we need to drop the extra 0 in front when the report ID is 0 for Windows.
    6fcb0bb

    Same for Output report. Right now we may report one more byte than real data on the bus due to Windows driver behavior, when the report ID is 0.

    All in all, we may need to align Windows HIDAPI behavior along with Linux and macOS. Need to check with the libusb backend as well.

    Another related old PR for macOS.

  23. mcuee commented on Jun 15, 2023

    @mcuee
    MemberAuthor

    There are many confusions under libusb Windows HID backend as well. I think there are more problems with libusb Windows HID backend (libusb project recommends people to use HIDAPI and not libusb, so it is a legacy thingy).

    There is another interesting issue there as well (hopefully not affecting HIDAPI).

  24. mcuee commented on Jun 15, 2023

    @mcuee
    MemberAuthor

    @tormodvolden

    FYI as well. I believe libusb/libusb#1217 is incorrect.

  25. Youw commented on Jun 15, 2023

    @Youw
    Member

    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...

  26. mcuee commented on Jun 16, 2023

    @mcuee
    MemberAuthor

    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

    1. Arduino Micro or Leonardo clone (ATmega32U4)
    2. Raspeberry Pico (official or from 3rd parties)
    3. 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.

  27. Youw commented on Jun 16, 2023

    @Youw
    Member

    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.

  28. mcuee commented on Jun 16, 2023

    @mcuee
    MemberAuthor

    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

  29. mcuee commented on Jun 16, 2023

    @mcuee
    MemberAuthor

    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.

  30. locked and limited conversation to collaborators on Jun 16, 2023
  31. converted this issue into a discussion #590 on Jun 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    build system/CIAnything related to building the project or running on CI

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions