Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hid_get_report_descriptor: missing unnumbered feature report #703

Closed
SuibianP opened this issue Oct 18, 2024 · 3 comments · Fixed by #707
Closed

hid_get_report_descriptor: missing unnumbered feature report #703

SuibianP opened this issue Oct 18, 2024 · 3 comments · Fixed by #707
Labels
Contributions Welcome Any external help is welcome Windows Related to Windows backend

Comments

@SuibianP
Copy link

On some devices, unnumbered feature reports seem omitted from the parsed HIDP_PREPARSED_DATA. The hid_pp_caps_info header indicates the count and size correctly, but marks it empty/unused.

# Feature caps_info struct:
pp_data->caps_info[2]->FirstCap           = 5
pp_data->caps_info[2]->LastCap            = 5
pp_data->caps_info[2]->NumberOfCaps       = 1
pp_data->caps_info[2]->ReportByteLength   = 91
# Output hid_pp_cap struct:
# Feature hid_pp_cap struct:
# Link Collections:

typedef struct hid_pp_caps_info_ {
USHORT FirstCap;
USHORT NumberOfCaps; // Includes empty caps after LastCap
USHORT LastCap;
USHORT ReportByteLength;
} hid_pp_caps_info, *phid_pp_caps_info;

If I anyhow print the trailing phid_pp_cap out, it consists entirely of zeros.

This is likely an existing bug/undocumented aspect of HidD_GetPreparsedData on MS side, and I am unsure if it could be worked around in userspace.

