@@ -48,6 +48,16 @@ static const struct {
4848 __s32 y ;
4949} hid_hat_to_axis [] = {{ 0 , 0 }, { 0 ,-1 }, { 1 ,-1 }, { 1 , 0 }, { 1 , 1 }, { 0 , 1 }, {-1 , 1 }, {-1 , 0 }, {-1 ,-1 }};
5050
51+ struct usage_priority {
52+ __u32 usage ; /* the HID usage associated */
53+ bool global ; /* we assume all usages to be slotted,
54+ * unless global
55+ */
56+ unsigned int slot_overwrite ; /* for globals: allows to set the usage
57+ * before or after the slots
58+ */
59+ };
60+
5161/*
5262 * hid-input will convert this list into priorities:
5363 * the first element will have the highest priority
@@ -57,17 +67,30 @@ static const struct {
5767 * hid-input will then shift the priority by 8 bits to leave some space
5868 * in case drivers want to interleave other fields.
5969 *
70+ * To accommodate slotted devices, the slot priority is
71+ * defined in the next 8 bits (defined by 0xff - slot).
72+ *
6073 * If drivers want to add fields before those, hid-input will
6174 * leave out the first 8 bits of the priority value.
6275 *
6376 * This still leaves us 65535 individual priority values.
6477 */
65- static const __u32 hidinput_usages_priorities [] = {
66- HID_DG_ERASER , /* Eraser (eraser touching) must always come before tipswitch */
67- HID_DG_INVERT , /* Invert must always come before In Range */
68- HID_DG_TIPSWITCH , /* Is the tip of the tool touching? */
69- HID_DG_TIPPRESSURE , /* Tip Pressure might emulate tip switch */
70- HID_DG_INRANGE , /* In Range needs to come after the other tool states */
78+ static const struct usage_priority hidinput_usages_priorities [] = {
79+ { /* Eraser (eraser touching) must always come before tipswitch */
80+ .usage = HID_DG_ERASER ,
81+ },
82+ { /* Invert must always come before In Range */
83+ .usage = HID_DG_INVERT ,
84+ },
85+ { /* Is the tip of the tool touching? */
86+ .usage = HID_DG_TIPSWITCH ,
87+ },
88+ { /* Tip Pressure might emulate tip switch */
89+ .usage = HID_DG_TIPPRESSURE ,
90+ },
91+ { /* In Range needs to come after the other tool states */
92+ .usage = HID_DG_INRANGE ,
93+ },
7194};
7295
7396#define map_abs (c ) hid_map_usage(hidinput, usage, &bit, &max, EV_ABS, (c))
@@ -612,6 +635,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
612635{
613636 struct input_dev * input = hidinput -> input ;
614637 struct hid_device * device = input_get_drvdata (input );
638+ const struct usage_priority * usage_priority = NULL ;
615639 int max = 0 , code ;
616640 unsigned int i = 0 ;
617641 unsigned long * bit = NULL ;
@@ -633,13 +657,26 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
633657
634658 /* assign a priority based on the static list declared here */
635659 for (i = 0 ; i < ARRAY_SIZE (hidinput_usages_priorities ); i ++ ) {
636- if (usage -> hid == hidinput_usages_priorities [i ]) {
660+ if (usage -> hid == hidinput_usages_priorities [i ].usage ) {
661+ usage_priority = & hidinput_usages_priorities [i ];
662+
637663 field -> usages_priorities [usage_index ] =
638664 (ARRAY_SIZE (hidinput_usages_priorities ) - i ) << 8 ;
639665 break ;
640666 }
641667 }
642668
669+ /*
670+ * For slotted devices, we need to also add the slot index
671+ * in the priority.
672+ */
673+ if (usage_priority && usage_priority -> global )
674+ field -> usages_priorities [usage_index ] |=
675+ usage_priority -> slot_overwrite ;
676+ else
677+ field -> usages_priorities [usage_index ] |=
678+ (0xff - field -> slot_idx ) << 16 ;
679+
643680 if (device -> driver -> input_mapping ) {
644681 int ret = device -> driver -> input_mapping (device , hidinput , field ,
645682 usage , & bit , & max );
@@ -2068,7 +2105,57 @@ static struct hid_input *hidinput_match_application(struct hid_report *report)
20682105static inline void hidinput_configure_usages (struct hid_input * hidinput ,
20692106 struct hid_report * report )
20702107{
2071- int i , j ;
2108+ int i , j , k ;
2109+ int first_field_index = 0 ;
2110+ int slot_collection_index = -1 ;
2111+ int prev_collection_index = -1 ;
2112+ unsigned int slot_idx = 0 ;
2113+ struct hid_field * field ;
2114+
2115+ /*
2116+ * First tag all the fields that are part of a slot,
2117+ * a slot needs to have one Contact ID in the collection
2118+ */
2119+ for (i = 0 ; i < report -> maxfield ; i ++ ) {
2120+ field = report -> field [i ];
2121+
2122+ /* ignore fields without usage */
2123+ if (field -> maxusage < 1 )
2124+ continue ;
2125+
2126+ /*
2127+ * janitoring when collection_index changes
2128+ */
2129+ if (prev_collection_index != field -> usage -> collection_index ) {
2130+ prev_collection_index = field -> usage -> collection_index ;
2131+ first_field_index = i ;
2132+ }
2133+
2134+ /*
2135+ * if we already found a Contact ID in the collection,
2136+ * tag and continue to the next.
2137+ */
2138+ if (slot_collection_index == field -> usage -> collection_index ) {
2139+ field -> slot_idx = slot_idx ;
2140+ continue ;
2141+ }
2142+
2143+ /* check if the current field has Contact ID */
2144+ for (j = 0 ; j < field -> maxusage ; j ++ ) {
2145+ if (field -> usage [j ].hid == HID_DG_CONTACTID ) {
2146+ slot_collection_index = field -> usage -> collection_index ;
2147+ slot_idx ++ ;
2148+
2149+ /*
2150+ * mark all previous fields and this one in the
2151+ * current collection to be slotted.
2152+ */
2153+ for (k = first_field_index ; k <= i ; k ++ )
2154+ report -> field [k ]-> slot_idx = slot_idx ;
2155+ break ;
2156+ }
2157+ }
2158+ }
20722159
20732160 for (i = 0 ; i < report -> maxfield ; i ++ )
20742161 for (j = 0 ; j < report -> field [i ]-> maxusage ; j ++ )
0 commit comments