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