aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-multitouch.c
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@enac.fr>2011-03-18 09:27:52 -0400
committerJiri Kosina <jkosina@suse.cz>2011-03-21 12:04:25 -0400
commit9498f954a4ec389806333041a1018909c6fe0518 (patch)
tree3a9e7af0b35e02fc05c06068a2a4a14732e40dca /drivers/hid/hid-multitouch.c
parent99759619b27662d1290901228d77a293e6e83200 (diff)
HID: hid-multitouch: Auto detection of maxcontacts
This patch enables support of autodetection of maxcontacts. When adding support for a new device, one is now able to let the device tell how many contacts it supports, or to manually set the value if the device happens to provide wrong information. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@enac.fr> Reviewed-by: Stéphane Chatty <chatty@enac.fr> Reviewed-by: Henrik Rydberg <rydberg@euromail.se> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-multitouch.c')
-rw-r--r--drivers/hid/hid-multitouch.c52
1 files changed, 37 insertions, 15 deletions
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index ee01e65e22d6..b9f9eeceaa98 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -60,8 +60,9 @@ struct mt_device {
60 __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ 60 __s8 inputmode; /* InputMode HID feature, -1 if non-existent */
61 __u8 num_received; /* how many contacts we received */ 61 __u8 num_received; /* how many contacts we received */
62 __u8 num_expected; /* expected last contact index */ 62 __u8 num_expected; /* expected last contact index */
63 __u8 maxcontacts;
63 bool curvalid; /* is the current contact valid? */ 64 bool curvalid; /* is the current contact valid? */
64 struct mt_slot slots[0]; /* first slot */ 65 struct mt_slot *slots;
65}; 66};
66 67
67struct mt_class { 68struct mt_class {
@@ -79,6 +80,8 @@ struct mt_class {
79#define MT_CLS_CYPRESS 4 80#define MT_CLS_CYPRESS 4
80#define MT_CLS_EGALAX 5 81#define MT_CLS_EGALAX 5
81 82
83#define MT_DEFAULT_MAXCONTACT 10
84
82/* 85/*
83 * these device-dependent functions determine what slot corresponds 86 * these device-dependent functions determine what slot corresponds
84 * to a valid contact that was just read. 87 * to a valid contact that was just read.
@@ -95,12 +98,12 @@ static int cypress_compute_slot(struct mt_device *td)
95static int find_slot_from_contactid(struct mt_device *td) 98static int find_slot_from_contactid(struct mt_device *td)
96{ 99{
97 int i; 100 int i;
98 for (i = 0; i < td->mtclass->maxcontacts; ++i) { 101 for (i = 0; i < td->maxcontacts; ++i) {
99 if (td->slots[i].contactid == td->curdata.contactid && 102 if (td->slots[i].contactid == td->curdata.contactid &&
100 td->slots[i].touch_state) 103 td->slots[i].touch_state)
101 return i; 104 return i;
102 } 105 }
103 for (i = 0; i < td->mtclass->maxcontacts; ++i) { 106 for (i = 0; i < td->maxcontacts; ++i) {
104 if (!td->slots[i].seen_in_this_frame && 107 if (!td->slots[i].seen_in_this_frame &&
105 !td->slots[i].touch_state) 108 !td->slots[i].touch_state)
106 return i; 109 return i;
@@ -113,8 +116,7 @@ static int find_slot_from_contactid(struct mt_device *td)
113 116
114struct mt_class mt_classes[] = { 117struct mt_class mt_classes[] = {
115 { .name = MT_CLS_DEFAULT, 118 { .name = MT_CLS_DEFAULT,
116 .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP, 119 .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP },
117 .maxcontacts = 10 },
118 { .name = MT_CLS_DUAL_INRANGE_CONTACTID, 120 { .name = MT_CLS_DUAL_INRANGE_CONTACTID,
119 .quirks = MT_QUIRK_VALID_IS_INRANGE | 121 .quirks = MT_QUIRK_VALID_IS_INRANGE |
120 MT_QUIRK_SLOT_IS_CONTACTID, 122 MT_QUIRK_SLOT_IS_CONTACTID,
@@ -142,9 +144,19 @@ struct mt_class mt_classes[] = {
142static void mt_feature_mapping(struct hid_device *hdev, 144static void mt_feature_mapping(struct hid_device *hdev,
143 struct hid_field *field, struct hid_usage *usage) 145 struct hid_field *field, struct hid_usage *usage)
144{ 146{
145 if (usage->hid == HID_DG_INPUTMODE) { 147 struct mt_device *td = hid_get_drvdata(hdev);
146 struct mt_device *td = hid_get_drvdata(hdev); 148
149 switch (usage->hid) {
150 case HID_DG_INPUTMODE:
147 td->inputmode = field->report->id; 151 td->inputmode = field->report->id;
152 break;
153 case HID_DG_CONTACTMAX:
154 td->maxcontacts = field->value[0];
155 if (td->mtclass->maxcontacts)
156 /* check if the maxcontacts is given by the class */
157 td->maxcontacts = td->mtclass->maxcontacts;
158
159 break;
148 } 160 }
149} 161}
150 162
@@ -208,8 +220,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
208 td->last_slot_field = usage->hid; 220 td->last_slot_field = usage->hid;
209 return 1; 221 return 1;
210 case HID_DG_CONTACTID: 222 case HID_DG_CONTACTID:
211 input_mt_init_slots(hi->input, 223 input_mt_init_slots(hi->input, td->maxcontacts);
212 td->mtclass->maxcontacts);
213 td->last_slot_field = usage->hid; 224 td->last_slot_field = usage->hid;
214 return 1; 225 return 1;
215 case HID_DG_WIDTH: 226 case HID_DG_WIDTH:
@@ -292,7 +303,7 @@ static void mt_complete_slot(struct mt_device *td)
292 if (td->curvalid) { 303 if (td->curvalid) {
293 int slotnum = mt_compute_slot(td); 304 int slotnum = mt_compute_slot(td);
294 305
295 if (slotnum >= 0 && slotnum < td->mtclass->maxcontacts) 306 if (slotnum >= 0 && slotnum < td->maxcontacts)
296 td->slots[slotnum] = td->curdata; 307 td->slots[slotnum] = td->curdata;
297 } 308 }
298 td->num_received++; 309 td->num_received++;
@@ -307,7 +318,7 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input)
307{ 318{
308 int i; 319 int i;
309 320
310 for (i = 0; i < td->mtclass->maxcontacts; ++i) { 321 for (i = 0; i < td->maxcontacts; ++i) {
311 struct mt_slot *s = &(td->slots[i]); 322 struct mt_slot *s = &(td->slots[i]);
312 if ((td->mtclass->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) && 323 if ((td->mtclass->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) &&
313 !s->seen_in_this_frame) { 324 !s->seen_in_this_frame) {
@@ -341,7 +352,7 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
341 struct mt_device *td = hid_get_drvdata(hid); 352 struct mt_device *td = hid_get_drvdata(hid);
342 __s32 quirks = td->mtclass->quirks; 353 __s32 quirks = td->mtclass->quirks;
343 354
344 if (hid->claimed & HID_CLAIMED_INPUT) { 355 if (hid->claimed & HID_CLAIMED_INPUT && td->slots) {
345 switch (usage->hid) { 356 switch (usage->hid) {
346 case HID_DG_INRANGE: 357 case HID_DG_INRANGE:
347 if (quirks & MT_QUIRK_VALID_IS_INRANGE) 358 if (quirks & MT_QUIRK_VALID_IS_INRANGE)
@@ -442,9 +453,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
442 */ 453 */
443 hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; 454 hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
444 455
445 td = kzalloc(sizeof(struct mt_device) + 456 td = kzalloc(sizeof(struct mt_device), GFP_KERNEL);
446 mtclass->maxcontacts * sizeof(struct mt_slot),
447 GFP_KERNEL);
448 if (!td) { 457 if (!td) {
449 dev_err(&hdev->dev, "cannot allocate multitouch data\n"); 458 dev_err(&hdev->dev, "cannot allocate multitouch data\n");
450 return -ENOMEM; 459 return -ENOMEM;
@@ -461,6 +470,18 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
461 if (ret) 470 if (ret)
462 goto fail; 471 goto fail;
463 472
473 if (!td->maxcontacts)
474 td->maxcontacts = MT_DEFAULT_MAXCONTACT;
475
476 td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot),
477 GFP_KERNEL);
478 if (!td->slots) {
479 dev_err(&hdev->dev, "cannot allocate multitouch slots\n");
480 hid_hw_stop(hdev);
481 ret = -ENOMEM;
482 goto fail;
483 }
484
464 mt_set_input_mode(hdev); 485 mt_set_input_mode(hdev);
465 486
466 return 0; 487 return 0;
@@ -482,6 +503,7 @@ static void mt_remove(struct hid_device *hdev)
482{ 503{
483 struct mt_device *td = hid_get_drvdata(hdev); 504 struct mt_device *td = hid_get_drvdata(hdev);
484 hid_hw_stop(hdev); 505 hid_hw_stop(hdev);
506 kfree(td->slots);
485 kfree(td); 507 kfree(td);
486 hid_set_drvdata(hdev, NULL); 508 hid_set_drvdata(hdev, NULL);
487} 509}