diff options
| -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); |
