aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorPing Cheng <pingc@wacom.com>2009-12-15 03:35:24 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-12-15 03:36:08 -0500
commitec67bbedcf290ef182a897017f65a2707106c7f8 (patch)
tree321fe650b72776e8555da3a94b049e2704bc2b2a /drivers/input
parentee54500d7b960984df125bdd0cd2105d6150e8f1 (diff)
Input: wacom - add support for new LCD tablets
This adds support for the foolowing Wacom devices: - 0x9F - a single touch only LCD tablet; - 0xE2 - a two finger touch only LCD tablet; - 0xE3 - a two finger touch, penabled LCD tablet. Signed-off-by: Ping Cheng <pingc@wacom.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/tablet/wacom.h3
-rw-r--r--drivers/input/tablet/wacom_sys.c226
-rw-r--r--drivers/input/tablet/wacom_wac.c204
-rw-r--r--drivers/input/tablet/wacom_wac.h10
4 files changed, 311 insertions, 132 deletions
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index d71da970602c..16310f368dab 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -71,6 +71,7 @@
71 * v1.51 (pc) - Added support for Intuos4 71 * v1.51 (pc) - Added support for Intuos4
72 * v1.52 (pc) - Query Wacom data upon system resume 72 * v1.52 (pc) - Query Wacom data upon system resume
73 * - add defines for features->type 73 * - add defines for features->type
74 * - add new devices (0x9F, 0xE2, and 0XE3)
74 */ 75 */
75 76
76/* 77/*
@@ -135,6 +136,8 @@ extern void input_dev_i4s(struct input_dev *input_dev, struct wacom_wac *wacom_w
135extern void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac); 136extern void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
136extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac); 137extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
137extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac); 138extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
139extern void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
140extern void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
138extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac); 141extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
139extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac); 142extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
140extern __u16 wacom_le16_to_cpu(unsigned char *data); 143extern __u16 wacom_le16_to_cpu(unsigned char *data);
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index b5b69cc0aaf0..072f33b3b2b0 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -209,6 +209,7 @@ void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
209 input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) | 209 input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) |
210 BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); 210 BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
211 input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | 211 input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) |
212 BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) |
212 BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2); 213 BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2);
213 input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); 214 input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0);
214} 215}
@@ -256,6 +257,7 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
256 BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) | 257 BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) |
257 BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA); 258 BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
258 input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | 259 input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) |
260 BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) |
259 BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_TOOL_BRUSH) | 261 BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_TOOL_BRUSH) |
260 BIT_MASK(BTN_TOOL_PENCIL) | BIT_MASK(BTN_TOOL_AIRBRUSH) | 262 BIT_MASK(BTN_TOOL_PENCIL) | BIT_MASK(BTN_TOOL_AIRBRUSH) |
261 BIT_MASK(BTN_TOOL_LENS) | BIT_MASK(BTN_STYLUS2); 263 BIT_MASK(BTN_TOOL_LENS) | BIT_MASK(BTN_STYLUS2);
@@ -269,7 +271,8 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
269 271
270void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac) 272void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
271{ 273{
272 input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2); 274 input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) |
275 BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_STYLUS2);
273} 276}
274 277
275void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) 278void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
@@ -277,12 +280,32 @@ void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
277 input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER); 280 input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER);
278} 281}
279 282
283void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
284{
285 if (wacom_wac->features->device_type == BTN_TOOL_DOUBLETAP ||
286 wacom_wac->features->device_type == BTN_TOOL_TRIPLETAP) {
287 input_set_abs_params(input_dev, ABS_RX, 0, wacom_wac->features->x_phy, 0, 0);
288 input_set_abs_params(input_dev, ABS_RY, 0, wacom_wac->features->y_phy, 0, 0);
289 input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP);
290 }
291}
292
293void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
294{
295 if (wacom_wac->features->device_type == BTN_TOOL_TRIPLETAP) {
296 input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP);
297 input_dev->evbit[0] |= BIT_MASK(EV_MSC);
298 input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL);
299 }
300}
301
280static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, 302static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc,
281 struct wacom_wac *wacom_wac) 303 struct wacom_features *features)
282{ 304{
283 struct usb_device *dev = interface_to_usbdev(intf); 305 struct usb_device *dev = interface_to_usbdev(intf);
284 struct wacom_features *features = wacom_wac->features; 306 char limit = 0;
285 char limit = 0, result = 0; 307 /* result has to be defined as int for some devices */
308 int result = 0;
286 int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0; 309 int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0;
287 unsigned char *report; 310 unsigned char *report;
288 311
@@ -328,13 +351,24 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
328 case HID_USAGE_X: 351 case HID_USAGE_X:
329 if (usage == WCM_DESKTOP) { 352 if (usage == WCM_DESKTOP) {
330 if (finger) { 353 if (finger) {
331 features->touch_x_max = 354 features->device_type = BTN_TOOL_DOUBLETAP;
332 features->touch_y_max = 355 if (features->type == TABLETPC2FG) {
333 wacom_le16_to_cpu(&report[i + 3]); 356 /* need to reset back */
357 features->pktlen = WACOM_PKGLEN_TPC2FG;
358 features->device_type = BTN_TOOL_TRIPLETAP;
359 }
334 features->x_max = 360 features->x_max =
361 wacom_le16_to_cpu(&report[i + 3]);
362 features->x_phy =
335 wacom_le16_to_cpu(&report[i + 6]); 363 wacom_le16_to_cpu(&report[i + 6]);
336 i += 7; 364 features->unit = report[i + 9];
365 features->unitExpo = report[i + 11];
366 i += 12;
337 } else if (pen) { 367 } else if (pen) {
368 /* penabled only accepts exact bytes of data */
369 if (features->type == TABLETPC2FG)
370 features->pktlen = WACOM_PKGLEN_PENABLED;
371 features->device_type = BTN_TOOL_PEN;
338 features->x_max = 372 features->x_max =
339 wacom_le16_to_cpu(&report[i + 3]); 373 wacom_le16_to_cpu(&report[i + 3]);
340 i += 4; 374 i += 4;
@@ -350,10 +384,35 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
350 break; 384 break;
351 385
352 case HID_USAGE_Y: 386 case HID_USAGE_Y:
353 if (usage == WCM_DESKTOP) 387 if (usage == WCM_DESKTOP) {
354 features->y_max = 388 if (finger) {
355 wacom_le16_to_cpu(&report[i + 3]); 389 features->device_type = BTN_TOOL_DOUBLETAP;
356 i += 4; 390 if (features->type == TABLETPC2FG) {
391 /* need to reset back */
392 features->pktlen = WACOM_PKGLEN_TPC2FG;
393 features->device_type = BTN_TOOL_TRIPLETAP;
394 features->y_max =
395 wacom_le16_to_cpu(&report[i + 3]);
396 features->y_phy =
397 wacom_le16_to_cpu(&report[i + 6]);
398 i += 7;
399 } else {
400 features->y_max =
401 features->x_max;
402 features->y_phy =
403 wacom_le16_to_cpu(&report[i + 3]);
404 i += 4;
405 }
406 } else if (pen) {
407 /* penabled only accepts exact bytes of data */
408 if (features->type == TABLETPC2FG)
409 features->pktlen = WACOM_PKGLEN_PENABLED;
410 features->device_type = BTN_TOOL_PEN;
411 features->y_max =
412 wacom_le16_to_cpu(&report[i + 3]);
413 i += 4;
414 }
415 }
357 break; 416 break;
358 417
359 case HID_USAGE_FINGER: 418 case HID_USAGE_FINGER:
@@ -376,7 +435,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
376 break; 435 break;
377 436
378 case HID_COLLECTION: 437 case HID_COLLECTION:
379 /* reset UsagePage ans Finger */ 438 /* reset UsagePage and Finger */
380 finger = usage = 0; 439 finger = usage = 0;
381 break; 440 break;
382 } 441 }
@@ -388,43 +447,92 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
388 return result; 447 return result;
389} 448}
390 449
391static int wacom_query_tablet_data(struct usb_interface *intf) 450static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features)
392{ 451{
393 unsigned char *rep_data; 452 unsigned char *rep_data;
394 int limit = 0; 453 int limit = 0, report_id = 2;
395 int error; 454 int error = -ENOMEM;
396 455
397 rep_data = kmalloc(2, GFP_KERNEL); 456 rep_data = kmalloc(2, GFP_KERNEL);
398 if (!rep_data) 457 if (!rep_data)
399 return -ENOMEM; 458 return error;
400 459
401 do { 460 /* ask to report tablet data if it is 2FGT or not a Tablet PC */
402 rep_data[0] = 2; 461 if (features->device_type == BTN_TOOL_TRIPLETAP) {
403 rep_data[1] = 2; 462 do {
404 error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, 463 rep_data[0] = 3;
405 2, rep_data, 2); 464 rep_data[1] = 4;
406 if (error >= 0) 465 report_id = 3;
407 error = usb_get_report(intf, 466 error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
408 WAC_HID_FEATURE_REPORT, 2, 467 report_id, rep_data, 2);
409 rep_data, 2); 468 if (error >= 0)
410 } while ((error < 0 || rep_data[1] != 2) && limit++ < 5); 469 error = usb_get_report(intf,
470 WAC_HID_FEATURE_REPORT, report_id,
471 rep_data, 3);
472 } while ((error < 0 || rep_data[1] != 4) && limit++ < 5);
473 } else if (features->type != TABLETPC && features->type != TABLETPC2FG) {
474 do {
475 rep_data[0] = 2;
476 rep_data[1] = 2;
477 error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
478 report_id, rep_data, 2);
479 if (error >= 0)
480 error = usb_get_report(intf,
481 WAC_HID_FEATURE_REPORT, report_id,
482 rep_data, 2);
483 } while ((error < 0 || rep_data[1] != 2) && limit++ < 5);
484 }
411 485
412 kfree(rep_data); 486 kfree(rep_data);
413 487
414 return error < 0 ? error : 0; 488 return error < 0 ? error : 0;
415} 489}
416 490
491static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
492 struct wacom_features *features)
493{
494 int error = 0;
495 struct usb_host_interface *interface = intf->cur_altsetting;
496 struct hid_descriptor *hid_desc;
497
498 /* default device to penabled */
499 features->device_type = BTN_TOOL_PEN;
500
501 /* only Tablet PCs need to retrieve the info */
502 if ((features->type != TABLETPC) && (features->type != TABLETPC2FG))
503 goto out;
504
505 if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
506 if (usb_get_extra_descriptor(&interface->endpoint[0],
507 HID_DEVICET_REPORT, &hid_desc)) {
508 printk("wacom: can not retrieve extra class descriptor\n");
509 error = 1;
510 goto out;
511 }
512 }
513 error = wacom_parse_hid(intf, hid_desc, features);
514 if (error)
515 goto out;
516
517 /* touch device found but size is not defined. use default */
518 if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) {
519 features->x_max = 1023;
520 features->y_max = 1023;
521 }
522
523 out:
524 return error;
525}
526
417static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) 527static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
418{ 528{
419 struct usb_device *dev = interface_to_usbdev(intf); 529 struct usb_device *dev = interface_to_usbdev(intf);
420 struct usb_host_interface *interface = intf->cur_altsetting;
421 struct usb_endpoint_descriptor *endpoint; 530 struct usb_endpoint_descriptor *endpoint;
422 struct wacom *wacom; 531 struct wacom *wacom;
423 struct wacom_wac *wacom_wac; 532 struct wacom_wac *wacom_wac;
424 struct wacom_features *features; 533 struct wacom_features *features;
425 struct input_dev *input_dev; 534 struct input_dev *input_dev;
426 int error = -ENOMEM; 535 int error = -ENOMEM;
427 struct hid_descriptor *hid_desc;
428 536
429 wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); 537 wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
430 wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL); 538 wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL);
@@ -432,7 +540,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
432 if (!wacom || !input_dev || !wacom_wac) 540 if (!wacom || !input_dev || !wacom_wac)
433 goto fail1; 541 goto fail1;
434 542
435 wacom_wac->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma); 543 wacom_wac->data = usb_buffer_alloc(dev, WACOM_PKGLEN_MAX, GFP_KERNEL, &wacom->data_dma);
436 if (!wacom_wac->data) 544 if (!wacom_wac->data)
437 goto fail1; 545 goto fail1;
438 546
@@ -448,7 +556,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
448 strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); 556 strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
449 557
450 wacom_wac->features = features = get_wacom_feature(id); 558 wacom_wac->features = features = get_wacom_feature(id);
451 BUG_ON(features->pktlen > 10); 559 BUG_ON(features->pktlen > WACOM_PKGLEN_MAX);
452 560
453 input_dev->name = wacom_wac->features->name; 561 input_dev->name = wacom_wac->features->name;
454 wacom->wacom_wac = wacom_wac; 562 wacom->wacom_wac = wacom_wac;
@@ -463,47 +571,24 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
463 571
464 endpoint = &intf->cur_altsetting->endpoint[0].desc; 572 endpoint = &intf->cur_altsetting->endpoint[0].desc;
465 573
466 /* Initialize touch_x_max and touch_y_max in case it is not defined */ 574 /* Retrieve the physical and logical size for OEM devices */
467 if (wacom_wac->features->type == TABLETPC) { 575 error = wacom_retrieve_hid_descriptor(intf, features);
468 features->touch_x_max = 1023; 576 if (error)
469 features->touch_y_max = 1023; 577 goto fail2;
470 } else {
471 features->touch_x_max = 0;
472 features->touch_y_max = 0;
473 }
474
475 /* TabletPC need to retrieve the physical and logical maximum from report descriptor */
476 if (wacom_wac->features->type == TABLETPC) {
477 if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
478 if (usb_get_extra_descriptor(&interface->endpoint[0],
479 HID_DEVICET_REPORT, &hid_desc)) {
480 printk("wacom: can not retrive extra class descriptor\n");
481 goto fail2;
482 }
483 }
484 error = wacom_parse_hid(intf, hid_desc, wacom_wac);
485 if (error)
486 goto fail2;
487 }
488 578
489 input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 579 input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
490 input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) | 580 input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOUCH);
491 BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS); 581
492 input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0); 582 input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0);
493 input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0); 583 input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0);
494 input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0); 584 input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0);
495 if (features->type == TABLETPC) {
496 input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP);
497 input_set_abs_params(input_dev, ABS_RX, 0, features->touch_x_max, 4, 0);
498 input_set_abs_params(input_dev, ABS_RY, 0, features->touch_y_max, 4, 0);
499 }
500 input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC); 585 input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
501 586
502 wacom_init_input_dev(input_dev, wacom_wac); 587 wacom_init_input_dev(input_dev, wacom_wac);
503 588
504 usb_fill_int_urb(wacom->irq, dev, 589 usb_fill_int_urb(wacom->irq, dev,
505 usb_rcvintpipe(dev, endpoint->bEndpointAddress), 590 usb_rcvintpipe(dev, endpoint->bEndpointAddress),
506 wacom_wac->data, wacom_wac->features->pktlen, 591 wacom_wac->data, features->pktlen,
507 wacom_sys_irq, wacom, endpoint->bInterval); 592 wacom_sys_irq, wacom, endpoint->bInterval);
508 wacom->irq->transfer_dma = wacom->data_dma; 593 wacom->irq->transfer_dma = wacom->data_dma;
509 wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 594 wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -512,18 +597,14 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
512 if (error) 597 if (error)
513 goto fail3; 598 goto fail3;
514 599
515 /* 600 /* Note that if query fails it is not a hard failure */
516 * Ask the tablet to report tablet data if it is not a Tablet PC. 601 wacom_query_tablet_data(intf, features);
517 * Note that if query fails it is not a hard failure.
518 */
519 if (wacom_wac->features->type != TABLETPC)
520 wacom_query_tablet_data(intf);
521 602
522 usb_set_intfdata(intf, wacom); 603 usb_set_intfdata(intf, wacom);
523 return 0; 604 return 0;
524 605
525 fail3: usb_free_urb(wacom->irq); 606 fail3: usb_free_urb(wacom->irq);
526 fail2: usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma); 607 fail2: usb_buffer_free(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
527 fail1: input_free_device(input_dev); 608 fail1: input_free_device(input_dev);
528 kfree(wacom); 609 kfree(wacom);
529 kfree(wacom_wac); 610 kfree(wacom_wac);
@@ -539,7 +620,7 @@ static void wacom_disconnect(struct usb_interface *intf)
539 usb_kill_urb(wacom->irq); 620 usb_kill_urb(wacom->irq);
540 input_unregister_device(wacom->dev); 621 input_unregister_device(wacom->dev);
541 usb_free_urb(wacom->irq); 622 usb_free_urb(wacom->irq);
542 usb_buffer_free(interface_to_usbdev(intf), 10, 623 usb_buffer_free(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
543 wacom->wacom_wac->data, wacom->data_dma); 624 wacom->wacom_wac->data, wacom->data_dma);
544 kfree(wacom->wacom_wac); 625 kfree(wacom->wacom_wac);
545 kfree(wacom); 626 kfree(wacom);
@@ -559,12 +640,15 @@ static int wacom_suspend(struct usb_interface *intf, pm_message_t message)
559static int wacom_resume(struct usb_interface *intf) 640static int wacom_resume(struct usb_interface *intf)
560{ 641{
561 struct wacom *wacom = usb_get_intfdata(intf); 642 struct wacom *wacom = usb_get_intfdata(intf);
643 struct wacom_features *features = wacom->wacom_wac->features;
562 int rv; 644 int rv;
563 645
564 mutex_lock(&wacom->lock); 646 mutex_lock(&wacom->lock);
565 if (wacom->open) { 647 if (wacom->open) {
566 rv = usb_submit_urb(wacom->irq, GFP_NOIO); 648 rv = usb_submit_urb(wacom->irq, GFP_NOIO);
567 wacom_query_tablet_data(intf); 649 /* switch to wacom mode if needed */
650 if (!wacom_retrieve_hid_descriptor(intf, features))
651 wacom_query_tablet_data(intf, features);
568 } else 652 } else
569 rv = 0; 653 rv = 0;
570 mutex_unlock(&wacom->lock); 654 mutex_unlock(&wacom->lock);
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index d5fc97d36102..46725894ea62 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -65,9 +65,8 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo)
65 65
66 prox = data[1] & 0x40; 66 prox = data[1] & 0x40;
67 67
68 wacom->id[0] = ERASER_DEVICE_ID;
69 if (prox) { 68 if (prox) {
70 69 wacom->id[0] = ERASER_DEVICE_ID;
71 pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); 70 pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
72 if (wacom->features->pressure_max > 255) 71 if (wacom->features->pressure_max > 255)
73 pressure = (pressure << 1) | ((data[4] >> 6) & 1); 72 pressure = (pressure << 1) | ((data[4] >> 6) & 1);
@@ -608,54 +607,146 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
608 return 1; 607 return 1;
609} 608}
610 609
610
611static void wacom_tpc_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx)
612{
613 wacom_report_abs(wcombo, ABS_X,
614 (data[2 + idx * 2] & 0xff) | ((data[3 + idx * 2] & 0x7f) << 8));
615 wacom_report_abs(wcombo, ABS_Y,
616 (data[6 + idx * 2] & 0xff) | ((data[7 + idx * 2] & 0x7f) << 8));
617 wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
618 wacom_report_key(wcombo, wacom->tool[idx], 1);
619 if (idx)
620 wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
621 else
622 wacom_report_key(wcombo, BTN_TOUCH, 1);
623}
624
625static void wacom_tpc_touch_out(struct wacom_wac *wacom, void *wcombo, int idx)
626{
627 wacom_report_abs(wcombo, ABS_X, 0);
628 wacom_report_abs(wcombo, ABS_Y, 0);
629 wacom_report_abs(wcombo, ABS_MISC, 0);
630 wacom_report_key(wcombo, wacom->tool[idx], 0);
631 if (idx)
632 wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
633 else
634 wacom_report_key(wcombo, BTN_TOUCH, 0);
635 return;
636}
637
638static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo)
639{
640 char *data = wacom->data;
641 struct urb *urb = ((struct wacom_combo *)wcombo)->urb;
642 static int firstFinger = 0;
643 static int secondFinger = 0;
644
645 wacom->tool[0] = BTN_TOOL_DOUBLETAP;
646 wacom->id[0] = TOUCH_DEVICE_ID;
647 wacom->tool[1] = BTN_TOOL_TRIPLETAP;
648
649 if (urb->actual_length != WACOM_PKGLEN_TPC1FG) {
650 switch (data[0]) {
651 case 6:
652 wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
653 wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
654 wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6]));
655 wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6]));
656 wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
657 wacom_report_key(wcombo, wacom->tool[0], 1);
658 break;
659 case 13:
660 /* keep this byte to send proper out-prox event */
661 wacom->id[1] = data[1] & 0x03;
662
663 if (data[1] & 0x01) {
664 wacom_tpc_finger_in(wacom, wcombo, data, 0);
665 firstFinger = 1;
666 } else if (firstFinger) {
667 wacom_tpc_touch_out(wacom, wcombo, 0);
668 }
669
670 if (data[1] & 0x02) {
671 /* sync first finger data */
672 if (firstFinger)
673 wacom_input_sync(wcombo);
674
675 wacom_tpc_finger_in(wacom, wcombo, data, 1);
676 secondFinger = 1;
677 } else if (secondFinger) {
678 /* sync first finger data */
679 if (firstFinger)
680 wacom_input_sync(wcombo);
681
682 wacom_tpc_touch_out(wacom, wcombo, 1);
683 secondFinger = 0;
684 }
685 if (!(data[1] & 0x01))
686 firstFinger = 0;
687 break;
688 }
689 } else {
690 wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
691 wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
692 wacom_report_key(wcombo, BTN_TOUCH, 1);
693 wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
694 wacom_report_key(wcombo, wacom->tool[0], 1);
695 }
696 return;
697}
698
611static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) 699static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
612{ 700{
613 char *data = wacom->data; 701 char *data = wacom->data;
614 int prox = 0, pressure; 702 int prox = 0, pressure, idx = -1;
615 static int stylusInProx, touchInProx = 1, touchOut; 703 static int stylusInProx, touchInProx = 1, touchOut;
616 struct urb *urb = ((struct wacom_combo *)wcombo)->urb; 704 struct urb *urb = ((struct wacom_combo *)wcombo)->urb;
617 705
618 dbg("wacom_tpc_irq: received report #%d", data[0]); 706 dbg("wacom_tpc_irq: received report #%d", data[0]);
619 707
620 if (urb->actual_length == WACOM_PKGLEN_TPC1FG || data[0] == 6) { /* Touch data */ 708 if (urb->actual_length == WACOM_PKGLEN_TPC1FG ||
709 data[0] == 6 || /* single touch */
710 data[0] == 13) { /* 2FG touch */
621 if (urb->actual_length == WACOM_PKGLEN_TPC1FG) { /* with touch */ 711 if (urb->actual_length == WACOM_PKGLEN_TPC1FG) { /* with touch */
622 prox = data[0] & 0x03; 712 prox = data[0] & 0x01;
623 } else { /* with capacity */ 713 } else { /* with capacity */
624 prox = data[1] & 0x03; 714 if (data[0] == 6)
715 /* single touch */
716 prox = data[1] & 0x01;
717 else
718 /* 2FG touch data */
719 prox = data[1] & 0x03;
625 } 720 }
626 721
627 if (!stylusInProx) { /* stylus not in prox */ 722 if (!stylusInProx) { /* stylus not in prox */
628 if (prox) { 723 if (prox) {
629 if (touchInProx) { 724 if (touchInProx) {
630 wacom->tool[1] = BTN_TOOL_DOUBLETAP; 725 wacom_tpc_touch_in(wacom, wcombo);
631 wacom->id[0] = TOUCH_DEVICE_ID;
632 if (urb->actual_length != WACOM_PKGLEN_TPC1FG) {
633 wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
634 wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
635 wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6]));
636 wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6]));
637 } else {
638 wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
639 wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
640 wacom_report_key(wcombo, BTN_TOUCH, 1);
641 }
642 wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
643 wacom_report_key(wcombo, wacom->tool[1], prox & 0x01);
644 touchOut = 1; 726 touchOut = 1;
645 return 1; 727 return 1;
646 } 728 }
647 } else { 729 } else {
648 wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); 730 /* 2FGT out-prox */
649 wacom_report_key(wcombo, wacom->tool[1], prox & 0x01); 731 if ((data[0] & 0xff) == 13) {
650 wacom_report_key(wcombo, BTN_TOUCH, 0); 732 idx = (wacom->id[1] & 0x01) - 1;
733 if (idx == 0) {
734 wacom_tpc_touch_out(wacom, wcombo, idx);
735 /* sync first finger event */
736 if (wacom->id[1] & 0x02)
737 wacom_input_sync(wcombo);
738 }
739 idx = (wacom->id[1] & 0x02) - 1;
740 if (idx == 1)
741 wacom_tpc_touch_out(wacom, wcombo, idx);
742 } else /* one finger touch */
743 wacom_tpc_touch_out(wacom, wcombo, 0);
651 touchOut = 0; 744 touchOut = 0;
652 touchInProx = 1; 745 touchInProx = 1;
653 return 1; 746 return 1;
654 } 747 }
655 } else if (touchOut || !prox) { /* force touch out-prox */ 748 } else if (touchOut || !prox) { /* force touch out-prox */
656 wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID); 749 wacom_tpc_touch_out(wacom, wcombo, 0);
657 wacom_report_key(wcombo, wacom->tool[1], 0);
658 wacom_report_key(wcombo, BTN_TOUCH, 0);
659 touchOut = 0; 750 touchOut = 0;
660 touchInProx = 1; 751 touchInProx = 1;
661 return 1; 752 return 1;
@@ -665,38 +756,14 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
665 756
666 touchInProx = 0; 757 touchInProx = 0;
667 758
668 wacom->id[0] = ERASER_DEVICE_ID;
669
670 /*
671 * if going from out of proximity into proximity select between the eraser
672 * and the pen based on the state of the stylus2 button, choose eraser if
673 * pressed else choose pen. if not a proximity change from out to in, send
674 * an out of proximity for previous tool then a in for new tool.
675 */
676 if (prox) { /* in prox */ 759 if (prox) { /* in prox */
677 if (!wacom->tool[0]) { 760 if (!wacom->id[0]) {
678 /* Going into proximity select tool */ 761 /* Going into proximity select tool */
679 wacom->tool[1] = (data[1] & 0x08) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; 762 wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
680 if (wacom->tool[1] == BTN_TOOL_PEN) 763 if (wacom->tool[0] == BTN_TOOL_PEN)
681 wacom->id[0] = STYLUS_DEVICE_ID; 764 wacom->id[0] = STYLUS_DEVICE_ID;
682 } else if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[1] & 0x08)) { 765 else
683 /* 766 wacom->id[0] = ERASER_DEVICE_ID;
684 * was entered with stylus2 pressed
685 * report out proximity for previous tool
686 */
687 wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
688 wacom_report_key(wcombo, wacom->tool[1], 0);
689 wacom_input_sync(wcombo);
690
691 /* set new tool */
692 wacom->tool[1] = BTN_TOOL_PEN;
693 wacom->id[0] = STYLUS_DEVICE_ID;
694 return 0;
695 }
696 if (wacom->tool[1] != BTN_TOOL_RUBBER) {
697 /* Unknown tool selected default to pen tool */
698 wacom->tool[1] = BTN_TOOL_PEN;
699 wacom->id[0] = STYLUS_DEVICE_ID;
700 } 767 }
701 wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); 768 wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
702 wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); 769 wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10);
@@ -706,17 +773,21 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
706 if (pressure < 0) 773 if (pressure < 0)
707 pressure = wacom->features->pressure_max + pressure + 1; 774 pressure = wacom->features->pressure_max + pressure + 1;
708 wacom_report_abs(wcombo, ABS_PRESSURE, pressure); 775 wacom_report_abs(wcombo, ABS_PRESSURE, pressure);
709 wacom_report_key(wcombo, BTN_TOUCH, pressure); 776 wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05);
710 } else { 777 } else {
778 wacom_report_abs(wcombo, ABS_X, 0);
779 wacom_report_abs(wcombo, ABS_Y, 0);
711 wacom_report_abs(wcombo, ABS_PRESSURE, 0); 780 wacom_report_abs(wcombo, ABS_PRESSURE, 0);
712 wacom_report_key(wcombo, BTN_STYLUS, 0); 781 wacom_report_key(wcombo, BTN_STYLUS, 0);
713 wacom_report_key(wcombo, BTN_STYLUS2, 0); 782 wacom_report_key(wcombo, BTN_STYLUS2, 0);
714 wacom_report_key(wcombo, BTN_TOUCH, 0); 783 wacom_report_key(wcombo, BTN_TOUCH, 0);
784 wacom->id[0] = 0;
785 /* pen is out so touch can be enabled now */
786 touchInProx = 1;
715 } 787 }
716 wacom_report_key(wcombo, wacom->tool[1], prox); 788 wacom_report_key(wcombo, wacom->tool[0], prox);
717 wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); 789 wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
718 stylusInProx = prox; 790 stylusInProx = prox;
719 wacom->tool[0] = prox;
720 return 1; 791 return 1;
721 } 792 }
722 return 0; 793 return 0;
@@ -751,6 +822,7 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
751 return wacom_intuos_irq(wacom_wac, wcombo); 822 return wacom_intuos_irq(wacom_wac, wcombo);
752 823
753 case TABLETPC: 824 case TABLETPC:
825 case TABLETPC2FG:
754 return wacom_tpc_irq(wacom_wac, wcombo); 826 return wacom_tpc_irq(wacom_wac, wcombo);
755 827
756 default: 828 default:
@@ -791,9 +863,17 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w
791 input_dev_i4s(input_dev, wacom_wac); 863 input_dev_i4s(input_dev, wacom_wac);
792 input_dev_i(input_dev, wacom_wac); 864 input_dev_i(input_dev, wacom_wac);
793 break; 865 break;
866 case TABLETPC2FG:
867 input_dev_tpc2fg(input_dev, wacom_wac);
868 /* fall through */
869 case TABLETPC:
870 input_dev_tpc(input_dev, wacom_wac);
871 if (wacom_wac->features->device_type != BTN_TOOL_PEN)
872 break; /* no need to process stylus stuff */
873
874 /* fall through */
794 case PL: 875 case PL:
795 case PTU: 876 case PTU:
796 case TABLETPC:
797 input_dev_pl(input_dev, wacom_wac); 877 input_dev_pl(input_dev, wacom_wac);
798 /* fall through */ 878 /* fall through */
799 case PENPARTNER: 879 case PENPARTNER:
@@ -863,6 +943,9 @@ static struct wacom_features wacom_features[] = {
863 { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }, 943 { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC },
864 { "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }, 944 { "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC },
865 { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }, 945 { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC },
946 { "Wacom ISDv4 9F", WACOM_PKGLEN_PENABLED, 26202, 16325, 255, 0, TABLETPC },
947 { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG },
948 { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG },
866 { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }, 949 { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS },
867 { } 950 { }
868}; 951};
@@ -927,6 +1010,9 @@ static struct usb_device_id wacom_ids[] = {
927 { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) }, 1010 { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) },
928 { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) }, 1011 { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) },
929 { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) }, 1012 { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) },
1013 { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9F) },
1014 { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xE2) },
1015 { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xE3) },
930 { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, 1016 { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
931 { } 1017 { }
932}; 1018};
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index 1bfe9a3bae93..39c2516e3d31 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -19,7 +19,9 @@
19#define WACOM_PKGLEN_INTUOS 10 19#define WACOM_PKGLEN_INTUOS 10
20#define WACOM_PKGLEN_PENABLED 8 20#define WACOM_PKGLEN_PENABLED 8
21#define WACOM_PKGLEN_TPC1FG 5 21#define WACOM_PKGLEN_TPC1FG 5
22#define WACOM_PKGLEN_TPC2FG 14
22 23
24/* device IDs */
23#define STYLUS_DEVICE_ID 0x02 25#define STYLUS_DEVICE_ID 0x02
24#define TOUCH_DEVICE_ID 0x03 26#define TOUCH_DEVICE_ID 0x03
25#define CURSOR_DEVICE_ID 0x06 27#define CURSOR_DEVICE_ID 0x06
@@ -43,6 +45,7 @@ enum {
43 WACOM_BEE, 45 WACOM_BEE,
44 WACOM_MO, 46 WACOM_MO,
45 TABLETPC, 47 TABLETPC,
48 TABLETPC2FG,
46 MAX_TYPE 49 MAX_TYPE
47}; 50};
48 51
@@ -54,8 +57,11 @@ struct wacom_features {
54 int pressure_max; 57 int pressure_max;
55 int distance_max; 58 int distance_max;
56 int type; 59 int type;
57 int touch_x_max; 60 int device_type;
58 int touch_y_max; 61 int x_phy;
62 int y_phy;
63 unsigned char unit;
64 unsigned char unitExpo;
59}; 65};
60 66
61struct wacom_wac { 67struct wacom_wac {