Skip to content

Instantly share code, notes, and snippets.

@todbot
Last active May 25, 2026 20:14
Show Gist options
  • Select an option

  • Save todbot/ef096ad868763a8566f262c0ff310e14 to your computer and use it in GitHub Desktop.

Select an option

Save todbot/ef096ad868763a8566f262c0ff310e14 to your computer and use it in GitHub Desktop.
HID LED LampArray
# lamparray_boot.py --
# any changes here only reflected after board reset
import usb_hid
LAMPARRAYHID_REPORT_DESCRIPTOR = bytes((
0x05, 0x59, # UsagePage(Lighting And Illumination[0x0059])
0x09, 0x01, # UsageId(LampArray[0x0001])
0xA1, 0x01, # Collection(Application)
0x85, 0x01, # ReportId(1)
0x09, 0x02, # UsageId(LampArrayAttributesReport[0x0002])
0xA1, 0x02, # Collection(Logical)
0x09, 0x03, # UsageId(LampCount[0x0003])
0x15, 0x00, # LogicalMinimum(0)
0x27, 0xFF, 0xFF, 0x00, 0x00, # LogicalMaximum(65,535)
0x95, 0x01, # ReportCount(1)
0x75, 0x10, # ReportSize(16)
0xB1, 0x03, # Feature(Constant, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
0x09, 0x04, # UsageId(BoundingBoxWidthInMicrometers[0x0004])
0x09, 0x05, # UsageId(BoundingBoxHeightInMicrometers[0x0005])
0x09, 0x06, # UsageId(BoundingBoxDepthInMicrometers[0x0006])
0x09, 0x07, # UsageId(LampArrayKind[0x0007])
0x09, 0x08, # UsageId(MinUpdateIntervalInMicroseconds[0x0008])
0x27, 0xFF, 0xFF, 0xFF, 0x7F, # LogicalMaximum(2,147,483,647)
0x95, 0x05, # ReportCount(5)
0x75, 0x20, # ReportSize(32)
0xB1, 0x03, # Feature(Constant, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
0xC0, # EndCollection()
0x85, 0x02, # ReportId(2)
0x09, 0x20, # UsageId(LampAttributesRequestReport[0x0020])
0xA1, 0x02, # Collection(Logical)
0x09, 0x21, # UsageId(LampId[0x0021])
0x27, 0xFF, 0xFF, 0x00, 0x00, # LogicalMaximum(65,535)
0x95, 0x01, # ReportCount(1)
0x75, 0x10, # ReportSize(16)
0xB1, 0x02, # Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
0xC0, # EndCollection()
0x85, 0x03, # ReportId(3)
0x09, 0x22, # UsageId(LampAttributesResponseReport[0x0022])
0xA1, 0x02, # Collection(Logical)
0x09, 0x21, # UsageId(LampId[0x0021])
0xB1, 0x02, # Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
0x09, 0x23, # UsageId(PositionXInMicrometers[0x0023])
0x09, 0x24, # UsageId(PositionYInMicrometers[0x0024])
0x09, 0x25, # UsageId(PositionZInMicrometers[0x0025])
0x09, 0x27, # UsageId(UpdateLatencyInMicroseconds[0x0027])
0x09, 0x26, # UsageId(LampPurposes[0x0026])
0x27, 0xFF, 0xFF, 0xFF, 0x7F, # LogicalMaximum(2,147,483,647)
0x95, 0x05, # ReportCount(5)
0x75, 0x20, # ReportSize(32)
0xB1, 0x02, # Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
0x09, 0x28, # UsageId(RedLevelCount[0x0028])
0x09, 0x29, # UsageId(GreenLevelCount[0x0029])
0x09, 0x2A, # UsageId(BlueLevelCount[0x002A])
0x09, 0x2B, # UsageId(IntensityLevelCount[0x002B])
0x09, 0x2C, # UsageId(IsProgrammable[0x002C])
0x09, 0x2D, # UsageId(InputBinding[0x002D])
0x26, 0xFF, 0x00, # LogicalMaximum(255)
0x95, 0x06, # ReportCount(6)
0x75, 0x08, # ReportSize(8)
0xB1, 0x02, # Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
0xC0, # EndCollection()
0x85, 0x04, # ReportId(4)
0x09, 0x50, # UsageId(LampMultiUpdateReport[0x0050])
0xA1, 0x02, # Collection(Logical)
0x09, 0x03, # UsageId(LampCount[0x0003])
0x25, 0x08, # LogicalMaximum(8)
0x95, 0x01, # ReportCount(1)
0xB1, 0x02, # Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
0x09, 0x55, # UsageId(LampUpdateFlags[0x0055])
0x25, 0x01, # LogicalMaximum(1)
0xB1, 0x02, # Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
0x09, 0x21, # UsageId(LampId[0x0021])
0x27, 0xFF, 0xFF, 0x00, 0x00, # LogicalMaximum(65,535)
0x95, 0x08, # ReportCount(8)
0x75, 0x10, # ReportSize(16)
0xB1, 0x02, # Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
0x09, 0x51, # UsageId(RedUpdateChannel[0x0051])
0x09, 0x52, # UsageId(GreenUpdateChannel[0x0052])
0x09, 0x53, # UsageId(BlueUpdateChannel[0x0053])
0x09, 0x54, # UsageId(IntensityUpdateChannel[0x0054])
0x09, 0x51, # UsageId(RedUpdateChannel[0x0051])
0x09, 0x52, # UsageId(GreenUpdateChannel[0x0052])
0x09, 0x53, # UsageId(BlueUpdateChannel[0x0053])
0x09, 0x54, # UsageId(IntensityUpdateChannel[0x0054])
0x09, 0x51, # UsageId(RedUpdateChannel[0x0051])
0x09, 0x52, # UsageId(GreenUpdateChannel[0x0052])
0x09, 0x53, # UsageId(BlueUpdateChannel[0x0053])
0x09, 0x54, # UsageId(IntensityUpdateChannel[0x0054])
0x09, 0x51, # UsageId(RedUpdateChannel[0x0051])
0x09, 0x52, # UsageId(GreenUpdateChannel[0x0052])
0x09, 0x53, # UsageId(BlueUpdateChannel[0x0053])
0x09, 0x54, # UsageId(IntensityUpdateChannel[0x0054])
0x09, 0x51, # UsageId(RedUpdateChannel[0x0051])
0x09, 0x52, # UsageId(GreenUpdateChannel[0x0052])
0x09, 0x53, # UsageId(BlueUpdateChannel[0x0053])
0x09, 0x54, # UsageId(IntensityUpdateChannel[0x0054])
0x09, 0x51, # UsageId(RedUpdateChannel[0x0051])
0x09, 0x52, # UsageId(GreenUpdateChannel[0x0052])
0x09, 0x53, # UsageId(BlueUpdateChannel[0x0053])
0x09, 0x54, # UsageId(IntensityUpdateChannel[0x0054])
0x09, 0x51, # UsageId(RedUpdateChannel[0x0051])
0x09, 0x52, # UsageId(GreenUpdateChannel[0x0052])
0x09, 0x53, # UsageId(BlueUpdateChannel[0x0053])
0x09, 0x54, # UsageId(IntensityUpdateChannel[0x0054])
0x09, 0x51, # UsageId(RedUpdateChannel[0x0051])
0x09, 0x52, # UsageId(GreenUpdateChannel[0x0052])
0x09, 0x53, # UsageId(BlueUpdateChannel[0x0053])
0x09, 0x54, # UsageId(IntensityUpdateChannel[0x0054])
0x26, 0xFF, 0x00, # LogicalMaximum(255)
0x95, 0x20, # ReportCount(32)
0x75, 0x08, # ReportSize(8)
0xB1, 0x02, # Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
0xC0, # EndCollection()
0x85, 0x05, # ReportId(5)
0x09, 0x60, # UsageId(LampRangeUpdateReport[0x0060])
0xA1, 0x02, # Collection(Logical)
0x09, 0x55, # UsageId(LampUpdateFlags[0x0055])
0x25, 0x01, # LogicalMaximum(1)
0x95, 0x01, # ReportCount(1)
0xB1, 0x02, # Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
0x09, 0x61, # UsageId(LampIdStart[0x0061])
0x09, 0x62, # UsageId(LampIdEnd[0x0062])
0x27, 0xFF, 0xFF, 0x00, 0x00, # LogicalMaximum(65,535)
0x95, 0x02, # ReportCount(2)
0x75, 0x10, # ReportSize(16)
0xB1, 0x02, # Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
0x09, 0x51, # UsageId(RedUpdateChannel[0x0051])
0x09, 0x52, # UsageId(GreenUpdateChannel[0x0052])
0x09, 0x53, # UsageId(BlueUpdateChannel[0x0053])
0x09, 0x54, # UsageId(IntensityUpdateChannel[0x0054])
0x26, 0xFF, 0x00, # LogicalMaximum(255)
0x95, 0x04, # ReportCount(4)
0x75, 0x08, # ReportSize(8)
0xB1, 0x02, # Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
0xC0, # EndCollection()
0x85, 0x06, # ReportId(6)
0x09, 0x70, # UsageId(LampArrayControlReport[0x0070])
0xA1, 0x02, # Collection(Logical)
0x09, 0x71, # UsageId(AutonomousMode[0x0071])
0x25, 0x01, # LogicalMaximum(1)
0x95, 0x01, # ReportCount(1)
0xB1, 0x02, # Feature(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, NonVolatile, BitField)
0xC0, # EndCollection()
0xC0, # EndCollection()
))
lamparray_hid = usb_hid.Device(
report_descriptor=LAMPARRAYHID_REPORT_DESCRIPTOR,
usage_page=0x0059, # UsagePage(Lighting And Illumination[0x0059])
usage=0x0001, # UsageId(LampArray[0x0001])
report_ids=(1, 2, 3, 4, 5, 6),
in_report_lengths=(22, 2, 28, 50, 9, 1),
out_report_lengths=(22, 2, 28, 50, 9, 1), # ???
)
usb_hid.enable( (lamparray_hid,) )
import time
import usb_hid
import adafruit_hid
lamparray_hid = adafruit_hid.find_device(usb_hid.devices, usage_page=0x0059, usage=0x0001)
print("lamparray_hid: %04x %04x" % (lamparray_hid.usage_page, lamparray_hid.usage) )
while True:
out_report = lamparray_hid.get_last_received_report(1) # out from computer
if out_report:
print("len:",len(out_report),["%02x" % x for x in out_report])
time.sleep(0.5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment