@@ -81,6 +81,7 @@ struct hid_report *hid_register_report(struct hid_device *device,
8181 report_enum -> report_id_hash [id ] = report ;
8282
8383 list_add_tail (& report -> list , & report_enum -> report_list );
84+ INIT_LIST_HEAD (& report -> field_entry_list );
8485
8586 return report ;
8687}
@@ -101,7 +102,7 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
101102
102103 field = kzalloc ((sizeof (struct hid_field ) +
103104 usages * sizeof (struct hid_usage ) +
104- 2 * usages * sizeof (unsigned int )), GFP_KERNEL );
105+ 3 * usages * sizeof (unsigned int )), GFP_KERNEL );
105106 if (!field )
106107 return NULL ;
107108
@@ -110,6 +111,7 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
110111 field -> usage = (struct hid_usage * )(field + 1 );
111112 field -> value = (s32 * )(field -> usage + usages );
112113 field -> new_value = (s32 * )(field -> value + usages );
114+ field -> usages_priorities = (s32 * )(field -> new_value + usages );
113115 field -> report = report ;
114116
115117 return field ;
@@ -657,6 +659,8 @@ static void hid_free_report(struct hid_report *report)
657659{
658660 unsigned n ;
659661
662+ kfree (report -> field_entries );
663+
660664 for (n = 0 ; n < report -> maxfield ; n ++ )
661665 kfree (report -> field [n ]);
662666 kfree (report );
@@ -1667,6 +1671,103 @@ static void hid_process_report(struct hid_device *hid,
16671671 }
16681672}
16691673
1674+ /*
1675+ * Insert a given usage_index in a field in the list
1676+ * of processed usages in the report.
1677+ *
1678+ * The elements of lower priority score are processed
1679+ * first.
1680+ */
1681+ static void __hid_insert_field_entry (struct hid_device * hid ,
1682+ struct hid_report * report ,
1683+ struct hid_field_entry * entry ,
1684+ struct hid_field * field ,
1685+ unsigned int usage_index )
1686+ {
1687+ struct hid_field_entry * next ;
1688+
1689+ entry -> field = field ;
1690+ entry -> index = usage_index ;
1691+ entry -> priority = field -> usages_priorities [usage_index ];
1692+
1693+ /* insert the element at the correct position */
1694+ list_for_each_entry (next ,
1695+ & report -> field_entry_list ,
1696+ list ) {
1697+ /*
1698+ * the priority of our element is strictly higher
1699+ * than the next one, insert it before
1700+ */
1701+ if (entry -> priority > next -> priority ) {
1702+ list_add_tail (& entry -> list , & next -> list );
1703+ return ;
1704+ }
1705+ }
1706+
1707+ /* lowest priority score: insert at the end */
1708+ list_add_tail (& entry -> list , & report -> field_entry_list );
1709+ }
1710+
1711+ static void hid_report_process_ordering (struct hid_device * hid ,
1712+ struct hid_report * report )
1713+ {
1714+ struct hid_field * field ;
1715+ struct hid_field_entry * entries ;
1716+ unsigned int a , u , usages ;
1717+ unsigned int count = 0 ;
1718+
1719+ /* count the number of individual fields in the report */
1720+ for (a = 0 ; a < report -> maxfield ; a ++ ) {
1721+ field = report -> field [a ];
1722+
1723+ if (field -> flags & HID_MAIN_ITEM_VARIABLE )
1724+ count += field -> report_count ;
1725+ else
1726+ count ++ ;
1727+ }
1728+
1729+ /* allocate the memory to process the fields */
1730+ entries = kcalloc (count , sizeof (* entries ), GFP_KERNEL );
1731+ if (!entries )
1732+ return ;
1733+
1734+ report -> field_entries = entries ;
1735+
1736+ /*
1737+ * walk through all fields in the report and
1738+ * store them by priority order in report->field_entry_list
1739+ *
1740+ * - Var elements are individualized (field + usage_index)
1741+ * - Arrays are taken as one, we can not chose an order for them
1742+ */
1743+ usages = 0 ;
1744+ for (a = 0 ; a < report -> maxfield ; a ++ ) {
1745+ field = report -> field [a ];
1746+
1747+ if (field -> flags & HID_MAIN_ITEM_VARIABLE ) {
1748+ for (u = 0 ; u < field -> report_count ; u ++ ) {
1749+ __hid_insert_field_entry (hid , report ,
1750+ & entries [usages ],
1751+ field , u );
1752+ usages ++ ;
1753+ }
1754+ } else {
1755+ __hid_insert_field_entry (hid , report , & entries [usages ],
1756+ field , 0 );
1757+ usages ++ ;
1758+ }
1759+ }
1760+ }
1761+
1762+ static void hid_process_ordering (struct hid_device * hid )
1763+ {
1764+ struct hid_report * report ;
1765+ struct hid_report_enum * report_enum = & hid -> report_enum [HID_INPUT_REPORT ];
1766+
1767+ list_for_each_entry (report , & report_enum -> report_list , list )
1768+ hid_report_process_ordering (hid , report );
1769+ }
1770+
16701771/*
16711772 * Output the field into the report.
16721773 */
@@ -2050,6 +2151,8 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
20502151 return - ENODEV ;
20512152 }
20522153
2154+ hid_process_ordering (hdev );
2155+
20532156 if ((hdev -> claimed & HID_CLAIMED_INPUT ) &&
20542157 (connect_mask & HID_CONNECT_FF ) && hdev -> ff_init )
20552158 hdev -> ff_init (hdev );
0 commit comments