mirror of
https://github.com/RPCS3/hidapi.git
synced 2026-07-01 18:25:51 -04:00
Reconstruction logic for padding bytes at the end of Reports (only possible for devices without ReportID) (#707)
-Add reconstruction logic of const padding bytes at the end of a report for devices which don't use ReportIDs -Enhanced padding logic to distinguish between byte and bit padding. -Add a new test case for Razer Cobra mouse `1532_00A3_0002_0001` which has a completly con feature report of 90 bytes. -Modified expected report descriptor reference file `045E_02FF_0005_0001_expected.rpt_desc` to include additional padding bytes.
This commit is contained in:
@@ -537,7 +537,10 @@ int hid_winapi_descriptor_reconstruct_pp_data(void *preparsed_data, unsigned cha
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN devicehasReportIDs = FALSE;
|
||||
struct rd_main_item_node *list = main_item_list; // List root;
|
||||
// Windows pp_data are per top-level collection, therefore top level coll end is unique
|
||||
struct rd_main_item_node* node_before_top_level_coll_end = NULL;
|
||||
|
||||
while (list->next != NULL)
|
||||
{
|
||||
@@ -552,12 +555,20 @@ int hid_winapi_descriptor_reconstruct_pp_data(void *preparsed_data, unsigned cha
|
||||
struct rd_main_item_node *list_node = rd_search_main_item_list_for_bit_position(last_bit_position[list->MainItemType][list->ReportID], list->MainItemType, list->ReportID, &last_report_item_lookup[list->MainItemType][list->ReportID]);
|
||||
rd_insert_main_item_node(last_bit_position[list->MainItemType][list->ReportID] + 1, list->FirstBit - 1, rd_item_node_padding, -1, 0, list->MainItemType, list->ReportID, &list_node);
|
||||
}
|
||||
if (list->ReportID != 0) {
|
||||
devicehasReportIDs = TRUE;
|
||||
}
|
||||
last_bit_position[list->MainItemType][list->ReportID] = list->LastBit;
|
||||
last_report_item_lookup[list->MainItemType][list->ReportID] = list;
|
||||
}
|
||||
}
|
||||
if (list->next->MainItemType == rd_collection_end) {
|
||||
// Store the node before the collection end - the last occurence is the end of the top level collection
|
||||
node_before_top_level_coll_end = list;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
// Add 8 bit padding at each report end
|
||||
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
|
||||
for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
|
||||
@@ -566,10 +577,31 @@ int hid_winapi_descriptor_reconstruct_pp_data(void *preparsed_data, unsigned cha
|
||||
if (padding < 8) {
|
||||
// Insert padding item after item referenced in last_report_item_lookup
|
||||
rd_insert_main_item_node(last_bit_position[rt_idx][reportid_idx] + 1, last_bit_position[rt_idx][reportid_idx] + padding, rd_item_node_padding, -1, 0, (rd_main_items) rt_idx, (unsigned char) reportid_idx, &last_report_item_lookup[rt_idx][reportid_idx]);
|
||||
if (last_report_item_lookup[rt_idx][reportid_idx] == node_before_top_level_coll_end) {
|
||||
// If this padding item is at the end of the top level collection, update node_before_top_level_coll_end
|
||||
node_before_top_level_coll_end = last_report_item_lookup[rt_idx][reportid_idx]->next;
|
||||
}
|
||||
last_bit_position[rt_idx][reportid_idx] += padding;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add full byte padding at the end of the report descriptor (only reconstructable, for devices without Report IDs)
|
||||
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
|
||||
if (!devicehasReportIDs && pp_data->caps_info[rt_idx].NumberOfCaps > 0 && pp_data->caps_info[rt_idx].ReportByteLength > 0) {
|
||||
// ReportID 0 means this device uses not Report IDs
|
||||
// => Maximum one report per type possible, so we can take the size from the buffer size for the report type
|
||||
const unsigned char reportId = 0;
|
||||
// ReportByteLength is the report length in bytes plus the one byte for the optional ReportID
|
||||
int padding = (pp_data->caps_info[rt_idx].ReportByteLength - 1) * 8 - (last_bit_position[rt_idx][reportId] + 1);
|
||||
|
||||
if (padding > 0) {
|
||||
// Insert padding item after item referenced in last_report_item_lookup
|
||||
rd_insert_main_item_node(last_bit_position[rt_idx][reportId] + 1, last_bit_position[rt_idx][reportId] + padding, rd_item_node_padding, -1, 0, (rd_main_items)rt_idx, reportId, &node_before_top_level_coll_end);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -652,13 +684,25 @@ int hid_winapi_descriptor_reconstruct_pp_data(void *preparsed_data, unsigned cha
|
||||
else if (main_item_list->TypeOfNode == rd_item_node_padding) {
|
||||
// Padding
|
||||
// The preparsed data doesn't contain any information about padding. Therefore all undefined gaps
|
||||
// in the reports are filled with the same style of constant padding.
|
||||
// in the reports are filled with the same style of constant bit or byte padding.
|
||||
|
||||
// Write "Report Size" with number of padding bits
|
||||
rd_write_short_item(rd_global_report_size, (main_item_list->LastBit - main_item_list->FirstBit + 1), &rpt_desc);
|
||||
if ((main_item_list->LastBit - main_item_list->FirstBit + 1) % 8 == 0) {
|
||||
// Padding in full bytes
|
||||
|
||||
// Write "Report Count" for padding always as 1
|
||||
rd_write_short_item(rd_global_report_count, 1, &rpt_desc);
|
||||
// Write "Report Size" for padding bytes is 8
|
||||
rd_write_short_item(rd_global_report_size, 8, &rpt_desc);
|
||||
|
||||
// Write "Report Count" with number of padding bytes
|
||||
rd_write_short_item(rd_global_report_count, (main_item_list->LastBit - main_item_list->FirstBit + 1) / 8, &rpt_desc);
|
||||
} else {
|
||||
// Padding in bits
|
||||
|
||||
// Write "Report Size" with number of padding bits
|
||||
rd_write_short_item(rd_global_report_size, (main_item_list->LastBit - main_item_list->FirstBit + 1), &rpt_desc);
|
||||
|
||||
// Write "Report Count" for padding bits is 1
|
||||
rd_write_short_item(rd_global_report_count, 1, &rpt_desc);
|
||||
}
|
||||
|
||||
if (rt_idx == HidP_Input) {
|
||||
// Write "Input" main item - We know it's Constant - We can only guess the other bits, but they don't matter in case of const
|
||||
|
||||
@@ -40,6 +40,7 @@ set(HID_DESCRIPTOR_RECONSTRUCT_TEST_CASES
|
||||
047F_C056_0003_FFA0
|
||||
047F_C056_0005_000B
|
||||
045E_02FF_0005_0001
|
||||
1532_00A3_0002_0001
|
||||
)
|
||||
|
||||
set(CMAKE_VERSION_SUPPORTS_ENVIRONMENT_MODIFICATION "3.22")
|
||||
|
||||
@@ -9,4 +9,4 @@
|
||||
0x00, 0x81, 0x02, 0x05, 0x01, 0x09, 0x39, 0x15, 0x01, 0x25,
|
||||
0x08, 0x35, 0x00, 0x46, 0x3B, 0x10, 0x65, 0x0E, 0x75, 0x04,
|
||||
0x95, 0x01, 0x81, 0x42, 0x75, 0x04, 0x95, 0x01, 0x81, 0x03,
|
||||
0xC0,
|
||||
0x75, 0x08, 0x95, 0x02, 0x81, 0x03, 0xC0,
|
||||
@@ -0,0 +1,302 @@
|
||||
# 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
|
||||
@@ -0,0 +1,9 @@
|
||||
0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01, 0xA1, 0x00,
|
||||
0x05, 0x09, 0x19, 0x01, 0x29, 0x05, 0x15, 0x00, 0x25, 0x01,
|
||||
0x75, 0x01, 0x95, 0x05, 0x81, 0x02, 0x75, 0x03, 0x95, 0x01,
|
||||
0x81, 0x03, 0x06, 0x00, 0xFF, 0x09, 0x40, 0x15, 0x81, 0x25,
|
||||
0x7F, 0x75, 0x08, 0x95, 0x02, 0x81, 0x02, 0x05, 0x01, 0x09,
|
||||
0x38, 0x15, 0x81, 0x25, 0x7F, 0x75, 0x08, 0x95, 0x01, 0x81,
|
||||
0x06, 0x09, 0x30, 0x09, 0x31, 0x16, 0x00, 0x80, 0x26, 0xFF,
|
||||
0x7F, 0x75, 0x10, 0x95, 0x02, 0x81, 0x06, 0xC0, 0x75, 0x08,
|
||||
0x95, 0x5A, 0xB1, 0x03, 0xC0,
|
||||
@@ -0,0 +1,53 @@
|
||||
HID report descriptor (dumped on Linux with hid-decode)
|
||||
Source: https://github.com/libusb/hidapi/issues/703
|
||||
|
||||
# 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
|
||||
Reference in New Issue
Block a user