diff options
| author | Nikolai Kondrashov <spbnick@gmail.com> | 2012-05-14 13:30:38 -0400 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2012-05-15 03:50:19 -0400 |
| commit | d1257081aecf44455fcab8675f1d54e8b242faa1 (patch) | |
| tree | 99b052b7952547859b0c8458a050c43becec5f59 | |
| parent | bb2e19769533cc7c11257c67690358473099be9a (diff) | |
HID: uclogic: Add support for UC-Logic TWHL850
Add support for UC-Logic Wireless Tablet TWHL850.
It is known to be sold as Genius MousePen M508W.
This tablet has a bug in the default (compatibility) mode which is used in this
driver: frame button assignments are mixed up. This is to be fixed with a driver
supporting the vendor-specific protocol.
Signed-off-by: Nikolai Kondrashov <spbnick@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
| -rw-r--r-- | drivers/hid/hid-core.c | 1 | ||||
| -rw-r--r-- | drivers/hid/hid-ids.h | 1 | ||||
| -rw-r--r-- | drivers/hid/hid-uclogic.c | 141 |
3 files changed, 143 insertions, 0 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index dc05d9b5022b..4e57eeba9778 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -1576,6 +1576,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1576 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, | 1576 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, |
| 1577 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, | 1577 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, |
| 1578 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, | 1578 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, |
| 1579 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) }, | ||
| 1579 | { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) }, | 1580 | { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) }, |
| 1580 | { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) }, | 1581 | { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) }, |
| 1581 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, | 1582 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index df87fdbf70bf..635810ab915e 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
| @@ -717,6 +717,7 @@ | |||
| 717 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004 | 717 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004 |
| 718 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005 | 718 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005 |
| 719 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP1062 0x0064 | 719 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP1062 0x0064 |
| 720 | #define USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850 0x0522 | ||
| 720 | 721 | ||
| 721 | #define USB_VENDOR_ID_UNITEC 0x227d | 722 | #define USB_VENDOR_ID_UNITEC 0x227d |
| 722 | #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709 | 723 | #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709 |
diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c index 1f1128910337..3aba02be1f26 100644 --- a/drivers/hid/hid-uclogic.c +++ b/drivers/hid/hid-uclogic.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
| 15 | #include <linux/hid.h> | 15 | #include <linux/hid.h> |
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/usb.h> | ||
| 17 | 18 | ||
| 18 | #include "hid-ids.h" | 19 | #include "hid-ids.h" |
| 19 | 20 | ||
| @@ -352,9 +353,125 @@ static __u8 pf1209_rdesc_fixed[] = { | |||
| 352 | 0xC0 /* End Collection */ | 353 | 0xC0 /* End Collection */ |
| 353 | }; | 354 | }; |
| 354 | 355 | ||
| 356 | /* | ||
| 357 | * See TWHL850 description, device and HID report descriptors at | ||
| 358 | * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Wireless_Tablet_TWHL850 | ||
| 359 | */ | ||
| 360 | |||
| 361 | /* Size of the original descriptors of TWHL850 tablet */ | ||
| 362 | #define TWHL850_RDESC_ORIG_SIZE0 182 | ||
| 363 | #define TWHL850_RDESC_ORIG_SIZE1 161 | ||
| 364 | #define TWHL850_RDESC_ORIG_SIZE2 92 | ||
| 365 | |||
| 366 | /* Fixed PID 0522 tablet report descriptor, interface 0 (stylus) */ | ||
| 367 | static __u8 twhl850_rdesc_fixed0[] = { | ||
| 368 | 0x05, 0x0D, /* Usage Page (Digitizer), */ | ||
| 369 | 0x09, 0x02, /* Usage (Pen), */ | ||
| 370 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 371 | 0x85, 0x09, /* Report ID (9), */ | ||
| 372 | 0x09, 0x20, /* Usage (Stylus), */ | ||
| 373 | 0xA0, /* Collection (Physical), */ | ||
| 374 | 0x14, /* Logical Minimum (0), */ | ||
| 375 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 376 | 0x75, 0x01, /* Report Size (1), */ | ||
| 377 | 0x95, 0x03, /* Report Count (3), */ | ||
| 378 | 0x09, 0x42, /* Usage (Tip Switch), */ | ||
| 379 | 0x09, 0x44, /* Usage (Barrel Switch), */ | ||
| 380 | 0x09, 0x46, /* Usage (Tablet Pick), */ | ||
| 381 | 0x81, 0x02, /* Input (Variable), */ | ||
| 382 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 383 | 0x95, 0x01, /* Report Count (1), */ | ||
| 384 | 0x09, 0x32, /* Usage (In Range), */ | ||
| 385 | 0x81, 0x02, /* Input (Variable), */ | ||
| 386 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 387 | 0x75, 0x10, /* Report Size (16), */ | ||
| 388 | 0xA4, /* Push, */ | ||
| 389 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 390 | 0x65, 0x13, /* Unit (Inch), */ | ||
| 391 | 0x55, 0xFD, /* Unit Exponent (-3), */ | ||
| 392 | 0x34, /* Physical Minimum (0), */ | ||
| 393 | 0x09, 0x30, /* Usage (X), */ | ||
| 394 | 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */ | ||
| 395 | 0x26, 0x00, 0x7D, /* Logical Maximum (32000), */ | ||
| 396 | 0x81, 0x02, /* Input (Variable), */ | ||
| 397 | 0x09, 0x31, /* Usage (Y), */ | ||
| 398 | 0x46, 0x88, 0x13, /* Physical Maximum (5000), */ | ||
| 399 | 0x26, 0x20, 0x4E, /* Logical Maximum (20000), */ | ||
| 400 | 0x81, 0x02, /* Input (Variable), */ | ||
| 401 | 0xB4, /* Pop, */ | ||
| 402 | 0x09, 0x30, /* Usage (Tip Pressure), */ | ||
| 403 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
| 404 | 0x81, 0x02, /* Input (Variable), */ | ||
| 405 | 0xC0, /* End Collection, */ | ||
| 406 | 0xC0 /* End Collection */ | ||
| 407 | }; | ||
| 408 | |||
| 409 | /* Fixed PID 0522 tablet report descriptor, interface 1 (mouse) */ | ||
| 410 | static __u8 twhl850_rdesc_fixed1[] = { | ||
| 411 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 412 | 0x09, 0x02, /* Usage (Mouse), */ | ||
| 413 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 414 | 0x85, 0x01, /* Report ID (1), */ | ||
| 415 | 0x09, 0x01, /* Usage (Pointer), */ | ||
| 416 | 0xA0, /* Collection (Physical), */ | ||
| 417 | 0x05, 0x09, /* Usage Page (Button), */ | ||
| 418 | 0x75, 0x01, /* Report Size (1), */ | ||
| 419 | 0x95, 0x03, /* Report Count (3), */ | ||
| 420 | 0x19, 0x01, /* Usage Minimum (01h), */ | ||
| 421 | 0x29, 0x03, /* Usage Maximum (03h), */ | ||
| 422 | 0x14, /* Logical Minimum (0), */ | ||
| 423 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 424 | 0x81, 0x02, /* Input (Variable), */ | ||
| 425 | 0x95, 0x05, /* Report Count (5), */ | ||
| 426 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 427 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 428 | 0x09, 0x30, /* Usage (X), */ | ||
| 429 | 0x09, 0x31, /* Usage (Y), */ | ||
| 430 | 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ | ||
| 431 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | ||
| 432 | 0x75, 0x10, /* Report Size (16), */ | ||
| 433 | 0x95, 0x02, /* Report Count (2), */ | ||
| 434 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
| 435 | 0x09, 0x38, /* Usage (Wheel), */ | ||
| 436 | 0x15, 0xFF, /* Logical Minimum (-1), */ | ||
| 437 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 438 | 0x95, 0x01, /* Report Count (1), */ | ||
| 439 | 0x75, 0x08, /* Report Size (8), */ | ||
| 440 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
| 441 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 442 | 0xC0, /* End Collection, */ | ||
| 443 | 0xC0 /* End Collection */ | ||
| 444 | }; | ||
| 445 | |||
| 446 | /* Fixed PID 0522 tablet report descriptor, interface 2 (frame buttons) */ | ||
| 447 | static __u8 twhl850_rdesc_fixed2[] = { | ||
| 448 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 449 | 0x09, 0x06, /* Usage (Keyboard), */ | ||
| 450 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 451 | 0x85, 0x03, /* Report ID (3), */ | ||
| 452 | 0x05, 0x07, /* Usage Page (Keyboard), */ | ||
| 453 | 0x14, /* Logical Minimum (0), */ | ||
| 454 | 0x19, 0xE0, /* Usage Minimum (KB Leftcontrol), */ | ||
| 455 | 0x29, 0xE7, /* Usage Maximum (KB Right GUI), */ | ||
| 456 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 457 | 0x75, 0x01, /* Report Size (1), */ | ||
| 458 | 0x95, 0x08, /* Report Count (8), */ | ||
| 459 | 0x81, 0x02, /* Input (Variable), */ | ||
| 460 | 0x18, /* Usage Minimum (None), */ | ||
| 461 | 0x29, 0xFF, /* Usage Maximum (FFh), */ | ||
| 462 | 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | ||
| 463 | 0x75, 0x08, /* Report Size (8), */ | ||
| 464 | 0x95, 0x06, /* Report Count (6), */ | ||
| 465 | 0x80, /* Input, */ | ||
| 466 | 0xC0 /* End Collection */ | ||
| 467 | }; | ||
| 468 | |||
| 355 | static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 469 | static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 356 | unsigned int *rsize) | 470 | unsigned int *rsize) |
| 357 | { | 471 | { |
| 472 | struct usb_interface *iface = to_usb_interface(hdev->dev.parent); | ||
| 473 | __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber; | ||
| 474 | |||
| 358 | switch (hdev->product) { | 475 | switch (hdev->product) { |
| 359 | case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209: | 476 | case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209: |
| 360 | if (*rsize == PF1209_RDESC_ORIG_SIZE) { | 477 | if (*rsize == PF1209_RDESC_ORIG_SIZE) { |
| @@ -386,6 +503,28 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
| 386 | *rsize = sizeof(wp1062_rdesc_fixed); | 503 | *rsize = sizeof(wp1062_rdesc_fixed); |
| 387 | } | 504 | } |
| 388 | break; | 505 | break; |
| 506 | case USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850: | ||
| 507 | switch (iface_num) { | ||
| 508 | case 0: | ||
| 509 | if (*rsize == TWHL850_RDESC_ORIG_SIZE0) { | ||
| 510 | rdesc = twhl850_rdesc_fixed0; | ||
| 511 | *rsize = sizeof(twhl850_rdesc_fixed0); | ||
| 512 | } | ||
| 513 | break; | ||
| 514 | case 1: | ||
| 515 | if (*rsize == TWHL850_RDESC_ORIG_SIZE1) { | ||
| 516 | rdesc = twhl850_rdesc_fixed1; | ||
| 517 | *rsize = sizeof(twhl850_rdesc_fixed1); | ||
| 518 | } | ||
| 519 | break; | ||
| 520 | case 2: | ||
| 521 | if (*rsize == TWHL850_RDESC_ORIG_SIZE2) { | ||
| 522 | rdesc = twhl850_rdesc_fixed2; | ||
| 523 | *rsize = sizeof(twhl850_rdesc_fixed2); | ||
| 524 | } | ||
| 525 | break; | ||
| 526 | } | ||
| 527 | break; | ||
| 389 | } | 528 | } |
| 390 | 529 | ||
| 391 | return rdesc; | 530 | return rdesc; |
| @@ -402,6 +541,8 @@ static const struct hid_device_id uclogic_devices[] = { | |||
| 402 | USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, | 541 | USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, |
| 403 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, | 542 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, |
| 404 | USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, | 543 | USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, |
| 544 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, | ||
| 545 | USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) }, | ||
| 405 | { } | 546 | { } |
| 406 | }; | 547 | }; |
| 407 | MODULE_DEVICE_TABLE(hid, uclogic_devices); | 548 | MODULE_DEVICE_TABLE(hid, uclogic_devices); |
