This is untested, but something like this.
From https://github.com/microsoft/ArduinoHidForWindows/blob/main/src/LampArrayReportDescriptor.h and https://learn.adafruit.com/adafruit-pixel-trinkey/hid-lamparray
This is untested, but something like this.
From https://github.com/microsoft/ArduinoHidForWindows/blob/main/src/LampArrayReportDescriptor.h and https://learn.adafruit.com/adafruit-pixel-trinkey/hid-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) |