HID report descriptor (dumped on Linux with hid-decode)
# device 0:0
# 0x05, 0x01,                    // Usage Page (Generic Desktop)        0
# 0x09, 0x02,                    // Usage (Mouse)                       2
# 0xa1, 0x01,                    // Collection (Application)            4
# 0x09, 0x01,                    //  Usage (Pointer)                    6
# 0xa1, 0x00,                    //  Collection (Physical)              8
# 0x05, 0x09,                    //   Usage Page (Button)               10
# 0x19, 0x01,                    //   Usage Minimum (1)                 12
# 0x29, 0x05,                    //   Usage Maximum (5)                 14
# 0x15, 0x00,                    //   Logical Minimum (0)               16
# 0x25, 0x01,                    //   Logical Maximum (1)               18
# 0x75, 0x01,                    //   Report Size (1)                   20
# 0x95, 0x05,                    //   Report Count (5)                  22
# 0x81, 0x02,                    //   Input (Data,Var,Abs)              24
# 0x75, 0x01,                    //   Report Size (1)                   26
# 0x95, 0x03,                    //   Report Count (3)                  28
# 0x81, 0x03,                    //   Input (Cnst,Var,Abs)              30
# 0x06, 0x00, 0xff,              //   Usage Page (Vendor Defined Page 1) 32
# 0x09, 0x40,                    //   Usage (Vendor Usage 0x40)         35
# 0x75, 0x08,                    //   Report Size (8)                   37
# 0x95, 0x02,                    //   Report Count (2)                  39
# 0x15, 0x81,                    //   Logical Minimum (-127)            41
# 0x25, 0x7f,                    //   Logical Maximum (127)             43
# 0x81, 0x02,                    //   Input (Data,Var,Abs)              45
# 0x05, 0x01,                    //   Usage Page (Generic Desktop)      47
# 0x09, 0x38,                    //   Usage (Wheel)                     49
# 0x15, 0x81,                    //   Logical Minimum (-127)            51
# 0x25, 0x7f,                    //   Logical Maximum (127)             53
# 0x75, 0x08,                    //   Report Size (8)                   55
# 0x95, 0x01,                    //   Report Count (1)                  57
# 0x81, 0x06,                    //   Input (Data,Var,Rel)              59
# 0x09, 0x30,                    //   Usage (X)                         61
# 0x09, 0x31,                    //   Usage (Y)                         63
# 0x16, 0x00, 0x80,              //   Logical Minimum (-32768)          65
# 0x26, 0xff, 0x7f,              //   Logical Maximum (32767)           68
# 0x75, 0x10,                    //   Report Size (16)                  71
# 0x95, 0x02,                    //   Report Count (2)                  73
# 0x81, 0x06,                    //   Input (Data,Var,Rel)              75
# 0xc0,                          //  End Collection                     77
# 0x06, 0x00, 0xff,              //  Usage Page (Vendor Defined Page 1) 78
# 0x09, 0x02,                    //  Usage (Vendor Usage 2)             81
# 0x15, 0x00,                    //  Logical Minimum (0)                83
# 0x25, 0x01,                    //  Logical Maximum (1)                85
# 0x75, 0x08,                    //  Report Size (8)                    87
# 0x95, 0x5a,                    //  Report Count (90)                  89
# 0xb1, 0x01,                    //  Feature (Cnst,Arr,Abs)             91
# 0xc0,                          // End Collection                      93
# 
R: 94 05 01 09 02 a1 01 09 01 a1 00 05 09 19 01 29 05 15 00 25 01 75 01 95 05 81 02 75 01 95 03 81 03 06 00 ff 09 40 75 08 95 02 15 81 25 7f 81 02 05 01 09 38 15 81 25 7f 75 08 95 01 81 06 09 30 09 31 16 00 80 26 ff 7f 75 10 95 02 81 06 c0 06 00 ff 09 02 15 00 25 01 75 08 95 5a b1 01 c0
N: device 0:0
I: 3 0001 0001
# device 1:0
# 0x05, 0x01,                    // Usage Page (Generic Desktop)        0
# 0x09, 0x06,                    // Usage (Keyboard)                    2
# 0xa1, 0x01,                    // Collection (Application)            4
# 0x85, 0x01,                    //  Report ID (1)                      6
# 0x05, 0x07,                    //  Usage Page (Keyboard)              8
# 0x19, 0xe0,                    //  Usage Minimum (224)                10
# 0x29, 0xe7,                    //  Usage Maximum (231)                12
# 0x15, 0x00,                    //  Logical Minimum (0)                14
# 0x25, 0x01,                    //  Logical Maximum (1)                16
# 0x75, 0x01,                    //  Report Size (1)                    18
# 0x95, 0x08,                    //  Report Count (8)                   20
# 0x81, 0x02,                    //  Input (Data,Var,Abs)               22
# 0x19, 0x00,                    //  Usage Minimum (0)                  24
# 0x2a, 0xff, 0x00,              //  Usage Maximum (255)                26
# 0x15, 0x00,                    //  Logical Minimum (0)                29
# 0x26, 0xff, 0x00,              //  Logical Maximum (255)              31
# 0x75, 0x08,                    //  Report Size (8)                    34
# 0x95, 0x0e,                    //  Report Count (14)                  36
# 0x81, 0x00,                    //  Input (Data,Arr,Abs)               38
# 0xc0,                          // End Collection                      40
# 0x05, 0x0c,                    // Usage Page (Consumer Devices)       41
# 0x09, 0x01,                    // Usage (Consumer Control)            43
# 0xa1, 0x01,                    // Collection (Application)            45
# 0x85, 0x02,                    //  Report ID (2)                      47
# 0x19, 0x00,                    //  Usage Minimum (0)                  49
# 0x2a, 0x3c, 0x02,              //  Usage Maximum (572)                51
# 0x15, 0x00,                    //  Logical Minimum (0)                54
# 0x26, 0x3c, 0x02,              //  Logical Maximum (572)              56
# 0x95, 0x01,                    //  Report Count (1)                   59
# 0x75, 0x10,                    //  Report Size (16)                   61
# 0x81, 0x00,                    //  Input (Data,Arr,Abs)               63
# 0x75, 0x08,                    //  Report Size (8)                    65
# 0x95, 0x0d,                    //  Report Count (13)                  67
# 0x81, 0x01,                    //  Input (Cnst,Arr,Abs)               69
# 0xc0,                          // End Collection                      71
# 0x05, 0x01,                    // Usage Page (Generic Desktop)        72
# 0x09, 0x80,                    // Usage (System Control)              74
# 0xa1, 0x01,                    // Collection (Application)            76
# 0x85, 0x03,                    //  Report ID (3)                      78
# 0x19, 0x81,                    //  Usage Minimum (129)                80
# 0x29, 0x83,                    //  Usage Maximum (131)                82
# 0x15, 0x00,                    //  Logical Minimum (0)                84
# 0x25, 0x01,                    //  Logical Maximum (1)                86
# 0x75, 0x01,                    //  Report Size (1)                    88
# 0x95, 0x03,                    //  Report Count (3)                   90
# 0x81, 0x02,                    //  Input (Data,Var,Abs)               92
# 0x95, 0x05,                    //  Report Count (5)                   94
# 0x81, 0x01,                    //  Input (Cnst,Arr,Abs)               96
# 0x75, 0x08,                    //  Report Size (8)                    98
# 0x95, 0x0e,                    //  Report Count (14)                  100
# 0x81, 0x01,                    //  Input (Cnst,Arr,Abs)               102
# 0xc0,                          // End Collection                      104
# 0x05, 0x01,                    // Usage Page (Generic Desktop)        105
# 0x09, 0x00,                    // Usage (Undefined)                   107
# 0xa1, 0x01,                    // Collection (Application)            109
# 0x85, 0x04,                    //  Report ID (4)                      111
# 0x09, 0x03,                    //  Usage (Vendor Usage 0x03)          113
# 0x15, 0x00,                    //  Logical Minimum (0)                115
# 0x26, 0xff, 0x00,              //  Logical Maximum (255)              117
# 0x35, 0x00,                    //  Physical Minimum (0)               120
# 0x46, 0xff, 0x00,              //  Physical Maximum (255)             122
# 0x75, 0x08,                    //  Report Size (8)                    125
# 0x95, 0x0f,                    //  Report Count (15)                  127
# 0x81, 0x00,                    //  Input (Data,Arr,Abs)               129
# 0xc0,                          // End Collection                      131
# 0x05, 0x01,                    // Usage Page (Generic Desktop)        132
# 0x09, 0x00,                    // Usage (Undefined)                   134
# 0xa1, 0x01,                    // Collection (Application)            136
# 0x85, 0x05,                    //  Report ID (5)                      138
# 0x09, 0x03,                    //  Usage (Vendor Usage 0x03)          140
# 0x15, 0x00,                    //  Logical Minimum (0)                142
# 0x26, 0xff, 0x00,              //  Logical Maximum (255)              144
# 0x35, 0x00,                    //  Physical Minimum (0)               147
# 0x46, 0xff, 0x00,              //  Physical Maximum (255)             149
# 0x75, 0x08,                    //  Report Size (8)                    152
# 0x95, 0x0f,                    //  Report Count (15)                  154
# 0x81, 0x00,                    //  Input (Data,Arr,Abs)               156
# 0xc0,                          // End Collection                      158
# 
R: 159 05 01 09 06 a1 01 85 01 05 07 19 e0 29 e7 15 00 25 01 75 01 95 08 81 02 19 00 2a ff 00 15 00 26 ff 00 75 08 95 0e 81 00 c0 05 0c 09 01 a1 01 85 02 19 00 2a 3c 02 15 00 26 3c 02 95 01 75 10 81 00 75 08 95 0d 81 01 c0 05 01 09 80 a1 01 85 03 19 81 29 83 15 00 25 01 75 01 95 03 81 02 95 05 81 01 75 08 95 0e 81 01 c0 05 01 09 00 a1 01 85 04 09 03 15 00 26 ff 00 35 00 46 ff 00 75 08 95 0f 81 00 c0 05 01 09 00 a1 01 85 05 09 03 15 00 26 ff 00 35 00 46 ff 00 75 08 95 0f 81 00 c0
N: device 1:0
I: 3 0001 0001
# device 2:0
# 0x05, 0x01,                    // Usage Page (Generic Desktop)        0
# 0x09, 0x06,                    // Usage (Keyboard)                    2
# 0xa1, 0x01,                    // Collection (Application)            4
# 0x05, 0x07,                    //  Usage Page (Keyboard)              6
# 0x19, 0xe0,                    //  Usage Minimum (224)                8
# 0x29, 0xe7,                    //  Usage Maximum (231)                10
# 0x15, 0x00,                    //  Logical Minimum (0)                12
# 0x25, 0x01,                    //  Logical Maximum (1)                14
# 0x75, 0x01,                    //  Report Size (1)                    16
# 0x95, 0x08,                    //  Report Count (8)                   18
# 0x81, 0x02,                    //  Input (Data,Var,Abs)               20
# 0x81, 0x01,                    //  Input (Cnst,Arr,Abs)               22
# 0x19, 0x00,                    //  Usage Minimum (0)                  24
# 0x2a, 0xff, 0x00,              //  Usage Maximum (255)                26
# 0x15, 0x00,                    //  Logical Minimum (0)                29
# 0x26, 0xff, 0x00,              //  Logical Maximum (255)              31
# 0x75, 0x08,                    //  Report Size (8)                    34
# 0x95, 0x06,                    //  Report Count (6)                   36
# 0x81, 0x00,                    //  Input (Data,Arr,Abs)               38
# 0x05, 0x08,                    //  Usage Page (LEDs)                  40
# 0x19, 0x01,                    //  Usage Minimum (1)                  42
# 0x29, 0x03,                    //  Usage Maximum (3)                  44
# 0x15, 0x00,                    //  Logical Minimum (0)                46
# 0x25, 0x01,                    //  Logical Maximum (1)                48
# 0x75, 0x01,                    //  Report Size (1)                    50
# 0x95, 0x03,                    //  Report Count (3)                   52
# 0x91, 0x02,                    //  Output (Data,Var,Abs)              54
# 0x95, 0x05,                    //  Report Count (5)                   56
# 0x91, 0x01,                    //  Output (Cnst,Arr,Abs)              58
# 0xc0,                          // End Collection                      60
# 
R: 61 05 01 09 06 a1 01 05 07 19 e0 29 e7 15 00 25 01 75 01 95 08 81 02 81 01 19 00 2a ff 00 15 00 26 ff 00 75 08 95 06 81 00 05 08 19 01 29 03 15 00 25 01 75 01 95 03 91 02 95 05 91 01 c0
N: device 2:0
I: 3 0001 0001
Full 1532_00A3_0002_0001.pp_data
# HIDAPI device info struct:
dev->vendor_id           = 0x1532
dev->product_id          = 0x00A3
dev->manufacturer_string = "Razer"
dev->product_string      = "Razer Cobra"
dev->release_number      = 0x0200
dev->interface_number    = 0
dev->usage               = 0x0002
dev->usage_page          = 0x0001
dev->path                = "\\?\HID#VID_1532&PID_00A3&MI_00#7&370ad372&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}"

