X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Finput%2Fwacom.c;h=cf84c6096f299721be8c24cb66d8baa9d43aad45;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=fec04dda088ea0edac8181912684337df12206a5;hpb=cee37fe97739d85991964371c1f3a745c00dd236;p=linux-2.6.git diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index fec04dda0..cf84c6096 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c @@ -9,7 +9,7 @@ * Copyright (c) 2000 Daniel Egger * Copyright (c) 2001 Frederic Lepied * Copyright (c) 2004 Panagiotis Issaris - * Copyright (c) 2002-2004 Ping Cheng + * Copyright (c) 2002-2006 Ping Cheng * * ChangeLog: * v0.1 (vp) - Initial release @@ -18,7 +18,7 @@ * v0.4 (sm) - Support for more Intuos models, menustrip * relative mode, proximity. * v0.5 (vp) - Big cleanup, nifty features removed, - * they belong in userspace + * they belong in userspace * v1.8 (vp) - Submit URB only when operating, moved to CVS, * use input_report_key instead of report_btn and * other cleanups @@ -51,6 +51,13 @@ * - Cleanups here and there * v1.30.1 (pi) - Added Graphire3 support * v1.40 (pc) - Add support for several new devices, fix eraser reporting, ... + * v1.43 (pc) - Added support for Cintiq 21UX + * - Fixed a Graphire bug + * - Merged wacom_intuos3_irq into wacom_intuos_irq + * v1.44 (pc) - Added support for Graphire4, Cintiq 710, Intuos3 6x11, etc. + * - Report Device IDs + * v1.45 (pc) - Added support for DTF 521, Intuos3 12x12 and 12x19 + * - Minor data report fix */ /* @@ -66,13 +73,14 @@ #include #include #include +#include #include #include /* * Version Information */ -#define DRIVER_VERSION "v1.40" +#define DRIVER_VERSION "v1.45" #define DRIVER_AUTHOR "Vojtech Pavlik " #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" #define DRIVER_LICENSE "GPL" @@ -82,6 +90,22 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE(DRIVER_LICENSE); #define USB_VENDOR_ID_WACOM 0x056a +#define STYLUS_DEVICE_ID 0x02 +#define CURSOR_DEVICE_ID 0x06 +#define ERASER_DEVICE_ID 0x0A + +enum { + PENPARTNER = 0, + GRAPHIRE, + WACOM_G4, + PL, + INTUOS, + INTUOS3, + INTUOS312, + INTUOS319, + CINTIQ, + MAX_TYPE +}; struct wacom_features { char *name; @@ -97,17 +121,29 @@ struct wacom_features { struct wacom { signed char *data; dma_addr_t data_dma; - struct input_dev dev; + struct input_dev *dev; struct usb_device *usbdev; struct urb *irq; struct wacom_features *features; int tool[2]; - int open; + int id[2]; __u32 serial[2]; char phys[32]; }; +#define USB_REQ_GET_REPORT 0x01 #define USB_REQ_SET_REPORT 0x09 + +static int usb_get_report(struct usb_interface *intf, unsigned char type, + unsigned char id, void *buf, int size) +{ + return usb_control_msg(interface_to_usbdev(intf), + usb_rcvctrlpipe(interface_to_usbdev(intf), 0), + USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, + (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber, + buf, size, 100); +} + static int usb_set_report(struct usb_interface *intf, unsigned char type, unsigned char id, void *buf, int size) { @@ -122,8 +158,8 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) { struct wacom *wacom = urb->context; unsigned char *data = wacom->data; - struct input_dev *dev = &wacom->dev; - int prox, pressure; + struct input_dev *dev = wacom->dev; + int prox, pressure, id; int retval; switch (urb->status) { @@ -149,7 +185,8 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) prox = data[1] & 0x40; input_regs(dev, regs); - + + id = ERASER_DEVICE_ID; if (prox) { pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); @@ -164,12 +201,15 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) * an out of proximity for previous tool then a in for new tool. */ if (!wacom->tool[0]) { - /* Going into proximity select tool */ - wacom->tool[1] = (data[4] & 0x20)? BTN_TOOL_RUBBER : BTN_TOOL_PEN; - } - else { + /* Eraser bit set for DTF */ + if (data[1] & 0x10) + wacom->tool[1] = BTN_TOOL_RUBBER; + else + /* Going into proximity select tool */ + wacom->tool[1] = (data[4] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; + } else { /* was entered with stylus2 pressed */ - if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20) ) { + if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) { /* report out proximity for previous tool */ input_report_key(dev, wacom->tool[1], 0); input_sync(dev); @@ -180,18 +220,19 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) if (wacom->tool[1] != BTN_TOOL_RUBBER) { /* Unknown tool selected default to pen tool */ wacom->tool[1] = BTN_TOOL_PEN; + id = STYLUS_DEVICE_ID; } input_report_key(dev, wacom->tool[1], prox); /* report in proximity for tool */ - input_report_abs(dev, ABS_X, data[3] | ((__u32)data[2] << 7) | ((__u32)(data[1] & 0x03) << 14)); - input_report_abs(dev, ABS_Y, data[6] | ((__u32)data[5] << 7) | ((__u32)(data[4] & 0x03) << 14)); + input_report_abs(dev, ABS_MISC, id); /* report tool id */ + input_report_abs(dev, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14)); + input_report_abs(dev, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14)); input_report_abs(dev, ABS_PRESSURE, pressure); input_report_key(dev, BTN_TOUCH, data[4] & 0x08); input_report_key(dev, BTN_STYLUS, data[4] & 0x10); /* Only allow the stylus2 button to be reported for the pen tool. */ input_report_key(dev, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20)); - } - else { + } else { /* report proximity-out of a (valid) tool */ if (wacom->tool[1] != BTN_TOOL_RUBBER) { /* Unknown tool selected default to pen tool */ @@ -203,7 +244,7 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) wacom->tool[0] = prox; /* Save proximity state */ input_sync(dev); -exit: + exit: retval = usb_submit_urb (urb, GFP_ATOMIC); if (retval) err ("%s - usb_submit_urb failed with result %d", @@ -214,8 +255,8 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs) { struct wacom *wacom = urb->context; unsigned char *data = wacom->data; - struct input_dev *dev = &wacom->dev; - int retval; + struct input_dev *dev = wacom->dev; + int retval, id; switch (urb->status) { case 0: @@ -232,23 +273,22 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs) goto exit; } - if (data[0] != 2) - { + if (data[0] != 2) { printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); goto exit; } input_regs(dev, regs); - if (data[1] & 0x04) - { + if (data[1] & 0x04) { input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x20); input_report_key(dev, BTN_TOUCH, data[1] & 0x08); - } - else - { + id = ERASER_DEVICE_ID; + } else { input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20); input_report_key(dev, BTN_TOUCH, data[1] & 0x01); + id = STYLUS_DEVICE_ID; } + input_report_abs(dev, ABS_MISC, id); /* report tool id */ input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[2])); input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[4])); input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6])); @@ -257,7 +297,7 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs) input_sync(dev); -exit: + exit: retval = usb_submit_urb (urb, GFP_ATOMIC); if (retval) err ("%s - usb_submit_urb failed with result %d", @@ -268,7 +308,7 @@ static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs) { struct wacom *wacom = urb->context; unsigned char *data = wacom->data; - struct input_dev *dev = &wacom->dev; + struct input_dev *dev = wacom->dev; int retval; switch (urb->status) { @@ -293,6 +333,7 @@ static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs) input_regs(dev, regs); input_report_key(dev, BTN_TOOL_PEN, 1); + input_report_abs(dev, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */ input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[1])); input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[3])); input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127); @@ -300,7 +341,7 @@ static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs) input_report_key(dev, BTN_STYLUS, (data[5] & 0x40)); input_sync(dev); -exit: + exit: retval = usb_submit_urb (urb, GFP_ATOMIC); if (retval) err ("%s - usb_submit_urb failed with result %d", @@ -311,8 +352,8 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) { struct wacom *wacom = urb->context; unsigned char *data = wacom->data; - struct input_dev *dev = &wacom->dev; - int x, y; + struct input_dev *dev = wacom->dev; + int x, y, id, rw; int retval; switch (urb->status) { @@ -330,57 +371,90 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) goto exit; } + if (data[0] == 99) return; /* for Volito tablets */ + if (data[0] != 2) { dbg("wacom_graphire_irq: received unknown report #%d", data[0]); goto exit; } - x = le16_to_cpu(*(__le16 *) &data[2]); - y = le16_to_cpu(*(__le16 *) &data[4]); - input_regs(dev, regs); - switch ((data[1] >> 5) & 3) { + id = STYLUS_DEVICE_ID; + if (data[1] & 0x10) { /* in prox */ - case 0: /* Pen */ - input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x80); - break; + switch ((data[1] >> 5) & 3) { - case 1: /* Rubber */ - input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x80); - break; - - case 2: /* Mouse with wheel */ - input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); - input_report_rel(dev, REL_WHEEL, (signed char) data[6]); - /* fall through */ - - case 3: /* Mouse without wheel */ - input_report_key(dev, BTN_TOOL_MOUSE, data[7] > 24); - input_report_key(dev, BTN_LEFT, data[1] & 0x01); - input_report_key(dev, BTN_RIGHT, data[1] & 0x02); - input_report_abs(dev, ABS_DISTANCE, data[7]); + case 0: /* Pen */ + wacom->tool[0] = BTN_TOOL_PEN; + break; - input_report_abs(dev, ABS_X, x); - input_report_abs(dev, ABS_Y, y); + case 1: /* Rubber */ + wacom->tool[0] = BTN_TOOL_RUBBER; + id = ERASER_DEVICE_ID; + break; - input_sync(dev); - goto exit; + case 2: /* Mouse with wheel */ + input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); + if (wacom->features->type == WACOM_G4) { + rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03); + input_report_rel(dev, REL_WHEEL, -rw); + } else + input_report_rel(dev, REL_WHEEL, -(signed char) data[6]); + /* fall through */ + + case 3: /* Mouse without wheel */ + wacom->tool[0] = BTN_TOOL_MOUSE; + id = CURSOR_DEVICE_ID; + input_report_key(dev, BTN_LEFT, data[1] & 0x01); + input_report_key(dev, BTN_RIGHT, data[1] & 0x02); + if (wacom->features->type == WACOM_G4) + input_report_abs(dev, ABS_DISTANCE, data[6]); + else + input_report_abs(dev, ABS_DISTANCE, data[7]); + break; + } } - if (data[1] & 0x80) { + if (data[1] & 0x90) { + x = le16_to_cpu(*(__le16 *) &data[2]); + y = le16_to_cpu(*(__le16 *) &data[4]); input_report_abs(dev, ABS_X, x); input_report_abs(dev, ABS_Y, y); + if (wacom->tool[0] != BTN_TOOL_MOUSE) { + input_report_abs(dev, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8)); + input_report_key(dev, BTN_TOUCH, data[1] & 0x01); + input_report_key(dev, BTN_STYLUS, data[1] & 0x02); + input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); + } } - input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6])); - input_report_key(dev, BTN_TOUCH, data[1] & 0x01); - input_report_key(dev, BTN_STYLUS, data[1] & 0x02); - input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); - + if (data[1] & 0x10) + input_report_abs(dev, ABS_MISC, id); /* report tool id */ + else + input_report_abs(dev, ABS_MISC, 0); /* reset tool id */ + input_report_key(dev, wacom->tool[0], data[1] & 0x10); input_sync(dev); -exit: + /* send pad data */ + if (wacom->features->type == WACOM_G4) { + if ((wacom->serial[1] & 0xc0) != (data[7] & 0xf8)) { + wacom->id[1] = 1; + wacom->serial[1] = (data[7] & 0xf8); + input_report_key(dev, BTN_0, (data[7] & 0x40)); + input_report_key(dev, BTN_4, (data[7] & 0x80)); + rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); + input_report_rel(dev, REL_WHEEL, rw); + input_report_key(dev, BTN_TOOL_FINGER, 0xf0); + input_event(dev, EV_MSC, MSC_SERIAL, 0xf0); + } else if (wacom->id[1]) { + wacom->id[1] = 0; + input_report_key(dev, BTN_TOOL_FINGER, 0); + input_event(dev, EV_MSC, MSC_SERIAL, 0xf0); + } + input_sync(dev); + } + exit: retval = usb_submit_urb (urb, GFP_ATOMIC); if (retval) err ("%s - usb_submit_urb failed with result %d", @@ -391,21 +465,21 @@ static int wacom_intuos_inout(struct urb *urb) { struct wacom *wacom = urb->context; unsigned char *data = wacom->data; - struct input_dev *dev = &wacom->dev; + struct input_dev *dev = wacom->dev; int idx; /* tool number */ idx = data[1] & 0x01; /* Enter report */ - if ((data[1] & 0xfc) == 0xc0) - { + if ((data[1] & 0xfc) == 0xc0) { /* serial number of the tool */ - wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 28) + - ((__u32)data[4] << 20) + ((__u32)data[5] << 12) + - ((__u32)data[6] << 4) + (data[7] >> 4); + wacom->serial[idx] = ((data[3] & 0x0f) << 28) + + (data[4] << 20) + (data[5] << 12) + + (data[6] << 4) + (data[7] >> 4); - switch (((__u32)data[2] << 4) | (data[3] >> 4)) { + wacom->id[idx] = (data[2] << 4) | (data[3] >> 4); + switch (wacom->id[idx]) { case 0x812: /* Inking pen */ case 0x801: /* Intuos3 Inking pen */ case 0x012: @@ -449,38 +523,47 @@ static int wacom_intuos_inout(struct urb *urb) case 0x112: case 0x913: /* Intuos3 Airbrush */ wacom->tool[idx] = BTN_TOOL_AIRBRUSH; - break; /* Airbrush */ + break; default: /* Unknown tool */ wacom->tool[idx] = BTN_TOOL_PEN; } - input_report_key(dev, wacom->tool[idx], 1); - input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); - input_sync(dev); + if(!((wacom->tool[idx] == BTN_TOOL_LENS) && + ((wacom->features->type == INTUOS312) + || (wacom->features->type == INTUOS319)))) { + input_report_abs(dev, ABS_MISC, wacom->id[idx]); /* report tool id */ + input_report_key(dev, wacom->tool[idx], 1); + input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); + input_sync(dev); + } return 1; } /* Exit report */ if ((data[1] & 0xfe) == 0x80) { input_report_key(dev, wacom->tool[idx], 0); + input_report_abs(dev, ABS_MISC, 0); /* reset tool id */ input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); input_sync(dev); return 1; } - return 0; + if((wacom->tool[idx] == BTN_TOOL_LENS) && ((wacom->features->type == INTUOS312) + || (wacom->features->type == INTUOS319))) + return 1; + else + return 0; } static void wacom_intuos_general(struct urb *urb) { struct wacom *wacom = urb->context; unsigned char *data = wacom->data; - struct input_dev *dev = &wacom->dev; + struct input_dev *dev = wacom->dev; unsigned int t; /* general pen packet */ - if ((data[1] & 0xb8) == 0xa0) - { - t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3); + if ((data[1] & 0xb8) == 0xa0) { + t = (data[6] << 2) | ((data[7] >> 6) & 3); input_report_abs(dev, ABS_PRESSURE, t); input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7)); @@ -491,10 +574,9 @@ static void wacom_intuos_general(struct urb *urb) } /* airbrush second packet */ - if ((data[1] & 0xbc) == 0xb4) - { + if ((data[1] & 0xbc) == 0xb4) { input_report_abs(dev, ABS_WHEEL, - ((__u32)data[6] << 2) | ((data[7] >> 6) & 3)); + (data[6] << 2) | ((data[7] >> 6) & 3)); input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7)); input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f); @@ -506,7 +588,7 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) { struct wacom *wacom = urb->context; unsigned char *data = wacom->data; - struct input_dev *dev = &wacom->dev; + struct input_dev *dev = wacom->dev; unsigned int t; int idx; int retval; @@ -526,7 +608,7 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) goto exit; } - if (data[0] != 2 && data[0] != 5 && data[0] != 6) { + if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) { dbg("wacom_intuos_irq: received unknown report #%d", data[0]); goto exit; } @@ -536,110 +618,12 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) /* tool number */ idx = data[1] & 0x01; - /* process in/out prox events */ - if (wacom_intuos_inout(urb)) goto exit; - - input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2])); - input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4])); - input_report_abs(dev, ABS_DISTANCE, data[9]); - - /* process general packets */ - wacom_intuos_general(urb); - - if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { /* 4D mouse or Lens cursor packets */ - - if (data[1] & 0x02) { /* Rotation packet */ - - t = ((__u32)data[6] << 3) | ((data[7] >> 5) & 7); - input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ? ((t - 1) / 2) : -t / 2); - - } else { - - if ((data[1] & 0x10) == 0) { /* 4D mouse packets */ - - input_report_key(dev, BTN_LEFT, data[8] & 0x01); - input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); - input_report_key(dev, BTN_RIGHT, data[8] & 0x04); - - input_report_key(dev, BTN_SIDE, data[8] & 0x20); - input_report_key(dev, BTN_EXTRA, data[8] & 0x10); - t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3); - input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); - - } else { - if (wacom->tool[idx] == BTN_TOOL_MOUSE) { /* 2D mouse packets */ - input_report_key(dev, BTN_LEFT, data[8] & 0x04); - input_report_key(dev, BTN_MIDDLE, data[8] & 0x08); - input_report_key(dev, BTN_RIGHT, data[8] & 0x10); - input_report_rel(dev, REL_WHEEL, - (-(__u32)(data[8] & 0x01) + (__u32)((data[8] & 0x02) >> 1))); - } - else { /* Lens cursor packets */ - input_report_key(dev, BTN_LEFT, data[8] & 0x01); - input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); - input_report_key(dev, BTN_RIGHT, data[8] & 0x04); - input_report_key(dev, BTN_SIDE, data[8] & 0x10); - input_report_key(dev, BTN_EXTRA, data[8] & 0x08); - } - } - } - } - - input_report_key(dev, wacom->tool[idx], 1); - input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); - input_sync(dev); - -exit: - retval = usb_submit_urb (urb, GFP_ATOMIC); - if (retval) - err ("%s - usb_submit_urb failed with result %d", - __FUNCTION__, retval); -} - -static void wacom_intuos3_irq(struct urb *urb, struct pt_regs *regs) -{ - struct wacom *wacom = urb->context; - unsigned char *data = wacom->data; - struct input_dev *dev = &wacom->dev; - unsigned int t; - int idx, retval; - - switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); - return; - default: - dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); - goto exit; - } - - /* check for valid report */ - if (data[0] != 2 && data[0] != 5 && data[0] != 12) - { - printk(KERN_INFO "wacom_intuos3_irq: received unknown report #%d\n", data[0]); - goto exit; - } - - input_regs(dev, regs); - - /* tool index is always 0 here since there is no dual input tool */ - idx = data[1] & 0x01; - /* pad packets. Works as a second tool and is always in prox */ - if (data[0] == 12) - { + if (data[0] == 12) { /* initiate the pad as a device */ if (wacom->tool[1] != BTN_TOOL_FINGER) - { wacom->tool[1] = BTN_TOOL_FINGER; - input_report_key(dev, wacom->tool[1], 1); - } + input_report_key(dev, BTN_0, (data[5] & 0x01)); input_report_key(dev, BTN_1, (data[5] & 0x02)); input_report_key(dev, BTN_2, (data[5] & 0x04)); @@ -650,46 +634,93 @@ static void wacom_intuos3_irq(struct urb *urb, struct pt_regs *regs) input_report_key(dev, BTN_7, (data[6] & 0x08)); input_report_abs(dev, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]); input_report_abs(dev, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); + + if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) | data[2]) + input_report_key(dev, wacom->tool[1], 1); + else + input_report_key(dev, wacom->tool[1], 0); input_event(dev, EV_MSC, MSC_SERIAL, 0xffffffff); input_sync(dev); goto exit; } /* process in/out prox events */ - if (wacom_intuos_inout(urb)) goto exit; + if (wacom_intuos_inout(urb)) + goto exit; - input_report_abs(dev, ABS_X, ((__u32)data[2] << 9) | ((__u32)data[3] << 1) | ((data[9] >> 1) & 1)); - input_report_abs(dev, ABS_Y, ((__u32)data[4] << 9) | ((__u32)data[5] << 1) | (data[9] & 1)); - input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); + /* Cintiq doesn't send data when RDY bit isn't set */ + if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40)) + goto exit; + + if (wacom->features->type >= INTUOS3) { + input_report_abs(dev, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); + input_report_abs(dev, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1)); + input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); + } else { + input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2])); + input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4])); + input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 3) & 0x1f)); + } /* process general packets */ wacom_intuos_general(urb); - if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) - { - /* Marker pen rotation packet. Reported as wheel due to valuator limitation */ - if (data[1] & 0x02) - { - t = ((__u32)data[6] << 3) | ((data[7] >> 5) & 7); - t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : - ((t-1) / 2 + 450)) : (450 - t / 2) ; - input_report_abs(dev, ABS_WHEEL, t); - } + /* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */ + if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { + + if (data[1] & 0x02) { + /* Rotation packet */ + if (wacom->features->type >= INTUOS3) { + /* I3 marker pen rotation reported as wheel + * due to valuator limitation + */ + t = (data[6] << 3) | ((data[7] >> 5) & 7); + t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : + ((t-1) / 2 + 450)) : (450 - t / 2) ; + input_report_abs(dev, ABS_WHEEL, t); + } else { + /* 4D mouse rotation packet */ + t = (data[6] << 3) | ((data[7] >> 5) & 7); + input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ? + ((t - 1) / 2) : -t / 2); + } - /* 2D mouse packets */ - if (wacom->tool[idx] == BTN_TOOL_MOUSE) - { + } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3) { + /* 4D mouse packet */ + input_report_key(dev, BTN_LEFT, data[8] & 0x01); + input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); + input_report_key(dev, BTN_RIGHT, data[8] & 0x04); + + input_report_key(dev, BTN_SIDE, data[8] & 0x20); + input_report_key(dev, BTN_EXTRA, data[8] & 0x10); + t = (data[6] << 2) | ((data[7] >> 6) & 3); + input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); + + } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { + /* 2D mouse packet */ input_report_key(dev, BTN_LEFT, data[8] & 0x04); input_report_key(dev, BTN_MIDDLE, data[8] & 0x08); input_report_key(dev, BTN_RIGHT, data[8] & 0x10); - input_report_key(dev, BTN_SIDE, data[8] & 0x40); - input_report_key(dev, BTN_EXTRA, data[8] & 0x20); - /* mouse wheel is positive when rolled backwards */ - input_report_rel(dev, REL_WHEEL, ((__u32)((data[8] & 0x02) >> 1) - - (__u32)(data[8] & 0x01))); + input_report_rel(dev, REL_WHEEL, (data[8] & 0x01) + - ((data[8] & 0x02) >> 1)); + + /* I3 2D mouse side buttons */ + if (wacom->features->type == INTUOS3) { + input_report_key(dev, BTN_SIDE, data[8] & 0x40); + input_report_key(dev, BTN_EXTRA, data[8] & 0x20); + } + + } else if (wacom->features->type < INTUOS3) { + /* Lens cursor packets */ + input_report_key(dev, BTN_LEFT, data[8] & 0x01); + input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); + input_report_key(dev, BTN_RIGHT, data[8] & 0x04); + input_report_key(dev, BTN_SIDE, data[8] & 0x10); + input_report_key(dev, BTN_EXTRA, data[8] & 0x08); } } + input_report_abs(dev, ABS_MISC, wacom->id[idx]); /* report tool id */ input_report_key(dev, wacom->tool[idx], 1); input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); input_sync(dev); @@ -702,35 +733,50 @@ exit: } static struct wacom_features wacom_features[] = { - { "Wacom Penpartner", 7, 5040, 3780, 255, 32, 0, wacom_penpartner_irq }, - { "Wacom Graphire", 8, 10206, 7422, 511, 32, 1, wacom_graphire_irq }, - { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 32, 1, wacom_graphire_irq }, - { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, 1, wacom_graphire_irq }, - { "Wacom Graphire3", 8, 10208, 7424, 511, 32, 1, wacom_graphire_irq }, - { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, 1, wacom_graphire_irq }, - { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 15, 2, wacom_intuos_irq }, - { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, - { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 15, 2, wacom_intuos_irq }, - { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 15, 2, wacom_intuos_irq }, - { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 15, 2, wacom_intuos_irq }, - { "Wacom PL400", 8, 5408, 4056, 255, 32, 3, wacom_pl_irq }, - { "Wacom PL500", 8, 6144, 4608, 255, 32, 3, wacom_pl_irq }, - { "Wacom PL600", 8, 6126, 4604, 255, 32, 3, wacom_pl_irq }, - { "Wacom PL600SX", 8, 6260, 5016, 255, 32, 3, wacom_pl_irq }, - { "Wacom PL550", 8, 6144, 4608, 511, 32, 3, wacom_pl_irq }, - { "Wacom PL800", 8, 7220, 5780, 511, 32, 3, wacom_pl_irq }, - { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, 2, wacom_intuos_irq }, - { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, - { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15, 2, wacom_intuos_irq }, - { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, 2, wacom_intuos_irq }, - { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, 2, wacom_intuos_irq }, - { "Wacom Volito", 8, 5104, 3712, 511, 32, 1, wacom_graphire_irq }, - { "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, 3, wacom_ptu_irq }, - { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, 4, wacom_intuos3_irq }, - { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, 4, wacom_intuos3_irq }, - { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, 4, wacom_intuos3_irq }, - { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, - { } + { "Wacom Penpartner", 7, 5040, 3780, 255, 32, PENPARTNER, wacom_penpartner_irq }, + { "Wacom Graphire", 8, 10206, 7422, 511, 32, GRAPHIRE, wacom_graphire_irq }, + { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 32, GRAPHIRE, wacom_graphire_irq }, + { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, + { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, + { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq }, + { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, WACOM_G4, wacom_graphire_irq }, + { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, WACOM_G4, wacom_graphire_irq }, + { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, + { "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq }, + { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, + { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 32, GRAPHIRE, wacom_graphire_irq }, + { "Wacom PenPartner2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq }, + { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_intuos_irq }, + { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, + { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_intuos_irq }, + { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, + { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, + { "Wacom PL400", 8, 5408, 4056, 255, 32, PL, wacom_pl_irq }, + { "Wacom PL500", 8, 6144, 4608, 255, 32, PL, wacom_pl_irq }, + { "Wacom PL600", 8, 6126, 4604, 255, 32, PL, wacom_pl_irq }, + { "Wacom PL600SX", 8, 6260, 5016, 255, 32, PL, wacom_pl_irq }, + { "Wacom PL550", 8, 6144, 4608, 511, 32, PL, wacom_pl_irq }, + { "Wacom PL800", 8, 7220, 5780, 511, 32, PL, wacom_pl_irq }, + { "Wacom PL700", 8, 6758, 5406, 511, 32, PL, wacom_pl_irq }, + { "Wacom PL510", 8, 6282, 4762, 511, 32, PL, wacom_pl_irq }, + { "Wacom DTU710", 8, 34080, 27660, 511, 32, PL, wacom_pl_irq }, + { "Wacom DTF521", 8, 6282, 4762, 511, 32, PL, wacom_pl_irq }, + { "Wacom DTF720", 8, 6858, 5506, 511, 32, PL, wacom_pl_irq }, + { "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, PL, wacom_ptu_irq }, + { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_intuos_irq }, + { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, + { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_intuos_irq }, + { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, + { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, + { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, INTUOS3, wacom_intuos_irq }, + { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, INTUOS3, wacom_intuos_irq }, + { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, INTUOS3, wacom_intuos_irq }, + { "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 15, INTUOS312, wacom_intuos_irq }, + { "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 15, INTUOS319, wacom_intuos_irq }, + { "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 15, INTUOS3, wacom_intuos_irq }, + { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 15, CINTIQ, wacom_intuos_irq }, + { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, + { } }; static struct usb_device_id wacom_ids[] = { @@ -740,6 +786,13 @@ static struct usb_device_id wacom_ids[] = { { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) }, @@ -751,16 +804,24 @@ static struct usb_device_id wacom_ids[] = { { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC3) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, { } }; @@ -771,14 +832,9 @@ static int wacom_open(struct input_dev *dev) { struct wacom *wacom = dev->private; - if (wacom->open++) - return 0; - wacom->irq->dev = wacom->usbdev; - if (usb_submit_urb(wacom->irq, GFP_KERNEL)) { - wacom->open--; + if (usb_submit_urb(wacom->irq, GFP_KERNEL)) return -EIO; - } return 0; } @@ -787,105 +843,100 @@ static void wacom_close(struct input_dev *dev) { struct wacom *wacom = dev->private; - if (!--wacom->open) - usb_kill_urb(wacom->irq); + usb_kill_urb(wacom->irq); } static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); struct usb_endpoint_descriptor *endpoint; - char rep_data[2] = {0x02, 0x02}; struct wacom *wacom; - char path[64]; + struct input_dev *input_dev; + char rep_data[2], limit = 0; - if (!(wacom = kmalloc(sizeof(struct wacom), GFP_KERNEL))) - return -ENOMEM; - memset(wacom, 0, sizeof(struct wacom)); + wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!wacom || !input_dev) + goto fail1; wacom->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma); - if (!wacom->data) { - kfree(wacom); - return -ENOMEM; - } + if (!wacom->data) + goto fail1; wacom->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!wacom->irq) { - usb_buffer_free(dev, 10, wacom->data, wacom->data_dma); - kfree(wacom); - return -ENOMEM; - } + if (!wacom->irq) + goto fail2; + + wacom->usbdev = dev; + wacom->dev = input_dev; + usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); + strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); wacom->features = wacom_features + (id - wacom_ids); + if (wacom->features->pktlen > 10) + BUG(); - wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS); - wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); - wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS); + input_dev->name = wacom->features->name; + usb_to_input_id(dev, &input_dev->id); + + input_dev->cdev.dev = &intf->dev; + input_dev->private = wacom; + input_dev->open = wacom_open; + input_dev->close = wacom_close; + + input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS); + input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS); + input_set_abs_params(input_dev, ABS_X, 0, wacom->features->x_max, 4, 0); + input_set_abs_params(input_dev, ABS_Y, 0, wacom->features->y_max, 4, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0); + input_dev->absbit[LONG(ABS_MISC)] |= BIT(ABS_MISC); switch (wacom->features->type) { - case 1: - wacom->dev.evbit[0] |= BIT(EV_REL); - wacom->dev.relbit[0] |= BIT(REL_WHEEL); - wacom->dev.absbit[0] |= BIT(ABS_DISTANCE); - wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); - wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2); + case WACOM_G4: + input_dev->evbit[0] |= BIT(EV_MSC); + input_dev->mscbit[0] |= BIT(MSC_SERIAL); + input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); + input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); + /* fall through */ + + case GRAPHIRE: + input_dev->evbit[0] |= BIT(EV_REL); + input_dev->relbit[0] |= BIT(REL_WHEEL); + input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); + input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2); + input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom->features->distance_max, 0, 0); break; - case 4: /* new functions for Intuos3 */ - wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); - wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); - wacom->dev.absbit[0] |= BIT(ABS_RX) | BIT(ABS_RY); + case INTUOS3: + case INTUOS312: + case INTUOS319: + case CINTIQ: + input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); + input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); + input_set_abs_params(input_dev, ABS_RX, 0, 4097, 0, 0); + input_set_abs_params(input_dev, ABS_RY, 0, 4097, 0, 0); /* fall through */ - case 2: - wacom->dev.evbit[0] |= BIT(EV_MSC) | BIT(EV_REL); - wacom->dev.mscbit[0] |= BIT(MSC_SERIAL); - wacom->dev.relbit[0] |= BIT(REL_WHEEL); - wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA); - wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH) + case INTUOS: + input_dev->evbit[0] |= BIT(EV_MSC) | BIT(EV_REL); + input_dev->mscbit[0] |= BIT(MSC_SERIAL); + input_dev->relbit[0] |= BIT(REL_WHEEL); + input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA); + input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH) | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2); - wacom->dev.absbit[0] |= BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE); + input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom->features->distance_max, 0, 0); + input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); + input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0); + input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0); + input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0); + input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0); break; - case 3: - wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); + case PL: + input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); break; } - wacom->dev.absmax[ABS_X] = wacom->features->x_max; - wacom->dev.absmax[ABS_Y] = wacom->features->y_max; - wacom->dev.absmax[ABS_PRESSURE] = wacom->features->pressure_max; - wacom->dev.absmax[ABS_DISTANCE] = wacom->features->distance_max; - wacom->dev.absmax[ABS_TILT_X] = 127; - wacom->dev.absmax[ABS_TILT_Y] = 127; - wacom->dev.absmax[ABS_WHEEL] = 1023; - - wacom->dev.absmax[ABS_RX] = 4097; - wacom->dev.absmax[ABS_RY] = 4097; - wacom->dev.absmin[ABS_RZ] = -900; - wacom->dev.absmax[ABS_RZ] = 899; - wacom->dev.absmin[ABS_THROTTLE] = -1023; - wacom->dev.absmax[ABS_THROTTLE] = 1023; - - wacom->dev.absfuzz[ABS_X] = 4; - wacom->dev.absfuzz[ABS_Y] = 4; - - wacom->dev.private = wacom; - wacom->dev.open = wacom_open; - wacom->dev.close = wacom_close; - - usb_make_path(dev, path, 64); - sprintf(wacom->phys, "%s/input0", path); - - wacom->dev.name = wacom->features->name; - wacom->dev.phys = wacom->phys; - wacom->dev.id.bustype = BUS_USB; - wacom->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); - wacom->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); - wacom->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice); - wacom->dev.dev = &intf->dev; - wacom->usbdev = dev; - endpoint = &intf->cur_altsetting->endpoint[0].desc; if (wacom->features->pktlen > 10) @@ -898,18 +949,23 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i wacom->irq->transfer_dma = wacom->data_dma; wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - input_register_device(&wacom->dev); - - /* ask the tablet to report tablet data */ - usb_set_report(intf, 3, 2, rep_data, 2); - /* repeat once (not sure why the first call often fails) */ - usb_set_report(intf, 3, 2, rep_data, 2); + input_register_device(wacom->dev); - printk(KERN_INFO "input: %s on %s\n", wacom->features->name, path); + /* Ask the tablet to report tablet data. Repeat until it succeeds */ + do { + rep_data[0] = 2; + rep_data[1] = 2; + usb_set_report(intf, 3, 2, rep_data, 2); + usb_get_report(intf, 3, 2, rep_data, 2); + } while (rep_data[1] != 2 && limit++ < 5); usb_set_intfdata(intf, wacom); - return 0; + +fail2: usb_buffer_free(dev, 10, wacom->data, wacom->data_dma); +fail1: input_free_device(input_dev); + kfree(wacom); + return -ENOMEM; } static void wacom_disconnect(struct usb_interface *intf) @@ -919,7 +975,7 @@ static void wacom_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (wacom) { usb_kill_urb(wacom->irq); - input_unregister_device(&wacom->dev); + input_unregister_device(wacom->dev); usb_free_urb(wacom->irq); usb_buffer_free(interface_to_usbdev(intf), 10, wacom->data, wacom->data_dma); kfree(wacom); @@ -927,7 +983,6 @@ static void wacom_disconnect(struct usb_interface *intf) } static struct usb_driver wacom_driver = { - .owner = THIS_MODULE, .name = "wacom", .probe = wacom_probe, .disconnect = wacom_disconnect,