[PATCH 1/1] platform/x86/tuxedo: Add virtual LampArray for TUXEDO NB04 devices

Benjamin Tissoires bentiss at kernel.org
Sat Sep 28 07:27:04 UTC 2024


On Sep 28 2024, Armin Wolf wrote:
> Am 27.09.24 um 23:01 schrieb Pavel Machek:
> 
> > Hi!
> > 
> > > The TUXEDO Sirius 16 Gen1 and TUXEDO Sirius 16 Gen2 devices have a per-key
> > > controllable RGB keyboard backlight. The firmware API for it is implemented
> > > via WMI.
> > Ok.
> > 
> > > To make the backlight userspace configurable this driver emulates a
> > > LampArray HID device and translates the input from hidraw to the
> > > corresponding WMI calls. This is a new approach as the leds subsystem lacks
> > > a suitable UAPI for per-key keyboard backlights, and like this no new UAPI
> > > needs to be established.
> > Please don't.
> > 
> > a) I don't believe emulating crazy HID interface si right thing to
> > do. (Ton of magic constants. IIRC it stores key positions with
> > micrometer accuracy or something that crazy. How is userland going to
> > use this? Will we update micrometers for every single machine?)

This is exactly why I suggest to make use of HID-BPF. The machine
specifics is going to be controlled by userspace, leaving out the crazy
bits out of the kernel.

> > 
> > Even if it is,
> > 
> > b) The emulation should go to generic layer, it is not specific to
> > your hardware.

Well, there is not so much about an emulation here. It's a different way
of presenting the information.
But given that HID LampArray is a HID standard, userspace is able to
implement it once for all the operating systems, which is why this is so
appealing for them. For reference, we have the same issue with SDL and
Steam regarding advanced game controller: they very much prefer to
directly use HID(raw) to talk to the device instead of having a Linux
specific interface.

Also, starting with v6.12, systemd (logind) will be able to provide
hidraw node access to non root applications (in the same way you can
request an input evdev node). So HID LampArray makes a lot of sense IMO.

> > 
> Maybe introducing a misc-device which provides an ioctl-based API similar
> to the HID LampArray would be a solution?
> 
> Basically we would need:
> - ioctl for querying the supported LEDs and their properties
> - ioctl for enabling/disabling autonomous mode
> - ioctl for updating a range of LEDs
> - ioctl for updating multiple LEDs at once

You'll definitely get the API wrong at first, then you'll need to adapt
for a new device, extend it, etc... But then, you'll depend on one
userspace application that can talk to your custom ioctls, because cross
platform applications will have to implement LampArray, and they'ĺl
probably skip your custom ioctls. And once that userspace application is
gone, you'll still have to maintain this forever.

Also, the application needs to have root access to that misc device, or
you need to add extra support for it in systemd...

> 
> If we implement this as a separate subsystem ("illumination subsystem"), then different
> drivers could use this. This would also allow us to add additional ioctl calls later
> for more features.

Again, I strongly advise against this.

I'll just reiterate what makes the more sense to me:
- provide a thin wmi-to-hid layer that creates a normal regular HID
  device from your device (could be using vendor collections)
- deal with the LampArray bits in the HID stack, that we can reuse for
  other devices (I was planing on getting there for my Corsair and
  Logitech keyboads).
- Meanwhile, while prototyping the LampArray support in userspace and
  kernelspace, make use of HID-BPF to transform your vendor protocol
  into LampArray. This will allow to fix things without having to
  support them forever. This is why HID-BPF exists: so we can create
  crazy but safe kernel interfaces, without having to support them
  forever.

Cheers,
Benjamin