# Preparsed Data struct:
pp_data->MagicKey                             = 0x48696450204B4452
pp_data->Usage                                = 0x0002
pp_data->UsagePage                            = 0x0001
pp_data->Reserved                             = 0x00000000
# Input caps_info struct:
pp_data->caps_info[0]->FirstCap           = 0
pp_data->caps_info[0]->LastCap            = 5
pp_data->caps_info[0]->NumberOfCaps       = 5
pp_data->caps_info[0]->ReportByteLength   = 9
# Output caps_info struct:
pp_data->caps_info[1]->FirstCap           = 5
pp_data->caps_info[1]->LastCap            = 5
pp_data->caps_info[1]->NumberOfCaps       = 0
pp_data->caps_info[1]->ReportByteLength   = 0
# Feature caps_info struct:
pp_data->caps_info[2]->FirstCap           = 5
pp_data->caps_info[2]->LastCap            = 5
pp_data->caps_info[2]->NumberOfCaps       = 1
pp_data->caps_info[2]->ReportByteLength   = 91
# LinkCollectionArray Offset & Size:
pp_data->FirstByteOfLinkCollectionArray       = 0x0270
pp_data->NumberLinkCollectionNodes            = 2
# Input hid_pp_cap struct:
pp_data->cap[0]->UsagePage                    = 0x0009
pp_data->cap[0]->ReportID                     = 0x00
pp_data->cap[0]->BitPosition                  = 0
pp_data->cap[0]->BitSize                      = 1
pp_data->cap[0]->ReportCount                  = 5
pp_data->cap[0]->BytePosition                 = 0x0001
pp_data->cap[0]->BitCount                     = 5
pp_data->cap[0]->BitField                     = 0x02
pp_data->cap[0]->NextBytePosition             = 0x0002
pp_data->cap[0]->LinkCollection               = 0x0001
pp_data->cap[0]->LinkUsagePage                = 0x0001
pp_data->cap[0]->LinkUsage                    = 0x0001
pp_data->cap[0]->IsMultipleItemsForArray      = 0
pp_data->cap[0]->IsButtonCap                  = 1
pp_data->cap[0]->IsPadding                    = 0
pp_data->cap[0]->IsAbsolute                   = 1
pp_data->cap[0]->IsRange                      = 1
pp_data->cap[0]->IsAlias                      = 0
pp_data->cap[0]->IsStringRange                = 0
pp_data->cap[0]->IsDesignatorRange            = 0
pp_data->cap[0]->Reserved1                    = 0x000000
pp_data->cap[0]->pp_cap->UnknownTokens[0].Token    = 0x00
pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000
pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000
pp_data->cap[0]->pp_cap->UnknownTokens[1].Token    = 0x00
pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000
pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000
pp_data->cap[0]->pp_cap->UnknownTokens[2].Token    = 0x00
pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000
pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000
pp_data->cap[0]->pp_cap->UnknownTokens[3].Token    = 0x00
pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000
pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000
pp_data->cap[0]->Range.UsageMin                     = 0x0001
pp_data->cap[0]->Range.UsageMax                     = 0x0005
pp_data->cap[0]->Range.StringMin                    = 0
pp_data->cap[0]->Range.StringMax                    = 0
pp_data->cap[0]->Range.DesignatorMin                = 0
pp_data->cap[0]->Range.DesignatorMax                = 0
pp_data->cap[0]->Range.DataIndexMin                 = 0
pp_data->cap[0]->Range.DataIndexMax                 = 4
pp_data->cap[0]->Button.LogicalMin                   = 0
pp_data->cap[0]->Button.LogicalMax                   = 0
pp_data->cap[0]->Units                    = 0
pp_data->cap[0]->UnitsExp                 = 0

