diff options
author | Benjamin Tissoires <benjamin.tissoires@enac.fr> | 2011-01-11 10:45:54 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2011-01-11 15:26:56 -0500 |
commit | 2d93666e70662cfcf1927e1a858685f5b38d5d65 (patch) | |
tree | ad466fccbbce01ff2329a8b1429b96ed27f1a10f /drivers/hid | |
parent | c64f6f934c7490faff76faf96217066a1b3570a0 (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/Kconfig | 10 | ||||
-rw-r--r-- | drivers/hid/hid-multitouch.c | 127 |
2 files changed, 78 insertions, 59 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 9bd21482e618..97c200b0f4b8 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 | |||
299 | config HID_NTRIG | 305 | config 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 3442ed56e964..07d3183fdde5 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 | ||
38 | struct mt_slot { | 40 | struct 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 | ||
57 | struct mt_class { | 59 | struct 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 | ||
75 | static int slot_is_contactid(struct mt_device *td) | ||
76 | { | ||
77 | return td->curdata.contactid; | ||
78 | } | ||
79 | |||
80 | static int slot_is_contactnumber(struct mt_device *td) | ||
81 | { | ||
82 | return td->num_received; | ||
83 | } | ||
84 | |||
85 | static int cypress_compute_slot(struct mt_device *td) | 78 | static 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 | ||
112 | struct mt_class mt_classes[] = { | 105 | struct 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 | ||
119 | static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi, | 125 | static 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 | ||
238 | static int mt_compute_slot(struct mt_device *td) | 244 | static 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 | */ |
258 | static void mt_complete_slot(struct mt_device *td) | 264 | static 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 | ||
393 | static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | 399 | static 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); |