aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikolai Kondrashov <spbnick@gmail.com>2012-05-14 13:30:38 -0400
committerJiri Kosina <jkosina@suse.cz>2012-05-15 03:50:19 -0400
commitd1257081aecf44455fcab8675f1d54e8b242faa1 (patch)
tree99b052b7952547859b0c8458a050c43becec5f59
parentbb2e19769533cc7c11257c67690358473099be9a (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.c1
-rw-r--r--drivers/hid/hid-ids.h1
-rw-r--r--drivers/hid/hid-uclogic.c141
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) */
367static __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) */
410static __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) */
447static __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
355static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, 469static __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};
407MODULE_DEVICE_TABLE(hid, uclogic_devices); 548MODULE_DEVICE_TABLE(hid, uclogic_devices);