pp_data->cap[1]->UsagePage                    = 0xFF00
pp_data->cap[1]->ReportID                     = 0x00
pp_data->cap[1]->BitPosition                  = 0
pp_data->cap[1]->BitSize                      = 8
pp_data->cap[1]->ReportCount                  = 2
pp_data->cap[1]->BytePosition                 = 0x0002
pp_data->cap[1]->BitCount                     = 16
pp_data->cap[1]->BitField                     = 0x02
pp_data->cap[1]->NextBytePosition             = 0x0004
pp_data->cap[1]->LinkCollection               = 0x0001
pp_data->cap[1]->LinkUsagePage                = 0x0001
pp_data->cap[1]->LinkUsage                    = 0x0001
pp_data->cap[1]->IsMultipleItemsForArray      = 0
pp_data->cap[1]->IsButtonCap                  = 0
pp_data->cap[1]->IsPadding                    = 0
pp_data->cap[1]->IsAbsolute                   = 1
pp_data->cap[1]->IsRange                      = 0
pp_data->cap[1]->IsAlias                      = 0
pp_data->cap[1]->IsStringRange                = 0
pp_data->cap[1]->IsDesignatorRange            = 0
pp_data->cap[1]->Reserved1                    = 0x000000
pp_data->cap[1]->pp_cap->UnknownTokens[0].Token    = 0x00
pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000
pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000
pp_data->cap[1]->pp_cap->UnknownTokens[1].Token    = 0x00
pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000
pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000
pp_data->cap[1]->pp_cap->UnknownTokens[2].Token    = 0x00
pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000
pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000
pp_data->cap[1]->pp_cap->UnknownTokens[3].Token    = 0x00
pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000
pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000
pp_data->cap[1]->NotRange.Usage                        = 0x0040
pp_data->cap[1]->NotRange.Reserved1                    = 0x0040
pp_data->cap[1]->NotRange.StringIndex                  = 0
pp_data->cap[1]->NotRange.Reserved2                    = 0
pp_data->cap[1]->NotRange.DesignatorIndex              = 0
pp_data->cap[1]->NotRange.Reserved3                    = 0
pp_data->cap[1]->NotRange.DataIndex                    = 5
pp_data->cap[1]->NotRange.Reserved4                    = 5
pp_data->cap[1]->NotButton.HasNull                   = 0
pp_data->cap[1]->NotButton.Reserved4                 = 0x000000
pp_data->cap[1]->NotButton.LogicalMin                = -127
pp_data->cap[1]->NotButton.LogicalMax                = 127
pp_data->cap[1]->NotButton.PhysicalMin               = 0
pp_data->cap[1]->NotButton.PhysicalMax               = 0
pp_data->cap[1]->Units                    = 0
pp_data->cap[1]->UnitsExp                 = 0

