diff options
author | Dmitry Torokhov <dtor@insightbb.com> | 2007-05-07 16:16:29 -0400 |
---|---|---|
committer | Dmitry Torokhov <dtor@insightbb.com> | 2007-05-08 01:41:29 -0400 |
commit | 4104d13fe0194736393d97c88ee045fb689c783b (patch) | |
tree | 1915a03fbad7541df368f0940387f0f15b7fc380 /drivers/usb/input | |
parent | d2ada5597d33a9108acb2caf912f85cbc9caab1e (diff) |
Input: move USB tablets under drivers/input/tablet
This will allow concentrating all input devices in one place
in {menu|x|q}config.
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/input')
-rw-r--r-- | drivers/usb/input/Kconfig | 60 | ||||
-rw-r--r-- | drivers/usb/input/Makefile | 8 | ||||
-rw-r--r-- | drivers/usb/input/acecad.c | 289 | ||||
-rw-r--r-- | drivers/usb/input/aiptek.c | 2236 | ||||
-rw-r--r-- | drivers/usb/input/gtco.c | 1055 | ||||
-rw-r--r-- | drivers/usb/input/kbtab.c | 226 | ||||
-rw-r--r-- | drivers/usb/input/wacom.h | 131 | ||||
-rw-r--r-- | drivers/usb/input/wacom_sys.c | 318 | ||||
-rw-r--r-- | drivers/usb/input/wacom_wac.c | 675 | ||||
-rw-r--r-- | drivers/usb/input/wacom_wac.h | 49 |
10 files changed, 0 insertions, 5047 deletions
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index a792e42f58a..86cad900c65 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig @@ -4,54 +4,6 @@ comment "USB Input Devices" depends on USB -config USB_AIPTEK - tristate "Aiptek 6000U/8000U tablet support" - depends on USB && INPUT - help - Say Y here if you want to use the USB version of the Aiptek 6000U - or Aiptek 8000U tablet. Make sure to say Y to "Mouse support" - (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" - (CONFIG_INPUT_EVDEV) as well. - - To compile this driver as a module, choose M here: the - module will be called aiptek. - -config USB_WACOM - tristate "Wacom Intuos/Graphire tablet support" - depends on USB && INPUT - help - Say Y here if you want to use the USB version of the Wacom Intuos - or Graphire tablet. Make sure to say Y to "Mouse support" - (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" - (CONFIG_INPUT_EVDEV) as well. - - To compile this driver as a module, choose M here: the - module will be called wacom. - -config USB_ACECAD - tristate "Acecad Flair tablet support" - depends on USB && INPUT - help - Say Y here if you want to use the USB version of the Acecad Flair - tablet. Make sure to say Y to "Mouse support" - (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" - (CONFIG_INPUT_EVDEV) as well. - - To compile this driver as a module, choose M here: the - module will be called acecad. - -config USB_KBTAB - tristate "KB Gear JamStudio tablet support" - depends on USB && INPUT - help - Say Y here if you want to use the USB version of the KB Gear - JamStudio tablet. Make sure to say Y to "Mouse support" - (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" - (CONFIG_INPUT_EVDEV) as well. - - To compile this driver as a module, choose M here: the - module will be called kbtab. - config USB_POWERMATE tristate "Griffin PowerMate and Contour Jog support" depends on USB && INPUT @@ -211,15 +163,3 @@ config USB_APPLETOUCH To compile this driver as a module, choose M here: the module will be called appletouch. - -config USB_GTCO - tristate "GTCO CalComp/InterWrite USB Support" - depends on USB && INPUT - ---help--- - Say Y here if you want to use the USB version of the GTCO - CalComp/InterWrite Tablet. Make sure to say Y to "Mouse support" - (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" - (CONFIG_INPUT_EVDEV) as well. - - To compile this driver as a module, choose M here: the - module will be called gtco. diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile index 284a0734e0c..a9e9b2fc5e7 100644 --- a/drivers/usb/input/Makefile +++ b/drivers/usb/input/Makefile @@ -2,22 +2,14 @@ # Makefile for the USB input drivers # -# Multipart objects. -wacom-objs := wacom_wac.o wacom_sys.o - -obj-$(CONFIG_USB_AIPTEK) += aiptek.o obj-$(CONFIG_USB_ATI_REMOTE) += ati_remote.o obj-$(CONFIG_USB_ATI_REMOTE2) += ati_remote2.o -obj-$(CONFIG_USB_KBTAB) += kbtab.o obj-$(CONFIG_USB_KEYSPAN_REMOTE) += keyspan_remote.o obj-$(CONFIG_USB_TOUCHSCREEN) += usbtouchscreen.o obj-$(CONFIG_USB_POWERMATE) += powermate.o -obj-$(CONFIG_USB_WACOM) += wacom.o -obj-$(CONFIG_USB_ACECAD) += acecad.o obj-$(CONFIG_USB_YEALINK) += yealink.o obj-$(CONFIG_USB_XPAD) += xpad.o obj-$(CONFIG_USB_APPLETOUCH) += appletouch.o -obj-$(CONFIG_USB_GTCO) += gtco.o ifeq ($(CONFIG_USB_DEBUG),y) EXTRA_CFLAGS += -DDEBUG diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c deleted file mode 100644 index dd2310458c4..00000000000 --- a/drivers/usb/input/acecad.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2001-2005 Edouard TISSERANT <edouard.tisserant@wanadoo.fr> - * Copyright (c) 2004-2005 Stephane VOLTZ <svoltz@numericable.fr> - * - * USB Acecad "Acecad Flair" tablet support - * - * Changelog: - * v3.2 - Added sysfs support - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/usb/input.h> - -/* - * Version Information - */ -#define DRIVER_VERSION "v3.2" -#define DRIVER_DESC "USB Acecad Flair tablet driver" -#define DRIVER_LICENSE "GPL" -#define DRIVER_AUTHOR "Edouard TISSERANT <edouard.tisserant@wanadoo.fr>" - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENSE); - -#define USB_VENDOR_ID_ACECAD 0x0460 -#define USB_DEVICE_ID_FLAIR 0x0004 -#define USB_DEVICE_ID_302 0x0008 - -struct usb_acecad { - char name[128]; - char phys[64]; - struct usb_device *usbdev; - struct input_dev *input; - struct urb *irq; - - unsigned char *data; - dma_addr_t data_dma; -}; - -static void usb_acecad_irq(struct urb *urb) -{ - struct usb_acecad *acecad = urb->context; - unsigned char *data = acecad->data; - struct input_dev *dev = acecad->input; - int prox, status; - - 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 resubmit; - } - - prox = (data[0] & 0x04) >> 2; - input_report_key(dev, BTN_TOOL_PEN, prox); - - if (prox) { - int x = data[1] | (data[2] << 8); - int y = data[3] | (data[4] << 8); - /* Pressure should compute the same way for flair and 302 */ - int pressure = data[5] | (data[6] << 8); - int touch = data[0] & 0x01; - int stylus = (data[0] & 0x10) >> 4; - int stylus2 = (data[0] & 0x20) >> 5; - input_report_abs(dev, ABS_X, x); - input_report_abs(dev, ABS_Y, y); - input_report_abs(dev, ABS_PRESSURE, pressure); - input_report_key(dev, BTN_TOUCH, touch); - input_report_key(dev, BTN_STYLUS, stylus); - input_report_key(dev, BTN_STYLUS2, stylus2); - } - - /* event termination */ - input_sync(dev); - -resubmit: - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) - err("can't resubmit intr, %s-%s/input0, status %d", - acecad->usbdev->bus->bus_name, acecad->usbdev->devpath, status); -} - -static int usb_acecad_open(struct input_dev *dev) -{ - struct usb_acecad *acecad = input_get_drvdata(dev); - - acecad->irq->dev = acecad->usbdev; - if (usb_submit_urb(acecad->irq, GFP_KERNEL)) - return -EIO; - - return 0; -} - -static void usb_acecad_close(struct input_dev *dev) -{ - struct usb_acecad *acecad = input_get_drvdata(dev); - - usb_kill_urb(acecad->irq); -} - -static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_host_interface *interface = intf->cur_altsetting; - struct usb_endpoint_descriptor *endpoint; - struct usb_acecad *acecad; - struct input_dev *input_dev; - int pipe, maxp; - int err = -ENOMEM; - - if (interface->desc.bNumEndpoints != 1) - return -ENODEV; - - endpoint = &interface->endpoint[0].desc; - - if (!usb_endpoint_is_int_in(endpoint)) - return -ENODEV; - - pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!acecad || !input_dev) { - err = -ENOMEM; - goto fail1; - } - - acecad->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &acecad->data_dma); - if (!acecad->data) { - err= -ENOMEM; - goto fail1; - } - - acecad->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!acecad->irq) { - err = -ENOMEM; - goto fail2; - } - - acecad->usbdev = dev; - acecad->input = input_dev; - - if (dev->manufacturer) - strlcpy(acecad->name, dev->manufacturer, sizeof(acecad->name)); - - if (dev->product) { - if (dev->manufacturer) - strlcat(acecad->name, " ", sizeof(acecad->name)); - strlcat(acecad->name, dev->product, sizeof(acecad->name)); - } - - usb_make_path(dev, acecad->phys, sizeof(acecad->phys)); - strlcat(acecad->phys, "/input0", sizeof(acecad->phys)); - - input_dev->name = acecad->name; - input_dev->phys = acecad->phys; - usb_to_input_id(dev, &input_dev->id); - input_dev->dev.parent = &intf->dev; - - input_set_drvdata(input_dev, acecad); - - input_dev->open = usb_acecad_open; - input_dev->close = usb_acecad_close; - - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); - input_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); - input_dev->keybit[LONG(BTN_DIGI)] = BIT(BTN_TOOL_PEN) |BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2); - - switch (id->driver_info) { - case 0: - input_dev->absmax[ABS_X] = 5000; - input_dev->absmax[ABS_Y] = 3750; - input_dev->absmax[ABS_PRESSURE] = 512; - if (!strlen(acecad->name)) - snprintf(acecad->name, sizeof(acecad->name), - "USB Acecad Flair Tablet %04x:%04x", - le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - break; - case 1: - input_dev->absmax[ABS_X] = 3000; - input_dev->absmax[ABS_Y] = 2250; - input_dev->absmax[ABS_PRESSURE] = 1024; - if (!strlen(acecad->name)) - snprintf(acecad->name, sizeof(acecad->name), - "USB Acecad 302 Tablet %04x:%04x", - le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - break; - } - - input_dev->absfuzz[ABS_X] = 4; - input_dev->absfuzz[ABS_Y] = 4; - - usb_fill_int_urb(acecad->irq, dev, pipe, - acecad->data, maxp > 8 ? 8 : maxp, - usb_acecad_irq, acecad, endpoint->bInterval); - acecad->irq->transfer_dma = acecad->data_dma; - acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - err = input_register_device(acecad->input); - if (err) - goto fail2; - - usb_set_intfdata(intf, acecad); - - return 0; - - fail2: usb_buffer_free(dev, 8, acecad->data, acecad->data_dma); - fail1: input_free_device(input_dev); - kfree(acecad); - return err; -} - -static void usb_acecad_disconnect(struct usb_interface *intf) -{ - struct usb_acecad *acecad = usb_get_intfdata(intf); - - usb_set_intfdata(intf, NULL); - if (acecad) { - usb_kill_urb(acecad->irq); - input_unregister_device(acecad->input); - usb_free_urb(acecad->irq); - usb_buffer_free(interface_to_usbdev(intf), 10, acecad->data, acecad->data_dma); - kfree(acecad); - } -} - -static struct usb_device_id usb_acecad_id_table [] = { - { USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_FLAIR), .driver_info = 0 }, - { USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_302), .driver_info = 1 }, - { } -}; - -MODULE_DEVICE_TABLE(usb, usb_acecad_id_table); - -static struct usb_driver usb_acecad_driver = { - .name = "usb_acecad", - .probe = usb_acecad_probe, - .disconnect = usb_acecad_disconnect, - .id_table = usb_acecad_id_table, -}; - -static int __init usb_acecad_init(void) -{ - int result = usb_register(&usb_acecad_driver); - if (result == 0) - info(DRIVER_VERSION ":" DRIVER_DESC); - return result; -} - -static void __exit usb_acecad_exit(void) -{ - usb_deregister(&usb_acecad_driver); -} - -module_init(usb_acecad_init); -module_exit(usb_acecad_exit); diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c deleted file mode 100644 index cc0a498763d..00000000000 --- a/drivers/usb/input/aiptek.c +++ /dev/null @@ -1,2236 +0,0 @@ -/* - * Native support for the Aiptek HyperPen USB Tablets - * (4000U/5000U/6000U/8000U/12000U) - * - * Copyright (c) 2001 Chris Atenasio <chris@crud.net> - * Copyright (c) 2002-2004 Bryan W. Headley <bwheadley@earthlink.net> - * - * based on wacom.c by - * Vojtech Pavlik <vojtech@suse.cz> - * Andreas Bach Aaen <abach@stofanet.dk> - * Clifford Wolf <clifford@clifford.at> - * Sam Mosel <sam.mosel@computer.org> - * James E. Blair <corvus@gnu.org> - * Daniel Egger <egger@suse.de> - * - * Many thanks to Oliver Kuechemann for his support. - * - * ChangeLog: - * v0.1 - Initial release - * v0.2 - Hack to get around fake event 28's. (Bryan W. Headley) - * v0.3 - Make URB dynamic (Bryan W. Headley, Jun-8-2002) - * Released to Linux 2.4.19 and 2.5.x - * v0.4 - Rewrote substantial portions of the code to deal with - * corrected control sequences, timing, dynamic configuration, - * support of 6000U - 12000U, procfs, and macro key support - * (Jan-1-2003 - Feb-5-2003, Bryan W. Headley) - * v1.0 - Added support for diagnostic messages, count of messages - * received from URB - Mar-8-2003, Bryan W. Headley - * v1.1 - added support for tablet resolution, changed DV and proximity - * some corrections - Jun-22-2003, martin schneebacher - * - Added support for the sysfs interface, deprecating the - * procfs interface for 2.5.x kernel. Also added support for - * Wheel command. Bryan W. Headley July-15-2003. - * v1.2 - Reworked jitter timer as a kernel thread. - * Bryan W. Headley November-28-2003/Jan-10-2004. - * v1.3 - Repaired issue of kernel thread going nuts on single-processor - * machines, introduced programmableDelay as a command line - * parameter. Feb 7 2004, Bryan W. Headley. - * v1.4 - Re-wire jitter so it does not require a thread. Courtesy of - * Rene van Paassen. Added reporting of physical pointer device - * (e.g., stylus, mouse in reports 2, 3, 4, 5. We don't know - * for reports 1, 6.) - * what physical device reports for reports 1, 6.) Also enabled - * MOUSE and LENS tool button modes. Renamed "rubber" to "eraser". - * Feb 20, 2004, Bryan W. Headley. - * v1.5 - Added previousJitterable, so we don't do jitter delay when the - * user is holding a button down for periods of time. - * - * NOTE: - * This kernel driver is augmented by the "Aiptek" XFree86 input - * driver for your X server, as well as the Gaiptek GUI Front-end - * "Tablet Manager". - * These three products are highly interactive with one another, - * so therefore it's easier to document them all as one subsystem. - * Please visit the project's "home page", located at, - * http://aiptektablet.sourceforge.net. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/jiffies.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/usb/input.h> -#include <asm/uaccess.h> -#include <asm/unaligned.h> - -/* - * Version Information - */ -#define DRIVER_VERSION "v1.5 (May-15-2004)" -#define DRIVER_AUTHOR "Bryan W. Headley/Chris Atenasio" -#define DRIVER_DESC "Aiptek HyperPen USB Tablet Driver (Linux 2.6.x)" - -/* - * Aiptek status packet: - * - * (returned as Report 1 - relative coordinates from mouse and stylus) - * - * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 - * byte0 0 0 0 0 0 0 0 1 - * byte1 0 0 0 0 0 BS2 BS Tip - * byte2 X7 X6 X5 X4 X3 X2 X1 X0 - * byte3 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 - * - * (returned as Report 2 - absolute coordinates from the stylus) - * - * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 - * byte0 0 0 0 0 0 0 1 0 - * byte1 X7 X6 X5 X4 X3 X2 X1 X0 - * byte2 X15 X14 X13 X12 X11 X10 X9 X8 - * byte3 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 - * byte4 Y15 Y14 Y13 Y12 Y11 Y10 Y9 Y8 - * byte5 * * * BS2 BS1 Tip IR DV - * byte6 P7 P6 P5 P4 P3 P2 P1 P0 - * byte7 P15 P14 P13 P12 P11 P10 P9 P8 - * - * (returned as Report 3 - absolute coordinates from the mouse) - * - * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 - * byte0 0 0 0 0 0 0 1 0 - * byte1 X7 X6 X5 X4 X3 X2 X1 X0 - * byte2 X15 X14 X13 X12 X11 X10 X9 X8 - * byte3 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 - * byte4 Y15 Y14 Y13 Y12 Y11 Y10 Y9 Y8 - * byte5 * * * BS2 BS1 Tip IR DV - * byte6 P7 P6 P5 P4 P3 P2 P1 P0 - * byte7 P15 P14 P13 P12 P11 P10 P9 P8 - * - * (returned as Report 4 - macrokeys from the stylus) - * - * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 - * byte0 0 0 0 0 0 1 0 0 - * byte1 0 0 0 BS2 BS Tip IR DV - * byte2 0 0 0 0 0 0 1 0 - * byte3 0 0 0 K4 K3 K2 K1 K0 - * byte4 P7 P6 P5 P4 P3 P2 P1 P0 - * byte5 P15 P14 P13 P12 P11 P10 P9 P8 - * - * (returned as Report 5 - macrokeys from the mouse) - * - * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 - * byte0 0 0 0 0 0 1 0 0 - * byte1 0 0 0 BS2 BS Tip IR DV - * byte2 0 0 0 0 0 0 1 0 - * byte3 0 0 0 K4 K3 K2 K1 K0 - * byte4 P7 P6 P5 P4 P3 P2 P1 P0 - * byte5 P15 P14 P13 P12 P11 P10 P9 P8 - * - * IR: In Range = Proximity on - * DV = Data Valid - * BS = Barrel Switch (as in, macro keys) - * BS2 also referred to as Tablet Pick - * - * Command Summary: - * - * Use report_type CONTROL (3) - * Use report_id 2 - * - * Command/Data Description Return Bytes Return Value - * 0x10/0x00 SwitchToMouse 0 - * 0x10/0x01 SwitchToTablet 0 - * 0x18/0x04 SetResolution 0 - * 0x12/0xFF AutoGainOn 0 - * 0x17/0x00 FilterOn 0 - * 0x01/0x00 GetXExtension 2 MaxX - * 0x01/0x01 GetYExtension 2 MaxY - * 0x02/0x00 GetModelCode 2 ModelCode = LOBYTE - * 0x03/0x00 GetODMCode 2 ODMCode - * 0x08/0x00 GetPressureLevels 2 =512 - * 0x04/0x00 GetFirmwareVersion 2 Firmware Version - * 0x11/0x02 EnableMacroKeys 0 - * - * To initialize the tablet: - * - * (1) Send Resolution500LPI (Command) - * (2) Query for Model code (Option Report) - * (3) Query for ODM code (Option Report) - * (4) Query for firmware (Option Report) - * (5) Query for GetXExtension (Option Report) - * (6) Query for GetYExtension (Option Report) - * (7) Query for GetPressureLevels (Option Report) - * (8) SwitchToTablet for Absolute coordinates, or - * SwitchToMouse for Relative coordinates (Command) - * (9) EnableMacroKeys (Command) - * (10) FilterOn (Command) - * (11) AutoGainOn (Command) - * - * (Step 9 can be omitted, but you'll then have no function keys.) - */ - -#define USB_VENDOR_ID_AIPTEK 0x08ca -#define USB_REQ_GET_REPORT 0x01 -#define USB_REQ_SET_REPORT 0x09 - - /* PointerMode codes - */ -#define AIPTEK_POINTER_ONLY_MOUSE_MODE 0 -#define AIPTEK_POINTER_ONLY_STYLUS_MODE 1 -#define AIPTEK_POINTER_EITHER_MODE 2 - -#define AIPTEK_POINTER_ALLOW_MOUSE_MODE(a) \ - (a == AIPTEK_POINTER_ONLY_MOUSE_MODE || \ - a == AIPTEK_POINTER_EITHER_MODE) -#define AIPTEK_POINTER_ALLOW_STYLUS_MODE(a) \ - (a == AIPTEK_POINTER_ONLY_STYLUS_MODE || \ - a == AIPTEK_POINTER_EITHER_MODE) - - /* CoordinateMode code - */ -#define AIPTEK_COORDINATE_RELATIVE_MODE 0 -#define AIPTEK_COORDINATE_ABSOLUTE_MODE 1 - - /* XTilt and YTilt values - */ -#define AIPTEK_TILT_MIN (-128) -#define AIPTEK_TILT_MAX 127 -#define AIPTEK_TILT_DISABLE (-10101) - - /* Wheel values - */ -#define AIPTEK_WHEEL_MIN 0 -#define AIPTEK_WHEEL_MAX 1024 -#define AIPTEK_WHEEL_DISABLE (-10101) - - /* ToolCode values, which BTW are 0x140 .. 0x14f - * We have things set up such that if TOOL_BUTTON_FIRED_BIT is - * not set, we'll send one instance of AIPTEK_TOOL_BUTTON_xxx. - * - * Whenever the user resets the value, TOOL_BUTTON_FIRED_BIT will - * get reset. - */ -#define TOOL_BUTTON(x) ((x) & 0x14f) -#define TOOL_BUTTON_FIRED(x) ((x) & 0x200) -#define TOOL_BUTTON_FIRED_BIT 0x200 - /* toolMode codes - */ -#define AIPTEK_TOOL_BUTTON_PEN_MODE BTN_TOOL_PEN -#define AIPTEK_TOOL_BUTTON_PEN_MODE BTN_TOOL_PEN -#define AIPTEK_TOOL_BUTTON_PENCIL_MODE BTN_TOOL_PENCIL -#define AIPTEK_TOOL_BUTTON_BRUSH_MODE BTN_TOOL_BRUSH -#define AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE BTN_TOOL_AIRBRUSH -#define AIPTEK_TOOL_BUTTON_ERASER_MODE BTN_TOOL_RUBBER -#define AIPTEK_TOOL_BUTTON_MOUSE_MODE BTN_TOOL_MOUSE -#define AIPTEK_TOOL_BUTTON_LENS_MODE BTN_TOOL_LENS - - /* Diagnostic message codes - */ -#define AIPTEK_DIAGNOSTIC_NA 0 -#define AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE 1 -#define AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE 2 -#define AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED 3 - - /* Time to wait (in ms) to help mask hand jittering - * when pressing the stylus buttons. - */ -#define AIPTEK_JITTER_DELAY_DEFAULT 50 - - /* Time to wait (in ms) in-between sending the tablet - * a command and beginning the process of reading the return - * sequence from the tablet. - */ -#define AIPTEK_PROGRAMMABLE_DELAY_25 25 -#define AIPTEK_PROGRAMMABLE_DELAY_50 50 -#define AIPTEK_PROGRAMMABLE_DELAY_100 100 -#define AIPTEK_PROGRAMMABLE_DELAY_200 200 -#define AIPTEK_PROGRAMMABLE_DELAY_300 300 -#define AIPTEK_PROGRAMMABLE_DELAY_400 400 -#define AIPTEK_PROGRAMMABLE_DELAY_DEFAULT AIPTEK_PROGRAMMABLE_DELAY_400 - - /* Mouse button programming - */ -#define AIPTEK_MOUSE_LEFT_BUTTON 0x01 -#define AIPTEK_MOUSE_RIGHT_BUTTON 0x02 -#define AIPTEK_MOUSE_MIDDLE_BUTTON 0x04 - - /* Stylus button programming - */ -#define AIPTEK_STYLUS_LOWER_BUTTON 0x08 -#define AIPTEK_STYLUS_UPPER_BUTTON 0x10 - - /* Length of incoming packet from the tablet - */ -#define AIPTEK_PACKET_LENGTH 8 - - /* We report in EV_MISC both the proximity and - * whether the report came from the stylus, tablet mouse - * or "unknown" -- Unknown when the tablet is in relative - * mode, because we only get report 1's. - */ -#define AIPTEK_REPORT_TOOL_UNKNOWN 0x10 -#define AIPTEK_REPORT_TOOL_STYLUS 0x20 -#define AIPTEK_REPORT_TOOL_MOUSE 0x40 - -static int programmableDelay = AIPTEK_PROGRAMMABLE_DELAY_DEFAULT; -static int jitterDelay = AIPTEK_JITTER_DELAY_DEFAULT; - -struct aiptek_features { - int odmCode; /* Tablet manufacturer code */ - int modelCode; /* Tablet model code (not unique) */ - int firmwareCode; /* prom/eeprom version */ - char usbPath[64 + 1]; /* device's physical usb path */ - char inputPath[64 + 1]; /* input device path */ -}; - -struct aiptek_settings { - int pointerMode; /* stylus-, mouse-only or either */ - int coordinateMode; /* absolute/relative coords */ - int toolMode; /* pen, pencil, brush, etc. tool */ - int xTilt; /* synthetic xTilt amount */ - int yTilt; /* synthetic yTilt amount */ - int wheel; /* synthetic wheel amount */ - int stylusButtonUpper; /* stylus upper btn delivers... */ - int stylusButtonLower; /* stylus lower btn delivers... */ - int mouseButtonLeft; /* mouse left btn delivers... */ - int mouseButtonMiddle; /* mouse middle btn delivers... */ - int mouseButtonRight; /* mouse right btn delivers... */ - int programmableDelay; /* delay for tablet programming */ - int jitterDelay; /* delay for hand jittering */ -}; - -struct aiptek { - struct input_dev *inputdev; /* input device struct */ - struct usb_device *usbdev; /* usb device struct */ - struct urb *urb; /* urb for incoming reports */ - dma_addr_t data_dma; /* our dma stuffage */ - struct aiptek_features features; /* tablet's array of features */ - struct aiptek_settings curSetting; /* tablet's current programmable */ - struct aiptek_settings newSetting; /* ... and new param settings */ - unsigned int ifnum; /* interface number for IO */ - int diagnostic; /* tablet diagnostic codes */ - unsigned long eventCount; /* event count */ - int inDelay; /* jitter: in jitter delay? */ - unsigned long endDelay; /* jitter: time when delay ends */ - int previousJitterable; /* jitterable prev value */ - unsigned char *data; /* incoming packet data */ -}; - -/* - * Permit easy lookup of keyboard events to send, versus - * the bitmap which comes from the tablet. This hides the - * issue that the F_keys are not sequentially numbered. - */ -static const int macroKeyEvents[] = { - KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, - KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, - KEY_F12, KEY_F13, KEY_F14, KEY_F15, KEY_F16, KEY_F17, - KEY_F18, KEY_F19, KEY_F20, KEY_F21, KEY_F22, KEY_F23, - KEY_F24, KEY_STOP, KEY_AGAIN, KEY_PROPS, KEY_UNDO, - KEY_FRONT, KEY_COPY, KEY_OPEN, KEY_PASTE, 0 -}; - -/*********************************************************************** - * Relative reports deliver values in 2's complement format to - * deal with negative offsets. - */ -static int aiptek_convert_from_2s_complement(unsigned char c) -{ - int ret; - unsigned char b = c; - int negate = 0; - - if ((b & 0x80) != 0) { - b = ~b; - b--; - negate = 1; - } - ret = b; - ret = (negate == 1) ? -ret : ret; - return ret; -} - -/*********************************************************************** - * aiptek_irq can receive one of six potential reports. - * The documentation for each is in the body of the function. - * - * The tablet reports on several attributes per invocation of - * aiptek_irq. Because the Linux Input Event system allows the - * transmission of ONE attribute per input_report_xxx() call, - * collation has to be done on the other end to reconstitute - * a complete tablet report. Further, the number of Input Event reports - * submitted varies, depending on what USB report type, and circumstance. - * To deal with this, EV_MSC is used to indicate an 'end-of-report' - * message. This has been an undocumented convention understood by the kernel - * tablet driver and clients such as gpm and XFree86's tablet drivers. - * - * Of the information received from the tablet, the one piece I - * cannot transmit is the proximity bit (without resorting to an EV_MSC - * convention above.) I therefore have taken over REL_MISC and ABS_MISC - * (for relative and absolute reports, respectively) for communicating - * Proximity. Why two events? I thought it interesting to know if the - * Proximity event occurred while the tablet was in absolute or relative - * mode. - * - * Other tablets use the notion of a certain minimum stylus pressure - * to infer proximity. While that could have been done, that is yet - * another 'by convention' behavior, the documentation for which - * would be spread between two (or more) pieces of software. - * - * EV_MSC usage was terminated for this purpose in Linux 2.5.x, and - * replaced with the input_sync() method (which emits EV_SYN.) - */ - -static void aiptek_irq(struct urb *urb) -{ - struct aiptek *aiptek = urb->context; - unsigned char *data = aiptek->data; - struct input_dev *inputdev = aiptek->inputdev; - int jitterable = 0; - int retval, macro, x, y, z, left, right, middle, p, dv, tip, bs, pck; - - 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; - } - - /* See if we are in a delay loop -- throw out report if true. - */ - if (aiptek->inDelay == 1 && time_after(aiptek->endDelay, jiffies)) { - goto exit; - } - - aiptek->inDelay = 0; - aiptek->eventCount++; - - /* Report 1 delivers relative coordinates with either a stylus - * or the mouse. You do not know, however, which input - * tool generated the event. - */ - if (data[0] == 1) { - if (aiptek->curSetting.coordinateMode == - AIPTEK_COORDINATE_ABSOLUTE_MODE) { - aiptek->diagnostic = - AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE; - } else { - x = aiptek_convert_from_2s_complement(data[2]); - y = aiptek_convert_from_2s_complement(data[3]); - - /* jitterable keeps track of whether any button has been pressed. - * We're also using it to remap the physical mouse button mask - * to pseudo-settings. (We don't specifically care about it's - * value after moving/transposing mouse button bitmasks, except - * that a non-zero value indicates that one or more - * mouse button was pressed.) - */ - jitterable = data[5] & 0x07; - - left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0; - right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0; - middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0; - - input_report_key(inputdev, BTN_LEFT, left); - input_report_key(inputdev, BTN_MIDDLE, middle); - input_report_key(inputdev, BTN_RIGHT, right); - input_report_rel(inputdev, REL_X, x); - input_report_rel(inputdev, REL_Y, y); - input_report_rel(inputdev, REL_MISC, 1 | AIPTEK_REPORT_TOOL_UNKNOWN); - - /* Wheel support is in the form of a single-event - * firing. - */ - if (aiptek->curSetting.wheel != AIPTEK_WHEEL_DISABLE) { - input_report_rel(inputdev, REL_WHEEL, - aiptek->curSetting.wheel); - aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE; - } - input_sync(inputdev); - } - } - /* Report 2 is delivered only by the stylus, and delivers - * absolute coordinates. - */ - else if (data[0] == 2) { - if (aiptek->curSetting.coordinateMode == AIPTEK_COORDINATE_RELATIVE_MODE) { - aiptek->diagnostic = AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE; - } else if (!AIPTEK_POINTER_ALLOW_STYLUS_MODE - (aiptek->curSetting.pointerMode)) { - aiptek->diagnostic = AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED; - } else { - x = le16_to_cpu(get_unaligned((__le16 *) (data + 1))); - y = le16_to_cpu(get_unaligned((__le16 *) (data + 3))); - z = le16_to_cpu(get_unaligned((__le16 *) (data + 6))); - - p = (data[5] & 0x01) != 0 ? 1 : 0; - dv = (data[5] & 0x02) != 0 ? 1 : 0; - tip = (data[5] & 0x04) != 0 ? 1 : 0; - - /* Use jitterable to re-arrange button masks - */ - jitterable = data[5] & 0x18; - - bs = (data[5] & aiptek->curSetting.stylusButtonLower) != 0 ? 1 : 0; - pck = (data[5] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0; - - /* dv indicates 'data valid' (e.g., the tablet is in sync - * and has delivered a "correct" report) We will ignore - * all 'bad' reports... - */ - if (dv != 0) { - /* If we've not already sent a tool_button_?? code, do - * so now. Then set FIRED_BIT so it won't be resent unless - * the user forces FIRED_BIT off. - */ - if (TOOL_BUTTON_FIRED - (aiptek->curSetting.toolMode) == 0) { - input_report_key(inputdev, - TOOL_BUTTON(aiptek->curSetting.toolMode), - 1); - aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; - } - - if (p != 0) { - input_report_abs(inputdev, ABS_X, x); - input_report_abs(inputdev, ABS_Y, y); - input_report_abs(inputdev, ABS_PRESSURE, z); - - input_report_key(inputdev, BTN_TOUCH, tip); - input_report_key(inputdev, BTN_STYLUS, bs); - input_report_key(inputdev, BTN_STYLUS2, pck); - - if (aiptek->curSetting.xTilt != - AIPTEK_TILT_DISABLE) { - input_report_abs(inputdev, - ABS_TILT_X, - aiptek->curSetting.xTilt); - } - if (aiptek->curSetting.yTilt != AIPTEK_TILT_DISABLE) { - input_report_abs(inputdev, - ABS_TILT_Y, - aiptek->curSetting.yTilt); - } - - /* Wheel support is in the form of a single-event - * firing. - */ - if (aiptek->curSetting.wheel != - AIPTEK_WHEEL_DISABLE) { - input_report_abs(inputdev, - ABS_WHEEL, - aiptek->curSetting.wheel); - aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE; - } - } - input_report_abs(inputdev, ABS_MISC, p | AIPTEK_REPORT_TOOL_STYLUS); - input_sync(inputdev); - } - } - } - /* Report 3's come from the mouse in absolute mode. - */ - else if (data[0] == 3) { - if (aiptek->curSetting.coordinateMode == AIPTEK_COORDINATE_RELATIVE_MODE) { - aiptek->diagnostic = AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE; - } else if (!AIPTEK_POINTER_ALLOW_MOUSE_MODE - (aiptek->curSetting.pointerMode)) { - aiptek->diagnostic = AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED; - } else { - x = le16_to_cpu(get_unaligned((__le16 *) (data + 1))); - y = le16_to_cpu(get_unaligned((__le16 *) (data + 3))); - - jitterable = data[5] & 0x1c; - - p = (data[5] & 0x01) != 0 ? 1 : 0; - dv = (data[5] & 0x02) != 0 ? 1 : 0; - left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0; - right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0; - middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0; - - if (dv != 0) { - /* If we've not already sent a tool_button_?? code, do - * so now. Then set FIRED_BIT so it won't be resent unless - * the user forces FIRED_BIT off. - */ - if (TOOL_BUTTON_FIRED - (aiptek->curSetting.toolMode) == 0) { - input_report_key(inputdev, - TOOL_BUTTON(aiptek->curSetting.toolMode), - 1); - aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; - } - - if (p != 0) { - input_report_abs(inputdev, ABS_X, x); - input_report_abs(inputdev, ABS_Y, y); - - input_report_key(inputdev, BTN_LEFT, left); - input_report_key(inputdev, BTN_MIDDLE, middle); - input_report_key(inputdev, BTN_RIGHT, right); - - /* Wheel support is in the form of a single-event - * firing. - */ - if (aiptek->curSetting.wheel != AIPTEK_WHEEL_DISABLE) { - input_report_abs(inputdev, - ABS_WHEEL, - aiptek->curSetting.wheel); - aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE; - } - } - input_report_rel(inputdev, REL_MISC, p | AIPTEK_REPORT_TOOL_MOUSE); - input_sync(inputdev); - } - } - } - /* Report 4s come from the macro keys when pressed by stylus - */ - else if (data[0] == 4) { - jitterable = data[1] & 0x18; - - p = (data[1] & 0x01) != 0 ? 1 : 0; - dv = (data[1] & 0x02) != 0 ? 1 : 0; - tip = (data[1] & 0x04) != 0 ? 1 : 0; - bs = (data[1] & aiptek->curSetting.stylusButtonLower) != 0 ? 1 : 0; - pck = (data[1] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0; - - macro = data[3]; - z = le16_to_cpu(get_unaligned((__le16 *) (data + 4))); - - if (dv != 0) { - /* If we've not already sent a tool_button_?? code, do - * so now. Then set FIRED_BIT so it won't be resent unless - * the user forces FIRED_BIT off. - */ - if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) { - input_report_key(inputdev, - TOOL_BUTTON(aiptek->curSetting.toolMode), - 1); - aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; - } - - if (p != 0) { - input_report_key(inputdev, BTN_TOUCH, tip); - input_report_key(inputdev, BTN_STYLUS, bs); - input_report_key(inputdev, BTN_STYLUS2, pck); - input_report_abs(inputdev, ABS_PRESSURE, z); - } - - /* For safety, we're sending key 'break' codes for the - * neighboring macro keys. - */ - if (macro > 0) { - input_report_key(inputdev, - macroKeyEvents[macro - 1], 0); - } - if (macro < 25) { - input_report_key(inputdev, - macroKeyEvents[macro + 1], 0); - } - input_report_key(inputdev, macroKeyEvents[macro], p); - input_report_abs(inputdev, ABS_MISC, - p | AIPTEK_REPORT_TOOL_STYLUS); - input_sync(inputdev); - } - } - /* Report 5s come from the macro keys when pressed by mouse - */ - else if (data[0] == 5) { - jitterable = data[1] & 0x1c; - - p = (data[1] & 0x01) != 0 ? 1 : 0; - dv = (data[1] & 0x02) != 0 ? 1 : 0; - left = (data[1]& aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0; - right = (data[1] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0; - middle = (data[1] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0; - macro = data[3]; - - if (dv != 0) { - /* If we've not already sent a tool_button_?? code, do - * so now. Then set FIRED_BIT so it won't be resent unless - * the user forces FIRED_BIT off. - */ - if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) { - input_report_key(inputdev, - TOOL_BUTTON(aiptek->curSetting.toolMode), - 1); - aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; - } - - if (p != 0) { - input_report_key(inputdev, BTN_LEFT, left); - input_report_key(inputdev, BTN_MIDDLE, middle); - input_report_key(inputdev, BTN_RIGHT, right); - } - - /* For safety, we're sending key 'break' codes for the - * neighboring macro keys. - */ - if (macro > 0) { - input_report_key(inputdev, - macroKeyEvents[macro - 1], 0); - } - if (macro < 25) { - input_report_key(inputdev, - macroKeyEvents[macro + 1], 0); - } - - input_report_key(inputdev, macroKeyEvents[macro], 1); - input_report_rel(inputdev, ABS_MISC, - p | AIPTEK_REPORT_TOOL_MOUSE); - input_sync(inputdev); - } - } - /* We have no idea which tool can generate a report 6. Theoretically, - * neither need to, having been given reports 4 & 5 for such use. - * However, report 6 is the 'official-looking' report for macroKeys; - * reports 4 & 5 supposively are used to support unnamed, unknown - * hat switches (which just so happen to be the macroKeys.) - */ - else if (data[0] == 6) { - macro = le16_to_cpu(get_unaligned((__le16 *) (data + 1))); - if (macro > 0) { - input_report_key(inputdev, macroKeyEvents[macro - 1], - 0); - } - if (macro < 25) { - input_report_key(inputdev, macroKeyEvents[macro + 1], - 0); - } - - /* If we've not already sent a tool_button_?? code, do - * so now. Then set FIRED_BIT so it won't be resent unless - * the user forces FIRED_BIT off. - */ - if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) { - input_report_key(inputdev, - TOOL_BUTTON(aiptek->curSetting. - toolMode), 1); - aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; - } - - input_report_key(inputdev, macroKeyEvents[macro], 1); - input_report_abs(inputdev, ABS_MISC, - 1 | AIPTEK_REPORT_TOOL_UNKNOWN); - input_sync(inputdev); - } else { - dbg("Unknown report %d", data[0]); - } - - /* Jitter may occur when the user presses a button on the stlyus - * or the mouse. What we do to prevent that is wait 'x' milliseconds - * following a 'jitterable' event, which should give the hand some time - * stabilize itself. - * - * We just introduced aiptek->previousJitterable to carry forth the - * notion that jitter occurs when the button state changes from on to off: - * a person drawing, holding a button down is not subject to jittering. - * With that in mind, changing from upper button depressed to lower button - * WILL transition through a jitter delay. - */ - - if (aiptek->previousJitterable != jitterable && - aiptek->curSetting.jitterDelay != 0 && aiptek->inDelay != 1) { - aiptek->endDelay = jiffies + - ((aiptek->curSetting.jitterDelay * HZ) / 1000); - aiptek->inDelay = 1; - } - aiptek->previousJitterable = jitterable; - -exit: - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval != 0) { - err("%s - usb_submit_urb failed with result %d", - __FUNCTION__, retval); - } -} - -/*********************************************************************** - * These are the USB id's known so far. We do not identify them to - * specific Aiptek model numbers, because there has been overlaps, - * use, and reuse of id's in existing models. Certain models have - * been known to use more than one ID, indicative perhaps of - * manufacturing revisions. In any event, we consider these - * IDs to not be model-specific nor unique. - */ -static const struct usb_device_id aiptek_ids[] = { - {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x01)}, - {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x10)}, - {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x20)}, - {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x21)}, - {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x22)}, - {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x23)}, - {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x24)}, - {} -}; - -MODULE_DEVICE_TABLE(usb, aiptek_ids); - -/*********************************************************************** - * Open an instance of the tablet driver. - */ -static int aiptek_open(struct input_dev *inputdev) -{ - struct aiptek *aiptek = input_get_drvdata(inputdev); - - aiptek->urb->dev = aiptek->usbdev; - if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0) - return -EIO; - - return 0; -} - -/*********************************************************************** - * Close an instance of the tablet driver. - */ -static void aiptek_close(struct input_dev *inputdev) -{ - struct aiptek *aiptek = input_get_drvdata(inputdev); - - usb_kill_urb(aiptek->urb); -} - -/*********************************************************************** - * aiptek_set_report and aiptek_get_report() are borrowed from Linux 2.4.x, - * where they were known as usb_set_report and usb_get_report. - */ -static int -aiptek_set_report(struct aiptek *aiptek, - unsigned char report_type, - unsigned char report_id, void *buffer, int size) -{ - return usb_control_msg(aiptek->usbdev, - usb_sndctrlpipe(aiptek->usbdev, 0), - USB_REQ_SET_REPORT, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | - USB_DIR_OUT, (report_type << 8) + report_id, - aiptek->ifnum, buffer, size, 5000); -} - -static int -aiptek_get_report(struct aiptek *aiptek, - unsigned char report_type, - unsigned char report_id, void *buffer, int size) -{ - return usb_control_msg(aiptek->usbdev, - usb_rcvctrlpipe(aiptek->usbdev, 0), - USB_REQ_GET_REPORT, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | - USB_DIR_IN, (report_type << 8) + report_id, - aiptek->ifnum, buffer, size, 5000); -} - -/*********************************************************************** - * Send a command to the tablet. - */ -static int -aiptek_command(struct aiptek *aiptek, unsigned char command, unsigned char data) -{ - const int sizeof_buf = 3 * sizeof(u8); - int ret; - u8 *buf; - - buf = kmalloc(sizeof_buf, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - buf[0] = 2; - buf[1] = command; - buf[2] = data; - - if ((ret = - aiptek_set_report(aiptek, 3, 2, buf, sizeof_buf)) != sizeof_buf) { - dbg("aiptek_program: failed, tried to send: 0x%02x 0x%02x", - command, data); - } - kfree(buf); - return ret < 0 ? ret : 0; -} - -/*********************************************************************** - * Retrieve information from the tablet. Querying info is defined as first - * sending the {command,data} sequence as a command, followed by a wait - * (aka, "programmaticDelay") and then a "read" request. - */ -static int -aiptek_query(struct aiptek *aiptek, unsigned char command, unsigned char data) -{ - const int sizeof_buf = 3 * sizeof(u8); - int ret; - u8 *buf; - - buf = kmalloc(sizeof_buf, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - buf[0] = 2; - buf[1] = command; - buf[2] = data; - - if (aiptek_command(aiptek, command, data) != 0) { - kfree(buf); - return -EIO; - } - msleep(aiptek->curSetting.programmableDelay); - - if ((ret = - aiptek_get_report(aiptek, 3, 2, buf, sizeof_buf)) != sizeof_buf) { - dbg("aiptek_query failed: returned 0x%02x 0x%02x 0x%02x", - buf[0], buf[1], buf[2]); - ret = -EIO; - } else { - ret = le16_to_cpu(get_unaligned((__le16 *) (buf + 1))); - } - kfree(buf); - return ret; -} - -/*********************************************************************** - * Program the tablet into either absolute or relative mode. - * We also get information about the tablet's size. - */ -static int aiptek_program_tablet(struct aiptek *aiptek) -{ - int ret; - /* Execute Resolution500LPI */ - if ((ret = aiptek_command(aiptek, 0x18, 0x04)) < 0) - return ret; - - /* Query getModelCode */ - if ((ret = aiptek_query(aiptek, 0x02, 0x00)) < 0) - return ret; - aiptek->features.modelCode = ret & 0xff; - - /* Query getODMCode */ - if ((ret = aiptek_query(aiptek, 0x03, 0x00)) < 0) - return ret; - aiptek->features.odmCode = ret; - - /* Query getFirmwareCode */ - if ((ret = aiptek_query(aiptek, 0x04, 0x00)) < 0) - return ret; - aiptek->features.firmwareCode = ret; - - /* Query getXextension */ - if ((ret = aiptek_query(aiptek, 0x01, 0x00)) < 0) - return ret; - aiptek->inputdev->absmin[ABS_X] = 0; - aiptek->inputdev->absmax[ABS_X] = ret - 1; - - /* Query getYextension */ - if ((ret = aiptek_query(aiptek, 0x01, 0x01)) < 0) - return ret; - aiptek->inputdev->absmin[ABS_Y] = 0; - aiptek->inputdev->absmax[ABS_Y] = ret - 1; - - /* Query getPressureLevels */ - if ((ret = aiptek_query(aiptek, 0x08, 0x00)) < 0) - return ret; - aiptek->inputdev->absmin[ABS_PRESSURE] = 0; - aiptek->inputdev->absmax[ABS_PRESSURE] = ret - 1; - - /* Depending on whether we are in absolute or relative mode, we will - * do a switchToTablet(absolute) or switchToMouse(relative) command. - */ - if (aiptek->curSetting.coordinateMode == - AIPTEK_COORDINATE_ABSOLUTE_MODE) { - /* Execute switchToTablet */ - if ((ret = aiptek_command(aiptek, 0x10, 0x01)) < 0) { - return ret; - } - } else { - /* Execute switchToMouse */ - if ((ret = aiptek_command(aiptek, 0x10, 0x00)) < 0) { - return ret; - } - } - - /* Enable the macro keys */ - if ((ret = aiptek_command(aiptek, 0x11, 0x02)) < 0) - return ret; -#if 0 - /* Execute FilterOn */ - if ((ret = aiptek_command(aiptek, 0x17, 0x00)) < 0) - return ret; -#endif - - /* Execute AutoGainOn */ - if ((ret = aiptek_command(aiptek, 0x12, 0xff)) < 0) - return ret; - - /* Reset the eventCount, so we track events from last (re)programming - */ - aiptek->diagnostic = AIPTEK_DIAGNOSTIC_NA; - aiptek->eventCount = 0; - - return 0; -} - -/*********************************************************************** - * Sysfs functions. Sysfs prefers that individually-tunable parameters - * exist in their separate pseudo-files. Summary data that is immutable - * may exist in a singular file so long as you don't define a writeable - * interface. - */ - -/*********************************************************************** - * support the 'size' file -- display support - */ -static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - return snprintf(buf, PAGE_SIZE, "%dx%d\n", - aiptek->inputdev->absmax[ABS_X] + 1, - aiptek->inputdev->absmax[ABS_Y] + 1); -} - -/* These structs define the sysfs files, param #1 is the name of the - * file, param 2 is the file permissions, param 3 & 4 are to the - * output generator and input parser routines. Absence of a routine is - * permitted -- it only means can't either 'cat' the file, or send data - * to it. - */ -static DEVICE_ATTR(size, S_IRUGO, show_tabletSize, NULL); - -/*********************************************************************** - * support routines for the 'product_id' file - */ -static ssize_t show_tabletProductId(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - return snprintf(buf, PAGE_SIZE, "0x%04x\n", - aiptek->inputdev->id.product); -} - -static DEVICE_ATTR(product_id, S_IRUGO, show_tabletProductId, NULL); - -/*********************************************************************** - * support routines for the 'vendor_id' file - */ -static ssize_t show_tabletVendorId(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev->id.vendor); -} - -static DEVICE_ATTR(vendor_id, S_IRUGO, show_tabletVendorId, NULL); - -/*********************************************************************** - * support routines for the 'vendor' file - */ -static ssize_t show_tabletManufacturer(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - int retval; - - if (aiptek == NULL) - return 0; - - retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->manufacturer); - return retval; -} - -static DEVICE_ATTR(vendor, S_IRUGO, show_tabletManufacturer, NULL); - -/*********************************************************************** - * support routines for the 'product' file - */ -static ssize_t show_tabletProduct(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - int retval; - - if (aiptek == NULL) - return 0; - - retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->product); - return retval; -} - -static DEVICE_ATTR(product, S_IRUGO, show_tabletProduct, NULL); - -/*********************************************************************** - * support routines for the 'pointer_mode' file. Note that this file - * both displays current setting and allows reprogramming. - */ -static ssize_t show_tabletPointerMode(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - char *s; - - if (aiptek == NULL) - return 0; - - switch (aiptek->curSetting.pointerMode) { - case AIPTEK_POINTER_ONLY_STYLUS_MODE: - s = "stylus"; - break; - - case AIPTEK_POINTER_ONLY_MOUSE_MODE: - s = "mouse"; - break; - - case AIPTEK_POINTER_EITHER_MODE: - s = "either"; - break; - - default: - s = "unknown"; - break; - } - return snprintf(buf, PAGE_SIZE, "%s\n", s); -} - -static ssize_t -store_tabletPointerMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - if (aiptek == NULL) - return 0; - - if (strcmp(buf, "stylus") == 0) { - aiptek->newSetting.pointerMode = - AIPTEK_POINTER_ONLY_STYLUS_MODE; - } else if (strcmp(buf, "mouse") == 0) { - aiptek->newSetting.pointerMode = AIPTEK_POINTER_ONLY_MOUSE_MODE; - } else if (strcmp(buf, "either") == 0) { - aiptek->newSetting.pointerMode = AIPTEK_POINTER_EITHER_MODE; - } - return count; -} - -static DEVICE_ATTR(pointer_mode, - S_IRUGO | S_IWUGO, - show_tabletPointerMode, store_tabletPointerMode); - -/*********************************************************************** - * support routines for the 'coordinate_mode' file. Note that this file - * both displays current setting and allows reprogramming. - */ -static ssize_t show_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - char *s; - - if (aiptek == NULL) - return 0; - - switch (aiptek->curSetting.coordinateMode) { - case AIPTEK_COORDINATE_ABSOLUTE_MODE: - s = "absolute"; - break; - - case AIPTEK_COORDINATE_RELATIVE_MODE: - s = "relative"; - break; - - default: - s = "unknown"; - break; - } - return snprintf(buf, PAGE_SIZE, "%s\n", s); -} - -static ssize_t -store_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - if (aiptek == NULL) - return 0; - - if (strcmp(buf, "absolute") == 0) { - aiptek->newSetting.pointerMode = - AIPTEK_COORDINATE_ABSOLUTE_MODE; - } else if (strcmp(buf, "relative") == 0) { - aiptek->newSetting.pointerMode = - AIPTEK_COORDINATE_RELATIVE_MODE; - } - return count; -} - -static DEVICE_ATTR(coordinate_mode, - S_IRUGO | S_IWUGO, - show_tabletCoordinateMode, store_tabletCoordinateMode); - -/*********************************************************************** - * support routines for the 'tool_mode' file. Note that this file - * both displays current setting and allows reprogramming. - */ -static ssize_t show_tabletToolMode(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - char *s; - - if (aiptek == NULL) - return 0; - - switch (TOOL_BUTTON(aiptek->curSetting.toolMode)) { - case AIPTEK_TOOL_BUTTON_MOUSE_MODE: - s = "mouse"; - break; - - case AIPTEK_TOOL_BUTTON_ERASER_MODE: - s = "eraser"; - break; - - case AIPTEK_TOOL_BUTTON_PENCIL_MODE: - s = "pencil"; - break; - - case AIPTEK_TOOL_BUTTON_PEN_MODE: - s = "pen"; - break; - - case AIPTEK_TOOL_BUTTON_BRUSH_MODE: - s = "brush"; - break; - - case AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE: - s = "airbrush"; - break; - - case AIPTEK_TOOL_BUTTON_LENS_MODE: - s = "lens"; - break; - - default: - s = "unknown"; - break; - } - return snprintf(buf, PAGE_SIZE, "%s\n", s); -} - -static ssize_t -store_tabletToolMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - if (aiptek == NULL) - return 0; - - if (strcmp(buf, "mouse") == 0) { - aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_MOUSE_MODE; - } else if (strcmp(buf, "eraser") == 0) { - aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_ERASER_MODE; - } else if (strcmp(buf, "pencil") == 0) { - aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PENCIL_MODE; - } else if (strcmp(buf, "pen") == 0) { - aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PEN_MODE; - } else if (strcmp(buf, "brush") == 0) { - aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_BRUSH_MODE; - } else if (strcmp(buf, "airbrush") == 0) { - aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE; - } else if (strcmp(buf, "lens") == 0) { - aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_LENS_MODE; - } - - return count; -} - -static DEVICE_ATTR(tool_mode, - S_IRUGO | S_IWUGO, - show_tabletToolMode, store_tabletToolMode); - -/*********************************************************************** - * support routines for the 'xtilt' file. Note that this file - * both displays current setting and allows reprogramming. - */ -static ssize_t show_tabletXtilt(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - if (aiptek->curSetting.xTilt == AIPTEK_TILT_DISABLE) { - return snprintf(buf, PAGE_SIZE, "disable\n"); - } else { - return snprintf(buf, PAGE_SIZE, "%d\n", - aiptek->curSetting.xTilt); - } -} - -static ssize_t -store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - int x; - - if (aiptek == NULL) - return 0; - - if (strcmp(buf, "disable") == 0) { - aiptek->newSetting.xTilt = AIPTEK_TILT_DISABLE; - } else { - x = (int)simple_strtol(buf, NULL, 10); - if (x >= AIPTEK_TILT_MIN && x <= AIPTEK_TILT_MAX) { - aiptek->newSetting.xTilt = x; - } - } - return count; -} - -static DEVICE_ATTR(xtilt, - S_IRUGO | S_IWUGO, show_tabletXtilt, store_tabletXtilt); - -/*********************************************************************** - * support routines for the 'ytilt' file. Note that this file - * both displays current setting and allows reprogramming. - */ -static ssize_t show_tabletYtilt(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - if (aiptek->curSetting.yTilt == AIPTEK_TILT_DISABLE) { - return snprintf(buf, PAGE_SIZE, "disable\n"); - } else { - return snprintf(buf, PAGE_SIZE, "%d\n", - aiptek->curSetting.yTilt); - } -} - -static ssize_t -store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - int y; - - if (aiptek == NULL) - return 0; - - if (strcmp(buf, "disable") == 0) { - aiptek->newSetting.yTilt = AIPTEK_TILT_DISABLE; - } else { - y = (int)simple_strtol(buf, NULL, 10); - if (y >= AIPTEK_TILT_MIN && y <= AIPTEK_TILT_MAX) { - aiptek->newSetting.yTilt = y; - } - } - return count; -} - -static DEVICE_ATTR(ytilt, - S_IRUGO | S_IWUGO, show_tabletYtilt, store_tabletYtilt); - -/*********************************************************************** - * support routines for the 'jitter' file. Note that this file - * both displays current setting and allows reprogramming. - */ -static ssize_t show_tabletJitterDelay(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - return snprintf(buf, PAGE_SIZE, "%d\n", aiptek->curSetting.jitterDelay); -} - -static ssize_t -store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - aiptek->newSetting.jitterDelay = (int)simple_strtol(buf, NULL, 10); - return count; -} - -static DEVICE_ATTR(jitter, - S_IRUGO | S_IWUGO, - show_tabletJitterDelay, store_tabletJitterDelay); - -/*********************************************************************** - * support routines for the 'delay' file. Note that this file - * both displays current setting and allows reprogramming. - */ -static ssize_t show_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - return snprintf(buf, PAGE_SIZE, "%d\n", - aiptek->curSetting.programmableDelay); -} - -static ssize_t -store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - aiptek->newSetting.programmableDelay = (int)simple_strtol(buf, NULL, 10); - return count; -} - -static DEVICE_ATTR(delay, - S_IRUGO | S_IWUGO, - show_tabletProgrammableDelay, store_tabletProgrammableDelay); - -/*********************************************************************** - * support routines for the 'input_path' file. Note that this file - * only displays current setting. - */ -static ssize_t show_tabletInputDevice(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - return snprintf(buf, PAGE_SIZE, "/dev/input/%s\n", - aiptek->features.inputPath); -} - -static DEVICE_ATTR(input_path, S_IRUGO, show_tabletInputDevice, NULL); - -/*********************************************************************** - * support routines for the 'event_count' file. Note that this file - * only displays current setting. - */ -static ssize_t show_tabletEventsReceived(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - return snprintf(buf, PAGE_SIZE, "%ld\n", aiptek->eventCount); -} - -static DEVICE_ATTR(event_count, S_IRUGO, show_tabletEventsReceived, NULL); - -/*********************************************************************** - * support routines for the 'diagnostic' file. Note that this file - * only displays current setting. - */ -static ssize_t show_tabletDiagnosticMessage(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - char *retMsg; - - if (aiptek == NULL) - return 0; - - switch (aiptek->diagnostic) { - case AIPTEK_DIAGNOSTIC_NA: - retMsg = "no errors\n"; - break; - - case AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE: - retMsg = "Error: receiving relative reports\n"; - break; - - case AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE: - retMsg = "Error: receiving absolute reports\n"; - break; - - case AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED: - if (aiptek->curSetting.pointerMode == - AIPTEK_POINTER_ONLY_MOUSE_MODE) { - retMsg = "Error: receiving stylus reports\n"; - } else { - retMsg = "Error: receiving mouse reports\n"; - } - break; - - default: - return 0; - } - return snprintf(buf, PAGE_SIZE, retMsg); -} - -static DEVICE_ATTR(diagnostic, S_IRUGO, show_tabletDiagnosticMessage, NULL); - -/*********************************************************************** - * support routines for the 'stylus_upper' file. Note that this file - * both displays current setting and allows for setting changing. - */ -static ssize_t show_tabletStylusUpper(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - char *s; - - if (aiptek == NULL) - return 0; - - switch (aiptek->curSetting.stylusButtonUpper) { - case AIPTEK_STYLUS_UPPER_BUTTON: - s = "upper"; - break; - - case AIPTEK_STYLUS_LOWER_BUTTON: - s = "lower"; - break; - - default: - s = "unknown"; - break; - } - return snprintf(buf, PAGE_SIZE, "%s\n", s); -} - -static ssize_t -store_tabletStylusUpper(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - if (strcmp(buf, "upper") == 0) { - aiptek->newSetting.stylusButtonUpper = - AIPTEK_STYLUS_UPPER_BUTTON; - } else if (strcmp(buf, "lower") == 0) { - aiptek->newSetting.stylusButtonUpper = - AIPTEK_STYLUS_LOWER_BUTTON; - } - return count; -} - -static DEVICE_ATTR(stylus_upper, - S_IRUGO | S_IWUGO, - show_tabletStylusUpper, store_tabletStylusUpper); - -/*********************************************************************** - * support routines for the 'stylus_lower' file. Note that this file - * both displays current setting and allows for setting changing. - */ -static ssize_t show_tabletStylusLower(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - char *s; - - if (aiptek == NULL) - return 0; - - switch (aiptek->curSetting.stylusButtonLower) { - case AIPTEK_STYLUS_UPPER_BUTTON: - s = "upper"; - break; - - case AIPTEK_STYLUS_LOWER_BUTTON: - s = "lower"; - break; - - default: - s = "unknown"; - break; - } - return snprintf(buf, PAGE_SIZE, "%s\n", s); -} - -static ssize_t -store_tabletStylusLower(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - if (strcmp(buf, "upper") == 0) { - aiptek->newSetting.stylusButtonLower = - AIPTEK_STYLUS_UPPER_BUTTON; - } else if (strcmp(buf, "lower") == 0) { - aiptek->newSetting.stylusButtonLower = - AIPTEK_STYLUS_LOWER_BUTTON; - } - return count; -} - -static DEVICE_ATTR(stylus_lower, - S_IRUGO | S_IWUGO, - show_tabletStylusLower, store_tabletStylusLower); - -/*********************************************************************** - * support routines for the 'mouse_left' file. Note that this file - * both displays current setting and allows for setting changing. - */ -static ssize_t show_tabletMouseLeft(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - char *s; - - if (aiptek == NULL) - return 0; - - switch (aiptek->curSetting.mouseButtonLeft) { - case AIPTEK_MOUSE_LEFT_BUTTON: - s = "left"; - break; - - case AIPTEK_MOUSE_MIDDLE_BUTTON: - s = "middle"; - break; - - case AIPTEK_MOUSE_RIGHT_BUTTON: - s = "right"; - break; - - default: - s = "unknown"; - break; - } - return snprintf(buf, PAGE_SIZE, "%s\n", s); -} - -static ssize_t -store_tabletMouseLeft(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - if (strcmp(buf, "left") == 0) { - aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_LEFT_BUTTON; - } else if (strcmp(buf, "middle") == 0) { - aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_MIDDLE_BUTTON; - } else if (strcmp(buf, "right") == 0) { - aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_RIGHT_BUTTON; - } - return count; -} - -static DEVICE_ATTR(mouse_left, - S_IRUGO | S_IWUGO, - show_tabletMouseLeft, store_tabletMouseLeft); - -/*********************************************************************** - * support routines for the 'mouse_middle' file. Note that this file - * both displays current setting and allows for setting changing. - */ -static ssize_t show_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - char *s; - - if (aiptek == NULL) - return 0; - - switch (aiptek->curSetting.mouseButtonMiddle) { - case AIPTEK_MOUSE_LEFT_BUTTON: - s = "left"; - break; - - case AIPTEK_MOUSE_MIDDLE_BUTTON: - s = "middle"; - break; - - case AIPTEK_MOUSE_RIGHT_BUTTON: - s = "right"; - break; - - default: - s = "unknown"; - break; - } - return snprintf(buf, PAGE_SIZE, "%s\n", s); -} - -static ssize_t -store_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - if (strcmp(buf, "left") == 0) { - aiptek->newSetting.mouseButtonMiddle = AIPTEK_MOUSE_LEFT_BUTTON; - } else if (strcmp(buf, "middle") == 0) { - aiptek->newSetting.mouseButtonMiddle = - AIPTEK_MOUSE_MIDDLE_BUTTON; - } else if (strcmp(buf, "right") == 0) { - aiptek->newSetting.mouseButtonMiddle = - AIPTEK_MOUSE_RIGHT_BUTTON; - } - return count; -} - -static DEVICE_ATTR(mouse_middle, - S_IRUGO | S_IWUGO, - show_tabletMouseMiddle, store_tabletMouseMiddle); - -/*********************************************************************** - * support routines for the 'mouse_right' file. Note that this file - * both displays current setting and allows for setting changing. - */ -static ssize_t show_tabletMouseRight(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - char *s; - - if (aiptek == NULL) - return 0; - - switch (aiptek->curSetting.mouseButtonRight) { - case AIPTEK_MOUSE_LEFT_BUTTON: - s = "left"; - break; - - case AIPTEK_MOUSE_MIDDLE_BUTTON: - s = "middle"; - break; - - case AIPTEK_MOUSE_RIGHT_BUTTON: - s = "right"; - break; - - default: - s = "unknown"; - break; - } - return snprintf(buf, PAGE_SIZE, "%s\n", s); -} - -static ssize_t -store_tabletMouseRight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - if (strcmp(buf, "left") == 0) { - aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_LEFT_BUTTON; - } else if (strcmp(buf, "middle") == 0) { - aiptek->newSetting.mouseButtonRight = - AIPTEK_MOUSE_MIDDLE_BUTTON; - } else if (strcmp(buf, "right") == 0) { - aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_RIGHT_BUTTON; - } - return count; -} - -static DEVICE_ATTR(mouse_right, - S_IRUGO | S_IWUGO, - show_tabletMouseRight, store_tabletMouseRight); - -/*********************************************************************** - * support routines for the 'wheel' file. Note that this file - * both displays current setting and allows for setting changing. - */ -static ssize_t show_tabletWheel(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - if (aiptek->curSetting.wheel == AIPTEK_WHEEL_DISABLE) { - return snprintf(buf, PAGE_SIZE, "disable\n"); - } else { - return snprintf(buf, PAGE_SIZE, "%d\n", - aiptek->curSetting.wheel); - } -} - -static ssize_t -store_tabletWheel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - aiptek->newSetting.wheel = (int)simple_strtol(buf, NULL, 10); - return count; -} - -static DEVICE_ATTR(wheel, - S_IRUGO | S_IWUGO, show_tabletWheel, store_tabletWheel); - -/*********************************************************************** - * support routines for the 'execute' file. Note that this file - * both displays current setting and allows for setting changing. - */ -static ssize_t show_tabletExecute(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - /* There is nothing useful to display, so a one-line manual - * is in order... - */ - return snprintf(buf, PAGE_SIZE, - "Write anything to this file to program your tablet.\n"); -} - -static ssize_t -store_tabletExecute(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - /* We do not care what you write to this file. Merely the action - * of writing to this file triggers a tablet reprogramming. - */ - memcpy(&aiptek->curSetting, &aiptek->newSetting, - sizeof(struct aiptek_settings)); - - if (aiptek_program_tablet(aiptek) < 0) - return -EIO; - - return count; -} - -static DEVICE_ATTR(execute, - S_IRUGO | S_IWUGO, show_tabletExecute, store_tabletExecute); - -/*********************************************************************** - * support routines for the 'odm_code' file. Note that this file - * only displays current setting. - */ -static ssize_t show_tabletODMCode(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.odmCode); -} - -static DEVICE_ATTR(odm_code, S_IRUGO, show_tabletODMCode, NULL); - -/*********************************************************************** - * support routines for the 'model_code' file. Note that this file - * only displays current setting. - */ -static ssize_t show_tabletModelCode(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.modelCode); -} - -static DEVICE_ATTR(model_code, S_IRUGO, show_tabletModelCode, NULL); - -/*********************************************************************** - * support routines for the 'firmware_code' file. Note that this file - * only displays current setting. - */ -static ssize_t show_firmwareCode(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct aiptek *aiptek = dev_get_drvdata(dev); - - if (aiptek == NULL) - return 0; - - return snprintf(buf, PAGE_SIZE, "%04x\n", - aiptek->features.firmwareCode); -} - -static DEVICE_ATTR(firmware_code, S_IRUGO, show_firmwareCode, NULL); - -/*********************************************************************** - * This routine removes all existing sysfs files managed by this device - * driver. - */ -static void aiptek_delete_files(struct device *dev) -{ - device_remove_file(dev, &dev_attr_size); - device_remove_file(dev, &dev_attr_product_id); - device_remove_file(dev, &dev_attr_vendor_id); - device_remove_file(dev, &dev_attr_vendor); - device_remove_file(dev, &dev_attr_product); - device_remove_file(dev, &dev_attr_pointer_mode); - device_remove_file(dev, &dev_attr_coordinate_mode); - device_remove_file(dev, &dev_attr_tool_mode); - device_remove_file(dev, &dev_attr_xtilt); - device_remove_file(dev, &dev_attr_ytilt); - device_remove_file(dev, &dev_attr_jitter); - device_remove_file(dev, &dev_attr_delay); - device_remove_file(dev, &dev_attr_input_path); - device_remove_file(dev, &dev_attr_event_count); - device_remove_file(dev, &dev_attr_diagnostic); - device_remove_file(dev, &dev_attr_odm_code); - device_remove_file(dev, &dev_attr_model_code); - device_remove_file(dev, &dev_attr_firmware_code); - device_remove_file(dev, &dev_attr_stylus_lower); - device_remove_file(dev, &dev_attr_stylus_upper); - device_remove_file(dev, &dev_attr_mouse_left); - device_remove_file(dev, &dev_attr_mouse_middle); - device_remove_file(dev, &dev_attr_mouse_right); - device_remove_file(dev, &dev_attr_wheel); - device_remove_file(dev, &dev_attr_execute); -} - -/*********************************************************************** - * This routine creates the sysfs files managed by this device - * driver. - */ -static int aiptek_add_files(struct device *dev) -{ - int ret; - - if ((ret = device_create_file(dev, &dev_attr_size)) || - (ret = device_create_file(dev, &dev_attr_product_id)) || - (ret = device_create_file(dev, &dev_attr_vendor_id)) || - (ret = device_create_file(dev, &dev_attr_vendor)) || - (ret = device_create_file(dev, &dev_attr_product)) || - (ret = device_create_file(dev, &dev_attr_pointer_mode)) || - (ret = device_create_file(dev, &dev_attr_coordinate_mode)) || - (ret = device_create_file(dev, &dev_attr_tool_mode)) || - (ret = device_create_file(dev, &dev_attr_xtilt)) || - (ret = device_create_file(dev, &dev_attr_ytilt)) || - (ret = device_create_file(dev, &dev_attr_jitter)) || - (ret = device_create_file(dev, &dev_attr_delay)) || - (ret = device_create_file(dev, &dev_attr_input_path)) || - (ret = device_create_file(dev, &dev_attr_event_count)) || - (ret = device_create_file(dev, &dev_attr_diagnostic)) || - (ret = device_create_file(dev, &dev_attr_odm_code)) || - (ret = device_create_file(dev, &dev_attr_model_code)) || - (ret = device_create_file(dev, &dev_attr_firmware_code)) || - (ret = device_create_file(dev, &dev_attr_stylus_lower)) || - (ret = device_create_file(dev, &dev_attr_stylus_upper)) || - (ret = device_create_file(dev, &dev_attr_mouse_left)) || - (ret = device_create_file(dev, &dev_attr_mouse_middle)) || - (ret = device_create_file(dev, &dev_attr_mouse_right)) || - (ret = device_create_file(dev, &dev_attr_wheel)) || - (ret = device_create_file(dev, &dev_attr_execute))) { - err("aiptek: killing own sysfs device files\n"); - aiptek_delete_files(dev); - } - return ret; -} - -/*********************************************************************** - * This routine is called when a tablet has been identified. It basically - * sets up the tablet and the driver's internal structures. - */ -static int -aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *usbdev = interface_to_usbdev(intf); - struct usb_endpoint_descriptor *endpoint; - struct aiptek *aiptek; - struct input_dev *inputdev; - struct input_handle *inputhandle; - struct list_head *node, *next; - int i; - int speeds[] = { 0, - AIPTEK_PROGRAMMABLE_DELAY_50, - AIPTEK_PROGRAMMABLE_DELAY_400, - AIPTEK_PROGRAMMABLE_DELAY_25, - AIPTEK_PROGRAMMABLE_DELAY_100, - AIPTEK_PROGRAMMABLE_DELAY_200, - AIPTEK_PROGRAMMABLE_DELAY_300 - }; - int err = -ENOMEM; - - /* programmableDelay is where the command-line specified - * delay is kept. We make it the first element of speeds[], - * so therefore, your override speed is tried first, then the - * remainder. Note that the default value of 400ms will be tried - * if you do not specify any command line parameter. - */ - speeds[0] = programmableDelay; - - aiptek = kzalloc(sizeof(struct aiptek), GFP_KERNEL); - inputdev = input_allocate_device(); - if (!aiptek || !inputdev) - goto fail1; - - aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH, - GFP_ATOMIC, &aiptek->data_dma); - if (!aiptek->data) - goto fail1; - - aiptek->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!aiptek->urb) - goto fail2; - - aiptek->inputdev = inputdev; - aiptek->usbdev = usbdev; - aiptek->ifnum = intf->altsetting[0].desc.bInterfaceNumber; - aiptek->inDelay = 0; - aiptek->endDelay = 0; - aiptek->previousJitterable = 0; - - /* Set up the curSettings struct. Said struct contains the current - * programmable parameters. The newSetting struct contains changes - * the user makes to the settings via the sysfs interface. Those - * changes are not "committed" to curSettings until the user - * writes to the sysfs/.../execute file. - */ - aiptek->curSetting.pointerMode = AIPTEK_POINTER_EITHER_MODE; - aiptek->curSetting.coordinateMode = AIPTEK_COORDINATE_ABSOLUTE_MODE; - aiptek->curSetting.toolMode = AIPTEK_TOOL_BUTTON_PEN_MODE; - aiptek->curSetting.xTilt = AIPTEK_TILT_DISABLE; - aiptek->curSetting.yTilt = AIPTEK_TILT_DISABLE; - aiptek->curSetting.mouseButtonLeft = AIPTEK_MOUSE_LEFT_BUTTON; - aiptek->curSetting.mouseButtonMiddle = AIPTEK_MOUSE_MIDDLE_BUTTON; - aiptek->curSetting.mouseButtonRight = AIPTEK_MOUSE_RIGHT_BUTTON; - aiptek->curSetting.stylusButtonUpper = AIPTEK_STYLUS_UPPER_BUTTON; - aiptek->curSetting.stylusButtonLower = AIPTEK_STYLUS_LOWER_BUTTON; - aiptek->curSetting.jitterDelay = jitterDelay; - aiptek->curSetting.programmableDelay = programmableDelay; - - /* Both structs should have equivalent settings - */ - aiptek->newSetting = aiptek->curSetting; - - /* Determine the usb devices' physical path. - * Asketh not why we always pretend we're using "../input0", - * but I suspect this will have to be refactored one - * day if a single USB device can be a keyboard & a mouse - * & a tablet, and the inputX number actually will tell - * us something... - */ - usb_make_path(usbdev, aiptek->features.usbPath, - sizeof(aiptek->features.usbPath)); - strlcat(aiptek->features.usbPath, "/input0", - sizeof(aiptek->features.usbPath)); - - /* Set up client data, pointers to open and close routines - * for the input device. - */ - inputdev->name = "Aiptek"; - inputdev->phys = aiptek->features.usbPath; - usb_to_input_id(usbdev, &inputdev->id); - inputdev->dev.parent = &intf->dev; - - input_set_drvdata(inputdev, aiptek); - - inputdev->open = aiptek_open; - inputdev->close = aiptek_close; - - /* Now program the capacities of the tablet, in terms of being - * an input device. - */ - inputdev->evbit[0] |= BIT(EV_KEY) - | BIT(EV_ABS) - | BIT(EV_REL) - | BIT(EV_MSC); - - inputdev->absbit[0] |= BIT(ABS_MISC); - - inputdev->relbit[0] |= - (BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL) | BIT(REL_MISC)); - - inputdev->keybit[LONG(BTN_LEFT)] |= - (BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE)); - - inputdev->keybit[LONG(BTN_DIGI)] |= - (BIT(BTN_TOOL_PEN) | - BIT(BTN_TOOL_RUBBER) | - BIT(BTN_TOOL_PENCIL) | - BIT(BTN_TOOL_AIRBRUSH) | - BIT(BTN_TOOL_BRUSH) | - BIT(BTN_TOOL_MOUSE) | - BIT(BTN_TOOL_LENS) | - BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2)); - - inputdev->mscbit[0] = BIT(MSC_SERIAL); - - /* Programming the tablet macro keys needs to be done with a for loop - * as the keycodes are discontiguous. - */ - for (i = 0; i < ARRAY_SIZE(macroKeyEvents); ++i) - set_bit(macroKeyEvents[i], inputdev->keybit); - - /* - * Program the input device coordinate capacities. We do not yet - * know what maximum X, Y, and Z values are, so we're putting fake - * values in. Later, we'll ask the tablet to put in the correct - * values. - */ - input_set_abs_params(inputdev, ABS_X, 0, 2999, 0, 0); - input_set_abs_params(inputdev, ABS_Y, 0, 2249, 0, 0); - input_set_abs_params(inputdev, ABS_PRESSURE, 0, 511, 0, 0); - input_set_abs_params(inputdev, ABS_TILT_X, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0); - input_set_abs_params(inputdev, ABS_TILT_Y, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0); - input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0); - - endpoint = &intf->altsetting[0].endpoint[0].desc; - - /* Go set up our URB, which is called when the tablet receives - * input. - */ - usb_fill_int_urb(aiptek->urb, - aiptek->usbdev, - usb_rcvintpipe(aiptek->usbdev, - endpoint->bEndpointAddress), - aiptek->data, 8, aiptek_irq, aiptek, - endpoint->bInterval); - - aiptek->urb->transfer_dma = aiptek->data_dma; - aiptek->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - /* Program the tablet. This sets the tablet up in the mode - * specified in newSetting, and also queries the tablet's - * physical capacities. - * - * Sanity check: if a tablet doesn't like the slow programmatic - * delay, we often get sizes of 0x0. Let's use that as an indicator - * to try faster delays, up to 25 ms. If that logic fails, well, you'll - * have to explain to us how your tablet thinks it's 0x0, and yet that's - * not an error :-) - */ - - for (i = 0; i < ARRAY_SIZE(speeds); ++i) { - aiptek->curSetting.programmableDelay = speeds[i]; - (void)aiptek_program_tablet(aiptek); - if (aiptek->inputdev->absmax[ABS_X] > 0) { - info("input: Aiptek using %d ms programming speed\n", - aiptek->curSetting.programmableDelay); - break; - } - } - - /* Register the tablet as an Input Device - */ - err = input_register_device(aiptek->inputdev); - if (err) - goto fail2; - - /* We now will look for the evdev device which is mapped to - * the tablet. The partial name is kept in the link list of - * input_handles associated with this input device. - * What identifies an evdev input_handler is that it begins - * with 'event', continues with a digit, and that in turn - * is mapped to input/eventN. - */ - list_for_each_safe(node, next, &inputdev->h_list) { - inputhandle = to_handle(node); - if (strncmp(inputhandle->name, "event", 5) == 0) { - strcpy(aiptek->features.inputPath, inputhandle->name); - break; - } - } - - /* Associate this driver's struct with the usb interface. - */ - usb_set_intfdata(intf, aiptek); - - /* Set up the sysfs files - */ - aiptek_add_files(&intf->dev); - - /* Make sure the evdev module is loaded. Assuming evdev IS a module :-) - */ - if (request_module("evdev") != 0) - info("aiptek: error loading 'evdev' module"); - - return 0; - - fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data, - aiptek->data_dma); - fail1: input_free_device(inputdev); - kfree(aiptek); - return err; -} - -/*********************************************************************** - * Deal with tablet disconnecting from the system. - */ -static void aiptek_disconnect(struct usb_interface *intf) -{ - struct aiptek *aiptek = usb_get_intfdata(intf); - - /* Disassociate driver's struct with usb interface - */ - usb_set_intfdata(intf, NULL); - if (aiptek != NULL) { - /* Free & unhook everything from the system. - */ - usb_kill_urb(aiptek->urb); - input_unregister_device(aiptek->inputdev); - aiptek_delete_files(&intf->dev); - usb_free_urb(aiptek->urb); - usb_buffer_free(interface_to_usbdev(intf), - AIPTEK_PACKET_LENGTH, - aiptek->data, aiptek->data_dma); - kfree(aiptek); - } -} - -static struct usb_driver aiptek_driver = { - .name = "aiptek", - .probe = aiptek_probe, - .disconnect = aiptek_disconnect, - .id_table = aiptek_ids, -}; - -static int __init aiptek_init(void) -{ - int result = usb_register(&aiptek_driver); - if (result == 0) { - info(DRIVER_VERSION ": " DRIVER_AUTHOR); - info(DRIVER_DESC); - } - return result; -} - -static void __exit aiptek_exit(void) -{ - usb_deregister(&aiptek_driver); -} - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); - -module_param(programmableDelay, int, 0); -MODULE_PARM_DESC(programmableDelay, "delay used during tablet programming"); -module_param(jitterDelay, int, 0); -MODULE_PARM_DESC(jitterDelay, "stylus/mouse settlement delay"); - -module_init(aiptek_init); -module_exit(aiptek_exit); diff --git a/drivers/usb/input/gtco.c b/drivers/usb/input/gtco.c deleted file mode 100644 index b2ca10f2fe0..00000000000 --- a/drivers/usb/input/gtco.c +++ /dev/null @@ -1,1055 +0,0 @@ -/* -*- linux-c -*- - -GTCO digitizer USB driver - -Use the err(), dbg() and info() macros from usb.h for system logging - -TO CHECK: Is pressure done right on report 5? - -Copyright (C) 2006 GTCO CalComp - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation, and that the name of GTCO-CalComp not be used in advertising -or publicity pertaining to distribution of the software without specific, -written prior permission. GTCO-CalComp makes no representations about the -suitability of this software for any purpose. It is provided "as is" -without express or implied warranty. - -GTCO-CALCOMP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO -EVENT SHALL GTCO-CALCOMP BE LIABLE FOR ANY SPECIAL, INDIRECT OR -CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTIONS, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. - -GTCO CalComp, Inc. -7125 Riverwood Drive -Columbia, MD 21046 - -Jeremy Roberson jroberson@gtcocalcomp.com -Scott Hill shill@gtcocalcomp.com -*/ - - - -/*#define DEBUG*/ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/input.h> -#include <linux/usb.h> -#include <asm/uaccess.h> -#include <asm/unaligned.h> -#include <asm/byteorder.h> - - -#include <linux/version.h> -#include <linux/usb/input.h> - -/* Version with a Major number of 2 is for kernel inclusion only. */ -#define GTCO_VERSION "2.00.0006" - - -/* MACROS */ - -#define VENDOR_ID_GTCO 0x078C -#define PID_400 0x400 -#define PID_401 0x401 -#define PID_1000 0x1000 -#define PID_1001 0x1001 -#define PID_1002 0x1002 - -/* Max size of a single report */ -#define REPORT_MAX_SIZE 10 - - -/* Bitmask whether pen is in range */ -#define MASK_INRANGE 0x20 -#define MASK_BUTTON 0x01F - -#define PATHLENGTH 64 - -/* DATA STRUCTURES */ - -/* Device table */ -static struct usb_device_id gtco_usbid_table [] = { - { USB_DEVICE(VENDOR_ID_GTCO, PID_400) }, - { USB_DEVICE(VENDOR_ID_GTCO, PID_401) }, - { USB_DEVICE(VENDOR_ID_GTCO, PID_1000) }, - { USB_DEVICE(VENDOR_ID_GTCO, PID_1001) }, - { USB_DEVICE(VENDOR_ID_GTCO, PID_1002) }, - { } -}; -MODULE_DEVICE_TABLE (usb, gtco_usbid_table); - - -/* Structure to hold all of our device specific stuff */ -struct gtco { - - struct input_dev *inputdevice; /* input device struct pointer */ - struct usb_device *usbdev; /* the usb device for this device */ - struct urb *urbinfo; /* urb for incoming reports */ - dma_addr_t buf_dma; /* dma addr of the data buffer*/ - unsigned char * buffer; /* databuffer for reports */ - - char usbpath[PATHLENGTH]; - int openCount; - - /* Information pulled from Report Descriptor */ - u32 usage; - u32 min_X; - u32 max_X; - u32 min_Y; - u32 max_Y; - s8 mintilt_X; - s8 maxtilt_X; - s8 mintilt_Y; - s8 maxtilt_Y; - u32 maxpressure; - u32 minpressure; -}; - - - -/* Code for parsing the HID REPORT DESCRIPTOR */ - -/* From HID1.11 spec */ -struct hid_descriptor -{ - struct usb_descriptor_header header; - __le16 bcdHID; - u8 bCountryCode; - u8 bNumDescriptors; - u8 bDescriptorType; - __le16 wDescriptorLength; -} __attribute__ ((packed)); - - -#define HID_DESCRIPTOR_SIZE 9 -#define HID_DEVICE_TYPE 33 -#define REPORT_DEVICE_TYPE 34 - - -#define PREF_TAG(x) ((x)>>4) -#define PREF_TYPE(x) ((x>>2)&0x03) -#define PREF_SIZE(x) ((x)&0x03) - -#define TYPE_MAIN 0 -#define TYPE_GLOBAL 1 -#define TYPE_LOCAL 2 -#define TYPE_RESERVED 3 - -#define TAG_MAIN_INPUT 0x8 -#define TAG_MAIN_OUTPUT 0x9 -#define TAG_MAIN_FEATURE 0xB -#define TAG_MAIN_COL_START 0xA -#define TAG_MAIN_COL_END 0xC - -#define TAG_GLOB_USAGE 0 -#define TAG_GLOB_LOG_MIN 1 -#define TAG_GLOB_LOG_MAX 2 -#define TAG_GLOB_PHYS_MIN 3 -#define TAG_GLOB_PHYS_MAX 4 -#define TAG_GLOB_UNIT_EXP 5 -#define TAG_GLOB_UNIT 6 -#define TAG_GLOB_REPORT_SZ 7 -#define TAG_GLOB_REPORT_ID 8 -#define TAG_GLOB_REPORT_CNT 9 -#define TAG_GLOB_PUSH 10 -#define TAG_GLOB_POP 11 - -#define TAG_GLOB_MAX 12 - -#define DIGITIZER_USAGE_TIP_PRESSURE 0x30 -#define DIGITIZER_USAGE_TILT_X 0x3D -#define DIGITIZER_USAGE_TILT_Y 0x3E - - -/* - * This is an abbreviated parser for the HID Report Descriptor. We - * know what devices we are talking to, so this is by no means meant - * to be generic. We can make some safe assumptions: - * - * - We know there are no LONG tags, all short - * - We know that we have no MAIN Feature and MAIN Output items - * - We know what the IRQ reports are supposed to look like. - * - * The main purpose of this is to use the HID report desc to figure - * out the mins and maxs of the fields in the IRQ reports. The IRQ - * reports for 400/401 change slightly if the max X is bigger than 64K. - * - */ -static void parse_hid_report_descriptor(struct gtco *device, char * report, - int length) -{ - int x, i = 0; - - /* Tag primitive vars */ - __u8 prefix; - __u8 size; - __u8 tag; - __u8 type; - __u8 data = 0; - __u16 data16 = 0; - __u32 data32 = 0; - - /* For parsing logic */ - int inputnum = 0; - __u32 usage = 0; - - /* Global Values, indexed by TAG */ - __u32 globalval[TAG_GLOB_MAX]; - __u32 oldval[TAG_GLOB_MAX]; - - /* Debug stuff */ - char maintype = 'x'; - char globtype[12]; - int indent = 0; - char indentstr[10] = ""; - - - dbg("======>>>>>>PARSE<<<<<<======"); - - /* Walk this report and pull out the info we need */ - while (i < length) { - prefix = report[i]; - - /* Skip over prefix */ - i++; - - /* Determine data size and save the data in the proper variable */ - size = PREF_SIZE(prefix); - switch (size) { - case 1: - data = report[i]; - break; - case 2: - data16 = le16_to_cpu(get_unaligned((__le16 *)&report[i])); - break; - case 3: - size = 4; - data32 = le32_to_cpu(get_unaligned((__le32 *)&report[i])); - break; - } - - /* Skip size of data */ - i += size; - - /* What we do depends on the tag type */ - tag = PREF_TAG(prefix); - type = PREF_TYPE(prefix); - switch (type) { - case TYPE_MAIN: - strcpy(globtype, ""); - switch (tag) { - - case TAG_MAIN_INPUT: - /* - * The INPUT MAIN tag signifies this is - * information from a report. We need to - * figure out what it is and store the - * min/max values - */ - - maintype = 'I'; - if (data == 2) - strcpy(globtype, "Variable"); - else if (data == 3) - strcpy(globtype, "Var|Const"); - - dbg("::::: Saving Report: %d input #%d Max: 0x%X(%d) Min:0x%X(%d) of %d bits", - globalval[TAG_GLOB_REPORT_ID], inputnum, - globalval[TAG_GLOB_LOG_MAX], globalval[TAG_GLOB_LOG_MAX], - globalval[TAG_GLOB_LOG_MIN], globalval[TAG_GLOB_LOG_MIN], - globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT]); - - - /* - We can assume that the first two input items - are always the X and Y coordinates. After - that, we look for everything else by - local usage value - */ - switch (inputnum) { - case 0: /* X coord */ - dbg("GER: X Usage: 0x%x", usage); - if (device->max_X == 0) { - device->max_X = globalval[TAG_GLOB_LOG_MAX]; - device->min_X = globalval[TAG_GLOB_LOG_MIN]; - } - break; - - case 1: /* Y coord */ - dbg("GER: Y Usage: 0x%x", usage); - if (device->max_Y == 0) { - device->max_Y = globalval[TAG_GLOB_LOG_MAX]; - device->min_Y = globalval[TAG_GLOB_LOG_MIN]; - } - break; - - default: - /* Tilt X */ - if (usage == DIGITIZER_USAGE_TILT_X) { - if (device->maxtilt_X == 0) { - device->maxtilt_X = globalval[TAG_GLOB_LOG_MAX]; - device->mintilt_X = globalval[TAG_GLOB_LOG_MIN]; - } - } - - /* Tilt Y */ - if (usage == DIGITIZER_USAGE_TILT_Y) { - if (device->maxtilt_Y == 0) { - device->maxtilt_Y = globalval[TAG_GLOB_LOG_MAX]; - device->mintilt_Y = globalval[TAG_GLOB_LOG_MIN]; - } - } - - /* Pressure */ - if (usage == DIGITIZER_USAGE_TIP_PRESSURE) { - if (device->maxpressure == 0) { - device->maxpressure = globalval[TAG_GLOB_LOG_MAX]; - device->minpressure = globalval[TAG_GLOB_LOG_MIN]; - } - } - - break; - } - - inputnum++; - break; - - case TAG_MAIN_OUTPUT: - maintype = 'O'; - break; - - case TAG_MAIN_FEATURE: - maintype = 'F'; - break; - - case TAG_MAIN_COL_START: - maintype = 'S'; - - if (data == 0) { - dbg("======>>>>>> Physical"); - strcpy(globtype, "Physical"); - } else - dbg("======>>>>>>"); - - /* Indent the debug output */ - indent++; - for (x = 0; x < indent; x++) - indentstr[x] = '-'; - indentstr[x] = 0; - - /* Save global tags */ - for (x = 0; x < TAG_GLOB_MAX; x++) - oldval[x] = globalval[x]; - - break; - - case TAG_MAIN_COL_END: - dbg("<<<<<<======"); - maintype = 'E'; - indent--; - for (x = 0; x < indent; x++) - indentstr[x] = '-'; - indentstr[x] = 0; - - /* Copy global tags back */ - for (x = 0; x < TAG_GLOB_MAX; x++) - globalval[x] = oldval[x]; - - break; - } - - switch (size) { - case 1: - dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x", - indentstr, tag, maintype, size, globtype, data); - break; - - case 2: - dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x", - indentstr, tag, maintype, size, globtype, data16); - break; - - case 4: - dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x", - indentstr, tag, maintype, size, globtype, data32); - break; - } - break; - - case TYPE_GLOBAL: - switch (tag) { - case TAG_GLOB_USAGE: - /* - * First time we hit the global usage tag, - * it should tell us the type of device - */ - if (device->usage == 0) - device->usage = data; - - strcpy(globtype, "USAGE"); - break; - - case TAG_GLOB_LOG_MIN: - strcpy(globtype, "LOG_MIN"); - break; - - case TAG_GLOB_LOG_MAX: - strcpy(globtype, "LOG_MAX"); - break; - - case TAG_GLOB_PHYS_MIN: - strcpy(globtype, "PHYS_MIN"); - break; - - case TAG_GLOB_PHYS_MAX: - strcpy(globtype, "PHYS_MAX"); - break; - - case TAG_GLOB_UNIT_EXP: - strcpy(globtype, "EXP"); - break; - - case TAG_GLOB_UNIT: - strcpy(globtype, "UNIT"); - break; - - case TAG_GLOB_REPORT_SZ: - strcpy(globtype, "REPORT_SZ"); - break; - - case TAG_GLOB_REPORT_ID: - strcpy(globtype, "REPORT_ID"); - /* New report, restart numbering */ - inputnum = 0; - break; - - case TAG_GLOB_REPORT_CNT: - strcpy(globtype, "REPORT_CNT"); - break; - - case TAG_GLOB_PUSH: - strcpy(globtype, "PUSH"); - break; - - case TAG_GLOB_POP: - strcpy(globtype, "POP"); - break; - } - - /* Check to make sure we have a good tag number - so we don't overflow array */ - if (tag < TAG_GLOB_MAX) { - switch (size) { - case 1: - dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x", - indentstr, globtype, tag, size, data); - globalval[tag] = data; - break; - - case 2: - dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x", - indentstr, globtype, tag, size, data16); - globalval[tag] = data16; - break; - - case 4: - dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x", - indentstr, globtype, tag, size, data32); - globalval[tag] = data32; - break; - } - } else { - dbg("%sGLOBALTAG: ILLEGAL TAG:%d SIZE: %d ", - indentstr, tag, size); - } - break; - - case TYPE_LOCAL: - switch (tag) { - case TAG_GLOB_USAGE: - strcpy(globtype, "USAGE"); - /* Always 1 byte */ - usage = data; - break; - - case TAG_GLOB_LOG_MIN: - strcpy(globtype, "MIN"); - break; - - case TAG_GLOB_LOG_MAX: - strcpy(globtype, "MAX"); - break; - - default: - strcpy(globtype, "UNKNOWN"); - break; - } - - switch (size) { - case 1: - dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", - indentstr, tag, globtype, size, data); - break; - - case 2: - dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", - indentstr, tag, globtype, size, data16); - break; - - case 4: - dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", - indentstr, tag, globtype, size, data32); - break; - } - - break; - } - } -} - -/* INPUT DRIVER Routines */ - -/* - * Called when opening the input device. This will submit the URB to - * the usb system so we start getting reports - */ -static int gtco_input_open(struct input_dev *inputdev) -{ - struct gtco *device = input_get_drvdata(inputdev); - - device->urbinfo->dev = device->usbdev; - if (usb_submit_urb(device->urbinfo, GFP_KERNEL)) - return -EIO; - - return 0; -} - -/* - * Called when closing the input device. This will unlink the URB - */ -static void gtco_input_close(struct input_dev *inputdev) -{ - struct gtco *device = input_get_drvdata(inputdev); - - usb_kill_urb(device->urbinfo); -} - - -/* - * Setup input device capabilities. Tell the input system what this - * device is capable of generating. - * - * This information is based on what is read from the HID report and - * placed in the struct gtco structure - * - */ -static void gtco_setup_caps(struct input_dev *inputdev) -{ - struct gtco *device = input_get_drvdata(inputdev); - - /* Which events */ - inputdev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC); - - /* Misc event menu block */ - inputdev->mscbit[0] = BIT(MSC_SCAN)|BIT(MSC_SERIAL)|BIT(MSC_RAW) ; - - /* Absolute values based on HID report info */ - input_set_abs_params(inputdev, ABS_X, device->min_X, device->max_X, - 0, 0); - input_set_abs_params(inputdev, ABS_Y, device->min_Y, device->max_Y, - 0, 0); - - /* Proximity */ - input_set_abs_params(inputdev, ABS_DISTANCE, 0, 1, 0, 0); - - /* Tilt & pressure */ - input_set_abs_params(inputdev, ABS_TILT_X, device->mintilt_X, - device->maxtilt_X, 0, 0); - input_set_abs_params(inputdev, ABS_TILT_Y, device->mintilt_Y, - device->maxtilt_Y, 0, 0); - input_set_abs_params(inputdev, ABS_PRESSURE, device->minpressure, - device->maxpressure, 0, 0); - - /* Transducer */ - input_set_abs_params(inputdev, ABS_MISC, 0, 0xFF, 0, 0); -} - -/* USB Routines */ - -/* - * URB callback routine. Called when we get IRQ reports from the - * digitizer. - * - * This bridges the USB and input device worlds. It generates events - * on the input device based on the USB reports. - */ -static void gtco_urb_callback(struct urb *urbinfo) -{ - struct gtco *device = urbinfo->context; - struct input_dev *inputdev; - int rc; - u32 val = 0; - s8 valsigned = 0; - char le_buffer[2]; - - inputdev = device->inputdevice; - - /* Was callback OK? */ - if (urbinfo->status == -ECONNRESET || - urbinfo->status == -ENOENT || - urbinfo->status == -ESHUTDOWN) { - - /* Shutdown is occurring. Return and don't queue up any more */ - return; - } - - if (urbinfo->status != 0) { - /* - * Some unknown error. Hopefully temporary. Just go and - * requeue an URB - */ - goto resubmit; - } - - /* - * Good URB, now process - */ - - /* PID dependent when we interpret the report */ - if (inputdev->id.product == PID_1000 || - inputdev->id.product == PID_1001 || - inputdev->id.product == PID_1002) { - - /* - * Switch on the report ID - * Conveniently, the reports have more information, the higher - * the report number. We can just fall through the case - * statements if we start with the highest number report - */ - switch (device->buffer[0]) { - case 5: - /* Pressure is 9 bits */ - val = ((u16)(device->buffer[8]) << 1); - val |= (u16)(device->buffer[7] >> 7); - input_report_abs(inputdev, ABS_PRESSURE, - device->buffer[8]); - - /* Mask out the Y tilt value used for pressure */ - device->buffer[7] = (u8)((device->buffer[7]) & 0x7F); - - /* Fall thru */ - case 4: - /* Tilt */ - - /* Sign extend these 7 bit numbers. */ - if (device->buffer[6] & 0x40) - device->buffer[6] |= 0x80; - - if (device->buffer[7] & 0x40) - device->buffer[7] |= 0x80; - - - valsigned = (device->buffer[6]); - input_report_abs(inputdev, ABS_TILT_X, (s32)valsigned); - - valsigned = (device->buffer[7]); - input_report_abs(inputdev, ABS_TILT_Y, (s32)valsigned); - - /* Fall thru */ - case 2: - case 3: - /* Convert buttons, only 5 bits possible */ - val = (device->buffer[5]) & MASK_BUTTON; - - /* We don't apply any meaning to the bitmask, - just report */ - input_event(inputdev, EV_MSC, MSC_SERIAL, val); - - /* Fall thru */ - case 1: - /* All reports have X and Y coords in the same place */ - val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[1])); - input_report_abs(inputdev, ABS_X, val); - - val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3])); - input_report_abs(inputdev, ABS_Y, val); - - /* Ditto for proximity bit */ - val = device->buffer[5] & MASK_INRANGE ? 1 : 0; - input_report_abs(inputdev, ABS_DISTANCE, val); - - /* Report 1 is an exception to how we handle buttons */ - /* Buttons are an index, not a bitmask */ - if (device->buffer[0] == 1) { - - /* - * Convert buttons, 5 bit index - * Report value of index set as one, - * the rest as 0 - */ - val = device->buffer[5] & MASK_BUTTON; - dbg("======>>>>>>REPORT 1: val 0x%X(%d)", - val, val); - - /* - * We don't apply any meaning to the button - * index, just report it - */ - input_event(inputdev, EV_MSC, MSC_SERIAL, val); - } - break; - - case 7: - /* Menu blocks */ - input_event(inputdev, EV_MSC, MSC_SCAN, - device->buffer[1]); - break; - } - } - - /* Other pid class */ - if (inputdev->id.product == PID_400 || - inputdev->id.product == PID_401) { - - /* Report 2 */ - if (device->buffer[0] == 2) { - /* Menu blocks */ - input_event(inputdev, EV_MSC, MSC_SCAN, device->buffer[1]); - } - - /* Report 1 */ - if (device->buffer[0] == 1) { - char buttonbyte; - - /* IF X max > 64K, we still a bit from the y report */ - if (device->max_X > 0x10000) { - - val = (u16)(((u16)(device->buffer[2] << 8)) | (u8)device->buffer[1]); - val |= (u32)(((u8)device->buffer[3] & 0x1) << 16); - - input_report_abs(inputdev, ABS_X, val); - - le_buffer[0] = (u8)((u8)(device->buffer[3]) >> 1); - le_buffer[0] |= (u8)((device->buffer[3] & 0x1) << 7); - - le_buffer[1] = (u8)(device->buffer[4] >> 1); - le_buffer[1] |= (u8)((device->buffer[5] & 0x1) << 7); - - val = le16_to_cpu(get_unaligned((__le16 *)le_buffer)); - input_report_abs(inputdev, ABS_Y, val); - - /* - * Shift the button byte right by one to - * make it look like the standard report - */ - buttonbyte = device->buffer[5] >> 1; - } else { - - val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[1])); - input_report_abs(inputdev, ABS_X, val); - - val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3])); - input_report_abs(inputdev, ABS_Y, val); - - buttonbyte = device->buffer[5]; - } - - /* BUTTONS and PROXIMITY */ - val = buttonbyte & MASK_INRANGE ? 1 : 0; - input_report_abs(inputdev, ABS_DISTANCE, val); - - /* Convert buttons, only 4 bits possible */ - val = buttonbyte & 0x0F; -#ifdef USE_BUTTONS - for (i = 0; i < 5; i++) - input_report_key(inputdev, BTN_DIGI + i, val & (1 << i)); -#else - /* We don't apply any meaning to the bitmask, just report */ - input_event(inputdev, EV_MSC, MSC_SERIAL, val); -#endif - - /* TRANSDUCER */ - input_report_abs(inputdev, ABS_MISC, device->buffer[6]); - } - } - - /* Everybody gets report ID's */ - input_event(inputdev, EV_MSC, MSC_RAW, device->buffer[0]); - - /* Sync it up */ - input_sync(inputdev); - - resubmit: - rc = usb_submit_urb(urbinfo, GFP_ATOMIC); - if (rc != 0) - err("usb_submit_urb failed rc=0x%x", rc); -} - -/* - * The probe routine. This is called when the kernel find the matching USB - * vendor/product. We do the following: - * - * - Allocate mem for a local structure to manage the device - * - Request a HID Report Descriptor from the device and parse it to - * find out the device parameters - * - Create an input device and assign it attributes - * - Allocate an URB so the device can talk to us when the input - * queue is open - */ -static int gtco_probe(struct usb_interface *usbinterface, - const struct usb_device_id *id) -{ - - struct gtco *gtco; - struct input_dev *input_dev; - struct hid_descriptor *hid_desc; - char *report = NULL; - int result = 0, retry; - int error; - struct usb_endpoint_descriptor *endpoint; - - /* Allocate memory for device structure */ - gtco = kzalloc(sizeof(struct gtco), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!gtco || !input_dev) { - err("No more memory"); - error = -ENOMEM; - goto err_free_devs; - } - - /* Set pointer to the input device */ - gtco->inputdevice = input_dev; - - /* Save interface information */ - gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface)); - - /* Allocate some data for incoming reports */ - gtco->buffer = usb_buffer_alloc(gtco->usbdev, REPORT_MAX_SIZE, - GFP_KERNEL, >co->buf_dma); - if (!gtco->buffer) { - err("No more memory for us buffers"); - error = -ENOMEM; - goto err_free_devs; - } - - /* Allocate URB for reports */ - gtco->urbinfo = usb_alloc_urb(0, GFP_KERNEL); - if (!gtco->urbinfo) { - err("Failed to allocate URB"); - return -ENOMEM; - goto err_free_buf; - } - - /* - * The endpoint is always altsetting 0, we know this since we know - * this device only has one interrupt endpoint - */ - endpoint = &usbinterface->altsetting[0].endpoint[0].desc; - - /* Some debug */ - dbg("gtco # interfaces: %d", usbinterface->num_altsetting); - dbg("num endpoints: %d", usbinterface->cur_altsetting->desc.bNumEndpoints); - dbg("interface class: %d", usbinterface->cur_altsetting->desc.bInterfaceClass); - dbg("endpoint: attribute:0x%x type:0x%x", endpoint->bmAttributes, endpoint->bDescriptorType); - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) - dbg("endpoint: we have interrupt endpoint\n"); - - dbg("endpoint extra len:%d ", usbinterface->altsetting[0].extralen); - - /* - * Find the HID descriptor so we can find out the size of the - * HID report descriptor - */ - if (usb_get_extra_descriptor(usbinterface->cur_altsetting, - HID_DEVICE_TYPE, &hid_desc) != 0){ - err("Can't retrieve exta USB descriptor to get hid report descriptor length"); - error = -EIO; - goto err_free_urb; - } - - dbg("Extra descriptor success: type:%d len:%d", - hid_desc->bDescriptorType, hid_desc->wDescriptorLength); - - report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL); - if (!report) { - err("No more memory for report"); - error = -ENOMEM; - goto err_free_urb; - } - - /* Couple of tries to get reply */ - for (retry = 0; retry < 3; retry++) { - result = usb_control_msg(gtco->usbdev, - usb_rcvctrlpipe(gtco->usbdev, 0), - USB_REQ_GET_DESCRIPTOR, - USB_RECIP_INTERFACE | USB_DIR_IN, - REPORT_DEVICE_TYPE << 8, - 0, /* interface */ - report, - hid_desc->wDescriptorLength, - 5000); /* 5 secs */ - - if (result == hid_desc->wDescriptorLength) - break; - } - - /* If we didn't get the report, fail */ - dbg("usb_control_msg result: :%d", result); - if (result != hid_desc->wDescriptorLength) { - err("Failed to get HID Report Descriptor of size: %d", - hid_desc->wDescriptorLength); - error = -EIO; - goto err_free_urb; - } - - /* Now we parse the report */ - parse_hid_report_descriptor(gtco, report, result); - - /* Now we delete it */ - kfree(report); - - /* Create a device file node */ - usb_make_path(gtco->usbdev, gtco->usbpath, sizeof(gtco->usbpath)); - strlcat(gtco->usbpath, "/input0", sizeof(gtco->usbpath)); - - /* Set Input device functions */ - input_dev->open = gtco_input_open; - input_dev->close = gtco_input_close; - - /* Set input device information */ - input_dev->name = "GTCO_CalComp"; - input_dev->phys = gtco->usbpath; - - input_set_drvdata(input_dev, gtco); - - /* Now set up all the input device capabilities */ - gtco_setup_caps(input_dev); - - /* Set input device required ID information */ - usb_to_input_id(gtco->usbdev, &input_dev->id); - input_dev->dev.parent = &usbinterface->dev; - - /* Setup the URB, it will be posted later on open of input device */ - endpoint = &usbinterface->altsetting[0].endpoint[0].desc; - - usb_fill_int_urb(gtco->urbinfo, - gtco->usbdev, - usb_rcvintpipe(gtco->usbdev, - endpoint->bEndpointAddress), - gtco->buffer, - REPORT_MAX_SIZE, - gtco_urb_callback, - gtco, - endpoint->bInterval); - - gtco->urbinfo->transfer_dma = gtco->buf_dma; - gtco->urbinfo->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - /* Save gtco pointer in USB interface gtco */ - usb_set_intfdata(usbinterface, gtco); - - /* All done, now register the input device */ - error = input_register_device(input_dev); - if (error) - goto err_free_urb; - - return 0; - - err_free_urb: - usb_free_urb(gtco->urbinfo); - err_free_buf: - usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE, - gtco->buffer, gtco->buf_dma); - err_free_devs: - kfree(report); - input_free_device(input_dev); - kfree(gtco); - return error; -} - -/* - * This function is a standard USB function called when the USB device - * is disconnected. We will get rid of the URV, de-register the input - * device, and free up allocated memory - */ -static void gtco_disconnect(struct usb_interface *interface) -{ - /* Grab private device ptr */ - struct gtco *gtco = usb_get_intfdata(interface); - - /* Now reverse all the registration stuff */ - if (gtco) { - input_unregister_device(gtco->inputdevice); - usb_kill_urb(gtco->urbinfo); - usb_free_urb(gtco->urbinfo); - usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE, - gtco->buffer, gtco->buf_dma); - kfree(gtco); - } - - info("gtco driver disconnected"); -} - -/* STANDARD MODULE LOAD ROUTINES */ - -static struct usb_driver gtco_driverinfo_table = { - .name = "gtco", - .id_table = gtco_usbid_table, - .probe = gtco_probe, - .disconnect = gtco_disconnect, -}; - -/* - * Register this module with the USB subsystem - */ -static int __init gtco_init(void) -{ - int error; - - error = usb_register(>co_driverinfo_table); - if (error) { - err("usb_register() failed rc=0x%x", error); - return error; - } - - printk("GTCO usb driver version: %s", GTCO_VERSION); - return 0; -} - -/* - * Deregister this module with the USB subsystem - */ -static void __exit gtco_exit(void) -{ - usb_deregister(>co_driverinfo_table); -} - -module_init(gtco_init); -module_exit(gtco_exit); - -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c deleted file mode 100644 index 91e6d00d4a4..00000000000 --- a/drivers/usb/input/kbtab.c +++ /dev/null @@ -1,226 +0,0 @@ -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/usb/input.h> -#include <asm/unaligned.h> - -/* - * Version Information - * v0.0.1 - Original, extremely basic version, 2.4.xx only - * v0.0.2 - Updated, works with 2.5.62 and 2.4.20; - * - added pressure-threshold modules param code from - * Alex Perry <alex.perry@ieee.org> - */ - -#define DRIVER_VERSION "v0.0.2" -#define DRIVER_AUTHOR "Josh Myer <josh@joshisanerd.com>" -#define DRIVER_DESC "USB KB Gear JamStudio Tablet driver" -#define DRIVER_LICENSE "GPL" - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENSE); - -#define USB_VENDOR_ID_KBGEAR 0x084e - -static int kb_pressure_click = 0x10; -module_param(kb_pressure_click, int, 0); -MODULE_PARM_DESC(kb_pressure_click, "pressure threshold for clicks"); - -struct kbtab { - unsigned char *data; - dma_addr_t data_dma; - struct input_dev *dev; - struct usb_device *usbdev; - struct urb *irq; - int x, y; - int button; - int pressure; - __u32 serial[2]; - char phys[32]; -}; - -static void kbtab_irq(struct urb *urb) -{ - struct kbtab *kbtab = urb->context; - unsigned char *data = kbtab->data; - struct input_dev *dev = kbtab->dev; - int 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; - } - - kbtab->x = le16_to_cpu(get_unaligned((__le16 *) &data[1])); - kbtab->y = le16_to_cpu(get_unaligned((__le16 *) &data[3])); - - kbtab->pressure = (data[5]); - - input_report_key(dev, BTN_TOOL_PEN, 1); - - input_report_abs(dev, ABS_X, kbtab->x); - input_report_abs(dev, ABS_Y, kbtab->y); - - /*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/ - input_report_key(dev, BTN_RIGHT, data[0] & 0x02); - - if (-1 == kb_pressure_click) { - input_report_abs(dev, ABS_PRESSURE, kbtab->pressure); - } else { - input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0); - }; - - 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 struct usb_device_id kbtab_ids[] = { - { USB_DEVICE(USB_VENDOR_ID_KBGEAR, 0x1001), .driver_info = 0 }, - { } -}; - -MODULE_DEVICE_TABLE(usb, kbtab_ids); - -static int kbtab_open(struct input_dev *dev) -{ - struct kbtab *kbtab = input_get_drvdata(dev); - - kbtab->irq->dev = kbtab->usbdev; - if (usb_submit_urb(kbtab->irq, GFP_KERNEL)) - return -EIO; - - return 0; -} - -static void kbtab_close(struct input_dev *dev) -{ - struct kbtab *kbtab = input_get_drvdata(dev); - - usb_kill_urb(kbtab->irq); -} - -static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_endpoint_descriptor *endpoint; - struct kbtab *kbtab; - struct input_dev *input_dev; - int error = -ENOMEM; - - kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!kbtab || !input_dev) - goto fail1; - - kbtab->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &kbtab->data_dma); - if (!kbtab->data) - goto fail1; - - kbtab->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!kbtab->irq) - goto fail2; - - kbtab->usbdev = dev; - kbtab->dev = input_dev; - - usb_make_path(dev, kbtab->phys, sizeof(kbtab->phys)); - strlcat(kbtab->phys, "/input0", sizeof(kbtab->phys)); - - input_dev->name = "KB Gear Tablet"; - input_dev->phys = kbtab->phys; - usb_to_input_id(dev, &input_dev->id); - input_dev->dev.parent = &intf->dev; - - input_set_drvdata(input_dev, kbtab); - - input_dev->open = kbtab_open; - input_dev->close = kbtab_close; - - input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC); - input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); - input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH); - input_dev->mscbit[0] |= BIT(MSC_SERIAL); - input_set_abs_params(input_dev, ABS_X, 0, 0x2000, 4, 0); - input_set_abs_params(input_dev, ABS_Y, 0, 0x1750, 4, 0); - input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xff, 0, 0); - - endpoint = &intf->cur_altsetting->endpoint[0].desc; - - usb_fill_int_urb(kbtab->irq, dev, - usb_rcvintpipe(dev, endpoint->bEndpointAddress), - kbtab->data, 8, - kbtab_irq, kbtab, endpoint->bInterval); - kbtab->irq->transfer_dma = kbtab->data_dma; - kbtab->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - error = input_register_device(kbtab->dev); - if (error) - goto fail3; - - usb_set_intfdata(intf, kbtab); - - return 0; - - fail3: usb_free_urb(kbtab->irq); - fail2: usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma); - fail1: input_free_device(input_dev); - kfree(kbtab); - return error; -} - -static void kbtab_disconnect(struct usb_interface *intf) -{ - struct kbtab *kbtab = usb_get_intfdata(intf); - - usb_set_intfdata(intf, NULL); - if (kbtab) { - usb_kill_urb(kbtab->irq); - input_unregister_device(kbtab->dev); - usb_free_urb(kbtab->irq); - usb_buffer_free(interface_to_usbdev(intf), 10, kbtab->data, kbtab->data_dma); - kfree(kbtab); - } -} - -static struct usb_driver kbtab_driver = { - .name = "kbtab", - .probe = kbtab_probe, - .disconnect = kbtab_disconnect, - .id_table = kbtab_ids, -}; - -static int __init kbtab_init(void) -{ - int retval; - retval = usb_register(&kbtab_driver); - if (retval) - goto out; - info(DRIVER_VERSION ":" DRIVER_DESC); -out: - return retval; -} - -static void __exit kbtab_exit(void) -{ - usb_deregister(&kbtab_driver); -} - -module_init(kbtab_init); -module_exit(kbtab_exit); diff --git a/drivers/usb/input/wacom.h b/drivers/usb/input/wacom.h deleted file mode 100644 index d85abfc5ab5..00000000000 --- a/drivers/usb/input/wacom.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * drivers/usb/input/wacom.h - * - * USB Wacom Graphire and Wacom Intuos tablet support - * - * Copyright (c) 2000-2004 Vojtech Pavlik <vojtech@ucw.cz> - * Copyright (c) 2000 Andreas Bach Aaen <abach@stofanet.dk> - * Copyright (c) 2000 Clifford Wolf <clifford@clifford.at> - * Copyright (c) 2000 Sam Mosel <sam.mosel@computer.org> - * Copyright (c) 2000 James E. Blair <corvus@gnu.org> - * Copyright (c) 2000 Daniel Egger <egger@suse.de> - * Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com> - * Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be> - * Copyright (c) 2002-2006 Ping Cheng <pingc@wacom.com> - * - * ChangeLog: - * v0.1 (vp) - Initial release - * v0.2 (aba) - Support for all buttons / combinations - * v0.3 (vp) - Support for Intuos added - * v0.4 (sm) - Support for more Intuos models, menustrip - * relative mode, proximity. - * v0.5 (vp) - Big cleanup, nifty features removed, - * 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 - * v1.11 (vp) - Add URB ->dev setting for new kernels - * v1.11 (jb) - Add support for the 4D Mouse & Lens - * v1.12 (de) - Add support for two more inking pen IDs - * v1.14 (vp) - Use new USB device id probing scheme. - * Fix Wacom Graphire mouse wheel - * v1.18 (vp) - Fix mouse wheel direction - * Make mouse relative - * v1.20 (fl) - Report tool id for Intuos devices - * - Multi tools support - * - Corrected Intuos protocol decoding (airbrush, 4D mouse, lens cursor...) - * - Add PL models support - * - Fix Wacom Graphire mouse wheel again - * v1.21 (vp) - Removed protocol descriptions - * - Added MISC_SERIAL for tool serial numbers - * (gb) - Identify version on module load. - * v1.21.1 (fl) - added Graphire2 support - * v1.21.2 (fl) - added Intuos2 support - * - added all the PL ids - * v1.21.3 (fl) - added another eraser id from Neil Okamoto - * - added smooth filter for Graphire from Peri Hankey - * - added PenPartner support from Olaf van Es - * - new tool ids from Ole Martin Bjoerndalen - * v1.29 (pc) - Add support for more tablets - * - Fix pressure reporting - * v1.30 (vp) - Merge 2.4 and 2.5 drivers - * - Since 2.5 now has input_sync(), remove MSC_SERIAL abuse - * - 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 - * v1.46 (pc) - Split wacom.c into wacom_sys.c and wacom_wac.c, - * - where wacom_sys.c deals with system specific code, - * - and wacom_wac.c deals with Wacom specific code - * - Support Intuos3 4x6 - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ -#ifndef WACOM_H -#define WACOM_H -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/usb/input.h> -#include <asm/unaligned.h> - -/* - * Version Information - */ -#define DRIVER_VERSION "v1.46" -#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" -#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" -#define DRIVER_LICENSE "GPL" - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENSE); - -#define USB_VENDOR_ID_WACOM 0x056a - -struct wacom { - dma_addr_t data_dma; - struct input_dev *dev; - struct usb_device *usbdev; - struct urb *irq; - struct wacom_wac * wacom_wac; - char phys[32]; -}; - -struct wacom_combo { - struct wacom * wacom; - struct urb * urb; -}; - -extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo); -extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data); -extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data); -extern void wacom_report_key(void *wcombo, unsigned int key_type, int key_data); -extern void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value); -extern void wacom_input_sync(void *wcombo); -extern void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac); -extern __u16 wacom_le16_to_cpu(unsigned char *data); -extern __u16 wacom_be16_to_cpu(unsigned char *data); -extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id); -extern const struct usb_device_id * get_device_table(void); - -#endif diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c deleted file mode 100644 index 1fe48208c2f..00000000000 --- a/drivers/usb/input/wacom_sys.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * drivers/usb/input/wacom_sys.c - * - * USB Wacom Graphire and Wacom Intuos tablet support - system specific code - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include "wacom.h" -#include "wacom_wac.h" - -#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) -{ - return usb_control_msg(interface_to_usbdev(intf), - usb_sndctrlpipe(interface_to_usbdev(intf), 0), - USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, - (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber, - buf, size, 1000); -} - -static struct input_dev * get_input_dev(struct wacom_combo *wcombo) -{ - return wcombo->wacom->dev; -} - -static void wacom_sys_irq(struct urb *urb) -{ - struct wacom *wacom = urb->context; - struct wacom_combo wcombo; - int 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; - } - - wcombo.wacom = wacom; - wcombo.urb = urb; - - if (wacom_wac_irq(wacom->wacom_wac, (void *)&wcombo)) - input_sync(get_input_dev(&wcombo)); - - exit: - retval = usb_submit_urb (urb, GFP_ATOMIC); - if (retval) - err ("%s - usb_submit_urb failed with result %d", - __FUNCTION__, retval); -} - -void wacom_report_key(void *wcombo, unsigned int key_type, int key_data) -{ - input_report_key(get_input_dev((struct wacom_combo *)wcombo), key_type, key_data); - return; -} - -void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data) -{ - input_report_abs(get_input_dev((struct wacom_combo *)wcombo), abs_type, abs_data); - return; -} - -void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data) -{ - input_report_rel(get_input_dev((struct wacom_combo *)wcombo), rel_type, rel_data); - return; -} - -void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value) -{ - input_event(get_input_dev((struct wacom_combo *)wcombo), type, code, value); - return; -} - -__u16 wacom_be16_to_cpu(unsigned char *data) -{ - __u16 value; - value = be16_to_cpu(*(__be16 *) data); - return value; -} - -__u16 wacom_le16_to_cpu(unsigned char *data) -{ - __u16 value; - value = le16_to_cpu(*(__le16 *) data); - return value; -} - -void wacom_input_sync(void *wcombo) -{ - input_sync(get_input_dev((struct wacom_combo *)wcombo)); - return; -} - -static int wacom_open(struct input_dev *dev) -{ - struct wacom *wacom = input_get_drvdata(dev); - - wacom->irq->dev = wacom->usbdev; - if (usb_submit_urb(wacom->irq, GFP_KERNEL)) - return -EIO; - - return 0; -} - -static void wacom_close(struct input_dev *dev) -{ - struct wacom *wacom = input_get_drvdata(dev); - - usb_kill_urb(wacom->irq); -} - -void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - 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_4); -} - -void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - 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_wac->features->distance_max, 0, 0); -} - -void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - 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); - input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); -} - -void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); - input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); -} - -void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - 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); - input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->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); -} - -void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); -} - -void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER); -} - -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; - struct wacom *wacom; - struct wacom_wac *wacom_wac; - struct input_dev *input_dev; - int error = -ENOMEM; - char rep_data[2], limit = 0; - - wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); - wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!wacom || !input_dev || !wacom_wac) - goto fail1; - - wacom_wac->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma); - if (!wacom_wac->data) - goto fail1; - - wacom->irq = usb_alloc_urb(0, GFP_KERNEL); - 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_wac->features = get_wacom_feature(id); - BUG_ON(wacom_wac->features->pktlen > 10); - - input_dev->name = wacom_wac->features->name; - wacom->wacom_wac = wacom_wac; - usb_to_input_id(dev, &input_dev->id); - - input_dev->dev.parent = &intf->dev; - - input_set_drvdata(input_dev, 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_wac->features->x_max, 4, 0); - input_set_abs_params(input_dev, ABS_Y, 0, wacom_wac->features->y_max, 4, 0); - input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_wac->features->pressure_max, 0, 0); - input_dev->absbit[LONG(ABS_MISC)] |= BIT(ABS_MISC); - - wacom_init_input_dev(input_dev, wacom_wac); - - endpoint = &intf->cur_altsetting->endpoint[0].desc; - - usb_fill_int_urb(wacom->irq, dev, - usb_rcvintpipe(dev, endpoint->bEndpointAddress), - wacom_wac->data, wacom_wac->features->pktlen, - wacom_sys_irq, wacom, endpoint->bInterval); - wacom->irq->transfer_dma = wacom->data_dma; - wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - error = input_register_device(wacom->dev); - if (error) - goto fail3; - - /* 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; - - fail3: usb_free_urb(wacom->irq); - fail2: usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma); - fail1: input_free_device(input_dev); - kfree(wacom); - kfree(wacom_wac); - return error; -} - -static void wacom_disconnect(struct usb_interface *intf) -{ - struct wacom *wacom = usb_get_intfdata (intf); - - usb_set_intfdata(intf, NULL); - if (wacom) { - usb_kill_urb(wacom->irq); - input_unregister_device(wacom->dev); - usb_free_urb(wacom->irq); - usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma); - kfree(wacom->wacom_wac); - kfree(wacom); - } -} - -static struct usb_driver wacom_driver = { - .name = "wacom", - .probe = wacom_probe, - .disconnect = wacom_disconnect, -}; - -static int __init wacom_init(void) -{ - int result; - wacom_driver.id_table = get_device_table(); - result = usb_register(&wacom_driver); - if (result == 0) - info(DRIVER_VERSION ":" DRIVER_DESC); - return result; -} - -static void __exit wacom_exit(void) -{ - usb_deregister(&wacom_driver); -} - -module_init(wacom_init); -module_exit(wacom_exit); diff --git a/drivers/usb/input/wacom_wac.c b/drivers/usb/input/wacom_wac.c deleted file mode 100644 index 4f3e9bc7177..00000000000 --- a/drivers/usb/input/wacom_wac.c +++ /dev/null @@ -1,675 +0,0 @@ -/* - * drivers/usb/input/wacom_wac.c - * - * USB Wacom Graphire and Wacom Intuos tablet support - Wacom specific code - * - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ -#include "wacom.h" -#include "wacom_wac.h" - -static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo) -{ - unsigned char *data = wacom->data; - - switch (data[0]) { - case 1: - if (data[5] & 0x80) { - wacom->tool[0] = (data[5] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; - wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID; - wacom_report_key(wcombo, wacom->tool[0], 1); - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ - wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); - wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); - wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127); - wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -127)); - wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40)); - } else { - wacom_report_key(wcombo, wacom->tool[0], 0); - wacom_report_abs(wcombo, ABS_MISC, 0); /* report tool id */ - wacom_report_abs(wcombo, ABS_PRESSURE, -1); - wacom_report_key(wcombo, BTN_TOUCH, 0); - } - break; - case 2: - wacom_report_key(wcombo, BTN_TOOL_PEN, 1); - wacom_report_abs(wcombo, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */ - wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); - wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); - wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127); - wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20)); - wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40)); - break; - default: - printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]); - return 0; - } - return 1; -} - -static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) -{ - unsigned char *data = wacom->data; - int prox, id, pressure; - - if (data[0] != 2) { - dbg("wacom_pl_irq: received unknown report #%d", data[0]); - return 0; - } - - prox = data[1] & 0x40; - - id = ERASER_DEVICE_ID; - if (prox) { - - pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); - if (wacom->features->pressure_max > 255) - pressure = (pressure << 1) | ((data[4] >> 6) & 1); - pressure += (wacom->features->pressure_max + 1) / 2; - - /* - * if going from out of proximity into proximity select between the eraser - * and the pen based on the state of the stylus2 button, choose eraser if - * pressed else choose pen. if not a proximity change from out to in, send - * an out of proximity for previous tool then a in for new tool. - */ - if (!wacom->tool[0]) { - /* 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)) { - /* report out proximity for previous tool */ - wacom_report_key(wcombo, wacom->tool[1], 0); - wacom_input_sync(wcombo); - wacom->tool[1] = BTN_TOOL_PEN; - return 0; - } - } - if (wacom->tool[1] != BTN_TOOL_RUBBER) { - /* Unknown tool selected default to pen tool */ - wacom->tool[1] = BTN_TOOL_PEN; - id = STYLUS_DEVICE_ID; - } - wacom_report_key(wcombo, wacom->tool[1], prox); /* report in proximity for tool */ - wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */ - wacom_report_abs(wcombo, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14)); - wacom_report_abs(wcombo, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14)); - wacom_report_abs(wcombo, ABS_PRESSURE, pressure); - - wacom_report_key(wcombo, BTN_TOUCH, data[4] & 0x08); - wacom_report_key(wcombo, BTN_STYLUS, data[4] & 0x10); - /* Only allow the stylus2 button to be reported for the pen tool. */ - wacom_report_key(wcombo, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20)); - } else { - /* report proximity-out of a (valid) tool */ - if (wacom->tool[1] != BTN_TOOL_RUBBER) { - /* Unknown tool selected default to pen tool */ - wacom->tool[1] = BTN_TOOL_PEN; - } - wacom_report_key(wcombo, wacom->tool[1], prox); - } - - wacom->tool[0] = prox; /* Save proximity state */ - return 1; -} - -static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo) -{ - unsigned char *data = wacom->data; - int id; - - if (data[0] != 2) { - printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); - return 0; - } - - if (data[1] & 0x04) { - wacom_report_key(wcombo, BTN_TOOL_RUBBER, data[1] & 0x20); - wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x08); - id = ERASER_DEVICE_ID; - } else { - wacom_report_key(wcombo, BTN_TOOL_PEN, data[1] & 0x20); - wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); - id = STYLUS_DEVICE_ID; - } - wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */ - wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); - wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); - wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); - wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); - wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); - return 1; -} - -static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) -{ - unsigned char *data = wacom->data; - int x, y, id, rw; - - if (data[0] != 2) { - dbg("wacom_graphire_irq: received unknown report #%d", data[0]); - return 0; - } - - id = STYLUS_DEVICE_ID; - if (data[1] & 0x80) { /* in prox */ - - switch ((data[1] >> 5) & 3) { - - case 0: /* Pen */ - wacom->tool[0] = BTN_TOOL_PEN; - break; - - case 1: /* Rubber */ - wacom->tool[0] = BTN_TOOL_RUBBER; - id = ERASER_DEVICE_ID; - break; - - case 2: /* Mouse with wheel */ - wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04); - if (wacom->features->type == WACOM_G4) { - rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03); - wacom_report_rel(wcombo, REL_WHEEL, -rw); - } else - wacom_report_rel(wcombo, REL_WHEEL, -(signed char) data[6]); - /* fall through */ - - case 3: /* Mouse without wheel */ - wacom->tool[0] = BTN_TOOL_MOUSE; - id = CURSOR_DEVICE_ID; - wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); - wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); - if (wacom->features->type == WACOM_G4) - wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); - else - wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); - break; - } - x = wacom_le16_to_cpu(&data[2]); - y = wacom_le16_to_cpu(&data[4]); - wacom_report_abs(wcombo, ABS_X, x); - wacom_report_abs(wcombo, ABS_Y, y); - if (wacom->tool[0] != BTN_TOOL_MOUSE) { - wacom_report_abs(wcombo, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8)); - wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); - wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); - wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04); - } - wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */ - wacom_report_key(wcombo, wacom->tool[0], 1); - } else if (!(data[1] & 0x90)) { - wacom_report_abs(wcombo, ABS_X, 0); - wacom_report_abs(wcombo, ABS_Y, 0); - if (wacom->tool[0] == BTN_TOOL_MOUSE) { - wacom_report_key(wcombo, BTN_LEFT, 0); - wacom_report_key(wcombo, BTN_RIGHT, 0); - wacom_report_abs(wcombo, ABS_DISTANCE, 0); - } else { - wacom_report_abs(wcombo, ABS_PRESSURE, 0); - wacom_report_key(wcombo, BTN_TOUCH, 0); - wacom_report_key(wcombo, BTN_STYLUS, 0); - wacom_report_key(wcombo, BTN_STYLUS2, 0); - } - wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ - wacom_report_key(wcombo, wacom->tool[0], 0); - } - - /* send pad data */ - if (wacom->features->type == WACOM_G4) { - if (data[7] & 0xf8) { - wacom_input_sync(wcombo); /* sync last event */ - wacom->id[1] = 1; - wacom->serial[1] = (data[7] & 0xf8); - wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); - wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); - rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); - wacom_report_rel(wcombo, REL_WHEEL, rw); - wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); - wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); - } else if (wacom->id[1]) { - wacom_input_sync(wcombo); /* sync last event */ - wacom->id[1] = 0; - wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); - wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); - wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); - wacom_report_abs(wcombo, ABS_MISC, 0); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); - } - } - return 1; -} - -static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) -{ - unsigned char *data = wacom->data; - int idx; - - /* tool number */ - idx = data[1] & 0x01; - - /* Enter report */ - if ((data[1] & 0xfc) == 0xc0) { - /* serial number of the tool */ - wacom->serial[idx] = ((data[3] & 0x0f) << 28) + - (data[4] << 20) + (data[5] << 12) + - (data[6] << 4) + (data[7] >> 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: - wacom->tool[idx] = BTN_TOOL_PENCIL; - break; - case 0x822: /* Pen */ - case 0x842: - case 0x852: - case 0x823: /* Intuos3 Grip Pen */ - case 0x813: /* Intuos3 Classic Pen */ - case 0x885: /* Intuos3 Marker Pen */ - case 0x022: - wacom->tool[idx] = BTN_TOOL_PEN; - break; - case 0x832: /* Stroke pen */ - case 0x032: - wacom->tool[idx] = BTN_TOOL_BRUSH; - break; - case 0x007: /* Mouse 4D and 2D */ - case 0x09c: - case 0x094: - case 0x017: /* Intuos3 2D Mouse */ - wacom->tool[idx] = BTN_TOOL_MOUSE; - break; - case 0x096: /* Lens cursor */ - case 0x097: /* Intuos3 Lens cursor */ - wacom->tool[idx] = BTN_TOOL_LENS; - break; - case 0x82a: /* Eraser */ - case 0x85a: - case 0x91a: - case 0xd1a: - case 0x0fa: - case 0x82b: /* Intuos3 Grip Pen Eraser */ - case 0x81b: /* Intuos3 Classic Pen Eraser */ - case 0x91b: /* Intuos3 Airbrush Eraser */ - wacom->tool[idx] = BTN_TOOL_RUBBER; - break; - case 0xd12: - case 0x912: - case 0x112: - case 0x913: /* Intuos3 Airbrush */ - wacom->tool[idx] = BTN_TOOL_AIRBRUSH; - break; - default: /* Unknown tool */ - wacom->tool[idx] = BTN_TOOL_PEN; - } - return 1; - } - - /* Exit report */ - if ((data[1] & 0xfe) == 0x80) { - wacom_report_abs(wcombo, ABS_X, 0); - wacom_report_abs(wcombo, ABS_Y, 0); - wacom_report_abs(wcombo, ABS_DISTANCE, 0); - if (wacom->tool[idx] >= BTN_TOOL_MOUSE) { - wacom_report_key(wcombo, BTN_LEFT, 0); - wacom_report_key(wcombo, BTN_MIDDLE, 0); - wacom_report_key(wcombo, BTN_RIGHT, 0); - wacom_report_key(wcombo, BTN_SIDE, 0); - wacom_report_key(wcombo, BTN_EXTRA, 0); - wacom_report_abs(wcombo, ABS_THROTTLE, 0); - wacom_report_abs(wcombo, ABS_RZ, 0); - } else { - wacom_report_abs(wcombo, ABS_PRESSURE, 0); - wacom_report_abs(wcombo, ABS_TILT_X, 0); - wacom_report_abs(wcombo, ABS_TILT_Y, 0); - wacom_report_key(wcombo, BTN_STYLUS, 0); - wacom_report_key(wcombo, BTN_STYLUS2, 0); - wacom_report_key(wcombo, BTN_TOUCH, 0); - wacom_report_abs(wcombo, ABS_WHEEL, 0); - } - wacom_report_key(wcombo, wacom->tool[idx], 0); - wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); - return 2; - } - return 0; -} - -static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) -{ - unsigned char *data = wacom->data; - unsigned int t; - - /* general pen packet */ - if ((data[1] & 0xb8) == 0xa0) { - t = (data[6] << 2) | ((data[7] >> 6) & 3); - wacom_report_abs(wcombo, ABS_PRESSURE, t); - wacom_report_abs(wcombo, ABS_TILT_X, - ((data[7] << 1) & 0x7e) | (data[8] >> 7)); - wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f); - wacom_report_key(wcombo, BTN_STYLUS, data[1] & 2); - wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 4); - wacom_report_key(wcombo, BTN_TOUCH, t > 10); - } - - /* airbrush second packet */ - if ((data[1] & 0xbc) == 0xb4) { - wacom_report_abs(wcombo, ABS_WHEEL, - (data[6] << 2) | ((data[7] >> 6) & 3)); - wacom_report_abs(wcombo, ABS_TILT_X, - ((data[7] << 1) & 0x7e) | (data[8] >> 7)); - wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f); - } - return; -} - -static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) -{ - unsigned char *data = wacom->data; - unsigned int t; - int idx, result; - - if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) { - dbg("wacom_intuos_irq: received unknown report #%d", data[0]); - return 0; - } - - /* tool number */ - idx = data[1] & 0x01; - - /* pad packets. Works as a second tool and is always in prox */ - if (data[0] == 12) { - /* initiate the pad as a device */ - if (wacom->tool[1] != BTN_TOOL_FINGER) - wacom->tool[1] = BTN_TOOL_FINGER; - - wacom_report_key(wcombo, BTN_0, (data[5] & 0x01)); - wacom_report_key(wcombo, BTN_1, (data[5] & 0x02)); - wacom_report_key(wcombo, BTN_2, (data[5] & 0x04)); - wacom_report_key(wcombo, BTN_3, (data[5] & 0x08)); - wacom_report_key(wcombo, BTN_4, (data[6] & 0x01)); - wacom_report_key(wcombo, BTN_5, (data[6] & 0x02)); - wacom_report_key(wcombo, BTN_6, (data[6] & 0x04)); - wacom_report_key(wcombo, BTN_7, (data[6] & 0x08)); - wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]); - wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); - - if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) | - data[2] | (data[3] & 0x1f) | data[4]) - wacom_report_key(wcombo, wacom->tool[1], 1); - else - wacom_report_key(wcombo, wacom->tool[1], 0); - wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff); - return 1; - } - - /* process in/out prox events */ - result = wacom_intuos_inout(wacom, wcombo); - if (result) - return result-1; - - /* Only large I3 and I1 & I2 support Lense Cursor */ - if((wacom->tool[idx] == BTN_TOOL_LENS) - && ((wacom->features->type == INTUOS3) - || (wacom->features->type == INTUOS3S))) - return 0; - - /* Cintiq doesn't send data when RDY bit isn't set */ - if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40)) - return 0; - - if (wacom->features->type >= INTUOS3S) { - wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); - wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1)); - wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); - } else { - wacom_report_abs(wcombo, ABS_X, wacom_be16_to_cpu(&data[2])); - wacom_report_abs(wcombo, ABS_Y, wacom_be16_to_cpu(&data[4])); - wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 3) & 0x1f)); - } - - /* process general packets */ - wacom_intuos_general(wacom, wcombo); - - /* 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 >= INTUOS3S) { - /* 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) ; - wacom_report_abs(wcombo, ABS_WHEEL, t); - } else { - /* 4D mouse rotation packet */ - t = (data[6] << 3) | ((data[7] >> 5) & 7); - wacom_report_abs(wcombo, ABS_RZ, (data[7] & 0x20) ? - ((t - 1) / 2) : -t / 2); - } - - } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3S) { - /* 4D mouse packet */ - wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); - wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); - wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x04); - - wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x20); - wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x10); - t = (data[6] << 2) | ((data[7] >> 6) & 3); - wacom_report_abs(wcombo, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); - - } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { - /* 2D mouse packet */ - wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x04); - wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x08); - wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x10); - wacom_report_rel(wcombo, REL_WHEEL, (data[8] & 0x01) - - ((data[8] & 0x02) >> 1)); - - /* I3 2D mouse side buttons */ - if (wacom->features->type >= INTUOS3S && wacom->features->type <= INTUOS3L) { - wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x40); - wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x20); - } - - } else if (wacom->features->type < INTUOS3S || wacom->features->type == INTUOS3L) { - /* Lens cursor packets */ - wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); - wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); - wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x04); - wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x10); - wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x08); - } - } - - wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */ - wacom_report_key(wcombo, wacom->tool[idx], 1); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); - return 1; -} - -int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) -{ - switch (wacom_wac->features->type) { - case PENPARTNER: - return (wacom_penpartner_irq(wacom_wac, wcombo)); - break; - case PL: - return (wacom_pl_irq(wacom_wac, wcombo)); - break; - case WACOM_G4: - case GRAPHIRE: - return (wacom_graphire_irq(wacom_wac, wcombo)); - break; - case PTU: - return (wacom_ptu_irq(wacom_wac, wcombo)); - break; - case INTUOS: - case INTUOS3S: - case INTUOS3: - case INTUOS3L: - case CINTIQ: - return (wacom_intuos_irq(wacom_wac, wcombo)); - break; - default: - return 0; - } - return 0; -} - -void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac) -{ - switch (wacom_wac->features->type) { - case WACOM_G4: - input_dev_g4(input_dev, wacom_wac); - /* fall through */ - case GRAPHIRE: - input_dev_g(input_dev, wacom_wac); - break; - case INTUOS3: - case INTUOS3L: - case CINTIQ: - input_dev_i3(input_dev, wacom_wac); - /* fall through */ - case INTUOS3S: - input_dev_i3s(input_dev, wacom_wac); - case INTUOS: - input_dev_i(input_dev, wacom_wac); - break; - case PL: - case PTU: - input_dev_pl(input_dev, wacom_wac); - break; - case PENPARTNER: - input_dev_pt(input_dev, wacom_wac); - break; - } - return; -} - -static struct wacom_features wacom_features[] = { - { "Wacom Penpartner", 7, 5040, 3780, 255, 0, PENPARTNER }, - { "Wacom Graphire", 8, 10206, 7422, 511, 63, GRAPHIRE }, - { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 63, GRAPHIRE }, - { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 63, GRAPHIRE }, - { "Wacom Graphire3", 8, 10208, 7424, 511, 63, GRAPHIRE }, - { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 63, GRAPHIRE }, - { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 63, WACOM_G4 }, - { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 63, WACOM_G4 }, - { "Wacom Volito", 8, 5104, 3712, 511, 63, GRAPHIRE }, - { "Wacom PenStation2", 8, 3250, 2320, 255, 63, GRAPHIRE }, - { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE }, - { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 63, GRAPHIRE }, - { "Wacom PenPartner2", 8, 3250, 2320, 255, 63, GRAPHIRE }, - { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, - { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, - { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 31, INTUOS }, - { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 31, INTUOS }, - { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 31, INTUOS }, - { "Wacom PL400", 8, 5408, 4056, 255, 0, PL }, - { "Wacom PL500", 8, 6144, 4608, 255, 0, PL }, - { "Wacom PL600", 8, 6126, 4604, 255, 0, PL }, - { "Wacom PL600SX", 8, 6260, 5016, 255, 0, PL }, - { "Wacom PL550", 8, 6144, 4608, 511, 0, PL }, - { "Wacom PL800", 8, 7220, 5780, 511, 0, PL }, - { "Wacom PL700", 8, 6758, 5406, 511, 0, PL }, - { "Wacom PL510", 8, 6282, 4762, 511, 0, PL }, - { "Wacom DTU710", 8, 34080, 27660, 511, 0, PL }, - { "Wacom DTF521", 8, 6282, 4762, 511, 0, PL }, - { "Wacom DTF720", 8, 6858, 5506, 511, 0, PL }, - { "Wacom Cintiq Partner",8, 20480, 15360, 511, 0, PTU }, - { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, - { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, - { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 31, INTUOS }, - { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 31, INTUOS }, - { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 31, INTUOS }, - { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 63, INTUOS3S }, - { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 63, INTUOS3 }, - { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 63, INTUOS3 }, - { "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 63, INTUOS3L }, - { "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 63, INTUOS3L }, - { "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 63, INTUOS3 }, - { "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 63, INTUOS3S }, - { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ }, - { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, - { } -}; - -static struct usb_device_id wacom_ids[] = { - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x00) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11) }, - { 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) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x30) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x32) }, - { 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, 0xC4) }, - { 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, 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, 0xB7) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, - { } -}; - -const struct usb_device_id * get_device_table(void) { - const struct usb_device_id * id_table = wacom_ids; - return id_table; -} - -struct wacom_features * get_wacom_feature(const struct usb_device_id * id) { - int index = id - wacom_ids; - struct wacom_features *wf = &wacom_features[index]; - return wf; -} - -MODULE_DEVICE_TABLE(usb, wacom_ids); diff --git a/drivers/usb/input/wacom_wac.h b/drivers/usb/input/wacom_wac.h deleted file mode 100644 index 89793666ee8..00000000000 --- a/drivers/usb/input/wacom_wac.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * drivers/usb/input/wacom_wac.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ -#ifndef WACOM_WAC_H -#define WACOM_WAC_H - -#define STYLUS_DEVICE_ID 0x02 -#define CURSOR_DEVICE_ID 0x06 -#define ERASER_DEVICE_ID 0x0A -#define PAD_DEVICE_ID 0x0F - -enum { - PENPARTNER = 0, - GRAPHIRE, - WACOM_G4, - PTU, - PL, - INTUOS, - INTUOS3S, - INTUOS3, - INTUOS3L, - CINTIQ, - MAX_TYPE -}; - -struct wacom_features { - char *name; - int pktlen; - int x_max; - int y_max; - int pressure_max; - int distance_max; - int type; -}; - -struct wacom_wac { - unsigned char *data; - int tool[2]; - int id[2]; - __u32 serial[2]; - struct wacom_features *features; -}; - -#endif |