aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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}