pp_data->cap[2]->UsagePage                    = 0x0001
pp_data->cap[2]->ReportID                     = 0x00
pp_data->cap[2]->BitPosition                  = 0
pp_data->cap[2]->BitSize                      = 8
pp_data->cap[2]->ReportCount                  = 1
pp_data->cap[2]->BytePosition                 = 0x0004
pp_data->cap[2]->BitCount                     = 8
pp_data->cap[2]->BitField                     = 0x06
pp_data->cap[2]->NextBytePosition             = 0x0005
pp_data->cap[2]->LinkCollection               = 0x0001
pp_data->cap[2]->LinkUsagePage                = 0x0001
pp_data->cap[2]->LinkUsage                    = 0x0001
pp_data->cap[2]->IsMultipleItemsForArray      = 0
pp_data->cap[2]->IsButtonCap                  = 0
pp_data->cap[2]->IsPadding                    = 0
pp_data->cap[2]->IsAbsolute                   = 0
pp_data->cap[2]->IsRange                      = 0
pp_data->cap[2]->IsAlias                      = 0
pp_data->cap[2]->IsStringRange                = 0
pp_data->cap[2]->IsDesignatorRange            = 0
pp_data->cap[2]->Reserved1                    = 0x000000
pp_data->cap[2]->pp_cap->UnknownTokens[0].Token    = 0x00
pp_data->cap[2]->pp_cap->UnknownTokens[0].Reserved = 0x000000
pp_data->cap[2]->pp_cap->UnknownTokens[0].BitField = 0x00000000
pp_data->cap[2]->pp_cap->UnknownTokens[1].Token    = 0x00
pp_data->cap[2]->pp_cap->UnknownTokens[1].Reserved = 0x000000
pp_data->cap[2]->pp_cap->UnknownTokens[1].BitField = 0x00000000
pp_data->cap[2]->pp_cap->UnknownTokens[2].Token    = 0x00
pp_data->cap[2]->pp_cap->UnknownTokens[2].Reserved = 0x000000
pp_data->cap[2]->pp_cap->UnknownTokens[2].BitField = 0x00000000
pp_data->cap[2]->pp_cap->UnknownTokens[3].Token    = 0x00
pp_data->cap[2]->pp_cap->UnknownTokens[3].Reserved = 0x000000
pp_data->cap[2]->pp_cap->UnknownTokens[3].BitField = 0x00000000
pp_data->cap[2]->NotRange.Usage                        = 0x0038
pp_data->cap[2]->NotRange.Reserved1                    = 0x0038
pp_data->cap[2]->NotRange.StringIndex                  = 0
pp_data->cap[2]->NotRange.Reserved2                    = 0
pp_data->cap[2]->NotRange.DesignatorIndex              = 0
pp_data->cap[2]->NotRange.Reserved3                    = 0
pp_data->cap[2]->NotRange.DataIndex                    = 6
pp_data->cap[2]->NotRange.Reserved4                    = 6
pp_data->cap[2]->NotButton.HasNull                   = 0
pp_data->cap[2]->NotButton.Reserved4                 = 0x000000
pp_data->cap[2]->NotButton.LogicalMin                = -127
pp_data->cap[2]->NotButton.LogicalMax                = 127
pp_data->cap[2]->NotButton.PhysicalMin               = 0
pp_data->cap[2]->NotButton.PhysicalMax               = 0
pp_data->cap[2]->Units                    = 0
pp_data->cap[2]->UnitsExp                 = 0

pp_data->cap[3]->UsagePage                    = 0x0001
pp_data->cap[3]->ReportID                     = 0x00
pp_data->cap[3]->BitPosition                  = 0
pp_data->cap[3]->BitSize                      = 16
pp_data->cap[3]->ReportCount                  = 1
pp_data->cap[3]->BytePosition                 = 0x0007
pp_data->cap[3]->BitCount                     = 16
pp_data->cap[3]->BitField                     = 0x06
pp_data->cap[3]->NextBytePosition             = 0x0009
pp_data->cap[3]->LinkCollection               = 0x0001
pp_data->cap[3]->LinkUsagePage                = 0x0001
pp_data->cap[3]->LinkUsage                    = 0x0001
pp_data->cap[3]->IsMultipleItemsForArray      = 0
pp_data->cap[3]->IsButtonCap                  = 0
pp_data->cap[3]->IsPadding                    = 0
pp_data->cap[3]->IsAbsolute                   = 0
pp_data->cap[3]->IsRange                      = 0
pp_data->cap[3]->IsAlias                      = 0
pp_data->cap[3]->IsStringRange                = 0
pp_data->cap[3]->IsDesignatorRange            = 0
pp_data->cap[3]->Reserved1                    = 0x000000
pp_data->cap[3]->pp_cap->UnknownTokens[0].Token    = 0x00
pp_data->cap[3]->pp_cap->UnknownTokens[0].Reserved = 0x000000
pp_data->cap[3]->pp_cap->UnknownTokens[0].BitField = 0x00000000
pp_data->cap[3]->pp_cap->UnknownTokens[1].Token    = 0x00
pp_data->cap[3]->pp_cap->UnknownTokens[1].Reserved = 0x000000
pp_data->cap[3]->pp_cap->UnknownTokens[1].BitField = 0x00000000
pp_data->cap[3]->pp_cap->UnknownTokens[2].Token    = 0x00
pp_data->cap[3]->pp_cap->UnknownTokens[2].Reserved = 0x000000
pp_data->cap[3]->pp_cap->UnknownTokens[2].BitField = 0x00000000
pp_data->cap[3]->pp_cap->UnknownTokens[3].Token    = 0x00
pp_data->cap[3]->pp_cap->UnknownTokens[3].Reserved = 0x000000
pp_data->cap[3]->pp_cap->UnknownTokens[3].BitField = 0x00000000
pp_data->cap[3]->NotRange.Usage                        = 0x0031
pp_data->cap[3]->NotRange.Reserved1                    = 0x0031
pp_data->cap[3]->NotRange.StringIndex                  = 0
pp_data->cap[3]->NotRange.Reserved2                    = 0
pp_data->cap[3]->NotRange.DesignatorIndex              = 0
pp_data->cap[3]->NotRange.Reserved3                    = 0
pp_data->cap[3]->NotRange.DataIndex                    = 7
pp_data->cap[3]->NotRange.Reserved4                    = 7
pp_data->cap[3]->NotButton.HasNull                   = 0
pp_data->cap[3]->NotButton.Reserved4                 = 0x000000
pp_data->cap[3]->NotButton.LogicalMin                = -32768
pp_data->cap[3]->NotButton.LogicalMax                = 32767
pp_data->cap[3]->NotButton.PhysicalMin               = 0
pp_data->cap[3]->NotButton.PhysicalMax               = 0
pp_data->cap[3]->Units                    = 0
pp_data->cap[3]->UnitsExp                 = 0

