pp_data_dump.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. #if defined(__MINGW32__)
  2. // Needed for %hh
  3. #define __USE_MINGW_ANSI_STDIO 1
  4. #endif
  5. #include <hid.c>
  6. #include <../windows/hidapi_descriptor_reconstruct.h>
  7. #include <hidapi.h>
  8. void dump_hid_pp_cap(FILE* file, phid_pp_cap pp_cap, unsigned int cap_idx) {
  9. fprintf(file, "pp_data->cap[%u]->UsagePage = 0x%04hX\n", cap_idx, pp_cap->UsagePage);
  10. fprintf(file, "pp_data->cap[%u]->ReportID = 0x%02hhX\n", cap_idx, pp_cap->ReportID);
  11. fprintf(file, "pp_data->cap[%u]->BitPosition = %hhu\n", cap_idx, pp_cap->BitPosition);
  12. fprintf(file, "pp_data->cap[%u]->BitSize = %hu\n", cap_idx, pp_cap->ReportSize);
  13. fprintf(file, "pp_data->cap[%u]->ReportCount = %hu\n", cap_idx, pp_cap->ReportCount);
  14. fprintf(file, "pp_data->cap[%u]->BytePosition = 0x%04hX\n", cap_idx, pp_cap->BytePosition);
  15. fprintf(file, "pp_data->cap[%u]->BitCount = %hu\n", cap_idx, pp_cap->BitCount);
  16. fprintf(file, "pp_data->cap[%u]->BitField = 0x%02lX\n", cap_idx, pp_cap->BitField);
  17. fprintf(file, "pp_data->cap[%u]->NextBytePosition = 0x%04hX\n", cap_idx, pp_cap->NextBytePosition);
  18. fprintf(file, "pp_data->cap[%u]->LinkCollection = 0x%04hX\n", cap_idx, pp_cap->LinkCollection);
  19. fprintf(file, "pp_data->cap[%u]->LinkUsagePage = 0x%04hX\n", cap_idx, pp_cap->LinkUsagePage);
  20. fprintf(file, "pp_data->cap[%u]->LinkUsage = 0x%04hX\n", cap_idx, pp_cap->LinkUsage);
  21. // 8 Flags in one byte
  22. fprintf(file, "pp_data->cap[%u]->IsMultipleItemsForArray = %hhu\n", cap_idx, pp_cap->IsMultipleItemsForArray);
  23. fprintf(file, "pp_data->cap[%u]->IsButtonCap = %hhu\n", cap_idx, pp_cap->IsButtonCap);
  24. fprintf(file, "pp_data->cap[%u]->IsPadding = %hhu\n", cap_idx, pp_cap->IsPadding);
  25. fprintf(file, "pp_data->cap[%u]->IsAbsolute = %hhu\n", cap_idx, pp_cap->IsAbsolute);
  26. fprintf(file, "pp_data->cap[%u]->IsRange = %hhu\n", cap_idx, pp_cap->IsRange);
  27. fprintf(file, "pp_data->cap[%u]->IsAlias = %hhu\n", cap_idx, pp_cap->IsAlias);
  28. fprintf(file, "pp_data->cap[%u]->IsStringRange = %hhu\n", cap_idx, pp_cap->IsStringRange);
  29. fprintf(file, "pp_data->cap[%u]->IsDesignatorRange = %hhu\n", cap_idx, pp_cap->IsDesignatorRange);
  30. fprintf(file, "pp_data->cap[%u]->Reserved1 = 0x%02hhX%02hhX%02hhX\n", cap_idx, pp_cap->Reserved1[0], pp_cap->Reserved1[1], pp_cap->Reserved1[2]);
  31. for (int token_idx = 0; token_idx < 4; token_idx++) {
  32. fprintf(file, "pp_data->cap[%u]->pp_cap->UnknownTokens[%d].Token = 0x%02hhX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].Token);
  33. fprintf(file, "pp_data->cap[%u]->pp_cap->UnknownTokens[%d].Reserved = 0x%02hhX%02hhX%02hhX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].Reserved[0], pp_cap->UnknownTokens[token_idx].Reserved[1], pp_cap->UnknownTokens[token_idx].Reserved[2]);
  34. fprintf(file, "pp_data->cap[%u]->pp_cap->UnknownTokens[%d].BitField = 0x%08lX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].BitField);
  35. }
  36. if (pp_cap->IsRange) {
  37. fprintf(file, "pp_data->cap[%u]->Range.UsageMin = 0x%04hX\n", cap_idx, pp_cap->Range.UsageMin);
  38. fprintf(file, "pp_data->cap[%u]->Range.UsageMax = 0x%04hX\n", cap_idx, pp_cap->Range.UsageMax);
  39. fprintf(file, "pp_data->cap[%u]->Range.StringMin = %hu\n", cap_idx, pp_cap->Range.StringMin);
  40. fprintf(file, "pp_data->cap[%u]->Range.StringMax = %hu\n", cap_idx, pp_cap->Range.StringMax);
  41. fprintf(file, "pp_data->cap[%u]->Range.DesignatorMin = %hu\n", cap_idx, pp_cap->Range.DesignatorMin);
  42. fprintf(file, "pp_data->cap[%u]->Range.DesignatorMax = %hu\n", cap_idx, pp_cap->Range.DesignatorMax);
  43. fprintf(file, "pp_data->cap[%u]->Range.DataIndexMin = %hu\n", cap_idx, pp_cap->Range.DataIndexMin);
  44. fprintf(file, "pp_data->cap[%u]->Range.DataIndexMax = %hu\n", cap_idx, pp_cap->Range.DataIndexMax);
  45. }
  46. else {
  47. fprintf(file, "pp_data->cap[%u]->NotRange.Usage = 0x%04hX\n", cap_idx, pp_cap->NotRange.Usage);
  48. fprintf(file, "pp_data->cap[%u]->NotRange.Reserved1 = 0x%04hX\n", cap_idx, pp_cap->NotRange.Reserved1);
  49. fprintf(file, "pp_data->cap[%u]->NotRange.StringIndex = %hu\n", cap_idx, pp_cap->NotRange.StringIndex);
  50. fprintf(file, "pp_data->cap[%u]->NotRange.Reserved2 = %hu\n", cap_idx, pp_cap->NotRange.Reserved2);
  51. fprintf(file, "pp_data->cap[%u]->NotRange.DesignatorIndex = %hu\n", cap_idx, pp_cap->NotRange.DesignatorIndex);
  52. fprintf(file, "pp_data->cap[%u]->NotRange.Reserved3 = %hu\n", cap_idx, pp_cap->NotRange.Reserved3);
  53. fprintf(file, "pp_data->cap[%u]->NotRange.DataIndex = %hu\n", cap_idx, pp_cap->NotRange.DataIndex);
  54. fprintf(file, "pp_data->cap[%u]->NotRange.Reserved4 = %hu\n", cap_idx, pp_cap->NotRange.Reserved4);
  55. }
  56. if (pp_cap->IsButtonCap) {
  57. fprintf(file, "pp_data->cap[%u]->Button.LogicalMin = %ld\n", cap_idx, pp_cap->Button.LogicalMin);
  58. fprintf(file, "pp_data->cap[%u]->Button.LogicalMax = %ld\n", cap_idx, pp_cap->Button.LogicalMax);
  59. }
  60. else
  61. {
  62. fprintf(file, "pp_data->cap[%u]->NotButton.HasNull = %hhu\n", cap_idx, pp_cap->NotButton.HasNull);
  63. fprintf(file, "pp_data->cap[%u]->NotButton.Reserved4 = 0x%02hhX%02hhX%02hhX\n", cap_idx, pp_cap->NotButton.Reserved4[0], pp_cap->NotButton.Reserved4[1], pp_cap->NotButton.Reserved4[2]);
  64. fprintf(file, "pp_data->cap[%u]->NotButton.LogicalMin = %ld\n", cap_idx, pp_cap->NotButton.LogicalMin);
  65. fprintf(file, "pp_data->cap[%u]->NotButton.LogicalMax = %ld\n", cap_idx, pp_cap->NotButton.LogicalMax);
  66. fprintf(file, "pp_data->cap[%u]->NotButton.PhysicalMin = %ld\n", cap_idx, pp_cap->NotButton.PhysicalMin);
  67. fprintf(file, "pp_data->cap[%u]->NotButton.PhysicalMax = %ld\n", cap_idx, pp_cap->NotButton.PhysicalMax);
  68. };
  69. fprintf(file, "pp_data->cap[%u]->Units = %lu\n", cap_idx, pp_cap->Units);
  70. fprintf(file, "pp_data->cap[%u]->UnitsExp = %lu\n", cap_idx, pp_cap->UnitsExp);
  71. }
  72. void dump_hidp_link_collection_node(FILE* file, phid_pp_link_collection_node pcoll, unsigned int coll_idx) {
  73. fprintf(file, "pp_data->LinkCollectionArray[%u]->LinkUsage = 0x%04hX\n", coll_idx, pcoll->LinkUsage);
  74. fprintf(file, "pp_data->LinkCollectionArray[%u]->LinkUsagePage = 0x%04hX\n", coll_idx, pcoll->LinkUsagePage);
  75. fprintf(file, "pp_data->LinkCollectionArray[%u]->Parent = %hu\n", coll_idx, pcoll->Parent);
  76. fprintf(file, "pp_data->LinkCollectionArray[%u]->NumberOfChildren = %hu\n", coll_idx, pcoll->NumberOfChildren);
  77. fprintf(file, "pp_data->LinkCollectionArray[%u]->NextSibling = %hu\n", coll_idx, pcoll->NextSibling);
  78. fprintf(file, "pp_data->LinkCollectionArray[%u]->FirstChild = %hu\n", coll_idx, pcoll->FirstChild);
  79. // The compilers are not consistent on ULONG-bit-fields: They lose the unsigned or define them as int.
  80. // Thus just always cast them to unsigned int, which should be fine, as the biggest bit-field is 28 bit
  81. fprintf(file, "pp_data->LinkCollectionArray[%u]->CollectionType = %u\n", coll_idx, (unsigned int)(pcoll->CollectionType));
  82. fprintf(file, "pp_data->LinkCollectionArray[%u]->IsAlias = %u\n", coll_idx, (unsigned int)(pcoll->IsAlias));
  83. fprintf(file, "pp_data->LinkCollectionArray[%u]->Reserved = 0x%08X\n", coll_idx, (unsigned int)(pcoll->Reserved));
  84. }
  85. int dump_pp_data(FILE* file, hid_device* dev)
  86. {
  87. BOOL res;
  88. hidp_preparsed_data* pp_data = NULL;
  89. res = HidD_GetPreparsedData(dev->device_handle, (PHIDP_PREPARSED_DATA*) &pp_data);
  90. if (!res) {
  91. printf("ERROR: HidD_GetPreparsedData failed!");
  92. return -1;
  93. }
  94. else {
  95. fprintf(file, "pp_data->MagicKey = 0x%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX\n", pp_data->MagicKey[0], pp_data->MagicKey[1], pp_data->MagicKey[2], pp_data->MagicKey[3], pp_data->MagicKey[4], pp_data->MagicKey[5], pp_data->MagicKey[6], pp_data->MagicKey[7]);
  96. fprintf(file, "pp_data->Usage = 0x%04hX\n", pp_data->Usage);
  97. fprintf(file, "pp_data->UsagePage = 0x%04hX\n", pp_data->UsagePage);
  98. fprintf(file, "pp_data->Reserved = 0x%04hX%04hX\n", pp_data->Reserved[0], pp_data->Reserved[1]);
  99. fprintf(file, "# Input caps_info struct:\n");
  100. fprintf(file, "pp_data->caps_info[0]->FirstCap = %hu\n", pp_data->caps_info[0].FirstCap);
  101. fprintf(file, "pp_data->caps_info[0]->LastCap = %hu\n", pp_data->caps_info[0].LastCap);
  102. fprintf(file, "pp_data->caps_info[0]->NumberOfCaps = %hu\n", pp_data->caps_info[0].NumberOfCaps);
  103. fprintf(file, "pp_data->caps_info[0]->ReportByteLength = %hu\n", pp_data->caps_info[0].ReportByteLength);
  104. fprintf(file, "# Output caps_info struct:\n");
  105. fprintf(file, "pp_data->caps_info[1]->FirstCap = %hu\n", pp_data->caps_info[1].FirstCap);
  106. fprintf(file, "pp_data->caps_info[1]->LastCap = %hu\n", pp_data->caps_info[1].LastCap);
  107. fprintf(file, "pp_data->caps_info[1]->NumberOfCaps = %hu\n", pp_data->caps_info[1].NumberOfCaps);
  108. fprintf(file, "pp_data->caps_info[1]->ReportByteLength = %hu\n", pp_data->caps_info[1].ReportByteLength);
  109. fprintf(file, "# Feature caps_info struct:\n");
  110. fprintf(file, "pp_data->caps_info[2]->FirstCap = %hu\n", pp_data->caps_info[2].FirstCap);
  111. fprintf(file, "pp_data->caps_info[2]->LastCap = %hu\n", pp_data->caps_info[2].LastCap);
  112. fprintf(file, "pp_data->caps_info[2]->NumberOfCaps = %hu\n", pp_data->caps_info[2].NumberOfCaps);
  113. fprintf(file, "pp_data->caps_info[2]->ReportByteLength = %hu\n", pp_data->caps_info[2].ReportByteLength);
  114. fprintf(file, "# LinkCollectionArray Offset & Size:\n");
  115. fprintf(file, "pp_data->FirstByteOfLinkCollectionArray = 0x%04hX\n", pp_data->FirstByteOfLinkCollectionArray);
  116. fprintf(file, "pp_data->NumberLinkCollectionNodes = %hu\n", pp_data->NumberLinkCollectionNodes);
  117. phid_pp_cap pcap = (phid_pp_cap)(((unsigned char*)pp_data) + offsetof(hidp_preparsed_data, caps));
  118. fprintf(file, "# Input hid_pp_cap struct:\n");
  119. for (int caps_idx = pp_data->caps_info[0].FirstCap; caps_idx < pp_data->caps_info[0].LastCap; caps_idx++) {
  120. dump_hid_pp_cap(file, pcap + caps_idx, caps_idx);
  121. fprintf(file, "\n");
  122. }
  123. fprintf(file, "# Output hid_pp_cap struct:\n");
  124. for (int caps_idx = pp_data->caps_info[1].FirstCap; caps_idx < pp_data->caps_info[1].LastCap; caps_idx++) {
  125. dump_hid_pp_cap(file, pcap + caps_idx, caps_idx);
  126. fprintf(file, "\n");
  127. }
  128. fprintf(file, "# Feature hid_pp_cap struct:\n");
  129. for (int caps_idx = pp_data->caps_info[2].FirstCap; caps_idx < pp_data->caps_info[2].LastCap; caps_idx++) {
  130. dump_hid_pp_cap(file, pcap + caps_idx, caps_idx);
  131. fprintf(file, "\n");
  132. }
  133. phid_pp_link_collection_node pcoll = (phid_pp_link_collection_node)(((unsigned char*)pcap) + pp_data->FirstByteOfLinkCollectionArray);
  134. fprintf(file, "# Link Collections:\n");
  135. for (int coll_idx = 0; coll_idx < pp_data->NumberLinkCollectionNodes; coll_idx++) {
  136. dump_hidp_link_collection_node(file, pcoll + coll_idx, coll_idx);
  137. }
  138. HidD_FreePreparsedData((PHIDP_PREPARSED_DATA) pp_data);
  139. return 0;
  140. }
  141. }
  142. int main(int argc, char* argv[])
  143. {
  144. (void)argc;
  145. (void)argv;
  146. #define MAX_STR 255
  147. struct hid_device_info *devs, *cur_dev;
  148. printf("pp_data_dump tool. Compiled with hidapi version %s, runtime version %s.\n", HID_API_VERSION_STR, hid_version_str());
  149. if (hid_version()->major == HID_API_VERSION_MAJOR && hid_version()->minor == HID_API_VERSION_MINOR && hid_version()->patch == HID_API_VERSION_PATCH) {
  150. printf("Compile-time version matches runtime version of hidapi.\n\n");
  151. }
  152. else {
  153. printf("Compile-time version is different than runtime version of hidapi.\n]n");
  154. }
  155. if (hid_init())
  156. return -1;
  157. devs = hid_enumerate(0x0, 0x0);
  158. cur_dev = devs;
  159. while (cur_dev) {
  160. printf("Device Found\n type: %04hx %04hx\n path: %s\n serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
  161. printf("\n");
  162. printf(" Manufacturer: %ls\n", cur_dev->manufacturer_string);
  163. printf(" Product: %ls\n", cur_dev->product_string);
  164. printf(" Release: %hX\n", cur_dev->release_number);
  165. printf(" Interface: %d\n", cur_dev->interface_number);
  166. printf(" Usage (page): %02X (%02X)\n", cur_dev->usage, cur_dev->usage_page);
  167. hid_device *device = hid_open_path(cur_dev->path);
  168. if (device) {
  169. char filename[MAX_STR];
  170. FILE* file;
  171. sprintf_s(filename, MAX_STR, "%04X_%04X_%04X_%04X.pp_data", cur_dev->vendor_id, cur_dev->product_id, cur_dev->usage, cur_dev->usage_page);
  172. errno_t err = fopen_s(&file, filename, "w");
  173. if (err == 0) {
  174. fprintf(file, "# HIDAPI device info struct:\n");
  175. fprintf(file, "dev->vendor_id = 0x%04hX\n", cur_dev->vendor_id);
  176. fprintf(file, "dev->product_id = 0x%04hX\n", cur_dev->product_id);
  177. fprintf(file, "dev->manufacturer_string = \"%ls\"\n", cur_dev->manufacturer_string);
  178. fprintf(file, "dev->product_string = \"%ls\"\n", cur_dev->product_string);
  179. fprintf(file, "dev->release_number = 0x%04hX\n", cur_dev->release_number);
  180. fprintf(file, "dev->interface_number = %d\n", cur_dev->interface_number);
  181. fprintf(file, "dev->usage = 0x%04hX\n", cur_dev->usage);
  182. fprintf(file, "dev->usage_page = 0x%04hX\n", cur_dev->usage_page);
  183. fprintf(file, "dev->path = \"%s\"\n", cur_dev->path);
  184. fprintf(file, "\n# Preparsed Data struct:\n");
  185. int res = dump_pp_data(file, device);
  186. if (res == 0) {
  187. printf("Dumped Preparsed Data to %s\n", filename);
  188. }
  189. else {
  190. printf("ERROR: Dump Preparsed Data to %s failed!\n", filename);
  191. }
  192. fclose(file);
  193. }
  194. hid_close(device);
  195. }
  196. else {
  197. printf(" Device: not available.\n");
  198. }
  199. printf("\n");
  200. cur_dev = cur_dev->next;
  201. }
  202. hid_free_enumeration(devs);
  203. /* Free static HIDAPI objects. */
  204. hid_exit();
  205. //system("pause");
  206. return 0;
  207. }