diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 11:51:43 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 11:51:43 -0700 |
commit | 393bfca19ecdce60a8d9a4d2577cac11ca924a25 (patch) | |
tree | a609269ca3332b8f2f7b2b4a2c96f7d824c0e639 /drivers/usb | |
parent | df6d3916f3b7b7e2067567a256dd4f0c1ea854a2 (diff) | |
parent | ba0acb5ee318901646f82c134cca2e4de0c43934 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/dtor/input
* master.kernel.org:/pub/scm/linux/kernel/git/dtor/input:
Input: move USB miscellaneous devices under drivers/input/misc
Input: move USB mice under drivers/input/mouse
Input: move USB gamepads under drivers/input/joystick
Input: move USB touchscreens under drivers/input/touchscreen
Input: move USB tablets under drivers/input/tablet
Input: i8042 - fix AUX port detection with some chips
Input: aaed2000_kbd - convert to use polldev library
Input: drivers/usb/input - usb_buffer_free() cleanup
Input: synaptics - don't complain about failed resets
Input: pull input.h into uinpit.h
Input: drivers/usb/input - fix sparse warnings (signedness)
Input: evdev - fix some sparse warnings (signedness, shadowing)
Input: drivers/joystick - fix various sparse warnings
Input: force feedback - make sure effect is present before playing
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/Makefile | 9 | ||||
-rw-r--r-- | drivers/usb/input/Kconfig | 225 | ||||
-rw-r--r-- | drivers/usb/input/Makefile | 24 | ||||
-rw-r--r-- | drivers/usb/input/acecad.c | 289 | ||||
-rw-r--r-- | drivers/usb/input/aiptek.c | 2236 | ||||
-rw-r--r-- | drivers/usb/input/appletouch.c | 706 | ||||
-rw-r--r-- | drivers/usb/input/ati_remote.c | 862 | ||||
-rw-r--r-- | drivers/usb/input/ati_remote2.c | 545 | ||||
-rw-r--r-- | drivers/usb/input/gtco.c | 1055 | ||||
-rw-r--r-- | drivers/usb/input/kbtab.c | 226 | ||||
-rw-r--r-- | drivers/usb/input/keyspan_remote.c | 592 | ||||
-rw-r--r-- | drivers/usb/input/map_to_7segment.h | 189 | ||||
-rw-r--r-- | drivers/usb/input/powermate.c | 465 | ||||
-rw-r--r-- | drivers/usb/input/usbtouchscreen.c | 840 | ||||
-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 | ||||
-rw-r--r-- | drivers/usb/input/xpad.c | 433 | ||||
-rw-r--r-- | drivers/usb/input/yealink.c | 1005 | ||||
-rw-r--r-- | drivers/usb/input/yealink.h | 220 |
22 files changed, 0 insertions, 11096 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 9980a4ddfed..b847bbc8b0e 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -85,8 +85,6 @@ source "drivers/usb/class/Kconfig" source "drivers/usb/storage/Kconfig" -source "drivers/usb/input/Kconfig" - source "drivers/usb/image/Kconfig" source "drivers/usb/net/Kconfig" diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index f5de58a63f2..0ef090b1b37 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -23,15 +23,6 @@ obj-$(CONFIG_USB_PRINTER) += class/ obj-$(CONFIG_USB_STORAGE) += storage/ obj-$(CONFIG_USB) += storage/ -obj-$(CONFIG_USB_ACECAD) += input/ -obj-$(CONFIG_USB_AIPTEK) += input/ -obj-$(CONFIG_USB_ATI_REMOTE) += input/ -obj-$(CONFIG_USB_KBTAB) += input/ -obj-$(CONFIG_USB_MTOUCH) += input/ -obj-$(CONFIG_USB_POWERMATE) += input/ -obj-$(CONFIG_USB_WACOM) += input/ -obj-$(CONFIG_USB_XPAD) += input/ - obj-$(CONFIG_USB_CATC) += net/ obj-$(CONFIG_USB_KAWETH) += net/ obj-$(CONFIG_USB_PEGASUS) += net/ diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig deleted file mode 100644 index a792e42f58a..00000000000 --- a/drivers/usb/input/Kconfig +++ /dev/null @@ -1,225 +0,0 @@ -# -# USB Input driver configuration -# -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 - ---help--- - Say Y here if you want to use Griffin PowerMate or Contour Jog devices. - These are aluminum dials which can measure clockwise and anticlockwise - rotation. The dial also acts as a pushbutton. The base contains an LED - which can be instructed to pulse or to switch to a particular intensity. - - You can download userspace tools from - <http://sowerbutts.com/powermate/>. - - To compile this driver as a module, choose M here: the - module will be called powermate. - -config USB_TOUCHSCREEN - tristate "USB Touchscreen Driver" - depends on USB && INPUT - ---help--- - USB Touchscreen driver for: - - eGalax Touchkit USB (also includes eTurboTouch CT-410/510/700) - - PanJit TouchSet USB - - 3M MicroTouch USB (EX II series) - - ITM - - some other eTurboTouch - - Gunze AHL61 - - DMC TSC-10/25 - - Have a look at <http://linux.chapter7.ch/touchkit/> for - a usage description and the required user-space stuff. - - To compile this driver as a module, choose M here: the - module will be called usbtouchscreen. - -config USB_TOUCHSCREEN_EGALAX - default y - bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED - depends on USB_TOUCHSCREEN - -config USB_TOUCHSCREEN_PANJIT - default y - bool "PanJit device support" if EMBEDDED - depends on USB_TOUCHSCREEN - -config USB_TOUCHSCREEN_3M - default y - bool "3M/Microtouch EX II series device support" if EMBEDDED - depends on USB_TOUCHSCREEN - -config USB_TOUCHSCREEN_ITM - default y - bool "ITM device support" if EMBEDDED - depends on USB_TOUCHSCREEN - -config USB_TOUCHSCREEN_ETURBO - default y - bool "eTurboTouch (non-eGalax compatible) device support" if EMBEDDED - depends on USB_TOUCHSCREEN - -config USB_TOUCHSCREEN_GUNZE - default y - bool "Gunze AHL61 device support" if EMBEDDED - depends on USB_TOUCHSCREEN - -config USB_TOUCHSCREEN_DMC_TSC10 - default y - bool "DMC TSC-10/25 device support" if EMBEDDED - depends on USB_TOUCHSCREEN - -config USB_YEALINK - tristate "Yealink usb-p1k voip phone" - depends on USB && INPUT && EXPERIMENTAL - ---help--- - Say Y here if you want to enable keyboard and LCD functions of the - Yealink usb-p1k usb phones. The audio part is enabled by the generic - usb sound driver, so you might want to enable that as well. - - For information about how to use these additional functions, see - <file:Documentation/input/yealink.txt>. - - To compile this driver as a module, choose M here: the module will be - called yealink. - -config USB_XPAD - tristate "X-Box gamepad support" - depends on USB && INPUT - ---help--- - Say Y here if you want to use the X-Box pad with your computer. - Make sure to say Y to "Joystick support" (CONFIG_INPUT_JOYDEV) - and/or "Event interface support" (CONFIG_INPUT_EVDEV) as well. - - For information about how to connect the X-Box pad to USB, see - <file:Documentation/input/xpad.txt>. - - To compile this driver as a module, choose M here: the - module will be called xpad. - -config USB_ATI_REMOTE - tristate "ATI / X10 USB RF remote control" - depends on USB && INPUT - ---help--- - Say Y here if you want to use an ATI or X10 "Lola" USB remote control. - These are RF remotes with USB receivers. - The ATI remote comes with many of ATI's All-In-Wonder video cards. - The X10 "Lola" remote is available at: - <http://www.x10.com/products/lola_sg1.htm> - This driver provides mouse pointer, left and right mouse buttons, - and maps all the other remote buttons to keypress events. - - To compile this driver as a module, choose M here: the module will be - called ati_remote. - -config USB_ATI_REMOTE2 - tristate "ATI / Philips USB RF remote control" - depends on USB && INPUT - ---help--- - Say Y here if you want to use an ATI or Philips USB RF remote control. - These are RF remotes with USB receivers. - ATI Remote Wonder II comes with some ATI's All-In-Wonder video cards - and is also available as a separate product. - This driver provides mouse pointer, left and right mouse buttons, - and maps all the other remote buttons to keypress events. - - To compile this driver as a module, choose M here: the module will be - called ati_remote2. - -config USB_KEYSPAN_REMOTE - tristate "Keyspan DMR USB remote control (EXPERIMENTAL)" - depends on USB && INPUT && EXPERIMENTAL - ---help--- - Say Y here if you want to use a Keyspan DMR USB remote control. - Currently only the UIA-11 type of receiver has been tested. The tag - on the receiver that connects to the USB port should have a P/N that - will tell you what type of DMR you have. The UIA-10 type is not - supported at this time. This driver maps all buttons to keypress - events. - - To compile this driver as a module, choose M here: the module will - be called keyspan_remote. - -config USB_APPLETOUCH - tristate "Apple USB Touchpad support" - depends on USB && INPUT - ---help--- - Say Y here if you want to use an Apple USB Touchpad. - - These are the touchpads that can be found on post-February 2005 - Apple Powerbooks (prior models have a Synaptics touchpad connected - to the ADB bus). - - This driver provides a basic mouse driver but can be interfaced - with the synaptics X11 driver to provide acceleration and - scrolling in X11. - - For further information, see - <file:Documentation/input/appletouch.txt>. - - 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 deleted file mode 100644 index 284a0734e0c..00000000000 --- a/drivers/usb/input/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -# -# 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 -endif diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c deleted file mode 100644 index be8e9243c06..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; - - signed 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/appletouch.c b/drivers/usb/input/appletouch.c deleted file mode 100644 index e3215267db1..00000000000 --- a/drivers/usb/input/appletouch.c +++ /dev/null @@ -1,706 +0,0 @@ -/* - * Apple USB Touchpad (for post-February 2005 PowerBooks and MacBooks) driver - * - * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net) - * Copyright (C) 2005 Stelian Pop (stelian@popies.net) - * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) - * Copyright (C) 2005 Peter Osterlund (petero2@telia.com) - * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch) - * Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch) - * - * Thanks to Alex Harper <basilisk@foobox.net> for his inputs. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/usb/input.h> - -/* Apple has powerbooks which have the keyboard with different Product IDs */ -#define APPLE_VENDOR_ID 0x05AC - -/* These names come from Info.plist in AppleUSBTrackpad.kext */ -#define FOUNTAIN_ANSI_PRODUCT_ID 0x020E -#define FOUNTAIN_ISO_PRODUCT_ID 0x020F - -#define FOUNTAIN_TP_ONLY_PRODUCT_ID 0x030A - -#define GEYSER1_TP_ONLY_PRODUCT_ID 0x030B - -#define GEYSER_ANSI_PRODUCT_ID 0x0214 -#define GEYSER_ISO_PRODUCT_ID 0x0215 -#define GEYSER_JIS_PRODUCT_ID 0x0216 - -/* MacBook devices */ -#define GEYSER3_ANSI_PRODUCT_ID 0x0217 -#define GEYSER3_ISO_PRODUCT_ID 0x0218 -#define GEYSER3_JIS_PRODUCT_ID 0x0219 - -/* - * Geyser IV: same as Geyser III according to Info.plist in AppleUSBTrackpad.kext - * -> same IOClass (AppleUSBGrIIITrackpad), same acceleration tables - */ -#define GEYSER4_ANSI_PRODUCT_ID 0x021A -#define GEYSER4_ISO_PRODUCT_ID 0x021B -#define GEYSER4_JIS_PRODUCT_ID 0x021C - -#define ATP_DEVICE(prod) \ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ - USB_DEVICE_ID_MATCH_INT_CLASS | \ - USB_DEVICE_ID_MATCH_INT_PROTOCOL, \ - .idVendor = APPLE_VENDOR_ID, \ - .idProduct = (prod), \ - .bInterfaceClass = 0x03, \ - .bInterfaceProtocol = 0x02 - -/* table of devices that work with this driver */ -static struct usb_device_id atp_table [] = { - { ATP_DEVICE(FOUNTAIN_ANSI_PRODUCT_ID) }, - { ATP_DEVICE(FOUNTAIN_ISO_PRODUCT_ID) }, - { ATP_DEVICE(FOUNTAIN_TP_ONLY_PRODUCT_ID) }, - { ATP_DEVICE(GEYSER1_TP_ONLY_PRODUCT_ID) }, - - /* PowerBooks Oct 2005 */ - { ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) }, - { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) }, - { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) }, - - /* Core Duo MacBook & MacBook Pro */ - { ATP_DEVICE(GEYSER3_ANSI_PRODUCT_ID) }, - { ATP_DEVICE(GEYSER3_ISO_PRODUCT_ID) }, - { ATP_DEVICE(GEYSER3_JIS_PRODUCT_ID) }, - - /* Core2 Duo MacBook & MacBook Pro */ - { ATP_DEVICE(GEYSER4_ANSI_PRODUCT_ID) }, - { ATP_DEVICE(GEYSER4_ISO_PRODUCT_ID) }, - { ATP_DEVICE(GEYSER4_JIS_PRODUCT_ID) }, - - /* Terminating entry */ - { } -}; -MODULE_DEVICE_TABLE (usb, atp_table); - -/* - * number of sensors. Note that only 16 instead of 26 X (horizontal) - * sensors exist on 12" and 15" PowerBooks. All models have 16 Y - * (vertical) sensors. - */ -#define ATP_XSENSORS 26 -#define ATP_YSENSORS 16 - -/* amount of fuzz this touchpad generates */ -#define ATP_FUZZ 16 - -/* maximum pressure this driver will report */ -#define ATP_PRESSURE 300 -/* - * multiplication factor for the X and Y coordinates. - * We try to keep the touchpad aspect ratio while still doing only simple - * arithmetics. - * The factors below give coordinates like: - * 0 <= x < 960 on 12" and 15" Powerbooks - * 0 <= x < 1600 on 17" Powerbooks - * 0 <= y < 646 - */ -#define ATP_XFACT 64 -#define ATP_YFACT 43 - -/* - * Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is - * ignored. - */ -#define ATP_THRESHOLD 5 - -/* MacBook Pro (Geyser 3 & 4) initialization constants */ -#define ATP_GEYSER3_MODE_READ_REQUEST_ID 1 -#define ATP_GEYSER3_MODE_WRITE_REQUEST_ID 9 -#define ATP_GEYSER3_MODE_REQUEST_VALUE 0x300 -#define ATP_GEYSER3_MODE_REQUEST_INDEX 0 -#define ATP_GEYSER3_MODE_VENDOR_VALUE 0x04 - -/* Structure to hold all of our device specific stuff */ -struct atp { - char phys[64]; - struct usb_device * udev; /* usb device */ - struct urb * urb; /* usb request block */ - signed char * data; /* transferred data */ - int open; /* non-zero if opened */ - struct input_dev *input; /* input dev */ - int valid; /* are the sensors valid ? */ - int x_old; /* last reported x/y, */ - int y_old; /* used for smoothing */ - /* current value of the sensors */ - signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS]; - /* last value of the sensors */ - signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; - /* accumulated sensors */ - int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; - int overflowwarn; /* overflow warning printed? */ - int datalen; /* size of an USB urb transfer */ -}; - -#define dbg_dump(msg, tab) \ - if (debug > 1) { \ - int i; \ - printk("appletouch: %s %lld", msg, (long long)jiffies); \ - for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) \ - printk(" %02x", tab[i]); \ - printk("\n"); \ - } - -#define dprintk(format, a...) \ - do { \ - if (debug) printk(format, ##a); \ - } while (0) - -MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann"); -MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver"); -MODULE_LICENSE("GPL"); - -/* - * Make the threshold a module parameter - */ -static int threshold = ATP_THRESHOLD; -module_param(threshold, int, 0644); -MODULE_PARM_DESC(threshold, "Discards any change in data from a sensor (trackpad has hundreds of these sensors) less than this value"); - -static int debug = 1; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Activate debugging output"); - -/* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */ -static inline int atp_is_geyser_2(struct atp *dev) -{ - u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct); - - return (productId == GEYSER_ANSI_PRODUCT_ID) || - (productId == GEYSER_ISO_PRODUCT_ID) || - (productId == GEYSER_JIS_PRODUCT_ID); -} - -static inline int atp_is_geyser_3(struct atp *dev) -{ - u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct); - - return (productId == GEYSER3_ANSI_PRODUCT_ID) || - (productId == GEYSER3_ISO_PRODUCT_ID) || - (productId == GEYSER3_JIS_PRODUCT_ID) || - (productId == GEYSER4_ANSI_PRODUCT_ID) || - (productId == GEYSER4_ISO_PRODUCT_ID) || - (productId == GEYSER4_JIS_PRODUCT_ID); -} - -static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, - int *z, int *fingers) -{ - int i; - /* values to calculate mean */ - int pcum = 0, psum = 0; - int is_increasing = 0; - - *fingers = 0; - - for (i = 0; i < nb_sensors; i++) { - if (xy_sensors[i] < threshold) { - if (is_increasing) - is_increasing = 0; - - continue; - } - - /* - * Makes the finger detection more versatile. For example, - * two fingers with no gap will be detected. Also, my - * tests show it less likely to have intermittent loss - * of multiple finger readings while moving around (scrolling). - * - * Changes the multiple finger detection to counting humps on - * sensors (transitions from nonincreasing to increasing) - * instead of counting transitions from low sensors (no - * finger reading) to high sensors (finger above - * sensor) - * - * - Jason Parekh <jasonparekh@gmail.com> - */ - if (i < 1 || (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) { - (*fingers)++; - is_increasing = 1; - } else if (i > 0 && xy_sensors[i - 1] >= xy_sensors[i]) { - is_increasing = 0; - } - - /* - * Subtracts threshold so a high sensor that just passes the threshold - * won't skew the calculated absolute coordinate. Fixes an issue - * where slowly moving the mouse would occassionaly jump a number of - * pixels (let me restate--slowly moving the mouse makes this issue - * most apparent). - */ - pcum += (xy_sensors[i] - threshold) * i; - psum += (xy_sensors[i] - threshold); - } - - if (psum > 0) { - *z = psum; - return pcum * fact / psum; - } - - return 0; -} - -static inline void atp_report_fingers(struct input_dev *input, int fingers) -{ - input_report_key(input, BTN_TOOL_FINGER, fingers == 1); - input_report_key(input, BTN_TOOL_DOUBLETAP, fingers == 2); - input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2); -} - -static void atp_complete(struct urb* urb) -{ - int x, y, x_z, y_z, x_f, y_f; - int retval, i, j; - struct atp *dev = urb->context; - - switch (urb->status) { - case 0: - /* success */ - break; - case -EOVERFLOW: - if(!dev->overflowwarn) { - printk("appletouch: OVERFLOW with data " - "length %d, actual length is %d\n", - dev->datalen, dev->urb->actual_length); - dev->overflowwarn = 1; - } - 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; - } - - /* drop incomplete datasets */ - if (dev->urb->actual_length != dev->datalen) { - dprintk("appletouch: incomplete data package" - " (first byte: %d, length: %d).\n", - dev->data[0], dev->urb->actual_length); - goto exit; - } - - /* reorder the sensors values */ - if (atp_is_geyser_3(dev)) { - memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); - - /* - * The values are laid out like this: - * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ... - * '-' is an unused value. - */ - - /* read X values */ - for (i = 0, j = 19; i < 20; i += 2, j += 3) { - dev->xy_cur[i] = dev->data[j + 1]; - dev->xy_cur[i + 1] = dev->data[j + 2]; - } - /* read Y values */ - for (i = 0, j = 1; i < 9; i += 2, j += 3) { - dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1]; - dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2]; - } - } else if (atp_is_geyser_2(dev)) { - memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); - - /* - * The values are laid out like this: - * Y1, Y2, -, Y3, Y4, -, ..., X1, X2, -, X3, X4, -, ... - * '-' is an unused value. - */ - - /* read X values */ - for (i = 0, j = 19; i < 20; i += 2, j += 3) { - dev->xy_cur[i] = dev->data[j]; - dev->xy_cur[i + 1] = dev->data[j + 1]; - } - - /* read Y values */ - for (i = 0, j = 1; i < 9; i += 2, j += 3) { - dev->xy_cur[ATP_XSENSORS + i] = dev->data[j]; - dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 1]; - } - } else { - for (i = 0; i < 8; i++) { - /* X values */ - dev->xy_cur[i ] = dev->data[5 * i + 2]; - dev->xy_cur[i + 8] = dev->data[5 * i + 4]; - dev->xy_cur[i + 16] = dev->data[5 * i + 42]; - if (i < 2) - dev->xy_cur[i + 24] = dev->data[5 * i + 44]; - - /* Y values */ - dev->xy_cur[i + 26] = dev->data[5 * i + 1]; - dev->xy_cur[i + 34] = dev->data[5 * i + 3]; - } - } - - dbg_dump("sample", dev->xy_cur); - - if (!dev->valid) { - /* first sample */ - dev->valid = 1; - dev->x_old = dev->y_old = -1; - memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); - - if (atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */ - goto exit; - - /* 17" Powerbooks have extra X sensors */ - for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) { - if (!dev->xy_cur[i]) continue; - - printk("appletouch: 17\" model detected.\n"); - if(atp_is_geyser_2(dev)) - input_set_abs_params(dev->input, ABS_X, 0, - (20 - 1) * - ATP_XFACT - 1, - ATP_FUZZ, 0); - else - input_set_abs_params(dev->input, ABS_X, 0, - (ATP_XSENSORS - 1) * - ATP_XFACT - 1, - ATP_FUZZ, 0); - - break; - } - - goto exit; - } - - for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { - /* accumulate the change */ - signed char change = dev->xy_old[i] - dev->xy_cur[i]; - dev->xy_acc[i] -= change; - - /* prevent down drifting */ - if (dev->xy_acc[i] < 0) - dev->xy_acc[i] = 0; - } - - memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); - - dbg_dump("accumulator", dev->xy_acc); - - x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS, - ATP_XFACT, &x_z, &x_f); - y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, - ATP_YFACT, &y_z, &y_f); - - if (x && y) { - if (dev->x_old != -1) { - x = (dev->x_old * 3 + x) >> 2; - y = (dev->y_old * 3 + y) >> 2; - dev->x_old = x; - dev->y_old = y; - - if (debug > 1) - printk("appletouch: X: %3d Y: %3d " - "Xz: %3d Yz: %3d\n", - x, y, x_z, y_z); - - input_report_key(dev->input, BTN_TOUCH, 1); - input_report_abs(dev->input, ABS_X, x); - input_report_abs(dev->input, ABS_Y, y); - input_report_abs(dev->input, ABS_PRESSURE, - min(ATP_PRESSURE, x_z + y_z)); - atp_report_fingers(dev->input, max(x_f, y_f)); - } - dev->x_old = x; - dev->y_old = y; - } - else if (!x && !y) { - - dev->x_old = dev->y_old = -1; - input_report_key(dev->input, BTN_TOUCH, 0); - input_report_abs(dev->input, ABS_PRESSURE, 0); - atp_report_fingers(dev->input, 0); - - /* reset the accumulator on release */ - memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); - } - - input_report_key(dev->input, BTN_LEFT, - !!dev->data[dev->datalen - 1]); - - input_sync(dev->input); - -exit: - retval = usb_submit_urb(dev->urb, GFP_ATOMIC); - if (retval) { - err("%s - usb_submit_urb failed with result %d", - __FUNCTION__, retval); - } -} - -static int atp_open(struct input_dev *input) -{ - struct atp *dev = input_get_drvdata(input); - - if (usb_submit_urb(dev->urb, GFP_ATOMIC)) - return -EIO; - - dev->open = 1; - return 0; -} - -static void atp_close(struct input_dev *input) -{ - struct atp *dev = input_get_drvdata(input); - - usb_kill_urb(dev->urb); - dev->open = 0; -} - -static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id) -{ - struct atp *dev; - struct input_dev *input_dev; - struct usb_device *udev = interface_to_usbdev(iface); - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - int int_in_endpointAddr = 0; - int i, error = -ENOMEM; - - /* set up the endpoint information */ - /* use only the first interrupt-in endpoint */ - iface_desc = iface->cur_altsetting; - for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { - endpoint = &iface_desc->endpoint[i].desc; - if (!int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) { - /* we found an interrupt in endpoint */ - int_in_endpointAddr = endpoint->bEndpointAddress; - break; - } - } - if (!int_in_endpointAddr) { - err("Could not find int-in endpoint"); - return -EIO; - } - - /* allocate memory for our device state and initialize it */ - dev = kzalloc(sizeof(struct atp), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!dev || !input_dev) { - err("Out of memory"); - goto err_free_devs; - } - - dev->udev = udev; - dev->input = input_dev; - dev->overflowwarn = 0; - if (atp_is_geyser_3(dev)) - dev->datalen = 64; - else if (atp_is_geyser_2(dev)) - dev->datalen = 64; - else - dev->datalen = 81; - - if (atp_is_geyser_3(dev)) { - /* - * By default Geyser 3 device sends standard USB HID mouse - * packets (Report ID 2). This code changes device mode, so it - * sends raw sensor reports (Report ID 5). - */ - char data[8]; - int size; - - size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - ATP_GEYSER3_MODE_READ_REQUEST_ID, - USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - ATP_GEYSER3_MODE_REQUEST_VALUE, - ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000); - - if (size != 8) { - err("Could not do mode read request from device" - " (Geyser 3 mode)"); - goto err_free_devs; - } - - /* Apply the mode switch */ - data[0] = ATP_GEYSER3_MODE_VENDOR_VALUE; - - size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - ATP_GEYSER3_MODE_WRITE_REQUEST_ID, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - ATP_GEYSER3_MODE_REQUEST_VALUE, - ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000); - - if (size != 8) { - err("Could not do mode write request to device" - " (Geyser 3 mode)"); - goto err_free_devs; - } - printk("appletouch Geyser 3 inited.\n"); - } - - dev->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->urb) - goto err_free_devs; - - dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL, - &dev->urb->transfer_dma); - if (!dev->data) - goto err_free_urb; - - usb_fill_int_urb(dev->urb, udev, - usb_rcvintpipe(udev, int_in_endpointAddr), - dev->data, dev->datalen, atp_complete, dev, 1); - - usb_make_path(udev, dev->phys, sizeof(dev->phys)); - strlcat(dev->phys, "/input0", sizeof(dev->phys)); - - input_dev->name = "appletouch"; - input_dev->phys = dev->phys; - usb_to_input_id(dev->udev, &input_dev->id); - input_dev->dev.parent = &iface->dev; - - input_set_drvdata(input_dev, dev); - - input_dev->open = atp_open; - input_dev->close = atp_close; - - set_bit(EV_ABS, input_dev->evbit); - - if (atp_is_geyser_3(dev)) { - /* - * MacBook have 20 X sensors, 10 Y sensors - */ - input_set_abs_params(input_dev, ABS_X, 0, - ((20 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0); - input_set_abs_params(input_dev, ABS_Y, 0, - ((10 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0); - } else if (atp_is_geyser_2(dev)) { - /* - * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected - * later. - */ - input_set_abs_params(input_dev, ABS_X, 0, - ((15 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0); - input_set_abs_params(input_dev, ABS_Y, 0, - ((9 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0); - } else { - /* - * 12" and 15" Powerbooks only have 16 x sensors, - * 17" models are detected later. - */ - input_set_abs_params(input_dev, ABS_X, 0, - (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0); - input_set_abs_params(input_dev, ABS_Y, 0, - (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0); - } - input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0); - - set_bit(EV_KEY, input_dev->evbit); - set_bit(BTN_TOUCH, input_dev->keybit); - set_bit(BTN_TOOL_FINGER, input_dev->keybit); - set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); - set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); - set_bit(BTN_LEFT, input_dev->keybit); - - error = input_register_device(dev->input); - if (error) - goto err_free_buffer; - - /* save our data pointer in this interface device */ - usb_set_intfdata(iface, dev); - - return 0; - - err_free_buffer: - usb_buffer_free(dev->udev, dev->datalen, - dev->data, dev->urb->transfer_dma); - err_free_urb: - usb_free_urb(dev->urb); - err_free_devs: - usb_set_intfdata(iface, NULL); - kfree(dev); - input_free_device(input_dev); - return error; -} - -static void atp_disconnect(struct usb_interface *iface) -{ - struct atp *dev = usb_get_intfdata(iface); - - usb_set_intfdata(iface, NULL); - if (dev) { - usb_kill_urb(dev->urb); - input_unregister_device(dev->input); - usb_buffer_free(dev->udev, dev->datalen, - dev->data, dev->urb->transfer_dma); - usb_free_urb(dev->urb); - kfree(dev); - } - printk(KERN_INFO "input: appletouch disconnected\n"); -} - -static int atp_suspend(struct usb_interface *iface, pm_message_t message) -{ - struct atp *dev = usb_get_intfdata(iface); - usb_kill_urb(dev->urb); - dev->valid = 0; - return 0; -} - -static int atp_resume(struct usb_interface *iface) -{ - struct atp *dev = usb_get_intfdata(iface); - if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC)) - return -EIO; - - return 0; -} - -static struct usb_driver atp_driver = { - .name = "appletouch", - .probe = atp_probe, - .disconnect = atp_disconnect, - .suspend = atp_suspend, - .resume = atp_resume, - .id_table = atp_table, -}; - -static int __init atp_init(void) -{ - return usb_register(&atp_driver); -} - -static void __exit atp_exit(void) -{ - usb_deregister(&atp_driver); -} - -module_init(atp_init); -module_exit(atp_exit); diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c deleted file mode 100644 index 471aab20644..00000000000 --- a/drivers/usb/input/ati_remote.c +++ /dev/null @@ -1,862 +0,0 @@ -/* - * USB ATI Remote support - * - * Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net> - * Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev - * - * This 2.2.0 version is a rewrite / cleanup of the 2.1.1 driver, including - * porting to the 2.6 kernel interfaces, along with other modification - * to better match the style of the existing usb/input drivers. However, the - * protocol and hardware handling is essentially unchanged from 2.1.1. - * - * The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by - * Vojtech Pavlik. - * - * Changes: - * - * Feb 2004: Torrey Hoffman <thoffman@arnor.net> - * Version 2.2.0 - * Jun 2004: Torrey Hoffman <thoffman@arnor.net> - * Version 2.2.1 - * Added key repeat support contributed by: - * Vincent Vanackere <vanackere@lif.univ-mrs.fr> - * Added support for the "Lola" remote contributed by: - * Seth Cohn <sethcohn@yahoo.com> - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * - * 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 - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * - * Hardware & software notes - * - * These remote controls are distributed by ATI as part of their - * "All-In-Wonder" video card packages. The receiver self-identifies as a - * "USB Receiver" with manufacturer "X10 Wireless Technology Inc". - * - * The "Lola" remote is available from X10. See: - * http://www.x10.com/products/lola_sg1.htm - * The Lola is similar to the ATI remote but has no mouse support, and slightly - * different keys. - * - * It is possible to use multiple receivers and remotes on multiple computers - * simultaneously by configuring them to use specific channels. - * - * The RF protocol used by the remote supports 16 distinct channels, 1 to 16. - * Actually, it may even support more, at least in some revisions of the - * hardware. - * - * Each remote can be configured to transmit on one channel as follows: - * - Press and hold the "hand icon" button. - * - When the red LED starts to blink, let go of the "hand icon" button. - * - When it stops blinking, input the channel code as two digits, from 01 - * to 16, and press the hand icon again. - * - * The timing can be a little tricky. Try loading the module with debug=1 - * to have the kernel print out messages about the remote control number - * and mask. Note: debugging prints remote numbers as zero-based hexadecimal. - * - * The driver has a "channel_mask" parameter. This bitmask specifies which - * channels will be ignored by the module. To mask out channels, just add - * all the 2^channel_number values together. - * - * For instance, set channel_mask = 2^4 = 16 (binary 10000) to make ati_remote - * ignore signals coming from remote controls transmitting on channel 4, but - * accept all other channels. - * - * Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be - * ignored. - * - * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this - * parameter are unused. - * - */ - -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/usb/input.h> -#include <linux/wait.h> -#include <linux/jiffies.h> - -/* - * Module and Version Information, Module Parameters - */ - -#define ATI_REMOTE_VENDOR_ID 0x0bc7 -#define ATI_REMOTE_PRODUCT_ID 0x004 -#define LOLA_REMOTE_PRODUCT_ID 0x002 -#define MEDION_REMOTE_PRODUCT_ID 0x006 - -#define DRIVER_VERSION "2.2.1" -#define DRIVER_AUTHOR "Torrey Hoffman <thoffman@arnor.net>" -#define DRIVER_DESC "ATI/X10 RF USB Remote Control" - -#define NAME_BUFSIZE 80 /* size of product name, path buffers */ -#define DATA_BUFSIZE 63 /* size of URB data buffers */ - -/* - * Duplicate event filtering time. - * Sequential, identical KIND_FILTERED inputs with less than - * FILTER_TIME milliseconds between them are considered as repeat - * events. The hardware generates 5 events for the first keypress - * and we have to take this into account for an accurate repeat - * behaviour. - */ -#define FILTER_TIME 60 /* msec */ -#define REPEAT_DELAY 500 /* msec */ - -static unsigned long channel_mask; -module_param(channel_mask, ulong, 0644); -MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); - -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); - -static int repeat_filter = FILTER_TIME; -module_param(repeat_filter, int, 0644); -MODULE_PARM_DESC(repeat_filter, "Repeat filter time, default = 60 msec"); - -static int repeat_delay = REPEAT_DELAY; -module_param(repeat_delay, int, 0644); -MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec"); - -#define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) -#undef err -#define err(format, arg...) printk(KERN_ERR format , ## arg) - -static struct usb_device_id ati_remote_table[] = { - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID) }, - {} /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, ati_remote_table); - -/* Get hi and low bytes of a 16-bits int */ -#define HI(a) ((unsigned char)((a) >> 8)) -#define LO(a) ((unsigned char)((a) & 0xff)) - -#define SEND_FLAG_IN_PROGRESS 1 -#define SEND_FLAG_COMPLETE 2 - -/* Device initialization strings */ -static char init1[] = { 0x01, 0x00, 0x20, 0x14 }; -static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; - -struct ati_remote { - struct input_dev *idev; - struct usb_device *udev; - struct usb_interface *interface; - - struct urb *irq_urb; - struct urb *out_urb; - struct usb_endpoint_descriptor *endpoint_in; - struct usb_endpoint_descriptor *endpoint_out; - unsigned char *inbuf; - unsigned char *outbuf; - dma_addr_t inbuf_dma; - dma_addr_t outbuf_dma; - - unsigned char old_data[2]; /* Detect duplicate events */ - unsigned long old_jiffies; - unsigned long acc_jiffies; /* handle acceleration */ - unsigned long first_jiffies; - - unsigned int repeat_count; - - char name[NAME_BUFSIZE]; - char phys[NAME_BUFSIZE]; - - wait_queue_head_t wait; - int send_flags; -}; - -/* "Kinds" of messages sent from the hardware to the driver. */ -#define KIND_END 0 -#define KIND_LITERAL 1 /* Simply pass to input system */ -#define KIND_FILTERED 2 /* Add artificial key-up events, drop keyrepeats */ -#define KIND_LU 3 /* Directional keypad diagonals - left up, */ -#define KIND_RU 4 /* right up, */ -#define KIND_LD 5 /* left down, */ -#define KIND_RD 6 /* right down */ -#define KIND_ACCEL 7 /* Directional keypad - left, right, up, down.*/ - -/* Translation table from hardware messages to input events. */ -static const struct { - short kind; - unsigned char data1, data2; - int type; - unsigned int code; - int value; -} ati_remote_tbl[] = { - /* Directional control pad axes */ - {KIND_ACCEL, 0x35, 0x70, EV_REL, REL_X, -1}, /* left */ - {KIND_ACCEL, 0x36, 0x71, EV_REL, REL_X, 1}, /* right */ - {KIND_ACCEL, 0x37, 0x72, EV_REL, REL_Y, -1}, /* up */ - {KIND_ACCEL, 0x38, 0x73, EV_REL, REL_Y, 1}, /* down */ - /* Directional control pad diagonals */ - {KIND_LU, 0x39, 0x74, EV_REL, 0, 0}, /* left up */ - {KIND_RU, 0x3a, 0x75, EV_REL, 0, 0}, /* right up */ - {KIND_LD, 0x3c, 0x77, EV_REL, 0, 0}, /* left down */ - {KIND_RD, 0x3b, 0x76, EV_REL, 0, 0}, /* right down */ - - /* "Mouse button" buttons */ - {KIND_LITERAL, 0x3d, 0x78, EV_KEY, BTN_LEFT, 1}, /* left btn down */ - {KIND_LITERAL, 0x3e, 0x79, EV_KEY, BTN_LEFT, 0}, /* left btn up */ - {KIND_LITERAL, 0x41, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */ - {KIND_LITERAL, 0x42, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */ - - /* Artificial "doubleclick" events are generated by the hardware. - * They are mapped to the "side" and "extra" mouse buttons here. */ - {KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */ - {KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */ - - /* keyboard. */ - {KIND_FILTERED, 0xd2, 0x0d, EV_KEY, KEY_1, 1}, - {KIND_FILTERED, 0xd3, 0x0e, EV_KEY, KEY_2, 1}, - {KIND_FILTERED, 0xd4, 0x0f, EV_KEY, KEY_3, 1}, - {KIND_FILTERED, 0xd5, 0x10, EV_KEY, KEY_4, 1}, - {KIND_FILTERED, 0xd6, 0x11, EV_KEY, KEY_5, 1}, - {KIND_FILTERED, 0xd7, 0x12, EV_KEY, KEY_6, 1}, - {KIND_FILTERED, 0xd8, 0x13, EV_KEY, KEY_7, 1}, - {KIND_FILTERED, 0xd9, 0x14, EV_KEY, KEY_8, 1}, - {KIND_FILTERED, 0xda, 0x15, EV_KEY, KEY_9, 1}, - {KIND_FILTERED, 0xdc, 0x17, EV_KEY, KEY_0, 1}, - {KIND_FILTERED, 0xc5, 0x00, EV_KEY, KEY_A, 1}, - {KIND_FILTERED, 0xc6, 0x01, EV_KEY, KEY_B, 1}, - {KIND_FILTERED, 0xde, 0x19, EV_KEY, KEY_C, 1}, - {KIND_FILTERED, 0xe0, 0x1b, EV_KEY, KEY_D, 1}, - {KIND_FILTERED, 0xe6, 0x21, EV_KEY, KEY_E, 1}, - {KIND_FILTERED, 0xe8, 0x23, EV_KEY, KEY_F, 1}, - - /* "special" keys */ - {KIND_FILTERED, 0xdd, 0x18, EV_KEY, KEY_KPENTER, 1}, /* "check" */ - {KIND_FILTERED, 0xdb, 0x16, EV_KEY, KEY_MENU, 1}, /* "menu" */ - {KIND_FILTERED, 0xc7, 0x02, EV_KEY, KEY_POWER, 1}, /* Power */ - {KIND_FILTERED, 0xc8, 0x03, EV_KEY, KEY_TV, 1}, /* TV */ - {KIND_FILTERED, 0xc9, 0x04, EV_KEY, KEY_DVD, 1}, /* DVD */ - {KIND_FILTERED, 0xca, 0x05, EV_KEY, KEY_WWW, 1}, /* WEB */ - {KIND_FILTERED, 0xcb, 0x06, EV_KEY, KEY_BOOKMARKS, 1}, /* "book" */ - {KIND_FILTERED, 0xcc, 0x07, EV_KEY, KEY_EDIT, 1}, /* "hand" */ - {KIND_FILTERED, 0xe1, 0x1c, EV_KEY, KEY_COFFEE, 1}, /* "timer" */ - {KIND_FILTERED, 0xe5, 0x20, EV_KEY, KEY_FRONT, 1}, /* "max" */ - {KIND_FILTERED, 0xe2, 0x1d, EV_KEY, KEY_LEFT, 1}, /* left */ - {KIND_FILTERED, 0xe4, 0x1f, EV_KEY, KEY_RIGHT, 1}, /* right */ - {KIND_FILTERED, 0xe7, 0x22, EV_KEY, KEY_DOWN, 1}, /* down */ - {KIND_FILTERED, 0xdf, 0x1a, EV_KEY, KEY_UP, 1}, /* up */ - {KIND_FILTERED, 0xe3, 0x1e, EV_KEY, KEY_OK, 1}, /* "OK" */ - {KIND_FILTERED, 0xce, 0x09, EV_KEY, KEY_VOLUMEDOWN, 1}, /* VOL + */ - {KIND_FILTERED, 0xcd, 0x08, EV_KEY, KEY_VOLUMEUP, 1}, /* VOL - */ - {KIND_FILTERED, 0xcf, 0x0a, EV_KEY, KEY_MUTE, 1}, /* MUTE */ - {KIND_FILTERED, 0xd0, 0x0b, EV_KEY, KEY_CHANNELUP, 1}, /* CH + */ - {KIND_FILTERED, 0xd1, 0x0c, EV_KEY, KEY_CHANNELDOWN, 1},/* CH - */ - {KIND_FILTERED, 0xec, 0x27, EV_KEY, KEY_RECORD, 1}, /* ( o) red */ - {KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1}, /* ( >) */ - {KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1}, /* (<<) */ - {KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1}, /* (>>) */ - {KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* ([]) */ - {KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1}, /* ('') */ - {KIND_FILTERED, 0xf0, 0x2b, EV_KEY, KEY_PREVIOUS, 1}, /* (<-) */ - {KIND_FILTERED, 0xef, 0x2a, EV_KEY, KEY_NEXT, 1}, /* (>+) */ - {KIND_FILTERED, 0xf2, 0x2D, EV_KEY, KEY_INFO, 1}, /* PLAYING */ - {KIND_FILTERED, 0xf3, 0x2E, EV_KEY, KEY_HOME, 1}, /* TOP */ - {KIND_FILTERED, 0xf4, 0x2F, EV_KEY, KEY_END, 1}, /* END */ - {KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_SELECT, 1}, /* SELECT */ - - {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} -}; - -/* Local function prototypes */ -static void ati_remote_dump (unsigned char *data, unsigned int actual_length); -static int ati_remote_open (struct input_dev *inputdev); -static void ati_remote_close (struct input_dev *inputdev); -static int ati_remote_sendpacket (struct ati_remote *ati_remote, u16 cmd, unsigned char *data); -static void ati_remote_irq_out (struct urb *urb); -static void ati_remote_irq_in (struct urb *urb); -static void ati_remote_input_report (struct urb *urb); -static int ati_remote_initialize (struct ati_remote *ati_remote); -static int ati_remote_probe (struct usb_interface *interface, const struct usb_device_id *id); -static void ati_remote_disconnect (struct usb_interface *interface); - -/* usb specific object to register with the usb subsystem */ -static struct usb_driver ati_remote_driver = { - .name = "ati_remote", - .probe = ati_remote_probe, - .disconnect = ati_remote_disconnect, - .id_table = ati_remote_table, -}; - -/* - * ati_remote_dump_input - */ -static void ati_remote_dump(unsigned char *data, unsigned int len) -{ - if ((len == 1) && (data[0] != (unsigned char)0xff) && (data[0] != 0x00)) - warn("Weird byte 0x%02x", data[0]); - else if (len == 4) - warn("Weird key %02x %02x %02x %02x", - data[0], data[1], data[2], data[3]); - else - warn("Weird data, len=%d %02x %02x %02x %02x %02x %02x ...", - len, data[0], data[1], data[2], data[3], data[4], data[5]); -} - -/* - * ati_remote_open - */ -static int ati_remote_open(struct input_dev *inputdev) -{ - struct ati_remote *ati_remote = input_get_drvdata(inputdev); - - /* On first open, submit the read urb which was set up previously. */ - ati_remote->irq_urb->dev = ati_remote->udev; - if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) { - dev_err(&ati_remote->interface->dev, - "%s: usb_submit_urb failed!\n", __FUNCTION__); - return -EIO; - } - - return 0; -} - -/* - * ati_remote_close - */ -static void ati_remote_close(struct input_dev *inputdev) -{ - struct ati_remote *ati_remote = input_get_drvdata(inputdev); - - usb_kill_urb(ati_remote->irq_urb); -} - -/* - * ati_remote_irq_out - */ -static void ati_remote_irq_out(struct urb *urb) -{ - struct ati_remote *ati_remote = urb->context; - - if (urb->status) { - dev_dbg(&ati_remote->interface->dev, "%s: status %d\n", - __FUNCTION__, urb->status); - return; - } - - ati_remote->send_flags |= SEND_FLAG_COMPLETE; - wmb(); - wake_up(&ati_remote->wait); -} - -/* - * ati_remote_sendpacket - * - * Used to send device initialization strings - */ -static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data) -{ - int retval = 0; - - /* Set up out_urb */ - memcpy(ati_remote->out_urb->transfer_buffer + 1, data, LO(cmd)); - ((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd); - - ati_remote->out_urb->transfer_buffer_length = LO(cmd) + 1; - ati_remote->out_urb->dev = ati_remote->udev; - ati_remote->send_flags = SEND_FLAG_IN_PROGRESS; - - retval = usb_submit_urb(ati_remote->out_urb, GFP_ATOMIC); - if (retval) { - dev_dbg(&ati_remote->interface->dev, - "sendpacket: usb_submit_urb failed: %d\n", retval); - return retval; - } - - wait_event_timeout(ati_remote->wait, - ((ati_remote->out_urb->status != -EINPROGRESS) || - (ati_remote->send_flags & SEND_FLAG_COMPLETE)), - HZ); - usb_kill_urb(ati_remote->out_urb); - - return retval; -} - -/* - * ati_remote_event_lookup - */ -static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) -{ - int i; - - for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) { - /* - * Decide if the table entry matches the remote input. - */ - if ((((ati_remote_tbl[i].data1 & 0x0f) == (d1 & 0x0f))) && - ((((ati_remote_tbl[i].data1 >> 4) - - (d1 >> 4) + rem) & 0x0f) == 0x0f) && - (ati_remote_tbl[i].data2 == d2)) - return i; - - } - return -1; -} - -/* - * ati_remote_compute_accel - * - * Implements acceleration curve for directional control pad - * If elapsed time since last event is > 1/4 second, user "stopped", - * so reset acceleration. Otherwise, user is probably holding the control - * pad down, so we increase acceleration, ramping up over two seconds to - * a maximum speed. - */ -static int ati_remote_compute_accel(struct ati_remote *ati_remote) -{ - static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; - unsigned long now = jiffies; - int acc; - - if (time_after(now, ati_remote->old_jiffies + msecs_to_jiffies(250))) { - acc = 1; - ati_remote->acc_jiffies = now; - } - else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(125))) - acc = accel[0]; - else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(250))) - acc = accel[1]; - else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(500))) - acc = accel[2]; - else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1000))) - acc = accel[3]; - else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1500))) - acc = accel[4]; - else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(2000))) - acc = accel[5]; - else - acc = accel[6]; - - return acc; -} - -/* - * ati_remote_report_input - */ -static void ati_remote_input_report(struct urb *urb) -{ - struct ati_remote *ati_remote = urb->context; - unsigned char *data= ati_remote->inbuf; - struct input_dev *dev = ati_remote->idev; - int index, acc; - int remote_num; - - /* Deal with strange looking inputs */ - if ( (urb->actual_length != 4) || (data[0] != 0x14) || - ((data[3] & 0x0f) != 0x00) ) { - ati_remote_dump(data, urb->actual_length); - return; - } - - /* Mask unwanted remote channels. */ - /* note: remote_num is 0-based, channel 1 on remote == 0 here */ - remote_num = (data[3] >> 4) & 0x0f; - if (channel_mask & (1 << (remote_num + 1))) { - dbginfo(&ati_remote->interface->dev, - "Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n", - remote_num, data[1], data[2], channel_mask); - return; - } - - /* Look up event code index in translation table */ - index = ati_remote_event_lookup(remote_num, data[1], data[2]); - if (index < 0) { - dev_warn(&ati_remote->interface->dev, - "Unknown input from channel 0x%02x: data %02x,%02x\n", - remote_num, data[1], data[2]); - return; - } - dbginfo(&ati_remote->interface->dev, - "channel 0x%02x; data %02x,%02x; index %d; keycode %d\n", - remote_num, data[1], data[2], index, ati_remote_tbl[index].code); - - if (ati_remote_tbl[index].kind == KIND_LITERAL) { - input_event(dev, ati_remote_tbl[index].type, - ati_remote_tbl[index].code, - ati_remote_tbl[index].value); - input_sync(dev); - - ati_remote->old_jiffies = jiffies; - return; - } - - if (ati_remote_tbl[index].kind == KIND_FILTERED) { - unsigned long now = jiffies; - - /* Filter duplicate events which happen "too close" together. */ - if (ati_remote->old_data[0] == data[1] && - ati_remote->old_data[1] == data[2] && - time_before(now, ati_remote->old_jiffies + - msecs_to_jiffies(repeat_filter))) { - ati_remote->repeat_count++; - } else { - ati_remote->repeat_count = 0; - ati_remote->first_jiffies = now; - } - - ati_remote->old_data[0] = data[1]; - ati_remote->old_data[1] = data[2]; - ati_remote->old_jiffies = now; - - /* Ensure we skip at least the 4 first duplicate events (generated - * by a single keypress), and continue skipping until repeat_delay - * msecs have passed - */ - if (ati_remote->repeat_count > 0 && - (ati_remote->repeat_count < 5 || - time_before(now, ati_remote->first_jiffies + - msecs_to_jiffies(repeat_delay)))) - return; - - - input_event(dev, ati_remote_tbl[index].type, - ati_remote_tbl[index].code, 1); - input_sync(dev); - input_event(dev, ati_remote_tbl[index].type, - ati_remote_tbl[index].code, 0); - input_sync(dev); - - } else { - - /* - * Other event kinds are from the directional control pad, and have an - * acceleration factor applied to them. Without this acceleration, the - * control pad is mostly unusable. - */ - acc = ati_remote_compute_accel(ati_remote); - - switch (ati_remote_tbl[index].kind) { - case KIND_ACCEL: - input_event(dev, ati_remote_tbl[index].type, - ati_remote_tbl[index].code, - ati_remote_tbl[index].value * acc); - break; - case KIND_LU: - input_report_rel(dev, REL_X, -acc); - input_report_rel(dev, REL_Y, -acc); - break; - case KIND_RU: - input_report_rel(dev, REL_X, acc); - input_report_rel(dev, REL_Y, -acc); - break; - case KIND_LD: - input_report_rel(dev, REL_X, -acc); - input_report_rel(dev, REL_Y, acc); - break; - case KIND_RD: - input_report_rel(dev, REL_X, acc); - input_report_rel(dev, REL_Y, acc); - break; - default: - dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", - ati_remote_tbl[index].kind); - } - input_sync(dev); - - ati_remote->old_jiffies = jiffies; - ati_remote->old_data[0] = data[1]; - ati_remote->old_data[1] = data[2]; - } -} - -/* - * ati_remote_irq_in - */ -static void ati_remote_irq_in(struct urb *urb) -{ - struct ati_remote *ati_remote = urb->context; - int retval; - - switch (urb->status) { - case 0: /* success */ - ati_remote_input_report(urb); - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: - dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n", - __FUNCTION__); - return; - default: /* error */ - dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n", - __FUNCTION__, urb->status); - } - - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n", - __FUNCTION__, retval); -} - -/* - * ati_remote_alloc_buffers - */ -static int ati_remote_alloc_buffers(struct usb_device *udev, - struct ati_remote *ati_remote) -{ - ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC, - &ati_remote->inbuf_dma); - if (!ati_remote->inbuf) - return -1; - - ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC, - &ati_remote->outbuf_dma); - if (!ati_remote->outbuf) - return -1; - - ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!ati_remote->irq_urb) - return -1; - - ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!ati_remote->out_urb) - return -1; - - return 0; -} - -/* - * ati_remote_free_buffers - */ -static void ati_remote_free_buffers(struct ati_remote *ati_remote) -{ - usb_free_urb(ati_remote->irq_urb); - usb_free_urb(ati_remote->out_urb); - - usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, - ati_remote->inbuf, ati_remote->inbuf_dma); - - usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, - ati_remote->outbuf, ati_remote->outbuf_dma); -} - -static void ati_remote_input_init(struct ati_remote *ati_remote) -{ - struct input_dev *idev = ati_remote->idev; - int i; - - idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); - idev->keybit[LONG(BTN_MOUSE)] = ( BIT(BTN_LEFT) | BIT(BTN_RIGHT) | - BIT(BTN_SIDE) | BIT(BTN_EXTRA) ); - idev->relbit[0] = BIT(REL_X) | BIT(REL_Y); - for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) - if (ati_remote_tbl[i].type == EV_KEY) - set_bit(ati_remote_tbl[i].code, idev->keybit); - - input_set_drvdata(idev, ati_remote); - - idev->open = ati_remote_open; - idev->close = ati_remote_close; - - idev->name = ati_remote->name; - idev->phys = ati_remote->phys; - - usb_to_input_id(ati_remote->udev, &idev->id); - idev->dev.parent = &ati_remote->udev->dev; -} - -static int ati_remote_initialize(struct ati_remote *ati_remote) -{ - struct usb_device *udev = ati_remote->udev; - int pipe, maxp; - - init_waitqueue_head(&ati_remote->wait); - - /* Set up irq_urb */ - pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress); - maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); - maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; - - usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf, - maxp, ati_remote_irq_in, ati_remote, - ati_remote->endpoint_in->bInterval); - ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma; - ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - /* Set up out_urb */ - pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress); - maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); - maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; - - usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf, - maxp, ati_remote_irq_out, ati_remote, - ati_remote->endpoint_out->bInterval); - ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma; - ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - /* send initialization strings */ - if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) || - (ati_remote_sendpacket(ati_remote, 0x8007, init2))) { - dev_err(&ati_remote->interface->dev, - "Initializing ati_remote hardware failed.\n"); - return -EIO; - } - - return 0; -} - -/* - * ati_remote_probe - */ -static int ati_remote_probe(struct usb_interface *interface, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct usb_host_interface *iface_host = interface->cur_altsetting; - struct usb_endpoint_descriptor *endpoint_in, *endpoint_out; - struct ati_remote *ati_remote; - struct input_dev *input_dev; - int err = -ENOMEM; - - if (iface_host->desc.bNumEndpoints != 2) { - err("%s: Unexpected desc.bNumEndpoints\n", __FUNCTION__); - return -ENODEV; - } - - endpoint_in = &iface_host->endpoint[0].desc; - endpoint_out = &iface_host->endpoint[1].desc; - - if (!usb_endpoint_is_int_in(endpoint_in)) { - err("%s: Unexpected endpoint_in\n", __FUNCTION__); - return -ENODEV; - } - if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) { - err("%s: endpoint_in message size==0? \n", __FUNCTION__); - return -ENODEV; - } - - ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ati_remote || !input_dev) - goto fail1; - - /* Allocate URB buffers, URBs */ - if (ati_remote_alloc_buffers(udev, ati_remote)) - goto fail2; - - ati_remote->endpoint_in = endpoint_in; - ati_remote->endpoint_out = endpoint_out; - ati_remote->udev = udev; - ati_remote->idev = input_dev; - ati_remote->interface = interface; - - usb_make_path(udev, ati_remote->phys, sizeof(ati_remote->phys)); - strlcpy(ati_remote->phys, "/input0", sizeof(ati_remote->phys)); - - if (udev->manufacturer) - strlcpy(ati_remote->name, udev->manufacturer, sizeof(ati_remote->name)); - - if (udev->product) - snprintf(ati_remote->name, sizeof(ati_remote->name), - "%s %s", ati_remote->name, udev->product); - - if (!strlen(ati_remote->name)) - snprintf(ati_remote->name, sizeof(ati_remote->name), - DRIVER_DESC "(%04x,%04x)", - le16_to_cpu(ati_remote->udev->descriptor.idVendor), - le16_to_cpu(ati_remote->udev->descriptor.idProduct)); - - ati_remote_input_init(ati_remote); - - /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ - err = ati_remote_initialize(ati_remote); - if (err) - goto fail3; - - /* Set up and register input device */ - err = input_register_device(ati_remote->idev); - if (err) - goto fail3; - - usb_set_intfdata(interface, ati_remote); - return 0; - - fail3: usb_kill_urb(ati_remote->irq_urb); - usb_kill_urb(ati_remote->out_urb); - fail2: ati_remote_free_buffers(ati_remote); - fail1: input_free_device(input_dev); - kfree(ati_remote); - return err; -} - -/* - * ati_remote_disconnect - */ -static void ati_remote_disconnect(struct usb_interface *interface) -{ - struct ati_remote *ati_remote; - - ati_remote = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - if (!ati_remote) { - warn("%s - null device?\n", __FUNCTION__); - return; - } - - usb_kill_urb(ati_remote->irq_urb); - usb_kill_urb(ati_remote->out_urb); - input_unregister_device(ati_remote->idev); - ati_remote_free_buffers(ati_remote); - kfree(ati_remote); -} - -/* - * ati_remote_init - */ -static int __init ati_remote_init(void) -{ - int result; - - result = usb_register(&ati_remote_driver); - if (result) - err("usb_register error #%d\n", result); - else - info("Registered USB driver " DRIVER_DESC " v. " DRIVER_VERSION); - - return result; -} - -/* - * ati_remote_exit - */ -static void __exit ati_remote_exit(void) -{ - usb_deregister(&ati_remote_driver); -} - -/* - * module specification - */ - -module_init(ati_remote_init); -module_exit(ati_remote_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c deleted file mode 100644 index a9032aa3465..00000000000 --- a/drivers/usb/input/ati_remote2.c +++ /dev/null @@ -1,545 +0,0 @@ -/* - * ati_remote2 - ATI/Philips USB RF remote driver - * - * Copyright (C) 2005 Ville Syrjala <syrjala@sci.fi> - * Copyright (C) 2007 Peter Stokes <linux@dadeos.freeserve.co.uk> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ - -#include <linux/usb/input.h> - -#define DRIVER_DESC "ATI/Philips USB RF remote driver" -#define DRIVER_VERSION "0.2" - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); -MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>"); -MODULE_LICENSE("GPL"); - -/* - * ATI Remote Wonder II Channel Configuration - * - * The remote control can by assigned one of sixteen "channels" in order to facilitate - * the use of multiple remote controls within range of each other. - * A remote's "channel" may be altered by pressing and holding the "PC" button for - * approximately 3 seconds, after which the button will slowly flash the count of the - * currently configured "channel", using the numeric keypad enter a number between 1 and - * 16 and then the "PC" button again, the button will slowly flash the count of the - * newly configured "channel". - */ - -static unsigned int channel_mask = 0xFFFF; -module_param(channel_mask, uint, 0644); -MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>"); - -static unsigned int mode_mask = 0x1F; -module_param(mode_mask, uint, 0644); -MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); - -static struct usb_device_id ati_remote2_id_table[] = { - { USB_DEVICE(0x0471, 0x0602) }, /* ATI Remote Wonder II */ - { } -}; -MODULE_DEVICE_TABLE(usb, ati_remote2_id_table); - -static struct { - int hw_code; - int key_code; -} ati_remote2_key_table[] = { - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - { 0x0c, KEY_POWER }, - { 0x0d, KEY_MUTE }, - { 0x10, KEY_VOLUMEUP }, - { 0x11, KEY_VOLUMEDOWN }, - { 0x20, KEY_CHANNELUP }, - { 0x21, KEY_CHANNELDOWN }, - { 0x28, KEY_FORWARD }, - { 0x29, KEY_REWIND }, - { 0x2c, KEY_PLAY }, - { 0x30, KEY_PAUSE }, - { 0x31, KEY_STOP }, - { 0x37, KEY_RECORD }, - { 0x38, KEY_DVD }, - { 0x39, KEY_TV }, - { 0x54, KEY_MENU }, - { 0x58, KEY_UP }, - { 0x59, KEY_DOWN }, - { 0x5a, KEY_LEFT }, - { 0x5b, KEY_RIGHT }, - { 0x5c, KEY_OK }, - { 0x78, KEY_A }, - { 0x79, KEY_B }, - { 0x7a, KEY_C }, - { 0x7b, KEY_D }, - { 0x7c, KEY_E }, - { 0x7d, KEY_F }, - { 0x82, KEY_ENTER }, - { 0x8e, KEY_VENDOR }, - { 0x96, KEY_COFFEE }, - { 0xa9, BTN_LEFT }, - { 0xaa, BTN_RIGHT }, - { 0xbe, KEY_QUESTION }, - { 0xd5, KEY_FRONT }, - { 0xd0, KEY_EDIT }, - { 0xf9, KEY_INFO }, - { (0x00 << 8) | 0x3f, KEY_PROG1 }, - { (0x01 << 8) | 0x3f, KEY_PROG2 }, - { (0x02 << 8) | 0x3f, KEY_PROG3 }, - { (0x03 << 8) | 0x3f, KEY_PROG4 }, - { (0x04 << 8) | 0x3f, KEY_PC }, - { 0, KEY_RESERVED } -}; - -struct ati_remote2 { - struct input_dev *idev; - struct usb_device *udev; - - struct usb_interface *intf[2]; - struct usb_endpoint_descriptor *ep[2]; - struct urb *urb[2]; - void *buf[2]; - dma_addr_t buf_dma[2]; - - unsigned long jiffies; - int mode; - - char name[64]; - char phys[64]; -}; - -static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id); -static void ati_remote2_disconnect(struct usb_interface *interface); - -static struct usb_driver ati_remote2_driver = { - .name = "ati_remote2", - .probe = ati_remote2_probe, - .disconnect = ati_remote2_disconnect, - .id_table = ati_remote2_id_table, -}; - -static int ati_remote2_open(struct input_dev *idev) -{ - struct ati_remote2 *ar2 = input_get_drvdata(idev); - int r; - - r = usb_submit_urb(ar2->urb[0], GFP_KERNEL); - if (r) { - dev_err(&ar2->intf[0]->dev, - "%s: usb_submit_urb() = %d\n", __FUNCTION__, r); - return r; - } - r = usb_submit_urb(ar2->urb[1], GFP_KERNEL); - if (r) { - usb_kill_urb(ar2->urb[0]); - dev_err(&ar2->intf[1]->dev, - "%s: usb_submit_urb() = %d\n", __FUNCTION__, r); - return r; - } - - return 0; -} - -static void ati_remote2_close(struct input_dev *idev) -{ - struct ati_remote2 *ar2 = input_get_drvdata(idev); - - usb_kill_urb(ar2->urb[0]); - usb_kill_urb(ar2->urb[1]); -} - -static void ati_remote2_input_mouse(struct ati_remote2 *ar2) -{ - struct input_dev *idev = ar2->idev; - u8 *data = ar2->buf[0]; - int channel, mode; - - channel = data[0] >> 4; - - if (!((1 << channel) & channel_mask)) - return; - - mode = data[0] & 0x0F; - - if (mode > 4) { - dev_err(&ar2->intf[0]->dev, - "Unknown mode byte (%02x %02x %02x %02x)\n", - data[3], data[2], data[1], data[0]); - return; - } - - if (!((1 << mode) & mode_mask)) - return; - - input_event(idev, EV_REL, REL_X, (s8) data[1]); - input_event(idev, EV_REL, REL_Y, (s8) data[2]); - input_sync(idev); -} - -static int ati_remote2_lookup(unsigned int hw_code) -{ - int i; - - for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++) - if (ati_remote2_key_table[i].hw_code == hw_code) - return i; - - return -1; -} - -static void ati_remote2_input_key(struct ati_remote2 *ar2) -{ - struct input_dev *idev = ar2->idev; - u8 *data = ar2->buf[1]; - int channel, mode, hw_code, index; - - channel = data[0] >> 4; - - if (!((1 << channel) & channel_mask)) - return; - - mode = data[0] & 0x0F; - - if (mode > 4) { - dev_err(&ar2->intf[1]->dev, - "Unknown mode byte (%02x %02x %02x %02x)\n", - data[3], data[2], data[1], data[0]); - return; - } - - hw_code = data[2]; - /* - * Mode keys (AUX1-AUX4, PC) all generate the same code byte. - * Use the mode byte to figure out which one was pressed. - */ - if (hw_code == 0x3f) { - /* - * For some incomprehensible reason the mouse pad generates - * events which look identical to the events from the last - * pressed mode key. Naturally we don't want to generate key - * events for the mouse pad so we filter out any subsequent - * events from the same mode key. - */ - if (ar2->mode == mode) - return; - - if (data[1] == 0) - ar2->mode = mode; - - hw_code |= mode << 8; - } - - if (!((1 << mode) & mode_mask)) - return; - - index = ati_remote2_lookup(hw_code); - if (index < 0) { - dev_err(&ar2->intf[1]->dev, - "Unknown code byte (%02x %02x %02x %02x)\n", - data[3], data[2], data[1], data[0]); - return; - } - - switch (data[1]) { - case 0: /* release */ - break; - case 1: /* press */ - ar2->jiffies = jiffies + msecs_to_jiffies(idev->rep[REP_DELAY]); - break; - case 2: /* repeat */ - - /* No repeat for mouse buttons. */ - if (ati_remote2_key_table[index].key_code == BTN_LEFT || - ati_remote2_key_table[index].key_code == BTN_RIGHT) - return; - - if (!time_after_eq(jiffies, ar2->jiffies)) - return; - - ar2->jiffies = jiffies + msecs_to_jiffies(idev->rep[REP_PERIOD]); - break; - default: - dev_err(&ar2->intf[1]->dev, - "Unknown state byte (%02x %02x %02x %02x)\n", - data[3], data[2], data[1], data[0]); - return; - } - - input_event(idev, EV_KEY, ati_remote2_key_table[index].key_code, data[1]); - input_sync(idev); -} - -static void ati_remote2_complete_mouse(struct urb *urb) -{ - struct ati_remote2 *ar2 = urb->context; - int r; - - switch (urb->status) { - case 0: - ati_remote2_input_mouse(ar2); - break; - case -ENOENT: - case -EILSEQ: - case -ECONNRESET: - case -ESHUTDOWN: - dev_dbg(&ar2->intf[0]->dev, - "%s(): urb status = %d\n", __FUNCTION__, urb->status); - return; - default: - dev_err(&ar2->intf[0]->dev, - "%s(): urb status = %d\n", __FUNCTION__, urb->status); - } - - r = usb_submit_urb(urb, GFP_ATOMIC); - if (r) - dev_err(&ar2->intf[0]->dev, - "%s(): usb_submit_urb() = %d\n", __FUNCTION__, r); -} - -static void ati_remote2_complete_key(struct urb *urb) -{ - struct ati_remote2 *ar2 = urb->context; - int r; - - switch (urb->status) { - case 0: - ati_remote2_input_key(ar2); - break; - case -ENOENT: - case -EILSEQ: - case -ECONNRESET: - case -ESHUTDOWN: - dev_dbg(&ar2->intf[1]->dev, - "%s(): urb status = %d\n", __FUNCTION__, urb->status); - return; - default: - dev_err(&ar2->intf[1]->dev, - "%s(): urb status = %d\n", __FUNCTION__, urb->status); - } - - r = usb_submit_urb(urb, GFP_ATOMIC); - if (r) - dev_err(&ar2->intf[1]->dev, - "%s(): usb_submit_urb() = %d\n", __FUNCTION__, r); -} - -static int ati_remote2_input_init(struct ati_remote2 *ar2) -{ - struct input_dev *idev; - int i, retval; - - idev = input_allocate_device(); - if (!idev) - return -ENOMEM; - - ar2->idev = idev; - input_set_drvdata(idev, ar2); - - idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL); - idev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT); - idev->relbit[0] = BIT(REL_X) | BIT(REL_Y); - for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++) - set_bit(ati_remote2_key_table[i].key_code, idev->keybit); - - idev->rep[REP_DELAY] = 250; - idev->rep[REP_PERIOD] = 33; - - idev->open = ati_remote2_open; - idev->close = ati_remote2_close; - - idev->name = ar2->name; - idev->phys = ar2->phys; - - usb_to_input_id(ar2->udev, &idev->id); - idev->dev.parent = &ar2->udev->dev; - - retval = input_register_device(idev); - if (retval) - input_free_device(idev); - - return retval; -} - -static int ati_remote2_urb_init(struct ati_remote2 *ar2) -{ - struct usb_device *udev = ar2->udev; - int i, pipe, maxp; - - for (i = 0; i < 2; i++) { - ar2->buf[i] = usb_buffer_alloc(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]); - if (!ar2->buf[i]) - return -ENOMEM; - - ar2->urb[i] = usb_alloc_urb(0, GFP_KERNEL); - if (!ar2->urb[i]) - return -ENOMEM; - - pipe = usb_rcvintpipe(udev, ar2->ep[i]->bEndpointAddress); - maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); - maxp = maxp > 4 ? 4 : maxp; - - usb_fill_int_urb(ar2->urb[i], udev, pipe, ar2->buf[i], maxp, - i ? ati_remote2_complete_key : ati_remote2_complete_mouse, - ar2, ar2->ep[i]->bInterval); - ar2->urb[i]->transfer_dma = ar2->buf_dma[i]; - ar2->urb[i]->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - } - - return 0; -} - -static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2) -{ - int i; - - for (i = 0; i < 2; i++) { - usb_free_urb(ar2->urb[i]); - - if (ar2->buf[i]) - usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]); - } -} - -static int ati_remote2_setup(struct ati_remote2 *ar2) -{ - int r, i, channel; - - /* - * Configure receiver to only accept input from remote "channel" - * channel == 0 -> Accept input from any remote channel - * channel == 1 -> Only accept input from remote channel 1 - * channel == 2 -> Only accept input from remote channel 2 - * ... - * channel == 16 -> Only accept input from remote channel 16 - */ - - channel = 0; - for (i = 0; i < 16; i++) { - if ((1 << i) & channel_mask) { - if (!(~(1 << i) & 0xFFFF & channel_mask)) - channel = i + 1; - break; - } - } - - r = usb_control_msg(ar2->udev, usb_sndctrlpipe(ar2->udev, 0), - 0x20, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - channel, 0x0, NULL, 0, USB_CTRL_SET_TIMEOUT); - if (r) { - dev_err(&ar2->udev->dev, "%s - failed to set channel due to error: %d\n", - __FUNCTION__, r); - return r; - } - - return 0; -} - -static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct usb_host_interface *alt = interface->cur_altsetting; - struct ati_remote2 *ar2; - int r; - - if (alt->desc.bInterfaceNumber) - return -ENODEV; - - ar2 = kzalloc(sizeof (struct ati_remote2), GFP_KERNEL); - if (!ar2) - return -ENOMEM; - - ar2->udev = udev; - - ar2->intf[0] = interface; - ar2->ep[0] = &alt->endpoint[0].desc; - - ar2->intf[1] = usb_ifnum_to_if(udev, 1); - r = usb_driver_claim_interface(&ati_remote2_driver, ar2->intf[1], ar2); - if (r) - goto fail1; - alt = ar2->intf[1]->cur_altsetting; - ar2->ep[1] = &alt->endpoint[0].desc; - - r = ati_remote2_urb_init(ar2); - if (r) - goto fail2; - - r = ati_remote2_setup(ar2); - if (r) - goto fail2; - - usb_make_path(udev, ar2->phys, sizeof(ar2->phys)); - strlcat(ar2->phys, "/input0", sizeof(ar2->phys)); - - strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name)); - - r = ati_remote2_input_init(ar2); - if (r) - goto fail2; - - usb_set_intfdata(interface, ar2); - - return 0; - - fail2: - ati_remote2_urb_cleanup(ar2); - - usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); - fail1: - kfree(ar2); - - return r; -} - -static void ati_remote2_disconnect(struct usb_interface *interface) -{ - struct ati_remote2 *ar2; - struct usb_host_interface *alt = interface->cur_altsetting; - - if (alt->desc.bInterfaceNumber) - return; - - ar2 = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - - input_unregister_device(ar2->idev); - - ati_remote2_urb_cleanup(ar2); - - usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); - - kfree(ar2); -} - -static int __init ati_remote2_init(void) -{ - int r; - - r = usb_register(&ati_remote2_driver); - if (r) - printk(KERN_ERR "ati_remote2: usb_register() = %d\n", r); - else - printk(KERN_INFO "ati_remote2: " DRIVER_DESC " " DRIVER_VERSION "\n"); - - return r; -} - -static void __exit ati_remote2_exit(void) -{ - usb_deregister(&ati_remote2_driver); -} - -module_init(ati_remote2_init); -module_exit(ati_remote2_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 c4781b9d129..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 { - signed 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/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c deleted file mode 100644 index 1bffc9fa98c..00000000000 --- a/drivers/usb/input/keyspan_remote.c +++ /dev/null @@ -1,592 +0,0 @@ -/* - * keyspan_remote: USB driver for the Keyspan DMR - * - * Copyright (C) 2005 Zymeta Corporation - Michael Downey (downey@zymeta.com) - * - * 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. - * - * This driver has been put together with the support of Innosys, Inc. - * and Keyspan, Inc the manufacturers of the Keyspan USB DMR product. - */ - -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/usb/input.h> - -#define DRIVER_VERSION "v0.1" -#define DRIVER_AUTHOR "Michael Downey <downey@zymeta.com>" -#define DRIVER_DESC "Driver for the USB Keyspan remote control." -#define DRIVER_LICENSE "GPL" - -/* Parameters that can be passed to the driver. */ -static int debug; -module_param(debug, int, 0444); -MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); - -/* Vendor and product ids */ -#define USB_KEYSPAN_VENDOR_ID 0x06CD -#define USB_KEYSPAN_PRODUCT_UIA11 0x0202 - -/* Defines for converting the data from the remote. */ -#define ZERO 0x18 -#define ZERO_MASK 0x1F /* 5 bits for a 0 */ -#define ONE 0x3C -#define ONE_MASK 0x3F /* 6 bits for a 1 */ -#define SYNC 0x3F80 -#define SYNC_MASK 0x3FFF /* 14 bits for a SYNC sequence */ -#define STOP 0x00 -#define STOP_MASK 0x1F /* 5 bits for the STOP sequence */ -#define GAP 0xFF - -#define RECV_SIZE 8 /* The UIA-11 type have a 8 byte limit. */ - -/* table of devices that work with this driver */ -static struct usb_device_id keyspan_table[] = { - { USB_DEVICE(USB_KEYSPAN_VENDOR_ID, USB_KEYSPAN_PRODUCT_UIA11) }, - { } /* Terminating entry */ -}; - -/* Structure to store all the real stuff that a remote sends to us. */ -struct keyspan_message { - u16 system; - u8 button; - u8 toggle; -}; - -/* Structure used for all the bit testing magic needed to be done. */ -struct bit_tester { - u32 tester; - int len; - int pos; - int bits_left; - u8 buffer[32]; -}; - -/* Structure to hold all of our driver specific stuff */ -struct usb_keyspan { - char name[128]; - char phys[64]; - struct usb_device* udev; - struct input_dev *input; - struct usb_interface* interface; - struct usb_endpoint_descriptor* in_endpoint; - struct urb* irq_urb; - int open; - dma_addr_t in_dma; - unsigned char* in_buffer; - - /* variables used to parse messages from remote. */ - struct bit_tester data; - int stage; - int toggle; -}; - -/* - * Table that maps the 31 possible keycodes to input keys. - * Currently there are 15 and 17 button models so RESERVED codes - * are blank areas in the mapping. - */ -static const int keyspan_key_table[] = { - KEY_RESERVED, /* 0 is just a place holder. */ - KEY_RESERVED, - KEY_STOP, - KEY_PLAYCD, - KEY_RESERVED, - KEY_PREVIOUSSONG, - KEY_REWIND, - KEY_FORWARD, - KEY_NEXTSONG, - KEY_RESERVED, - KEY_RESERVED, - KEY_RESERVED, - KEY_PAUSE, - KEY_VOLUMEUP, - KEY_RESERVED, - KEY_RESERVED, - KEY_RESERVED, - KEY_VOLUMEDOWN, - KEY_RESERVED, - KEY_UP, - KEY_RESERVED, - KEY_MUTE, - KEY_LEFT, - KEY_ENTER, - KEY_RIGHT, - KEY_RESERVED, - KEY_RESERVED, - KEY_DOWN, - KEY_RESERVED, - KEY_KPASTERISK, - KEY_RESERVED, - KEY_MENU -}; - -static struct usb_driver keyspan_driver; - -/* - * Debug routine that prints out what we've received from the remote. - */ -static void keyspan_print(struct usb_keyspan* dev) /*unsigned char* data)*/ -{ - char codes[4 * RECV_SIZE]; - int i; - - for (i = 0; i < RECV_SIZE; i++) - snprintf(codes + i * 3, 4, "%02x ", dev->in_buffer[i]); - - dev_info(&dev->udev->dev, "%s\n", codes); -} - -/* - * Routine that manages the bit_tester structure. It makes sure that there are - * at least bits_needed bits loaded into the tester. - */ -static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed) -{ - if (dev->data.bits_left >= bits_needed) - return 0; - - /* - * Somehow we've missed the last message. The message will be repeated - * though so it's not too big a deal - */ - if (dev->data.pos >= dev->data.len) { - dev_dbg(&dev->udev->dev, - "%s - Error ran out of data. pos: %d, len: %d\n", - __FUNCTION__, dev->data.pos, dev->data.len); - return -1; - } - - /* Load as much as we can into the tester. */ - while ((dev->data.bits_left + 7 < (sizeof(dev->data.tester) * 8)) && - (dev->data.pos < dev->data.len)) { - dev->data.tester += (dev->data.buffer[dev->data.pos++] << dev->data.bits_left); - dev->data.bits_left += 8; - } - - return 0; -} - -/* - * Routine that handles all the logic needed to parse out the message from the remote. - */ -static void keyspan_check_data(struct usb_keyspan *remote) -{ - int i; - int found = 0; - struct keyspan_message message; - - switch(remote->stage) { - case 0: - /* - * In stage 0 we want to find the start of a message. The remote sends a 0xFF as filler. - * So the first byte that isn't a FF should be the start of a new message. - */ - for (i = 0; i < RECV_SIZE && remote->in_buffer[i] == GAP; ++i); - - if (i < RECV_SIZE) { - memcpy(remote->data.buffer, remote->in_buffer, RECV_SIZE); - remote->data.len = RECV_SIZE; - remote->data.pos = 0; - remote->data.tester = 0; - remote->data.bits_left = 0; - remote->stage = 1; - } - break; - - case 1: - /* - * Stage 1 we should have 16 bytes and should be able to detect a - * SYNC. The SYNC is 14 bits, 7 0's and then 7 1's. - */ - memcpy(remote->data.buffer + remote->data.len, remote->in_buffer, RECV_SIZE); - remote->data.len += RECV_SIZE; - - found = 0; - while ((remote->data.bits_left >= 14 || remote->data.pos < remote->data.len) && !found) { - for (i = 0; i < 8; ++i) { - if (keyspan_load_tester(remote, 14) != 0) { - remote->stage = 0; - return; - } - - if ((remote->data.tester & SYNC_MASK) == SYNC) { - remote->data.tester = remote->data.tester >> 14; - remote->data.bits_left -= 14; - found = 1; - break; - } else { - remote->data.tester = remote->data.tester >> 1; - --remote->data.bits_left; - } - } - } - - if (!found) { - remote->stage = 0; - remote->data.len = 0; - } else { - remote->stage = 2; - } - break; - - case 2: - /* - * Stage 2 we should have 24 bytes which will be enough for a full - * message. We need to parse out the system code, button code, - * toggle code, and stop. - */ - memcpy(remote->data.buffer + remote->data.len, remote->in_buffer, RECV_SIZE); - remote->data.len += RECV_SIZE; - - message.system = 0; - for (i = 0; i < 9; i++) { - keyspan_load_tester(remote, 6); - - if ((remote->data.tester & ZERO_MASK) == ZERO) { - message.system = message.system << 1; - remote->data.tester = remote->data.tester >> 5; - remote->data.bits_left -= 5; - } else if ((remote->data.tester & ONE_MASK) == ONE) { - message.system = (message.system << 1) + 1; - remote->data.tester = remote->data.tester >> 6; - remote->data.bits_left -= 6; - } else { - err("%s - Unknown sequence found in system data.\n", __FUNCTION__); - remote->stage = 0; - return; - } - } - - message.button = 0; - for (i = 0; i < 5; i++) { - keyspan_load_tester(remote, 6); - - if ((remote->data.tester & ZERO_MASK) == ZERO) { - message.button = message.button << 1; - remote->data.tester = remote->data.tester >> 5; - remote->data.bits_left -= 5; - } else if ((remote->data.tester & ONE_MASK) == ONE) { - message.button = (message.button << 1) + 1; - remote->data.tester = remote->data.tester >> 6; - remote->data.bits_left -= 6; - } else { - err("%s - Unknown sequence found in button data.\n", __FUNCTION__); - remote->stage = 0; - return; - } - } - - keyspan_load_tester(remote, 6); - if ((remote->data.tester & ZERO_MASK) == ZERO) { - message.toggle = 0; - remote->data.tester = remote->data.tester >> 5; - remote->data.bits_left -= 5; - } else if ((remote->data.tester & ONE_MASK) == ONE) { - message.toggle = 1; - remote->data.tester = remote->data.tester >> 6; - remote->data.bits_left -= 6; - } else { - err("%s - Error in message, invalid toggle.\n", __FUNCTION__); - remote->stage = 0; - return; - } - - keyspan_load_tester(remote, 5); - if ((remote->data.tester & STOP_MASK) == STOP) { - remote->data.tester = remote->data.tester >> 5; - remote->data.bits_left -= 5; - } else { - err("Bad message recieved, no stop bit found.\n"); - } - - dev_dbg(&remote->udev->dev, - "%s found valid message: system: %d, button: %d, toggle: %d\n", - __FUNCTION__, message.system, message.button, message.toggle); - - if (message.toggle != remote->toggle) { - input_report_key(remote->input, keyspan_key_table[message.button], 1); - input_report_key(remote->input, keyspan_key_table[message.button], 0); - input_sync(remote->input); - remote->toggle = message.toggle; - } - - remote->stage = 0; - break; - } -} - -/* - * Routine for sending all the initialization messages to the remote. - */ -static int keyspan_setup(struct usb_device* dev) -{ - int retval = 0; - - retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0x11, 0x40, 0x5601, 0x0, NULL, 0, 0); - if (retval) { - dev_dbg(&dev->dev, "%s - failed to set bit rate due to error: %d\n", - __FUNCTION__, retval); - return(retval); - } - - retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0x44, 0x40, 0x0, 0x0, NULL, 0, 0); - if (retval) { - dev_dbg(&dev->dev, "%s - failed to set resume sensitivity due to error: %d\n", - __FUNCTION__, retval); - return(retval); - } - - retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - 0x22, 0x40, 0x0, 0x0, NULL, 0, 0); - if (retval) { - dev_dbg(&dev->dev, "%s - failed to turn receive on due to error: %d\n", - __FUNCTION__, retval); - return(retval); - } - - dev_dbg(&dev->dev, "%s - Setup complete.\n", __FUNCTION__); - return(retval); -} - -/* - * Routine used to handle a new message that has come in. - */ -static void keyspan_irq_recv(struct urb *urb) -{ - struct usb_keyspan *dev = urb->context; - int retval; - - /* Check our status in case we need to bail out early. */ - switch (urb->status) { - case 0: - break; - - /* Device went away so don't keep trying to read from it. */ - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - return; - - default: - goto resubmit; - break; - } - - if (debug) - keyspan_print(dev); - - keyspan_check_data(dev); - -resubmit: - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - err ("%s - usb_submit_urb failed with result: %d", __FUNCTION__, retval); -} - -static int keyspan_open(struct input_dev *dev) -{ - struct usb_keyspan *remote = input_get_drvdata(dev); - - remote->irq_urb->dev = remote->udev; - if (usb_submit_urb(remote->irq_urb, GFP_KERNEL)) - return -EIO; - - return 0; -} - -static void keyspan_close(struct input_dev *dev) -{ - struct usb_keyspan *remote = input_get_drvdata(dev); - - usb_kill_urb(remote->irq_urb); -} - -static struct usb_endpoint_descriptor *keyspan_get_in_endpoint(struct usb_host_interface *iface) -{ - - struct usb_endpoint_descriptor *endpoint; - int i; - - for (i = 0; i < iface->desc.bNumEndpoints; ++i) { - endpoint = &iface->endpoint[i].desc; - - if (usb_endpoint_is_int_in(endpoint)) { - /* we found our interrupt in endpoint */ - return endpoint; - } - } - - return NULL; -} - -/* - * Routine that sets up the driver to handle a specific USB device detected on the bus. - */ -static int keyspan_probe(struct usb_interface *interface, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct usb_endpoint_descriptor *endpoint; - struct usb_keyspan *remote; - struct input_dev *input_dev; - int i, error; - - endpoint = keyspan_get_in_endpoint(interface->cur_altsetting); - if (!endpoint) - return -ENODEV; - - remote = kzalloc(sizeof(*remote), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!remote || !input_dev) { - error = -ENOMEM; - goto fail1; - } - - remote->udev = udev; - remote->input = input_dev; - remote->interface = interface; - remote->in_endpoint = endpoint; - remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */ - - remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma); - if (!remote->in_buffer) { - error = -ENOMEM; - goto fail1; - } - - remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!remote->irq_urb) { - error = -ENOMEM; - goto fail2; - } - - error = keyspan_setup(udev); - if (error) { - error = -ENODEV; - goto fail3; - } - - if (udev->manufacturer) - strlcpy(remote->name, udev->manufacturer, sizeof(remote->name)); - - if (udev->product) { - if (udev->manufacturer) - strlcat(remote->name, " ", sizeof(remote->name)); - strlcat(remote->name, udev->product, sizeof(remote->name)); - } - - if (!strlen(remote->name)) - snprintf(remote->name, sizeof(remote->name), - "USB Keyspan Remote %04x:%04x", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); - - usb_make_path(udev, remote->phys, sizeof(remote->phys)); - strlcat(remote->phys, "/input0", sizeof(remote->phys)); - - input_dev->name = remote->name; - input_dev->phys = remote->phys; - usb_to_input_id(udev, &input_dev->id); - input_dev->dev.parent = &interface->dev; - - input_dev->evbit[0] = BIT(EV_KEY); /* We will only report KEY events. */ - for (i = 0; i < ARRAY_SIZE(keyspan_key_table); i++) - if (keyspan_key_table[i] != KEY_RESERVED) - set_bit(keyspan_key_table[i], input_dev->keybit); - - input_set_drvdata(input_dev, remote); - - input_dev->open = keyspan_open; - input_dev->close = keyspan_close; - - /* - * Initialize the URB to access the device. The urb gets sent to the device in keyspan_open() - */ - usb_fill_int_urb(remote->irq_urb, - remote->udev, usb_rcvintpipe(remote->udev, remote->in_endpoint->bEndpointAddress), - remote->in_buffer, RECV_SIZE, keyspan_irq_recv, remote, - remote->in_endpoint->bInterval); - remote->irq_urb->transfer_dma = remote->in_dma; - remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - /* we can register the device now, as it is ready */ - error = input_register_device(remote->input); - if (error) - goto fail3; - - /* save our data pointer in this interface device */ - usb_set_intfdata(interface, remote); - - return 0; - - fail3: usb_free_urb(remote->irq_urb); - fail2: usb_buffer_free(udev, RECV_SIZE, remote->in_buffer, remote->in_dma); - fail1: kfree(remote); - input_free_device(input_dev); - - return error; -} - -/* - * Routine called when a device is disconnected from the USB. - */ -static void keyspan_disconnect(struct usb_interface *interface) -{ - struct usb_keyspan *remote; - - remote = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - - if (remote) { /* We have a valid driver structure so clean up everything we allocated. */ - input_unregister_device(remote->input); - usb_kill_urb(remote->irq_urb); - usb_free_urb(remote->irq_urb); - usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma); - kfree(remote); - } -} - -/* - * Standard driver set up sections - */ -static struct usb_driver keyspan_driver = -{ - .name = "keyspan_remote", - .probe = keyspan_probe, - .disconnect = keyspan_disconnect, - .id_table = keyspan_table -}; - -static int __init usb_keyspan_init(void) -{ - int result; - - /* register this driver with the USB subsystem */ - result = usb_register(&keyspan_driver); - if (result) - err("usb_register failed. Error number %d\n", result); - - return result; -} - -static void __exit usb_keyspan_exit(void) -{ - /* deregister this driver with the USB subsystem */ - usb_deregister(&keyspan_driver); -} - -module_init(usb_keyspan_init); -module_exit(usb_keyspan_exit); - -MODULE_DEVICE_TABLE(usb, keyspan_table); -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENSE); diff --git a/drivers/usb/input/map_to_7segment.h b/drivers/usb/input/map_to_7segment.h deleted file mode 100644 index a424094d9fe..00000000000 --- a/drivers/usb/input/map_to_7segment.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * drivers/usb/input/map_to_7segment.h - * - * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com> - * - * 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 - */ - -#ifndef MAP_TO_7SEGMENT_H -#define MAP_TO_7SEGMENT_H - -/* This file provides translation primitives and tables for the conversion - * of (ASCII) characters to a 7-segments notation. - * - * The 7 segment's wikipedia notation below is used as standard. - * See: http://en.wikipedia.org/wiki/Seven_segment_display - * - * Notation: +-a-+ - * f b - * +-g-+ - * e c - * +-d-+ - * - * Usage: - * - * Register a map variable, and fill it with a character set: - * static SEG7_DEFAULT_MAP(map_seg7); - * - * - * Then use for conversion: - * seg7 = map_to_seg7(&map_seg7, some_char); - * ... - * - * In device drivers it is recommended, if required, to make the char map - * accessible via the sysfs interface using the following scheme: - * - * static ssize_t show_map(struct device *dev, char *buf) { - * memcpy(buf, &map_seg7, sizeof(map_seg7)); - * return sizeof(map_seg7); - * } - * static ssize_t store_map(struct device *dev, const char *buf, size_t cnt) { - * if(cnt != sizeof(map_seg7)) - * return -EINVAL; - * memcpy(&map_seg7, buf, cnt); - * return cnt; - * } - * static DEVICE_ATTR(map_seg7, PERMS_RW, show_map, store_map); - * - * History: - * 2005-05-31 RFC linux-kernel@vger.kernel.org - */ -#include <linux/errno.h> - - -#define BIT_SEG7_A 0 -#define BIT_SEG7_B 1 -#define BIT_SEG7_C 2 -#define BIT_SEG7_D 3 -#define BIT_SEG7_E 4 -#define BIT_SEG7_F 5 -#define BIT_SEG7_G 6 -#define BIT_SEG7_RESERVED 7 - -struct seg7_conversion_map { - unsigned char table[128]; -}; - -static inline int map_to_seg7(struct seg7_conversion_map *map, int c) -{ - return c >= 0 && c < sizeof(map->table) ? map->table[c] : -EINVAL; -} - -#define SEG7_CONVERSION_MAP(_name, _map) \ - struct seg7_conversion_map _name = { .table = { _map } } - -/* - * It is recommended to use a facility that allows user space to redefine - * custom character sets for LCD devices. Please use a sysfs interface - * as described above. - */ -#define MAP_TO_SEG7_SYSFS_FILE "map_seg7" - -/******************************************************************************* - * ASCII conversion table - ******************************************************************************/ - -#define _SEG7(l,a,b,c,d,e,f,g) \ - ( a<<BIT_SEG7_A | b<<BIT_SEG7_B | c<<BIT_SEG7_C | d<<BIT_SEG7_D | \ - e<<BIT_SEG7_E | f<<BIT_SEG7_F | g<<BIT_SEG7_G ) - -#define _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - -#define _MAP_33_47_ASCII_SEG7_SYMBOL \ - _SEG7('!',0,0,0,0,1,1,0), _SEG7('"',0,1,0,0,0,1,0), _SEG7('#',0,1,1,0,1,1,0),\ - _SEG7('$',1,0,1,1,0,1,1), _SEG7('%',0,0,1,0,0,1,0), _SEG7('&',1,0,1,1,1,1,1),\ - _SEG7('\'',0,0,0,0,0,1,0),_SEG7('(',1,0,0,1,1,1,0), _SEG7(')',1,1,1,1,0,0,0),\ - _SEG7('*',0,1,1,0,1,1,1), _SEG7('+',0,1,1,0,0,0,1), _SEG7(',',0,0,0,0,1,0,0),\ - _SEG7('-',0,0,0,0,0,0,1), _SEG7('.',0,0,0,0,1,0,0), _SEG7('/',0,1,0,0,1,0,1), - -#define _MAP_48_57_ASCII_SEG7_NUMERIC \ - _SEG7('0',1,1,1,1,1,1,0), _SEG7('1',0,1,1,0,0,0,0), _SEG7('2',1,1,0,1,1,0,1),\ - _SEG7('3',1,1,1,1,0,0,1), _SEG7('4',0,1,1,0,0,1,1), _SEG7('5',1,0,1,1,0,1,1),\ - _SEG7('6',1,0,1,1,1,1,1), _SEG7('7',1,1,1,0,0,0,0), _SEG7('8',1,1,1,1,1,1,1),\ - _SEG7('9',1,1,1,1,0,1,1), - -#define _MAP_58_64_ASCII_SEG7_SYMBOL \ - _SEG7(':',0,0,0,1,0,0,1), _SEG7(';',0,0,0,1,0,0,1), _SEG7('<',1,0,0,0,0,1,1),\ - _SEG7('=',0,0,0,1,0,0,1), _SEG7('>',1,1,0,0,0,0,1), _SEG7('?',1,1,1,0,0,1,0),\ - _SEG7('@',1,1,0,1,1,1,1), - -#define _MAP_65_90_ASCII_SEG7_ALPHA_UPPR \ - _SEG7('A',1,1,1,0,1,1,1), _SEG7('B',1,1,1,1,1,1,1), _SEG7('C',1,0,0,1,1,1,0),\ - _SEG7('D',1,1,1,1,1,1,0), _SEG7('E',1,0,0,1,1,1,1), _SEG7('F',1,0,0,0,1,1,1),\ - _SEG7('G',1,1,1,1,0,1,1), _SEG7('H',0,1,1,0,1,1,1), _SEG7('I',0,1,1,0,0,0,0),\ - _SEG7('J',0,1,1,1,0,0,0), _SEG7('K',0,1,1,0,1,1,1), _SEG7('L',0,0,0,1,1,1,0),\ - _SEG7('M',1,1,1,0,1,1,0), _SEG7('N',1,1,1,0,1,1,0), _SEG7('O',1,1,1,1,1,1,0),\ - _SEG7('P',1,1,0,0,1,1,1), _SEG7('Q',1,1,1,1,1,1,0), _SEG7('R',1,1,1,0,1,1,1),\ - _SEG7('S',1,0,1,1,0,1,1), _SEG7('T',0,0,0,1,1,1,1), _SEG7('U',0,1,1,1,1,1,0),\ - _SEG7('V',0,1,1,1,1,1,0), _SEG7('W',0,1,1,1,1,1,1), _SEG7('X',0,1,1,0,1,1,1),\ - _SEG7('Y',0,1,1,0,0,1,1), _SEG7('Z',1,1,0,1,1,0,1), - -#define _MAP_91_96_ASCII_SEG7_SYMBOL \ - _SEG7('[',1,0,0,1,1,1,0), _SEG7('\\',0,0,1,0,0,1,1),_SEG7(']',1,1,1,1,0,0,0),\ - _SEG7('^',1,1,0,0,0,1,0), _SEG7('_',0,0,0,1,0,0,0), _SEG7('`',0,1,0,0,0,0,0), - -#define _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ - _SEG7('A',1,1,1,0,1,1,1), _SEG7('b',0,0,1,1,1,1,1), _SEG7('c',0,0,0,1,1,0,1),\ - _SEG7('d',0,1,1,1,1,0,1), _SEG7('E',1,0,0,1,1,1,1), _SEG7('F',1,0,0,0,1,1,1),\ - _SEG7('G',1,1,1,1,0,1,1), _SEG7('h',0,0,1,0,1,1,1), _SEG7('i',0,0,1,0,0,0,0),\ - _SEG7('j',0,0,1,1,0,0,0), _SEG7('k',0,0,1,0,1,1,1), _SEG7('L',0,0,0,1,1,1,0),\ - _SEG7('M',1,1,1,0,1,1,0), _SEG7('n',0,0,1,0,1,0,1), _SEG7('o',0,0,1,1,1,0,1),\ - _SEG7('P',1,1,0,0,1,1,1), _SEG7('q',1,1,1,0,0,1,1), _SEG7('r',0,0,0,0,1,0,1),\ - _SEG7('S',1,0,1,1,0,1,1), _SEG7('T',0,0,0,1,1,1,1), _SEG7('u',0,0,1,1,1,0,0),\ - _SEG7('v',0,0,1,1,1,0,0), _SEG7('W',0,1,1,1,1,1,1), _SEG7('X',0,1,1,0,1,1,1),\ - _SEG7('y',0,1,1,1,0,1,1), _SEG7('Z',1,1,0,1,1,0,1), - -#define _MAP_123_126_ASCII_SEG7_SYMBOL \ - _SEG7('{',1,0,0,1,1,1,0), _SEG7('|',0,0,0,0,1,1,0), _SEG7('}',1,1,1,1,0,0,0),\ - _SEG7('~',1,0,0,0,0,0,0), - -/* Maps */ - -/* This set tries to map as close as possible to the visible characteristics - * of the ASCII symbol, lowercase and uppercase letters may differ in - * presentation on the display. - */ -#define MAP_ASCII7SEG_ALPHANUM \ - _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \ - _MAP_33_47_ASCII_SEG7_SYMBOL \ - _MAP_48_57_ASCII_SEG7_NUMERIC \ - _MAP_58_64_ASCII_SEG7_SYMBOL \ - _MAP_65_90_ASCII_SEG7_ALPHA_UPPR \ - _MAP_91_96_ASCII_SEG7_SYMBOL \ - _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ - _MAP_123_126_ASCII_SEG7_SYMBOL - -/* This set tries to map as close as possible to the symbolic characteristics - * of the ASCII character for maximum discrimination. - * For now this means all alpha chars are in lower case representations. - * (This for example facilitates the use of hex numbers with uppercase input.) - */ -#define MAP_ASCII7SEG_ALPHANUM_LC \ - _MAP_0_32_ASCII_SEG7_NON_PRINTABLE \ - _MAP_33_47_ASCII_SEG7_SYMBOL \ - _MAP_48_57_ASCII_SEG7_NUMERIC \ - _MAP_58_64_ASCII_SEG7_SYMBOL \ - _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ - _MAP_91_96_ASCII_SEG7_SYMBOL \ - _MAP_97_122_ASCII_SEG7_ALPHA_LOWER \ - _MAP_123_126_ASCII_SEG7_SYMBOL - -#define SEG7_DEFAULT_MAP(_name) \ - SEG7_CONVERSION_MAP(_name,MAP_ASCII7SEG_ALPHANUM) - -#endif /* MAP_TO_7SEGMENT_H */ - diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c deleted file mode 100644 index 4f93a760fae..00000000000 --- a/drivers/usb/input/powermate.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * A driver for the Griffin Technology, Inc. "PowerMate" USB controller dial. - * - * v1.1, (c)2002 William R Sowerbutts <will@sowerbutts.com> - * - * This device is a anodised aluminium knob which connects over USB. It can measure - * clockwise and anticlockwise rotation. The dial also acts as a pushbutton with - * a spring for automatic release. The base contains a pair of LEDs which illuminate - * the translucent base. It rotates without limit and reports its relative rotation - * back to the host when polled by the USB controller. - * - * Testing with the knob I have has shown that it measures approximately 94 "clicks" - * for one full rotation. Testing with my High Speed Rotation Actuator (ok, it was - * a variable speed cordless electric drill) has shown that the device can measure - * speeds of up to 7 clicks either clockwise or anticlockwise between pollings from - * the host. If it counts more than 7 clicks before it is polled, it will wrap back - * to zero and start counting again. This was at quite high speed, however, almost - * certainly faster than the human hand could turn it. Griffin say that it loses a - * pulse or two on a direction change; the granularity is so fine that I never - * noticed this in practice. - * - * The device's microcontroller can be programmed to set the LED to either a constant - * intensity, or to a rhythmic pulsing. Several patterns and speeds are available. - * - * Griffin were very happy to provide documentation and free hardware for development. - * - * Some userspace tools are available on the web: http://sowerbutts.com/powermate/ - * - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/usb/input.h> - -#define POWERMATE_VENDOR 0x077d /* Griffin Technology, Inc. */ -#define POWERMATE_PRODUCT_NEW 0x0410 /* Griffin PowerMate */ -#define POWERMATE_PRODUCT_OLD 0x04AA /* Griffin soundKnob */ - -#define CONTOUR_VENDOR 0x05f3 /* Contour Design, Inc. */ -#define CONTOUR_JOG 0x0240 /* Jog and Shuttle */ - -/* these are the command codes we send to the device */ -#define SET_STATIC_BRIGHTNESS 0x01 -#define SET_PULSE_ASLEEP 0x02 -#define SET_PULSE_AWAKE 0x03 -#define SET_PULSE_MODE 0x04 - -/* these refer to bits in the powermate_device's requires_update field. */ -#define UPDATE_STATIC_BRIGHTNESS (1<<0) -#define UPDATE_PULSE_ASLEEP (1<<1) -#define UPDATE_PULSE_AWAKE (1<<2) -#define UPDATE_PULSE_MODE (1<<3) - -/* at least two versions of the hardware exist, with differing payload - sizes. the first three bytes always contain the "interesting" data in - the relevant format. */ -#define POWERMATE_PAYLOAD_SIZE_MAX 6 -#define POWERMATE_PAYLOAD_SIZE_MIN 3 -struct powermate_device { - signed char *data; - dma_addr_t data_dma; - struct urb *irq, *config; - struct usb_ctrlrequest *configcr; - dma_addr_t configcr_dma; - struct usb_device *udev; - struct input_dev *input; - spinlock_t lock; - int static_brightness; - int pulse_speed; - int pulse_table; - int pulse_asleep; - int pulse_awake; - int requires_update; // physical settings which are out of sync - char phys[64]; -}; - -static char pm_name_powermate[] = "Griffin PowerMate"; -static char pm_name_soundknob[] = "Griffin SoundKnob"; - -static void powermate_config_complete(struct urb *urb); - -/* Callback for data arriving from the PowerMate over the USB interrupt pipe */ -static void powermate_irq(struct urb *urb) -{ - struct powermate_device *pm = urb->context; - 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; - } - - /* handle updates to device state */ - input_report_key(pm->input, BTN_0, pm->data[0] & 0x01); - input_report_rel(pm->input, REL_DIAL, pm->data[1]); - input_sync(pm->input); - -exit: - retval = usb_submit_urb (urb, GFP_ATOMIC); - if (retval) - err ("%s - usb_submit_urb failed with result %d", - __FUNCTION__, retval); -} - -/* Decide if we need to issue a control message and do so. Must be called with pm->lock taken */ -static void powermate_sync_state(struct powermate_device *pm) -{ - if (pm->requires_update == 0) - return; /* no updates are required */ - if (pm->config->status == -EINPROGRESS) - return; /* an update is already in progress; it'll issue this update when it completes */ - - if (pm->requires_update & UPDATE_PULSE_ASLEEP){ - pm->configcr->wValue = cpu_to_le16( SET_PULSE_ASLEEP ); - pm->configcr->wIndex = cpu_to_le16( pm->pulse_asleep ? 1 : 0 ); - pm->requires_update &= ~UPDATE_PULSE_ASLEEP; - }else if (pm->requires_update & UPDATE_PULSE_AWAKE){ - pm->configcr->wValue = cpu_to_le16( SET_PULSE_AWAKE ); - pm->configcr->wIndex = cpu_to_le16( pm->pulse_awake ? 1 : 0 ); - pm->requires_update &= ~UPDATE_PULSE_AWAKE; - }else if (pm->requires_update & UPDATE_PULSE_MODE){ - int op, arg; - /* the powermate takes an operation and an argument for its pulse algorithm. - the operation can be: - 0: divide the speed - 1: pulse at normal speed - 2: multiply the speed - the argument only has an effect for operations 0 and 2, and ranges between - 1 (least effect) to 255 (maximum effect). - - thus, several states are equivalent and are coalesced into one state. - - we map this onto a range from 0 to 510, with: - 0 -- 254 -- use divide (0 = slowest) - 255 -- use normal speed - 256 -- 510 -- use multiple (510 = fastest). - - Only values of 'arg' quite close to 255 are particularly useful/spectacular. - */ - if (pm->pulse_speed < 255) { - op = 0; // divide - arg = 255 - pm->pulse_speed; - } else if (pm->pulse_speed > 255) { - op = 2; // multiply - arg = pm->pulse_speed - 255; - } else { - op = 1; // normal speed - arg = 0; // can be any value - } - pm->configcr->wValue = cpu_to_le16( (pm->pulse_table << 8) | SET_PULSE_MODE ); - pm->configcr->wIndex = cpu_to_le16( (arg << 8) | op ); - pm->requires_update &= ~UPDATE_PULSE_MODE; - } else if (pm->requires_update & UPDATE_STATIC_BRIGHTNESS) { - pm->configcr->wValue = cpu_to_le16( SET_STATIC_BRIGHTNESS ); - pm->configcr->wIndex = cpu_to_le16( pm->static_brightness ); - pm->requires_update &= ~UPDATE_STATIC_BRIGHTNESS; - } else { - printk(KERN_ERR "powermate: unknown update required"); - pm->requires_update = 0; /* fudge the bug */ - return; - } - -/* printk("powermate: %04x %04x\n", pm->configcr->wValue, pm->configcr->wIndex); */ - - pm->configcr->bRequestType = 0x41; /* vendor request */ - pm->configcr->bRequest = 0x01; - pm->configcr->wLength = 0; - - usb_fill_control_urb(pm->config, pm->udev, usb_sndctrlpipe(pm->udev, 0), - (void *) pm->configcr, NULL, 0, - powermate_config_complete, pm); - pm->config->setup_dma = pm->configcr_dma; - pm->config->transfer_flags |= URB_NO_SETUP_DMA_MAP; - - if (usb_submit_urb(pm->config, GFP_ATOMIC)) - printk(KERN_ERR "powermate: usb_submit_urb(config) failed"); -} - -/* Called when our asynchronous control message completes. We may need to issue another immediately */ -static void powermate_config_complete(struct urb *urb) -{ - struct powermate_device *pm = urb->context; - unsigned long flags; - - if (urb->status) - printk(KERN_ERR "powermate: config urb returned %d\n", urb->status); - - spin_lock_irqsave(&pm->lock, flags); - powermate_sync_state(pm); - spin_unlock_irqrestore(&pm->lock, flags); -} - -/* Set the LED up as described and begin the sync with the hardware if required */ -static void powermate_pulse_led(struct powermate_device *pm, int static_brightness, int pulse_speed, - int pulse_table, int pulse_asleep, int pulse_awake) -{ - unsigned long flags; - - if (pulse_speed < 0) - pulse_speed = 0; - if (pulse_table < 0) - pulse_table = 0; - if (pulse_speed > 510) - pulse_speed = 510; - if (pulse_table > 2) - pulse_table = 2; - - pulse_asleep = !!pulse_asleep; - pulse_awake = !!pulse_awake; - - - spin_lock_irqsave(&pm->lock, flags); - - /* mark state updates which are required */ - if (static_brightness != pm->static_brightness) { - pm->static_brightness = static_brightness; - pm->requires_update |= UPDATE_STATIC_BRIGHTNESS; - } - if (pulse_asleep != pm->pulse_asleep) { - pm->pulse_asleep = pulse_asleep; - pm->requires_update |= (UPDATE_PULSE_ASLEEP | UPDATE_STATIC_BRIGHTNESS); - } - if (pulse_awake != pm->pulse_awake) { - pm->pulse_awake = pulse_awake; - pm->requires_update |= (UPDATE_PULSE_AWAKE | UPDATE_STATIC_BRIGHTNESS); - } - if (pulse_speed != pm->pulse_speed || pulse_table != pm->pulse_table) { - pm->pulse_speed = pulse_speed; - pm->pulse_table = pulse_table; - pm->requires_update |= UPDATE_PULSE_MODE; - } - - powermate_sync_state(pm); - - spin_unlock_irqrestore(&pm->lock, flags); -} - -/* Callback from the Input layer when an event arrives from userspace to configure the LED */ -static int powermate_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int _value) -{ - unsigned int command = (unsigned int)_value; - struct powermate_device *pm = input_get_drvdata(dev); - - if (type == EV_MSC && code == MSC_PULSELED){ - /* - bits 0- 7: 8 bits: LED brightness - bits 8-16: 9 bits: pulsing speed modifier (0 ... 510); 0-254 = slower, 255 = standard, 256-510 = faster. - bits 17-18: 2 bits: pulse table (0, 1, 2 valid) - bit 19: 1 bit : pulse whilst asleep? - bit 20: 1 bit : pulse constantly? - */ - int static_brightness = command & 0xFF; // bits 0-7 - int pulse_speed = (command >> 8) & 0x1FF; // bits 8-16 - int pulse_table = (command >> 17) & 0x3; // bits 17-18 - int pulse_asleep = (command >> 19) & 0x1; // bit 19 - int pulse_awake = (command >> 20) & 0x1; // bit 20 - - powermate_pulse_led(pm, static_brightness, pulse_speed, pulse_table, pulse_asleep, pulse_awake); - } - - return 0; -} - -static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_device *pm) -{ - pm->data = usb_buffer_alloc(udev, POWERMATE_PAYLOAD_SIZE_MAX, - GFP_ATOMIC, &pm->data_dma); - if (!pm->data) - return -1; - - pm->configcr = usb_buffer_alloc(udev, sizeof(*(pm->configcr)), - GFP_ATOMIC, &pm->configcr_dma); - if (!pm->configcr) - return -1; - - return 0; -} - -static void powermate_free_buffers(struct usb_device *udev, struct powermate_device *pm) -{ - if (pm->data) - usb_buffer_free(udev, POWERMATE_PAYLOAD_SIZE_MAX, - pm->data, pm->data_dma); - if (pm->configcr) - usb_buffer_free(udev, sizeof(*(pm->configcr)), - pm->configcr, pm->configcr_dma); -} - -/* Called whenever a USB device matching one in our supported devices table is connected */ -static int powermate_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev (intf); - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct powermate_device *pm; - struct input_dev *input_dev; - int pipe, maxp; - int error = -ENOMEM; - - interface = intf->cur_altsetting; - endpoint = &interface->endpoint[0].desc; - if (!usb_endpoint_is_int_in(endpoint)) - return -EIO; - - usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0x0a, USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, interface->desc.bInterfaceNumber, NULL, 0, - USB_CTRL_SET_TIMEOUT); - - pm = kzalloc(sizeof(struct powermate_device), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!pm || !input_dev) - goto fail1; - - if (powermate_alloc_buffers(udev, pm)) - goto fail2; - - pm->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!pm->irq) - goto fail2; - - pm->config = usb_alloc_urb(0, GFP_KERNEL); - if (!pm->config) - goto fail3; - - pm->udev = udev; - pm->input = input_dev; - - usb_make_path(udev, pm->phys, sizeof(pm->phys)); - strlcpy(pm->phys, "/input0", sizeof(pm->phys)); - - spin_lock_init(&pm->lock); - - switch (le16_to_cpu(udev->descriptor.idProduct)) { - case POWERMATE_PRODUCT_NEW: - input_dev->name = pm_name_powermate; - break; - case POWERMATE_PRODUCT_OLD: - input_dev->name = pm_name_soundknob; - break; - default: - input_dev->name = pm_name_soundknob; - printk(KERN_WARNING "powermate: unknown product id %04x\n", - le16_to_cpu(udev->descriptor.idProduct)); - } - - input_dev->phys = pm->phys; - usb_to_input_id(udev, &input_dev->id); - input_dev->dev.parent = &intf->dev; - - input_set_drvdata(input_dev, pm); - - input_dev->event = powermate_input_event; - - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_MSC); - input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0); - input_dev->relbit[LONG(REL_DIAL)] = BIT(REL_DIAL); - input_dev->mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED); - - /* get a handle to the interrupt data pipe */ - pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); - - if (maxp < POWERMATE_PAYLOAD_SIZE_MIN || maxp > POWERMATE_PAYLOAD_SIZE_MAX) { - printk(KERN_WARNING "powermate: Expected payload of %d--%d bytes, found %d bytes!\n", - POWERMATE_PAYLOAD_SIZE_MIN, POWERMATE_PAYLOAD_SIZE_MAX, maxp); - maxp = POWERMATE_PAYLOAD_SIZE_MAX; - } - - usb_fill_int_urb(pm->irq, udev, pipe, pm->data, - maxp, powermate_irq, - pm, endpoint->bInterval); - pm->irq->transfer_dma = pm->data_dma; - pm->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - /* register our interrupt URB with the USB system */ - if (usb_submit_urb(pm->irq, GFP_KERNEL)) { - error = -EIO; - goto fail4; - } - - error = input_register_device(pm->input); - if (error) - goto fail5; - - - /* force an update of everything */ - pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS; - powermate_pulse_led(pm, 0x80, 255, 0, 1, 0); // set default pulse parameters - - usb_set_intfdata(intf, pm); - return 0; - - fail5: usb_kill_urb(pm->irq); - fail4: usb_free_urb(pm->config); - fail3: usb_free_urb(pm->irq); - fail2: powermate_free_buffers(udev, pm); - fail1: input_free_device(input_dev); - kfree(pm); - return error; -} - -/* Called when a USB device we've accepted ownership of is removed */ -static void powermate_disconnect(struct usb_interface *intf) -{ - struct powermate_device *pm = usb_get_intfdata (intf); - - usb_set_intfdata(intf, NULL); - if (pm) { - pm->requires_update = 0; - usb_kill_urb(pm->irq); - input_unregister_device(pm->input); - usb_free_urb(pm->irq); - usb_free_urb(pm->config); - powermate_free_buffers(interface_to_usbdev(intf), pm); - - kfree(pm); - } -} - -static struct usb_device_id powermate_devices [] = { - { USB_DEVICE(POWERMATE_VENDOR, POWERMATE_PRODUCT_NEW) }, - { USB_DEVICE(POWERMATE_VENDOR, POWERMATE_PRODUCT_OLD) }, - { USB_DEVICE(CONTOUR_VENDOR, CONTOUR_JOG) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, powermate_devices); - -static struct usb_driver powermate_driver = { - .name = "powermate", - .probe = powermate_probe, - .disconnect = powermate_disconnect, - .id_table = powermate_devices, -}; - -static int __init powermate_init(void) -{ - return usb_register(&powermate_driver); -} - -static void __exit powermate_cleanup(void) -{ - usb_deregister(&powermate_driver); -} - -module_init(powermate_init); -module_exit(powermate_cleanup); - -MODULE_AUTHOR( "William R Sowerbutts" ); -MODULE_DESCRIPTION( "Griffin Technology, Inc PowerMate driver" ); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c deleted file mode 100644 index e0829413336..00000000000 --- a/drivers/usb/input/usbtouchscreen.c +++ /dev/null @@ -1,840 +0,0 @@ -/****************************************************************************** - * usbtouchscreen.c - * Driver for USB Touchscreens, supporting those devices: - * - eGalax Touchkit - * includes eTurboTouch CT-410/510/700 - * - 3M/Microtouch EX II series - * - ITM - * - PanJit TouchSet - * - eTurboTouch - * - Gunze AHL61 - * - DMC TSC-10/25 - * - * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch> - * Copyright (C) by Todd E. Johnson (mtouchusb.c) - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Driver is based on touchkitusb.c - * - ITM parts are from itmtouch.c - * - 3M parts are from mtouchusb.c - * - PanJit parts are from an unmerged driver by Lanslott Gish - * - DMC TSC 10/25 are from Holger Schurig, with ideas from an unmerged - * driver from Marius Vollmer - * - *****************************************************************************/ - -//#define DEBUG - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/input.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/usb.h> -#include <linux/usb/input.h> - - -#define DRIVER_VERSION "v0.5" -#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" -#define DRIVER_DESC "USB Touchscreen Driver" - -static int swap_xy; -module_param(swap_xy, bool, 0644); -MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); - -/* device specifc data/functions */ -struct usbtouch_usb; -struct usbtouch_device_info { - int min_xc, max_xc; - int min_yc, max_yc; - int min_press, max_press; - int rept_size; - int flags; - - void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len); - int (*get_pkt_len) (unsigned char *pkt, int len); - int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt); - int (*init) (struct usbtouch_usb *usbtouch); -}; - -#define USBTOUCH_FLG_BUFFER 0x01 - - -/* a usbtouch device */ -struct usbtouch_usb { - unsigned char *data; - dma_addr_t data_dma; - unsigned char *buffer; - int buf_len; - struct urb *irq; - struct usb_device *udev; - struct input_dev *input; - struct usbtouch_device_info *type; - char name[128]; - char phys[64]; - - int x, y; - int touch, press; -}; - - -#if defined(CONFIG_USB_TOUCHSCREEN_EGALAX) || defined(CONFIG_USB_TOUCHSCREEN_ETURBO) -#define MULTI_PACKET -#endif - -#ifdef MULTI_PACKET -static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, - unsigned char *pkt, int len); -#endif - -/* device types */ -enum { - DEVTPYE_DUMMY = -1, - DEVTYPE_EGALAX, - DEVTYPE_PANJIT, - DEVTYPE_3M, - DEVTYPE_ITM, - DEVTYPE_ETURBO, - DEVTYPE_GUNZE, - DEVTYPE_DMC_TSC10, -}; - -static struct usb_device_id usbtouch_devices[] = { -#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX - {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX}, - {USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX}, - {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX}, - {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX}, - {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX}, - {USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX}, - {USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX}, -#endif - -#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT - {USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT}, - {USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT}, - {USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT}, - {USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT}, -#endif - -#ifdef CONFIG_USB_TOUCHSCREEN_3M - {USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M}, -#endif - -#ifdef CONFIG_USB_TOUCHSCREEN_ITM - {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, -#endif - -#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO - {USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO}, -#endif - -#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE - {USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE}, -#endif - -#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10 - {USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10}, -#endif - - {} -}; - - -/***************************************************************************** - * eGalax part - */ - -#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX - -#define EGALAX_PKT_TYPE_MASK 0xFE -#define EGALAX_PKT_TYPE_REPT 0x80 -#define EGALAX_PKT_TYPE_DIAG 0x0A - -static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt) -{ - if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) - return 0; - - dev->x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F); - dev->y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F); - dev->touch = pkt[0] & 0x01; - - return 1; -} - -static int egalax_get_pkt_len(unsigned char *buf, int len) -{ - switch (buf[0] & EGALAX_PKT_TYPE_MASK) { - case EGALAX_PKT_TYPE_REPT: - return 5; - - case EGALAX_PKT_TYPE_DIAG: - if (len < 2) - return -1; - - return buf[1] + 2; - } - - return 0; -} -#endif - - -/***************************************************************************** - * PanJit Part - */ -#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT -static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt) -{ - dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; - dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; - dev->touch = pkt[0] & 0x01; - - return 1; -} -#endif - - -/***************************************************************************** - * 3M/Microtouch Part - */ -#ifdef CONFIG_USB_TOUCHSCREEN_3M - -#define MTOUCHUSB_ASYNC_REPORT 1 -#define MTOUCHUSB_RESET 7 -#define MTOUCHUSB_REQ_CTRLLR_ID 10 - -static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) -{ - dev->x = (pkt[8] << 8) | pkt[7]; - dev->y = (pkt[10] << 8) | pkt[9]; - dev->touch = (pkt[2] & 0x40) ? 1 : 0; - - return 1; -} - -static int mtouch_init(struct usbtouch_usb *usbtouch) -{ - int ret, i; - - ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), - MTOUCHUSB_RESET, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); - dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", - __FUNCTION__, ret); - if (ret < 0) - return ret; - msleep(150); - - for (i = 0; i < 3; i++) { - ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), - MTOUCHUSB_ASYNC_REPORT, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); - dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", - __FUNCTION__, ret); - if (ret >= 0) - break; - if (ret != -EPIPE) - return ret; - } - - return 0; -} -#endif - - -/***************************************************************************** - * ITM Part - */ -#ifdef CONFIG_USB_TOUCHSCREEN_ITM -static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt) -{ - int touch; - /* - * ITM devices report invalid x/y data if not touched. - * if the screen was touched before but is not touched any more - * report touch as 0 with the last valid x/y data once. then stop - * reporting data until touched again. - */ - dev->press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F); - - touch = ~pkt[7] & 0x20; - if (!touch) { - if (dev->touch) { - dev->touch = 0; - return 1; - } - - return 0; - } - - dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F); - dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F); - dev->touch = touch; - - return 1; -} -#endif - - -/***************************************************************************** - * eTurboTouch part - */ -#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO -static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) -{ - unsigned int shift; - - /* packets should start with sync */ - if (!(pkt[0] & 0x80)) - return 0; - - shift = (6 - (pkt[0] & 0x03)); - dev->x = ((pkt[3] << 7) | pkt[4]) >> shift; - dev->y = ((pkt[1] << 7) | pkt[2]) >> shift; - dev->touch = (pkt[0] & 0x10) ? 1 : 0; - - return 1; -} - -static int eturbo_get_pkt_len(unsigned char *buf, int len) -{ - if (buf[0] & 0x80) - return 5; - if (buf[0] == 0x01) - return 3; - return 0; -} -#endif - - -/***************************************************************************** - * Gunze part - */ -#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE -static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt) -{ - if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80)) - return 0; - - dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F); - dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F); - dev->touch = pkt[0] & 0x20; - - return 1; -} -#endif - -/***************************************************************************** - * DMC TSC-10/25 Part - * - * Documentation about the controller and it's protocol can be found at - * http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf - * http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf - */ -#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10 - -/* supported data rates. currently using 130 */ -#define TSC10_RATE_POINT 0x50 -#define TSC10_RATE_30 0x40 -#define TSC10_RATE_50 0x41 -#define TSC10_RATE_80 0x42 -#define TSC10_RATE_100 0x43 -#define TSC10_RATE_130 0x44 -#define TSC10_RATE_150 0x45 - -/* commands */ -#define TSC10_CMD_RESET 0x55 -#define TSC10_CMD_RATE 0x05 -#define TSC10_CMD_DATA1 0x01 - -static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) -{ - struct usb_device *dev = usbtouch->udev; - int ret; - unsigned char buf[2]; - - /* reset */ - buf[0] = buf[1] = 0xFF; - ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), - TSC10_CMD_RESET, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT); - if (ret < 0) - return ret; - if (buf[0] != 0x06 || buf[1] != 0x00) - return -ENODEV; - - /* set coordinate output rate */ - buf[0] = buf[1] = 0xFF; - ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), - TSC10_CMD_RATE, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); - if (ret < 0) - return ret; - if (buf[0] != 0x06 || buf[1] != 0x00) - return -ENODEV; - - /* start sending data */ - ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), - TSC10_CMD_DATA1, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); - if (ret < 0) - return ret; - - return 0; -} - - -static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt) -{ - dev->x = ((pkt[2] & 0x03) << 8) | pkt[1]; - dev->y = ((pkt[4] & 0x03) << 8) | pkt[3]; - dev->touch = pkt[0] & 0x01; - - return 1; -} -#endif - - -/***************************************************************************** - * the different device descriptors - */ -static struct usbtouch_device_info usbtouch_dev_info[] = { -#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX - [DEVTYPE_EGALAX] = { - .min_xc = 0x0, - .max_xc = 0x07ff, - .min_yc = 0x0, - .max_yc = 0x07ff, - .rept_size = 16, - .flags = USBTOUCH_FLG_BUFFER, - .process_pkt = usbtouch_process_multi, - .get_pkt_len = egalax_get_pkt_len, - .read_data = egalax_read_data, - }, -#endif - -#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT - [DEVTYPE_PANJIT] = { - .min_xc = 0x0, - .max_xc = 0x0fff, - .min_yc = 0x0, - .max_yc = 0x0fff, - .rept_size = 8, - .read_data = panjit_read_data, - }, -#endif - -#ifdef CONFIG_USB_TOUCHSCREEN_3M - [DEVTYPE_3M] = { - .min_xc = 0x0, - .max_xc = 0x4000, - .min_yc = 0x0, - .max_yc = 0x4000, - .rept_size = 11, - .read_data = mtouch_read_data, - .init = mtouch_init, - }, -#endif - -#ifdef CONFIG_USB_TOUCHSCREEN_ITM - [DEVTYPE_ITM] = { - .min_xc = 0x0, - .max_xc = 0x0fff, - .min_yc = 0x0, - .max_yc = 0x0fff, - .max_press = 0xff, - .rept_size = 8, - .read_data = itm_read_data, - }, -#endif - -#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO - [DEVTYPE_ETURBO] = { - .min_xc = 0x0, - .max_xc = 0x07ff, - .min_yc = 0x0, - .max_yc = 0x07ff, - .rept_size = 8, - .flags = USBTOUCH_FLG_BUFFER, - .process_pkt = usbtouch_process_multi, - .get_pkt_len = eturbo_get_pkt_len, - .read_data = eturbo_read_data, - }, -#endif - -#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE - [DEVTYPE_GUNZE] = { - .min_xc = 0x0, - .max_xc = 0x0fff, - .min_yc = 0x0, - .max_yc = 0x0fff, - .rept_size = 4, - .read_data = gunze_read_data, - }, -#endif - -#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10 - [DEVTYPE_DMC_TSC10] = { - .min_xc = 0x0, - .max_xc = 0x03ff, - .min_yc = 0x0, - .max_yc = 0x03ff, - .rept_size = 5, - .init = dmc_tsc10_init, - .read_data = dmc_tsc10_read_data, - }, -#endif -}; - - -/***************************************************************************** - * Generic Part - */ -static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, - unsigned char *pkt, int len) -{ - struct usbtouch_device_info *type = usbtouch->type; - - if (!type->read_data(usbtouch, pkt)) - return; - - input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch); - - if (swap_xy) { - input_report_abs(usbtouch->input, ABS_X, usbtouch->y); - input_report_abs(usbtouch->input, ABS_Y, usbtouch->x); - } else { - input_report_abs(usbtouch->input, ABS_X, usbtouch->x); - input_report_abs(usbtouch->input, ABS_Y, usbtouch->y); - } - if (type->max_press) - input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press); - input_sync(usbtouch->input); -} - - -#ifdef MULTI_PACKET -static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, - unsigned char *pkt, int len) -{ - unsigned char *buffer; - int pkt_len, pos, buf_len, tmp; - - /* process buffer */ - if (unlikely(usbtouch->buf_len)) { - /* try to get size */ - pkt_len = usbtouch->type->get_pkt_len( - usbtouch->buffer, usbtouch->buf_len); - - /* drop? */ - if (unlikely(!pkt_len)) - goto out_flush_buf; - - /* need to append -pkt_len bytes before able to get size */ - if (unlikely(pkt_len < 0)) { - int append = -pkt_len; - if (unlikely(append > len)) - append = len; - if (usbtouch->buf_len + append >= usbtouch->type->rept_size) - goto out_flush_buf; - memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append); - usbtouch->buf_len += append; - - pkt_len = usbtouch->type->get_pkt_len( - usbtouch->buffer, usbtouch->buf_len); - if (pkt_len < 0) - return; - } - - /* append */ - tmp = pkt_len - usbtouch->buf_len; - if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size) - goto out_flush_buf; - memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp); - usbtouch_process_pkt(usbtouch, usbtouch->buffer, pkt_len); - - buffer = pkt + tmp; - buf_len = len - tmp; - } else { - buffer = pkt; - buf_len = len; - } - - /* loop over the received packet, process */ - pos = 0; - while (pos < buf_len) { - /* get packet len */ - pkt_len = usbtouch->type->get_pkt_len(buffer + pos, len); - - /* unknown packet: drop everything */ - if (unlikely(!pkt_len)) - goto out_flush_buf; - - /* full packet: process */ - if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) { - usbtouch_process_pkt(usbtouch, buffer + pos, pkt_len); - } else { - /* incomplete packet: save in buffer */ - memcpy(usbtouch->buffer, buffer + pos, buf_len - pos); - usbtouch->buf_len = buf_len - pos; - return; - } - pos += pkt_len; - } - -out_flush_buf: - usbtouch->buf_len = 0; - return; -} -#endif - - -static void usbtouch_irq(struct urb *urb) -{ - struct usbtouch_usb *usbtouch = urb->context; - int retval; - - switch (urb->status) { - case 0: - /* success */ - break; - case -ETIME: - /* this urb is timing out */ - dbg("%s - urb timed out - was the device unplugged?", - __FUNCTION__); - return; - 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; - } - - usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length); - -exit: - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - err("%s - usb_submit_urb failed with result: %d", - __FUNCTION__, retval); -} - -static int usbtouch_open(struct input_dev *input) -{ - struct usbtouch_usb *usbtouch = input_get_drvdata(input); - - usbtouch->irq->dev = usbtouch->udev; - - if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) - return -EIO; - - return 0; -} - -static void usbtouch_close(struct input_dev *input) -{ - struct usbtouch_usb *usbtouch = input_get_drvdata(input); - - usb_kill_urb(usbtouch->irq); -} - - -static void usbtouch_free_buffers(struct usb_device *udev, - struct usbtouch_usb *usbtouch) -{ - if (usbtouch->data) - usb_buffer_free(udev, usbtouch->type->rept_size, - usbtouch->data, usbtouch->data_dma); - kfree(usbtouch->buffer); -} - - -static int usbtouch_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usbtouch_usb *usbtouch; - struct input_dev *input_dev; - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct usb_device *udev = interface_to_usbdev(intf); - struct usbtouch_device_info *type; - int err = -ENOMEM; - - interface = intf->cur_altsetting; - endpoint = &interface->endpoint[0].desc; - - usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!usbtouch || !input_dev) - goto out_free; - - type = &usbtouch_dev_info[id->driver_info]; - usbtouch->type = type; - if (!type->process_pkt) - type->process_pkt = usbtouch_process_pkt; - - usbtouch->data = usb_buffer_alloc(udev, type->rept_size, - GFP_KERNEL, &usbtouch->data_dma); - if (!usbtouch->data) - goto out_free; - - if (type->flags & USBTOUCH_FLG_BUFFER) { - usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL); - if (!usbtouch->buffer) - goto out_free_buffers; - } - - usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!usbtouch->irq) { - dbg("%s - usb_alloc_urb failed: usbtouch->irq", __FUNCTION__); - goto out_free_buffers; - } - - usbtouch->udev = udev; - usbtouch->input = input_dev; - - if (udev->manufacturer) - strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name)); - - if (udev->product) { - if (udev->manufacturer) - strlcat(usbtouch->name, " ", sizeof(usbtouch->name)); - strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name)); - } - - if (!strlen(usbtouch->name)) - snprintf(usbtouch->name, sizeof(usbtouch->name), - "USB Touchscreen %04x:%04x", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); - - usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys)); - strlcpy(usbtouch->phys, "/input0", sizeof(usbtouch->phys)); - - input_dev->name = usbtouch->name; - input_dev->phys = usbtouch->phys; - usb_to_input_id(udev, &input_dev->id); - input_dev->dev.parent = &intf->dev; - - input_set_drvdata(input_dev, usbtouch); - - input_dev->open = usbtouch_open; - input_dev->close = usbtouch_close; - - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0); - input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0); - if (type->max_press) - input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press, - type->max_press, 0, 0); - - usb_fill_int_urb(usbtouch->irq, usbtouch->udev, - usb_rcvintpipe(usbtouch->udev, endpoint->bEndpointAddress), - usbtouch->data, type->rept_size, - usbtouch_irq, usbtouch, endpoint->bInterval); - - usbtouch->irq->dev = usbtouch->udev; - usbtouch->irq->transfer_dma = usbtouch->data_dma; - usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - /* device specific init */ - if (type->init) { - err = type->init(usbtouch); - if (err) { - dbg("%s - type->init() failed, err: %d", __FUNCTION__, err); - goto out_free_buffers; - } - } - - err = input_register_device(usbtouch->input); - if (err) { - dbg("%s - input_register_device failed, err: %d", __FUNCTION__, err); - goto out_free_buffers; - } - - usb_set_intfdata(intf, usbtouch); - - return 0; - -out_free_buffers: - usbtouch_free_buffers(udev, usbtouch); -out_free: - input_free_device(input_dev); - kfree(usbtouch); - return err; -} - -static void usbtouch_disconnect(struct usb_interface *intf) -{ - struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); - - dbg("%s - called", __FUNCTION__); - - if (!usbtouch) - return; - - dbg("%s - usbtouch is initialized, cleaning up", __FUNCTION__); - usb_set_intfdata(intf, NULL); - usb_kill_urb(usbtouch->irq); - input_unregister_device(usbtouch->input); - usb_free_urb(usbtouch->irq); - usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); - kfree(usbtouch); -} - -MODULE_DEVICE_TABLE(usb, usbtouch_devices); - -static struct usb_driver usbtouch_driver = { - .name = "usbtouchscreen", - .probe = usbtouch_probe, - .disconnect = usbtouch_disconnect, - .id_table = usbtouch_devices, -}; - -static int __init usbtouch_init(void) -{ - return usb_register(&usbtouch_driver); -} - -static void __exit usbtouch_cleanup(void) -{ - usb_deregister(&usbtouch_driver); -} - -module_init(usbtouch_init); -module_exit(usbtouch_cleanup); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); - -MODULE_ALIAS("touchkitusb"); -MODULE_ALIAS("itmtouch"); -MODULE_ALIAS("mtouchusb"); 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 a2302228724..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 { - signed char *data; - int tool[2]; - int id[2]; - __u32 serial[2]; - struct wacom_features *features; -}; - -#endif diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c deleted file mode 100644 index 8c8cd95a698..00000000000 --- a/drivers/usb/input/xpad.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - * X-Box gamepad - v0.0.6 - * - * Copyright (c) 2002 Marko Friedemann <mfr@bmx-chemnitz.de> - * 2004 Oliver Schwartz <Oliver.Schwartz@gmx.de>, - * Steven Toth <steve@toth.demon.co.uk>, - * Franz Lehner <franz@caos.at>, - * Ivan Hawkes <blackhawk@ivanhawkes.com> - * 2005 Dominic Cerquetti <binary1230@yahoo.com> - * 2006 Adam Buchbinder <adam.buchbinder@gmail.com> - * - * 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 - * - * - * This driver is based on: - * - information from http://euc.jp/periphs/xbox-controller.ja.html - * - the iForce driver drivers/char/joystick/iforce.c - * - the skeleton-driver drivers/usb/usb-skeleton.c - * - * Thanks to: - * - ITO Takayuki for providing essential xpad information on his website - * - Vojtech Pavlik - iforce driver / input subsystem - * - Greg Kroah-Hartman - usb-skeleton driver - * - XBOX Linux project - extra USB id's - * - * TODO: - * - fine tune axes (especially trigger axes) - * - fix "analog" buttons (reported as digital now) - * - get rumble working - * - need USB IDs for other dance pads - * - * History: - * - * 2002-06-27 - 0.0.1 : first version, just said "XBOX HID controller" - * - * 2002-07-02 - 0.0.2 : basic working version - * - all axes and 9 of the 10 buttons work (german InterAct device) - * - the black button does not work - * - * 2002-07-14 - 0.0.3 : rework by Vojtech Pavlik - * - indentation fixes - * - usb + input init sequence fixes - * - * 2002-07-16 - 0.0.4 : minor changes, merge with Vojtech's v0.0.3 - * - verified the lack of HID and report descriptors - * - verified that ALL buttons WORK - * - fixed d-pad to axes mapping - * - * 2002-07-17 - 0.0.5 : simplified d-pad handling - * - * 2004-10-02 - 0.0.6 : DDR pad support - * - borrowed from the XBOX linux kernel - * - USB id's for commonly used dance pads are present - * - dance pads will map D-PAD to buttons, not axes - * - pass the module paramater 'dpad_to_buttons' to force - * the D-PAD to map to buttons if your pad is not detected - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/stat.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/usb/input.h> - -#define DRIVER_VERSION "v0.0.6" -#define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>" -#define DRIVER_DESC "X-Box pad driver" - -#define XPAD_PKT_LEN 32 - -/* xbox d-pads should map to buttons, as is required for DDR pads - but we map them to axes when possible to simplify things */ -#define MAP_DPAD_TO_BUTTONS 0 -#define MAP_DPAD_TO_AXES 1 -#define MAP_DPAD_UNKNOWN -1 - -static int dpad_to_buttons; -module_param(dpad_to_buttons, bool, S_IRUGO); -MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads"); - -static const struct xpad_device { - u16 idVendor; - u16 idProduct; - char *name; - u8 dpad_mapping; -} xpad_device[] = { - { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES }, - { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES }, - { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES }, - { 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES }, - { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS }, - { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES }, - { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES }, - { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES }, - { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES }, - { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES }, - { 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES }, - { 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES }, - { 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES }, - { 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES }, - { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS }, - { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES }, - { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS }, - { 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES }, - { 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES }, - { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES }, - { 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES }, - { 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES}, - { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES }, - { 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES }, - { 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES }, - { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES }, - { 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES }, - { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES }, - { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES }, - { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS }, - { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS }, - { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES }, - { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN } -}; - -static const signed short xpad_btn[] = { - BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, /* "analog" buttons */ - BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR, /* start/back/sticks */ - -1 /* terminating entry */ -}; - -/* only used if MAP_DPAD_TO_BUTTONS */ -static const signed short xpad_btn_pad[] = { - BTN_LEFT, BTN_RIGHT, /* d-pad left, right */ - BTN_0, BTN_1, /* d-pad up, down (XXX names??) */ - -1 /* terminating entry */ -}; - -static const signed short xpad_abs[] = { - ABS_X, ABS_Y, /* left stick */ - ABS_RX, ABS_RY, /* right stick */ - ABS_Z, ABS_RZ, /* triggers left/right */ - -1 /* terminating entry */ -}; - -/* only used if MAP_DPAD_TO_AXES */ -static const signed short xpad_abs_pad[] = { - ABS_HAT0X, ABS_HAT0Y, /* d-pad axes */ - -1 /* terminating entry */ -}; - -static struct usb_device_id xpad_table [] = { - { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */ - { } -}; - -MODULE_DEVICE_TABLE (usb, xpad_table); - -struct usb_xpad { - struct input_dev *dev; /* input device interface */ - struct usb_device *udev; /* usb device */ - - struct urb *irq_in; /* urb for interrupt in report */ - unsigned char *idata; /* input data */ - dma_addr_t idata_dma; - - char phys[65]; /* physical device path */ - - int dpad_mapping; /* map d-pad to buttons or to axes */ -}; - -/* - * xpad_process_packet - * - * Completes a request by converting the data into events for the - * input subsystem. - * - * The used report descriptor was taken from ITO Takayukis website: - * http://euc.jp/periphs/xbox-controller.ja.html - */ - -static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) -{ - struct input_dev *dev = xpad->dev; - - /* left stick */ - input_report_abs(dev, ABS_X, (__s16) (((__s16)data[13] << 8) | data[12])); - input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[15] << 8) | data[14])); - - /* right stick */ - input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[17] << 8) | data[16])); - input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[19] << 8) | data[18])); - - /* triggers left/right */ - input_report_abs(dev, ABS_Z, data[10]); - input_report_abs(dev, ABS_RZ, data[11]); - - /* digital pad */ - if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { - input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); - input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); - } else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ { - input_report_key(dev, BTN_LEFT, data[2] & 0x04); - input_report_key(dev, BTN_RIGHT, data[2] & 0x08); - input_report_key(dev, BTN_0, data[2] & 0x01); // up - input_report_key(dev, BTN_1, data[2] & 0x02); // down - } - - /* start/back buttons and stick press left/right */ - input_report_key(dev, BTN_START, data[2] & 0x10); - input_report_key(dev, BTN_BACK, data[2] & 0x20); - input_report_key(dev, BTN_THUMBL, data[2] & 0x40); - input_report_key(dev, BTN_THUMBR, data[2] & 0x80); - - /* "analog" buttons A, B, X, Y */ - input_report_key(dev, BTN_A, data[4]); - input_report_key(dev, BTN_B, data[5]); - input_report_key(dev, BTN_X, data[6]); - input_report_key(dev, BTN_Y, data[7]); - - /* "analog" buttons black, white */ - input_report_key(dev, BTN_C, data[8]); - input_report_key(dev, BTN_Z, data[9]); - - input_sync(dev); -} - -static void xpad_irq_in(struct urb *urb) -{ - struct usb_xpad *xpad = urb->context; - 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; - } - - xpad_process_packet(xpad, 0, xpad->idata); - -exit: - retval = usb_submit_urb (urb, GFP_ATOMIC); - if (retval) - err ("%s - usb_submit_urb failed with result %d", - __FUNCTION__, retval); -} - -static int xpad_open (struct input_dev *dev) -{ - struct usb_xpad *xpad = input_get_drvdata(dev); - - xpad->irq_in->dev = xpad->udev; - if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) - return -EIO; - - return 0; -} - -static void xpad_close (struct input_dev *dev) -{ - struct usb_xpad *xpad = input_get_drvdata(dev); - - usb_kill_urb(xpad->irq_in); -} - -static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) -{ - set_bit(abs, input_dev->absbit); - - switch (abs) { - case ABS_X: - case ABS_Y: - case ABS_RX: - case ABS_RY: /* the two sticks */ - input_set_abs_params(input_dev, abs, -32768, 32767, 16, 128); - break; - case ABS_Z: - case ABS_RZ: /* the triggers */ - input_set_abs_params(input_dev, abs, 0, 255, 0, 0); - break; - case ABS_HAT0X: - case ABS_HAT0Y: /* the d-pad (only if MAP_DPAD_TO_AXES) */ - input_set_abs_params(input_dev, abs, -1, 1, 0, 0); - break; - } -} - -static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev (intf); - struct usb_xpad *xpad; - struct input_dev *input_dev; - struct usb_endpoint_descriptor *ep_irq_in; - int i; - int error = -ENOMEM; - - for (i = 0; xpad_device[i].idVendor; i++) { - if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && - (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct)) - break; - } - - xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!xpad || !input_dev) - goto fail1; - - xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, - GFP_ATOMIC, &xpad->idata_dma); - if (!xpad->idata) - goto fail1; - - xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL); - if (!xpad->irq_in) - goto fail2; - - xpad->udev = udev; - xpad->dpad_mapping = xpad_device[i].dpad_mapping; - if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN) - xpad->dpad_mapping = dpad_to_buttons; - xpad->dev = input_dev; - usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); - strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); - - input_dev->name = xpad_device[i].name; - input_dev->phys = xpad->phys; - usb_to_input_id(udev, &input_dev->id); - input_dev->dev.parent = &intf->dev; - - input_set_drvdata(input_dev, xpad); - - input_dev->open = xpad_open; - input_dev->close = xpad_close; - - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - - /* set up buttons */ - for (i = 0; xpad_btn[i] >= 0; i++) - set_bit(xpad_btn[i], input_dev->keybit); - if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) - for (i = 0; xpad_btn_pad[i] >= 0; i++) - set_bit(xpad_btn_pad[i], input_dev->keybit); - - /* set up axes */ - for (i = 0; xpad_abs[i] >= 0; i++) - xpad_set_up_abs(input_dev, xpad_abs[i]); - if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) - for (i = 0; xpad_abs_pad[i] >= 0; i++) - xpad_set_up_abs(input_dev, xpad_abs_pad[i]); - - ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; - usb_fill_int_urb(xpad->irq_in, udev, - usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), - xpad->idata, XPAD_PKT_LEN, xpad_irq_in, - xpad, ep_irq_in->bInterval); - xpad->irq_in->transfer_dma = xpad->idata_dma; - xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - error = input_register_device(xpad->dev); - if (error) - goto fail3; - - usb_set_intfdata(intf, xpad); - return 0; - - fail3: usb_free_urb(xpad->irq_in); - fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); - fail1: input_free_device(input_dev); - kfree(xpad); - return error; - -} - -static void xpad_disconnect(struct usb_interface *intf) -{ - struct usb_xpad *xpad = usb_get_intfdata (intf); - - usb_set_intfdata(intf, NULL); - if (xpad) { - usb_kill_urb(xpad->irq_in); - input_unregister_device(xpad->dev); - usb_free_urb(xpad->irq_in); - usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN, - xpad->idata, xpad->idata_dma); - kfree(xpad); - } -} - -static struct usb_driver xpad_driver = { - .name = "xpad", - .probe = xpad_probe, - .disconnect = xpad_disconnect, - .id_table = xpad_table, -}; - -static int __init usb_xpad_init(void) -{ - int result = usb_register(&xpad_driver); - if (result == 0) - info(DRIVER_DESC ":" DRIVER_VERSION); - return result; -} - -static void __exit usb_xpad_exit(void) -{ - usb_deregister(&xpad_driver); -} - -module_init(usb_xpad_init); -module_exit(usb_xpad_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c deleted file mode 100644 index c54f1a5dcb4..00000000000 --- a/drivers/usb/input/yealink.c +++ /dev/null @@ -1,1005 +0,0 @@ -/* - * drivers/usb/input/yealink.c - * - * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com> - * - * 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 - */ -/* - * Description: - * Driver for the USB-P1K voip usb phone. - * This device is produced by Yealink Network Technology Co Ltd - * but may be branded under several names: - * - Yealink usb-p1k - * - Tiptel 115 - * - ... - * - * This driver is based on: - * - the usbb2k-api http://savannah.nongnu.org/projects/usbb2k-api/ - * - information from http://memeteau.free.fr/usbb2k - * - the xpad-driver drivers/usb/input/xpad.c - * - * Thanks to: - * - Olivier Vandorpe, for providing the usbb2k-api. - * - Martin Diehl, for spotting my memory allocation bug. - * - * History: - * 20050527 henk First version, functional keyboard. Keyboard events - * will pop-up on the ../input/eventX bus. - * 20050531 henk Added led, LCD, dialtone and sysfs interface. - * 20050610 henk Cleanups, make it ready for public consumption. - * 20050630 henk Cleanups, fixes in response to comments. - * 20050701 henk sysfs write serialisation, fix potential unload races - * 20050801 henk Added ringtone, restructure USB - * 20050816 henk Merge 2.6.13-rc6 - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/rwsem.h> -#include <linux/usb/input.h> - -#include "map_to_7segment.h" -#include "yealink.h" - -#define DRIVER_VERSION "yld-20051230" -#define DRIVER_AUTHOR "Henk Vergonet" -#define DRIVER_DESC "Yealink phone driver" - -#define YEALINK_POLLING_FREQUENCY 10 /* in [Hz] */ - -struct yld_status { - u8 lcd[24]; - u8 led; - u8 dialtone; - u8 ringtone; - u8 keynum; -} __attribute__ ((packed)); - -/* - * Register the LCD segment and icon map - */ -#define _LOC(k,l) { .a = (k), .m = (l) } -#define _SEG(t, a, am, b, bm, c, cm, d, dm, e, em, f, fm, g, gm) \ - { .type = (t), \ - .u = { .s = { _LOC(a, am), _LOC(b, bm), _LOC(c, cm), \ - _LOC(d, dm), _LOC(e, em), _LOC(g, gm), \ - _LOC(f, fm) } } } -#define _PIC(t, h, hm, n) \ - { .type = (t), \ - .u = { .p = { .name = (n), .a = (h), .m = (hm) } } } - -static const struct lcd_segment_map { - char type; - union { - struct pictogram_map { - u8 a,m; - char name[10]; - } p; - struct segment_map { - u8 a,m; - } s[7]; - } u; -} lcdMap[] = { -#include "yealink.h" -}; - -struct yealink_dev { - struct input_dev *idev; /* input device */ - struct usb_device *udev; /* usb device */ - - /* irq input channel */ - struct yld_ctl_packet *irq_data; - dma_addr_t irq_dma; - struct urb *urb_irq; - - /* control output channel */ - struct yld_ctl_packet *ctl_data; - dma_addr_t ctl_dma; - struct usb_ctrlrequest *ctl_req; - dma_addr_t ctl_req_dma; - struct urb *urb_ctl; - - char phys[64]; /* physical device path */ - - u8 lcdMap[ARRAY_SIZE(lcdMap)]; /* state of LCD, LED ... */ - int key_code; /* last reported key */ - - int stat_ix; - union { - struct yld_status s; - u8 b[sizeof(struct yld_status)]; - } master, copy; -}; - - -/******************************************************************************* - * Yealink lcd interface - ******************************************************************************/ - -/* - * Register a default 7 segment character set - */ -static SEG7_DEFAULT_MAP(map_seg7); - - /* Display a char, - * char '\9' and '\n' are placeholders and do not overwrite the original text. - * A space will always hide an icon. - */ -static int setChar(struct yealink_dev *yld, int el, int chr) -{ - int i, a, m, val; - - if (el >= ARRAY_SIZE(lcdMap)) - return -EINVAL; - - if (chr == '\t' || chr == '\n') - return 0; - - yld->lcdMap[el] = chr; - - if (lcdMap[el].type == '.') { - a = lcdMap[el].u.p.a; - m = lcdMap[el].u.p.m; - if (chr != ' ') - yld->master.b[a] |= m; - else - yld->master.b[a] &= ~m; - return 0; - } - - val = map_to_seg7(&map_seg7, chr); - for (i = 0; i < ARRAY_SIZE(lcdMap[0].u.s); i++) { - m = lcdMap[el].u.s[i].m; - - if (m == 0) - continue; - - a = lcdMap[el].u.s[i].a; - if (val & 1) - yld->master.b[a] |= m; - else - yld->master.b[a] &= ~m; - val = val >> 1; - } - return 0; -}; - -/******************************************************************************* - * Yealink key interface - ******************************************************************************/ - -/* Map device buttons to internal key events. - * - * USB-P1K button layout: - * - * up - * IN OUT - * down - * - * pickup C hangup - * 1 2 3 - * 4 5 6 - * 7 8 9 - * * 0 # - * - * The "up" and "down" keys, are symbolised by arrows on the button. - * The "pickup" and "hangup" keys are symbolised by a green and red phone - * on the button. - */ -static int map_p1k_to_key(int scancode) -{ - switch(scancode) { /* phone key: */ - case 0x23: return KEY_LEFT; /* IN */ - case 0x33: return KEY_UP; /* up */ - case 0x04: return KEY_RIGHT; /* OUT */ - case 0x24: return KEY_DOWN; /* down */ - case 0x03: return KEY_ENTER; /* pickup */ - case 0x14: return KEY_BACKSPACE; /* C */ - case 0x13: return KEY_ESC; /* hangup */ - case 0x00: return KEY_1; /* 1 */ - case 0x01: return KEY_2; /* 2 */ - case 0x02: return KEY_3; /* 3 */ - case 0x10: return KEY_4; /* 4 */ - case 0x11: return KEY_5; /* 5 */ - case 0x12: return KEY_6; /* 6 */ - case 0x20: return KEY_7; /* 7 */ - case 0x21: return KEY_8; /* 8 */ - case 0x22: return KEY_9; /* 9 */ - case 0x30: return KEY_KPASTERISK; /* * */ - case 0x31: return KEY_0; /* 0 */ - case 0x32: return KEY_LEFTSHIFT | - KEY_3 << 8; /* # */ - } - return -EINVAL; -} - -/* Completes a request by converting the data into events for the - * input subsystem. - * - * The key parameter can be cascaded: key2 << 8 | key1 - */ -static void report_key(struct yealink_dev *yld, int key) -{ - struct input_dev *idev = yld->idev; - - if (yld->key_code >= 0) { - /* old key up */ - input_report_key(idev, yld->key_code & 0xff, 0); - if (yld->key_code >> 8) - input_report_key(idev, yld->key_code >> 8, 0); - } - - yld->key_code = key; - if (key >= 0) { - /* new valid key */ - input_report_key(idev, key & 0xff, 1); - if (key >> 8) - input_report_key(idev, key >> 8, 1); - } - input_sync(idev); -} - -/******************************************************************************* - * Yealink usb communication interface - ******************************************************************************/ - -static int yealink_cmd(struct yealink_dev *yld, struct yld_ctl_packet *p) -{ - u8 *buf = (u8 *)p; - int i; - u8 sum = 0; - - for(i=0; i<USB_PKT_LEN-1; i++) - sum -= buf[i]; - p->sum = sum; - return usb_control_msg(yld->udev, - usb_sndctrlpipe(yld->udev, 0), - USB_REQ_SET_CONFIGURATION, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, - 0x200, 3, - p, sizeof(*p), - USB_CTRL_SET_TIMEOUT); -} - -static u8 default_ringtone[] = { - 0xEF, /* volume [0-255] */ - 0xFB, 0x1E, 0x00, 0x0C, /* 1250 [hz], 12/100 [s] */ - 0xFC, 0x18, 0x00, 0x0C, /* 1000 [hz], 12/100 [s] */ - 0xFB, 0x1E, 0x00, 0x0C, - 0xFC, 0x18, 0x00, 0x0C, - 0xFB, 0x1E, 0x00, 0x0C, - 0xFC, 0x18, 0x00, 0x0C, - 0xFB, 0x1E, 0x00, 0x0C, - 0xFC, 0x18, 0x00, 0x0C, - 0xFF, 0xFF, 0x01, 0x90, /* silent, 400/100 [s] */ - 0x00, 0x00 /* end of sequence */ -}; - -static int yealink_set_ringtone(struct yealink_dev *yld, u8 *buf, size_t size) -{ - struct yld_ctl_packet *p = yld->ctl_data; - int ix, len; - - if (size <= 0) - return -EINVAL; - - /* Set the ringtone volume */ - memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data))); - yld->ctl_data->cmd = CMD_RING_VOLUME; - yld->ctl_data->size = 1; - yld->ctl_data->data[0] = buf[0]; - yealink_cmd(yld, p); - - buf++; - size--; - - p->cmd = CMD_RING_NOTE; - ix = 0; - while (size != ix) { - len = size - ix; - if (len > sizeof(p->data)) - len = sizeof(p->data); - p->size = len; - p->offset = cpu_to_be16(ix); - memcpy(p->data, &buf[ix], len); - yealink_cmd(yld, p); - ix += len; - } - return 0; -} - -/* keep stat_master & stat_copy in sync. - */ -static int yealink_do_idle_tasks(struct yealink_dev *yld) -{ - u8 val; - int i, ix, len; - - ix = yld->stat_ix; - - memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data))); - yld->ctl_data->cmd = CMD_KEYPRESS; - yld->ctl_data->size = 1; - yld->ctl_data->sum = 0xff - CMD_KEYPRESS; - - /* If state update pointer wraps do a KEYPRESS first. */ - if (ix >= sizeof(yld->master)) { - yld->stat_ix = 0; - return 0; - } - - /* find update candidates: copy != master */ - do { - val = yld->master.b[ix]; - if (val != yld->copy.b[ix]) - goto send_update; - } while (++ix < sizeof(yld->master)); - - /* nothing todo, wait a bit and poll for a KEYPRESS */ - yld->stat_ix = 0; - /* TODO how can we wait abit. ?? - * msleep_interruptible(1000 / YEALINK_POLLING_FREQUENCY); - */ - return 0; - -send_update: - - /* Setup an appropriate update request */ - yld->copy.b[ix] = val; - yld->ctl_data->data[0] = val; - - switch(ix) { - case offsetof(struct yld_status, led): - yld->ctl_data->cmd = CMD_LED; - yld->ctl_data->sum = -1 - CMD_LED - val; - break; - case offsetof(struct yld_status, dialtone): - yld->ctl_data->cmd = CMD_DIALTONE; - yld->ctl_data->sum = -1 - CMD_DIALTONE - val; - break; - case offsetof(struct yld_status, ringtone): - yld->ctl_data->cmd = CMD_RINGTONE; - yld->ctl_data->sum = -1 - CMD_RINGTONE - val; - break; - case offsetof(struct yld_status, keynum): - val--; - val &= 0x1f; - yld->ctl_data->cmd = CMD_SCANCODE; - yld->ctl_data->offset = cpu_to_be16(val); - yld->ctl_data->data[0] = 0; - yld->ctl_data->sum = -1 - CMD_SCANCODE - val; - break; - default: - len = sizeof(yld->master.s.lcd) - ix; - if (len > sizeof(yld->ctl_data->data)) - len = sizeof(yld->ctl_data->data); - - /* Combine up to <len> consecutive LCD bytes in a singe request - */ - yld->ctl_data->cmd = CMD_LCD; - yld->ctl_data->offset = cpu_to_be16(ix); - yld->ctl_data->size = len; - yld->ctl_data->sum = -CMD_LCD - ix - val - len; - for(i=1; i<len; i++) { - ix++; - val = yld->master.b[ix]; - yld->copy.b[ix] = val; - yld->ctl_data->data[i] = val; - yld->ctl_data->sum -= val; - } - } - yld->stat_ix = ix + 1; - return 1; -} - -/* Decide on how to handle responses - * - * The state transition diagram is somethhing like: - * - * syncState<--+ - * | | - * | idle - * \|/ | - * init --ok--> waitForKey --ok--> getKey - * ^ ^ | - * | +-------ok-------+ - * error,start - * - */ -static void urb_irq_callback(struct urb *urb) -{ - struct yealink_dev *yld = urb->context; - int ret; - - if (urb->status) - err("%s - urb status %d", __FUNCTION__, urb->status); - - switch (yld->irq_data->cmd) { - case CMD_KEYPRESS: - - yld->master.s.keynum = yld->irq_data->data[0]; - break; - - case CMD_SCANCODE: - dbg("get scancode %x", yld->irq_data->data[0]); - - report_key(yld, map_p1k_to_key(yld->irq_data->data[0])); - break; - - default: - err("unexpected response %x", yld->irq_data->cmd); - } - - yealink_do_idle_tasks(yld); - - ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC); - if (ret) - err("%s - usb_submit_urb failed %d", __FUNCTION__, ret); -} - -static void urb_ctl_callback(struct urb *urb) -{ - struct yealink_dev *yld = urb->context; - int ret; - - if (urb->status) - err("%s - urb status %d", __FUNCTION__, urb->status); - - switch (yld->ctl_data->cmd) { - case CMD_KEYPRESS: - case CMD_SCANCODE: - /* ask for a response */ - ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC); - break; - default: - /* send new command */ - yealink_do_idle_tasks(yld); - ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC); - } - - if (ret) - err("%s - usb_submit_urb failed %d", __FUNCTION__, ret); -} - -/******************************************************************************* - * input event interface - ******************************************************************************/ - -/* TODO should we issue a ringtone on a SND_BELL event? -static int input_ev(struct input_dev *dev, unsigned int type, - unsigned int code, int value) -{ - - if (type != EV_SND) - return -EINVAL; - - switch (code) { - case SND_BELL: - case SND_TONE: - break; - default: - return -EINVAL; - } - - return 0; -} -*/ - -static int input_open(struct input_dev *dev) -{ - struct yealink_dev *yld = input_get_drvdata(dev); - int i, ret; - - dbg("%s", __FUNCTION__); - - /* force updates to device */ - for (i = 0; i<sizeof(yld->master); i++) - yld->copy.b[i] = ~yld->master.b[i]; - yld->key_code = -1; /* no keys pressed */ - - yealink_set_ringtone(yld, default_ringtone, sizeof(default_ringtone)); - - /* issue INIT */ - memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data))); - yld->ctl_data->cmd = CMD_INIT; - yld->ctl_data->size = 10; - yld->ctl_data->sum = 0x100-CMD_INIT-10; - if ((ret = usb_submit_urb(yld->urb_ctl, GFP_KERNEL)) != 0) { - dbg("%s - usb_submit_urb failed with result %d", - __FUNCTION__, ret); - return ret; - } - return 0; -} - -static void input_close(struct input_dev *dev) -{ - struct yealink_dev *yld = input_get_drvdata(dev); - - usb_kill_urb(yld->urb_ctl); - usb_kill_urb(yld->urb_irq); -} - -/******************************************************************************* - * sysfs interface - ******************************************************************************/ - -static DECLARE_RWSEM(sysfs_rwsema); - -/* Interface to the 7-segments translation table aka. char set. - */ -static ssize_t show_map(struct device *dev, struct device_attribute *attr, - char *buf) -{ - memcpy(buf, &map_seg7, sizeof(map_seg7)); - return sizeof(map_seg7); -} - -static ssize_t store_map(struct device *dev, struct device_attribute *attr, - const char *buf, size_t cnt) -{ - if (cnt != sizeof(map_seg7)) - return -EINVAL; - memcpy(&map_seg7, buf, sizeof(map_seg7)); - return sizeof(map_seg7); -} - -/* Interface to the LCD. - */ - -/* Reading /sys/../lineX will return the format string with its settings: - * - * Example: - * cat ./line3 - * 888888888888 - * Linux Rocks! - */ -static ssize_t show_line(struct device *dev, char *buf, int a, int b) -{ - struct yealink_dev *yld; - int i; - - down_read(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_read(&sysfs_rwsema); - return -ENODEV; - } - - for (i = a; i < b; i++) - *buf++ = lcdMap[i].type; - *buf++ = '\n'; - for (i = a; i < b; i++) - *buf++ = yld->lcdMap[i]; - *buf++ = '\n'; - *buf = 0; - - up_read(&sysfs_rwsema); - return 3 + ((b - a) << 1); -} - -static ssize_t show_line1(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return show_line(dev, buf, LCD_LINE1_OFFSET, LCD_LINE2_OFFSET); -} - -static ssize_t show_line2(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return show_line(dev, buf, LCD_LINE2_OFFSET, LCD_LINE3_OFFSET); -} - -static ssize_t show_line3(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return show_line(dev, buf, LCD_LINE3_OFFSET, LCD_LINE4_OFFSET); -} - -/* Writing to /sys/../lineX will set the coresponding LCD line. - * - Excess characters are ignored. - * - If less characters are written than allowed, the remaining digits are - * unchanged. - * - The '\n' or '\t' char is a placeholder, it does not overwrite the - * original content. - */ -static ssize_t store_line(struct device *dev, const char *buf, size_t count, - int el, size_t len) -{ - struct yealink_dev *yld; - int i; - - down_write(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_write(&sysfs_rwsema); - return -ENODEV; - } - - if (len > count) - len = count; - for (i = 0; i < len; i++) - setChar(yld, el++, buf[i]); - - up_write(&sysfs_rwsema); - return count; -} - -static ssize_t store_line1(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - return store_line(dev, buf, count, LCD_LINE1_OFFSET, LCD_LINE1_SIZE); -} - -static ssize_t store_line2(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - return store_line(dev, buf, count, LCD_LINE2_OFFSET, LCD_LINE2_SIZE); -} - -static ssize_t store_line3(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - return store_line(dev, buf, count, LCD_LINE3_OFFSET, LCD_LINE3_SIZE); -} - -/* Interface to visible and audible "icons", these include: - * pictures on the LCD, the LED, and the dialtone signal. - */ - -/* Get a list of "switchable elements" with their current state. */ -static ssize_t get_icons(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct yealink_dev *yld; - int i, ret = 1; - - down_read(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_read(&sysfs_rwsema); - return -ENODEV; - } - - for (i = 0; i < ARRAY_SIZE(lcdMap); i++) { - if (lcdMap[i].type != '.') - continue; - ret += sprintf(&buf[ret], "%s %s\n", - yld->lcdMap[i] == ' ' ? " " : "on", - lcdMap[i].u.p.name); - } - up_read(&sysfs_rwsema); - return ret; -} - -/* Change the visibility of a particular element. */ -static ssize_t set_icon(struct device *dev, const char *buf, size_t count, - int chr) -{ - struct yealink_dev *yld; - int i; - - down_write(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_write(&sysfs_rwsema); - return -ENODEV; - } - - for (i = 0; i < ARRAY_SIZE(lcdMap); i++) { - if (lcdMap[i].type != '.') - continue; - if (strncmp(buf, lcdMap[i].u.p.name, count) == 0) { - setChar(yld, i, chr); - break; - } - } - - up_write(&sysfs_rwsema); - return count; -} - -static ssize_t show_icon(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - return set_icon(dev, buf, count, buf[0]); -} - -static ssize_t hide_icon(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - return set_icon(dev, buf, count, ' '); -} - -/* Upload a ringtone to the device. - */ - -/* Stores raw ringtone data in the phone */ -static ssize_t store_ringtone(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct yealink_dev *yld; - - down_write(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_write(&sysfs_rwsema); - return -ENODEV; - } - - /* TODO locking with async usb control interface??? */ - yealink_set_ringtone(yld, (char *)buf, count); - up_write(&sysfs_rwsema); - return count; -} - -#define _M444 S_IRUGO -#define _M664 S_IRUGO|S_IWUSR|S_IWGRP -#define _M220 S_IWUSR|S_IWGRP - -static DEVICE_ATTR(map_seg7 , _M664, show_map , store_map ); -static DEVICE_ATTR(line1 , _M664, show_line1 , store_line1 ); -static DEVICE_ATTR(line2 , _M664, show_line2 , store_line2 ); -static DEVICE_ATTR(line3 , _M664, show_line3 , store_line3 ); -static DEVICE_ATTR(get_icons , _M444, get_icons , NULL ); -static DEVICE_ATTR(show_icon , _M220, NULL , show_icon ); -static DEVICE_ATTR(hide_icon , _M220, NULL , hide_icon ); -static DEVICE_ATTR(ringtone , _M220, NULL , store_ringtone); - -static struct attribute *yld_attributes[] = { - &dev_attr_line1.attr, - &dev_attr_line2.attr, - &dev_attr_line3.attr, - &dev_attr_get_icons.attr, - &dev_attr_show_icon.attr, - &dev_attr_hide_icon.attr, - &dev_attr_map_seg7.attr, - &dev_attr_ringtone.attr, - NULL -}; - -static struct attribute_group yld_attr_group = { - .attrs = yld_attributes -}; - -/******************************************************************************* - * Linux interface and usb initialisation - ******************************************************************************/ - -struct driver_info { - char *name; -}; - -static const struct driver_info info_P1K = { - .name = "Yealink usb-p1k", -}; - -static const struct usb_device_id usb_table [] = { - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | - USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x6993, - .idProduct = 0xb001, - .bInterfaceClass = USB_CLASS_HID, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .driver_info = (kernel_ulong_t)&info_P1K - }, - { } -}; - -static int usb_cleanup(struct yealink_dev *yld, int err) -{ - if (yld == NULL) - return err; - - usb_kill_urb(yld->urb_irq); /* parameter validation in core/urb */ - usb_kill_urb(yld->urb_ctl); /* parameter validation in core/urb */ - - if (yld->idev) { - if (err) - input_free_device(yld->idev); - else - input_unregister_device(yld->idev); - } - if (yld->ctl_req) - usb_buffer_free(yld->udev, sizeof(*(yld->ctl_req)), - yld->ctl_req, yld->ctl_req_dma); - if (yld->ctl_data) - usb_buffer_free(yld->udev, USB_PKT_LEN, - yld->ctl_data, yld->ctl_dma); - if (yld->irq_data) - usb_buffer_free(yld->udev, USB_PKT_LEN, - yld->irq_data, yld->irq_dma); - - usb_free_urb(yld->urb_irq); /* parameter validation in core/urb */ - usb_free_urb(yld->urb_ctl); /* parameter validation in core/urb */ - kfree(yld); - return err; -} - -static void usb_disconnect(struct usb_interface *intf) -{ - struct yealink_dev *yld; - - down_write(&sysfs_rwsema); - yld = usb_get_intfdata(intf); - sysfs_remove_group(&intf->dev.kobj, &yld_attr_group); - usb_set_intfdata(intf, NULL); - up_write(&sysfs_rwsema); - - usb_cleanup(yld, 0); -} - -static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev (intf); - struct driver_info *nfo = (struct driver_info *)id->driver_info; - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct yealink_dev *yld; - struct input_dev *input_dev; - int ret, pipe, i; - - interface = intf->cur_altsetting; - endpoint = &interface->endpoint[0].desc; - if (!usb_endpoint_is_int_in(endpoint)) - return -ENODEV; - - yld = kzalloc(sizeof(struct yealink_dev), GFP_KERNEL); - if (!yld) - return -ENOMEM; - - yld->udev = udev; - - yld->idev = input_dev = input_allocate_device(); - if (!input_dev) - return usb_cleanup(yld, -ENOMEM); - - /* allocate usb buffers */ - yld->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN, - GFP_ATOMIC, &yld->irq_dma); - if (yld->irq_data == NULL) - return usb_cleanup(yld, -ENOMEM); - - yld->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN, - GFP_ATOMIC, &yld->ctl_dma); - if (!yld->ctl_data) - return usb_cleanup(yld, -ENOMEM); - - yld->ctl_req = usb_buffer_alloc(udev, sizeof(*(yld->ctl_req)), - GFP_ATOMIC, &yld->ctl_req_dma); - if (yld->ctl_req == NULL) - return usb_cleanup(yld, -ENOMEM); - - /* allocate urb structures */ - yld->urb_irq = usb_alloc_urb(0, GFP_KERNEL); - if (yld->urb_irq == NULL) - return usb_cleanup(yld, -ENOMEM); - - yld->urb_ctl = usb_alloc_urb(0, GFP_KERNEL); - if (yld->urb_ctl == NULL) - return usb_cleanup(yld, -ENOMEM); - - /* get a handle to the interrupt data pipe */ - pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); - ret = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); - if (ret != USB_PKT_LEN) - err("invalid payload size %d, expected %zd", ret, USB_PKT_LEN); - - /* initialise irq urb */ - usb_fill_int_urb(yld->urb_irq, udev, pipe, yld->irq_data, - USB_PKT_LEN, - urb_irq_callback, - yld, endpoint->bInterval); - yld->urb_irq->transfer_dma = yld->irq_dma; - yld->urb_irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - yld->urb_irq->dev = udev; - - /* initialise ctl urb */ - yld->ctl_req->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | - USB_DIR_OUT; - yld->ctl_req->bRequest = USB_REQ_SET_CONFIGURATION; - yld->ctl_req->wValue = cpu_to_le16(0x200); - yld->ctl_req->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber); - yld->ctl_req->wLength = cpu_to_le16(USB_PKT_LEN); - - usb_fill_control_urb(yld->urb_ctl, udev, usb_sndctrlpipe(udev, 0), - (void *)yld->ctl_req, yld->ctl_data, USB_PKT_LEN, - urb_ctl_callback, yld); - yld->urb_ctl->setup_dma = yld->ctl_req_dma; - yld->urb_ctl->transfer_dma = yld->ctl_dma; - yld->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP | - URB_NO_TRANSFER_DMA_MAP; - yld->urb_ctl->dev = udev; - - /* find out the physical bus location */ - usb_make_path(udev, yld->phys, sizeof(yld->phys)); - strlcat(yld->phys, "/input0", sizeof(yld->phys)); - - /* register settings for the input device */ - input_dev->name = nfo->name; - input_dev->phys = yld->phys; - usb_to_input_id(udev, &input_dev->id); - input_dev->dev.parent = &intf->dev; - - input_set_drvdata(input_dev, yld); - - input_dev->open = input_open; - input_dev->close = input_close; - /* input_dev->event = input_ev; TODO */ - - /* register available key events */ - input_dev->evbit[0] = BIT(EV_KEY); - for (i = 0; i < 256; i++) { - int k = map_p1k_to_key(i); - if (k >= 0) { - set_bit(k & 0xff, input_dev->keybit); - if (k >> 8) - set_bit(k >> 8, input_dev->keybit); - } - } - - ret = input_register_device(yld->idev); - if (ret) - return usb_cleanup(yld, ret); - - usb_set_intfdata(intf, yld); - - /* clear visible elements */ - for (i = 0; i < ARRAY_SIZE(lcdMap); i++) - setChar(yld, i, ' '); - - /* display driver version on LCD line 3 */ - store_line3(&intf->dev, NULL, - DRIVER_VERSION, sizeof(DRIVER_VERSION)); - - /* Register sysfs hooks (don't care about failure) */ - ret = sysfs_create_group(&intf->dev.kobj, &yld_attr_group); - return 0; -} - -static struct usb_driver yealink_driver = { - .name = "yealink", - .probe = usb_probe, - .disconnect = usb_disconnect, - .id_table = usb_table, -}; - -static int __init yealink_dev_init(void) -{ - int ret = usb_register(&yealink_driver); - if (ret == 0) - info(DRIVER_DESC ":" DRIVER_VERSION); - return ret; -} - -static void __exit yealink_dev_exit(void) -{ - usb_deregister(&yealink_driver); -} - -module_init(yealink_dev_init); -module_exit(yealink_dev_exit); - -MODULE_DEVICE_TABLE (usb, usb_table); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/input/yealink.h b/drivers/usb/input/yealink.h deleted file mode 100644 index 48af0be9cbd..00000000000 --- a/drivers/usb/input/yealink.h +++ /dev/null @@ -1,220 +0,0 @@ -/* - * drivers/usb/input/yealink.h - * - * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com> - * - * - * 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 - */ -#ifndef INPUT_YEALINK_H -#define INPUT_YEALINK_H - -/* Using the control channel on interface 3 various aspects of the phone - * can be controlled like LCD, LED, dialtone and the ringtone. - */ - -struct yld_ctl_packet { - u8 cmd; /* command code, see below */ - u8 size; /* 1-11, size of used data bytes. */ - u16 offset; /* internal packet offset */ - u8 data[11]; - s8 sum; /* negative sum of 15 preceding bytes */ -} __attribute__ ((packed)); - -#define USB_PKT_LEN sizeof(struct yld_ctl_packet) - -/* The following yld_ctl_packet's are available: */ - -/* Init registers - * - * cmd 0x8e - * size 10 - * offset 0 - * data 0,0,0,0.... - */ -#define CMD_INIT 0x8e - -/* Request key scan - * - * cmd 0x80 - * size 1 - * offset 0 - * data[0] on return returns the key number, if it changes there's a new - * key pressed. - */ -#define CMD_KEYPRESS 0x80 - -/* Request scancode - * - * cmd 0x81 - * size 1 - * offset key number [0-1f] - * data[0] on return returns the scancode - */ -#define CMD_SCANCODE 0x81 - -/* Set LCD - * - * cmd 0x04 - * size 1-11 - * offset 0-23 - * data segment bits - */ -#define CMD_LCD 0x04 - -/* Set led - * - * cmd 0x05 - * size 1 - * offset 0 - * data[0] 0 OFF / 1 ON - */ -#define CMD_LED 0x05 - -/* Set ringtone volume - * - * cmd 0x11 - * size 1 - * offset 0 - * data[0] 0-0xff volume - */ -#define CMD_RING_VOLUME 0x11 - -/* Set ringtone notes - * - * cmd 0x02 - * size 1-11 - * offset 0-> - * data binary representation LE16(-freq), LE16(duration) .... - */ -#define CMD_RING_NOTE 0x02 - -/* Sound ringtone via the speaker on the back - * - * cmd 0x03 - * size 1 - * offset 0 - * data[0] 0 OFF / 0x24 ON - */ -#define CMD_RINGTONE 0x03 - -/* Sound dial tone via the ear speaker - * - * cmd 0x09 - * size 1 - * offset 0 - * data[0] 0 OFF / 1 ON - */ -#define CMD_DIALTONE 0x09 - -#endif /* INPUT_YEALINK_H */ - - -#if defined(_SEG) && defined(_PIC) -/* This table maps the LCD segments onto individual bit positions in the - * yld_status struct. - */ - -/* LCD, each segment must be driven seperately. - * - * Layout: - * - * |[] [][] [][] [][] in |[][] - * |[] M [][] D [][] : [][] out |[][] - * store - * - * NEW REP SU MO TU WE TH FR SA - * - * [] [] [] [] [] [] [] [] [] [] [] [] - * [] [] [] [] [] [] [] [] [] [] [] [] - */ - -/* Line 1 - * Format : 18.e8.M8.88...188 - * Icon names : M D : IN OUT STORE - */ -#define LCD_LINE1_OFFSET 0 -#define LCD_LINE1_SIZE 17 - -/* Note: first g then f => ! ! */ -/* _SEG( type a b c d e g f ) */ - _SEG('1', 0,0 , 22,2 , 22,2 , 0,0 , 0,0 , 0,0 , 0,0 ), - _SEG('8', 20,1 , 20,2 , 20,4 , 20,8 , 21,4 , 21,2 , 21,1 ), - _PIC('.', 22,1 , "M" ), - _SEG('e', 18,1 , 18,2 , 18,4 , 18,1 , 19,2 , 18,1 , 19,1 ), - _SEG('8', 16,1 , 16,2 , 16,4 , 16,8 , 17,4 , 17,2 , 17,1 ), - _PIC('.', 15,8 , "D" ), - _SEG('M', 14,1 , 14,2 , 14,4 , 14,1 , 15,4 , 15,2 , 15,1 ), - _SEG('8', 12,1 , 12,2 , 12,4 , 12,8 , 13,4 , 13,2 , 13,1 ), - _PIC('.', 11,8 , ":" ), - _SEG('8', 10,1 , 10,2 , 10,4 , 10,8 , 11,4 , 11,2 , 11,1 ), - _SEG('8', 8,1 , 8,2 , 8,4 , 8,8 , 9,4 , 9,2 , 9,1 ), - _PIC('.', 7,1 , "IN" ), - _PIC('.', 7,2 , "OUT" ), - _PIC('.', 7,4 , "STORE" ), - _SEG('1', 0,0 , 5,1 , 5,1 , 0,0 , 0,0 , 0,0 , 0,0 ), - _SEG('8', 4,1 , 4,2 , 4,4 , 4,8 , 5,8 , 5,4 , 5,2 ), - _SEG('8', 2,1 , 2,2 , 2,4 , 2,8 , 3,4 , 3,2 , 3,1 ), - -/* Line 2 - * Format : ......... - * Pict. name : NEW REP SU MO TU WE TH FR SA - */ -#define LCD_LINE2_OFFSET LCD_LINE1_OFFSET + LCD_LINE1_SIZE -#define LCD_LINE2_SIZE 9 - - _PIC('.', 23,2 , "NEW" ), - _PIC('.', 23,4 , "REP" ), - _PIC('.', 1,8 , "SU" ), - _PIC('.', 1,4 , "MO" ), - _PIC('.', 1,2 , "TU" ), - _PIC('.', 1,1 , "WE" ), - _PIC('.', 0,1 , "TH" ), - _PIC('.', 0,2 , "FR" ), - _PIC('.', 0,4 , "SA" ), - -/* Line 3 - * Format : 888888888888 - */ -#define LCD_LINE3_OFFSET LCD_LINE2_OFFSET + LCD_LINE2_SIZE -#define LCD_LINE3_SIZE 12 - - _SEG('8', 22,16, 22,32, 22,64, 22,128, 23,128, 23,64, 23,32 ), - _SEG('8', 20,16, 20,32, 20,64, 20,128, 21,128, 21,64, 21,32 ), - _SEG('8', 18,16, 18,32, 18,64, 18,128, 19,128, 19,64, 19,32 ), - _SEG('8', 16,16, 16,32, 16,64, 16,128, 17,128, 17,64, 17,32 ), - _SEG('8', 14,16, 14,32, 14,64, 14,128, 15,128, 15,64, 15,32 ), - _SEG('8', 12,16, 12,32, 12,64, 12,128, 13,128, 13,64, 13,32 ), - _SEG('8', 10,16, 10,32, 10,64, 10,128, 11,128, 11,64, 11,32 ), - _SEG('8', 8,16, 8,32, 8,64, 8,128, 9,128, 9,64, 9,32 ), - _SEG('8', 6,16, 6,32, 6,64, 6,128, 7,128, 7,64, 7,32 ), - _SEG('8', 4,16, 4,32, 4,64, 4,128, 5,128, 5,64, 5,32 ), - _SEG('8', 2,16, 2,32, 2,64, 2,128, 3,128, 3,64, 3,32 ), - _SEG('8', 0,16, 0,32, 0,64, 0,128, 1,128, 1,64, 1,32 ), - -/* Line 4 - * - * The LED, DIALTONE and RINGTONE are implemented as icons and use the same - * sysfs interface. - */ -#define LCD_LINE4_OFFSET LCD_LINE3_OFFSET + LCD_LINE3_SIZE - - _PIC('.', offsetof(struct yld_status, led) , 0x01, "LED" ), - _PIC('.', offsetof(struct yld_status, dialtone) , 0x01, "DIALTONE" ), - _PIC('.', offsetof(struct yld_status, ringtone) , 0x24, "RINGTONE" ), - -#undef _SEG -#undef _PIC -#endif /* _SEG && _PIC */ |