pp_data->cap[4]->UsagePage                    = 0x0001
pp_data->cap[4]->ReportID                     = 0x00
pp_data->cap[4]->BitPosition                  = 0
pp_data->cap[4]->BitSize                      = 16
pp_data->cap[4]->ReportCount                  = 1
pp_data->cap[4]->BytePosition                 = 0x0005
pp_data->cap[4]->BitCount                     = 16
pp_data->cap[4]->BitField                     = 0x06
pp_data->cap[4]->NextBytePosition             = 0x0007
pp_data->cap[4]->LinkCollection               = 0x0001
pp_data->cap[4]->LinkUsagePage                = 0x0001
pp_data->cap[4]->LinkUsage                    = 0x0001
pp_data->cap[4]->IsMultipleItemsForArray      = 0
pp_data->cap[4]->IsButtonCap                  = 0
pp_data->cap[4]->IsPadding                    = 0
pp_data->cap[4]->IsAbsolute                   = 0
pp_data->cap[4]->IsRange                      = 0
pp_data->cap[4]->IsAlias                      = 0
pp_data->cap[4]->IsStringRange                = 0
pp_data->cap[4]->IsDesignatorRange            = 0
pp_data->cap[4]->Reserved1                    = 0x000000
pp_data->cap[4]->pp_cap->UnknownTokens[0].Token    = 0x00
pp_data->cap[4]->pp_cap->UnknownTokens[0].Reserved = 0x000000
pp_data->cap[4]->pp_cap->UnknownTokens[0].BitField = 0x00000000
pp_data->cap[4]->pp_cap->UnknownTokens[1].Token    = 0x00
pp_data->cap[4]->pp_cap->UnknownTokens[1].Reserved = 0x000000
pp_data->cap[4]->pp_cap->UnknownTokens[1].BitField = 0x00000000
pp_data->cap[4]->pp_cap->UnknownTokens[2].Token    = 0x00
pp_data->cap[4]->pp_cap->UnknownTokens[2].Reserved = 0x000000
pp_data->cap[4]->pp_cap->UnknownTokens[2].BitField = 0x00000000
pp_data->cap[4]->pp_cap->UnknownTokens[3].Token    = 0x00
pp_data->cap[4]->pp_cap->UnknownTokens[3].Reserved = 0x000000
pp_data->cap[4]->pp_cap->UnknownTokens[3].BitField = 0x00000000
pp_data->cap[4]->NotRange.Usage                        = 0x0030
pp_data->cap[4]->NotRange.Reserved1                    = 0x0030
pp_data->cap[4]->NotRange.StringIndex                  = 0
pp_data->cap[4]->NotRange.Reserved2                    = 0
pp_data->cap[4]->NotRange.DesignatorIndex              = 0
pp_data->cap[4]->NotRange.Reserved3                    = 0
pp_data->cap[4]->NotRange.DataIndex                    = 8
pp_data->cap[4]->NotRange.Reserved4                    = 8
pp_data->cap[4]->NotButton.HasNull                   = 0
pp_data->cap[4]->NotButton.Reserved4                 = 0x000000
pp_data->cap[4]->NotButton.LogicalMin                = -32768
pp_data->cap[4]->NotButton.LogicalMax                = 32767
pp_data->cap[4]->NotButton.PhysicalMin               = 0
pp_data->cap[4]->NotButton.PhysicalMax               = 0
pp_data->cap[4]->Units                    = 0
pp_data->cap[4]->UnitsExp                 = 0

