hidapi_descriptor_reconstruct.c 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990
  1. /*******************************************************
  2. HIDAPI - Multi-Platform library for
  3. communication with HID devices.
  4. libusb/hidapi Team
  5. Copyright 2022, All Rights Reserved.
  6. At the discretion of the user of this library,
  7. this software may be licensed under the terms of the
  8. GNU General Public License v3, a BSD-Style license, or the
  9. original HIDAPI license as outlined in the LICENSE.txt,
  10. LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
  11. files located at the root of the source distribution.
  12. These files may also be found in the public source
  13. code repository located at:
  14. https://github.com/libusb/hidapi .
  15. ********************************************************/
  16. #include "hidapi_descriptor_reconstruct.h"
  17. /**
  18. * @brief References to report descriptor buffer.
  19. *
  20. */
  21. struct rd_buffer {
  22. unsigned char* buf; /* Pointer to the array which stores the reconstructed descriptor */
  23. size_t buf_size; /* Size of the buffer in bytes */
  24. size_t byte_idx; /* Index of the next report byte to write to buf array */
  25. };
  26. /**
  27. * @brief Function that appends a byte to encoded report descriptor buffer.
  28. *
  29. * @param[in] byte Single byte to append.
  30. * @param rpt_desc Pointer to report descriptor buffer struct.
  31. */
  32. static void rd_append_byte(unsigned char byte, struct rd_buffer* rpt_desc) {
  33. if (rpt_desc->byte_idx < rpt_desc->buf_size) {
  34. rpt_desc->buf[rpt_desc->byte_idx] = byte;
  35. rpt_desc->byte_idx++;
  36. }
  37. }
  38. /**
  39. * @brief Writes a short report descriptor item according USB HID spec 1.11 chapter 6.2.2.2.
  40. *
  41. * @param[in] rd_item Enumeration identifying type (Main, Global, Local) and function (e.g Usage or Report Count) of the item.
  42. * @param[in] data Data (Size depends on rd_item 0,1,2 or 4bytes).
  43. * @param rpt_desc Pointer to report descriptor buffer struct.
  44. *
  45. * @return Returns 0 if successful, -1 for error.
  46. */
  47. static int rd_write_short_item(rd_items rd_item, LONG64 data, struct rd_buffer* rpt_desc) {
  48. if (rd_item & 0x03) {
  49. // Invalid input data, last to bits are reserved for data size
  50. return -1;
  51. }
  52. if (rd_item == rd_main_collection_end) {
  53. // Item without data (1Byte prefix only)
  54. unsigned char oneBytePrefix = (unsigned char) rd_item + 0x00;
  55. rd_append_byte(oneBytePrefix, rpt_desc);
  56. }
  57. else if ((rd_item == rd_global_logical_minimum) ||
  58. (rd_item == rd_global_logical_maximum) ||
  59. (rd_item == rd_global_physical_minimum) ||
  60. (rd_item == rd_global_physical_maximum)) {
  61. // Item with signed integer data
  62. if ((data >= -128) && (data <= 127)) {
  63. // 1Byte prefix + 1Byte data
  64. unsigned char oneBytePrefix = (unsigned char) rd_item + 0x01;
  65. char localData = (char)data;
  66. rd_append_byte(oneBytePrefix, rpt_desc);
  67. rd_append_byte(localData & 0xFF, rpt_desc);
  68. }
  69. else if ((data >= -32768) && (data <= 32767)) {
  70. // 1Byte prefix + 2Byte data
  71. unsigned char oneBytePrefix = (unsigned char) rd_item + 0x02;
  72. INT16 localData = (INT16)data;
  73. rd_append_byte(oneBytePrefix, rpt_desc);
  74. rd_append_byte(localData & 0xFF, rpt_desc);
  75. rd_append_byte(localData >> 8 & 0xFF, rpt_desc);
  76. }
  77. else if ((data >= -2147483648LL) && (data <= 2147483647)) {
  78. // 1Byte prefix + 4Byte data
  79. unsigned char oneBytePrefix = (unsigned char) rd_item + 0x03;
  80. INT32 localData = (INT32)data;
  81. rd_append_byte(oneBytePrefix, rpt_desc);
  82. rd_append_byte(localData & 0xFF, rpt_desc);
  83. rd_append_byte(localData >> 8 & 0xFF, rpt_desc);
  84. rd_append_byte(localData >> 16 & 0xFF, rpt_desc);
  85. rd_append_byte(localData >> 24 & 0xFF, rpt_desc);
  86. }
  87. else {
  88. // Data out of 32 bit signed integer range
  89. return -1;
  90. }
  91. }
  92. else {
  93. // Item with unsigned integer data
  94. if ((data >= 0) && (data <= 0xFF)) {
  95. // 1Byte prefix + 1Byte data
  96. unsigned char oneBytePrefix = (unsigned char) rd_item + 0x01;
  97. unsigned char localData = (unsigned char)data;
  98. rd_append_byte(oneBytePrefix, rpt_desc);
  99. rd_append_byte(localData & 0xFF, rpt_desc);
  100. }
  101. else if ((data >= 0) && (data <= 0xFFFF)) {
  102. // 1Byte prefix + 2Byte data
  103. unsigned char oneBytePrefix = (unsigned char) rd_item + 0x02;
  104. UINT16 localData = (UINT16)data;
  105. rd_append_byte(oneBytePrefix, rpt_desc);
  106. rd_append_byte(localData & 0xFF, rpt_desc);
  107. rd_append_byte(localData >> 8 & 0xFF, rpt_desc);
  108. }
  109. else if ((data >= 0) && (data <= 0xFFFFFFFF)) {
  110. // 1Byte prefix + 4Byte data
  111. unsigned char oneBytePrefix = (unsigned char) rd_item + 0x03;
  112. UINT32 localData = (UINT32)data;
  113. rd_append_byte(oneBytePrefix, rpt_desc);
  114. rd_append_byte(localData & 0xFF, rpt_desc);
  115. rd_append_byte(localData >> 8 & 0xFF, rpt_desc);
  116. rd_append_byte(localData >> 16 & 0xFF, rpt_desc);
  117. rd_append_byte(localData >> 24 & 0xFF, rpt_desc);
  118. }
  119. else {
  120. // Data out of 32 bit unsigned integer range
  121. return -1;
  122. }
  123. }
  124. return 0;
  125. }
  126. static struct rd_main_item_node * rd_append_main_item_node(int first_bit, int last_bit, rd_node_type type_of_node, int caps_index, int collection_index, rd_main_items main_item_type, unsigned char report_id, struct rd_main_item_node **list) {
  127. struct rd_main_item_node *new_list_node;
  128. // Determine last node in the list
  129. while (*list != NULL)
  130. {
  131. list = &(*list)->next;
  132. }
  133. new_list_node = malloc(sizeof(*new_list_node)); // Create new list entry
  134. new_list_node->FirstBit = first_bit;
  135. new_list_node->LastBit = last_bit;
  136. new_list_node->TypeOfNode = type_of_node;
  137. new_list_node->CapsIndex = caps_index;
  138. new_list_node->CollectionIndex = collection_index;
  139. new_list_node->MainItemType = main_item_type;
  140. new_list_node->ReportID = report_id;
  141. new_list_node->next = NULL; // NULL marks last node in the list
  142. *list = new_list_node;
  143. return new_list_node;
  144. }
  145. static struct rd_main_item_node * rd_insert_main_item_node(int first_bit, int last_bit, rd_node_type type_of_node, int caps_index, int collection_index, rd_main_items main_item_type, unsigned char report_id, struct rd_main_item_node **list) {
  146. // Insert item after the main item node referenced by list
  147. struct rd_main_item_node *next_item = (*list)->next;
  148. (*list)->next = NULL;
  149. rd_append_main_item_node(first_bit, last_bit, type_of_node, caps_index, collection_index, main_item_type, report_id, list);
  150. (*list)->next->next = next_item;
  151. return (*list)->next;
  152. }
  153. static struct rd_main_item_node * rd_search_main_item_list_for_bit_position(int search_bit, rd_main_items main_item_type, unsigned char report_id, struct rd_main_item_node **list) {
  154. // Determine first INPUT/OUTPUT/FEATURE main item, where the last bit position is equal or greater than the search bit position
  155. while (((*list)->next->MainItemType != rd_collection) &&
  156. ((*list)->next->MainItemType != rd_collection_end) &&
  157. !(((*list)->next->LastBit >= search_bit) &&
  158. ((*list)->next->ReportID == report_id) &&
  159. ((*list)->next->MainItemType == main_item_type))
  160. )
  161. {
  162. list = &(*list)->next;
  163. }
  164. return *list;
  165. }
  166. int hid_winapi_descriptor_reconstruct_pp_data(void *preparsed_data, unsigned char *buf, size_t buf_size)
  167. {
  168. hidp_preparsed_data *pp_data = (hidp_preparsed_data *) preparsed_data;
  169. // Check if MagicKey is correct, to ensure that pp_data points to an valid preparse data structure
  170. if (memcmp(pp_data->MagicKey, "HidP KDR", 8) != 0) {
  171. return -1;
  172. }
  173. struct rd_buffer rpt_desc;
  174. rpt_desc.buf = buf;
  175. rpt_desc.buf_size = buf_size;
  176. rpt_desc.byte_idx = 0;
  177. // Set pointer to the first node of link_collection_nodes
  178. phid_pp_link_collection_node link_collection_nodes = (phid_pp_link_collection_node)(((unsigned char*)&pp_data->caps[0]) + pp_data->FirstByteOfLinkCollectionArray);
  179. // ****************************************************************************************************************************
  180. // Create lookup tables for the bit range of each report per collection (position of first bit and last bit in each collection)
  181. // coll_bit_range[COLLECTION_INDEX][REPORT_ID][INPUT/OUTPUT/FEATURE]
  182. // ****************************************************************************************************************************
  183. // Allocate memory and initialize lookup table
  184. rd_bit_range ****coll_bit_range;
  185. coll_bit_range = malloc(pp_data->NumberLinkCollectionNodes * sizeof(*coll_bit_range));
  186. for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
  187. coll_bit_range[collection_node_idx] = malloc(256 * sizeof(*coll_bit_range[0])); // 256 possible report IDs (incl. 0x00)
  188. for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
  189. coll_bit_range[collection_node_idx][reportid_idx] = malloc(NUM_OF_HIDP_REPORT_TYPES * sizeof(*coll_bit_range[0][0]));
  190. for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
  191. coll_bit_range[collection_node_idx][reportid_idx][rt_idx] = malloc(sizeof(rd_bit_range));
  192. coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->FirstBit = -1;
  193. coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->LastBit = -1;
  194. }
  195. }
  196. }
  197. // Fill the lookup table where caps exist
  198. for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
  199. for (USHORT caps_idx = pp_data->caps_info[rt_idx].FirstCap; caps_idx < pp_data->caps_info[rt_idx].LastCap; caps_idx++) {
  200. int first_bit, last_bit;
  201. first_bit = (pp_data->caps[caps_idx].BytePosition - 1) * 8
  202. + pp_data->caps[caps_idx].BitPosition;
  203. last_bit = first_bit + pp_data->caps[caps_idx].ReportSize
  204. * pp_data->caps[caps_idx].ReportCount - 1;
  205. if (coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->FirstBit == -1 ||
  206. coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->FirstBit > first_bit) {
  207. coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->FirstBit = first_bit;
  208. }
  209. if (coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->LastBit < last_bit) {
  210. coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->LastBit = last_bit;
  211. }
  212. }
  213. }
  214. // *************************************************************************
  215. // -Determine hierarchy levels of each collections and store it in:
  216. // coll_levels[COLLECTION_INDEX]
  217. // -Determine number of direct childs of each collections and store it in:
  218. // coll_number_of_direct_childs[COLLECTION_INDEX]
  219. // *************************************************************************
  220. int max_coll_level = 0;
  221. int *coll_levels = malloc(pp_data->NumberLinkCollectionNodes * sizeof(coll_levels[0]));
  222. int *coll_number_of_direct_childs = malloc(pp_data->NumberLinkCollectionNodes * sizeof(coll_number_of_direct_childs[0]));
  223. for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
  224. coll_levels[collection_node_idx] = -1;
  225. coll_number_of_direct_childs[collection_node_idx] = 0;
  226. }
  227. {
  228. int actual_coll_level = 0;
  229. USHORT collection_node_idx = 0;
  230. while (actual_coll_level >= 0) {
  231. coll_levels[collection_node_idx] = actual_coll_level;
  232. if ((link_collection_nodes[collection_node_idx].NumberOfChildren > 0) &&
  233. (coll_levels[link_collection_nodes[collection_node_idx].FirstChild] == -1)) {
  234. actual_coll_level++;
  235. coll_levels[collection_node_idx] = actual_coll_level;
  236. if (max_coll_level < actual_coll_level) {
  237. max_coll_level = actual_coll_level;
  238. }
  239. coll_number_of_direct_childs[collection_node_idx]++;
  240. collection_node_idx = link_collection_nodes[collection_node_idx].FirstChild;
  241. }
  242. else if (link_collection_nodes[collection_node_idx].NextSibling != 0) {
  243. coll_number_of_direct_childs[link_collection_nodes[collection_node_idx].Parent]++;
  244. collection_node_idx = link_collection_nodes[collection_node_idx].NextSibling;
  245. }
  246. else {
  247. actual_coll_level--;
  248. if (actual_coll_level >= 0) {
  249. collection_node_idx = link_collection_nodes[collection_node_idx].Parent;
  250. }
  251. }
  252. }
  253. }
  254. // *********************************************************************************
  255. // Propagate the bit range of each report from the child collections to their parent
  256. // and store the merged result for the parent
  257. // *********************************************************************************
  258. for (int actual_coll_level = max_coll_level - 1; actual_coll_level >= 0; actual_coll_level--) {
  259. for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
  260. if (coll_levels[collection_node_idx] == actual_coll_level) {
  261. USHORT child_idx = link_collection_nodes[collection_node_idx].FirstChild;
  262. while (child_idx) {
  263. for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
  264. for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
  265. // Merge bit range from childs
  266. if ((coll_bit_range[child_idx][reportid_idx][rt_idx]->FirstBit != -1) &&
  267. (coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->FirstBit > coll_bit_range[child_idx][reportid_idx][rt_idx]->FirstBit)) {
  268. coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->FirstBit = coll_bit_range[child_idx][reportid_idx][rt_idx]->FirstBit;
  269. }
  270. if (coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->LastBit < coll_bit_range[child_idx][reportid_idx][rt_idx]->LastBit) {
  271. coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->LastBit = coll_bit_range[child_idx][reportid_idx][rt_idx]->LastBit;
  272. }
  273. child_idx = link_collection_nodes[child_idx].NextSibling;
  274. }
  275. }
  276. }
  277. }
  278. }
  279. }
  280. // **************************************************************************************************
  281. // Determine child collection order of the whole hierarchy, based on previously determined bit ranges
  282. // and store it this index coll_child_order[COLLECTION_INDEX][DIRECT_CHILD_INDEX]
  283. // **************************************************************************************************
  284. USHORT **coll_child_order;
  285. coll_child_order = malloc(pp_data->NumberLinkCollectionNodes * sizeof(*coll_child_order));
  286. {
  287. BOOLEAN *coll_parsed_flag;
  288. coll_parsed_flag = malloc(pp_data->NumberLinkCollectionNodes * sizeof(coll_parsed_flag[0]));
  289. for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
  290. coll_parsed_flag[collection_node_idx] = FALSE;
  291. }
  292. int actual_coll_level = 0;
  293. USHORT collection_node_idx = 0;
  294. while (actual_coll_level >= 0) {
  295. if ((coll_number_of_direct_childs[collection_node_idx] != 0) &&
  296. (coll_parsed_flag[link_collection_nodes[collection_node_idx].FirstChild] == FALSE)) {
  297. coll_parsed_flag[link_collection_nodes[collection_node_idx].FirstChild] = TRUE;
  298. coll_child_order[collection_node_idx] = malloc((coll_number_of_direct_childs[collection_node_idx]) * sizeof(*coll_child_order[0]));
  299. {
  300. // Create list of child collection indices
  301. // sorted reverse to the order returned to HidP_GetLinkCollectionNodeschild
  302. // which seems to match the original order, as long as no bit position needs to be considered
  303. USHORT child_idx = link_collection_nodes[collection_node_idx].FirstChild;
  304. int child_count = coll_number_of_direct_childs[collection_node_idx] - 1;
  305. coll_child_order[collection_node_idx][child_count] = child_idx;
  306. while (link_collection_nodes[child_idx].NextSibling) {
  307. child_count--;
  308. child_idx = link_collection_nodes[child_idx].NextSibling;
  309. coll_child_order[collection_node_idx][child_count] = child_idx;
  310. }
  311. }
  312. if (coll_number_of_direct_childs[collection_node_idx] > 1) {
  313. // Sort child collections indices by bit positions
  314. for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
  315. for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
  316. for (int child_idx = 1; child_idx < coll_number_of_direct_childs[collection_node_idx]; child_idx++) {
  317. // since the coll_bit_range array is not sorted, we need to reference the collection index in
  318. // our sorted coll_child_order array, and look up the corresponding bit ranges for comparing values to sort
  319. int prev_coll_idx = coll_child_order[collection_node_idx][child_idx - 1];
  320. int cur_coll_idx = coll_child_order[collection_node_idx][child_idx];
  321. if ((coll_bit_range[prev_coll_idx][reportid_idx][rt_idx]->FirstBit != -1) &&
  322. (coll_bit_range[cur_coll_idx][reportid_idx][rt_idx]->FirstBit != -1) &&
  323. (coll_bit_range[prev_coll_idx][reportid_idx][rt_idx]->FirstBit > coll_bit_range[cur_coll_idx][reportid_idx][rt_idx]->FirstBit)) {
  324. // Swap position indices of the two compared child collections
  325. USHORT idx_latch = coll_child_order[collection_node_idx][child_idx - 1];
  326. coll_child_order[collection_node_idx][child_idx - 1] = coll_child_order[collection_node_idx][child_idx];
  327. coll_child_order[collection_node_idx][child_idx] = idx_latch;
  328. }
  329. }
  330. }
  331. }
  332. }
  333. actual_coll_level++;
  334. collection_node_idx = link_collection_nodes[collection_node_idx].FirstChild;
  335. }
  336. else if (link_collection_nodes[collection_node_idx].NextSibling != 0) {
  337. collection_node_idx = link_collection_nodes[collection_node_idx].NextSibling;
  338. }
  339. else {
  340. actual_coll_level--;
  341. if (actual_coll_level >= 0) {
  342. collection_node_idx = link_collection_nodes[collection_node_idx].Parent;
  343. }
  344. }
  345. }
  346. free(coll_parsed_flag);
  347. }
  348. // ***************************************************************************************
  349. // Create sorted main_item_list containing all the Collection and CollectionEnd main items
  350. // ***************************************************************************************
  351. struct rd_main_item_node *main_item_list = NULL; // List root
  352. // Lookup table to find the Collection items in the list by index
  353. struct rd_main_item_node **coll_begin_lookup = malloc(pp_data->NumberLinkCollectionNodes * sizeof(*coll_begin_lookup));
  354. struct rd_main_item_node **coll_end_lookup = malloc(pp_data->NumberLinkCollectionNodes * sizeof(*coll_end_lookup));
  355. {
  356. int *coll_last_written_child = malloc(pp_data->NumberLinkCollectionNodes * sizeof(coll_last_written_child[0]));
  357. for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
  358. coll_last_written_child[collection_node_idx] = -1;
  359. }
  360. int actual_coll_level = 0;
  361. USHORT collection_node_idx = 0;
  362. struct rd_main_item_node *firstDelimiterNode = NULL;
  363. struct rd_main_item_node *delimiterCloseNode = NULL;
  364. coll_begin_lookup[0] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_collection, 0, &main_item_list);
  365. while (actual_coll_level >= 0) {
  366. if ((coll_number_of_direct_childs[collection_node_idx] != 0) &&
  367. (coll_last_written_child[collection_node_idx] == -1)) {
  368. // Collection has child collections, but none is written to the list yet
  369. coll_last_written_child[collection_node_idx] = coll_child_order[collection_node_idx][0];
  370. collection_node_idx = coll_child_order[collection_node_idx][0];
  371. // In a HID Report Descriptor, the first usage declared is the most preferred usage for the control.
  372. // While the order in the WIN32 capabiliy strutures is the opposite:
  373. // Here the preferred usage is the last aliased usage in the sequence.
  374. if (link_collection_nodes[collection_node_idx].IsAlias && (firstDelimiterNode == NULL)) {
  375. // Alliased Collection (First node in link_collection_nodes -> Last entry in report descriptor output)
  376. firstDelimiterNode = main_item_list;
  377. coll_begin_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_usage, 0, &main_item_list);
  378. coll_begin_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_close, 0, &main_item_list);
  379. delimiterCloseNode = main_item_list;
  380. }
  381. else {
  382. // Normal not aliased collection
  383. coll_begin_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_collection, 0, &main_item_list);
  384. actual_coll_level++;
  385. }
  386. }
  387. else if ((coll_number_of_direct_childs[collection_node_idx] > 1) &&
  388. (coll_last_written_child[collection_node_idx] != coll_child_order[collection_node_idx][coll_number_of_direct_childs[collection_node_idx] - 1])) {
  389. // Collection has child collections, and this is not the first child
  390. int nextChild = 1;
  391. while (coll_last_written_child[collection_node_idx] != coll_child_order[collection_node_idx][nextChild - 1]) {
  392. nextChild++;
  393. }
  394. coll_last_written_child[collection_node_idx] = coll_child_order[collection_node_idx][nextChild];
  395. collection_node_idx = coll_child_order[collection_node_idx][nextChild];
  396. if (link_collection_nodes[collection_node_idx].IsAlias && (firstDelimiterNode == NULL)) {
  397. // Alliased Collection (First node in link_collection_nodes -> Last entry in report descriptor output)
  398. firstDelimiterNode = main_item_list;
  399. coll_begin_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_usage, 0, &main_item_list);
  400. coll_begin_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_close, 0, &main_item_list);
  401. delimiterCloseNode = main_item_list;
  402. }
  403. else if (link_collection_nodes[collection_node_idx].IsAlias && (firstDelimiterNode != NULL)) {
  404. coll_begin_lookup[collection_node_idx] = rd_insert_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_usage, 0, &firstDelimiterNode);
  405. }
  406. else if (!link_collection_nodes[collection_node_idx].IsAlias && (firstDelimiterNode != NULL)) {
  407. coll_begin_lookup[collection_node_idx] = rd_insert_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_usage, 0, &firstDelimiterNode);
  408. coll_begin_lookup[collection_node_idx] = rd_insert_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_open, 0, &firstDelimiterNode);
  409. firstDelimiterNode = NULL;
  410. main_item_list = delimiterCloseNode;
  411. delimiterCloseNode = NULL; // Last entry of alias has .IsAlias == FALSE
  412. }
  413. if (!link_collection_nodes[collection_node_idx].IsAlias) {
  414. coll_begin_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_collection, 0, &main_item_list);
  415. actual_coll_level++;
  416. }
  417. }
  418. else {
  419. actual_coll_level--;
  420. coll_end_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_collection_end, 0, &main_item_list);
  421. collection_node_idx = link_collection_nodes[collection_node_idx].Parent;
  422. }
  423. }
  424. free(coll_last_written_child);
  425. }
  426. // ****************************************************************
  427. // Inserted Input/Output/Feature main items into the main_item_list
  428. // in order of reconstructed bit positions
  429. // ****************************************************************
  430. for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
  431. // Add all value caps to node list
  432. struct rd_main_item_node *firstDelimiterNode = NULL;
  433. struct rd_main_item_node *delimiterCloseNode = NULL;
  434. for (USHORT caps_idx = pp_data->caps_info[rt_idx].FirstCap; caps_idx < pp_data->caps_info[rt_idx].LastCap; caps_idx++) {
  435. struct rd_main_item_node *coll_begin = coll_begin_lookup[pp_data->caps[caps_idx].LinkCollection];
  436. int first_bit, last_bit;
  437. first_bit = (pp_data->caps[caps_idx].BytePosition - 1) * 8 +
  438. pp_data->caps[caps_idx].BitPosition;
  439. last_bit = first_bit + pp_data->caps[caps_idx].ReportSize *
  440. pp_data->caps[caps_idx].ReportCount - 1;
  441. for (int child_idx = 0; child_idx < coll_number_of_direct_childs[pp_data->caps[caps_idx].LinkCollection]; child_idx++) {
  442. // Determine in which section before/between/after child collection the item should be inserted
  443. if (first_bit < coll_bit_range[coll_child_order[pp_data->caps[caps_idx].LinkCollection][child_idx]][pp_data->caps[caps_idx].ReportID][rt_idx]->FirstBit)
  444. {
  445. // Note, that the default value for undefined coll_bit_range is -1, which can't be greater than the bit position
  446. break;
  447. }
  448. coll_begin = coll_end_lookup[coll_child_order[pp_data->caps[caps_idx].LinkCollection][child_idx]];
  449. }
  450. struct rd_main_item_node *list_node;
  451. list_node = rd_search_main_item_list_for_bit_position(first_bit, (rd_main_items) rt_idx, pp_data->caps[caps_idx].ReportID, &coll_begin);
  452. // In a HID Report Descriptor, the first usage declared is the most preferred usage for the control.
  453. // While the order in the WIN32 capabiliy strutures is the opposite:
  454. // Here the preferred usage is the last aliased usage in the sequence.
  455. if (pp_data->caps[caps_idx].IsAlias && (firstDelimiterNode == NULL)) {
  456. // Alliased Usage (First node in pp_data->caps -> Last entry in report descriptor output)
  457. firstDelimiterNode = list_node;
  458. rd_insert_main_item_node(first_bit, last_bit, rd_item_node_cap, caps_idx, pp_data->caps[caps_idx].LinkCollection, rd_delimiter_usage, pp_data->caps[caps_idx].ReportID, &list_node);
  459. rd_insert_main_item_node(first_bit, last_bit, rd_item_node_cap, caps_idx, pp_data->caps[caps_idx].LinkCollection, rd_delimiter_close, pp_data->caps[caps_idx].ReportID, &list_node);
  460. delimiterCloseNode = list_node;
  461. } else if (pp_data->caps[caps_idx].IsAlias && (firstDelimiterNode != NULL)) {
  462. rd_insert_main_item_node(first_bit, last_bit, rd_item_node_cap, caps_idx, pp_data->caps[caps_idx].LinkCollection, rd_delimiter_usage, pp_data->caps[caps_idx].ReportID, &list_node);
  463. }
  464. else if (!pp_data->caps[caps_idx].IsAlias && (firstDelimiterNode != NULL)) {
  465. // Alliased Collection (Last node in pp_data->caps -> First entry in report descriptor output)
  466. rd_insert_main_item_node(first_bit, last_bit, rd_item_node_cap, caps_idx, pp_data->caps[caps_idx].LinkCollection, rd_delimiter_usage, pp_data->caps[caps_idx].ReportID, &list_node);
  467. rd_insert_main_item_node(first_bit, last_bit, rd_item_node_cap, caps_idx, pp_data->caps[caps_idx].LinkCollection, rd_delimiter_open, pp_data->caps[caps_idx].ReportID, &list_node);
  468. firstDelimiterNode = NULL;
  469. list_node = delimiterCloseNode;
  470. delimiterCloseNode = NULL; // Last entry of alias has .IsAlias == FALSE
  471. }
  472. if (!pp_data->caps[caps_idx].IsAlias) {
  473. rd_insert_main_item_node(first_bit, last_bit, rd_item_node_cap, caps_idx, pp_data->caps[caps_idx].LinkCollection, (rd_main_items) rt_idx, pp_data->caps[caps_idx].ReportID, &list_node);
  474. }
  475. }
  476. }
  477. // ***********************************************************
  478. // Add const main items for padding to main_item_list
  479. // -To fill all bit gaps
  480. // -At each report end for 8bit padding
  481. // Note that information about the padding at the report end,
  482. // is not stored in the preparsed data, but in practice all
  483. // report descriptors seem to have it, as assumed here.
  484. // ***********************************************************
  485. {
  486. int *last_bit_position[NUM_OF_HIDP_REPORT_TYPES];
  487. struct rd_main_item_node **last_report_item_lookup[NUM_OF_HIDP_REPORT_TYPES];
  488. for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
  489. last_bit_position[rt_idx] = malloc(256 * sizeof(*last_bit_position[rt_idx]));
  490. last_report_item_lookup[rt_idx] = malloc(256 * sizeof(*last_report_item_lookup[rt_idx]));
  491. for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
  492. last_bit_position[rt_idx][reportid_idx] = -1;
  493. last_report_item_lookup[rt_idx][reportid_idx] = NULL;
  494. }
  495. }
  496. struct rd_main_item_node *list = main_item_list; // List root;
  497. while (list->next != NULL)
  498. {
  499. if ((list->MainItemType >= rd_input) &&
  500. (list->MainItemType <= rd_feature)) {
  501. // INPUT, OUTPUT or FEATURE
  502. if (list->FirstBit != -1) {
  503. if ((last_bit_position[list->MainItemType][list->ReportID] + 1 != list->FirstBit) &&
  504. (last_report_item_lookup[list->MainItemType][list->ReportID] != NULL) &&
  505. (last_report_item_lookup[list->MainItemType][list->ReportID]->FirstBit != list->FirstBit) // Happens in case of IsMultipleItemsForArray for multiple dedicated usages for a multi-button array
  506. ) {
  507. 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]);
  508. 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);
  509. }
  510. last_bit_position[list->MainItemType][list->ReportID] = list->LastBit;
  511. last_report_item_lookup[list->MainItemType][list->ReportID] = list;
  512. }
  513. }
  514. list = list->next;
  515. }
  516. // Add 8 bit padding at each report end
  517. for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
  518. for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
  519. if (last_bit_position[rt_idx][reportid_idx] != -1) {
  520. int padding = 8 - ((last_bit_position[rt_idx][reportid_idx] + 1) % 8);
  521. if (padding < 8) {
  522. // Insert padding item after item referenced in last_report_item_lookup
  523. 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]);
  524. }
  525. }
  526. }
  527. free(last_bit_position[rt_idx]);
  528. free(last_report_item_lookup[rt_idx]);
  529. }
  530. }
  531. // ***********************************
  532. // Encode the report descriptor output
  533. // ***********************************
  534. UCHAR last_report_id = 0;
  535. USAGE last_usage_page = 0;
  536. LONG last_physical_min = 0;// If both, Physical Minimum and Physical Maximum are 0, the logical limits should be taken as physical limits according USB HID spec 1.11 chapter 6.2.2.7
  537. LONG last_physical_max = 0;
  538. ULONG last_unit_exponent = 0; // If Unit Exponent is Undefined it should be considered as 0 according USB HID spec 1.11 chapter 6.2.2.7
  539. ULONG last_unit = 0; // If the first nibble is 7, or second nibble of Unit is 0, the unit is None according USB HID spec 1.11 chapter 6.2.2.7
  540. BOOLEAN inhibit_write_of_usage = FALSE; // Needed in case of delimited usage print, before the normal collection or cap
  541. int report_count = 0;
  542. while (main_item_list != NULL)
  543. {
  544. int rt_idx = main_item_list->MainItemType;
  545. int caps_idx = main_item_list->CapsIndex;
  546. if (main_item_list->MainItemType == rd_collection) {
  547. if (last_usage_page != link_collection_nodes[main_item_list->CollectionIndex].LinkUsagePage) {
  548. // Write "Usage Page" at the begin of a collection - except it refers the same table as wrote last
  549. rd_write_short_item(rd_global_usage_page, link_collection_nodes[main_item_list->CollectionIndex].LinkUsagePage, &rpt_desc);
  550. last_usage_page = link_collection_nodes[main_item_list->CollectionIndex].LinkUsagePage;
  551. }
  552. if (inhibit_write_of_usage) {
  553. // Inhibit only once after DELIMITER statement
  554. inhibit_write_of_usage = FALSE;
  555. }
  556. else {
  557. // Write "Usage" of collection
  558. rd_write_short_item(rd_local_usage, link_collection_nodes[main_item_list->CollectionIndex].LinkUsage, &rpt_desc);
  559. }
  560. // Write begin of "Collection"
  561. rd_write_short_item(rd_main_collection, link_collection_nodes[main_item_list->CollectionIndex].CollectionType, &rpt_desc);
  562. }
  563. else if (main_item_list->MainItemType == rd_collection_end) {
  564. // Write "End Collection"
  565. rd_write_short_item(rd_main_collection_end, 0, &rpt_desc);
  566. }
  567. else if (main_item_list->MainItemType == rd_delimiter_open) {
  568. if (main_item_list->CollectionIndex != -1) {
  569. // Write "Usage Page" inside of a collection delmiter section
  570. if (last_usage_page != link_collection_nodes[main_item_list->CollectionIndex].LinkUsagePage) {
  571. rd_write_short_item(rd_global_usage_page, link_collection_nodes[main_item_list->CollectionIndex].LinkUsagePage, &rpt_desc);
  572. last_usage_page = link_collection_nodes[main_item_list->CollectionIndex].LinkUsagePage;
  573. }
  574. }
  575. else if (main_item_list->CapsIndex != 0) {
  576. // Write "Usage Page" inside of a main item delmiter section
  577. if (pp_data->caps[caps_idx].UsagePage != last_usage_page) {
  578. rd_write_short_item(rd_global_usage_page, pp_data->caps[caps_idx].UsagePage, &rpt_desc);
  579. last_usage_page = pp_data->caps[caps_idx].UsagePage;
  580. }
  581. }
  582. // Write "Delimiter Open"
  583. rd_write_short_item(rd_local_delimiter, 1, &rpt_desc); // 1 = open set of aliased usages
  584. }
  585. else if (main_item_list->MainItemType == rd_delimiter_usage) {
  586. if (main_item_list->CollectionIndex != -1) {
  587. // Write aliased collection "Usage"
  588. rd_write_short_item(rd_local_usage, link_collection_nodes[main_item_list->CollectionIndex].LinkUsage, &rpt_desc);
  589. } if (main_item_list->CapsIndex != 0) {
  590. // Write aliased main item range from "Usage Minimum" to "Usage Maximum"
  591. if (pp_data->caps[caps_idx].IsRange) {
  592. rd_write_short_item(rd_local_usage_minimum, pp_data->caps[caps_idx].Range.UsageMin, &rpt_desc);
  593. rd_write_short_item(rd_local_usage_maximum, pp_data->caps[caps_idx].Range.UsageMax, &rpt_desc);
  594. }
  595. else {
  596. // Write single aliased main item "Usage"
  597. rd_write_short_item(rd_local_usage, pp_data->caps[caps_idx].NotRange.Usage, &rpt_desc);
  598. }
  599. }
  600. }
  601. else if (main_item_list->MainItemType == rd_delimiter_close) {
  602. // Write "Delimiter Close"
  603. rd_write_short_item(rd_local_delimiter, 0, &rpt_desc); // 0 = close set of aliased usages
  604. // Inhibit next usage write
  605. inhibit_write_of_usage = TRUE;
  606. }
  607. else if (main_item_list->TypeOfNode == rd_item_node_padding) {
  608. // Padding
  609. // The preparsed data doesn't contain any information about padding. Therefore all undefined gaps
  610. // in the reports are filled with the same style of constant padding.
  611. // Write "Report Size" with number of padding bits
  612. rd_write_short_item(rd_global_report_size, (main_item_list->LastBit - main_item_list->FirstBit + 1), &rpt_desc);
  613. // Write "Report Count" for padding always as 1
  614. rd_write_short_item(rd_global_report_count, 1, &rpt_desc);
  615. if (rt_idx == HidP_Input) {
  616. // 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
  617. rd_write_short_item(rd_main_input, 0x03, &rpt_desc); // Const / Abs
  618. }
  619. else if (rt_idx == HidP_Output) {
  620. // Write "Output" main item - We know it's Constant - We can only guess the other bits, but they don't matter in case of const
  621. rd_write_short_item(rd_main_output, 0x03, &rpt_desc); // Const / Abs
  622. }
  623. else if (rt_idx == HidP_Feature) {
  624. // Write "Feature" main item - We know it's Constant - We can only guess the other bits, but they don't matter in case of const
  625. rd_write_short_item(rd_main_feature, 0x03, &rpt_desc); // Const / Abs
  626. }
  627. report_count = 0;
  628. }
  629. else if (pp_data->caps[caps_idx].IsButtonCap) {
  630. // Button
  631. // (The preparsed data contain different data for 1 bit Button caps, than for parametric Value caps)
  632. if (last_report_id != pp_data->caps[caps_idx].ReportID) {
  633. // Write "Report ID" if changed
  634. rd_write_short_item(rd_global_report_id, pp_data->caps[caps_idx].ReportID, &rpt_desc);
  635. last_report_id = pp_data->caps[caps_idx].ReportID;
  636. }
  637. // Write "Usage Page" when changed
  638. if (pp_data->caps[caps_idx].UsagePage != last_usage_page) {
  639. rd_write_short_item(rd_global_usage_page, pp_data->caps[caps_idx].UsagePage, &rpt_desc);
  640. last_usage_page = pp_data->caps[caps_idx].UsagePage;
  641. }
  642. // Write only local report items for each cap, if ReportCount > 1
  643. if (pp_data->caps[caps_idx].IsRange) {
  644. report_count += (pp_data->caps[caps_idx].Range.DataIndexMax - pp_data->caps[caps_idx].Range.DataIndexMin);
  645. }
  646. if (inhibit_write_of_usage) {
  647. // Inhibit only once after Delimiter - Reset flag
  648. inhibit_write_of_usage = FALSE;
  649. }
  650. else {
  651. if (pp_data->caps[caps_idx].IsRange) {
  652. // Write range from "Usage Minimum" to "Usage Maximum"
  653. rd_write_short_item(rd_local_usage_minimum, pp_data->caps[caps_idx].Range.UsageMin, &rpt_desc);
  654. rd_write_short_item(rd_local_usage_maximum, pp_data->caps[caps_idx].Range.UsageMax, &rpt_desc);
  655. }
  656. else {
  657. // Write single "Usage"
  658. rd_write_short_item(rd_local_usage, pp_data->caps[caps_idx].NotRange.Usage, &rpt_desc);
  659. }
  660. }
  661. if (pp_data->caps[caps_idx].IsDesignatorRange) {
  662. // Write physical descriptor indices range from "Designator Minimum" to "Designator Maximum"
  663. rd_write_short_item(rd_local_designator_minimum, pp_data->caps[caps_idx].Range.DesignatorMin, &rpt_desc);
  664. rd_write_short_item(rd_local_designator_maximum, pp_data->caps[caps_idx].Range.DesignatorMax, &rpt_desc);
  665. }
  666. else if (pp_data->caps[caps_idx].NotRange.DesignatorIndex != 0) {
  667. // Designator set 0 is a special descriptor set (of the HID Physical Descriptor),
  668. // that specifies the number of additional descriptor sets.
  669. // Therefore Designator Index 0 can never be a useful reference for a control and we can inhibit it.
  670. // Write single "Designator Index"
  671. rd_write_short_item(rd_local_designator_index, pp_data->caps[caps_idx].NotRange.DesignatorIndex, &rpt_desc);
  672. }
  673. if (pp_data->caps[caps_idx].IsStringRange) {
  674. // Write range of indices of the USB string descriptor, from "String Minimum" to "String Maximum"
  675. rd_write_short_item(rd_local_string_minimum, pp_data->caps[caps_idx].Range.StringMin, &rpt_desc);
  676. rd_write_short_item(rd_local_string_maximum, pp_data->caps[caps_idx].Range.StringMax, &rpt_desc);
  677. }
  678. else if (pp_data->caps[caps_idx].NotRange.StringIndex != 0) {
  679. // String Index 0 is a special entry of the USB string descriptor, that contains a list of supported languages,
  680. // therefore Designator Index 0 can never be a useful reference for a control and we can inhibit it.
  681. // Write single "String Index"
  682. rd_write_short_item(rd_local_string, pp_data->caps[caps_idx].NotRange.StringIndex, &rpt_desc);
  683. }
  684. if ((main_item_list->next != NULL) &&
  685. ((int)main_item_list->next->MainItemType == rt_idx) &&
  686. (main_item_list->next->TypeOfNode == rd_item_node_cap) &&
  687. (pp_data->caps[main_item_list->next->CapsIndex].IsButtonCap) &&
  688. (!pp_data->caps[caps_idx].IsRange) && // This node in list is no array
  689. (!pp_data->caps[main_item_list->next->CapsIndex].IsRange) && // Next node in list is no array
  690. (pp_data->caps[main_item_list->next->CapsIndex].UsagePage == pp_data->caps[caps_idx].UsagePage) &&
  691. (pp_data->caps[main_item_list->next->CapsIndex].ReportID == pp_data->caps[caps_idx].ReportID) &&
  692. (pp_data->caps[main_item_list->next->CapsIndex].BitField == pp_data->caps[caps_idx].BitField)
  693. ) {
  694. if (main_item_list->next->FirstBit != main_item_list->FirstBit) {
  695. // In case of IsMultipleItemsForArray for multiple dedicated usages for a multi-button array, the report count should be incremented
  696. // Skip global items until any of them changes, than use ReportCount item to write the count of identical report fields
  697. report_count++;
  698. }
  699. }
  700. else {
  701. if ((pp_data->caps[caps_idx].Button.LogicalMin == 0) &&
  702. (pp_data->caps[caps_idx].Button.LogicalMax == 0)) {
  703. // While a HID report descriptor must always contain LogicalMinimum and LogicalMaximum,
  704. // the preparsed data contain both fields set to zero, for the case of simple buttons
  705. // Write "Logical Minimum" set to 0 and "Logical Maximum" set to 1
  706. rd_write_short_item(rd_global_logical_minimum, 0, &rpt_desc);
  707. rd_write_short_item(rd_global_logical_maximum, 1, &rpt_desc);
  708. }
  709. else {
  710. // Write logical range from "Logical Minimum" to "Logical Maximum"
  711. rd_write_short_item(rd_global_logical_minimum, pp_data->caps[caps_idx].Button.LogicalMin, &rpt_desc);
  712. rd_write_short_item(rd_global_logical_maximum, pp_data->caps[caps_idx].Button.LogicalMax, &rpt_desc);
  713. }
  714. // Write "Report Size"
  715. rd_write_short_item(rd_global_report_size, pp_data->caps[caps_idx].ReportSize, &rpt_desc);
  716. // Write "Report Count"
  717. if (!pp_data->caps[caps_idx].IsRange) {
  718. // Variable bit field with one bit per button
  719. // In case of multiple usages with the same items, only "Usage" is written per cap, and "Report Count" is incremented
  720. rd_write_short_item(rd_global_report_count, pp_data->caps[caps_idx].ReportCount + report_count, &rpt_desc);
  721. }
  722. else {
  723. // Button array of "Report Size" x "Report Count
  724. rd_write_short_item(rd_global_report_count, pp_data->caps[caps_idx].ReportCount, &rpt_desc);
  725. }
  726. // Buttons have only 1 bit and therefore no physical limits/units -> Set to undefined state
  727. if (last_physical_min != 0) {
  728. // Write "Physical Minimum", but only if changed
  729. last_physical_min = 0;
  730. rd_write_short_item(rd_global_physical_minimum, last_physical_min, &rpt_desc);
  731. }
  732. if (last_physical_max != 0) {
  733. // Write "Physical Maximum", but only if changed
  734. last_physical_max = 0;
  735. rd_write_short_item(rd_global_physical_maximum, last_physical_max, &rpt_desc);
  736. }
  737. if (last_unit_exponent != 0) {
  738. // Write "Unit Exponent", but only if changed
  739. last_unit_exponent = 0;
  740. rd_write_short_item(rd_global_unit_exponent, last_unit_exponent, &rpt_desc);
  741. }
  742. if (last_unit != 0) {
  743. // Write "Unit",but only if changed
  744. last_unit = 0;
  745. rd_write_short_item(rd_global_unit, last_unit, &rpt_desc);
  746. }
  747. // Write "Input" main item
  748. if (rt_idx == HidP_Input) {
  749. rd_write_short_item(rd_main_input, pp_data->caps[caps_idx].BitField, &rpt_desc);
  750. }
  751. // Write "Output" main item
  752. else if (rt_idx == HidP_Output) {
  753. rd_write_short_item(rd_main_output, pp_data->caps[caps_idx].BitField, &rpt_desc);
  754. }
  755. // Write "Feature" main item
  756. else if (rt_idx == HidP_Feature) {
  757. rd_write_short_item(rd_main_feature, pp_data->caps[caps_idx].BitField, &rpt_desc);
  758. }
  759. report_count = 0;
  760. }
  761. }
  762. else {
  763. if (last_report_id != pp_data->caps[caps_idx].ReportID) {
  764. // Write "Report ID" if changed
  765. rd_write_short_item(rd_global_report_id, pp_data->caps[caps_idx].ReportID, &rpt_desc);
  766. last_report_id = pp_data->caps[caps_idx].ReportID;
  767. }
  768. // Write "Usage Page" if changed
  769. if (pp_data->caps[caps_idx].UsagePage != last_usage_page) {
  770. rd_write_short_item(rd_global_usage_page, pp_data->caps[caps_idx].UsagePage, &rpt_desc);
  771. last_usage_page = pp_data->caps[caps_idx].UsagePage;
  772. }
  773. if (inhibit_write_of_usage) {
  774. // Inhibit only once after Delimiter - Reset flag
  775. inhibit_write_of_usage = FALSE;
  776. }
  777. else {
  778. if (pp_data->caps[caps_idx].IsRange) {
  779. // Write usage range from "Usage Minimum" to "Usage Maximum"
  780. rd_write_short_item(rd_local_usage_minimum, pp_data->caps[caps_idx].Range.UsageMin, &rpt_desc);
  781. rd_write_short_item(rd_local_usage_maximum, pp_data->caps[caps_idx].Range.UsageMax, &rpt_desc);
  782. }
  783. else {
  784. // Write single "Usage"
  785. rd_write_short_item(rd_local_usage, pp_data->caps[caps_idx].NotRange.Usage, &rpt_desc);
  786. }
  787. }
  788. if (pp_data->caps[caps_idx].IsDesignatorRange) {
  789. // Write physical descriptor indices range from "Designator Minimum" to "Designator Maximum"
  790. rd_write_short_item(rd_local_designator_minimum, pp_data->caps[caps_idx].Range.DesignatorMin, &rpt_desc);
  791. rd_write_short_item(rd_local_designator_maximum, pp_data->caps[caps_idx].Range.DesignatorMax, &rpt_desc);
  792. }
  793. else if (pp_data->caps[caps_idx].NotRange.DesignatorIndex != 0) {
  794. // Designator set 0 is a special descriptor set (of the HID Physical Descriptor),
  795. // that specifies the number of additional descriptor sets.
  796. // Therefore Designator Index 0 can never be a useful reference for a control and we can inhibit it.
  797. // Write single "Designator Index"
  798. rd_write_short_item(rd_local_designator_index, pp_data->caps[caps_idx].NotRange.DesignatorIndex, &rpt_desc);
  799. }
  800. if (pp_data->caps[caps_idx].IsStringRange) {
  801. // Write range of indices of the USB string descriptor, from "String Minimum" to "String Maximum"
  802. rd_write_short_item(rd_local_string_minimum, pp_data->caps[caps_idx].Range.StringMin, &rpt_desc);
  803. rd_write_short_item(rd_local_string_maximum, pp_data->caps[caps_idx].Range.StringMax, &rpt_desc);
  804. }
  805. else if (pp_data->caps[caps_idx].NotRange.StringIndex != 0) {
  806. // String Index 0 is a special entry of the USB string descriptor, that contains a list of supported languages,
  807. // therefore Designator Index 0 can never be a useful reference for a control and we can inhibit it.
  808. // Write single "String Index"
  809. rd_write_short_item(rd_local_string, pp_data->caps[caps_idx].NotRange.StringIndex, &rpt_desc);
  810. }
  811. if ((pp_data->caps[caps_idx].BitField & 0x02) != 0x02) {
  812. // In case of an value array overwrite "Report Count"
  813. pp_data->caps[caps_idx].ReportCount = pp_data->caps[caps_idx].Range.DataIndexMax - pp_data->caps[caps_idx].Range.DataIndexMin + 1;
  814. }
  815. // Print only local report items for each cap, if ReportCount > 1
  816. if ((main_item_list->next != NULL) &&
  817. ((int) main_item_list->next->MainItemType == rt_idx) &&
  818. (main_item_list->next->TypeOfNode == rd_item_node_cap) &&
  819. (!pp_data->caps[main_item_list->next->CapsIndex].IsButtonCap) &&
  820. (!pp_data->caps[caps_idx].IsRange) && // This node in list is no array
  821. (!pp_data->caps[main_item_list->next->CapsIndex].IsRange) && // Next node in list is no array
  822. (pp_data->caps[main_item_list->next->CapsIndex].UsagePage == pp_data->caps[caps_idx].UsagePage) &&
  823. (pp_data->caps[main_item_list->next->CapsIndex].NotButton.LogicalMin == pp_data->caps[caps_idx].NotButton.LogicalMin) &&
  824. (pp_data->caps[main_item_list->next->CapsIndex].NotButton.LogicalMax == pp_data->caps[caps_idx].NotButton.LogicalMax) &&
  825. (pp_data->caps[main_item_list->next->CapsIndex].NotButton.PhysicalMin == pp_data->caps[caps_idx].NotButton.PhysicalMin) &&
  826. (pp_data->caps[main_item_list->next->CapsIndex].NotButton.PhysicalMax == pp_data->caps[caps_idx].NotButton.PhysicalMax) &&
  827. (pp_data->caps[main_item_list->next->CapsIndex].UnitsExp == pp_data->caps[caps_idx].UnitsExp) &&
  828. (pp_data->caps[main_item_list->next->CapsIndex].Units == pp_data->caps[caps_idx].Units) &&
  829. (pp_data->caps[main_item_list->next->CapsIndex].ReportSize == pp_data->caps[caps_idx].ReportSize) &&
  830. (pp_data->caps[main_item_list->next->CapsIndex].ReportID == pp_data->caps[caps_idx].ReportID) &&
  831. (pp_data->caps[main_item_list->next->CapsIndex].BitField == pp_data->caps[caps_idx].BitField) &&
  832. (pp_data->caps[main_item_list->next->CapsIndex].ReportCount == 1) &&
  833. (pp_data->caps[caps_idx].ReportCount == 1)
  834. ) {
  835. // Skip global items until any of them changes, than use ReportCount item to write the count of identical report fields
  836. report_count++;
  837. }
  838. else {
  839. // Value
  840. // Write logical range from "Logical Minimum" to "Logical Maximum"
  841. rd_write_short_item(rd_global_logical_minimum, pp_data->caps[caps_idx].NotButton.LogicalMin, &rpt_desc);
  842. rd_write_short_item(rd_global_logical_maximum, pp_data->caps[caps_idx].NotButton.LogicalMax, &rpt_desc);
  843. if ((last_physical_min != pp_data->caps[caps_idx].NotButton.PhysicalMin) ||
  844. (last_physical_max != pp_data->caps[caps_idx].NotButton.PhysicalMax)) {
  845. // Write range from "Physical Minimum" to " Physical Maximum", but only if one of them changed
  846. rd_write_short_item(rd_global_physical_minimum, pp_data->caps[caps_idx].NotButton.PhysicalMin, &rpt_desc);
  847. last_physical_min = pp_data->caps[caps_idx].NotButton.PhysicalMin;
  848. rd_write_short_item(rd_global_physical_maximum, pp_data->caps[caps_idx].NotButton.PhysicalMax, &rpt_desc);
  849. last_physical_max = pp_data->caps[caps_idx].NotButton.PhysicalMax;
  850. }
  851. if (last_unit_exponent != pp_data->caps[caps_idx].UnitsExp) {
  852. // Write "Unit Exponent", but only if changed
  853. rd_write_short_item(rd_global_unit_exponent, pp_data->caps[caps_idx].UnitsExp, &rpt_desc);
  854. last_unit_exponent = pp_data->caps[caps_idx].UnitsExp;
  855. }
  856. if (last_unit != pp_data->caps[caps_idx].Units) {
  857. // Write physical "Unit", but only if changed
  858. rd_write_short_item(rd_global_unit, pp_data->caps[caps_idx].Units, &rpt_desc);
  859. last_unit = pp_data->caps[caps_idx].Units;
  860. }
  861. // Write "Report Size"
  862. rd_write_short_item(rd_global_report_size, pp_data->caps[caps_idx].ReportSize, &rpt_desc);
  863. // Write "Report Count"
  864. rd_write_short_item(rd_global_report_count, pp_data->caps[caps_idx].ReportCount + report_count, &rpt_desc);
  865. if (rt_idx == HidP_Input) {
  866. // Write "Input" main item
  867. rd_write_short_item(rd_main_input, pp_data->caps[caps_idx].BitField, &rpt_desc);
  868. }
  869. else if (rt_idx == HidP_Output) {
  870. // Write "Output" main item
  871. rd_write_short_item(rd_main_output, pp_data->caps[caps_idx].BitField, &rpt_desc);
  872. }
  873. else if (rt_idx == HidP_Feature) {
  874. // Write "Feature" main item
  875. rd_write_short_item(rd_main_feature, pp_data->caps[caps_idx].BitField, &rpt_desc);
  876. }
  877. report_count = 0;
  878. }
  879. }
  880. // Go to next item in main_item_list and free the memory of the actual item
  881. struct rd_main_item_node *main_item_list_prev = main_item_list;
  882. main_item_list = main_item_list->next;
  883. free(main_item_list_prev);
  884. }
  885. // Free multidimensionable array: coll_bit_range[COLLECTION_INDEX][REPORT_ID][INPUT/OUTPUT/FEATURE]
  886. // Free multidimensionable array: coll_child_order[COLLECTION_INDEX][DIRECT_CHILD_INDEX]
  887. for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
  888. for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
  889. for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
  890. free(coll_bit_range[collection_node_idx][reportid_idx][rt_idx]);
  891. }
  892. free(coll_bit_range[collection_node_idx][reportid_idx]);
  893. }
  894. free(coll_bit_range[collection_node_idx]);
  895. if (coll_number_of_direct_childs[collection_node_idx] != 0) free(coll_child_order[collection_node_idx]);
  896. }
  897. free(coll_bit_range);
  898. free(coll_child_order);
  899. // Free one dimensional arrays
  900. free(coll_begin_lookup);
  901. free(coll_end_lookup);
  902. free(coll_levels);
  903. free(coll_number_of_direct_childs);
  904. return (int) rpt_desc.byte_idx;
  905. }