> 
> Thanks,
> Armin Wolf
> 
> > > +
> > > +// We don't know if the WMI API is stable and how unique the GUID is for this ODM. To be on the safe
> > > +// side we therefore only run this driver on tested devices defined by this list.
> > 80 columns, /* */ is usual comment style.
> > 
> > To illustrate my point... this is crazy:
> > 
> > (and would require equally crazy par in openrgb to parse).
> > 
> > Best regards,
> > 								Pavel
> > 
> > > +
> > > +static const uint8_t sirius_16_ansii_kbl_mapping[] = {
> > > +	0x29, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42,
> > > +	0x43, 0x44, 0x45, 0xf1, 0x46, 0x4c,   0x4a, 0x4d, 0x4b, 0x4e,
> > > +	0x35, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
> > > +	0x27, 0x2d, 0x2e, 0x2a,               0x53, 0x55, 0x54, 0x56,
> > > +	0x2b, 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c, 0x12,
> > > +	0x13, 0x2f, 0x30, 0x31,               0x5f, 0x60, 0x61,
> > > +	0x39, 0x04, 0x16, 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f,
> > > +	0x33, 0x34, 0x28,                     0x5c, 0x5d, 0x5e, 0x57,
> > > +	0xe1, 0x1d, 0x1b, 0x06, 0x19, 0x05, 0x11, 0x10, 0x36, 0x37,
> > > +	0x38, 0xe5, 0x52,                     0x59, 0x5a, 0x5b,
> > > +	0xe0, 0xfe, 0xe3, 0xe2, 0x2c, 0xe6, 0x65, 0xe4, 0x50, 0x51,
> > > +	0x4f,                                 0x62, 0x63, 0x58
> > > +};
> > > +
> > > +static const uint32_t sirius_16_ansii_kbl_mapping_pos_x[] = {
> > > +	 25000,  41700,  58400,  75100,  91800, 108500, 125200, 141900, 158600, 175300,
> > > +	192000, 208700, 225400, 242100, 258800, 275500,   294500, 311200, 327900, 344600,
> > > +	 24500,  42500,  61000,  79500,  98000, 116500, 135000, 153500, 172000, 190500,
> > > +	209000, 227500, 246000, 269500,                   294500, 311200, 327900, 344600,
> > > +	 31000,  51500,  70000,  88500, 107000, 125500, 144000, 162500, 181000, 199500,
> > > +	218000, 236500, 255000, 273500,                   294500, 311200, 327900,
> > > +	 33000,  57000,  75500,  94000, 112500, 131000, 149500, 168000, 186500, 205000,
> > > +	223500, 242000, 267500,                           294500, 311200, 327900, 344600,
> > > +	 37000,  66000,  84500, 103000, 121500, 140000, 158500, 177000, 195500, 214000,
> > > +	232500, 251500, 273500,                           294500, 311200, 327900,
> > > +	 28000,  47500,  66000,  84500, 140000, 195500, 214000, 234000, 255000, 273500,
> > > +	292000,                                           311200, 327900, 344600
> > > +};
> > > +
> > > +static const uint32_t sirius_16_ansii_kbl_mapping_pos_y[] = {
> > > +	 53000,  53000,  53000,  53000,  53000,  53000,  53000,  53000,  53000,  53000,
> > > +	 53000,  53000,  53000,  53000,  53000,  53000,    53000,  53000,  53000,  53000,
> > > +	 67500,  67500,  67500,  67500,  67500,  67500,  67500,  67500,  67500,  67500,
> > > +	 67500,  67500,  67500,  67500,                    67500,  67500,  67500,  67500,
> > > +	 85500,  85500,  85500,  85500,  85500,  85500,  85500,  85500,  85500,  85500,
> > > +	 85500,  85500,  85500,  85500,                    85500,  85500,  85500,
> > > +	103500, 103500, 103500, 103500, 103500, 103500, 103500, 103500, 103500, 103500,
> > > +	103500, 103500, 103500,                           103500, 103500, 103500,  94500,
> > > +	121500, 121500, 121500, 121500, 121500, 121500, 121500, 121500, 121500, 121500,
> > > +	121500, 121500, 129000,                           121500, 121500, 121500,
> > > +	139500, 139500, 139500, 139500, 139500, 139500, 139500, 139500, 147000, 147000,
> > > +	147000,                                           139500, 139500, 130500
> > > +};
> > > +
> > > +static const uint32_t sirius_16_ansii_kbl_mapping_pos_z[] = {
> > > +	  5000,   5000,   5000,   5000,   5000,   5000,   5000,   5000,   5000,   5000,
> > > +	  5000,   5000,   5000,   5000,   5000,   5000,     5000,   5000,   5000,   5000,
> > > +	  5250,   5250,   5250,   5250,   5250,   5250,   5250,   5250,   5250,   5250,
> > > +	  5250,   5250,   5250,   5250,                     5250,   5250,   5250,   5250,
> > > +	  5500,   5500,   5500,   5500,   5500,   5500,   5500,   5500,   5500,   5500,
> > > +	  5500,   5500,   5500,   5500,                     5500,   5500,   5500,
> > > +	  5750,   5750,   5750,   5750,   5750,   5750,   5750,   5750,   5750,   5750,
> > > +	  5750,   5750,   5750,                             5750,   5750,   5750,   5625,
> > > +	  6000,   6000,   6000,   6000,   6000,   6000,   6000,   6000,   6000,   6000,
> > > +	  6000,   6000,   6125,                             6000,   6000,   6000,
> > > +	  6250,   6250,   6250,   6250,   6250,   6250,   6250,   6250,   6375,   6375,
> > > +	  6375,                                             6250,   6250,   6125
> > > +};
> > > +
> > > +static const uint8_t sirius_16_iso_kbl_mapping[] = {
> > > +	0x29, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42,
> > > +	0x43, 0x44, 0x45, 0xf1, 0x46, 0x4c,   0x4a, 0x4d, 0x4b, 0x4e,
> > > +	0x35, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
> > > +	0x27, 0x2d, 0x2e, 0x2a,               0x53, 0x55, 0x54, 0x56,
> > > +	0x2b, 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c, 0x12,
> > > +	0x13, 0x2f, 0x30,                     0x5f, 0x60, 0x61,
> > > +	0x39, 0x04, 0x16, 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f,
> > > +	0x33, 0x34, 0x32, 0x28,               0x5c, 0x5d, 0x5e, 0x57,
> > > +	0xe1, 0x64, 0x1d, 0x1b, 0x06, 0x19, 0x05, 0x11, 0x10, 0x36,
> > > +	0x37, 0x38, 0xe5, 0x52,               0x59, 0x5a, 0x5b,
> > > +	0xe0, 0xfe, 0xe3, 0xe2, 0x2c, 0xe6, 0x65, 0xe4, 0x50, 0x51,
> > > +	0x4f,                                 0x62, 0x63, 0x58
> > > +};
> > > +
> > > +static const uint32_t sirius_16_iso_kbl_mapping_pos_x[] = {
> > > +	 25000,  41700,  58400,  75100,  91800, 108500, 125200, 141900, 158600, 175300,
> > > +	192000, 208700, 225400, 242100, 258800, 275500,   294500, 311200, 327900, 344600,
> > > +	 24500,  42500,  61000,  79500,  98000, 116500, 135000, 153500, 172000, 190500,
> > > +	209000, 227500, 246000, 269500,                   294500, 311200, 327900, 344600,
> > > +	 31000,  51500,  70000,  88500, 107000, 125500, 144000, 162500, 181000, 199500,
> > > +	218000, 234500, 251000,                           294500, 311200, 327900,
> > > +	 33000,  57000,  75500,  94000, 112500, 131000, 149500, 168000, 186500, 205000,
> > > +	223500, 240000, 256500, 271500,                   294500, 311200, 327900, 344600,
> > > +	 28000,  47500,  66000,  84500, 103000, 121500, 140000, 158500, 177000, 195500,
> > > +	214000, 232500, 251500, 273500,                   294500, 311200, 327900,
> > > +	 28000,  47500,  66000,  84500, 140000, 195500, 214000, 234000, 255000, 273500,
> > > +	292000,                                           311200, 327900, 344600
> > > +};
> > > +
> > > +static const uint32_t sirius_16_iso_kbl_mapping_pos_y[] = {
> > > +	 53000,  53000,  53000,  53000,  53000,  53000,  53000,  53000,  53000,  53000,
> > > +	 53000,  53000,  53000,  53000,  53000,  53000,    53000,  53000,  53000,  53000,
> > > +	 67500,  67500,  67500,  67500,  67500,  67500,  67500,  67500,  67500,  67500,
> > > +	 67500,  67500,  67500,  67500,                    67500,  67500,  67500,  67500,
> > > +	 85500,  85500,  85500,  85500,  85500,  85500,  85500,  85500,  85500,  85500,
> > > +	 85500,  85500,  85500,                            85500,  85500,  85500,
> > > +	103500, 103500, 103500, 103500, 103500, 103500, 103500, 103500, 103500, 103500,
> > > +	103500, 103500, 103500,  94500,                   103500, 103500, 103500,  94500,
> > > +	121500, 121500, 121500, 121500, 121500, 121500, 121500, 121500, 121500, 121500,
> > > +	121500, 121500, 121500, 129000,                   121500, 121500, 121500,
> > > +	139500, 139500, 139500, 139500, 139500, 139500, 139500, 139500, 147000, 147000,
> > > +	147000,                                           139500, 139500, 130500
> > > +};
> > > +
> > > +static const uint32_t sirius_16_iso_kbl_mapping_pos_z[] = {
> > > +	  5000,   5000,   5000,   5000,   5000,   5000,   5000,   5000,   5000,   5000,
> > > +	  5000,   5000,   5000,   5000, 5000, 5000,         5000,   5000,   5000,   5000,
> > > +	  5250,   5250,   5250,   5250,   5250,   5250,   5250,   5250,   5250,   5250,
> > > +	  5250,   5250,   5250,   5250,                     5250,   5250,   5250,   5250,
> > > +	  5500,   5500,   5500,   5500,   5500,   5500,   5500,   5500,   5500,   5500,
> > > +	  5500,   5500,   5500,                             5500,   5500,   5500,
> > > +	  5750,   5750,   5750,   5750,   5750,   5750,   5750,   5750,   5750,   5750,
> > > +	  5750,   5750,   5750,   5750,                     5750,   5750,   5750,   5625,
> > > +	  6000,   6000,   6000,   6000,   6000,   6000,   6000,   6000,   6000,   6000,
> > > +	  6000,   6000,   6000,   6125,                     6000,   6000,   6000,
> > > +	  6250,   6250,   6250,   6250,   6250,   6250,   6250,   6250,   6375,   6375,
> > > +	  6375,                                             6250,   6250,   6125
> > > +};
> > ...
> > > +
> > > +static uint8_t report_descriptor[327] = {
> > > +	0x05, 0x59,			// Usage Page (Lighting and Illumination)
> > > +	0x09, 0x01,			// Usage (Lamp Array)
> > > +	0xa1, 0x01,			// Collection (Application)
> > > +	0x85, LAMP_ARRAY_ATTRIBUTES_REPORT_ID, //  Report ID (1)
> > > +	0x09, 0x02,			//  Usage (Lamp Array Attributes Report)
> > > +	0xa1, 0x02,			//  Collection (Logical)
> > > +	0x09, 0x03,			//   Usage (Lamp Count)
> > > +	0x15, 0x00,			//   Logical Minimum (0)
> > > +	0x27, 0xff, 0xff, 0x00, 0x00,	//   Logical Maximum (65535)
> > > +	0x75, 0x10,			//   Report Size (16)
> > > +	0x95, 0x01,			//   Report Count (1)
> > > +	0xb1, 0x03,			//   Feature (Cnst,Var,Abs)
> > > +	0x09, 0x04,			//   Usage (Bounding Box Width In Micrometers)
> > > +	0x09, 0x05,			//   Usage (Bounding Box Height In Micrometers)
> > > +	0x09, 0x06,			//   Usage (Bounding Box Depth In Micrometers)
> > > +	0x09, 0x07,			//   Usage (Lamp Array Kind)
> > > +	0x09, 0x08,			//   Usage (Min Update Interval In Microseconds)
> > > +	0x15, 0x00,			//   Logical Minimum (0)
> > > +	0x27, 0xff, 0xff, 0xff, 0x7f,	//   Logical Maximum (2147483647)
> > > +	0x75, 0x20,			//   Report Size (32)
> > > +	0x95, 0x05,			//   Report Count (5)
> > > +	0xb1, 0x03,			//   Feature (Cnst,Var,Abs)
> > > +	0xc0,				//  End Collection
> > > +	0x85, LAMP_ATTRIBUTES_REQUEST_REPORT_ID, //  Report ID (2)
> > > +	0x09, 0x20,			//  Usage (Lamp Attributes Request Report)
> > > +	0xa1, 0x02,			//  Collection (Logical)
> > > +	0x09, 0x21,			//   Usage (Lamp Id)
> > > +	0x15, 0x00,			//   Logical Minimum (0)
> > > +	0x27, 0xff, 0xff, 0x00, 0x00,	//   Logical Maximum (65535)
> > > +	0x75, 0x10,			//   Report Size (16)
> > > +	0x95, 0x01,			//   Report Count (1)
> > > +	0xb1, 0x02,			//   Feature (Data,Var,Abs)
> > > +	0xc0,				//  End Collection
> > > +	0x85, LAMP_ATTRIBUTES_RESPONSE_REPORT_ID, //  Report ID (3)
> > > +	0x09, 0x22,			//  Usage (Lamp Attributes Response Report)
> > > +	0xa1, 0x02,			//  Collection (Logical)
> > > +	0x09, 0x21,			//   Usage (Lamp Id)
> > > +	0x15, 0x00,			//   Logical Minimum (0)
> > > +	0x27, 0xff, 0xff, 0x00, 0x00,	//   Logical Maximum (65535)
> > > +	0x75, 0x10,			//   Report Size (16)
> > > +	0x95, 0x01,			//   Report Count (1)
> > > +	0xb1, 0x02,			//   Feature (Data,Var,Abs)
> > > +	0x09, 0x23,			//   Usage (Position X In Micrometers)
> > > +	0x09, 0x24,			//   Usage (Position Y In Micrometers)
> > > +	0x09, 0x25,			//   Usage (Position Z In Micrometers)
> > > +	0x09, 0x27,			//   Usage (Update Latency In Microseconds)
> > > +	0x09, 0x26,			//   Usage (Lamp Purposes)
> > > +	0x15, 0x00,			//   Logical Minimum (0)
> > > +	0x27, 0xff, 0xff, 0xff, 0x7f,	//   Logical Maximum (2147483647)
> > > +	0x75, 0x20,			//   Report Size (32)
> > > +	0x95, 0x05,			//   Report Count (5)
> > > +	0xb1, 0x02,			//   Feature (Data,Var,Abs)
> > > +	0x09, 0x28,			//   Usage (Red Level Count)
> > > +	0x09, 0x29,			//   Usage (Green Level Count)
> > > +	0x09, 0x2a,			//   Usage (Blue Level Count)
> > > +	0x09, 0x2b,			//   Usage (Intensity Level Count)
> > > +	0x09, 0x2c,			//   Usage (Is Programmable)
> > > +	0x09, 0x2d,			//   Usage (Input Binding)
> > > +	0x15, 0x00,			//   Logical Minimum (0)
> > > +	0x26, 0xff, 0x00,		//   Logical Maximum (255)
> > > +	0x75, 0x08,			//   Report Size (8)
> > > +	0x95, 0x06,			//   Report Count (6)
> > > +	0xb1, 0x02,			//   Feature (Data,Var,Abs)
> > > +	0xc0,				//  End Collection
> > > +	0x85, LAMP_MULTI_UPDATE_REPORT_ID, //  Report ID (4)
> > > +	0x09, 0x50,			//  Usage (Lamp Multi Update Report)
> > > +	0xa1, 0x02,			//  Collection (Logical)
> > > +	0x09, 0x03,			//   Usage (Lamp Count)
> > > +	0x09, 0x55,			//   Usage (Lamp Update Flags)
> > > +	0x15, 0x00,			//   Logical Minimum (0)
> > > +	0x25, 0x08,			//   Logical Maximum (8)
> > > +	0x75, 0x08,			//   Report Size (8)
> > > +	0x95, 0x02,			//   Report Count (2)
> > > +	0xb1, 0x02,			//   Feature (Data,Var,Abs)
> > > +	0x09, 0x21,			//   Usage (Lamp Id)
> > > +	0x15, 0x00,			//   Logical Minimum (0)
> > > +	0x27, 0xff, 0xff, 0x00, 0x00,	//   Logical Maximum (65535)
> > > +	0x75, 0x10,			//   Report Size (16)
> > > +	0x95, 0x08,			//   Report Count (8)
> > > +	0xb1, 0x02,			//   Feature (Data,Var,Abs)
> > > +	0x09, 0x51,			//   Usage (Red Update Channel)
> > > +	0x09, 0x52,			//   Usage (Green Update Channel)
> > > +	0x09, 0x53,			//   Usage (Blue Update Channel)
> > > +	0x09, 0x54,			//   Usage (Intensity Update Channel)
> > > +	0x09, 0x51,			//   Usage (Red Update Channel)
> > > +	0x09, 0x52,			//   Usage (Green Update Channel)
> > > +	0x09, 0x53,			//   Usage (Blue Update Channel)
> > > +	0x09, 0x54,			//   Usage (Intensity Update Channel)
> > > +	0x09, 0x51,			//   Usage (Red Update Channel)
> > > +	0x09, 0x52,			//   Usage (Green Update Channel)
> > > +	0x09, 0x53,			//   Usage (Blue Update Channel)
> > > +	0x09, 0x54,			//   Usage (Intensity Update Channel)
> > > +	0x09, 0x51,			//   Usage (Red Update Channel)
> > > +	0x09, 0x52,			//   Usage (Green Update Channel)
> > > +	0x09, 0x53,			//   Usage (Blue Update Channel)
> > > +	0x09, 0x54,			//   Usage (Intensity Update Channel)
> > > +	0x09, 0x51,			//   Usage (Red Update Channel)
> > > +	0x09, 0x52,			//   Usage (Green Update Channel)
> > > +	0x09, 0x53,			//   Usage (Blue Update Channel)
> > > +	0x09, 0x54,			//   Usage (Intensity Update Channel)
> > > +	0x09, 0x51,			//   Usage (Red Update Channel)
> > > +	0x09, 0x52,			//   Usage (Green Update Channel)
> > > +	0x09, 0x53,			//   Usage (Blue Update Channel)
> > > +	0x09, 0x54,			//   Usage (Intensity Update Channel)
> > > +	0x09, 0x51,			//   Usage (Red Update Channel)
> > > +	0x09, 0x52,			//   Usage (Green Update Channel)
> > > +	0x09, 0x53,			//   Usage (Blue Update Channel)
> > > +	0x09, 0x54,			//   Usage (Intensity Update Channel)
> > > +	0x09, 0x51,			//   Usage (Red Update Channel)
> > > +	0x09, 0x52,			//   Usage (Green Update Channel)
> > > +	0x09, 0x53,			//   Usage (Blue Update Channel)
> > > +	0x09, 0x54,			//   Usage (Intensity Update Channel)
> > > +	0x15, 0x00,			//   Logical Minimum (0)
> > > +	0x26, 0xff, 0x00,		//   Logical Maximum (255)
> > > +	0x75, 0x08,			//   Report Size (8)
> > > +	0x95, 0x20,			//   Report Count (32)
> > > +	0xb1, 0x02,			//   Feature (Data,Var,Abs)
> > > +	0xc0,				//  End Collection
> > > +	0x85, LAMP_RANGE_UPDATE_REPORT_ID, //  Report ID (5)
> > > +	0x09, 0x60,			//  Usage (Lamp Range Update Report)
> > > +	0xa1, 0x02,			//  Collection (Logical)
> > > +	0x09, 0x55,			//   Usage (Lamp Update Flags)
> > > +	0x15, 0x00,			//   Logical Minimum (0)
> > > +	0x25, 0x08,			//   Logical Maximum (8)
> > > +	0x75, 0x08,			//   Report Size (8)
> > > +	0x95, 0x01,			//   Report Count (1)
> > > +	0xb1, 0x02,			//   Feature (Data,Var,Abs)
> > > +	0x09, 0x61,			//   Usage (Lamp Id Start)
> > > +	0x09, 0x62,			//   Usage (Lamp Id End)
> > > +	0x15, 0x00,			//   Logical Minimum (0)
> > > +	0x27, 0xff, 0xff, 0x00, 0x00,	//   Logical Maximum (65535)
> > > +	0x75, 0x10,			//   Report Size (16)
> > > +	0x95, 0x02,			//   Report Count (2)
> > > +	0xb1, 0x02,			//   Feature (Data,Var,Abs)
> > > +	0x09, 0x51,			//   Usage (Red Update Channel)
> > > +	0x09, 0x52,			//   Usage (Green Update Channel)
> > > +	0x09, 0x53,			//   Usage (Blue Update Channel)
> > > +	0x09, 0x54,			//   Usage (Intensity Update Channel)
> > > +	0x15, 0x00,			//   Logical Minimum (0)
> > > +	0x26, 0xff, 0x00,		//   Logical Maximum (255)
> > > +	0x75, 0x08,			//   Report Size (8)
> > > +	0x95, 0x04,			//   Report Count (4)
> > > +	0xb1, 0x02,			//   Feature (Data,Var,Abs)
> > > +	0xc0,				//  End Collection
> > > +	0x85, LAMP_ARRAY_CONTROL_REPORT_ID, //  Report ID (6)
> > > +	0x09, 0x70,			//  Usage (Lamp Array Control Report)
> > > +	0xa1, 0x02,			//  Collection (Logical)
> > > +	0x09, 0x71,			//   Usage (Autonomous Mode)
> > > +	0x15, 0x00,			//   Logical Minimum (0)
> > > +	0x25, 0x01,			//   Logical Maximum (1)
> > > +	0x75, 0x08,			//   Report Size (8)
> > > +	0x95, 0x01,			//   Report Count (1)
> > > +	0xb1, 0x02,			//   Feature (Data,Var,Abs)
> > > +	0xc0,				//  End Collection
> > > +	0xc0				// End Collection
> > > +};
> > > +


More information about the dri-devel mailing list