# Output hid_pp_cap struct:
# Feature hid_pp_cap struct:
# Link Collections:
pp_data->LinkCollectionArray[0]->LinkUsage          = 0x0002
pp_data->LinkCollectionArray[0]->LinkUsagePage      = 0x0001
pp_data->LinkCollectionArray[0]->Parent             = 0
pp_data->LinkCollectionArray[0]->NumberOfChildren   = 1
pp_data->LinkCollectionArray[0]->NextSibling        = 0
pp_data->LinkCollectionArray[0]->FirstChild         = 1
pp_data->LinkCollectionArray[0]->CollectionType     = 1
pp_data->LinkCollectionArray[0]->IsAlias            = 0
pp_data->LinkCollectionArray[0]->Reserved           = 0x00000000
pp_data->LinkCollectionArray[1]->LinkUsage          = 0x0001
pp_data->LinkCollectionArray[1]->LinkUsagePage      = 0x0001
pp_data->LinkCollectionArray[1]->Parent             = 0
pp_data->LinkCollectionArray[1]->NumberOfChildren   = 0
pp_data->LinkCollectionArray[1]->NextSibling        = 0
pp_data->LinkCollectionArray[1]->FirstChild         = 0
pp_data->LinkCollectionArray[1]->CollectionType     = 0
pp_data->LinkCollectionArray[1]->IsAlias            = 0
pp_data->LinkCollectionArray[1]->Reserved           = 0x00000000
Full HIDP_PREPARSED_DATA
48 69 64 50 20 4B 44 52 02 00 01 00 00 00 00 00
00 00 05 00 05 00 09 00 05 00 00 00 05 00 00 00
05 00 01 00 05 00 5B 00 70 02 02 00 09 00 00 00
01 00 05 00 01 00 05 00 02 00 00 00 02 00 01 00
01 00 01 00 1C 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 01 00 05 00 00 00 00 00
00 00 00 00 00 00 04 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 FF 00 00 08 00 02 00 02 00 10 00
02 00 00 00 04 00 01 00 01 00 01 00 08 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
40 00 40 00 00 00 00 00 00 00 00 00 05 00 05 00
00 00 00 00 81 FF FF FF 7F 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00
08 00 01 00 04 00 08 00 06 00 00 00 05 00 01 00
01 00 01 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 38 00 38 00 00 00 00 00
00 00 00 00 06 00 06 00 00 00 00 00 81 FF FF FF
7F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 01 00 00 00 10 00 01 00 07 00 10 00
06 00 00 00 09 00 01 00 01 00 01 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
31 00 31 00 00 00 00 00 00 00 00 00 07 00 07 00
00 00 00 00 00 80 FF FF FF 7F 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00
10 00 01 00 05 00 10 00 06 00 00 00 07 00 01 00
01 00 01 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 30 00 30 00 00 00 00 00
00 00 00 00 08 00 08 00 00 00 00 00 00 80 FF FF
FF 7F 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
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 02 00 01 00
00 00 01 00 00 00 01 00 01 00 00 00 01 00 01 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 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 AB AB AB AB AB AB AB AB AB AB AB AB
AB AB AB AB 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 B6 A8 3A 4B F2 62 00 00
A0 D8 77 36 04 02 00 00 00 02 78 36 04 02 00 00
EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE
EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE
EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE
EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE
EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE
EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE
EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE
EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE
EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE
EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE
EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE
EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE
EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE
EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE
EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE
EE FE EE FE EE FE EE FE EE FE EE FE EE FE EE FE
00 00 00 00 00 00 00 00 B4 A8 39 4A D7 62 00 34
E0 C3 78 36 04 02 00 00 90 92 78 36 04 02 00 00
00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00
98 00 00 00 00 00 00 00 25 05 00 00 FD FD FD FD
0C 01 00 00 00 00 00 00 01 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 09 00 00 00 00 00 00 00
5B 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
C0 92 78 36 04 02 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
10 01 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
14 01 00 00 00 00 00 00 90 C5 77 36 04 02 00 00
E8 03 00 00 00 00 00 00 FD FD FD FD AB AB AB AB
AB AB AB AB AB AB AB AB AB AB AB AB EE FE EE FE
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
EE FE EE FE EE FE EE FE AF A8 39 51 D5 62 00 34
90 92 78 36 04 02 00 00 10 C6 77 36 04 02 00 00
00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00
48 00 00 00 00 00 00 00 27 05 00 00 FD FD FD FD
40 C6 77 36 04 02 00 00 32 15 A3 00 00 00 00 00
00 C7 77 36 04 02 00 00 00 02 00 00 00 00 00 00
70 C7 77 36 04 02 00 00 E0 C7 77 36 04 02 00 00
01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 FD FD FD FD AB AB AB AB
AB AB AB AB AB AB AB AB AB AB AB AB EE FE EE FE
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
EE FE EE FE EE FE EE FE A8 A8 39 56 CE 62 00 33
60 C5 77 36 04 02 00 00 D0 C6 77 36 04 02 00 00
00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00
59 00 00 00 00 00 00 00 28 05 00 00 FD FD FD FD
5C 5C 3F 5C 48 49 44 23 56 49 44 5F 31 35 33 32
26 50 49 44 5F 30 30 41 33 26 4D 49 5F 30 30 23
37 26 33 37 30 61 64 33 37 32 26 30 26 30 30 30
30 23 7B 34 64 31 65 35 35 62 32 2D 66 31 36 66
2D 31 31 63 66 2D 38 38 63 62 2D 30 30 31 31 31
31 30 30 30 30 33 30 7D 00 FD FD FD FD AB AB AB
AB AB AB AB AB AB AB AB AB AB AB AB AB FE EE FE
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
EE FE EE FE EE FE EE FE A3 A8 39 5D C9 62 00 3A
10 C6 77 36 04 02 00 00 40 C7 77 36 04 02 00 00
00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00
02 00 00 00 00 00 00 00 2B 05 00 00 FD FD FD FD
00 00 FD FD FD FD AB AB AB AB AB AB AB AB AB AB
AB AB AB AB AB AB EE FE EE FE EE FE EE FE EE FE
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
EE FE EE FE EE FE EE FE A3 A8 39 5D C2 62 00 30
D0 C6 77 36 04 02 00 00 B0 C7 77 36 04 02 00 00
00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00
0C 00 00 00 00 00 00 00 2C 05 00 00 FD FD FD FD
52 00 61 00 7A 00 65 00 72 00 00 00 FD FD FD FD
AB AB AB AB AB AB AB AB AB AB AB AB AB AB AB AB
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
EE FE EE FE EE FE EE FE AC A8 39 52 C2 62 00 34
40 C7 77 36 04 02 00 00 30 C8 77 36 04 02 00 00
00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00
18 00 00 00 00 00 00 00 2D 05 00 00 FD FD FD FD
52 00 61 00 7A 00 65 00 72 00 20 00 43 00 6F 00
62 00 72 00 61 00 00 00 FD FD FD FD AB AB AB AB
AB AB AB AB AB AB AB AB AB AB AB AB EE FE EE FE
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
EE FE EE FE EE FE EE FE A3 A9 39 5C CD 62 00 3C
B0 C7 77 36 04 02 00 00 00 00 00 00 00 00 00 00
C8 C2 F5 E3 F9 7F 00 00 1B 00 00 00 02 00 00 00
00 10 00 00 00 00 00 00 32 05 00 00 FD FD FD FD
23 20 48 49 44 41 50 49 20 64 65 76 69 63 65 20
69 6E 66 6F 20 73 74 72 75 63 74 3A 0A 64 65 76
2D 3E 76 65 6E 64 6F 72 5F 69 64 20 20 20 20 20
20 20 20 20 20 20 3D 20 30 78 31 35 33 32 0A 64
65 76 2D 3E 70 72 6F 64 75 63 74 5F 69 64 20 20
20 20 20 20 20 20 20 20 3D 20 30 78 30 30 41 33
0A 64 65 76 2D 3E 6D 61 6E 75 66 61 63 74 75 72
65 72 5F 73 74 72 69 6E 67 20 3D 20 22 52 61 7A
65 72 22 0A 64 65 76 2D 3E 70 72 6F 64 75 63 74
5F 73 74 72 69 6E 67 20 20 20 20 20 20 3D 20 22
52 61 7A 65 72 20 43 6F 62 72 61 22 0A 64 65 76
2D 3E 72 65 6C 65 61 73 65 5F 6E 75 6D 62 65 72
20 20 20 20 20 20 3D 20 30 78 30 32 30 30 0A 64
65 76 2D 3E 69 6E 74 65 72 66 61 63 65 5F 6E 75
6D 62 65 72 20 20 20 20 3D 20 30 0A 64 65 76 2D
3E 75 73 61 67 65 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 3D 20 30 78 30 30 30 32 0A 64 65
76 2D 3E 75 73 61 67 65 5F 70 61 67 65 20 20 20
20 20 20 20 20 20 20 3D 20 30 78 30 30 30 31 0A
64 65 76 2D 3E 70 61 74 68 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 3D 20 22 5C 5C 3F 5C
48 49 44 23 56 49 44 5F 31 35 33 32 26 50 49 44
5F 30 30 41 33 26 4D 49 5F 30 30 23 37 26 33 37
30 61 64 33 37 32 26 30 26 30 30 30 30 23 7B 34
64 31 65 35 35 62 32 2D 66 31 36 66 2D 31 31 63
66 2D 38 38 63 62 2D 30 30 31 31 31 31 30 30 30
30 33 30 7D 22 0A 0A 23 20 50 72 65 70 61 72 73
65 64 20 44 61 74 61 20 73 74 72 75 63 74 3A 0A
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

(Followed by all 0x00 until HID_API_MAX_REPORT_DESCRIPTOR_SIZE)

@Youw Youw added Windows Related to Windows backend Contributions Welcome Any external help is welcome labels Oct 18, 2024
@JoergAtGithub
Copy link
Contributor

This is a known limitation of the reconstructor: All bits in the feature report are const, and Windows removes any information about const caps during the pre-parsing step. The reconstructor determines these const padding bits from the bit position of the next non-const cap, but this does not work for additional const bytes at the end of the report.

But your example shows that in this particular case there is the possibility, to improve this. While we have no information about additional const bytes for a particular report, Windows tells us the needed buffer size for input, output and feature reports. This is the size of the largest report + one byte. In case of devices that don't use ReportIDs, we know that there can be only one report of each type. So we could determine the number of additional const bytes at the end of the report from hid_pp_caps_info->ReportByteLength.

@Youw
Copy link
Member

Youw commented Oct 29, 2024

@SuibianP would you be able to check if #707 brings any improvement for your case?

@SuibianP
Copy link
Author

@Youw Tried dumping from the device just now and hid_report_reconstructor_test adds the last const report correctly. Usage page and usage are gone for good as expected.

@JoergAtGithub Thanks for the implementation!

@Youw Youw closed this as completed in #707 Oct 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Contributions Welcome Any external help is welcome Windows Related to Windows backend
Projects
None yet
3 participants