aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@enac.fr>2011-01-11 10:45:54 -0500
committerJiri Kosina <jkosina@suse.cz>2011-01-11 15:26:56 -0500
commit2d93666e70662cfcf1927e1a858685f5b38d5d65 (patch)
treead466fccbbce01ff2329a8b1429b96ed27f1a10f /drivers/hid
parentc64f6f934c7490faff76faf96217066a1b3570a0 (diff)
HID: hid-multitouch: minor fixes based on additional review
* amended Kconfig (PixCir and Hanvon are the same panel but with different name) * insert field name in mt_class and retrieving it in mt_probe * add 2 quirks: MT_QUIRK_VALID_IS_INRANGE, MT_QUIRK_VALID_IS_CONFIDENCE, in order to find the field "valid" * inlined slot_is_contactid and slot_is_contact_number * cosmetics changes (tabs and comments) * do not send unnecessary properties once the touch is up Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr> Acked-by: Henrik Rydberg <rydberg@euromail.se> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/Kconfig10
-rw-r--r--drivers/hid/hid-multitouch.c127
2 files changed, 78 insertions, 59 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 9bd21482e61..97c200b0f4b 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -292,10 +292,16 @@ config HID_MULTITOUCH
292 Generic support for HID multitouch panels. 292 Generic support for HID multitouch panels.
293 293
294 Say Y here if you have one of the following devices: 294 Say Y here if you have one of the following devices:
295 - PixCir touchscreen 295 - Cypress TrueTouch panels
296 - Cypress TrueTouch 296 - Hanvon dual touch panels
297 - Pixcir dual touch panels
297 - 'Sensing Win7-TwoFinger' panel by GeneralTouch 298 - 'Sensing Win7-TwoFinger' panel by GeneralTouch
298 299
300 If unsure, say N.
301
302 To compile this driver as a module, choose M here: the
303 module will be called hid-multitouch.
304
299config HID_NTRIG 305config HID_NTRIG
300 tristate "N-Trig touch screen" 306 tristate "N-Trig touch screen"
301 depends on USB_HID 307 depends on USB_HID
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 3442ed56e96..07d3183fdde 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -32,8 +32,10 @@ MODULE_LICENSE("GPL");
32/* quirks to control the device */ 32/* quirks to control the device */
33#define MT_QUIRK_NOT_SEEN_MEANS_UP (1 << 0) 33#define MT_QUIRK_NOT_SEEN_MEANS_UP (1 << 0)
34#define MT_QUIRK_SLOT_IS_CONTACTID (1 << 1) 34#define MT_QUIRK_SLOT_IS_CONTACTID (1 << 1)
35#define MT_QUIRK_CYPRESS (1 << 2) 35#define MT_QUIRK_CYPRESS (1 << 2)
36#define MT_QUIRK_SLOT_IS_CONTACTNUMBER (1 << 3) 36#define MT_QUIRK_SLOT_IS_CONTACTNUMBER (1 << 3)
37#define MT_QUIRK_VALID_IS_INRANGE (1 << 4)
38#define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 5)
37 39
38struct mt_slot { 40struct mt_slot {
39 __s32 x, y, p, w, h; 41 __s32 x, y, p, w, h;
@@ -55,6 +57,7 @@ struct mt_device {
55}; 57};
56 58
57struct mt_class { 59struct mt_class {
60 __s32 name; /* MT_CLS */
58 __s32 quirks; 61 __s32 quirks;
59 __s32 sn_move; /* Signal/noise ratio for move events */ 62 __s32 sn_move; /* Signal/noise ratio for move events */
60 __s32 sn_pressure; /* Signal/noise ratio for pressure events */ 63 __s32 sn_pressure; /* Signal/noise ratio for pressure events */
@@ -62,26 +65,16 @@ struct mt_class {
62}; 65};
63 66
64/* classes of device behavior */ 67/* classes of device behavior */
65#define MT_CLS_DEFAULT 0 68#define MT_CLS_DEFAULT 1
66#define MT_CLS_DUAL1 1 69#define MT_CLS_DUAL1 2
67#define MT_CLS_DUAL2 2 70#define MT_CLS_DUAL2 3
68#define MT_CLS_CYPRESS 3 71#define MT_CLS_CYPRESS 4
69 72
70/* 73/*
71 * these device-dependent functions determine what slot corresponds 74 * these device-dependent functions determine what slot corresponds
72 * to a valid contact that was just read. 75 * to a valid contact that was just read.
73 */ 76 */
74 77
75static int slot_is_contactid(struct mt_device *td)
76{
77 return td->curdata.contactid;
78}
79
80static int slot_is_contactnumber(struct mt_device *td)
81{
82 return td->num_received;
83}
84
85static int cypress_compute_slot(struct mt_device *td) 78static int cypress_compute_slot(struct mt_device *td)
86{ 79{
87 if (td->curdata.contactid != 0 || td->num_received == 0) 80 if (td->curdata.contactid != 0 || td->num_received == 0)
@@ -103,17 +96,30 @@ static int find_slot_from_contactid(struct mt_device *td)
103 !td->slots[i].touch_state) 96 !td->slots[i].touch_state)
104 return i; 97 return i;
105 } 98 }
106 return -1;
107 /* should not occurs. If this happens that means 99 /* should not occurs. If this happens that means
108 * that the device sent more touches that it says 100 * that the device sent more touches that it says
109 * in the report descriptor. It is ignored then. */ 101 * in the report descriptor. It is ignored then. */
102 return -1;
110} 103}
111 104
112struct mt_class mt_classes[] = { 105struct mt_class mt_classes[] = {
113 { 0, 0, 0, 10 }, /* MT_CLS_DEFAULT */ 106 { .name = MT_CLS_DEFAULT,
114 { MT_QUIRK_SLOT_IS_CONTACTID, 0, 0, 2 }, /* MT_CLS_DUAL1 */ 107 .quirks = MT_QUIRK_VALID_IS_INRANGE,
115 { MT_QUIRK_SLOT_IS_CONTACTNUMBER, 0, 0, 10 }, /* MT_CLS_DUAL2 */ 108 .maxcontacts = 10 },
116 { MT_QUIRK_CYPRESS | MT_QUIRK_NOT_SEEN_MEANS_UP, 0, 0, 10 }, /* MT_CLS_CYPRESS */ 109 { .name = MT_CLS_DUAL1,
110 .quirks = MT_QUIRK_VALID_IS_INRANGE |
111 MT_QUIRK_SLOT_IS_CONTACTID,
112 .maxcontacts = 2 },
113 { .name = MT_CLS_DUAL2,
114 .quirks = MT_QUIRK_VALID_IS_INRANGE |
115 MT_QUIRK_SLOT_IS_CONTACTNUMBER,
116 .maxcontacts = 2 },
117 { .name = MT_CLS_CYPRESS,
118 .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
119 MT_QUIRK_CYPRESS,
120 .maxcontacts = 10 },
121
122 { }
117}; 123};
118 124
119static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi, 125static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi,
@@ -192,7 +198,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
192 hid_map_usage(hi, usage, bit, max, 198 hid_map_usage(hi, usage, bit, max,
193 EV_ABS, ABS_MT_TOUCH_MINOR); 199 EV_ABS, ABS_MT_TOUCH_MINOR);
194 field->logical_maximum = 1; 200 field->logical_maximum = 1;
195 field->logical_minimum = 1; 201 field->logical_minimum = 0;
196 set_abs(hi->input, ABS_MT_ORIENTATION, field, 0); 202 set_abs(hi->input, ABS_MT_ORIENTATION, field, 0);
197 td->last_slot_field = usage->hid; 203 td->last_slot_field = usage->hid;
198 return 1; 204 return 1;
@@ -237,16 +243,16 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
237 243
238static int mt_compute_slot(struct mt_device *td) 244static int mt_compute_slot(struct mt_device *td)
239{ 245{
240 struct mt_class *cls = td->mtclass; 246 __s32 quirks = td->mtclass->quirks;
241 247
242 if (cls->quirks & MT_QUIRK_SLOT_IS_CONTACTID) 248 if (quirks & MT_QUIRK_SLOT_IS_CONTACTID)
243 return slot_is_contactid(td); 249 return td->curdata.contactid;
244 250
245 if (cls->quirks & MT_QUIRK_CYPRESS) 251 if (quirks & MT_QUIRK_CYPRESS)
246 return cypress_compute_slot(td); 252 return cypress_compute_slot(td);
247 253
248 if (cls->quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER) 254 if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER)
249 return slot_is_contactnumber(td); 255 return td->num_received;
250 256
251 return find_slot_from_contactid(td); 257 return find_slot_from_contactid(td);
252} 258}
@@ -257,16 +263,12 @@ static int mt_compute_slot(struct mt_device *td)
257 */ 263 */
258static void mt_complete_slot(struct mt_device *td) 264static void mt_complete_slot(struct mt_device *td)
259{ 265{
266 td->curdata.seen_in_this_frame = true;
260 if (td->curvalid) { 267 if (td->curvalid) {
261 struct mt_slot *slot;
262 int slotnum = mt_compute_slot(td); 268 int slotnum = mt_compute_slot(td);
263 269
264 if (slotnum >= 0 && slotnum < td->mtclass->maxcontacts) { 270 if (slotnum >= 0 && slotnum < td->mtclass->maxcontacts)
265 slot = td->slots + slotnum; 271 td->slots[slotnum] = td->curdata;
266
267 memcpy(slot, &(td->curdata), sizeof(struct mt_slot));
268 slot->seen_in_this_frame = true;
269 }
270 } 272 }
271 td->num_received++; 273 td->num_received++;
272} 274}
@@ -284,21 +286,19 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input)
284 struct mt_slot *s = &(td->slots[i]); 286 struct mt_slot *s = &(td->slots[i]);
285 if ((td->mtclass->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) && 287 if ((td->mtclass->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) &&
286 !s->seen_in_this_frame) { 288 !s->seen_in_this_frame) {
287 /*
288 * this slot does not contain useful data,
289 * notify its closure
290 */
291 s->touch_state = false; 289 s->touch_state = false;
292 } 290 }
293 291
294 input_mt_slot(input, i); 292 input_mt_slot(input, i);
295 input_mt_report_slot_state(input, MT_TOOL_FINGER, 293 input_mt_report_slot_state(input, MT_TOOL_FINGER,
296 s->touch_state); 294 s->touch_state);
297 input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x); 295 if (s->touch_state) {
298 input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y); 296 input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x);
299 input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p); 297 input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y);
300 input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, s->w); 298 input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
301 input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, s->h); 299 input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, s->w);
300 input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, s->h);
301 }
302 s->seen_in_this_frame = false; 302 s->seen_in_this_frame = false;
303 303
304 } 304 }
@@ -314,16 +314,22 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
314 struct hid_usage *usage, __s32 value) 314 struct hid_usage *usage, __s32 value)
315{ 315{
316 struct mt_device *td = hid_get_drvdata(hid); 316 struct mt_device *td = hid_get_drvdata(hid);
317 __s32 quirks = td->mtclass->quirks;
317 318
318 if (hid->claimed & HID_CLAIMED_INPUT) { 319 if (hid->claimed & HID_CLAIMED_INPUT) {
319 switch (usage->hid) { 320 switch (usage->hid) {
320 case HID_DG_INRANGE: 321 case HID_DG_INRANGE:
322 if (quirks & MT_QUIRK_VALID_IS_INRANGE)
323 td->curvalid = value;
321 break; 324 break;
322 case HID_DG_TIPSWITCH: 325 case HID_DG_TIPSWITCH:
323 td->curvalid = value; 326 if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
327 td->curvalid = value;
324 td->curdata.touch_state = value; 328 td->curdata.touch_state = value;
325 break; 329 break;
326 case HID_DG_CONFIDENCE: 330 case HID_DG_CONFIDENCE:
331 if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE)
332 td->curvalid = value;
327 break; 333 break;
328 case HID_DG_CONTACTID: 334 case HID_DG_CONTACTID:
329 td->curdata.contactid = value; 335 td->curdata.contactid = value;
@@ -345,26 +351,26 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
345 break; 351 break;
346 case HID_DG_CONTACTCOUNT: 352 case HID_DG_CONTACTCOUNT:
347 /* 353 /*
348 * We must not overwrite the previous value (some 354 * Includes multi-packet support where subsequent
349 * devices send one sequence splitted over several 355 * packets are sent with zero contactcount.
350 * messages)
351 */ 356 */
352 if (value) 357 if (value)
353 td->num_expected = value - 1; 358 td->num_expected = value;
354 break; 359 break;
355 360
356 default: 361 default:
357 /* fallback to the generic hidinput handling */ 362 /* fallback to the generic hidinput handling */
358 return 0; 363 return 0;
359 } 364 }
360 }
361 365
362 if (usage->hid == td->last_slot_field) 366 if (usage->hid == td->last_slot_field)
363 mt_complete_slot(td); 367 mt_complete_slot(td);
368
369 if (field->index == td->last_field_index
370 && td->num_received >= td->num_expected)
371 mt_emit_event(td, field->hidinput->input);
364 372
365 if (field->index == td->last_field_index 373 }
366 && td->num_received > td->num_expected)
367 mt_emit_event(td, field->hidinput->input);
368 374
369 /* we have handled the hidinput part, now remains hiddev */ 375 /* we have handled the hidinput part, now remains hiddev */
370 if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) 376 if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
@@ -392,9 +398,16 @@ static void mt_set_input_mode(struct hid_device *hdev)
392 398
393static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) 399static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
394{ 400{
395 int ret; 401 int ret, i;
396 struct mt_device *td; 402 struct mt_device *td;
397 struct mt_class *mtclass = mt_classes + id->driver_data; 403 struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
404
405 for (i = 0; mt_classes[i].name ; i++) {
406 if (id->driver_data == mt_classes[i].name) {
407 mtclass = &(mt_classes[i]);
408 break;
409 }
410 }
398 411
399 /* This allows the driver to correctly support devices 412 /* This allows the driver to correctly support devices
400 * that emit events over several HID messages. 413 * that emit events over several HID messages.
@@ -417,7 +430,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
417 goto fail; 430 goto fail;
418 431
419 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 432 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
420 if (ret != 0) 433 if (ret)
421 goto fail; 434 goto fail;
422 435
423 mt_set_input_mode(hdev); 436 mt_set_input_mode(hdev);