Skip to content

Instantly share code, notes, and snippets.

@todbot
Last active June 7, 2024 19:34
Show Gist options
  • Save todbot/6c39e9f2e9719643e5be8f1c82cf9f79 to your computer and use it in GitHub Desktop.
Save todbot/6c39e9f2e9719643e5be8f1c82cf9f79 to your computer and use it in GitHub Desktop.
circuitpython raw hid demo
# rawhid_code.py -- copy to CIRCUITPY as "code.py"
# don't forget to install rawhid_boot.py as "boot.py" and press reset
# works with report IDs up to 63 byte report count
# test with hidapitester like:
# ./hidapitester --usagePage 0xff00 --usage 1 --open -l 64 --send-output 2,3,4,5 --timeout 1000 --read-input 1
# adapted from code presented here:
# https://github.com/libusb/hidapi/issues/478
import time
import usb_hid
import adafruit_hid
raw_hid = adafruit_hid.find_device(usb_hid.devices, usage_page=0xff00, usage=0x01)
print("raw_hid: %04x %04x" % (raw_hid.usage_page, raw_hid.usage) )
while True:
out_report = raw_hid.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
raw_hid.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
))
raw_hid = 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( (raw_hid,) )
@dtcooper
Copy link

Is this duplicated line needed?

    0x09, 0x00,        # Usage (Undefined)
    0x09, 0x00,        # Usage Page (Undefined)

Trying to understand how to write the simplest two-way custom HID device. Thanks for sharing this! Very useful.

@todbot
Copy link
Author

todbot commented May 23, 2024

Hi @dtcooper,
It's unclear to me. Since it's all in the same Collection, I think most items apply as soon as they're stated. So I think you may be correct. But I've never tested it.

@dtcooper
Copy link

dtcooper commented Jun 7, 2024

Appears to be broken in CircuitPython 9.1.0-beta.3 for at least the Raspberry Pi Pico. Workaround is use CircuitPython 9.1.0-beta.2.

Noting this for anyone that might find this info useful! See related issue: adafruit/circuitpython#9306

Cheers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment