@@ -41,6 +41,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
41
41
42
42
#define T100_TPAD_INTF 2
43
43
44
+ #define T100CHI_MOUSE_REPORT_ID 0x06
44
45
#define FEATURE_REPORT_ID 0x0d
45
46
#define INPUT_REPORT_ID 0x5d
46
47
#define FEATURE_KBD_REPORT_ID 0x5a
@@ -117,6 +118,15 @@ static const struct asus_touchpad_info asus_t100ta_tp = {
117
118
.max_contacts = 5 ,
118
119
};
119
120
121
+ static const struct asus_touchpad_info asus_t100chi_tp = {
122
+ .max_x = 2640 ,
123
+ .max_y = 1320 ,
124
+ .res_x = 31 , /* units/mm */
125
+ .res_y = 29 , /* units/mm */
126
+ .contact_size = 3 ,
127
+ .max_contacts = 4 ,
128
+ };
129
+
120
130
static void asus_report_contact_down (struct asus_drvdata * drvdat ,
121
131
int toolType , u8 * data )
122
132
{
@@ -126,6 +136,12 @@ static void asus_report_contact_down(struct asus_drvdata *drvdat,
126
136
x = (data [0 ] & CONTACT_X_MSB_MASK ) << 4 | data [1 ];
127
137
y = drvdat -> tp -> max_y - ((data [0 ] & CONTACT_Y_MSB_MASK ) << 8 | data [2 ]);
128
138
139
+ input_report_abs (input , ABS_MT_POSITION_X , x );
140
+ input_report_abs (input , ABS_MT_POSITION_Y , y );
141
+
142
+ if (drvdat -> tp -> contact_size < 5 )
143
+ return ;
144
+
129
145
if (toolType == MT_TOOL_PALM ) {
130
146
touch_major = MAX_TOUCH_MAJOR ;
131
147
pressure = MAX_PRESSURE ;
@@ -134,8 +150,6 @@ static void asus_report_contact_down(struct asus_drvdata *drvdat,
134
150
pressure = data [4 ] & CONTACT_PRESSURE_MASK ;
135
151
}
136
152
137
- input_report_abs (input , ABS_MT_POSITION_X , x );
138
- input_report_abs (input , ABS_MT_POSITION_Y , y );
139
153
input_report_abs (input , ABS_MT_TOUCH_MAJOR , touch_major );
140
154
input_report_abs (input , ABS_MT_PRESSURE , pressure );
141
155
}
@@ -147,6 +161,9 @@ static void asus_report_tool_width(struct asus_drvdata *drvdat)
147
161
struct input_mt_slot * oldest ;
148
162
int oldid , count , i ;
149
163
164
+ if (drvdat -> tp -> contact_size < 5 )
165
+ return ;
166
+
150
167
oldest = NULL ;
151
168
oldid = mt -> trkid ;
152
169
count = 0 ;
@@ -172,15 +189,17 @@ static void asus_report_tool_width(struct asus_drvdata *drvdat)
172
189
173
190
static int asus_report_input (struct asus_drvdata * drvdat , u8 * data , int size )
174
191
{
175
- int i ;
192
+ int i , toolType = MT_TOOL_FINGER ;
176
193
u8 * contactData = data + 2 ;
177
194
178
195
if (size != 3 + drvdat -> tp -> contact_size * drvdat -> tp -> max_contacts )
179
196
return 0 ;
180
197
181
198
for (i = 0 ; i < drvdat -> tp -> max_contacts ; i ++ ) {
182
199
bool down = !!(data [1 ] & BIT (i + 3 ));
183
- int toolType = contactData [3 ] & CONTACT_TOOL_TYPE_MASK ?
200
+
201
+ if (drvdat -> tp -> contact_size >= 5 )
202
+ toolType = contactData [3 ] & CONTACT_TOOL_TYPE_MASK ?
184
203
MT_TOOL_PALM : MT_TOOL_FINGER ;
185
204
186
205
input_mt_slot (drvdat -> input , i );
@@ -359,6 +378,11 @@ static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
359
378
struct input_dev * input = hi -> input ;
360
379
struct asus_drvdata * drvdata = hid_get_drvdata (hdev );
361
380
381
+ /* T100CHI uses MULTI_INPUT, bind the touchpad to the mouse hid_input */
382
+ if (drvdata -> quirks & QUIRK_T100CHI &&
383
+ hi -> report -> id != T100CHI_MOUSE_REPORT_ID )
384
+ return 0 ;
385
+
362
386
if (drvdata -> tp ) {
363
387
int ret ;
364
388
@@ -368,9 +392,15 @@ static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
368
392
drvdata -> tp -> max_y , 0 , 0 );
369
393
input_abs_set_res (input , ABS_MT_POSITION_X , drvdata -> tp -> res_x );
370
394
input_abs_set_res (input , ABS_MT_POSITION_Y , drvdata -> tp -> res_y );
371
- input_set_abs_params (input , ABS_TOOL_WIDTH , 0 , MAX_TOUCH_MAJOR , 0 , 0 );
372
- input_set_abs_params (input , ABS_MT_TOUCH_MAJOR , 0 , MAX_TOUCH_MAJOR , 0 , 0 );
373
- input_set_abs_params (input , ABS_MT_PRESSURE , 0 , MAX_PRESSURE , 0 , 0 );
395
+
396
+ if (drvdata -> tp -> contact_size >= 5 ) {
397
+ input_set_abs_params (input , ABS_TOOL_WIDTH , 0 ,
398
+ MAX_TOUCH_MAJOR , 0 , 0 );
399
+ input_set_abs_params (input , ABS_MT_TOUCH_MAJOR , 0 ,
400
+ MAX_TOUCH_MAJOR , 0 , 0 );
401
+ input_set_abs_params (input , ABS_MT_PRESSURE , 0 ,
402
+ MAX_PRESSURE , 0 , 0 );
403
+ }
374
404
375
405
__set_bit (BTN_LEFT , input -> keybit );
376
406
__set_bit (INPUT_PROP_BUTTONPAD , input -> propbit );
@@ -408,6 +438,26 @@ static int asus_input_mapping(struct hid_device *hdev,
408
438
return -1 ;
409
439
}
410
440
441
+ /*
442
+ * Ignore a bunch of bogus collections in the T100CHI descriptor.
443
+ * This avoids a bunch of non-functional hid_input devices getting
444
+ * created because of the T100CHI using HID_QUIRK_MULTI_INPUT.
445
+ */
446
+ if (drvdata -> quirks & QUIRK_T100CHI ) {
447
+ if (field -> application == (HID_UP_GENDESK | 0x0080 ) ||
448
+ usage -> hid == (HID_UP_GENDEVCTRLS | 0x0024 ) ||
449
+ usage -> hid == (HID_UP_GENDEVCTRLS | 0x0025 ) ||
450
+ usage -> hid == (HID_UP_GENDEVCTRLS | 0x0026 ))
451
+ return -1 ;
452
+ /*
453
+ * We use the hid_input for the mouse report for the touchpad,
454
+ * keep the left button, to avoid the core removing it.
455
+ */
456
+ if (field -> application == HID_GD_MOUSE &&
457
+ usage -> hid != (HID_UP_BUTTON | 1 ))
458
+ return -1 ;
459
+ }
460
+
411
461
/* ASUS-specific keyboard hotkeys */
412
462
if ((usage -> hid & HID_USAGE_PAGE ) == 0xff310000 ) {
413
463
set_bit (EV_REP , hi -> input -> evbit );
@@ -559,6 +609,16 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
559
609
}
560
610
}
561
611
612
+ if (drvdata -> quirks & QUIRK_T100CHI ) {
613
+ /*
614
+ * All functionality is on a single HID interface and for
615
+ * userspace the touchpad must be a separate input_dev.
616
+ */
617
+ hdev -> quirks |= HID_QUIRK_MULTI_INPUT |
618
+ HID_QUIRK_NO_EMPTY_INPUT ;
619
+ drvdata -> tp = & asus_t100chi_tp ;
620
+ }
621
+
562
622
if (drvdata -> quirks & QUIRK_NO_INIT_REPORTS )
563
623
hdev -> quirks |= HID_QUIRK_NO_INIT_REPORTS ;
564
624
0 commit comments