diff options
author | Nikolai Kondrashov <spbnick@gmail.com> | 2012-03-06 02:54:24 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2012-03-06 05:20:55 -0500 |
commit | a786e83cb088f1afcd1d55e44efd4b89d78c32d1 (patch) | |
tree | 08fc229f20024d1ffbd386221d0ad01aa155a7d8 /drivers/hid/hid-waltop.c | |
parent | 56d27dd6ec6e832b3b22b0c0fab960476b9694fc (diff) |
HID: waltop: Add support for tablet with PID 0038
Add support for unknown Waltop tablet with product ID 0x0038.
This tablet is sold as Genius G-Pen F509.
Signed-off-by: Nikolai Kondrashov <spbnick@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-waltop.c')
-rw-r--r-- | drivers/hid/hid-waltop.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/drivers/hid/hid-waltop.c b/drivers/hid/hid-waltop.c index c1dce51b1c1e..2cfd95c4467b 100644 --- a/drivers/hid/hid-waltop.c +++ b/drivers/hid/hid-waltop.c | |||
@@ -211,6 +211,64 @@ static __u8 q_pad_rdesc_fixed[] = { | |||
211 | }; | 211 | }; |
212 | 212 | ||
213 | /* | 213 | /* |
214 | * See description, device and HID report descriptors of tablet with PID 0038 at | ||
215 | * http://sf.net/apps/mediawiki/digimend/?title=Waltop_PID_0038 | ||
216 | */ | ||
217 | |||
218 | /* Size of the original report descriptor of tablet with PID 0038 */ | ||
219 | #define PID_0038_RDESC_ORIG_SIZE 241 | ||
220 | |||
221 | /* | ||
222 | * Fixed report descriptor for tablet with PID 0038. | ||
223 | */ | ||
224 | static __u8 pid_0038_rdesc_fixed[] = { | ||
225 | 0x05, 0x0D, /* Usage Page (Digitizer), */ | ||
226 | 0x09, 0x02, /* Usage (Pen), */ | ||
227 | 0xA1, 0x01, /* Collection (Application), */ | ||
228 | 0x85, 0x10, /* Report ID (16), */ | ||
229 | 0x09, 0x20, /* Usage (Stylus), */ | ||
230 | 0xA0, /* Collection (Physical), */ | ||
231 | 0x09, 0x42, /* Usage (Tip Switch), */ | ||
232 | 0x09, 0x44, /* Usage (Barrel Switch), */ | ||
233 | 0x09, 0x46, /* Usage (Tablet Pick), */ | ||
234 | 0x15, 0x01, /* Logical Minimum (1), */ | ||
235 | 0x25, 0x03, /* Logical Maximum (3), */ | ||
236 | 0x75, 0x04, /* Report Size (4), */ | ||
237 | 0x95, 0x01, /* Report Count (1), */ | ||
238 | 0x80, /* Input, */ | ||
239 | 0x09, 0x32, /* Usage (In Range), */ | ||
240 | 0x14, /* Logical Minimum (0), */ | ||
241 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
242 | 0x75, 0x01, /* Report Size (1), */ | ||
243 | 0x95, 0x01, /* Report Count (1), */ | ||
244 | 0x81, 0x02, /* Input (Variable), */ | ||
245 | 0x95, 0x03, /* Report Count (3), */ | ||
246 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
247 | 0x75, 0x10, /* Report Size (16), */ | ||
248 | 0x95, 0x01, /* Report Count (1), */ | ||
249 | 0x14, /* Logical Minimum (0), */ | ||
250 | 0xA4, /* Push, */ | ||
251 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
252 | 0x65, 0x13, /* Unit (Inch), */ | ||
253 | 0x55, 0xFD, /* Unit Exponent (-3), */ | ||
254 | 0x34, /* Physical Minimum (0), */ | ||
255 | 0x09, 0x30, /* Usage (X), */ | ||
256 | 0x46, 0x2E, 0x22, /* Physical Maximum (8750), */ | ||
257 | 0x26, 0x00, 0x46, /* Logical Maximum (17920), */ | ||
258 | 0x81, 0x02, /* Input (Variable), */ | ||
259 | 0x09, 0x31, /* Usage (Y), */ | ||
260 | 0x46, 0x82, 0x14, /* Physical Maximum (5250), */ | ||
261 | 0x26, 0x00, 0x2A, /* Logical Maximum (10752), */ | ||
262 | 0x81, 0x02, /* Input (Variable), */ | ||
263 | 0xB4, /* Pop, */ | ||
264 | 0x09, 0x30, /* Usage (Tip Pressure), */ | ||
265 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
266 | 0x81, 0x02, /* Input (Variable), */ | ||
267 | 0xC0, /* End Collection, */ | ||
268 | 0xC0 /* End Collection */ | ||
269 | }; | ||
270 | |||
271 | /* | ||
214 | * See Media Tablet 10.6 inch description, device and HID report descriptors at | 272 | * See Media Tablet 10.6 inch description, device and HID report descriptors at |
215 | * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Media_Tablet_10.6%22 | 273 | * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Media_Tablet_10.6%22 |
216 | */ | 274 | */ |
@@ -444,6 +502,47 @@ static __u8 media_tablet_14_1_inch_rdesc_fixed[] = { | |||
444 | 0xC0 /* End Collection */ | 502 | 0xC0 /* End Collection */ |
445 | }; | 503 | }; |
446 | 504 | ||
505 | struct waltop_state { | ||
506 | u8 pressure0; | ||
507 | u8 pressure1; | ||
508 | }; | ||
509 | |||
510 | static int waltop_probe(struct hid_device *hdev, | ||
511 | const struct hid_device_id *id) | ||
512 | { | ||
513 | int ret; | ||
514 | struct waltop_state *s; | ||
515 | |||
516 | s = kzalloc(sizeof(*s), GFP_KERNEL); | ||
517 | if (s == NULL) { | ||
518 | hid_err(hdev, "can't allocate device state\n"); | ||
519 | ret = -ENOMEM; | ||
520 | goto err; | ||
521 | } | ||
522 | |||
523 | s->pressure0 = 0; | ||
524 | s->pressure1 = 0; | ||
525 | |||
526 | hid_set_drvdata(hdev, s); | ||
527 | |||
528 | ret = hid_parse(hdev); | ||
529 | if (ret) { | ||
530 | hid_err(hdev, "parse failed\n"); | ||
531 | goto err; | ||
532 | } | ||
533 | |||
534 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
535 | if (ret) { | ||
536 | hid_err(hdev, "hw start failed\n"); | ||
537 | goto err; | ||
538 | } | ||
539 | |||
540 | return 0; | ||
541 | err: | ||
542 | kfree(s); | ||
543 | return ret; | ||
544 | } | ||
545 | |||
447 | static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 546 | static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
448 | unsigned int *rsize) | 547 | unsigned int *rsize) |
449 | { | 548 | { |
@@ -466,6 +565,12 @@ static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
466 | *rsize = sizeof(q_pad_rdesc_fixed); | 565 | *rsize = sizeof(q_pad_rdesc_fixed); |
467 | } | 566 | } |
468 | break; | 567 | break; |
568 | case USB_DEVICE_ID_WALTOP_PID_0038: | ||
569 | if (*rsize == PID_0038_RDESC_ORIG_SIZE) { | ||
570 | rdesc = pid_0038_rdesc_fixed; | ||
571 | *rsize = sizeof(pid_0038_rdesc_fixed); | ||
572 | } | ||
573 | break; | ||
469 | case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH: | 574 | case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH: |
470 | if (*rsize == MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE) { | 575 | if (*rsize == MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE) { |
471 | rdesc = media_tablet_10_6_inch_rdesc_fixed; | 576 | rdesc = media_tablet_10_6_inch_rdesc_fixed; |
@@ -482,6 +587,44 @@ static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
482 | return rdesc; | 587 | return rdesc; |
483 | } | 588 | } |
484 | 589 | ||
590 | static int waltop_raw_event(struct hid_device *hdev, struct hid_report *report, | ||
591 | u8 *data, int size) | ||
592 | { | ||
593 | /* If this is a pen input report of a tablet with PID 0038 */ | ||
594 | if (hdev->product == USB_DEVICE_ID_WALTOP_PID_0038 && | ||
595 | report->type == HID_INPUT_REPORT && | ||
596 | report->id == 16 && | ||
597 | size == 8) { | ||
598 | struct waltop_state *s = hid_get_drvdata(hdev); | ||
599 | |||
600 | /* | ||
601 | * Ignore maximum pressure reported when a barrel button is | ||
602 | * pressed. | ||
603 | */ | ||
604 | |||
605 | /* If a barrel button is pressed */ | ||
606 | if ((data[1] & 0xF) > 1) { | ||
607 | /* Use the last known pressure */ | ||
608 | data[6] = s->pressure0; | ||
609 | data[7] = s->pressure1; | ||
610 | } else { | ||
611 | /* Remember reported pressure */ | ||
612 | s->pressure0 = data[6]; | ||
613 | s->pressure1 = data[7]; | ||
614 | } | ||
615 | } | ||
616 | |||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | static void waltop_remove(struct hid_device *hdev) | ||
621 | { | ||
622 | struct waltop_state *s = hid_get_drvdata(hdev); | ||
623 | |||
624 | hid_hw_stop(hdev); | ||
625 | kfree(s); | ||
626 | } | ||
627 | |||
485 | static const struct hid_device_id waltop_devices[] = { | 628 | static const struct hid_device_id waltop_devices[] = { |
486 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, | 629 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, |
487 | USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, | 630 | USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, |
@@ -490,6 +633,8 @@ static const struct hid_device_id waltop_devices[] = { | |||
490 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, | 633 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, |
491 | USB_DEVICE_ID_WALTOP_Q_PAD) }, | 634 | USB_DEVICE_ID_WALTOP_Q_PAD) }, |
492 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, | 635 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, |
636 | USB_DEVICE_ID_WALTOP_PID_0038) }, | ||
637 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, | ||
493 | USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, | 638 | USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, |
494 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, | 639 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, |
495 | USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, | 640 | USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, |
@@ -500,7 +645,10 @@ MODULE_DEVICE_TABLE(hid, waltop_devices); | |||
500 | static struct hid_driver waltop_driver = { | 645 | static struct hid_driver waltop_driver = { |
501 | .name = "waltop", | 646 | .name = "waltop", |
502 | .id_table = waltop_devices, | 647 | .id_table = waltop_devices, |
648 | .probe = waltop_probe, | ||
503 | .report_fixup = waltop_report_fixup, | 649 | .report_fixup = waltop_report_fixup, |
650 | .raw_event = waltop_raw_event, | ||
651 | .remove = waltop_remove, | ||
504 | }; | 652 | }; |
505 | 653 | ||
506 | static int __init waltop_init(void) | 654 | static int __init waltop_init(void) |