@@ -537,7 +537,10 @@ int hid_winapi_descriptor_reconstruct_pp_data(void *preparsed_data, unsigned cha
537537 }
538538 }
539539
540+ BOOLEAN devicehasReportIDs = FALSE;
540541 struct rd_main_item_node * list = main_item_list ; // List root;
542+ // Windows pp_data are per top-level collection, therefore top level coll end is unique
543+ struct rd_main_item_node * node_before_top_level_coll_end = NULL ;
541544
542545 while (list -> next != NULL )
543546 {
@@ -552,12 +555,20 @@ int hid_winapi_descriptor_reconstruct_pp_data(void *preparsed_data, unsigned cha
552555 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 ]);
553556 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 );
554557 }
558+ if (list -> ReportID != 0 ) {
559+ devicehasReportIDs = TRUE;
560+ }
555561 last_bit_position [list -> MainItemType ][list -> ReportID ] = list -> LastBit ;
556562 last_report_item_lookup [list -> MainItemType ][list -> ReportID ] = list ;
557563 }
558564 }
565+ if (list -> next -> MainItemType == rd_collection_end ) {
566+ // Store the node before the collection end - the last occurence is the end of the top level collection
567+ node_before_top_level_coll_end = list ;
568+ }
559569 list = list -> next ;
560570 }
571+
561572 // Add 8 bit padding at each report end
562573 for (HIDP_REPORT_TYPE rt_idx = 0 ; rt_idx < NUM_OF_HIDP_REPORT_TYPES ; rt_idx ++ ) {
563574 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
566577 if (padding < 8 ) {
567578 // Insert padding item after item referenced in last_report_item_lookup
568579 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 ]);
580+ if (last_report_item_lookup [rt_idx ][reportid_idx ] == node_before_top_level_coll_end ) {
581+ // If this padding item is at the end of the top level collection, update node_before_top_level_coll_end
582+ node_before_top_level_coll_end = last_report_item_lookup [rt_idx ][reportid_idx ]-> next ;
583+ }
584+ last_bit_position [rt_idx ][reportid_idx ] += padding ;
569585 }
570586 }
571587 }
572588 }
589+
590+ // Add full byte padding at the end of the report descriptor (only reconstructable, for devices without Report IDs)
591+ for (HIDP_REPORT_TYPE rt_idx = 0 ; rt_idx < NUM_OF_HIDP_REPORT_TYPES ; rt_idx ++ ) {
592+ if (!devicehasReportIDs && pp_data -> caps_info [rt_idx ].NumberOfCaps > 0 && pp_data -> caps_info [rt_idx ].ReportByteLength > 0 ) {
593+ // ReportID 0 means this device uses not Report IDs
594+ // => Maximum one report per type possible, so we can take the size from the buffer size for the report type
595+ const unsigned char reportId = 0 ;
596+ // ReportByteLength is the report length in bytes plus the one byte for the optional ReportID
597+ int padding = (pp_data -> caps_info [rt_idx ].ReportByteLength - 1 ) * 8 - (last_bit_position [rt_idx ][reportId ] + 1 );
598+
599+ if (padding > 0 ) {
600+ // Insert padding item after item referenced in last_report_item_lookup
601+ 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 );
602+ }
603+ }
604+ }
573605 }
574606
575607
@@ -652,13 +684,25 @@ int hid_winapi_descriptor_reconstruct_pp_data(void *preparsed_data, unsigned cha
652684 else if (main_item_list -> TypeOfNode == rd_item_node_padding ) {
653685 // Padding
654686 // The preparsed data doesn't contain any information about padding. Therefore all undefined gaps
655- // in the reports are filled with the same style of constant padding.
687+ // in the reports are filled with the same style of constant bit or byte padding.
688+
689+ if ((main_item_list -> LastBit - main_item_list -> FirstBit + 1 ) % 8 == 0 ) {
690+ // Padding in full bytes
656691
657- // Write "Report Size" with number of padding bits
658- rd_write_short_item (rd_global_report_size , ( main_item_list -> LastBit - main_item_list -> FirstBit + 1 ) , & rpt_desc );
692+ // Write "Report Size" for padding bytes is 8
693+ rd_write_short_item (rd_global_report_size , 8 , & rpt_desc );
659694
660- // Write "Report Count" for padding always as 1
661- rd_write_short_item (rd_global_report_count , 1 , & rpt_desc );
695+ // Write "Report Count" with number of padding bytes
696+ rd_write_short_item (rd_global_report_count , (main_item_list -> LastBit - main_item_list -> FirstBit + 1 ) / 8 , & rpt_desc );
697+ } else {
698+ // Padding in bits
699+
700+ // Write "Report Size" with number of padding bits
701+ rd_write_short_item (rd_global_report_size , (main_item_list -> LastBit - main_item_list -> FirstBit + 1 ), & rpt_desc );
702+
703+ // Write "Report Count" for padding bits is 1
704+ rd_write_short_item (rd_global_report_count , 1 , & rpt_desc );
705+ }
662706
663707 if (rt_idx == HidP_Input ) {
664708 // 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
0 commit comments