aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-waltop.c
diff options
context:
space:
mode:
authorNikolai Kondrashov <spbnick@gmail.com>2012-03-06 02:54:24 -0500
committerJiri Kosina <jkosina@suse.cz>2012-03-06 05:20:55 -0500
commita786e83cb088f1afcd1d55e44efd4b89d78c32d1 (patch)
tree08fc229f20024d1ffbd386221d0ad01aa155a7d8 /drivers/hid/hid-waltop.c
parent56d27dd6ec6e832b3b22b0c0fab960476b9694fc (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.c148
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 */
224static __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
505struct waltop_state {
506 u8 pressure0;
507 u8 pressure1;
508};
509
510static 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;
541err:
542 kfree(s);
543 return ret;
544}
545
447static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc, 546static __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
590static 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
620static 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
485static const struct hid_device_id waltop_devices[] = { 628static 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);
500static struct hid_driver waltop_driver = { 645static 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
506static int __init waltop_init(void) 654static int __init waltop_init(void)