Skip to content

Commit

Permalink
HID: waltop: Add support for tablet with PID 0038
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Nikolai Kondrashov authored and Jiri Kosina committed Mar 6, 2012
1 parent 56d27dd commit a786e83
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/hid/hid-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1566,6 +1566,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_Q_PAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_PID_0038) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_XAT, USB_DEVICE_ID_XAT_CSR) },
Expand Down
1 change: 1 addition & 0 deletions drivers/hid/hid-ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,7 @@
#define USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH 0x0032
#define USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH 0x0034
#define USB_DEVICE_ID_WALTOP_Q_PAD 0x0037
#define USB_DEVICE_ID_WALTOP_PID_0038 0x0038
#define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH 0x0501
#define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH 0x0500

Expand Down
148 changes: 148 additions & 0 deletions drivers/hid/hid-waltop.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,64 @@ static __u8 q_pad_rdesc_fixed[] = {
0xC0 /* End Collection */
};

/*
* See description, device and HID report descriptors of tablet with PID 0038 at
* http://sf.net/apps/mediawiki/digimend/?title=Waltop_PID_0038
*/

/* Size of the original report descriptor of tablet with PID 0038 */
#define PID_0038_RDESC_ORIG_SIZE 241

/*
* Fixed report descriptor for tablet with PID 0038.
*/
static __u8 pid_0038_rdesc_fixed[] = {
0x05, 0x0D, /* Usage Page (Digitizer), */
0x09, 0x02, /* Usage (Pen), */
0xA1, 0x01, /* Collection (Application), */
0x85, 0x10, /* Report ID (16), */
0x09, 0x20, /* Usage (Stylus), */
0xA0, /* Collection (Physical), */
0x09, 0x42, /* Usage (Tip Switch), */
0x09, 0x44, /* Usage (Barrel Switch), */
0x09, 0x46, /* Usage (Tablet Pick), */
0x15, 0x01, /* Logical Minimum (1), */
0x25, 0x03, /* Logical Maximum (3), */
0x75, 0x04, /* Report Size (4), */
0x95, 0x01, /* Report Count (1), */
0x80, /* Input, */
0x09, 0x32, /* Usage (In Range), */
0x14, /* Logical Minimum (0), */
0x25, 0x01, /* Logical Maximum (1), */
0x75, 0x01, /* Report Size (1), */
0x95, 0x01, /* Report Count (1), */
0x81, 0x02, /* Input (Variable), */
0x95, 0x03, /* Report Count (3), */
0x81, 0x03, /* Input (Constant, Variable), */
0x75, 0x10, /* Report Size (16), */
0x95, 0x01, /* Report Count (1), */
0x14, /* Logical Minimum (0), */
0xA4, /* Push, */
0x05, 0x01, /* Usage Page (Desktop), */
0x65, 0x13, /* Unit (Inch), */
0x55, 0xFD, /* Unit Exponent (-3), */
0x34, /* Physical Minimum (0), */
0x09, 0x30, /* Usage (X), */
0x46, 0x2E, 0x22, /* Physical Maximum (8750), */
0x26, 0x00, 0x46, /* Logical Maximum (17920), */
0x81, 0x02, /* Input (Variable), */
0x09, 0x31, /* Usage (Y), */
0x46, 0x82, 0x14, /* Physical Maximum (5250), */
0x26, 0x00, 0x2A, /* Logical Maximum (10752), */
0x81, 0x02, /* Input (Variable), */
0xB4, /* Pop, */
0x09, 0x30, /* Usage (Tip Pressure), */
0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
0x81, 0x02, /* Input (Variable), */
0xC0, /* End Collection, */
0xC0 /* End Collection */
};

/*
* See Media Tablet 10.6 inch description, device and HID report descriptors at
* http://sf.net/apps/mediawiki/digimend/?title=Waltop_Media_Tablet_10.6%22
Expand Down Expand Up @@ -444,6 +502,47 @@ static __u8 media_tablet_14_1_inch_rdesc_fixed[] = {
0xC0 /* End Collection */
};

struct waltop_state {
u8 pressure0;
u8 pressure1;
};

static int waltop_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
int ret;
struct waltop_state *s;

s = kzalloc(sizeof(*s), GFP_KERNEL);
if (s == NULL) {
hid_err(hdev, "can't allocate device state\n");
ret = -ENOMEM;
goto err;
}

s->pressure0 = 0;
s->pressure1 = 0;

hid_set_drvdata(hdev, s);

ret = hid_parse(hdev);
if (ret) {
hid_err(hdev, "parse failed\n");
goto err;
}

ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (ret) {
hid_err(hdev, "hw start failed\n");
goto err;
}

return 0;
err:
kfree(s);
return ret;
}

static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
Expand All @@ -466,6 +565,12 @@ static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc,
*rsize = sizeof(q_pad_rdesc_fixed);
}
break;
case USB_DEVICE_ID_WALTOP_PID_0038:
if (*rsize == PID_0038_RDESC_ORIG_SIZE) {
rdesc = pid_0038_rdesc_fixed;
*rsize = sizeof(pid_0038_rdesc_fixed);
}
break;
case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH:
if (*rsize == MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE) {
rdesc = media_tablet_10_6_inch_rdesc_fixed;
Expand All @@ -482,13 +587,53 @@ static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc,
return rdesc;
}

static int waltop_raw_event(struct hid_device *hdev, struct hid_report *report,
u8 *data, int size)
{
/* If this is a pen input report of a tablet with PID 0038 */
if (hdev->product == USB_DEVICE_ID_WALTOP_PID_0038 &&
report->type == HID_INPUT_REPORT &&
report->id == 16 &&
size == 8) {
struct waltop_state *s = hid_get_drvdata(hdev);

/*
* Ignore maximum pressure reported when a barrel button is
* pressed.
*/

/* If a barrel button is pressed */
if ((data[1] & 0xF) > 1) {
/* Use the last known pressure */
data[6] = s->pressure0;
data[7] = s->pressure1;
} else {
/* Remember reported pressure */
s->pressure0 = data[6];
s->pressure1 = data[7];
}
}

return 0;
}

static void waltop_remove(struct hid_device *hdev)
{
struct waltop_state *s = hid_get_drvdata(hdev);

hid_hw_stop(hdev);
kfree(s);
}

static const struct hid_device_id waltop_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
USB_DEVICE_ID_WALTOP_Q_PAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
USB_DEVICE_ID_WALTOP_PID_0038) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
Expand All @@ -500,7 +645,10 @@ MODULE_DEVICE_TABLE(hid, waltop_devices);
static struct hid_driver waltop_driver = {
.name = "waltop",
.id_table = waltop_devices,
.probe = waltop_probe,
.report_fixup = waltop_report_fixup,
.raw_event = waltop_raw_event,
.remove = waltop_remove,
};

static int __init waltop_init(void)
Expand Down

0 comments on commit a786e83

Please sign in to comment.