diff options
Diffstat (limited to 'drivers/usb/input')
34 files changed, 0 insertions, 18719 deletions
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig deleted file mode 100644 index 661af7aa623..00000000000 --- a/drivers/usb/input/Kconfig +++ /dev/null @@ -1,356 +0,0 @@ -# -# USB Input driver configuration -# -comment "USB Input Devices" - depends on USB - -config USB_HID - tristate "USB Human Interface Device (full HID) support" - depends on USB - ---help--- - Say Y here if you want full HID support to connect keyboards, - mice, joysticks, graphic tablets, or any other HID based devices - to your computer via USB. You also need to select HID Input layer - support (below) if you want to use keyboards, mice, joysticks and - the like ... as well as Uninterruptible Power Supply (UPS) and - monitor control devices. - - You can't use this driver and the HIDBP (Boot Protocol) keyboard - and mouse drivers at the same time. More information is available: - <file:Documentation/input/input.txt>. - - If unsure, say Y. - - To compile this driver as a module, choose M here: the - module will be called usbhid. - -comment "Input core support is needed for USB HID input layer or HIDBP support" - depends on USB_HID && INPUT=n - -config USB_HIDINPUT - bool "HID input layer support" - default y - depends on INPUT && USB_HID - help - Say Y here if you want to use a USB keyboard, mouse or joystick, - or any other HID input device. - - If unsure, say Y. - -config USB_HIDINPUT_POWERBOOK - bool "Enable support for iBook/PowerBook special keys" - default n - depends on USB_HIDINPUT - help - Say Y here if you want support for the special keys (Fn, Numlock) on - Apple iBooks and PowerBooks. - - If unsure, say N. - -config HID_FF - bool "Force feedback support (EXPERIMENTAL)" - depends on USB_HIDINPUT && EXPERIMENTAL - help - Say Y here is you want force feedback support for a few HID devices. - See below for a list of supported devices. - - See <file:Documentation/input/ff.txt> for a description of the force - feedback API. - - If unsure, say N. - -config HID_PID - bool "PID device support" - depends on HID_FF - help - Say Y here if you have a PID-compliant device and wish to enable force - feedback for it. Microsoft Sidewinder Force Feedback 2 is one of such - devices. - -config LOGITECH_FF - bool "Logitech WingMan *3D support" - depends on HID_FF - select INPUT_FF_MEMLESS if USB_HID - help - Say Y here if you have one of these devices: - - Logitech WingMan Cordless RumblePad - - Logitech WingMan Force 3D - and if you want to enable force feedback for them. - Note: if you say N here, this device will still be supported, but without - force feedback. - -config THRUSTMASTER_FF - bool "ThrustMaster FireStorm Dual Power 2 support (EXPERIMENTAL)" - depends on HID_FF && EXPERIMENTAL - select INPUT_FF_MEMLESS if USB_HID - help - Say Y here if you have a THRUSTMASTER FireStore Dual Power 2, - and want to enable force feedback support for it. - Note: if you say N here, this device will still be supported, but without - force feedback. - -config ZEROPLUS_FF - bool "Zeroplus based game controller support" - depends on HID_FF - select INPUT_FF_MEMLESS if USB_HID - help - Say Y here if you have a Zeroplus based game controller and want to - enable force feedback for it. - -config USB_HIDDEV - bool "/dev/hiddev raw HID device support" - depends on USB_HID - help - Say Y here if you want to support HID devices (from the USB - specification standpoint) that aren't strictly user interface - devices, like monitor controls and Uninterruptable Power Supplies. - - This module supports these devices separately using a separate - event interface on /dev/usb/hiddevX (char 180:96 to 180:111). - - If unsure, say Y. - -menu "USB HID Boot Protocol drivers" - depends on USB!=n && USB_HID!=y - -config USB_KBD - tristate "USB HIDBP Keyboard (simple Boot) support" - depends on USB && INPUT - ---help--- - Say Y here only if you are absolutely sure that you don't want - to use the generic HID driver for your USB keyboard and prefer - to use the keyboard in its limited Boot Protocol mode instead. - - This is almost certainly not what you want. This is mostly - useful for embedded applications or simple keyboards. - - To compile this driver as a module, choose M here: the - module will be called usbkbd. - - If even remotely unsure, say N. - -config USB_MOUSE - tristate "USB HIDBP Mouse (simple Boot) support" - depends on USB && INPUT - ---help--- - Say Y here only if you are absolutely sure that you don't want - to use the generic HID driver for your USB mouse and prefer - to use the mouse in its limited Boot Protocol mode instead. - - This is almost certainly not what you want. This is mostly - useful for embedded applications or simple mice. - - To compile this driver as a module, choose M here: the - module will be called usbmouse. - - If even remotely unsure, say N. - -endmenu - -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. diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile deleted file mode 100644 index d946d5213b3..00000000000 --- a/drivers/usb/input/Makefile +++ /dev/null @@ -1,54 +0,0 @@ -# -# Makefile for the USB input drivers -# - -# Multipart objects. -wacom-objs := wacom_wac.o wacom_sys.o -usbhid-objs := hid-core.o - -# Optional parts of multipart objects. - -ifeq ($(CONFIG_USB_HIDDEV),y) - usbhid-objs += hiddev.o -endif -ifeq ($(CONFIG_USB_HIDINPUT),y) - usbhid-objs += hid-input.o -endif -ifeq ($(CONFIG_HID_PID),y) - usbhid-objs += hid-pidff.o -endif -ifeq ($(CONFIG_LOGITECH_FF),y) - usbhid-objs += hid-lgff.o -endif -ifeq ($(CONFIG_THRUSTMASTER_FF),y) - usbhid-objs += hid-tmff.o -endif -ifeq ($(CONFIG_ZEROPLUS_FF),y) - usbhid-objs += hid-zpff.o -endif -ifeq ($(CONFIG_HID_FF),y) - usbhid-objs += hid-ff.o -endif - -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_HID) += usbhid.o -obj-$(CONFIG_USB_KBD) += usbkbd.o -obj-$(CONFIG_USB_KBTAB) += kbtab.o -obj-$(CONFIG_USB_KEYSPAN_REMOTE) += keyspan_remote.o -obj-$(CONFIG_USB_MOUSE) += usbmouse.o -obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o -obj-$(CONFIG_USB_ITMTOUCH) += itmtouch.o -obj-$(CONFIG_USB_EGALAX) += touchkitusb.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 - -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 909138e5aa0..00000000000 --- a/drivers/usb/input/acecad.c +++ /dev/null @@ -1,279 +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 = dev->private; - - 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 = dev->private; - - 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; - - 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) - goto fail1; - - acecad->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &acecad->data_dma); - if (!acecad->data) - goto fail1; - - acecad->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!acecad->irq) - 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->cdev.dev = &intf->dev; - input_dev->private = 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; - - input_register_device(acecad->input); - - 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 -ENOMEM; -} - -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 9f52429ce65..00000000000 --- a/drivers/usb/input/aiptek.c +++ /dev/null @@ -1,2235 +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 <linux/sched.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 = inputdev->private; - - 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 = inputdev->private; - - 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 - }; - - /* 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->cdev.dev = &intf->dev; - inputdev->private = 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 - */ - input_register_device(aiptek->inputdev); - - /* 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 -ENOMEM; -} - -/* Forward declaration */ -static void aiptek_disconnect(struct usb_interface *intf); - -static struct usb_driver aiptek_driver = { - .name = "aiptek", - .probe = aiptek_probe, - .disconnect = aiptek_disconnect, - .id_table = aiptek_ids, -}; - -/*********************************************************************** - * 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 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 c77291d3d06..00000000000 --- a/drivers/usb/input/appletouch.c +++ /dev/null @@ -1,705 +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->private; - - 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->private; - - 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, retval = -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) { - retval = -ENOMEM; - goto err_free_devs; - } - - dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL, - &dev->urb->transfer_dma); - if (!dev->data) { - retval = -ENOMEM; - 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->cdev.dev = &iface->dev; - - input_dev->private = 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); - - input_register_device(dev->input); - - /* save our data pointer in this interface device */ - usb_set_intfdata(iface, dev); - - return 0; - - err_free_urb: - usb_free_urb(dev->urb); - err_free_devs: - usb_set_intfdata(iface, NULL); - kfree(dev); - input_free_device(input_dev); - return retval; -} - -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 b724e36f7b9..00000000000 --- a/drivers/usb/input/ati_remote.c +++ /dev/null @@ -1,842 +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 */ - -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"); - -#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 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 = inputdev->private; - - /* 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 = inputdev->private; - - 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) { - /* 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(jiffies, ati_remote->old_jiffies + msecs_to_jiffies(repeat_filter))) { - ati_remote->repeat_count++; - } else { - ati_remote->repeat_count = 0; - } - - ati_remote->old_data[0] = data[1]; - ati_remote->old_data[1] = data[2]; - ati_remote->old_jiffies = jiffies; - - if (ati_remote->repeat_count > 0 && - ati_remote->repeat_count < 5) - 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); - - idev->private = 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->cdev.dev = &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 */ - input_register_device(ati_remote->idev); - - 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 83f1f79db7c..00000000000 --- a/drivers/usb/input/ati_remote2.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - * ati_remote2 - ATI/Philips USB RF remote driver - * - * Copyright (C) 2005 Ville Syrjala <syrjala@sci.fi> - * - * 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.1" - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); -MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>"); -MODULE_LICENSE("GPL"); - -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 = idev->private; - 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 = idev->private; - - 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]; - - if (data[0] > 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 << data[0]) & 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 hw_code, index; - - if (data[0] > 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 == data[0]) - return; - - if (data[1] == 0) - ar2->mode = data[0]; - - hw_code |= data[0] << 8; - } - - if (!((1 << data[0]) & 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; - - idev = input_allocate_device(); - if (!idev) - return -ENOMEM; - - ar2->idev = idev; - idev->private = 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->cdev.dev = &ar2->udev->dev; - - i = input_register_device(idev); - if (i) - input_free_device(idev); - - return i; -} - -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_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; - - 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/hid-core.c b/drivers/usb/input/hid-core.c deleted file mode 100644 index 0811c39bd14..00000000000 --- a/drivers/usb/input/hid-core.c +++ /dev/null @@ -1,2289 +0,0 @@ -/* - * USB HID support for Linux - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> - * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc - */ - -/* - * 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 <linux/module.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/list.h> -#include <linux/mm.h> -#include <linux/smp_lock.h> -#include <linux/spinlock.h> -#include <asm/unaligned.h> -#include <asm/byteorder.h> -#include <linux/input.h> -#include <linux/wait.h> - -#undef DEBUG -#undef DEBUG_DATA - -#include <linux/usb.h> - -#include "hid.h" -#include <linux/hiddev.h> - -/* - * Version Information - */ - -#define DRIVER_VERSION "v2.6" -#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik" -#define DRIVER_DESC "USB HID core driver" -#define DRIVER_LICENSE "GPL" - -static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick", - "Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"}; -/* - * Module parameters. - */ - -static unsigned int hid_mousepoll_interval; -module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); -MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); - -/* - * Register a new report for a device. - */ - -static struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id) -{ - struct hid_report_enum *report_enum = device->report_enum + type; - struct hid_report *report; - - if (report_enum->report_id_hash[id]) - return report_enum->report_id_hash[id]; - - if (!(report = kzalloc(sizeof(struct hid_report), GFP_KERNEL))) - return NULL; - - if (id != 0) - report_enum->numbered = 1; - - report->id = id; - report->type = type; - report->size = 0; - report->device = device; - report_enum->report_id_hash[id] = report; - - list_add_tail(&report->list, &report_enum->report_list); - - return report; -} - -/* - * Register a new field for this report. - */ - -static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values) -{ - struct hid_field *field; - - if (report->maxfield == HID_MAX_FIELDS) { - dbg("too many fields in report"); - return NULL; - } - - if (!(field = kzalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage) - + values * sizeof(unsigned), GFP_KERNEL))) return NULL; - - field->index = report->maxfield++; - report->field[field->index] = field; - field->usage = (struct hid_usage *)(field + 1); - field->value = (unsigned *)(field->usage + usages); - field->report = report; - - return field; -} - -/* - * Open a collection. The type/usage is pushed on the stack. - */ - -static int open_collection(struct hid_parser *parser, unsigned type) -{ - struct hid_collection *collection; - unsigned usage; - - usage = parser->local.usage[0]; - - if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) { - dbg("collection stack overflow"); - return -1; - } - - if (parser->device->maxcollection == parser->device->collection_size) { - collection = kmalloc(sizeof(struct hid_collection) * - parser->device->collection_size * 2, GFP_KERNEL); - if (collection == NULL) { - dbg("failed to reallocate collection array"); - return -1; - } - memcpy(collection, parser->device->collection, - sizeof(struct hid_collection) * - parser->device->collection_size); - memset(collection + parser->device->collection_size, 0, - sizeof(struct hid_collection) * - parser->device->collection_size); - kfree(parser->device->collection); - parser->device->collection = collection; - parser->device->collection_size *= 2; - } - - parser->collection_stack[parser->collection_stack_ptr++] = - parser->device->maxcollection; - - collection = parser->device->collection + - parser->device->maxcollection++; - collection->type = type; - collection->usage = usage; - collection->level = parser->collection_stack_ptr - 1; - - if (type == HID_COLLECTION_APPLICATION) - parser->device->maxapplication++; - - return 0; -} - -/* - * Close a collection. - */ - -static int close_collection(struct hid_parser *parser) -{ - if (!parser->collection_stack_ptr) { - dbg("collection stack underflow"); - return -1; - } - parser->collection_stack_ptr--; - return 0; -} - -/* - * Climb up the stack, search for the specified collection type - * and return the usage. - */ - -static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type) -{ - int n; - for (n = parser->collection_stack_ptr - 1; n >= 0; n--) - if (parser->device->collection[parser->collection_stack[n]].type == type) - return parser->device->collection[parser->collection_stack[n]].usage; - return 0; /* we know nothing about this usage type */ -} - -/* - * Add a usage to the temporary parser table. - */ - -static int hid_add_usage(struct hid_parser *parser, unsigned usage) -{ - if (parser->local.usage_index >= HID_MAX_USAGES) { - dbg("usage index exceeded"); - return -1; - } - parser->local.usage[parser->local.usage_index] = usage; - parser->local.collection_index[parser->local.usage_index] = - parser->collection_stack_ptr ? - parser->collection_stack[parser->collection_stack_ptr - 1] : 0; - parser->local.usage_index++; - return 0; -} - -/* - * Register a new field for this report. - */ - -static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsigned flags) -{ - struct hid_report *report; - struct hid_field *field; - int usages; - unsigned offset; - int i; - - if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) { - dbg("hid_register_report failed"); - return -1; - } - - if (parser->global.logical_maximum < parser->global.logical_minimum) { - dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum); - return -1; - } - - offset = report->size; - report->size += parser->global.report_size * parser->global.report_count; - - if (!parser->local.usage_index) /* Ignore padding fields */ - return 0; - - usages = max_t(int, parser->local.usage_index, parser->global.report_count); - - if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL) - return 0; - - field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL); - field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL); - field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); - - for (i = 0; i < usages; i++) { - int j = i; - /* Duplicate the last usage we parsed if we have excess values */ - if (i >= parser->local.usage_index) - j = parser->local.usage_index - 1; - field->usage[i].hid = parser->local.usage[j]; - field->usage[i].collection_index = - parser->local.collection_index[j]; - } - - field->maxusage = usages; - field->flags = flags; - field->report_offset = offset; - field->report_type = report_type; - field->report_size = parser->global.report_size; - field->report_count = parser->global.report_count; - field->logical_minimum = parser->global.logical_minimum; - field->logical_maximum = parser->global.logical_maximum; - field->physical_minimum = parser->global.physical_minimum; - field->physical_maximum = parser->global.physical_maximum; - field->unit_exponent = parser->global.unit_exponent; - field->unit = parser->global.unit; - - return 0; -} - -/* - * Read data value from item. - */ - -static u32 item_udata(struct hid_item *item) -{ - switch (item->size) { - case 1: return item->data.u8; - case 2: return item->data.u16; - case 4: return item->data.u32; - } - return 0; -} - -static s32 item_sdata(struct hid_item *item) -{ - switch (item->size) { - case 1: return item->data.s8; - case 2: return item->data.s16; - case 4: return item->data.s32; - } - return 0; -} - -/* - * Process a global item. - */ - -static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) -{ - switch (item->tag) { - - case HID_GLOBAL_ITEM_TAG_PUSH: - - if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) { - dbg("global enviroment stack overflow"); - return -1; - } - - memcpy(parser->global_stack + parser->global_stack_ptr++, - &parser->global, sizeof(struct hid_global)); - return 0; - - case HID_GLOBAL_ITEM_TAG_POP: - - if (!parser->global_stack_ptr) { - dbg("global enviroment stack underflow"); - return -1; - } - - memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr, - sizeof(struct hid_global)); - return 0; - - case HID_GLOBAL_ITEM_TAG_USAGE_PAGE: - parser->global.usage_page = item_udata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM: - parser->global.logical_minimum = item_sdata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM: - if (parser->global.logical_minimum < 0) - parser->global.logical_maximum = item_sdata(item); - else - parser->global.logical_maximum = item_udata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM: - parser->global.physical_minimum = item_sdata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM: - if (parser->global.physical_minimum < 0) - parser->global.physical_maximum = item_sdata(item); - else - parser->global.physical_maximum = item_udata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT: - parser->global.unit_exponent = item_sdata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_UNIT: - parser->global.unit = item_udata(item); - return 0; - - case HID_GLOBAL_ITEM_TAG_REPORT_SIZE: - if ((parser->global.report_size = item_udata(item)) > 32) { - dbg("invalid report_size %d", parser->global.report_size); - return -1; - } - return 0; - - case HID_GLOBAL_ITEM_TAG_REPORT_COUNT: - if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) { - dbg("invalid report_count %d", parser->global.report_count); - return -1; - } - return 0; - - case HID_GLOBAL_ITEM_TAG_REPORT_ID: - if ((parser->global.report_id = item_udata(item)) == 0) { - dbg("report_id 0 is invalid"); - return -1; - } - return 0; - - default: - dbg("unknown global tag 0x%x", item->tag); - return -1; - } -} - -/* - * Process a local item. - */ - -static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) -{ - __u32 data; - unsigned n; - - if (item->size == 0) { - dbg("item data expected for local item"); - return -1; - } - - data = item_udata(item); - - switch (item->tag) { - - case HID_LOCAL_ITEM_TAG_DELIMITER: - - if (data) { - /* - * We treat items before the first delimiter - * as global to all usage sets (branch 0). - * In the moment we process only these global - * items and the first delimiter set. - */ - if (parser->local.delimiter_depth != 0) { - dbg("nested delimiters"); - return -1; - } - parser->local.delimiter_depth++; - parser->local.delimiter_branch++; - } else { - if (parser->local.delimiter_depth < 1) { - dbg("bogus close delimiter"); - return -1; - } - parser->local.delimiter_depth--; - } - return 1; - - case HID_LOCAL_ITEM_TAG_USAGE: - - if (parser->local.delimiter_branch > 1) { - dbg("alternative usage ignored"); - return 0; - } - - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - - return hid_add_usage(parser, data); - - case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM: - - if (parser->local.delimiter_branch > 1) { - dbg("alternative usage ignored"); - return 0; - } - - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - - parser->local.usage_minimum = data; - return 0; - - case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM: - - if (parser->local.delimiter_branch > 1) { - dbg("alternative usage ignored"); - return 0; - } - - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - - for (n = parser->local.usage_minimum; n <= data; n++) - if (hid_add_usage(parser, n)) { - dbg("hid_add_usage failed\n"); - return -1; - } - return 0; - - default: - - dbg("unknown local item tag 0x%x", item->tag); - return 0; - } - return 0; -} - -/* - * Process a main item. - */ - -static int hid_parser_main(struct hid_parser *parser, struct hid_item *item) -{ - __u32 data; - int ret; - - data = item_udata(item); - - switch (item->tag) { - case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION: - ret = open_collection(parser, data & 0xff); - break; - case HID_MAIN_ITEM_TAG_END_COLLECTION: - ret = close_collection(parser); - break; - case HID_MAIN_ITEM_TAG_INPUT: - ret = hid_add_field(parser, HID_INPUT_REPORT, data); - break; - case HID_MAIN_ITEM_TAG_OUTPUT: - ret = hid_add_field(parser, HID_OUTPUT_REPORT, data); - break; - case HID_MAIN_ITEM_TAG_FEATURE: - ret = hid_add_field(parser, HID_FEATURE_REPORT, data); - break; - default: - dbg("unknown main item tag 0x%x", item->tag); - ret = 0; - } - - memset(&parser->local, 0, sizeof(parser->local)); /* Reset the local parser environment */ - - return ret; -} - -/* - * Process a reserved item. - */ - -static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item) -{ - dbg("reserved item type, tag 0x%x", item->tag); - return 0; -} - -/* - * Free a report and all registered fields. The field->usage and - * field->value table's are allocated behind the field, so we need - * only to free(field) itself. - */ - -static void hid_free_report(struct hid_report *report) -{ - unsigned n; - - for (n = 0; n < report->maxfield; n++) - kfree(report->field[n]); - kfree(report); -} - -/* - * Free a device structure, all reports, and all fields. - */ - -static void hid_free_device(struct hid_device *device) -{ - unsigned i,j; - - for (i = 0; i < HID_REPORT_TYPES; i++) { - struct hid_report_enum *report_enum = device->report_enum + i; - - for (j = 0; j < 256; j++) { - struct hid_report *report = report_enum->report_id_hash[j]; - if (report) - hid_free_report(report); - } - } - - kfree(device->rdesc); - kfree(device); -} - -/* - * Fetch a report description item from the data stream. We support long - * items, though they are not used yet. - */ - -static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item) -{ - u8 b; - - if ((end - start) <= 0) - return NULL; - - b = *start++; - - item->type = (b >> 2) & 3; - item->tag = (b >> 4) & 15; - - if (item->tag == HID_ITEM_TAG_LONG) { - - item->format = HID_ITEM_FORMAT_LONG; - - if ((end - start) < 2) - return NULL; - - item->size = *start++; - item->tag = *start++; - - if ((end - start) < item->size) - return NULL; - - item->data.longdata = start; - start += item->size; - return start; - } - - item->format = HID_ITEM_FORMAT_SHORT; - item->size = b & 3; - - switch (item->size) { - - case 0: - return start; - - case 1: - if ((end - start) < 1) - return NULL; - item->data.u8 = *start++; - return start; - - case 2: - if ((end - start) < 2) - return NULL; - item->data.u16 = le16_to_cpu(get_unaligned((__le16*)start)); - start = (__u8 *)((__le16 *)start + 1); - return start; - - case 3: - item->size++; - if ((end - start) < 4) - return NULL; - item->data.u32 = le32_to_cpu(get_unaligned((__le32*)start)); - start = (__u8 *)((__le32 *)start + 1); - return start; - } - - return NULL; -} - -/* - * Parse a report description into a hid_device structure. Reports are - * enumerated, fields are attached to these reports. - */ - -static struct hid_device *hid_parse_report(__u8 *start, unsigned size) -{ - struct hid_device *device; - struct hid_parser *parser; - struct hid_item item; - __u8 *end; - unsigned i; - static int (*dispatch_type[])(struct hid_parser *parser, - struct hid_item *item) = { - hid_parser_main, - hid_parser_global, - hid_parser_local, - hid_parser_reserved - }; - - if (!(device = kzalloc(sizeof(struct hid_device), GFP_KERNEL))) - return NULL; - - if (!(device->collection = kzalloc(sizeof(struct hid_collection) * - HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) { - kfree(device); - return NULL; - } - device->collection_size = HID_DEFAULT_NUM_COLLECTIONS; - - for (i = 0; i < HID_REPORT_TYPES; i++) - INIT_LIST_HEAD(&device->report_enum[i].report_list); - - if (!(device->rdesc = (__u8 *)kmalloc(size, GFP_KERNEL))) { - kfree(device->collection); - kfree(device); - return NULL; - } - memcpy(device->rdesc, start, size); - device->rsize = size; - - if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) { - kfree(device->rdesc); - kfree(device->collection); - kfree(device); - return NULL; - } - parser->device = device; - - end = start + size; - while ((start = fetch_item(start, end, &item)) != NULL) { - - if (item.format != HID_ITEM_FORMAT_SHORT) { - dbg("unexpected long global item"); - kfree(device->collection); - hid_free_device(device); - kfree(parser); - return NULL; - } - - if (dispatch_type[item.type](parser, &item)) { - dbg("item %u %u %u %u parsing failed\n", - item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); - kfree(device->collection); - hid_free_device(device); - kfree(parser); - return NULL; - } - - if (start == end) { - if (parser->collection_stack_ptr) { - dbg("unbalanced collection at end of report description"); - kfree(device->collection); - hid_free_device(device); - kfree(parser); - return NULL; - } - if (parser->local.delimiter_depth) { - dbg("unbalanced delimiter at end of report description"); - kfree(device->collection); - hid_free_device(device); - kfree(parser); - return NULL; - } - kfree(parser); - return device; - } - } - - dbg("item fetching failed at offset %d\n", (int)(end - start)); - kfree(device->collection); - hid_free_device(device); - kfree(parser); - return NULL; -} - -/* - * Convert a signed n-bit integer to signed 32-bit integer. Common - * cases are done through the compiler, the screwed things has to be - * done by hand. - */ - -static s32 snto32(__u32 value, unsigned n) -{ - switch (n) { - case 8: return ((__s8)value); - case 16: return ((__s16)value); - case 32: return ((__s32)value); - } - return value & (1 << (n - 1)) ? value | (-1 << n) : value; -} - -/* - * Convert a signed 32-bit integer to a signed n-bit integer. - */ - -static u32 s32ton(__s32 value, unsigned n) -{ - s32 a = value >> (n - 1); - if (a && a != -1) - return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1; - return value & ((1 << n) - 1); -} - -/* - * Extract/implement a data field from/to a little endian report (bit array). - * - * Code sort-of follows HID spec: - * http://www.usb.org/developers/devclass_docs/HID1_11.pdf - * - * While the USB HID spec allows unlimited length bit fields in "report - * descriptors", most devices never use more than 16 bits. - * One model of UPS is claimed to report "LINEV" as a 32-bit field. - * Search linux-kernel and linux-usb-devel archives for "hid-core extract". - */ - -static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) -{ - u64 x; - - WARN_ON(n > 32); - - report += offset >> 3; /* adjust byte index */ - offset &= 7; /* now only need bit offset into one byte */ - x = get_unaligned((u64 *) report); - x = le64_to_cpu(x); - x = (x >> offset) & ((1ULL << n) - 1); /* extract bit field */ - return (u32) x; -} - -/* - * "implement" : set bits in a little endian bit stream. - * Same concepts as "extract" (see comments above). - * The data mangled in the bit stream remains in little endian - * order the whole time. It make more sense to talk about - * endianness of register values by considering a register - * a "cached" copy of the little endiad bit stream. - */ -static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) -{ - u64 x; - u64 m = (1ULL << n) - 1; - - WARN_ON(n > 32); - - WARN_ON(value > m); - value &= m; - - report += offset >> 3; - offset &= 7; - - x = get_unaligned((u64 *)report); - x &= cpu_to_le64(~(m << offset)); - x |= cpu_to_le64(((u64) value) << offset); - put_unaligned(x, (u64 *) report); -} - -/* - * Search an array for a value. - */ - -static __inline__ int search(__s32 *array, __s32 value, unsigned n) -{ - while (n--) { - if (*array++ == value) - return 0; - } - return -1; -} - -static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt) -{ - hid_dump_input(usage, value); - if (hid->claimed & HID_CLAIMED_INPUT) - hidinput_hid_event(hid, field, usage, value); - if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt) - hiddev_hid_event(hid, field, usage, value); -} - -/* - * Analyse a received field, and fetch the data from it. The field - * content is stored for next report processing (we do differential - * reporting to the layer). - */ - -static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt) -{ - unsigned n; - unsigned count = field->report_count; - unsigned offset = field->report_offset; - unsigned size = field->report_size; - __s32 min = field->logical_minimum; - __s32 max = field->logical_maximum; - __s32 *value; - - if (!(value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC))) - return; - - for (n = 0; n < count; n++) { - - value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) : - extract(data, offset + n * size, size); - - if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */ - && value[n] >= min && value[n] <= max - && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1) - goto exit; - } - - for (n = 0; n < count; n++) { - - if (HID_MAIN_ITEM_VARIABLE & field->flags) { - hid_process_event(hid, field, &field->usage[n], value[n], interrupt); - continue; - } - - if (field->value[n] >= min && field->value[n] <= max - && field->usage[field->value[n] - min].hid - && search(value, field->value[n], count)) - hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt); - - if (value[n] >= min && value[n] <= max - && field->usage[value[n] - min].hid - && search(field->value, value[n], count)) - hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt); - } - - memcpy(field->value, value, count * sizeof(__s32)); -exit: - kfree(value); -} - -static int hid_input_report(int type, struct urb *urb, int interrupt) -{ - struct hid_device *hid = urb->context; - struct hid_report_enum *report_enum = hid->report_enum + type; - u8 *data = urb->transfer_buffer; - int len = urb->actual_length; - struct hid_report *report; - int n, size; - - if (!len) { - dbg("empty report"); - return -1; - } - -#ifdef DEBUG_DATA - printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", len, report_enum->numbered ? "" : "un"); -#endif - - n = 0; /* Normally report number is 0 */ - if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */ - n = *data++; - len--; - } - -#ifdef DEBUG_DATA - { - int i; - printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, len); - for (i = 0; i < len; i++) - printk(" %02x", data[i]); - printk("\n"); - } -#endif - - if (!(report = report_enum->report_id_hash[n])) { - dbg("undefined report_id %d received", n); - return -1; - } - - size = ((report->size - 1) >> 3) + 1; - - if (len < size) { - dbg("report %d is too short, (%d < %d)", report->id, len, size); - memset(data + len, 0, size - len); - } - - if (hid->claimed & HID_CLAIMED_HIDDEV) - hiddev_report_event(hid, report); - - for (n = 0; n < report->maxfield; n++) - hid_input_field(hid, report->field[n], data, interrupt); - - if (hid->claimed & HID_CLAIMED_INPUT) - hidinput_report_event(hid, report); - - return 0; -} - -/* - * Input submission and I/O error handler. - */ - -static void hid_io_error(struct hid_device *hid); - -/* Start up the input URB */ -static int hid_start_in(struct hid_device *hid) -{ - unsigned long flags; - int rc = 0; - - spin_lock_irqsave(&hid->inlock, flags); - if (hid->open > 0 && !test_bit(HID_SUSPENDED, &hid->iofl) && - !test_and_set_bit(HID_IN_RUNNING, &hid->iofl)) { - rc = usb_submit_urb(hid->urbin, GFP_ATOMIC); - if (rc != 0) - clear_bit(HID_IN_RUNNING, &hid->iofl); - } - spin_unlock_irqrestore(&hid->inlock, flags); - return rc; -} - -/* I/O retry timer routine */ -static void hid_retry_timeout(unsigned long _hid) -{ - struct hid_device *hid = (struct hid_device *) _hid; - - dev_dbg(&hid->intf->dev, "retrying intr urb\n"); - if (hid_start_in(hid)) - hid_io_error(hid); -} - -/* Workqueue routine to reset the device or clear a halt */ -static void hid_reset(struct work_struct *work) -{ - struct hid_device *hid = - container_of(work, struct hid_device, reset_work); - int rc_lock, rc = 0; - - if (test_bit(HID_CLEAR_HALT, &hid->iofl)) { - dev_dbg(&hid->intf->dev, "clear halt\n"); - rc = usb_clear_halt(hid->dev, hid->urbin->pipe); - clear_bit(HID_CLEAR_HALT, &hid->iofl); - hid_start_in(hid); - } - - else if (test_bit(HID_RESET_PENDING, &hid->iofl)) { - dev_dbg(&hid->intf->dev, "resetting device\n"); - rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf); - if (rc_lock >= 0) { - rc = usb_reset_composite_device(hid->dev, hid->intf); - if (rc_lock) - usb_unlock_device(hid->dev); - } - clear_bit(HID_RESET_PENDING, &hid->iofl); - } - - switch (rc) { - case 0: - if (!test_bit(HID_IN_RUNNING, &hid->iofl)) - hid_io_error(hid); - break; - default: - err("can't reset device, %s-%s/input%d, status %d", - hid->dev->bus->bus_name, - hid->dev->devpath, - hid->ifnum, rc); - /* FALLTHROUGH */ - case -EHOSTUNREACH: - case -ENODEV: - case -EINTR: - break; - } -} - -/* Main I/O error handler */ -static void hid_io_error(struct hid_device *hid) -{ - unsigned long flags; - - spin_lock_irqsave(&hid->inlock, flags); - - /* Stop when disconnected */ - if (usb_get_intfdata(hid->intf) == NULL) - goto done; - - /* When an error occurs, retry at increasing intervals */ - if (hid->retry_delay == 0) { - hid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */ - hid->stop_retry = jiffies + msecs_to_jiffies(1000); - } else if (hid->retry_delay < 100) - hid->retry_delay *= 2; - - if (time_after(jiffies, hid->stop_retry)) { - - /* Retries failed, so do a port reset */ - if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) { - schedule_work(&hid->reset_work); - goto done; - } - } - - mod_timer(&hid->io_retry, - jiffies + msecs_to_jiffies(hid->retry_delay)); -done: - spin_unlock_irqrestore(&hid->inlock, flags); -} - -/* - * Input interrupt completion handler. - */ - -static void hid_irq_in(struct urb *urb) -{ - struct hid_device *hid = urb->context; - int status; - - switch (urb->status) { - case 0: /* success */ - hid->retry_delay = 0; - hid_input_report(HID_INPUT_REPORT, urb, 1); - break; - case -EPIPE: /* stall */ - clear_bit(HID_IN_RUNNING, &hid->iofl); - set_bit(HID_CLEAR_HALT, &hid->iofl); - schedule_work(&hid->reset_work); - return; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: /* unplug */ - clear_bit(HID_IN_RUNNING, &hid->iofl); - return; - case -EILSEQ: /* protocol error or unplug */ - case -EPROTO: /* protocol error or unplug */ - case -ETIME: /* protocol error or unplug */ - case -ETIMEDOUT: /* Should never happen, but... */ - clear_bit(HID_IN_RUNNING, &hid->iofl); - hid_io_error(hid); - return; - default: /* error */ - warn("input irq status %d received", urb->status); - } - - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) { - clear_bit(HID_IN_RUNNING, &hid->iofl); - if (status != -EPERM) { - err("can't resubmit intr, %s-%s/input%d, status %d", - hid->dev->bus->bus_name, - hid->dev->devpath, - hid->ifnum, status); - hid_io_error(hid); - } - } -} - -/* - * Output the field into the report. - */ - -static void hid_output_field(struct hid_field *field, __u8 *data) -{ - unsigned count = field->report_count; - unsigned offset = field->report_offset; - unsigned size = field->report_size; - unsigned n; - - for (n = 0; n < count; n++) { - if (field->logical_minimum < 0) /* signed values */ - implement(data, offset + n * size, size, s32ton(field->value[n], size)); - else /* unsigned values */ - implement(data, offset + n * size, size, field->value[n]); - } -} - -/* - * Create a report. - */ - -static void hid_output_report(struct hid_report *report, __u8 *data) -{ - unsigned n; - - if (report->id > 0) - *data++ = report->id; - - for (n = 0; n < report->maxfield; n++) - hid_output_field(report->field[n], data); -} - -/* - * Set a field value. The report this field belongs to has to be - * created and transferred to the device, to set this value in the - * device. - */ - -int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) -{ - unsigned size = field->report_size; - - hid_dump_input(field->usage + offset, value); - - if (offset >= field->report_count) { - dbg("offset (%d) exceeds report_count (%d)", offset, field->report_count); - hid_dump_field(field, 8); - return -1; - } - if (field->logical_minimum < 0) { - if (value != snto32(s32ton(value, size), size)) { - dbg("value %d is out of range", value); - return -1; - } - } - field->value[offset] = value; - return 0; -} - -/* - * Find a report field with a specified HID usage. - */ -#if 0 -struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_usage, int type) -{ - struct hid_report *report; - int i; - - list_for_each_entry(report, &hid->report_enum[type].report_list, list) - for (i = 0; i < report->maxfield; i++) - if (report->field[i]->logical == wanted_usage) - return report->field[i]; - return NULL; -} -#endif /* 0 */ - -static int hid_submit_out(struct hid_device *hid) -{ - struct hid_report *report; - - report = hid->out[hid->outtail]; - - hid_output_report(report, hid->outbuf); - hid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); - hid->urbout->dev = hid->dev; - - dbg("submitting out urb"); - - if (usb_submit_urb(hid->urbout, GFP_ATOMIC)) { - err("usb_submit_urb(out) failed"); - return -1; - } - - return 0; -} - -static int hid_submit_ctrl(struct hid_device *hid) -{ - struct hid_report *report; - unsigned char dir; - int len; - - report = hid->ctrl[hid->ctrltail].report; - dir = hid->ctrl[hid->ctrltail].dir; - - len = ((report->size - 1) >> 3) + 1 + (report->id > 0); - if (dir == USB_DIR_OUT) { - hid_output_report(report, hid->ctrlbuf); - hid->urbctrl->pipe = usb_sndctrlpipe(hid->dev, 0); - hid->urbctrl->transfer_buffer_length = len; - } else { - int maxpacket, padlen; - - hid->urbctrl->pipe = usb_rcvctrlpipe(hid->dev, 0); - maxpacket = usb_maxpacket(hid->dev, hid->urbctrl->pipe, 0); - if (maxpacket > 0) { - padlen = (len + maxpacket - 1) / maxpacket; - padlen *= maxpacket; - if (padlen > hid->bufsize) - padlen = hid->bufsize; - } else - padlen = 0; - hid->urbctrl->transfer_buffer_length = padlen; - } - hid->urbctrl->dev = hid->dev; - - hid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir; - hid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT; - hid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id); - hid->cr->wIndex = cpu_to_le16(hid->ifnum); - hid->cr->wLength = cpu_to_le16(len); - - dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u", - hid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report", - hid->cr->wValue, hid->cr->wIndex, hid->cr->wLength); - - if (usb_submit_urb(hid->urbctrl, GFP_ATOMIC)) { - err("usb_submit_urb(ctrl) failed"); - return -1; - } - - return 0; -} - -/* - * Output interrupt completion handler. - */ - -static void hid_irq_out(struct urb *urb) -{ - struct hid_device *hid = urb->context; - unsigned long flags; - int unplug = 0; - - switch (urb->status) { - case 0: /* success */ - break; - case -ESHUTDOWN: /* unplug */ - unplug = 1; - case -EILSEQ: /* protocol error or unplug */ - case -EPROTO: /* protocol error or unplug */ - case -ECONNRESET: /* unlink */ - case -ENOENT: - break; - default: /* error */ - warn("output irq status %d received", urb->status); - } - - spin_lock_irqsave(&hid->outlock, flags); - - if (unplug) - hid->outtail = hid->outhead; - else - hid->outtail = (hid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1); - - if (hid->outhead != hid->outtail) { - if (hid_submit_out(hid)) { - clear_bit(HID_OUT_RUNNING, &hid->iofl); - wake_up(&hid->wait); - } - spin_unlock_irqrestore(&hid->outlock, flags); - return; - } - - clear_bit(HID_OUT_RUNNING, &hid->iofl); - spin_unlock_irqrestore(&hid->outlock, flags); - wake_up(&hid->wait); -} - -/* - * Control pipe completion handler. - */ - -static void hid_ctrl(struct urb *urb) -{ - struct hid_device *hid = urb->context; - unsigned long flags; - int unplug = 0; - - spin_lock_irqsave(&hid->ctrllock, flags); - - switch (urb->status) { - case 0: /* success */ - if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) - hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0); - break; - case -ESHUTDOWN: /* unplug */ - unplug = 1; - case -EILSEQ: /* protocol error or unplug */ - case -EPROTO: /* protocol error or unplug */ - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -EPIPE: /* report not available */ - break; - default: /* error */ - warn("ctrl urb status %d received", urb->status); - } - - if (unplug) - hid->ctrltail = hid->ctrlhead; - else - hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); - - if (hid->ctrlhead != hid->ctrltail) { - if (hid_submit_ctrl(hid)) { - clear_bit(HID_CTRL_RUNNING, &hid->iofl); - wake_up(&hid->wait); - } - spin_unlock_irqrestore(&hid->ctrllock, flags); - return; - } - - clear_bit(HID_CTRL_RUNNING, &hid->iofl); - spin_unlock_irqrestore(&hid->ctrllock, flags); - wake_up(&hid->wait); -} - -void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) -{ - int head; - unsigned long flags; - - if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN) - return; - - if (hid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) { - - spin_lock_irqsave(&hid->outlock, flags); - - if ((head = (hid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == hid->outtail) { - spin_unlock_irqrestore(&hid->outlock, flags); - warn("output queue full"); - return; - } - - hid->out[hid->outhead] = report; - hid->outhead = head; - - if (!test_and_set_bit(HID_OUT_RUNNING, &hid->iofl)) - if (hid_submit_out(hid)) - clear_bit(HID_OUT_RUNNING, &hid->iofl); - - spin_unlock_irqrestore(&hid->outlock, flags); - return; - } - - spin_lock_irqsave(&hid->ctrllock, flags); - - if ((head = (hid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == hid->ctrltail) { - spin_unlock_irqrestore(&hid->ctrllock, flags); - warn("control queue full"); - return; - } - - hid->ctrl[hid->ctrlhead].report = report; - hid->ctrl[hid->ctrlhead].dir = dir; - hid->ctrlhead = head; - - if (!test_and_set_bit(HID_CTRL_RUNNING, &hid->iofl)) - if (hid_submit_ctrl(hid)) - clear_bit(HID_CTRL_RUNNING, &hid->iofl); - - spin_unlock_irqrestore(&hid->ctrllock, flags); -} - -int hid_wait_io(struct hid_device *hid) -{ - if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &hid->iofl) && - !test_bit(HID_OUT_RUNNING, &hid->iofl)), - 10*HZ)) { - dbg("timeout waiting for ctrl or out queue to clear"); - return -1; - } - - return 0; -} - -static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (idle << 8) | report, - ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT); -} - -static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, - unsigned char type, void *buf, int size) -{ - int result, retries = 4; - - memset(buf,0,size); // Make sure we parse really received data - - do { - result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, - (type << 8), ifnum, buf, size, USB_CTRL_GET_TIMEOUT); - retries--; - } while (result < size && retries); - return result; -} - -int hid_open(struct hid_device *hid) -{ - ++hid->open; - if (hid_start_in(hid)) - hid_io_error(hid); - return 0; -} - -void hid_close(struct hid_device *hid) -{ - if (!--hid->open) - usb_kill_urb(hid->urbin); -} - -#define USB_VENDOR_ID_PANJIT 0x134c - -#define USB_VENDOR_ID_TURBOX 0x062a -#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 - -/* - * Initialize all reports - */ - -void hid_init_reports(struct hid_device *hid) -{ - struct hid_report *report; - int err, ret; - - list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) - hid_submit_report(hid, report, USB_DIR_IN); - - list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list) - hid_submit_report(hid, report, USB_DIR_IN); - - err = 0; - ret = hid_wait_io(hid); - while (ret) { - err |= ret; - if (test_bit(HID_CTRL_RUNNING, &hid->iofl)) - usb_kill_urb(hid->urbctrl); - if (test_bit(HID_OUT_RUNNING, &hid->iofl)) - usb_kill_urb(hid->urbout); - ret = hid_wait_io(hid); - } - - if (err) - warn("timeout initializing reports"); -} - -#define USB_VENDOR_ID_GTCO 0x078c -#define USB_DEVICE_ID_GTCO_90 0x0090 -#define USB_DEVICE_ID_GTCO_100 0x0100 -#define USB_DEVICE_ID_GTCO_101 0x0101 -#define USB_DEVICE_ID_GTCO_103 0x0103 -#define USB_DEVICE_ID_GTCO_104 0x0104 -#define USB_DEVICE_ID_GTCO_105 0x0105 -#define USB_DEVICE_ID_GTCO_106 0x0106 -#define USB_DEVICE_ID_GTCO_107 0x0107 -#define USB_DEVICE_ID_GTCO_108 0x0108 -#define USB_DEVICE_ID_GTCO_200 0x0200 -#define USB_DEVICE_ID_GTCO_201 0x0201 -#define USB_DEVICE_ID_GTCO_202 0x0202 -#define USB_DEVICE_ID_GTCO_203 0x0203 -#define USB_DEVICE_ID_GTCO_204 0x0204 -#define USB_DEVICE_ID_GTCO_205 0x0205 -#define USB_DEVICE_ID_GTCO_206 0x0206 -#define USB_DEVICE_ID_GTCO_207 0x0207 -#define USB_DEVICE_ID_GTCO_300 0x0300 -#define USB_DEVICE_ID_GTCO_301 0x0301 -#define USB_DEVICE_ID_GTCO_302 0x0302 -#define USB_DEVICE_ID_GTCO_303 0x0303 -#define USB_DEVICE_ID_GTCO_304 0x0304 -#define USB_DEVICE_ID_GTCO_305 0x0305 -#define USB_DEVICE_ID_GTCO_306 0x0306 -#define USB_DEVICE_ID_GTCO_307 0x0307 -#define USB_DEVICE_ID_GTCO_308 0x0308 -#define USB_DEVICE_ID_GTCO_309 0x0309 -#define USB_DEVICE_ID_GTCO_400 0x0400 -#define USB_DEVICE_ID_GTCO_401 0x0401 -#define USB_DEVICE_ID_GTCO_402 0x0402 -#define USB_DEVICE_ID_GTCO_403 0x0403 -#define USB_DEVICE_ID_GTCO_404 0x0404 -#define USB_DEVICE_ID_GTCO_405 0x0405 -#define USB_DEVICE_ID_GTCO_500 0x0500 -#define USB_DEVICE_ID_GTCO_501 0x0501 -#define USB_DEVICE_ID_GTCO_502 0x0502 -#define USB_DEVICE_ID_GTCO_503 0x0503 -#define USB_DEVICE_ID_GTCO_504 0x0504 -#define USB_DEVICE_ID_GTCO_1000 0x1000 -#define USB_DEVICE_ID_GTCO_1001 0x1001 -#define USB_DEVICE_ID_GTCO_1002 0x1002 -#define USB_DEVICE_ID_GTCO_1003 0x1003 -#define USB_DEVICE_ID_GTCO_1004 0x1004 -#define USB_DEVICE_ID_GTCO_1005 0x1005 -#define USB_DEVICE_ID_GTCO_1006 0x1006 - -#define USB_VENDOR_ID_WACOM 0x056a - -#define USB_VENDOR_ID_ACECAD 0x0460 -#define USB_DEVICE_ID_ACECAD_FLAIR 0x0004 -#define USB_DEVICE_ID_ACECAD_302 0x0008 - -#define USB_VENDOR_ID_KBGEAR 0x084e -#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 - -#define USB_VENDOR_ID_AIPTEK 0x08ca -#define USB_DEVICE_ID_AIPTEK_01 0x0001 -#define USB_DEVICE_ID_AIPTEK_10 0x0010 -#define USB_DEVICE_ID_AIPTEK_20 0x0020 -#define USB_DEVICE_ID_AIPTEK_21 0x0021 -#define USB_DEVICE_ID_AIPTEK_22 0x0022 -#define USB_DEVICE_ID_AIPTEK_23 0x0023 -#define USB_DEVICE_ID_AIPTEK_24 0x0024 - -#define USB_VENDOR_ID_GRIFFIN 0x077d -#define USB_DEVICE_ID_POWERMATE 0x0410 -#define USB_DEVICE_ID_SOUNDKNOB 0x04AA - -#define USB_VENDOR_ID_ATEN 0x0557 -#define USB_DEVICE_ID_ATEN_UC100KM 0x2004 -#define USB_DEVICE_ID_ATEN_CS124U 0x2202 -#define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204 -#define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205 -#define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208 - -#define USB_VENDOR_ID_TOPMAX 0x0663 -#define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 - -#define USB_VENDOR_ID_HAPP 0x078b -#define USB_DEVICE_ID_UGCI_DRIVING 0x0010 -#define USB_DEVICE_ID_UGCI_FLYING 0x0020 -#define USB_DEVICE_ID_UGCI_FIGHTING 0x0030 - -#define USB_VENDOR_ID_MGE 0x0463 -#define USB_DEVICE_ID_MGE_UPS 0xffff -#define USB_DEVICE_ID_MGE_UPS1 0x0001 - -#define USB_VENDOR_ID_ONTRAK 0x0a07 -#define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 - -#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f -#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 - -#define USB_VENDOR_ID_A4TECH 0x09da -#define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 - -#define USB_VENDOR_ID_AASHIMA 0x06d6 -#define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025 -#define USB_DEVICE_ID_AASHIMA_PREDATOR 0x0026 - -#define USB_VENDOR_ID_CYPRESS 0x04b4 -#define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001 -#define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500 -#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE 0x7417 - -#define USB_VENDOR_ID_BERKSHIRE 0x0c98 -#define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140 - -#define USB_VENDOR_ID_ALPS 0x0433 -#define USB_DEVICE_ID_IBM_GAMEPAD 0x1101 - -#define USB_VENDOR_ID_SAITEK 0x06a3 -#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 - -#define USB_VENDOR_ID_NEC 0x073e -#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301 - -#define USB_VENDOR_ID_CHIC 0x05fe -#define USB_DEVICE_ID_CHIC_GAMEPAD 0x0014 - -#define USB_VENDOR_ID_GLAB 0x06c2 -#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 -#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 -#define USB_DEVICE_ID_0_0_4_IF_KIT 0x0040 -#define USB_DEVICE_ID_0_16_16_IF_KIT 0x0044 -#define USB_DEVICE_ID_8_8_8_IF_KIT 0x0045 -#define USB_DEVICE_ID_0_8_7_IF_KIT 0x0051 -#define USB_DEVICE_ID_0_8_8_IF_KIT 0x0053 -#define USB_DEVICE_ID_PHIDGET_MOTORCONTROL 0x0058 - -#define USB_VENDOR_ID_WISEGROUP 0x0925 -#define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 -#define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104 -#define USB_DEVICE_ID_8_8_4_IF_KIT 0x8201 -#define USB_DEVICE_ID_DUAL_USB_JOYPAD 0x8866 - -#define USB_VENDOR_ID_WISEGROUP_LTD 0x6677 -#define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802 - -#define USB_VENDOR_ID_CODEMERCS 0x07c0 -#define USB_DEVICE_ID_CODEMERCS_IOW40 0x1500 -#define USB_DEVICE_ID_CODEMERCS_IOW24 0x1501 -#define USB_DEVICE_ID_CODEMERCS_IOW48 0x1502 -#define USB_DEVICE_ID_CODEMERCS_IOW28 0x1503 - -#define USB_VENDOR_ID_DELORME 0x1163 -#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 -#define USB_DEVICE_ID_DELORME_EM_LT20 0x0200 - -#define USB_VENDOR_ID_MCC 0x09db -#define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 -#define USB_DEVICE_ID_MCC_PMD1208LS 0x007a - -#define USB_VENDOR_ID_VERNIER 0x08f7 -#define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 -#define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 -#define USB_DEVICE_ID_VERNIER_SKIP 0x0003 -#define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 - -#define USB_VENDOR_ID_LD 0x0f11 -#define USB_DEVICE_ID_LD_CASSY 0x1000 -#define USB_DEVICE_ID_LD_POCKETCASSY 0x1010 -#define USB_DEVICE_ID_LD_MOBILECASSY 0x1020 -#define USB_DEVICE_ID_LD_JWM 0x1080 -#define USB_DEVICE_ID_LD_DMMP 0x1081 -#define USB_DEVICE_ID_LD_UMIP 0x1090 -#define USB_DEVICE_ID_LD_XRAY1 0x1100 -#define USB_DEVICE_ID_LD_XRAY2 0x1101 -#define USB_DEVICE_ID_LD_VIDEOCOM 0x1200 -#define USB_DEVICE_ID_LD_COM3LAB 0x2000 -#define USB_DEVICE_ID_LD_TELEPORT 0x2010 -#define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020 -#define USB_DEVICE_ID_LD_POWERCONTROL 0x2030 -#define USB_DEVICE_ID_LD_MACHINETEST 0x2040 - -#define USB_VENDOR_ID_APPLE 0x05ac -#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 -#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e -#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f -#define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214 -#define USB_DEVICE_ID_APPLE_GEYSER_ISO 0x0215 -#define USB_DEVICE_ID_APPLE_GEYSER_JIS 0x0216 -#define USB_DEVICE_ID_APPLE_GEYSER3_ANSI 0x0217 -#define USB_DEVICE_ID_APPLE_GEYSER3_ISO 0x0218 -#define USB_DEVICE_ID_APPLE_GEYSER3_JIS 0x0219 -#define USB_DEVICE_ID_APPLE_GEYSER4_ANSI 0x021a -#define USB_DEVICE_ID_APPLE_GEYSER4_ISO 0x021b -#define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c -#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a -#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b - -#define USB_VENDOR_ID_CHERRY 0x046a -#define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 - -#define USB_VENDOR_ID_YEALINK 0x6993 -#define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001 - -#define USB_VENDOR_ID_ALCOR 0x058f -#define USB_DEVICE_ID_ALCOR_USBRS232 0x9720 - -#define USB_VENDOR_ID_SUN 0x0430 -#define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab - -#define USB_VENDOR_ID_AIRCABLE 0x16CA -#define USB_DEVICE_ID_AIRCABLE1 0x1502 - -#define USB_VENDOR_ID_LOGITECH 0x046d -#define USB_DEVICE_ID_LOGITECH_USB_RECEIVER 0xc101 - -/* - * Alphabetically sorted blacklist by quirk type. - */ - -static const struct hid_blacklist { - __u16 idVendor; - __u16 idProduct; - unsigned quirks; -} hid_blacklist[] = { - - { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_21, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_16_16_IF_KIT, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_103, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_104, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_105, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_106, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_107, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_108, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_200, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_201, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_202, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_203, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_204, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_205, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_206, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_207, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_300, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_301, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_302, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_303, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_304, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_305, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_306, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_307, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_308, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_309, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_400, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_401, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_402, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_403, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_405, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_500, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_501, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1003, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 30, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 108, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 118, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE }, - - { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE }, - - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, - - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL }, - { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 }, - { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 }, - - { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, - { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, - - { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION }, - - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN }, - - { USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_PANJIT, 0x0003, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE }, - - { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, - - { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS }, - - { 0, 0 } -}; - -/* - * Traverse the supplied list of reports and find the longest - */ -static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *max) -{ - struct hid_report *report; - int size; - - list_for_each_entry(report, &hid->report_enum[type].report_list, list) { - size = ((report->size - 1) >> 3) + 1; - if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered) - size++; - if (*max < size) - *max = size; - } -} - -static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) -{ - if (!(hid->inbuf = usb_buffer_alloc(dev, hid->bufsize, GFP_ATOMIC, &hid->inbuf_dma))) - return -1; - if (!(hid->outbuf = usb_buffer_alloc(dev, hid->bufsize, GFP_ATOMIC, &hid->outbuf_dma))) - return -1; - if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), GFP_ATOMIC, &hid->cr_dma))) - return -1; - if (!(hid->ctrlbuf = usb_buffer_alloc(dev, hid->bufsize, GFP_ATOMIC, &hid->ctrlbuf_dma))) - return -1; - - return 0; -} - -static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) -{ - if (hid->inbuf) - usb_buffer_free(dev, hid->bufsize, hid->inbuf, hid->inbuf_dma); - if (hid->outbuf) - usb_buffer_free(dev, hid->bufsize, hid->outbuf, hid->outbuf_dma); - if (hid->cr) - usb_buffer_free(dev, sizeof(*(hid->cr)), hid->cr, hid->cr_dma); - if (hid->ctrlbuf) - usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma); -} - -/* - * Cherry Cymotion keyboard have an invalid HID report descriptor, - * that needs fixing before we can parse it. - */ - -static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize) -{ - if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { - info("Fixing up Cherry Cymotion report descriptor"); - rdesc[11] = rdesc[16] = 0xff; - rdesc[12] = rdesc[17] = 0x03; - } -} - -static struct hid_device *usb_hid_configure(struct usb_interface *intf) -{ - struct usb_host_interface *interface = intf->cur_altsetting; - struct usb_device *dev = interface_to_usbdev (intf); - struct hid_descriptor *hdesc; - struct hid_device *hid; - unsigned quirks = 0, rsize = 0; - char *rdesc; - int n, len, insize = 0; - - /* Ignore all Wacom devices */ - if (le16_to_cpu(dev->descriptor.idVendor) == USB_VENDOR_ID_WACOM) - return NULL; - - for (n = 0; hid_blacklist[n].idVendor; n++) - if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) && - (hid_blacklist[n].idProduct == le16_to_cpu(dev->descriptor.idProduct))) - quirks = hid_blacklist[n].quirks; - - /* Many keyboards and mice don't like to be polled for reports, - * so we will always set the HID_QUIRK_NOGET flag for them. */ - if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) { - if (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD || - interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) - quirks |= HID_QUIRK_NOGET; - } - - if (quirks & HID_QUIRK_IGNORE) - return NULL; - - if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && - (!interface->desc.bNumEndpoints || - usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) { - dbg("class descriptor not present\n"); - return NULL; - } - - for (n = 0; n < hdesc->bNumDescriptors; n++) - if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) - rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); - - if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) { - dbg("weird size of report descriptor (%u)", rsize); - return NULL; - } - - if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) { - dbg("couldn't allocate rdesc memory"); - return NULL; - } - - hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0); - - if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) { - dbg("reading report descriptor failed"); - kfree(rdesc); - return NULL; - } - - if ((quirks & HID_QUIRK_CYMOTION)) - hid_fixup_cymotion_descriptor(rdesc, rsize); - -#ifdef DEBUG_DATA - printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); - for (n = 0; n < rsize; n++) - printk(" %02x", (unsigned char) rdesc[n]); - printk("\n"); -#endif - - if (!(hid = hid_parse_report(rdesc, n))) { - dbg("parsing report descriptor failed"); - kfree(rdesc); - return NULL; - } - - kfree(rdesc); - hid->quirks = quirks; - - hid->bufsize = HID_MIN_BUFFER_SIZE; - hid_find_max_report(hid, HID_INPUT_REPORT, &hid->bufsize); - hid_find_max_report(hid, HID_OUTPUT_REPORT, &hid->bufsize); - hid_find_max_report(hid, HID_FEATURE_REPORT, &hid->bufsize); - - if (hid->bufsize > HID_MAX_BUFFER_SIZE) - hid->bufsize = HID_MAX_BUFFER_SIZE; - - hid_find_max_report(hid, HID_INPUT_REPORT, &insize); - - if (insize > HID_MAX_BUFFER_SIZE) - insize = HID_MAX_BUFFER_SIZE; - - if (hid_alloc_buffers(dev, hid)) { - hid_free_buffers(dev, hid); - goto fail; - } - - for (n = 0; n < interface->desc.bNumEndpoints; n++) { - - struct usb_endpoint_descriptor *endpoint; - int pipe; - int interval; - - endpoint = &interface->endpoint[n].desc; - if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */ - continue; - - interval = endpoint->bInterval; - - /* Change the polling interval of mice. */ - if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) - interval = hid_mousepoll_interval; - - if (usb_endpoint_dir_in(endpoint)) { - if (hid->urbin) - continue; - if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL))) - goto fail; - pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, insize, - hid_irq_in, hid, interval); - hid->urbin->transfer_dma = hid->inbuf_dma; - hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - } else { - if (hid->urbout) - continue; - if (!(hid->urbout = usb_alloc_urb(0, GFP_KERNEL))) - goto fail; - pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress); - usb_fill_int_urb(hid->urbout, dev, pipe, hid->outbuf, 0, - hid_irq_out, hid, interval); - hid->urbout->transfer_dma = hid->outbuf_dma; - hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - } - } - - if (!hid->urbin) { - err("couldn't find an input interrupt endpoint"); - goto fail; - } - - init_waitqueue_head(&hid->wait); - - INIT_WORK(&hid->reset_work, hid_reset); - setup_timer(&hid->io_retry, hid_retry_timeout, (unsigned long) hid); - - spin_lock_init(&hid->inlock); - spin_lock_init(&hid->outlock); - spin_lock_init(&hid->ctrllock); - - hid->version = le16_to_cpu(hdesc->bcdHID); - hid->country = hdesc->bCountryCode; - hid->dev = dev; - hid->intf = intf; - hid->ifnum = interface->desc.bInterfaceNumber; - - hid->name[0] = 0; - - if (dev->manufacturer) - strlcpy(hid->name, dev->manufacturer, sizeof(hid->name)); - - if (dev->product) { - if (dev->manufacturer) - strlcat(hid->name, " ", sizeof(hid->name)); - strlcat(hid->name, dev->product, sizeof(hid->name)); - } - - if (!strlen(hid->name)) - snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x", - le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - - usb_make_path(dev, hid->phys, sizeof(hid->phys)); - strlcat(hid->phys, "/input", sizeof(hid->phys)); - len = strlen(hid->phys); - if (len < sizeof(hid->phys) - 1) - snprintf(hid->phys + len, sizeof(hid->phys) - len, - "%d", intf->altsetting[0].desc.bInterfaceNumber); - - if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0) - hid->uniq[0] = 0; - - hid->urbctrl = usb_alloc_urb(0, GFP_KERNEL); - if (!hid->urbctrl) - goto fail; - - usb_fill_control_urb(hid->urbctrl, dev, 0, (void *) hid->cr, - hid->ctrlbuf, 1, hid_ctrl, hid); - hid->urbctrl->setup_dma = hid->cr_dma; - hid->urbctrl->transfer_dma = hid->ctrlbuf_dma; - hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); - - return hid; - -fail: - usb_free_urb(hid->urbin); - usb_free_urb(hid->urbout); - usb_free_urb(hid->urbctrl); - hid_free_buffers(dev, hid); - hid_free_device(hid); - - return NULL; -} - -static void hid_disconnect(struct usb_interface *intf) -{ - struct hid_device *hid = usb_get_intfdata (intf); - - if (!hid) - return; - - spin_lock_irq(&hid->inlock); /* Sync with error handler */ - usb_set_intfdata(intf, NULL); - spin_unlock_irq(&hid->inlock); - usb_kill_urb(hid->urbin); - usb_kill_urb(hid->urbout); - usb_kill_urb(hid->urbctrl); - - del_timer_sync(&hid->io_retry); - flush_scheduled_work(); - - if (hid->claimed & HID_CLAIMED_INPUT) - hidinput_disconnect(hid); - if (hid->claimed & HID_CLAIMED_HIDDEV) - hiddev_disconnect(hid); - - usb_free_urb(hid->urbin); - usb_free_urb(hid->urbctrl); - usb_free_urb(hid->urbout); - - hid_free_buffers(hid->dev, hid); - hid_free_device(hid); -} - -static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct hid_device *hid; - char path[64]; - int i; - char *c; - - dbg("HID probe called for ifnum %d", - intf->altsetting->desc.bInterfaceNumber); - - if (!(hid = usb_hid_configure(intf))) - return -ENODEV; - - hid_init_reports(hid); - hid_dump_device(hid); - - if (!hidinput_connect(hid)) - hid->claimed |= HID_CLAIMED_INPUT; - if (!hiddev_connect(hid)) - hid->claimed |= HID_CLAIMED_HIDDEV; - - usb_set_intfdata(intf, hid); - - if (!hid->claimed) { - printk ("HID device not claimed by input or hiddev\n"); - hid_disconnect(intf); - return -ENODEV; - } - - printk(KERN_INFO); - - if (hid->claimed & HID_CLAIMED_INPUT) - printk("input"); - if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV)) - printk(","); - if (hid->claimed & HID_CLAIMED_HIDDEV) - printk("hiddev%d", hid->minor); - - c = "Device"; - for (i = 0; i < hid->maxcollection; i++) { - if (hid->collection[i].type == HID_COLLECTION_APPLICATION && - (hid->collection[i].usage & HID_USAGE_PAGE) == HID_UP_GENDESK && - (hid->collection[i].usage & 0xffff) < ARRAY_SIZE(hid_types)) { - c = hid_types[hid->collection[i].usage & 0xffff]; - break; - } - } - - usb_make_path(interface_to_usbdev(intf), path, 63); - - printk(": USB HID v%x.%02x %s [%s] on %s\n", - hid->version >> 8, hid->version & 0xff, c, hid->name, path); - - return 0; -} - -static int hid_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct hid_device *hid = usb_get_intfdata (intf); - - spin_lock_irq(&hid->inlock); /* Sync with error handler */ - set_bit(HID_SUSPENDED, &hid->iofl); - spin_unlock_irq(&hid->inlock); - del_timer(&hid->io_retry); - usb_kill_urb(hid->urbin); - dev_dbg(&intf->dev, "suspend\n"); - return 0; -} - -static int hid_resume(struct usb_interface *intf) -{ - struct hid_device *hid = usb_get_intfdata (intf); - int status; - - clear_bit(HID_SUSPENDED, &hid->iofl); - hid->retry_delay = 0; - status = hid_start_in(hid); - dev_dbg(&intf->dev, "resume status %d\n", status); - return status; -} - -/* Treat USB reset pretty much the same as suspend/resume */ -static void hid_pre_reset(struct usb_interface *intf) -{ - /* FIXME: What if the interface is already suspended? */ - hid_suspend(intf, PMSG_ON); -} - -static void hid_post_reset(struct usb_interface *intf) -{ - struct usb_device *dev = interface_to_usbdev (intf); - - hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0); - /* FIXME: Any more reinitialization needed? */ - - hid_resume(intf); -} - -static struct usb_device_id hid_usb_ids [] = { - { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, - .bInterfaceClass = USB_INTERFACE_CLASS_HID }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, hid_usb_ids); - -static struct usb_driver hid_driver = { - .name = "usbhid", - .probe = hid_probe, - .disconnect = hid_disconnect, - .suspend = hid_suspend, - .resume = hid_resume, - .pre_reset = hid_pre_reset, - .post_reset = hid_post_reset, - .id_table = hid_usb_ids, -}; - -static int __init hid_init(void) -{ - int retval; - retval = hiddev_init(); - if (retval) - goto hiddev_init_fail; - retval = usb_register(&hid_driver); - if (retval) - goto usb_register_fail; - info(DRIVER_VERSION ":" DRIVER_DESC); - - return 0; -usb_register_fail: - hiddev_exit(); -hiddev_init_fail: - return retval; -} - -static void __exit hid_exit(void) -{ - usb_deregister(&hid_driver); - hiddev_exit(); -} - -module_init(hid_init); -module_exit(hid_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENSE); diff --git a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h deleted file mode 100644 index f04d6d75c09..00000000000 --- a/drivers/usb/input/hid-debug.h +++ /dev/null @@ -1,757 +0,0 @@ -/* - * $Id: hid-debug.h,v 1.8 2001/09/25 09:37:57 vojtech Exp $ - * - * (c) 1999 Andreas Gal <gal@cs.uni-magdeburg.de> - * (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz> - * - * Some debug stuff for the HID parser. - */ - -/* - * 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 - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#include <linux/input.h> - -struct hid_usage_entry { - unsigned page; - unsigned usage; - char *description; -}; - -static const struct hid_usage_entry hid_usage_table[] = { - { 0, 0, "Undefined" }, - { 1, 0, "GenericDesktop" }, - {0, 0x01, "Pointer"}, - {0, 0x02, "Mouse"}, - {0, 0x04, "Joystick"}, - {0, 0x05, "GamePad"}, - {0, 0x06, "Keyboard"}, - {0, 0x07, "Keypad"}, - {0, 0x08, "MultiAxis"}, - {0, 0x30, "X"}, - {0, 0x31, "Y"}, - {0, 0x32, "Z"}, - {0, 0x33, "Rx"}, - {0, 0x34, "Ry"}, - {0, 0x35, "Rz"}, - {0, 0x36, "Slider"}, - {0, 0x37, "Dial"}, - {0, 0x38, "Wheel"}, - {0, 0x39, "HatSwitch"}, - {0, 0x3a, "CountedBuffer"}, - {0, 0x3b, "ByteCount"}, - {0, 0x3c, "MotionWakeup"}, - {0, 0x3d, "Start"}, - {0, 0x3e, "Select"}, - {0, 0x40, "Vx"}, - {0, 0x41, "Vy"}, - {0, 0x42, "Vz"}, - {0, 0x43, "Vbrx"}, - {0, 0x44, "Vbry"}, - {0, 0x45, "Vbrz"}, - {0, 0x46, "Vno"}, - {0, 0x80, "SystemControl"}, - {0, 0x81, "SystemPowerDown"}, - {0, 0x82, "SystemSleep"}, - {0, 0x83, "SystemWakeUp"}, - {0, 0x84, "SystemContextMenu"}, - {0, 0x85, "SystemMainMenu"}, - {0, 0x86, "SystemAppMenu"}, - {0, 0x87, "SystemMenuHelp"}, - {0, 0x88, "SystemMenuExit"}, - {0, 0x89, "SystemMenuSelect"}, - {0, 0x8a, "SystemMenuRight"}, - {0, 0x8b, "SystemMenuLeft"}, - {0, 0x8c, "SystemMenuUp"}, - {0, 0x8d, "SystemMenuDown"}, - {0, 0x90, "D-PadUp"}, - {0, 0x91, "D-PadDown"}, - {0, 0x92, "D-PadRight"}, - {0, 0x93, "D-PadLeft"}, - { 2, 0, "Simulation" }, - {0, 0xb0, "Aileron"}, - {0, 0xb1, "AileronTrim"}, - {0, 0xb2, "Anti-Torque"}, - {0, 0xb3, "Autopilot"}, - {0, 0xb4, "Chaff"}, - {0, 0xb5, "Collective"}, - {0, 0xb6, "DiveBrake"}, - {0, 0xb7, "ElectronicCountermeasures"}, - {0, 0xb8, "Elevator"}, - {0, 0xb9, "ElevatorTrim"}, - {0, 0xba, "Rudder"}, - {0, 0xbb, "Throttle"}, - {0, 0xbc, "FlightCommunications"}, - {0, 0xbd, "FlareRelease"}, - {0, 0xbe, "LandingGear"}, - {0, 0xbf, "ToeBrake"}, - { 7, 0, "Keyboard" }, - { 8, 0, "LED" }, - {0, 0x01, "NumLock"}, - {0, 0x02, "CapsLock"}, - {0, 0x03, "ScrollLock"}, - {0, 0x04, "Compose"}, - {0, 0x05, "Kana"}, - {0, 0x4b, "GenericIndicator"}, - { 9, 0, "Button" }, - { 10, 0, "Ordinal" }, - { 12, 0, "Consumer" }, - {0, 0x238, "HorizontalWheel"}, - { 13, 0, "Digitizers" }, - {0, 0x01, "Digitizer"}, - {0, 0x02, "Pen"}, - {0, 0x03, "LightPen"}, - {0, 0x04, "TouchScreen"}, - {0, 0x05, "TouchPad"}, - {0, 0x20, "Stylus"}, - {0, 0x21, "Puck"}, - {0, 0x22, "Finger"}, - {0, 0x30, "TipPressure"}, - {0, 0x31, "BarrelPressure"}, - {0, 0x32, "InRange"}, - {0, 0x33, "Touch"}, - {0, 0x34, "UnTouch"}, - {0, 0x35, "Tap"}, - {0, 0x39, "TabletFunctionKey"}, - {0, 0x3a, "ProgramChangeKey"}, - {0, 0x3c, "Invert"}, - {0, 0x42, "TipSwitch"}, - {0, 0x43, "SecondaryTipSwitch"}, - {0, 0x44, "BarrelSwitch"}, - {0, 0x45, "Eraser"}, - {0, 0x46, "TabletPick"}, - { 15, 0, "PhysicalInterfaceDevice" }, - {0, 0x00, "Undefined"}, - {0, 0x01, "Physical_Interface_Device"}, - {0, 0x20, "Normal"}, - {0, 0x21, "Set_Effect_Report"}, - {0, 0x22, "Effect_Block_Index"}, - {0, 0x23, "Parameter_Block_Offset"}, - {0, 0x24, "ROM_Flag"}, - {0, 0x25, "Effect_Type"}, - {0, 0x26, "ET_Constant_Force"}, - {0, 0x27, "ET_Ramp"}, - {0, 0x28, "ET_Custom_Force_Data"}, - {0, 0x30, "ET_Square"}, - {0, 0x31, "ET_Sine"}, - {0, 0x32, "ET_Triangle"}, - {0, 0x33, "ET_Sawtooth_Up"}, - {0, 0x34, "ET_Sawtooth_Down"}, - {0, 0x40, "ET_Spring"}, - {0, 0x41, "ET_Damper"}, - {0, 0x42, "ET_Inertia"}, - {0, 0x43, "ET_Friction"}, - {0, 0x50, "Duration"}, - {0, 0x51, "Sample_Period"}, - {0, 0x52, "Gain"}, - {0, 0x53, "Trigger_Button"}, - {0, 0x54, "Trigger_Repeat_Interval"}, - {0, 0x55, "Axes_Enable"}, - {0, 0x56, "Direction_Enable"}, - {0, 0x57, "Direction"}, - {0, 0x58, "Type_Specific_Block_Offset"}, - {0, 0x59, "Block_Type"}, - {0, 0x5A, "Set_Envelope_Report"}, - {0, 0x5B, "Attack_Level"}, - {0, 0x5C, "Attack_Time"}, - {0, 0x5D, "Fade_Level"}, - {0, 0x5E, "Fade_Time"}, - {0, 0x5F, "Set_Condition_Report"}, - {0, 0x60, "CP_Offset"}, - {0, 0x61, "Positive_Coefficient"}, - {0, 0x62, "Negative_Coefficient"}, - {0, 0x63, "Positive_Saturation"}, - {0, 0x64, "Negative_Saturation"}, - {0, 0x65, "Dead_Band"}, - {0, 0x66, "Download_Force_Sample"}, - {0, 0x67, "Isoch_Custom_Force_Enable"}, - {0, 0x68, "Custom_Force_Data_Report"}, - {0, 0x69, "Custom_Force_Data"}, - {0, 0x6A, "Custom_Force_Vendor_Defined_Data"}, - {0, 0x6B, "Set_Custom_Force_Report"}, - {0, 0x6C, "Custom_Force_Data_Offset"}, - {0, 0x6D, "Sample_Count"}, - {0, 0x6E, "Set_Periodic_Report"}, - {0, 0x6F, "Offset"}, - {0, 0x70, "Magnitude"}, - {0, 0x71, "Phase"}, - {0, 0x72, "Period"}, - {0, 0x73, "Set_Constant_Force_Report"}, - {0, 0x74, "Set_Ramp_Force_Report"}, - {0, 0x75, "Ramp_Start"}, - {0, 0x76, "Ramp_End"}, - {0, 0x77, "Effect_Operation_Report"}, - {0, 0x78, "Effect_Operation"}, - {0, 0x79, "Op_Effect_Start"}, - {0, 0x7A, "Op_Effect_Start_Solo"}, - {0, 0x7B, "Op_Effect_Stop"}, - {0, 0x7C, "Loop_Count"}, - {0, 0x7D, "Device_Gain_Report"}, - {0, 0x7E, "Device_Gain"}, - {0, 0x7F, "PID_Pool_Report"}, - {0, 0x80, "RAM_Pool_Size"}, - {0, 0x81, "ROM_Pool_Size"}, - {0, 0x82, "ROM_Effect_Block_Count"}, - {0, 0x83, "Simultaneous_Effects_Max"}, - {0, 0x84, "Pool_Alignment"}, - {0, 0x85, "PID_Pool_Move_Report"}, - {0, 0x86, "Move_Source"}, - {0, 0x87, "Move_Destination"}, - {0, 0x88, "Move_Length"}, - {0, 0x89, "PID_Block_Load_Report"}, - {0, 0x8B, "Block_Load_Status"}, - {0, 0x8C, "Block_Load_Success"}, - {0, 0x8D, "Block_Load_Full"}, - {0, 0x8E, "Block_Load_Error"}, - {0, 0x8F, "Block_Handle"}, - {0, 0x90, "PID_Block_Free_Report"}, - {0, 0x91, "Type_Specific_Block_Handle"}, - {0, 0x92, "PID_State_Report"}, - {0, 0x94, "Effect_Playing"}, - {0, 0x95, "PID_Device_Control_Report"}, - {0, 0x96, "PID_Device_Control"}, - {0, 0x97, "DC_Enable_Actuators"}, - {0, 0x98, "DC_Disable_Actuators"}, - {0, 0x99, "DC_Stop_All_Effects"}, - {0, 0x9A, "DC_Device_Reset"}, - {0, 0x9B, "DC_Device_Pause"}, - {0, 0x9C, "DC_Device_Continue"}, - {0, 0x9F, "Device_Paused"}, - {0, 0xA0, "Actuators_Enabled"}, - {0, 0xA4, "Safety_Switch"}, - {0, 0xA5, "Actuator_Override_Switch"}, - {0, 0xA6, "Actuator_Power"}, - {0, 0xA7, "Start_Delay"}, - {0, 0xA8, "Parameter_Block_Size"}, - {0, 0xA9, "Device_Managed_Pool"}, - {0, 0xAA, "Shared_Parameter_Blocks"}, - {0, 0xAB, "Create_New_Effect_Report"}, - {0, 0xAC, "RAM_Pool_Available"}, - { 0x84, 0, "Power Device" }, - { 0x84, 0x02, "PresentStatus" }, - { 0x84, 0x03, "ChangeStatus" }, - { 0x84, 0x04, "UPS" }, - { 0x84, 0x05, "PowerSupply" }, - { 0x84, 0x10, "BatterySystem" }, - { 0x84, 0x11, "BatterySystemID" }, - { 0x84, 0x12, "Battery" }, - { 0x84, 0x13, "BatteryID" }, - { 0x84, 0x14, "Charger" }, - { 0x84, 0x15, "ChargerID" }, - { 0x84, 0x16, "PowerConverter" }, - { 0x84, 0x17, "PowerConverterID" }, - { 0x84, 0x18, "OutletSystem" }, - { 0x84, 0x19, "OutletSystemID" }, - { 0x84, 0x1a, "Input" }, - { 0x84, 0x1b, "InputID" }, - { 0x84, 0x1c, "Output" }, - { 0x84, 0x1d, "OutputID" }, - { 0x84, 0x1e, "Flow" }, - { 0x84, 0x1f, "FlowID" }, - { 0x84, 0x20, "Outlet" }, - { 0x84, 0x21, "OutletID" }, - { 0x84, 0x22, "Gang" }, - { 0x84, 0x24, "PowerSummary" }, - { 0x84, 0x25, "PowerSummaryID" }, - { 0x84, 0x30, "Voltage" }, - { 0x84, 0x31, "Current" }, - { 0x84, 0x32, "Frequency" }, - { 0x84, 0x33, "ApparentPower" }, - { 0x84, 0x35, "PercentLoad" }, - { 0x84, 0x40, "ConfigVoltage" }, - { 0x84, 0x41, "ConfigCurrent" }, - { 0x84, 0x43, "ConfigApparentPower" }, - { 0x84, 0x53, "LowVoltageTransfer" }, - { 0x84, 0x54, "HighVoltageTransfer" }, - { 0x84, 0x56, "DelayBeforeStartup" }, - { 0x84, 0x57, "DelayBeforeShutdown" }, - { 0x84, 0x58, "Test" }, - { 0x84, 0x5a, "AudibleAlarmControl" }, - { 0x84, 0x60, "Present" }, - { 0x84, 0x61, "Good" }, - { 0x84, 0x62, "InternalFailure" }, - { 0x84, 0x65, "Overload" }, - { 0x84, 0x66, "OverCharged" }, - { 0x84, 0x67, "OverTemperature" }, - { 0x84, 0x68, "ShutdownRequested" }, - { 0x84, 0x69, "ShutdownImminent" }, - { 0x84, 0x6b, "SwitchOn/Off" }, - { 0x84, 0x6c, "Switchable" }, - { 0x84, 0x6d, "Used" }, - { 0x84, 0x6e, "Boost" }, - { 0x84, 0x73, "CommunicationLost" }, - { 0x84, 0xfd, "iManufacturer" }, - { 0x84, 0xfe, "iProduct" }, - { 0x84, 0xff, "iSerialNumber" }, - { 0x85, 0, "Battery System" }, - { 0x85, 0x01, "SMBBatteryMode" }, - { 0x85, 0x02, "SMBBatteryStatus" }, - { 0x85, 0x03, "SMBAlarmWarning" }, - { 0x85, 0x04, "SMBChargerMode" }, - { 0x85, 0x05, "SMBChargerStatus" }, - { 0x85, 0x06, "SMBChargerSpecInfo" }, - { 0x85, 0x07, "SMBSelectorState" }, - { 0x85, 0x08, "SMBSelectorPresets" }, - { 0x85, 0x09, "SMBSelectorInfo" }, - { 0x85, 0x29, "RemainingCapacityLimit" }, - { 0x85, 0x2c, "CapacityMode" }, - { 0x85, 0x42, "BelowRemainingCapacityLimit" }, - { 0x85, 0x44, "Charging" }, - { 0x85, 0x45, "Discharging" }, - { 0x85, 0x4b, "NeedReplacement" }, - { 0x85, 0x66, "RemainingCapacity" }, - { 0x85, 0x68, "RunTimeToEmpty" }, - { 0x85, 0x6a, "AverageTimeToFull" }, - { 0x85, 0x83, "DesignCapacity" }, - { 0x85, 0x85, "ManufacturerDate" }, - { 0x85, 0x89, "iDeviceChemistry" }, - { 0x85, 0x8b, "Rechargable" }, - { 0x85, 0x8f, "iOEMInformation" }, - { 0x85, 0x8d, "CapacityGranularity1" }, - { 0x85, 0xd0, "ACPresent" }, - /* pages 0xff00 to 0xffff are vendor-specific */ - { 0xffff, 0, "Vendor-specific-FF" }, - { 0, 0, NULL } -}; - -static void resolv_usage_page(unsigned page) { - const struct hid_usage_entry *p; - - for (p = hid_usage_table; p->description; p++) - if (p->page == page) { - printk("%s", p->description); - return; - } - printk("%04x", page); -} - -static void resolv_usage(unsigned usage) { - const struct hid_usage_entry *p; - - resolv_usage_page(usage >> 16); - printk("."); - for (p = hid_usage_table; p->description; p++) - if (p->page == (usage >> 16)) { - for(++p; p->description && p->usage != 0; p++) - if (p->usage == (usage & 0xffff)) { - printk("%s", p->description); - return; - } - break; - } - printk("%04x", usage & 0xffff); -} - -__inline__ static void tab(int n) { - while (n--) printk(" "); -} - -static void hid_dump_field(struct hid_field *field, int n) { - int j; - - if (field->physical) { - tab(n); - printk("Physical("); - resolv_usage(field->physical); printk(")\n"); - } - if (field->logical) { - tab(n); - printk("Logical("); - resolv_usage(field->logical); printk(")\n"); - } - tab(n); printk("Usage(%d)\n", field->maxusage); - for (j = 0; j < field->maxusage; j++) { - tab(n+2);resolv_usage(field->usage[j].hid); printk("\n"); - } - if (field->logical_minimum != field->logical_maximum) { - tab(n); printk("Logical Minimum(%d)\n", field->logical_minimum); - tab(n); printk("Logical Maximum(%d)\n", field->logical_maximum); - } - if (field->physical_minimum != field->physical_maximum) { - tab(n); printk("Physical Minimum(%d)\n", field->physical_minimum); - tab(n); printk("Physical Maximum(%d)\n", field->physical_maximum); - } - if (field->unit_exponent) { - tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent); - } - if (field->unit) { - char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" }; - char *units[5][8] = { - { "None", "None", "None", "None", "None", "None", "None", "None" }, - { "None", "Centimeter", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" }, - { "None", "Radians", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" }, - { "None", "Inch", "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" }, - { "None", "Degrees", "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" } - }; - - int i; - int sys; - __u32 data = field->unit; - - /* First nibble tells us which system we're in. */ - sys = data & 0xf; - data >>= 4; - - if(sys > 4) { - tab(n); printk("Unit(Invalid)\n"); - } - else { - int earlier_unit = 0; - - tab(n); printk("Unit(%s : ", systems[sys]); - - for (i=1 ; i<sizeof(__u32)*2 ; i++) { - char nibble = data & 0xf; - data >>= 4; - if (nibble != 0) { - if(earlier_unit++ > 0) - printk("*"); - printk("%s", units[sys][i]); - if(nibble != 1) { - /* This is a _signed_ nibble(!) */ - - int val = nibble & 0x7; - if(nibble & 0x08) - val = -((0x7 & ~val) +1); - printk("^%d", val); - } - } - } - printk(")\n"); - } - } - tab(n); printk("Report Size(%u)\n", field->report_size); - tab(n); printk("Report Count(%u)\n", field->report_count); - tab(n); printk("Report Offset(%u)\n", field->report_offset); - - tab(n); printk("Flags( "); - j = field->flags; - printk("%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : ""); - printk("%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array "); - printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute "); - printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : ""); - printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : ""); - printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPrefferedState " : ""); - printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : ""); - printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : ""); - printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : ""); - printk(")\n"); -} - -static void __attribute__((unused)) hid_dump_device(struct hid_device *device) { - struct hid_report_enum *report_enum; - struct hid_report *report; - struct list_head *list; - unsigned i,k; - static char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; - - for (i = 0; i < HID_REPORT_TYPES; i++) { - report_enum = device->report_enum + i; - list = report_enum->report_list.next; - while (list != &report_enum->report_list) { - report = (struct hid_report *) list; - tab(2); - printk("%s", table[i]); - if (report->id) - printk("(%d)", report->id); - printk("[%s]", table[report->type]); - printk("\n"); - for (k = 0; k < report->maxfield; k++) { - tab(4); - printk("Field(%d)\n", k); - hid_dump_field(report->field[k], 6); - } - list = list->next; - } - } -} - -static void __attribute__((unused)) hid_dump_input(struct hid_usage *usage, __s32 value) { - printk("hid-debug: input "); - resolv_usage(usage->hid); - printk(" = %d\n", value); -} - - -static char *events[EV_MAX + 1] = { - [EV_SYN] = "Sync", [EV_KEY] = "Key", - [EV_REL] = "Relative", [EV_ABS] = "Absolute", - [EV_MSC] = "Misc", [EV_LED] = "LED", - [EV_SND] = "Sound", [EV_REP] = "Repeat", - [EV_FF] = "ForceFeedback", [EV_PWR] = "Power", - [EV_FF_STATUS] = "ForceFeedbackStatus", -}; - -static char *syncs[2] = { - [SYN_REPORT] = "Report", [SYN_CONFIG] = "Config", -}; -static char *keys[KEY_MAX + 1] = { - [KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc", - [KEY_1] = "1", [KEY_2] = "2", - [KEY_3] = "3", [KEY_4] = "4", - [KEY_5] = "5", [KEY_6] = "6", - [KEY_7] = "7", [KEY_8] = "8", - [KEY_9] = "9", [KEY_0] = "0", - [KEY_MINUS] = "Minus", [KEY_EQUAL] = "Equal", - [KEY_BACKSPACE] = "Backspace", [KEY_TAB] = "Tab", - [KEY_Q] = "Q", [KEY_W] = "W", - [KEY_E] = "E", [KEY_R] = "R", - [KEY_T] = "T", [KEY_Y] = "Y", - [KEY_U] = "U", [KEY_I] = "I", - [KEY_O] = "O", [KEY_P] = "P", - [KEY_LEFTBRACE] = "LeftBrace", [KEY_RIGHTBRACE] = "RightBrace", - [KEY_ENTER] = "Enter", [KEY_LEFTCTRL] = "LeftControl", - [KEY_A] = "A", [KEY_S] = "S", - [KEY_D] = "D", [KEY_F] = "F", - [KEY_G] = "G", [KEY_H] = "H", - [KEY_J] = "J", [KEY_K] = "K", - [KEY_L] = "L", [KEY_SEMICOLON] = "Semicolon", - [KEY_APOSTROPHE] = "Apostrophe", [KEY_GRAVE] = "Grave", - [KEY_LEFTSHIFT] = "LeftShift", [KEY_BACKSLASH] = "BackSlash", - [KEY_Z] = "Z", [KEY_X] = "X", - [KEY_C] = "C", [KEY_V] = "V", - [KEY_B] = "B", [KEY_N] = "N", - [KEY_M] = "M", [KEY_COMMA] = "Comma", - [KEY_DOT] = "Dot", [KEY_SLASH] = "Slash", - [KEY_RIGHTSHIFT] = "RightShift", [KEY_KPASTERISK] = "KPAsterisk", - [KEY_LEFTALT] = "LeftAlt", [KEY_SPACE] = "Space", - [KEY_CAPSLOCK] = "CapsLock", [KEY_F1] = "F1", - [KEY_F2] = "F2", [KEY_F3] = "F3", - [KEY_F4] = "F4", [KEY_F5] = "F5", - [KEY_F6] = "F6", [KEY_F7] = "F7", - [KEY_F8] = "F8", [KEY_F9] = "F9", - [KEY_F10] = "F10", [KEY_NUMLOCK] = "NumLock", - [KEY_SCROLLLOCK] = "ScrollLock", [KEY_KP7] = "KP7", - [KEY_KP8] = "KP8", [KEY_KP9] = "KP9", - [KEY_KPMINUS] = "KPMinus", [KEY_KP4] = "KP4", - [KEY_KP5] = "KP5", [KEY_KP6] = "KP6", - [KEY_KPPLUS] = "KPPlus", [KEY_KP1] = "KP1", - [KEY_KP2] = "KP2", [KEY_KP3] = "KP3", - [KEY_KP0] = "KP0", [KEY_KPDOT] = "KPDot", - [KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd", - [KEY_F11] = "F11", [KEY_F12] = "F12", - [KEY_RO] = "RO", [KEY_KATAKANA] = "Katakana", - [KEY_HIRAGANA] = "HIRAGANA", [KEY_HENKAN] = "Henkan", - [KEY_KATAKANAHIRAGANA] = "Katakana/Hiragana", [KEY_MUHENKAN] = "Muhenkan", - [KEY_KPJPCOMMA] = "KPJpComma", [KEY_KPENTER] = "KPEnter", - [KEY_RIGHTCTRL] = "RightCtrl", [KEY_KPSLASH] = "KPSlash", - [KEY_SYSRQ] = "SysRq", [KEY_RIGHTALT] = "RightAlt", - [KEY_LINEFEED] = "LineFeed", [KEY_HOME] = "Home", - [KEY_UP] = "Up", [KEY_PAGEUP] = "PageUp", - [KEY_LEFT] = "Left", [KEY_RIGHT] = "Right", - [KEY_END] = "End", [KEY_DOWN] = "Down", - [KEY_PAGEDOWN] = "PageDown", [KEY_INSERT] = "Insert", - [KEY_DELETE] = "Delete", [KEY_MACRO] = "Macro", - [KEY_MUTE] = "Mute", [KEY_VOLUMEDOWN] = "VolumeDown", - [KEY_VOLUMEUP] = "VolumeUp", [KEY_POWER] = "Power", - [KEY_KPEQUAL] = "KPEqual", [KEY_KPPLUSMINUS] = "KPPlusMinus", - [KEY_PAUSE] = "Pause", [KEY_KPCOMMA] = "KPComma", - [KEY_HANGUEL] = "Hangeul", [KEY_HANJA] = "Hanja", - [KEY_YEN] = "Yen", [KEY_LEFTMETA] = "LeftMeta", - [KEY_RIGHTMETA] = "RightMeta", [KEY_COMPOSE] = "Compose", - [KEY_STOP] = "Stop", [KEY_AGAIN] = "Again", - [KEY_PROPS] = "Props", [KEY_UNDO] = "Undo", - [KEY_FRONT] = "Front", [KEY_COPY] = "Copy", - [KEY_OPEN] = "Open", [KEY_PASTE] = "Paste", - [KEY_FIND] = "Find", [KEY_CUT] = "Cut", - [KEY_HELP] = "Help", [KEY_MENU] = "Menu", - [KEY_CALC] = "Calc", [KEY_SETUP] = "Setup", - [KEY_SLEEP] = "Sleep", [KEY_WAKEUP] = "WakeUp", - [KEY_FILE] = "File", [KEY_SENDFILE] = "SendFile", - [KEY_DELETEFILE] = "DeleteFile", [KEY_XFER] = "X-fer", - [KEY_PROG1] = "Prog1", [KEY_PROG2] = "Prog2", - [KEY_WWW] = "WWW", [KEY_MSDOS] = "MSDOS", - [KEY_COFFEE] = "Coffee", [KEY_DIRECTION] = "Direction", - [KEY_CYCLEWINDOWS] = "CycleWindows", [KEY_MAIL] = "Mail", - [KEY_BOOKMARKS] = "Bookmarks", [KEY_COMPUTER] = "Computer", - [KEY_BACK] = "Back", [KEY_FORWARD] = "Forward", - [KEY_CLOSECD] = "CloseCD", [KEY_EJECTCD] = "EjectCD", - [KEY_EJECTCLOSECD] = "EjectCloseCD", [KEY_NEXTSONG] = "NextSong", - [KEY_PLAYPAUSE] = "PlayPause", [KEY_PREVIOUSSONG] = "PreviousSong", - [KEY_STOPCD] = "StopCD", [KEY_RECORD] = "Record", - [KEY_REWIND] = "Rewind", [KEY_PHONE] = "Phone", - [KEY_ISO] = "ISOKey", [KEY_CONFIG] = "Config", - [KEY_HOMEPAGE] = "HomePage", [KEY_REFRESH] = "Refresh", - [KEY_EXIT] = "Exit", [KEY_MOVE] = "Move", - [KEY_EDIT] = "Edit", [KEY_SCROLLUP] = "ScrollUp", - [KEY_SCROLLDOWN] = "ScrollDown", [KEY_KPLEFTPAREN] = "KPLeftParenthesis", - [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_NEW] = "New", - [KEY_REDO] = "Redo", [KEY_F13] = "F13", - [KEY_F14] = "F14", [KEY_F15] = "F15", - [KEY_F16] = "F16", [KEY_F17] = "F17", - [KEY_F18] = "F18", [KEY_F19] = "F19", - [KEY_F20] = "F20", [KEY_F21] = "F21", - [KEY_F22] = "F22", [KEY_F23] = "F23", - [KEY_F24] = "F24", [KEY_PLAYCD] = "PlayCD", - [KEY_PAUSECD] = "PauseCD", [KEY_PROG3] = "Prog3", - [KEY_PROG4] = "Prog4", [KEY_SUSPEND] = "Suspend", - [KEY_CLOSE] = "Close", [KEY_PLAY] = "Play", - [KEY_FASTFORWARD] = "FastForward", [KEY_BASSBOOST] = "BassBoost", - [KEY_PRINT] = "Print", [KEY_HP] = "HP", - [KEY_CAMERA] = "Camera", [KEY_SOUND] = "Sound", - [KEY_QUESTION] = "Question", [KEY_EMAIL] = "Email", - [KEY_CHAT] = "Chat", [KEY_SEARCH] = "Search", - [KEY_CONNECT] = "Connect", [KEY_FINANCE] = "Finance", - [KEY_SPORT] = "Sport", [KEY_SHOP] = "Shop", - [KEY_ALTERASE] = "AlternateErase", [KEY_CANCEL] = "Cancel", - [KEY_BRIGHTNESSDOWN] = "BrightnessDown", [KEY_BRIGHTNESSUP] = "BrightnessUp", - [KEY_MEDIA] = "Media", [KEY_UNKNOWN] = "Unknown", - [BTN_0] = "Btn0", [BTN_1] = "Btn1", - [BTN_2] = "Btn2", [BTN_3] = "Btn3", - [BTN_4] = "Btn4", [BTN_5] = "Btn5", - [BTN_6] = "Btn6", [BTN_7] = "Btn7", - [BTN_8] = "Btn8", [BTN_9] = "Btn9", - [BTN_LEFT] = "LeftBtn", [BTN_RIGHT] = "RightBtn", - [BTN_MIDDLE] = "MiddleBtn", [BTN_SIDE] = "SideBtn", - [BTN_EXTRA] = "ExtraBtn", [BTN_FORWARD] = "ForwardBtn", - [BTN_BACK] = "BackBtn", [BTN_TASK] = "TaskBtn", - [BTN_TRIGGER] = "Trigger", [BTN_THUMB] = "ThumbBtn", - [BTN_THUMB2] = "ThumbBtn2", [BTN_TOP] = "TopBtn", - [BTN_TOP2] = "TopBtn2", [BTN_PINKIE] = "PinkieBtn", - [BTN_BASE] = "BaseBtn", [BTN_BASE2] = "BaseBtn2", - [BTN_BASE3] = "BaseBtn3", [BTN_BASE4] = "BaseBtn4", - [BTN_BASE5] = "BaseBtn5", [BTN_BASE6] = "BaseBtn6", - [BTN_DEAD] = "BtnDead", [BTN_A] = "BtnA", - [BTN_B] = "BtnB", [BTN_C] = "BtnC", - [BTN_X] = "BtnX", [BTN_Y] = "BtnY", - [BTN_Z] = "BtnZ", [BTN_TL] = "BtnTL", - [BTN_TR] = "BtnTR", [BTN_TL2] = "BtnTL2", - [BTN_TR2] = "BtnTR2", [BTN_SELECT] = "BtnSelect", - [BTN_START] = "BtnStart", [BTN_MODE] = "BtnMode", - [BTN_THUMBL] = "BtnThumbL", [BTN_THUMBR] = "BtnThumbR", - [BTN_TOOL_PEN] = "ToolPen", [BTN_TOOL_RUBBER] = "ToolRubber", - [BTN_TOOL_BRUSH] = "ToolBrush", [BTN_TOOL_PENCIL] = "ToolPencil", - [BTN_TOOL_AIRBRUSH] = "ToolAirbrush", [BTN_TOOL_FINGER] = "ToolFinger", - [BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens", - [BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus", - [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "ToolDoubleTap", - [BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_GEAR_DOWN] = "WheelBtn", - [BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok", - [KEY_SELECT] = "Select", [KEY_GOTO] = "Goto", - [KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2", - [KEY_OPTION] = "Option", [KEY_INFO] = "Info", - [KEY_TIME] = "Time", [KEY_VENDOR] = "Vendor", - [KEY_ARCHIVE] = "Archive", [KEY_PROGRAM] = "Program", - [KEY_CHANNEL] = "Channel", [KEY_FAVORITES] = "Favorites", - [KEY_EPG] = "EPG", [KEY_PVR] = "PVR", - [KEY_MHP] = "MHP", [KEY_LANGUAGE] = "Language", - [KEY_TITLE] = "Title", [KEY_SUBTITLE] = "Subtitle", - [KEY_ANGLE] = "Angle", [KEY_ZOOM] = "Zoom", - [KEY_MODE] = "Mode", [KEY_KEYBOARD] = "Keyboard", - [KEY_SCREEN] = "Screen", [KEY_PC] = "PC", - [KEY_TV] = "TV", [KEY_TV2] = "TV2", - [KEY_VCR] = "VCR", [KEY_VCR2] = "VCR2", - [KEY_SAT] = "Sat", [KEY_SAT2] = "Sat2", - [KEY_CD] = "CD", [KEY_TAPE] = "Tape", - [KEY_RADIO] = "Radio", [KEY_TUNER] = "Tuner", - [KEY_PLAYER] = "Player", [KEY_TEXT] = "Text", - [KEY_DVD] = "DVD", [KEY_AUX] = "Aux", - [KEY_MP3] = "MP3", [KEY_AUDIO] = "Audio", - [KEY_VIDEO] = "Video", [KEY_DIRECTORY] = "Directory", - [KEY_LIST] = "List", [KEY_MEMO] = "Memo", - [KEY_CALENDAR] = "Calendar", [KEY_RED] = "Red", - [KEY_GREEN] = "Green", [KEY_YELLOW] = "Yellow", - [KEY_BLUE] = "Blue", [KEY_CHANNELUP] = "ChannelUp", - [KEY_CHANNELDOWN] = "ChannelDown", [KEY_FIRST] = "First", - [KEY_LAST] = "Last", [KEY_AB] = "AB", - [KEY_NEXT] = "Next", [KEY_RESTART] = "Restart", - [KEY_SLOW] = "Slow", [KEY_SHUFFLE] = "Shuffle", - [KEY_BREAK] = "Break", [KEY_PREVIOUS] = "Previous", - [KEY_DIGITS] = "Digits", [KEY_TEEN] = "TEEN", - [KEY_TWEN] = "TWEN", [KEY_DEL_EOL] = "DeleteEOL", - [KEY_DEL_EOS] = "DeleteEOS", [KEY_INS_LINE] = "InsertLine", - [KEY_DEL_LINE] = "DeleteLine", - [KEY_SEND] = "Send", [KEY_REPLY] = "Reply", - [KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save", - [KEY_DOCUMENTS] = "Documents", - [KEY_FN] = "Fn", [KEY_FN_ESC] = "Fn+ESC", - [KEY_FN_1] = "Fn+1", [KEY_FN_2] = "Fn+2", - [KEY_FN_B] = "Fn+B", [KEY_FN_D] = "Fn+D", - [KEY_FN_E] = "Fn+E", [KEY_FN_F] = "Fn+F", - [KEY_FN_S] = "Fn+S", - [KEY_FN_F1] = "Fn+F1", [KEY_FN_F2] = "Fn+F2", - [KEY_FN_F3] = "Fn+F3", [KEY_FN_F4] = "Fn+F4", - [KEY_FN_F5] = "Fn+F5", [KEY_FN_F6] = "Fn+F6", - [KEY_FN_F7] = "Fn+F7", [KEY_FN_F8] = "Fn+F8", - [KEY_FN_F9] = "Fn+F9", [KEY_FN_F10] = "Fn+F10", - [KEY_FN_F11] = "Fn+F11", [KEY_FN_F12] = "Fn+F12", - [KEY_KBDILLUMTOGGLE] = "KbdIlluminationToggle", - [KEY_KBDILLUMDOWN] = "KbdIlluminationDown", - [KEY_KBDILLUMUP] = "KbdIlluminationUp", - [KEY_SWITCHVIDEOMODE] = "SwitchVideoMode", -}; - -static char *relatives[REL_MAX + 1] = { - [REL_X] = "X", [REL_Y] = "Y", - [REL_Z] = "Z", [REL_HWHEEL] = "HWheel", - [REL_DIAL] = "Dial", [REL_WHEEL] = "Wheel", - [REL_MISC] = "Misc", -}; - -static char *absolutes[ABS_MAX + 1] = { - [ABS_X] = "X", [ABS_Y] = "Y", - [ABS_Z] = "Z", [ABS_RX] = "Rx", - [ABS_RY] = "Ry", [ABS_RZ] = "Rz", - [ABS_THROTTLE] = "Throttle", [ABS_RUDDER] = "Rudder", - [ABS_WHEEL] = "Wheel", [ABS_GAS] = "Gas", - [ABS_BRAKE] = "Brake", [ABS_HAT0X] = "Hat0X", - [ABS_HAT0Y] = "Hat0Y", [ABS_HAT1X] = "Hat1X", - [ABS_HAT1Y] = "Hat1Y", [ABS_HAT2X] = "Hat2X", - [ABS_HAT2Y] = "Hat2Y", [ABS_HAT3X] = "Hat3X", - [ABS_HAT3Y] = "Hat 3Y", [ABS_PRESSURE] = "Pressure", - [ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt", - [ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "Tool Width", - [ABS_VOLUME] = "Volume", [ABS_MISC] = "Misc", -}; - -static char *misc[MSC_MAX + 1] = { - [MSC_SERIAL] = "Serial", [MSC_PULSELED] = "Pulseled", - [MSC_GESTURE] = "Gesture", [MSC_RAW] = "RawData" -}; - -static char *leds[LED_MAX + 1] = { - [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock", - [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose", - [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep", - [LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute", - [LED_MISC] = "Misc", -}; - -static char *repeats[REP_MAX + 1] = { - [REP_DELAY] = "Delay", [REP_PERIOD] = "Period" -}; - -static char *sounds[SND_MAX + 1] = { - [SND_CLICK] = "Click", [SND_BELL] = "Bell", - [SND_TONE] = "Tone" -}; - -static char **names[EV_MAX + 1] = { - [EV_SYN] = syncs, [EV_KEY] = keys, - [EV_REL] = relatives, [EV_ABS] = absolutes, - [EV_MSC] = misc, [EV_LED] = leds, - [EV_SND] = sounds, [EV_REP] = repeats, -}; - -static void __attribute__((unused)) resolv_event(__u8 type, __u16 code) { - - printk("%s.%s", events[type] ? events[type] : "?", - names[type] ? (names[type][code] ? names[type][code] : "?") : "?"); -} diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c deleted file mode 100644 index a8fc46c721c..00000000000 --- a/drivers/usb/input/hid-ff.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * $Id: hid-ff.c,v 1.2 2002/04/18 22:02:47 jdeneux Exp $ - * - * Force feedback support for hid devices. - * Not all hid devices use the same protocol. For example, some use PID, - * other use their own proprietary procotol. - * - * Copyright (c) 2002-2004 Johann Deneux - */ - -/* - * 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 - * - * Should you need to contact me, the author, you can do so by - * e-mail - mail your message to <johann.deneux@it.uu.se> - */ - -#include <linux/input.h> - -#undef DEBUG -#include <linux/usb.h> - -#include "hid.h" - -/* - * This table contains pointers to initializers. To add support for new - * devices, you need to add the USB vendor and product ids here. - */ -struct hid_ff_initializer { - u16 idVendor; - u16 idProduct; - int (*init)(struct hid_device*); -}; - -/* - * We try pidff when no other driver is found because PID is the - * standards compliant way of implementing force feedback in HID. - * pidff_init() will quickly abort if the device doesn't appear to - * be a PID device - */ -static struct hid_ff_initializer inits[] = { -#ifdef CONFIG_LOGITECH_FF - { 0x46d, 0xc211, hid_lgff_init }, /* Logitech Cordless rumble pad */ - { 0x46d, 0xc283, hid_lgff_init }, /* Logitech Wingman Force 3d */ - { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */ - { 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */ -#endif -#ifdef CONFIG_THRUSTMASTER_FF - { 0x44f, 0xb304, hid_tmff_init }, -#endif -#ifdef CONFIG_ZEROPLUS_FF - { 0xc12, 0x0005, hid_zpff_init }, - { 0xc12, 0x0030, hid_zpff_init }, -#endif - { 0, 0, hid_pidff_init} /* Matches anything */ -}; - -int hid_ff_init(struct hid_device* hid) -{ - struct hid_ff_initializer *init; - int vendor = le16_to_cpu(hid->dev->descriptor.idVendor); - int product = le16_to_cpu(hid->dev->descriptor.idProduct); - - for (init = inits; init->idVendor; init++) - if (init->idVendor == vendor && init->idProduct == product) - break; - - return init->init(hid); -} diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c deleted file mode 100644 index 3a7e5fbff02..00000000000 --- a/drivers/usb/input/hid-input.c +++ /dev/null @@ -1,872 +0,0 @@ -/* - * $Id: hid-input.c,v 1.2 2002/04/23 00:59:25 rdamazio Exp $ - * - * Copyright (c) 2000-2001 Vojtech Pavlik - * - * USB HID to Linux Input mapping - */ - -/* - * 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 - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/kernel.h> -#include <linux/usb/input.h> - -#undef DEBUG - -#include "hid.h" - -#define unk KEY_UNKNOWN - -static const unsigned char hid_keyboard[256] = { - 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, - 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, - 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, - 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, - 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, - 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, - 115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk, - 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, - unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, - unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, - unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, - unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, - 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, - 150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk -}; - -static const struct { - __s32 x; - __s32 y; -} hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; - -#define map_abs(c) do { usage->code = c; usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; } while (0) -#define map_rel(c) do { usage->code = c; usage->type = EV_REL; bit = input->relbit; max = REL_MAX; } while (0) -#define map_key(c) do { usage->code = c; usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; } while (0) -#define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0) - -#define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0) -#define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) - -#ifdef CONFIG_USB_HIDINPUT_POWERBOOK - -struct hidinput_key_translation { - u16 from; - u16 to; - u8 flags; -}; - -#define POWERBOOK_FLAG_FKEY 0x01 - -static struct hidinput_key_translation powerbook_fn_keys[] = { - { KEY_BACKSPACE, KEY_DELETE }, - { KEY_F1, KEY_BRIGHTNESSDOWN, POWERBOOK_FLAG_FKEY }, - { KEY_F2, KEY_BRIGHTNESSUP, POWERBOOK_FLAG_FKEY }, - { KEY_F3, KEY_MUTE, POWERBOOK_FLAG_FKEY }, - { KEY_F4, KEY_VOLUMEDOWN, POWERBOOK_FLAG_FKEY }, - { KEY_F5, KEY_VOLUMEUP, POWERBOOK_FLAG_FKEY }, - { KEY_F6, KEY_NUMLOCK, POWERBOOK_FLAG_FKEY }, - { KEY_F7, KEY_SWITCHVIDEOMODE, POWERBOOK_FLAG_FKEY }, - { KEY_F8, KEY_KBDILLUMTOGGLE, POWERBOOK_FLAG_FKEY }, - { KEY_F9, KEY_KBDILLUMDOWN, POWERBOOK_FLAG_FKEY }, - { KEY_F10, KEY_KBDILLUMUP, POWERBOOK_FLAG_FKEY }, - { KEY_UP, KEY_PAGEUP }, - { KEY_DOWN, KEY_PAGEDOWN }, - { KEY_LEFT, KEY_HOME }, - { KEY_RIGHT, KEY_END }, - { } -}; - -static struct hidinput_key_translation powerbook_numlock_keys[] = { - { KEY_J, KEY_KP1 }, - { KEY_K, KEY_KP2 }, - { KEY_L, KEY_KP3 }, - { KEY_U, KEY_KP4 }, - { KEY_I, KEY_KP5 }, - { KEY_O, KEY_KP6 }, - { KEY_7, KEY_KP7 }, - { KEY_8, KEY_KP8 }, - { KEY_9, KEY_KP9 }, - { KEY_M, KEY_KP0 }, - { KEY_DOT, KEY_KPDOT }, - { KEY_SLASH, KEY_KPPLUS }, - { KEY_SEMICOLON, KEY_KPMINUS }, - { KEY_P, KEY_KPASTERISK }, - { KEY_MINUS, KEY_KPEQUAL }, - { KEY_0, KEY_KPSLASH }, - { KEY_F6, KEY_NUMLOCK }, - { KEY_KPENTER, KEY_KPENTER }, - { KEY_BACKSPACE, KEY_BACKSPACE }, - { } -}; - -static struct hidinput_key_translation powerbook_iso_keyboard[] = { - { KEY_GRAVE, KEY_102ND }, - { KEY_102ND, KEY_GRAVE }, - { } -}; - -static int usbhid_pb_fnmode = 1; -module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644); -MODULE_PARM_DESC(pb_fnmode, - "Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)"); - -static struct hidinput_key_translation *find_translation(struct hidinput_key_translation *table, u16 from) -{ - struct hidinput_key_translation *trans; - - /* Look for the translation */ - for (trans = table; trans->from; trans++) - if (trans->from == from) - return trans; - - return NULL; -} - -static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, - struct hid_usage *usage, __s32 value) -{ - struct hidinput_key_translation *trans; - - if (usage->code == KEY_FN) { - if (value) hid->quirks |= HID_QUIRK_POWERBOOK_FN_ON; - else hid->quirks &= ~HID_QUIRK_POWERBOOK_FN_ON; - - input_event(input, usage->type, usage->code, value); - - return 1; - } - - if (usbhid_pb_fnmode) { - int do_translate; - - trans = find_translation(powerbook_fn_keys, usage->code); - if (trans) { - if (test_bit(usage->code, hid->pb_pressed_fn)) - do_translate = 1; - else if (trans->flags & POWERBOOK_FLAG_FKEY) - do_translate = - (usbhid_pb_fnmode == 2 && (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) || - (usbhid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)); - else - do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON); - - if (do_translate) { - if (value) - set_bit(usage->code, hid->pb_pressed_fn); - else - clear_bit(usage->code, hid->pb_pressed_fn); - - input_event(input, usage->type, trans->to, value); - - return 1; - } - } - - if (test_bit(usage->code, hid->pb_pressed_numlock) || - test_bit(LED_NUML, input->led)) { - trans = find_translation(powerbook_numlock_keys, usage->code); - - if (trans) { - if (value) - set_bit(usage->code, hid->pb_pressed_numlock); - else - clear_bit(usage->code, hid->pb_pressed_numlock); - - input_event(input, usage->type, trans->to, value); - } - - return 1; - } - } - - if (hid->quirks & HID_QUIRK_POWERBOOK_ISO_KEYBOARD) { - trans = find_translation(powerbook_iso_keyboard, usage->code); - if (trans) { - input_event(input, usage->type, trans->to, value); - return 1; - } - } - - return 0; -} - -static void hidinput_pb_setup(struct input_dev *input) -{ - struct hidinput_key_translation *trans; - - set_bit(KEY_NUMLOCK, input->keybit); - - /* Enable all needed keys */ - for (trans = powerbook_fn_keys; trans->from; trans++) - set_bit(trans->to, input->keybit); - - for (trans = powerbook_numlock_keys; trans->from; trans++) - set_bit(trans->to, input->keybit); - - for (trans = powerbook_iso_keyboard; trans->from; trans++) - set_bit(trans->to, input->keybit); -} -#else -static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, - struct hid_usage *usage, __s32 value) -{ - return 0; -} - -static inline void hidinput_pb_setup(struct input_dev *input) -{ -} -#endif - -static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, - struct hid_usage *usage) -{ - struct input_dev *input = hidinput->input; - struct hid_device *device = input->private; - int max = 0, code; - unsigned long *bit = NULL; - - field->hidinput = hidinput; - -#ifdef DEBUG - printk(KERN_DEBUG "Mapping: "); - resolv_usage(usage->hid); - printk(" ---> "); -#endif - - if (field->flags & HID_MAIN_ITEM_CONSTANT) - goto ignore; - - switch (usage->hid & HID_USAGE_PAGE) { - - case HID_UP_UNDEFINED: - goto ignore; - - case HID_UP_KEYBOARD: - - set_bit(EV_REP, input->evbit); - - if ((usage->hid & HID_USAGE) < 256) { - if (!hid_keyboard[usage->hid & HID_USAGE]) goto ignore; - map_key_clear(hid_keyboard[usage->hid & HID_USAGE]); - } else - map_key(KEY_UNKNOWN); - - break; - - case HID_UP_BUTTON: - - code = ((usage->hid - 1) & 0xf); - - switch (field->application) { - case HID_GD_MOUSE: - case HID_GD_POINTER: code += 0x110; break; - case HID_GD_JOYSTICK: code += 0x120; break; - case HID_GD_GAMEPAD: code += 0x130; break; - default: - switch (field->physical) { - case HID_GD_MOUSE: - case HID_GD_POINTER: code += 0x110; break; - case HID_GD_JOYSTICK: code += 0x120; break; - case HID_GD_GAMEPAD: code += 0x130; break; - default: code += 0x100; - } - } - - map_key(code); - break; - - - case HID_UP_SIMULATION: - - switch (usage->hid & 0xffff) { - case 0xba: map_abs(ABS_RUDDER); break; - case 0xbb: map_abs(ABS_THROTTLE); break; - case 0xc4: map_abs(ABS_GAS); break; - case 0xc5: map_abs(ABS_BRAKE); break; - case 0xc8: map_abs(ABS_WHEEL); break; - default: goto ignore; - } - break; - - case HID_UP_GENDESK: - - if ((usage->hid & 0xf0) == 0x80) { /* SystemControl */ - switch (usage->hid & 0xf) { - case 0x1: map_key_clear(KEY_POWER); break; - case 0x2: map_key_clear(KEY_SLEEP); break; - case 0x3: map_key_clear(KEY_WAKEUP); break; - default: goto unknown; - } - break; - } - - if ((usage->hid & 0xf0) == 0x90) { /* D-pad */ - switch (usage->hid) { - case HID_GD_UP: usage->hat_dir = 1; break; - case HID_GD_DOWN: usage->hat_dir = 5; break; - case HID_GD_RIGHT: usage->hat_dir = 3; break; - case HID_GD_LEFT: usage->hat_dir = 7; break; - default: goto unknown; - } - if (field->dpad) { - map_abs(field->dpad); - goto ignore; - } - map_abs(ABS_HAT0X); - break; - } - - switch (usage->hid) { - - /* These usage IDs map directly to the usage codes. */ - case HID_GD_X: case HID_GD_Y: case HID_GD_Z: - case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: - case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL: - if (field->flags & HID_MAIN_ITEM_RELATIVE) - map_rel(usage->hid & 0xf); - else - map_abs(usage->hid & 0xf); - break; - - case HID_GD_HATSWITCH: - usage->hat_min = field->logical_minimum; - usage->hat_max = field->logical_maximum; - map_abs(ABS_HAT0X); - break; - - case HID_GD_START: map_key_clear(BTN_START); break; - case HID_GD_SELECT: map_key_clear(BTN_SELECT); break; - - default: goto unknown; - } - - break; - - case HID_UP_LED: - if (((usage->hid - 1) & 0xffff) >= LED_MAX) - goto ignore; - map_led((usage->hid - 1) & 0xffff); - break; - - case HID_UP_DIGITIZER: - - switch (usage->hid & 0xff) { - - case 0x30: /* TipPressure */ - if (!test_bit(BTN_TOUCH, input->keybit)) { - device->quirks |= HID_QUIRK_NOTOUCH; - set_bit(EV_KEY, input->evbit); - set_bit(BTN_TOUCH, input->keybit); - } - - map_abs_clear(ABS_PRESSURE); - break; - - case 0x32: /* InRange */ - switch (field->physical & 0xff) { - case 0x21: map_key(BTN_TOOL_MOUSE); break; - case 0x22: map_key(BTN_TOOL_FINGER); break; - default: map_key(BTN_TOOL_PEN); break; - } - break; - - case 0x3c: /* Invert */ - map_key_clear(BTN_TOOL_RUBBER); - break; - - case 0x33: /* Touch */ - case 0x42: /* TipSwitch */ - case 0x43: /* TipSwitch2 */ - device->quirks &= ~HID_QUIRK_NOTOUCH; - map_key_clear(BTN_TOUCH); - break; - - case 0x44: /* BarrelSwitch */ - map_key_clear(BTN_STYLUS); - break; - - default: goto unknown; - } - break; - - case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */ - - switch (usage->hid & HID_USAGE) { - case 0x000: goto ignore; - case 0x034: map_key_clear(KEY_SLEEP); break; - case 0x036: map_key_clear(BTN_MISC); break; - case 0x045: map_key_clear(KEY_RADIO); break; - case 0x08a: map_key_clear(KEY_WWW); break; - case 0x08d: map_key_clear(KEY_PROGRAM); break; - case 0x095: map_key_clear(KEY_HELP); break; - case 0x09c: map_key_clear(KEY_CHANNELUP); break; - case 0x09d: map_key_clear(KEY_CHANNELDOWN); break; - case 0x0b0: map_key_clear(KEY_PLAY); break; - case 0x0b1: map_key_clear(KEY_PAUSE); break; - case 0x0b2: map_key_clear(KEY_RECORD); break; - case 0x0b3: map_key_clear(KEY_FASTFORWARD); break; - case 0x0b4: map_key_clear(KEY_REWIND); break; - case 0x0b5: map_key_clear(KEY_NEXTSONG); break; - case 0x0b6: map_key_clear(KEY_PREVIOUSSONG); break; - case 0x0b7: map_key_clear(KEY_STOPCD); break; - case 0x0b8: map_key_clear(KEY_EJECTCD); break; - case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break; - case 0x0e0: map_abs_clear(ABS_VOLUME); break; - case 0x0e2: map_key_clear(KEY_MUTE); break; - case 0x0e5: map_key_clear(KEY_BASSBOOST); break; - case 0x0e9: map_key_clear(KEY_VOLUMEUP); break; - case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break; - case 0x183: map_key_clear(KEY_CONFIG); break; - case 0x18a: map_key_clear(KEY_MAIL); break; - case 0x192: map_key_clear(KEY_CALC); break; - case 0x194: map_key_clear(KEY_FILE); break; - case 0x1a7: map_key_clear(KEY_DOCUMENTS); break; - case 0x201: map_key_clear(KEY_NEW); break; - case 0x207: map_key_clear(KEY_SAVE); break; - case 0x208: map_key_clear(KEY_PRINT); break; - case 0x209: map_key_clear(KEY_PROPS); break; - case 0x21a: map_key_clear(KEY_UNDO); break; - case 0x21b: map_key_clear(KEY_COPY); break; - case 0x21c: map_key_clear(KEY_CUT); break; - case 0x21d: map_key_clear(KEY_PASTE); break; - case 0x221: map_key_clear(KEY_FIND); break; - case 0x223: map_key_clear(KEY_HOMEPAGE); break; - case 0x224: map_key_clear(KEY_BACK); break; - case 0x225: map_key_clear(KEY_FORWARD); break; - case 0x226: map_key_clear(KEY_STOP); break; - case 0x227: map_key_clear(KEY_REFRESH); break; - case 0x22a: map_key_clear(KEY_BOOKMARKS); break; - case 0x233: map_key_clear(KEY_SCROLLUP); break; - case 0x234: map_key_clear(KEY_SCROLLDOWN); break; - case 0x238: map_rel(REL_HWHEEL); break; - case 0x279: map_key_clear(KEY_REDO); break; - case 0x289: map_key_clear(KEY_REPLY); break; - case 0x28b: map_key_clear(KEY_FORWARDMAIL); break; - case 0x28c: map_key_clear(KEY_SEND); break; - - /* Reported on a Cherry Cymotion keyboard */ - case 0x301: map_key_clear(KEY_PROG1); break; - case 0x302: map_key_clear(KEY_PROG2); break; - case 0x303: map_key_clear(KEY_PROG3); break; - - default: goto ignore; - } - break; - - case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */ - - set_bit(EV_REP, input->evbit); - switch (usage->hid & HID_USAGE) { - case 0x021: map_key_clear(KEY_PRINT); break; - case 0x070: map_key_clear(KEY_HP); break; - case 0x071: map_key_clear(KEY_CAMERA); break; - case 0x072: map_key_clear(KEY_SOUND); break; - case 0x073: map_key_clear(KEY_QUESTION); break; - case 0x080: map_key_clear(KEY_EMAIL); break; - case 0x081: map_key_clear(KEY_CHAT); break; - case 0x082: map_key_clear(KEY_SEARCH); break; - case 0x083: map_key_clear(KEY_CONNECT); break; - case 0x084: map_key_clear(KEY_FINANCE); break; - case 0x085: map_key_clear(KEY_SPORT); break; - case 0x086: map_key_clear(KEY_SHOP); break; - default: goto ignore; - } - break; - - case HID_UP_MSVENDOR: - goto ignore; - - case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB keyboards */ - - set_bit(EV_REP, input->evbit); - switch(usage->hid & HID_USAGE) { - case 0x003: - /* The fn key on Apple PowerBooks */ - map_key_clear(KEY_FN); - hidinput_pb_setup(input); - break; - - default: goto ignore; - } - break; - - case HID_UP_LOGIVENDOR: /* Reported on Logitech Ultra X Media Remote */ - - set_bit(EV_REP, input->evbit); - switch(usage->hid & HID_USAGE) { - case 0x004: map_key_clear(KEY_AGAIN); break; - case 0x00d: map_key_clear(KEY_HOME); break; - case 0x024: map_key_clear(KEY_SHUFFLE); break; - case 0x025: map_key_clear(KEY_TV); break; - case 0x026: map_key_clear(KEY_MENU); break; - case 0x031: map_key_clear(KEY_AUDIO); break; - case 0x032: map_key_clear(KEY_TEXT); break; - case 0x033: map_key_clear(KEY_LAST); break; - case 0x047: map_key_clear(KEY_MP3); break; - case 0x048: map_key_clear(KEY_DVD); break; - case 0x049: map_key_clear(KEY_MEDIA); break; - case 0x04a: map_key_clear(KEY_VIDEO); break; - case 0x04b: map_key_clear(KEY_ANGLE); break; - case 0x04c: map_key_clear(KEY_LANGUAGE); break; - case 0x04d: map_key_clear(KEY_SUBTITLE); break; - case 0x051: map_key_clear(KEY_RED); break; - case 0x052: map_key_clear(KEY_CLOSE); break; - default: goto ignore; - } - break; - - case HID_UP_PID: - - switch(usage->hid & HID_USAGE) { - case 0xa4: map_key_clear(BTN_DEAD); break; - default: goto ignore; - } - break; - - default: - unknown: - if (field->report_size == 1) { - if (field->report->type == HID_OUTPUT_REPORT) { - map_led(LED_MISC); - break; - } - map_key(BTN_MISC); - break; - } - if (field->flags & HID_MAIN_ITEM_RELATIVE) { - map_rel(REL_MISC); - break; - } - map_abs(ABS_MISC); - break; - } - - if (device->quirks & HID_QUIRK_MIGHTYMOUSE) { - if (usage->hid == HID_GD_Z) - map_rel(REL_HWHEEL); - else if (usage->code == BTN_1) - map_key(BTN_2); - else if (usage->code == BTN_2) - map_key(BTN_1); - } - - if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) && - (usage->type == EV_REL) && (usage->code == REL_WHEEL)) - set_bit(REL_HWHEEL, bit); - - if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005)) - || ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) - goto ignore; - - if ((device->quirks & HID_QUIRK_BAD_RELATIVE_KEYS) && - usage->type == EV_KEY && (field->flags & HID_MAIN_ITEM_RELATIVE)) - field->flags &= ~HID_MAIN_ITEM_RELATIVE; - - set_bit(usage->type, input->evbit); - - while (usage->code <= max && test_and_set_bit(usage->code, bit)) - usage->code = find_next_zero_bit(bit, max + 1, usage->code); - - if (usage->code > max) - goto ignore; - - - if (usage->type == EV_ABS) { - - int a = field->logical_minimum; - int b = field->logical_maximum; - - if ((device->quirks & HID_QUIRK_BADPAD) && (usage->code == ABS_X || usage->code == ABS_Y)) { - a = field->logical_minimum = 0; - b = field->logical_maximum = 255; - } - - if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK) - input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4); - else input_set_abs_params(input, usage->code, a, b, 0, 0); - - } - - if (usage->type == EV_ABS && - (usage->hat_min < usage->hat_max || usage->hat_dir)) { - int i; - for (i = usage->code; i < usage->code + 2 && i <= max; i++) { - input_set_abs_params(input, i, -1, 1, 0, 0); - set_bit(i, input->absbit); - } - if (usage->hat_dir && !field->dpad) - field->dpad = usage->code; - } - -#ifdef DEBUG - resolv_event(usage->type, usage->code); - printk("\n"); -#endif - return; - -ignore: -#ifdef DEBUG - printk("IGNORED\n"); -#endif - return; -} - -void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) -{ - struct input_dev *input; - int *quirks = &hid->quirks; - - if (!field->hidinput) - return; - - input = field->hidinput->input; - - if (!usage->type) - return; - - if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005)) - || ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) { - if (value) hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON; - else hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON; - return; - } - - if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) { - input_event(input, usage->type, usage->code, -value); - return; - } - - if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) { - input_event(input, usage->type, REL_HWHEEL, value); - return; - } - - if ((hid->quirks & HID_QUIRK_POWERBOOK_HAS_FN) && hidinput_pb_event(hid, input, usage, value)) - return; - - if (usage->hat_min < usage->hat_max || usage->hat_dir) { - int hat_dir = usage->hat_dir; - if (!hat_dir) - hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; - if (hat_dir < 0 || hat_dir > 8) hat_dir = 0; - input_event(input, usage->type, usage->code , hid_hat_to_axis[hat_dir].x); - input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[hat_dir].y); - return; - } - - if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */ - *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT); - return; - } - - if (usage->hid == (HID_UP_DIGITIZER | 0x0032)) { /* InRange */ - if (value) { - input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1); - return; - } - input_event(input, usage->type, usage->code, 0); - input_event(input, usage->type, BTN_TOOL_RUBBER, 0); - return; - } - - if (usage->hid == (HID_UP_DIGITIZER | 0x0030) && (*quirks & HID_QUIRK_NOTOUCH)) { /* Pressure */ - int a = field->logical_minimum; - int b = field->logical_maximum; - input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3)); - } - - if (usage->hid == (HID_UP_PID | 0x83UL)) { /* Simultaneous Effects Max */ - dbg("Maximum Effects - %d",value); - return; - } - - if (usage->hid == (HID_UP_PID | 0x7fUL)) { - dbg("PID Pool Report\n"); - return; - } - - if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */ - return; - - input_event(input, usage->type, usage->code, value); - - if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY)) - input_event(input, usage->type, usage->code, 0); -} - -void hidinput_report_event(struct hid_device *hid, struct hid_report *report) -{ - struct hid_input *hidinput; - - list_for_each_entry(hidinput, &hid->inputs, list) - input_sync(hidinput->input); -} - -static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field) -{ - struct hid_report *report; - int i, j; - - list_for_each_entry(report, &hid->report_enum[HID_OUTPUT_REPORT].report_list, list) { - for (i = 0; i < report->maxfield; i++) { - *field = report->field[i]; - for (j = 0; j < (*field)->maxusage; j++) - if ((*field)->usage[j].type == type && (*field)->usage[j].code == code) - return j; - } - } - return -1; -} - -static int hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) -{ - struct hid_device *hid = dev->private; - struct hid_field *field; - int offset; - - if (type == EV_FF) - return input_ff_event(dev, type, code, value); - - if (type != EV_LED) - return -1; - - if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) { - warn("event field not found"); - return -1; - } - - hid_set_field(field, offset, value); - hid_submit_report(hid, field->report, USB_DIR_OUT); - - return 0; -} - -static int hidinput_open(struct input_dev *dev) -{ - struct hid_device *hid = dev->private; - return hid_open(hid); -} - -static void hidinput_close(struct input_dev *dev) -{ - struct hid_device *hid = dev->private; - hid_close(hid); -} - -/* - * Register the input device; print a message. - * Configure the input layer interface - * Read all reports and initialize the absolute field values. - */ - -int hidinput_connect(struct hid_device *hid) -{ - struct usb_device *dev = hid->dev; - struct hid_report *report; - struct hid_input *hidinput = NULL; - struct input_dev *input_dev; - int i, j, k; - - INIT_LIST_HEAD(&hid->inputs); - - for (i = 0; i < hid->maxcollection; i++) - if (hid->collection[i].type == HID_COLLECTION_APPLICATION || - hid->collection[i].type == HID_COLLECTION_PHYSICAL) - if (IS_INPUT_APPLICATION(hid->collection[i].usage)) - break; - - if (i == hid->maxcollection) - return -1; - - for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) - list_for_each_entry(report, &hid->report_enum[k].report_list, list) { - - if (!report->maxfield) - continue; - - if (!hidinput) { - hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!hidinput || !input_dev) { - kfree(hidinput); - input_free_device(input_dev); - err("Out of memory during hid input probe"); - return -1; - } - - input_dev->private = hid; - input_dev->event = hidinput_input_event; - input_dev->open = hidinput_open; - input_dev->close = hidinput_close; - - input_dev->name = hid->name; - input_dev->phys = hid->phys; - input_dev->uniq = hid->uniq; - usb_to_input_id(dev, &input_dev->id); - input_dev->cdev.dev = &hid->intf->dev; - - hidinput->input = input_dev; - list_add_tail(&hidinput->list, &hid->inputs); - } - - for (i = 0; i < report->maxfield; i++) - for (j = 0; j < report->field[i]->maxusage; j++) - hidinput_configure_usage(hidinput, report->field[i], - report->field[i]->usage + j); - - if (hid->quirks & HID_QUIRK_MULTI_INPUT) { - /* This will leave hidinput NULL, so that it - * allocates another one if we have more inputs on - * the same interface. Some devices (e.g. Happ's - * UGCI) cram a lot of unrelated inputs into the - * same interface. */ - hidinput->report = report; - input_register_device(hidinput->input); - hidinput = NULL; - } - } - - /* This only gets called when we are a single-input (most of the - * time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is - * only useful in this case, and not for multi-input quirks. */ - if (hidinput) { - hid_ff_init(hid); - input_register_device(hidinput->input); - } - - return 0; -} - -void hidinput_disconnect(struct hid_device *hid) -{ - struct hid_input *hidinput, *next; - - list_for_each_entry_safe(hidinput, next, &hid->inputs, list) { - list_del(&hidinput->list); - input_unregister_device(hidinput->input); - kfree(hidinput); - } -} diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c deleted file mode 100644 index 93da222b6da..00000000000 --- a/drivers/usb/input/hid-lgff.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Force feedback support for hid-compliant for some of the devices from - * Logitech, namely: - * - WingMan Cordless RumblePad - * - WingMan Force 3D - * - * Copyright (c) 2002-2004 Johann Deneux - * Copyright (c) 2006 Anssi Hannula <anssi.hannula@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 - * - * Should you need to contact me, the author, you can do so by - * e-mail - mail your message to <johann.deneux@it.uu.se> - */ - -#include <linux/input.h> -#include <linux/usb.h> -#include "hid.h" - -struct device_type { - u16 idVendor; - u16 idProduct; - const signed short *ff; -}; - -static const signed short ff_rumble[] = { - FF_RUMBLE, - -1 -}; - -static const signed short ff_joystick[] = { - FF_CONSTANT, - -1 -}; - -static const struct device_type devices[] = { - { 0x046d, 0xc211, ff_rumble }, - { 0x046d, 0xc219, ff_rumble }, - { 0x046d, 0xc283, ff_joystick }, - { 0x0000, 0x0000, ff_joystick } -}; - -static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect) -{ - struct hid_device *hid = dev->private; - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - int x, y; - unsigned int left, right; - -#define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff - - switch (effect->type) { - case FF_CONSTANT: - x = effect->u.ramp.start_level + 0x7f; /* 0x7f is center */ - y = effect->u.ramp.end_level + 0x7f; - CLAMP(x); - CLAMP(y); - report->field[0]->value[0] = 0x51; - report->field[0]->value[1] = 0x08; - report->field[0]->value[2] = x; - report->field[0]->value[3] = y; - dbg("(x, y)=(%04x, %04x)", x, y); - hid_submit_report(hid, report, USB_DIR_OUT); - break; - - case FF_RUMBLE: - right = effect->u.rumble.strong_magnitude; - left = effect->u.rumble.weak_magnitude; - right = right * 0xff / 0xffff; - left = left * 0xff / 0xffff; - CLAMP(left); - CLAMP(right); - report->field[0]->value[0] = 0x42; - report->field[0]->value[1] = 0x00; - report->field[0]->value[2] = left; - report->field[0]->value[3] = right; - dbg("(left, right)=(%04x, %04x)", left, right); - hid_submit_report(hid, report, USB_DIR_OUT); - break; - } - return 0; -} - -int hid_lgff_init(struct hid_device* hid) -{ - struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; - struct hid_report *report; - struct hid_field *field; - int error; - int i, j; - - /* Find the report to use */ - if (list_empty(report_list)) { - err("No output report found"); - return -1; - } - - /* Check that the report looks ok */ - report = list_entry(report_list->next, struct hid_report, list); - if (!report) { - err("NULL output report"); - return -1; - } - - field = report->field[0]; - if (!field) { - err("NULL field"); - return -1; - } - - for (i = 0; i < ARRAY_SIZE(devices); i++) { - if (dev->id.vendor == devices[i].idVendor && - dev->id.product == devices[i].idProduct) { - for (j = 0; devices[i].ff[j] >= 0; j++) - set_bit(devices[i].ff[j], dev->ffbit); - break; - } - } - - error = input_ff_create_memless(dev, NULL, hid_lgff_play); - if (error) - return error; - - printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n"); - - return 0; -} diff --git a/drivers/usb/input/hid-pidff.c b/drivers/usb/input/hid-pidff.c deleted file mode 100644 index 5420c13eb8e..00000000000 --- a/drivers/usb/input/hid-pidff.c +++ /dev/null @@ -1,1330 +0,0 @@ -/* - * Force feedback driver for USB HID PID compliant devices - * - * Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@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 - */ - -/* #define DEBUG */ - -#define debug(format, arg...) pr_debug("hid-pidff: " format "\n" , ## arg) - -#include <linux/sched.h> -#include <linux/input.h> -#include <linux/usb.h> - -#include "hid.h" - -#define PID_EFFECTS_MAX 64 - -/* Report usage table used to put reports into an array */ - -#define PID_SET_EFFECT 0 -#define PID_EFFECT_OPERATION 1 -#define PID_DEVICE_GAIN 2 -#define PID_POOL 3 -#define PID_BLOCK_LOAD 4 -#define PID_BLOCK_FREE 5 -#define PID_DEVICE_CONTROL 6 -#define PID_CREATE_NEW_EFFECT 7 - -#define PID_REQUIRED_REPORTS 7 - -#define PID_SET_ENVELOPE 8 -#define PID_SET_CONDITION 9 -#define PID_SET_PERIODIC 10 -#define PID_SET_CONSTANT 11 -#define PID_SET_RAMP 12 -static const u8 pidff_reports[] = { - 0x21, 0x77, 0x7d, 0x7f, 0x89, 0x90, 0x96, 0xab, - 0x5a, 0x5f, 0x6e, 0x73, 0x74 -}; - -/* device_control is really 0x95, but 0x96 specified as it is the usage of -the only field in that report */ - -/* Value usage tables used to put fields and values into arrays */ - -#define PID_EFFECT_BLOCK_INDEX 0 - -#define PID_DURATION 1 -#define PID_GAIN 2 -#define PID_TRIGGER_BUTTON 3 -#define PID_TRIGGER_REPEAT_INT 4 -#define PID_DIRECTION_ENABLE 5 -#define PID_START_DELAY 6 -static const u8 pidff_set_effect[] = { - 0x22, 0x50, 0x52, 0x53, 0x54, 0x56, 0xa7 -}; - -#define PID_ATTACK_LEVEL 1 -#define PID_ATTACK_TIME 2 -#define PID_FADE_LEVEL 3 -#define PID_FADE_TIME 4 -static const u8 pidff_set_envelope[] = { 0x22, 0x5b, 0x5c, 0x5d, 0x5e }; - -#define PID_PARAM_BLOCK_OFFSET 1 -#define PID_CP_OFFSET 2 -#define PID_POS_COEFFICIENT 3 -#define PID_NEG_COEFFICIENT 4 -#define PID_POS_SATURATION 5 -#define PID_NEG_SATURATION 6 -#define PID_DEAD_BAND 7 -static const u8 pidff_set_condition[] = { - 0x22, 0x23, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65 -}; - -#define PID_MAGNITUDE 1 -#define PID_OFFSET 2 -#define PID_PHASE 3 -#define PID_PERIOD 4 -static const u8 pidff_set_periodic[] = { 0x22, 0x70, 0x6f, 0x71, 0x72 }; -static const u8 pidff_set_constant[] = { 0x22, 0x70 }; - -#define PID_RAMP_START 1 -#define PID_RAMP_END 2 -static const u8 pidff_set_ramp[] = { 0x22, 0x75, 0x76 }; - -#define PID_RAM_POOL_AVAILABLE 1 -static const u8 pidff_block_load[] = { 0x22, 0xac }; - -#define PID_LOOP_COUNT 1 -static const u8 pidff_effect_operation[] = { 0x22, 0x7c }; - -static const u8 pidff_block_free[] = { 0x22 }; - -#define PID_DEVICE_GAIN_FIELD 0 -static const u8 pidff_device_gain[] = { 0x7e }; - -#define PID_RAM_POOL_SIZE 0 -#define PID_SIMULTANEOUS_MAX 1 -#define PID_DEVICE_MANAGED_POOL 2 -static const u8 pidff_pool[] = { 0x80, 0x83, 0xa9 }; - -/* Special field key tables used to put special field keys into arrays */ - -#define PID_ENABLE_ACTUATORS 0 -#define PID_RESET 1 -static const u8 pidff_device_control[] = { 0x97, 0x9a }; - -#define PID_CONSTANT 0 -#define PID_RAMP 1 -#define PID_SQUARE 2 -#define PID_SINE 3 -#define PID_TRIANGLE 4 -#define PID_SAW_UP 5 -#define PID_SAW_DOWN 6 -#define PID_SPRING 7 -#define PID_DAMPER 8 -#define PID_INERTIA 9 -#define PID_FRICTION 10 -static const u8 pidff_effect_types[] = { - 0x26, 0x27, 0x30, 0x31, 0x32, 0x33, 0x34, - 0x40, 0x41, 0x42, 0x43 -}; - -#define PID_BLOCK_LOAD_SUCCESS 0 -#define PID_BLOCK_LOAD_FULL 1 -static const u8 pidff_block_load_status[] = { 0x8c, 0x8d }; - -#define PID_EFFECT_START 0 -#define PID_EFFECT_STOP 1 -static const u8 pidff_effect_operation_status[] = { 0x79, 0x7b }; - -struct pidff_usage { - struct hid_field *field; - s32 *value; -}; - -struct pidff_device { - struct hid_device *hid; - - struct hid_report *reports[sizeof(pidff_reports)]; - - struct pidff_usage set_effect[sizeof(pidff_set_effect)]; - struct pidff_usage set_envelope[sizeof(pidff_set_envelope)]; - struct pidff_usage set_condition[sizeof(pidff_set_condition)]; - struct pidff_usage set_periodic[sizeof(pidff_set_periodic)]; - struct pidff_usage set_constant[sizeof(pidff_set_constant)]; - struct pidff_usage set_ramp[sizeof(pidff_set_ramp)]; - - struct pidff_usage device_gain[sizeof(pidff_device_gain)]; - struct pidff_usage block_load[sizeof(pidff_block_load)]; - struct pidff_usage pool[sizeof(pidff_pool)]; - struct pidff_usage effect_operation[sizeof(pidff_effect_operation)]; - struct pidff_usage block_free[sizeof(pidff_block_free)]; - - /* Special field is a field that is not composed of - usage<->value pairs that pidff_usage values are */ - - /* Special field in create_new_effect */ - struct hid_field *create_new_effect_type; - - /* Special fields in set_effect */ - struct hid_field *set_effect_type; - struct hid_field *effect_direction; - - /* Special field in device_control */ - struct hid_field *device_control; - - /* Special field in block_load */ - struct hid_field *block_load_status; - - /* Special field in effect_operation */ - struct hid_field *effect_operation_status; - - int control_id[sizeof(pidff_device_control)]; - int type_id[sizeof(pidff_effect_types)]; - int status_id[sizeof(pidff_block_load_status)]; - int operation_id[sizeof(pidff_effect_operation_status)]; - - int pid_id[PID_EFFECTS_MAX]; -}; - -/* - * Scale an unsigned value with range 0..max for the given field - */ -static int pidff_rescale(int i, int max, struct hid_field *field) -{ - return i * (field->logical_maximum - field->logical_minimum) / max + - field->logical_minimum; -} - -/* - * Scale a signed value in range -0x8000..0x7fff for the given field - */ -static int pidff_rescale_signed(int i, struct hid_field *field) -{ - return i == 0 ? 0 : i > - 0 ? i * field->logical_maximum / 0x7fff : i * - field->logical_minimum / -0x8000; -} - -static void pidff_set(struct pidff_usage *usage, u16 value) -{ - usage->value[0] = pidff_rescale(value, 0xffff, usage->field); - debug("calculated from %d to %d", value, usage->value[0]); -} - -static void pidff_set_signed(struct pidff_usage *usage, s16 value) -{ - if (usage->field->logical_minimum < 0) - usage->value[0] = pidff_rescale_signed(value, usage->field); - else { - if (value < 0) - usage->value[0] = - pidff_rescale(-value, 0x8000, usage->field); - else - usage->value[0] = - pidff_rescale(value, 0x7fff, usage->field); - } - debug("calculated from %d to %d", value, usage->value[0]); -} - -/* - * Send envelope report to the device - */ -static void pidff_set_envelope_report(struct pidff_device *pidff, - struct ff_envelope *envelope) -{ - pidff->set_envelope[PID_EFFECT_BLOCK_INDEX].value[0] = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; - - pidff->set_envelope[PID_ATTACK_LEVEL].value[0] = - pidff_rescale(envelope->attack_level > - 0x7fff ? 0x7fff : envelope->attack_level, 0x7fff, - pidff->set_envelope[PID_ATTACK_LEVEL].field); - pidff->set_envelope[PID_FADE_LEVEL].value[0] = - pidff_rescale(envelope->fade_level > - 0x7fff ? 0x7fff : envelope->fade_level, 0x7fff, - pidff->set_envelope[PID_FADE_LEVEL].field); - - pidff->set_envelope[PID_ATTACK_TIME].value[0] = envelope->attack_length; - pidff->set_envelope[PID_FADE_TIME].value[0] = envelope->fade_length; - - debug("attack %u => %d", envelope->attack_level, - pidff->set_envelope[PID_ATTACK_LEVEL].value[0]); - - hid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE], - USB_DIR_OUT); -} - -/* - * Test if the new envelope differs from old one - */ -static int pidff_needs_set_envelope(struct ff_envelope *envelope, - struct ff_envelope *old) -{ - return envelope->attack_level != old->attack_level || - envelope->fade_level != old->fade_level || - envelope->attack_length != old->attack_length || - envelope->fade_length != old->fade_length; -} - -/* - * Send constant force report to the device - */ -static void pidff_set_constant_force_report(struct pidff_device *pidff, - struct ff_effect *effect) -{ - pidff->set_constant[PID_EFFECT_BLOCK_INDEX].value[0] = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; - pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE], - effect->u.constant.level); - - hid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT], - USB_DIR_OUT); -} - -/* - * Test if the constant parameters have changed between effects - */ -static int pidff_needs_set_constant(struct ff_effect *effect, - struct ff_effect *old) -{ - return effect->u.constant.level != old->u.constant.level; -} - -/* - * Send set effect report to the device - */ -static void pidff_set_effect_report(struct pidff_device *pidff, - struct ff_effect *effect) -{ - pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; - pidff->set_effect_type->value[0] = - pidff->create_new_effect_type->value[0]; - pidff->set_effect[PID_DURATION].value[0] = effect->replay.length; - pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = effect->trigger.button; - pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = - effect->trigger.interval; - pidff->set_effect[PID_GAIN].value[0] = - pidff->set_effect[PID_GAIN].field->logical_maximum; - pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1; - pidff->effect_direction->value[0] = - pidff_rescale(effect->direction, 0xffff, - pidff->effect_direction); - pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay; - - hid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], - USB_DIR_OUT); -} - -/* - * Test if the values used in set_effect have changed - */ -static int pidff_needs_set_effect(struct ff_effect *effect, - struct ff_effect *old) -{ - return effect->replay.length != old->replay.length || - effect->trigger.interval != old->trigger.interval || - effect->trigger.button != old->trigger.button || - effect->direction != old->direction || - effect->replay.delay != old->replay.delay; -} - -/* - * Send periodic effect report to the device - */ -static void pidff_set_periodic_report(struct pidff_device *pidff, - struct ff_effect *effect) -{ - pidff->set_periodic[PID_EFFECT_BLOCK_INDEX].value[0] = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; - pidff_set_signed(&pidff->set_periodic[PID_MAGNITUDE], - effect->u.periodic.magnitude); - pidff_set_signed(&pidff->set_periodic[PID_OFFSET], - effect->u.periodic.offset); - pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase); - pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period; - - hid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC], - USB_DIR_OUT); - -} - -/* - * Test if periodic effect parameters have changed - */ -static int pidff_needs_set_periodic(struct ff_effect *effect, - struct ff_effect *old) -{ - return effect->u.periodic.magnitude != old->u.periodic.magnitude || - effect->u.periodic.offset != old->u.periodic.offset || - effect->u.periodic.phase != old->u.periodic.phase || - effect->u.periodic.period != old->u.periodic.period; -} - -/* - * Send condition effect reports to the device - */ -static void pidff_set_condition_report(struct pidff_device *pidff, - struct ff_effect *effect) -{ - int i; - - pidff->set_condition[PID_EFFECT_BLOCK_INDEX].value[0] = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; - - for (i = 0; i < 2; i++) { - pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i; - pidff_set_signed(&pidff->set_condition[PID_CP_OFFSET], - effect->u.condition[i].center); - pidff_set_signed(&pidff->set_condition[PID_POS_COEFFICIENT], - effect->u.condition[i].right_coeff); - pidff_set_signed(&pidff->set_condition[PID_NEG_COEFFICIENT], - effect->u.condition[i].left_coeff); - pidff_set(&pidff->set_condition[PID_POS_SATURATION], - effect->u.condition[i].right_saturation); - pidff_set(&pidff->set_condition[PID_NEG_SATURATION], - effect->u.condition[i].left_saturation); - pidff_set(&pidff->set_condition[PID_DEAD_BAND], - effect->u.condition[i].deadband); - hid_wait_io(pidff->hid); - hid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION], - USB_DIR_OUT); - } -} - -/* - * Test if condition effect parameters have changed - */ -static int pidff_needs_set_condition(struct ff_effect *effect, - struct ff_effect *old) -{ - int i; - int ret = 0; - - for (i = 0; i < 2; i++) { - struct ff_condition_effect *cond = &effect->u.condition[i]; - struct ff_condition_effect *old_cond = &old->u.condition[i]; - - ret |= cond->center != old_cond->center || - cond->right_coeff != old_cond->right_coeff || - cond->left_coeff != old_cond->left_coeff || - cond->right_saturation != old_cond->right_saturation || - cond->left_saturation != old_cond->left_saturation || - cond->deadband != old_cond->deadband; - } - - return ret; -} - -/* - * Send ramp force report to the device - */ -static void pidff_set_ramp_force_report(struct pidff_device *pidff, - struct ff_effect *effect) -{ - pidff->set_ramp[PID_EFFECT_BLOCK_INDEX].value[0] = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; - pidff_set_signed(&pidff->set_ramp[PID_RAMP_START], - effect->u.ramp.start_level); - pidff_set_signed(&pidff->set_ramp[PID_RAMP_END], - effect->u.ramp.end_level); - hid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP], - USB_DIR_OUT); -} - -/* - * Test if ramp force parameters have changed - */ -static int pidff_needs_set_ramp(struct ff_effect *effect, struct ff_effect *old) -{ - return effect->u.ramp.start_level != old->u.ramp.start_level || - effect->u.ramp.end_level != old->u.ramp.end_level; -} - -/* - * Send a request for effect upload to the device - * - * Returns 0 if device reported success, -ENOSPC if the device reported memory - * is full. Upon unknown response the function will retry for 60 times, if - * still unsuccessful -EIO is returned. - */ -static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum) -{ - int j; - - pidff->create_new_effect_type->value[0] = efnum; - hid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT], - USB_DIR_OUT); - debug("create_new_effect sent, type: %d", efnum); - - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0; - pidff->block_load_status->value[0] = 0; - hid_wait_io(pidff->hid); - - for (j = 0; j < 60; j++) { - debug("pid_block_load requested"); - hid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD], - USB_DIR_IN); - hid_wait_io(pidff->hid); - if (pidff->block_load_status->value[0] == - pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) { - debug("device reported free memory: %d bytes", - pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? - pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); - return 0; - } - if (pidff->block_load_status->value[0] == - pidff->status_id[PID_BLOCK_LOAD_FULL]) { - debug("not enough memory free: %d bytes", - pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? - pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); - return -ENOSPC; - } - } - printk(KERN_ERR "hid-pidff: pid_block_load failed 60 times\n"); - return -EIO; -} - -/* - * Play the effect with PID id n times - */ -static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n) -{ - pidff->effect_operation[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id; - - if (n == 0) { - pidff->effect_operation_status->value[0] = - pidff->operation_id[PID_EFFECT_STOP]; - } else { - pidff->effect_operation_status->value[0] = - pidff->operation_id[PID_EFFECT_START]; - pidff->effect_operation[PID_LOOP_COUNT].value[0] = n; - } - - hid_wait_io(pidff->hid); - hid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION], - USB_DIR_OUT); -} - -/** - * Play the effect with effect id @effect_id for @value times - */ -static int pidff_playback(struct input_dev *dev, int effect_id, int value) -{ - struct pidff_device *pidff = dev->ff->private; - - pidff_playback_pid(pidff, pidff->pid_id[effect_id], value); - - return 0; -} - -/* - * Erase effect with PID id - */ -static void pidff_erase_pid(struct pidff_device *pidff, int pid_id) -{ - pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id; - hid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE], - USB_DIR_OUT); -} - -/* - * Stop and erase effect with effect_id - */ -static int pidff_erase_effect(struct input_dev *dev, int effect_id) -{ - struct pidff_device *pidff = dev->ff->private; - int pid_id = pidff->pid_id[effect_id]; - - debug("starting to erase %d/%d", effect_id, pidff->pid_id[effect_id]); - pidff_playback_pid(pidff, pid_id, 0); - pidff_erase_pid(pidff, pid_id); - - return 0; -} - -/* - * Effect upload handler - */ -static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect, - struct ff_effect *old) -{ - struct pidff_device *pidff = dev->ff->private; - int type_id; - int error; - - switch (effect->type) { - case FF_CONSTANT: - if (!old) { - error = pidff_request_effect_upload(pidff, - pidff->type_id[PID_CONSTANT]); - if (error) - return error; - } - if (!old || pidff_needs_set_effect(effect, old)) - pidff_set_effect_report(pidff, effect); - if (!old || pidff_needs_set_constant(effect, old)) - pidff_set_constant_force_report(pidff, effect); - if (!old || - pidff_needs_set_envelope(&effect->u.constant.envelope, - &old->u.constant.envelope)) - pidff_set_envelope_report(pidff, - &effect->u.constant.envelope); - break; - - case FF_PERIODIC: - if (!old) { - switch (effect->u.periodic.waveform) { - case FF_SQUARE: - type_id = PID_SQUARE; - break; - case FF_TRIANGLE: - type_id = PID_TRIANGLE; - break; - case FF_SINE: - type_id = PID_SINE; - break; - case FF_SAW_UP: - type_id = PID_SAW_UP; - break; - case FF_SAW_DOWN: - type_id = PID_SAW_DOWN; - break; - default: - printk(KERN_ERR - "hid-pidff: invalid waveform\n"); - return -EINVAL; - } - - error = pidff_request_effect_upload(pidff, - pidff->type_id[type_id]); - if (error) - return error; - } - if (!old || pidff_needs_set_effect(effect, old)) - pidff_set_effect_report(pidff, effect); - if (!old || pidff_needs_set_periodic(effect, old)) - pidff_set_periodic_report(pidff, effect); - if (!old || - pidff_needs_set_envelope(&effect->u.periodic.envelope, - &old->u.periodic.envelope)) - pidff_set_envelope_report(pidff, - &effect->u.periodic.envelope); - break; - - case FF_RAMP: - if (!old) { - error = pidff_request_effect_upload(pidff, - pidff->type_id[PID_RAMP]); - if (error) - return error; - } - if (!old || pidff_needs_set_effect(effect, old)) - pidff_set_effect_report(pidff, effect); - if (!old || pidff_needs_set_ramp(effect, old)) - pidff_set_ramp_force_report(pidff, effect); - if (!old || - pidff_needs_set_envelope(&effect->u.ramp.envelope, - &old->u.ramp.envelope)) - pidff_set_envelope_report(pidff, - &effect->u.ramp.envelope); - break; - - case FF_SPRING: - if (!old) { - error = pidff_request_effect_upload(pidff, - pidff->type_id[PID_SPRING]); - if (error) - return error; - } - if (!old || pidff_needs_set_effect(effect, old)) - pidff_set_effect_report(pidff, effect); - if (!old || pidff_needs_set_condition(effect, old)) - pidff_set_condition_report(pidff, effect); - break; - - case FF_FRICTION: - if (!old) { - error = pidff_request_effect_upload(pidff, - pidff->type_id[PID_FRICTION]); - if (error) - return error; - } - if (!old || pidff_needs_set_effect(effect, old)) - pidff_set_effect_report(pidff, effect); - if (!old || pidff_needs_set_condition(effect, old)) - pidff_set_condition_report(pidff, effect); - break; - - case FF_DAMPER: - if (!old) { - error = pidff_request_effect_upload(pidff, - pidff->type_id[PID_DAMPER]); - if (error) - return error; - } - if (!old || pidff_needs_set_effect(effect, old)) - pidff_set_effect_report(pidff, effect); - if (!old || pidff_needs_set_condition(effect, old)) - pidff_set_condition_report(pidff, effect); - break; - - case FF_INERTIA: - if (!old) { - error = pidff_request_effect_upload(pidff, - pidff->type_id[PID_INERTIA]); - if (error) - return error; - } - if (!old || pidff_needs_set_effect(effect, old)) - pidff_set_effect_report(pidff, effect); - if (!old || pidff_needs_set_condition(effect, old)) - pidff_set_condition_report(pidff, effect); - break; - - default: - printk(KERN_ERR "hid-pidff: invalid type\n"); - return -EINVAL; - } - - if (!old) - pidff->pid_id[effect->id] = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; - - debug("uploaded"); - - return 0; -} - -/* - * set_gain() handler - */ -static void pidff_set_gain(struct input_dev *dev, u16 gain) -{ - struct pidff_device *pidff = dev->ff->private; - - pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain); - hid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], - USB_DIR_OUT); -} - -static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude) -{ - struct hid_field *field = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].field; - - if (!magnitude) { - pidff_playback_pid(pidff, field->logical_minimum, 0); - return; - } - - pidff_playback_pid(pidff, field->logical_minimum, 1); - - pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum; - pidff->set_effect_type->value[0] = pidff->type_id[PID_SPRING]; - pidff->set_effect[PID_DURATION].value[0] = 0; - pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0; - pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0; - pidff_set(&pidff->set_effect[PID_GAIN], magnitude); - pidff->set_effect[PID_START_DELAY].value[0] = 0; - - hid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], - USB_DIR_OUT); -} - -/* - * pidff_set_autocenter() handler - */ -static void pidff_set_autocenter(struct input_dev *dev, u16 magnitude) -{ - struct pidff_device *pidff = dev->ff->private; - - pidff_autocenter(pidff, magnitude); -} - -/* - * Find fields from a report and fill a pidff_usage - */ -static int pidff_find_fields(struct pidff_usage *usage, const u8 *table, - struct hid_report *report, int count, int strict) -{ - int i, j, k, found; - - for (k = 0; k < count; k++) { - found = 0; - for (i = 0; i < report->maxfield; i++) { - if (report->field[i]->maxusage != - report->field[i]->report_count) { - debug("maxusage and report_count do not match, " - "skipping"); - continue; - } - for (j = 0; j < report->field[i]->maxusage; j++) { - if (report->field[i]->usage[j].hid == - (HID_UP_PID | table[k])) { - debug("found %d at %d->%d", k, i, j); - usage[k].field = report->field[i]; - usage[k].value = - &report->field[i]->value[j]; - found = 1; - break; - } - } - if (found) - break; - } - if (!found && strict) { - debug("failed to locate %d", k); - return -1; - } - } - return 0; -} - -/* - * Return index into pidff_reports for the given usage - */ -static int pidff_check_usage(int usage) -{ - int i; - - for (i = 0; i < sizeof(pidff_reports); i++) - if (usage == (HID_UP_PID | pidff_reports[i])) - return i; - - return -1; -} - -/* - * Find the reports and fill pidff->reports[] - * report_type specifies either OUTPUT or FEATURE reports - */ -static void pidff_find_reports(struct hid_device *hid, int report_type, - struct pidff_device *pidff) -{ - struct hid_report *report; - int i, ret; - - list_for_each_entry(report, - &hid->report_enum[report_type].report_list, list) { - if (report->maxfield < 1) - continue; - ret = pidff_check_usage(report->field[0]->logical); - if (ret != -1) { - debug("found usage 0x%02x from field->logical", - pidff_reports[ret]); - pidff->reports[ret] = report; - continue; - } - - /* - * Sometimes logical collections are stacked to indicate - * different usages for the report and the field, in which - * case we want the usage of the parent. However, Linux HID - * implementation hides this fact, so we have to dig it up - * ourselves - */ - i = report->field[0]->usage[0].collection_index; - if (i <= 0 || - hid->collection[i - 1].type != HID_COLLECTION_LOGICAL) - continue; - ret = pidff_check_usage(hid->collection[i - 1].usage); - if (ret != -1 && !pidff->reports[ret]) { - debug("found usage 0x%02x from collection array", - pidff_reports[ret]); - pidff->reports[ret] = report; - } - } -} - -/* - * Test if the required reports have been found - */ -static int pidff_reports_ok(struct pidff_device *pidff) -{ - int i; - - for (i = 0; i <= PID_REQUIRED_REPORTS; i++) { - if (!pidff->reports[i]) { - debug("%d missing", i); - return 0; - } - } - - return 1; -} - -/* - * Find a field with a specific usage within a report - */ -static struct hid_field *pidff_find_special_field(struct hid_report *report, - int usage, int enforce_min) -{ - int i; - - for (i = 0; i < report->maxfield; i++) { - if (report->field[i]->logical == (HID_UP_PID | usage) && - report->field[i]->report_count > 0) { - if (!enforce_min || - report->field[i]->logical_minimum == 1) - return report->field[i]; - else { - printk(KERN_ERR "hid-pidff: logical_minimum " - "is not 1 as it should be\n"); - return NULL; - } - } - } - return NULL; -} - -/* - * Fill a pidff->*_id struct table - */ -static int pidff_find_special_keys(int *keys, struct hid_field *fld, - const u8 *usagetable, int count) -{ - - int i, j; - int found = 0; - - for (i = 0; i < count; i++) { - for (j = 0; j < fld->maxusage; j++) { - if (fld->usage[j].hid == (HID_UP_PID | usagetable[i])) { - keys[i] = j + 1; - found++; - break; - } - } - } - return found; -} - -#define PIDFF_FIND_SPECIAL_KEYS(keys, field, name) \ - pidff_find_special_keys(pidff->keys, pidff->field, pidff_ ## name, \ - sizeof(pidff_ ## name)) - -/* - * Find and check the special fields - */ -static int pidff_find_special_fields(struct pidff_device *pidff) -{ - debug("finding special fields"); - - pidff->create_new_effect_type = - pidff_find_special_field(pidff->reports[PID_CREATE_NEW_EFFECT], - 0x25, 1); - pidff->set_effect_type = - pidff_find_special_field(pidff->reports[PID_SET_EFFECT], - 0x25, 1); - pidff->effect_direction = - pidff_find_special_field(pidff->reports[PID_SET_EFFECT], - 0x57, 0); - pidff->device_control = - pidff_find_special_field(pidff->reports[PID_DEVICE_CONTROL], - 0x96, 1); - pidff->block_load_status = - pidff_find_special_field(pidff->reports[PID_BLOCK_LOAD], - 0x8b, 1); - pidff->effect_operation_status = - pidff_find_special_field(pidff->reports[PID_EFFECT_OPERATION], - 0x78, 1); - - debug("search done"); - - if (!pidff->create_new_effect_type || !pidff->set_effect_type) { - printk(KERN_ERR "hid-pidff: effect lists not found\n"); - return -1; - } - - if (!pidff->effect_direction) { - printk(KERN_ERR "hid-pidff: direction field not found\n"); - return -1; - } - - if (!pidff->device_control) { - printk(KERN_ERR "hid-pidff: device control field not found\n"); - return -1; - } - - if (!pidff->block_load_status) { - printk(KERN_ERR - "hid-pidff: block load status field not found\n"); - return -1; - } - - if (!pidff->effect_operation_status) { - printk(KERN_ERR - "hid-pidff: effect operation field not found\n"); - return -1; - } - - pidff_find_special_keys(pidff->control_id, pidff->device_control, - pidff_device_control, - sizeof(pidff_device_control)); - - PIDFF_FIND_SPECIAL_KEYS(control_id, device_control, device_control); - - if (!PIDFF_FIND_SPECIAL_KEYS(type_id, create_new_effect_type, - effect_types)) { - printk(KERN_ERR "hid-pidff: no effect types found\n"); - return -1; - } - - if (PIDFF_FIND_SPECIAL_KEYS(status_id, block_load_status, - block_load_status) != - sizeof(pidff_block_load_status)) { - printk(KERN_ERR - "hidpidff: block load status identifiers not found\n"); - return -1; - } - - if (PIDFF_FIND_SPECIAL_KEYS(operation_id, effect_operation_status, - effect_operation_status) != - sizeof(pidff_effect_operation_status)) { - printk(KERN_ERR - "hidpidff: effect operation identifiers not found\n"); - return -1; - } - - return 0; -} - -/** - * Find the implemented effect types - */ -static int pidff_find_effects(struct pidff_device *pidff, - struct input_dev *dev) -{ - int i; - - for (i = 0; i < sizeof(pidff_effect_types); i++) { - int pidff_type = pidff->type_id[i]; - if (pidff->set_effect_type->usage[pidff_type].hid != - pidff->create_new_effect_type->usage[pidff_type].hid) { - printk(KERN_ERR "hid-pidff: " - "effect type number %d is invalid\n", i); - return -1; - } - } - - if (pidff->type_id[PID_CONSTANT]) - set_bit(FF_CONSTANT, dev->ffbit); - if (pidff->type_id[PID_RAMP]) - set_bit(FF_RAMP, dev->ffbit); - if (pidff->type_id[PID_SQUARE]) { - set_bit(FF_SQUARE, dev->ffbit); - set_bit(FF_PERIODIC, dev->ffbit); - } - if (pidff->type_id[PID_SINE]) { - set_bit(FF_SINE, dev->ffbit); - set_bit(FF_PERIODIC, dev->ffbit); - } - if (pidff->type_id[PID_TRIANGLE]) { - set_bit(FF_TRIANGLE, dev->ffbit); - set_bit(FF_PERIODIC, dev->ffbit); - } - if (pidff->type_id[PID_SAW_UP]) { - set_bit(FF_SAW_UP, dev->ffbit); - set_bit(FF_PERIODIC, dev->ffbit); - } - if (pidff->type_id[PID_SAW_DOWN]) { - set_bit(FF_SAW_DOWN, dev->ffbit); - set_bit(FF_PERIODIC, dev->ffbit); - } - if (pidff->type_id[PID_SPRING]) - set_bit(FF_SPRING, dev->ffbit); - if (pidff->type_id[PID_DAMPER]) - set_bit(FF_DAMPER, dev->ffbit); - if (pidff->type_id[PID_INERTIA]) - set_bit(FF_INERTIA, dev->ffbit); - if (pidff->type_id[PID_FRICTION]) - set_bit(FF_FRICTION, dev->ffbit); - - return 0; - -} - -#define PIDFF_FIND_FIELDS(name, report, strict) \ - pidff_find_fields(pidff->name, pidff_ ## name, \ - pidff->reports[report], \ - sizeof(pidff_ ## name), strict) - -/* - * Fill and check the pidff_usages - */ -static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) -{ - int envelope_ok = 0; - - if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) { - printk(KERN_ERR - "hid-pidff: unknown set_effect report layout\n"); - return -ENODEV; - } - - PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0); - if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) { - printk(KERN_ERR - "hid-pidff: unknown pid_block_load report layout\n"); - return -ENODEV; - } - - if (PIDFF_FIND_FIELDS(effect_operation, PID_EFFECT_OPERATION, 1)) { - printk(KERN_ERR - "hid-pidff: unknown effect_operation report layout\n"); - return -ENODEV; - } - - if (PIDFF_FIND_FIELDS(block_free, PID_BLOCK_FREE, 1)) { - printk(KERN_ERR - "hid-pidff: unknown pid_block_free report layout\n"); - return -ENODEV; - } - - if (!PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1)) - envelope_ok = 1; - - if (pidff_find_special_fields(pidff) || pidff_find_effects(pidff, dev)) - return -ENODEV; - - if (!envelope_ok) { - if (test_and_clear_bit(FF_CONSTANT, dev->ffbit)) - printk(KERN_WARNING "hid-pidff: " - "has constant effect but no envelope\n"); - if (test_and_clear_bit(FF_RAMP, dev->ffbit)) - printk(KERN_WARNING "hid-pidff: " - "has ramp effect but no envelope\n"); - - if (test_and_clear_bit(FF_PERIODIC, dev->ffbit)) - printk(KERN_WARNING "hid-pidff: " - "has periodic effect but no envelope\n"); - } - - if (test_bit(FF_CONSTANT, dev->ffbit) && - PIDFF_FIND_FIELDS(set_constant, PID_SET_CONSTANT, 1)) { - printk(KERN_WARNING - "hid-pidff: unknown constant effect layout\n"); - clear_bit(FF_CONSTANT, dev->ffbit); - } - - if (test_bit(FF_RAMP, dev->ffbit) && - PIDFF_FIND_FIELDS(set_ramp, PID_SET_RAMP, 1)) { - printk(KERN_WARNING "hid-pidff: unknown ramp effect layout\n"); - clear_bit(FF_RAMP, dev->ffbit); - } - - if ((test_bit(FF_SPRING, dev->ffbit) || - test_bit(FF_DAMPER, dev->ffbit) || - test_bit(FF_FRICTION, dev->ffbit) || - test_bit(FF_INERTIA, dev->ffbit)) && - PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) { - printk(KERN_WARNING - "hid-pidff: unknown condition effect layout\n"); - clear_bit(FF_SPRING, dev->ffbit); - clear_bit(FF_DAMPER, dev->ffbit); - clear_bit(FF_FRICTION, dev->ffbit); - clear_bit(FF_INERTIA, dev->ffbit); - } - - if (test_bit(FF_PERIODIC, dev->ffbit) && - PIDFF_FIND_FIELDS(set_periodic, PID_SET_PERIODIC, 1)) { - printk(KERN_WARNING - "hid-pidff: unknown periodic effect layout\n"); - clear_bit(FF_PERIODIC, dev->ffbit); - } - - PIDFF_FIND_FIELDS(pool, PID_POOL, 0); - - if (!PIDFF_FIND_FIELDS(device_gain, PID_DEVICE_GAIN, 1)) - set_bit(FF_GAIN, dev->ffbit); - - return 0; -} - -/* - * Reset the device - */ -static void pidff_reset(struct pidff_device *pidff) -{ - struct hid_device *hid = pidff->hid; - int i = 0; - - pidff->device_control->value[0] = pidff->control_id[PID_RESET]; - /* We reset twice as sometimes hid_wait_io isn't waiting long enough */ - hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); - hid_wait_io(hid); - hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); - hid_wait_io(hid); - - pidff->device_control->value[0] = - pidff->control_id[PID_ENABLE_ACTUATORS]; - hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); - hid_wait_io(hid); - - /* pool report is sometimes messed up, refetch it */ - hid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN); - hid_wait_io(hid); - - if (pidff->pool[PID_SIMULTANEOUS_MAX].value) { - int sim_effects = pidff->pool[PID_SIMULTANEOUS_MAX].value[0]; - while (sim_effects < 2) { - if (i++ > 20) { - printk(KERN_WARNING "hid-pidff: device reports " - "%d simultaneous effects\n", - sim_effects); - break; - } - debug("pid_pool requested again"); - hid_submit_report(hid, pidff->reports[PID_POOL], - USB_DIR_IN); - hid_wait_io(hid); - } - } -} - -/* - * Test if autocenter modification is using the supported method - */ -static int pidff_check_autocenter(struct pidff_device *pidff, - struct input_dev *dev) -{ - int error; - - /* - * Let's find out if autocenter modification is supported - * Specification doesn't specify anything, so we request an - * effect upload and cancel it immediately. If the approved - * effect id was one above the minimum, then we assume the first - * effect id is a built-in spring type effect used for autocenter - */ - - error = pidff_request_effect_upload(pidff, 1); - if (error) { - printk(KERN_ERR "hid-pidff: upload request failed\n"); - return error; - } - - if (pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] == - pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + 1) { - pidff_autocenter(pidff, 0xffff); - set_bit(FF_AUTOCENTER, dev->ffbit); - } else { - printk(KERN_NOTICE "hid-pidff: " - "device has unknown autocenter control method\n"); - } - - pidff_erase_pid(pidff, - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]); - - return 0; - -} - -/* - * Check if the device is PID and initialize it - */ -int hid_pidff_init(struct hid_device *hid) -{ - struct pidff_device *pidff; - struct hid_input *hidinput = list_entry(hid->inputs.next, - struct hid_input, list); - struct input_dev *dev = hidinput->input; - struct ff_device *ff; - int max_effects; - int error; - - debug("starting pid init"); - - if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) { - debug("not a PID device, no output report"); - return -ENODEV; - } - - pidff = kzalloc(sizeof(*pidff), GFP_KERNEL); - if (!pidff) - return -ENOMEM; - - pidff->hid = hid; - - pidff_find_reports(hid, HID_OUTPUT_REPORT, pidff); - pidff_find_reports(hid, HID_FEATURE_REPORT, pidff); - - if (!pidff_reports_ok(pidff)) { - debug("reports not ok, aborting"); - error = -ENODEV; - goto fail; - } - - error = pidff_init_fields(pidff, dev); - if (error) - goto fail; - - pidff_reset(pidff); - - if (test_bit(FF_GAIN, dev->ffbit)) { - pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff); - hid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], - USB_DIR_OUT); - } - - error = pidff_check_autocenter(pidff, dev); - if (error) - goto fail; - - max_effects = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_maximum - - pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + - 1; - debug("max effects is %d", max_effects); - - if (max_effects > PID_EFFECTS_MAX) - max_effects = PID_EFFECTS_MAX; - - if (pidff->pool[PID_SIMULTANEOUS_MAX].value) - debug("max simultaneous effects is %d", - pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); - - if (pidff->pool[PID_RAM_POOL_SIZE].value) - debug("device memory size is %d bytes", - pidff->pool[PID_RAM_POOL_SIZE].value[0]); - - if (pidff->pool[PID_DEVICE_MANAGED_POOL].value && - pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) { - printk(KERN_NOTICE "hid-pidff: " - "device does not support device managed pool\n"); - goto fail; - } - - error = input_ff_create(dev, max_effects); - if (error) - goto fail; - - ff = dev->ff; - ff->private = pidff; - ff->upload = pidff_upload_effect; - ff->erase = pidff_erase_effect; - ff->set_gain = pidff_set_gain; - ff->set_autocenter = pidff_set_autocenter; - ff->playback = pidff_playback; - - printk(KERN_INFO "Force feedback for USB HID PID devices by " - "Anssi Hannula <anssi.hannula@gmail.com>\n"); - - return 0; - - fail: - kfree(pidff); - return error; -} diff --git a/drivers/usb/input/hid-tmff.c b/drivers/usb/input/hid-tmff.c deleted file mode 100644 index 2d5be4c318a..00000000000 --- a/drivers/usb/input/hid-tmff.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Force feedback support for various HID compliant devices by ThrustMaster: - * ThrustMaster FireStorm Dual Power 2 - * and possibly others whose device ids haven't been added. - * - * Modified to support ThrustMaster devices by Zinx Verituse - * on 2003-01-25 from the Logitech force feedback driver, - * which is by Johann Deneux. - * - * Copyright (c) 2003 Zinx Verituse <zinx@epicsol.org> - * Copyright (c) 2002 Johann Deneux - */ - -/* - * 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/input.h> - -#undef DEBUG -#include <linux/usb.h> - -#include "hid.h" - -/* Usages for thrustmaster devices I know about */ -#define THRUSTMASTER_USAGE_RUMBLE_LR (HID_UP_GENDESK | 0xbb) - - -struct tmff_device { - struct hid_report *report; - struct hid_field *rumble; -}; - -/* Changes values from 0 to 0xffff into values from minimum to maximum */ -static inline int hid_tmff_scale(unsigned int in, int minimum, int maximum) -{ - int ret; - - ret = (in * (maximum - minimum) / 0xffff) + minimum; - if (ret < minimum) - return minimum; - if (ret > maximum) - return maximum; - return ret; -} - -static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *effect) -{ - struct hid_device *hid = dev->private; - struct tmff_device *tmff = data; - int left, right; /* Rumbling */ - - left = hid_tmff_scale(effect->u.rumble.weak_magnitude, - tmff->rumble->logical_minimum, tmff->rumble->logical_maximum); - right = hid_tmff_scale(effect->u.rumble.strong_magnitude, - tmff->rumble->logical_minimum, tmff->rumble->logical_maximum); - - tmff->rumble->value[0] = left; - tmff->rumble->value[1] = right; - dbg("(left,right)=(%08x, %08x)", left, right); - hid_submit_report(hid, tmff->report, USB_DIR_OUT); - - return 0; -} - -int hid_tmff_init(struct hid_device *hid) -{ - struct tmff_device *tmff; - struct list_head *pos; - struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct input_dev *input_dev = hidinput->input; - int error; - - tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL); - if (!tmff) - return -ENOMEM; - - /* Find the report to use */ - __list_for_each(pos, &hid->report_enum[HID_OUTPUT_REPORT].report_list) { - struct hid_report *report = (struct hid_report *)pos; - int fieldnum; - - for (fieldnum = 0; fieldnum < report->maxfield; ++fieldnum) { - struct hid_field *field = report->field[fieldnum]; - - if (field->maxusage <= 0) - continue; - - switch (field->usage[0].hid) { - case THRUSTMASTER_USAGE_RUMBLE_LR: - if (field->report_count < 2) { - warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR with report_count < 2"); - continue; - } - - if (field->logical_maximum == field->logical_minimum) { - warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR with logical_maximum == logical_minimum"); - continue; - } - - if (tmff->report && tmff->report != report) { - warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR in other report"); - continue; - } - - if (tmff->rumble && tmff->rumble != field) { - warn("ignoring duplicate THRUSTMASTER_USAGE_RUMBLE_LR"); - continue; - } - - tmff->report = report; - tmff->rumble = field; - - set_bit(FF_RUMBLE, input_dev->ffbit); - break; - - default: - warn("ignoring unknown output usage %08x", field->usage[0].hid); - continue; - } - } - } - - error = input_ff_create_memless(input_dev, tmff, hid_tmff_play); - if (error) { - kfree(tmff); - return error; - } - - info("Force feedback for ThrustMaster rumble pad devices by Zinx Verituse <zinx@epicsol.org>"); - - return 0; -} - diff --git a/drivers/usb/input/hid-zpff.c b/drivers/usb/input/hid-zpff.c deleted file mode 100644 index d2ce3214572..00000000000 --- a/drivers/usb/input/hid-zpff.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Force feedback support for Zeroplus based devices - * - * Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@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 - */ - - -/* #define DEBUG */ - -#define debug(format, arg...) pr_debug("hid-zpff: " format "\n" , ## arg) - -#include <linux/input.h> -#include <linux/usb.h> -#include "hid.h" - -struct zpff_device { - struct hid_report *report; -}; - -static int hid_zpff_play(struct input_dev *dev, void *data, - struct ff_effect *effect) -{ - struct hid_device *hid = dev->private; - struct zpff_device *zpff = data; - int left, right; - - /* - * The following is specified the other way around in the Zeroplus - * datasheet but the order below is correct for the XFX Executioner; - * however it is possible that the XFX Executioner is an exception - */ - - left = effect->u.rumble.strong_magnitude; - right = effect->u.rumble.weak_magnitude; - debug("called with 0x%04x 0x%04x", left, right); - - left = left * 0x7f / 0xffff; - right = right * 0x7f / 0xffff; - - zpff->report->field[2]->value[0] = left; - zpff->report->field[3]->value[0] = right; - debug("running with 0x%02x 0x%02x", left, right); - hid_submit_report(hid, zpff->report, USB_DIR_OUT); - - return 0; -} - -int hid_zpff_init(struct hid_device *hid) -{ - struct zpff_device *zpff; - struct hid_report *report; - struct hid_input *hidinput = list_entry(hid->inputs.next, - struct hid_input, list); - struct list_head *report_list = - &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct input_dev *dev = hidinput->input; - int error; - - if (list_empty(report_list)) { - printk(KERN_ERR "hid-zpff: no output report found\n"); - return -ENODEV; - } - - report = list_entry(report_list->next, struct hid_report, list); - - if (report->maxfield < 4) { - printk(KERN_ERR "hid-zpff: not enough fields in report\n"); - return -ENODEV; - } - - zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL); - if (!zpff) - return -ENOMEM; - - set_bit(FF_RUMBLE, dev->ffbit); - - error = input_ff_create_memless(dev, zpff, hid_zpff_play); - if (error) { - kfree(zpff); - return error; - } - - zpff->report = report; - zpff->report->field[0]->value[0] = 0x00; - zpff->report->field[1]->value[0] = 0x02; - zpff->report->field[2]->value[0] = 0x00; - zpff->report->field[3]->value[0] = 0x00; - hid_submit_report(hid, zpff->report, USB_DIR_OUT); - - printk(KERN_INFO "Force feedback for Zeroplus based devices by " - "Anssi Hannula <anssi.hannula@gmail.com>\n"); - - return 0; -} diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h deleted file mode 100644 index 76ad68d9edf..00000000000 --- a/drivers/usb/input/hid.h +++ /dev/null @@ -1,540 +0,0 @@ -#ifndef __HID_H -#define __HID_H - -/* - * $Id: hid.h,v 1.24 2001/12/27 10:37:41 vojtech Exp $ - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2001 Vojtech Pavlik - */ - -/* - * 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 - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#include <linux/types.h> -#include <linux/slab.h> -#include <linux/list.h> -#include <linux/timer.h> -#include <linux/workqueue.h> - -/* - * USB HID (Human Interface Device) interface class code - */ - -#define USB_INTERFACE_CLASS_HID 3 - -/* - * USB HID interface subclass and protocol codes - */ - -#define USB_INTERFACE_SUBCLASS_BOOT 1 -#define USB_INTERFACE_PROTOCOL_KEYBOARD 1 -#define USB_INTERFACE_PROTOCOL_MOUSE 2 - -/* - * HID class requests - */ - -#define HID_REQ_GET_REPORT 0x01 -#define HID_REQ_GET_IDLE 0x02 -#define HID_REQ_GET_PROTOCOL 0x03 -#define HID_REQ_SET_REPORT 0x09 -#define HID_REQ_SET_IDLE 0x0A -#define HID_REQ_SET_PROTOCOL 0x0B - -/* - * HID class descriptor types - */ - -#define HID_DT_HID (USB_TYPE_CLASS | 0x01) -#define HID_DT_REPORT (USB_TYPE_CLASS | 0x02) -#define HID_DT_PHYSICAL (USB_TYPE_CLASS | 0x03) - -/* - * We parse each description item into this structure. Short items data - * values are expanded to 32-bit signed int, long items contain a pointer - * into the data area. - */ - -struct hid_item { - unsigned format; - __u8 size; - __u8 type; - __u8 tag; - union { - __u8 u8; - __s8 s8; - __u16 u16; - __s16 s16; - __u32 u32; - __s32 s32; - __u8 *longdata; - } data; -}; - -/* - * HID report item format - */ - -#define HID_ITEM_FORMAT_SHORT 0 -#define HID_ITEM_FORMAT_LONG 1 - -/* - * Special tag indicating long items - */ - -#define HID_ITEM_TAG_LONG 15 - -/* - * HID report descriptor item type (prefix bit 2,3) - */ - -#define HID_ITEM_TYPE_MAIN 0 -#define HID_ITEM_TYPE_GLOBAL 1 -#define HID_ITEM_TYPE_LOCAL 2 -#define HID_ITEM_TYPE_RESERVED 3 - -/* - * HID report descriptor main item tags - */ - -#define HID_MAIN_ITEM_TAG_INPUT 8 -#define HID_MAIN_ITEM_TAG_OUTPUT 9 -#define HID_MAIN_ITEM_TAG_FEATURE 11 -#define HID_MAIN_ITEM_TAG_BEGIN_COLLECTION 10 -#define HID_MAIN_ITEM_TAG_END_COLLECTION 12 - -/* - * HID report descriptor main item contents - */ - -#define HID_MAIN_ITEM_CONSTANT 0x001 -#define HID_MAIN_ITEM_VARIABLE 0x002 -#define HID_MAIN_ITEM_RELATIVE 0x004 -#define HID_MAIN_ITEM_WRAP 0x008 -#define HID_MAIN_ITEM_NONLINEAR 0x010 -#define HID_MAIN_ITEM_NO_PREFERRED 0x020 -#define HID_MAIN_ITEM_NULL_STATE 0x040 -#define HID_MAIN_ITEM_VOLATILE 0x080 -#define HID_MAIN_ITEM_BUFFERED_BYTE 0x100 - -/* - * HID report descriptor collection item types - */ - -#define HID_COLLECTION_PHYSICAL 0 -#define HID_COLLECTION_APPLICATION 1 -#define HID_COLLECTION_LOGICAL 2 - -/* - * HID report descriptor global item tags - */ - -#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0 -#define HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM 1 -#define HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM 2 -#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM 3 -#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM 4 -#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 5 -#define HID_GLOBAL_ITEM_TAG_UNIT 6 -#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 7 -#define HID_GLOBAL_ITEM_TAG_REPORT_ID 8 -#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 9 -#define HID_GLOBAL_ITEM_TAG_PUSH 10 -#define HID_GLOBAL_ITEM_TAG_POP 11 - -/* - * HID report descriptor local item tags - */ - -#define HID_LOCAL_ITEM_TAG_USAGE 0 -#define HID_LOCAL_ITEM_TAG_USAGE_MINIMUM 1 -#define HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM 2 -#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 3 -#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM 4 -#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM 5 -#define HID_LOCAL_ITEM_TAG_STRING_INDEX 7 -#define HID_LOCAL_ITEM_TAG_STRING_MINIMUM 8 -#define HID_LOCAL_ITEM_TAG_STRING_MAXIMUM 9 -#define HID_LOCAL_ITEM_TAG_DELIMITER 10 - -/* - * HID usage tables - */ - -#define HID_USAGE_PAGE 0xffff0000 - -#define HID_UP_UNDEFINED 0x00000000 -#define HID_UP_GENDESK 0x00010000 -#define HID_UP_SIMULATION 0x00020000 -#define HID_UP_KEYBOARD 0x00070000 -#define HID_UP_LED 0x00080000 -#define HID_UP_BUTTON 0x00090000 -#define HID_UP_ORDINAL 0x000a0000 -#define HID_UP_CONSUMER 0x000c0000 -#define HID_UP_DIGITIZER 0x000d0000 -#define HID_UP_PID 0x000f0000 -#define HID_UP_HPVENDOR 0xff7f0000 -#define HID_UP_MSVENDOR 0xff000000 -#define HID_UP_CUSTOM 0x00ff0000 -#define HID_UP_LOGIVENDOR 0xffbc0000 - -#define HID_USAGE 0x0000ffff - -#define HID_GD_POINTER 0x00010001 -#define HID_GD_MOUSE 0x00010002 -#define HID_GD_JOYSTICK 0x00010004 -#define HID_GD_GAMEPAD 0x00010005 -#define HID_GD_KEYBOARD 0x00010006 -#define HID_GD_KEYPAD 0x00010007 -#define HID_GD_MULTIAXIS 0x00010008 -#define HID_GD_X 0x00010030 -#define HID_GD_Y 0x00010031 -#define HID_GD_Z 0x00010032 -#define HID_GD_RX 0x00010033 -#define HID_GD_RY 0x00010034 -#define HID_GD_RZ 0x00010035 -#define HID_GD_SLIDER 0x00010036 -#define HID_GD_DIAL 0x00010037 -#define HID_GD_WHEEL 0x00010038 -#define HID_GD_HATSWITCH 0x00010039 -#define HID_GD_BUFFER 0x0001003a -#define HID_GD_BYTECOUNT 0x0001003b -#define HID_GD_MOTION 0x0001003c -#define HID_GD_START 0x0001003d -#define HID_GD_SELECT 0x0001003e -#define HID_GD_VX 0x00010040 -#define HID_GD_VY 0x00010041 -#define HID_GD_VZ 0x00010042 -#define HID_GD_VBRX 0x00010043 -#define HID_GD_VBRY 0x00010044 -#define HID_GD_VBRZ 0x00010045 -#define HID_GD_VNO 0x00010046 -#define HID_GD_FEATURE 0x00010047 -#define HID_GD_UP 0x00010090 -#define HID_GD_DOWN 0x00010091 -#define HID_GD_RIGHT 0x00010092 -#define HID_GD_LEFT 0x00010093 - -/* - * HID report types --- Ouch! HID spec says 1 2 3! - */ - -#define HID_INPUT_REPORT 0 -#define HID_OUTPUT_REPORT 1 -#define HID_FEATURE_REPORT 2 - -/* - * HID device quirks. - */ - -#define HID_QUIRK_INVERT 0x00000001 -#define HID_QUIRK_NOTOUCH 0x00000002 -#define HID_QUIRK_IGNORE 0x00000004 -#define HID_QUIRK_NOGET 0x00000008 -#define HID_QUIRK_HIDDEV 0x00000010 -#define HID_QUIRK_BADPAD 0x00000020 -#define HID_QUIRK_MULTI_INPUT 0x00000040 -#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080 -#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100 -#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200 -#define HID_QUIRK_MIGHTYMOUSE 0x00000400 -#define HID_QUIRK_CYMOTION 0x00000800 -#define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000 -#define HID_QUIRK_POWERBOOK_FN_ON 0x00002000 -#define HID_QUIRK_INVERT_HWHEEL 0x00004000 -#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00008000 -#define HID_QUIRK_BAD_RELATIVE_KEYS 0x00010000 - -/* - * This is the global environment of the parser. This information is - * persistent for main-items. The global environment can be saved and - * restored with PUSH/POP statements. - */ - -struct hid_global { - unsigned usage_page; - __s32 logical_minimum; - __s32 logical_maximum; - __s32 physical_minimum; - __s32 physical_maximum; - __s32 unit_exponent; - unsigned unit; - unsigned report_id; - unsigned report_size; - unsigned report_count; -}; - -/* - * This is the local environment. It is persistent up the next main-item. - */ - -#define HID_MAX_DESCRIPTOR_SIZE 4096 -#define HID_MAX_USAGES 1024 -#define HID_DEFAULT_NUM_COLLECTIONS 16 - -struct hid_local { - unsigned usage[HID_MAX_USAGES]; /* usage array */ - unsigned collection_index[HID_MAX_USAGES]; /* collection index array */ - unsigned usage_index; - unsigned usage_minimum; - unsigned delimiter_depth; - unsigned delimiter_branch; -}; - -/* - * This is the collection stack. We climb up the stack to determine - * application and function of each field. - */ - -struct hid_collection { - unsigned type; - unsigned usage; - unsigned level; -}; - -struct hid_usage { - unsigned hid; /* hid usage code */ - unsigned collection_index; /* index into collection array */ - /* hidinput data */ - __u16 code; /* input driver code */ - __u8 type; /* input driver type */ - __s8 hat_min; /* hat switch fun */ - __s8 hat_max; /* ditto */ - __s8 hat_dir; /* ditto */ -}; - -struct hid_input; - -struct hid_field { - unsigned physical; /* physical usage for this field */ - unsigned logical; /* logical usage for this field */ - unsigned application; /* application usage for this field */ - struct hid_usage *usage; /* usage table for this function */ - unsigned maxusage; /* maximum usage index */ - unsigned flags; /* main-item flags (i.e. volatile,array,constant) */ - unsigned report_offset; /* bit offset in the report */ - unsigned report_size; /* size of this field in the report */ - unsigned report_count; /* number of this field in the report */ - unsigned report_type; /* (input,output,feature) */ - __s32 *value; /* last known value(s) */ - __s32 logical_minimum; - __s32 logical_maximum; - __s32 physical_minimum; - __s32 physical_maximum; - __s32 unit_exponent; - unsigned unit; - struct hid_report *report; /* associated report */ - unsigned index; /* index into report->field[] */ - /* hidinput data */ - struct hid_input *hidinput; /* associated input structure */ - __u16 dpad; /* dpad input code */ -}; - -#define HID_MAX_FIELDS 64 - -struct hid_report { - struct list_head list; - unsigned id; /* id of this report */ - unsigned type; /* report type */ - struct hid_field *field[HID_MAX_FIELDS]; /* fields of the report */ - unsigned maxfield; /* maximum valid field index */ - unsigned size; /* size of the report (bits) */ - struct hid_device *device; /* associated device */ -}; - -struct hid_report_enum { - unsigned numbered; - struct list_head report_list; - struct hid_report *report_id_hash[256]; -}; - -#define HID_REPORT_TYPES 3 - -#define HID_MIN_BUFFER_SIZE 64 /* make sure there is at least a packet size of space */ -#define HID_MAX_BUFFER_SIZE 4096 /* 4kb */ -#define HID_CONTROL_FIFO_SIZE 256 /* to init devices with >100 reports */ -#define HID_OUTPUT_FIFO_SIZE 64 - -struct hid_control_fifo { - unsigned char dir; - struct hid_report *report; -}; - -#define HID_CLAIMED_INPUT 1 -#define HID_CLAIMED_HIDDEV 2 - -#define HID_CTRL_RUNNING 1 -#define HID_OUT_RUNNING 2 -#define HID_IN_RUNNING 3 -#define HID_RESET_PENDING 4 -#define HID_SUSPENDED 5 -#define HID_CLEAR_HALT 6 - -struct hid_input { - struct list_head list; - struct hid_report *report; - struct input_dev *input; -}; - -struct hid_device { /* device report descriptor */ - __u8 *rdesc; - unsigned rsize; - struct hid_collection *collection; /* List of HID collections */ - unsigned collection_size; /* Number of allocated hid_collections */ - unsigned maxcollection; /* Number of parsed collections */ - unsigned maxapplication; /* Number of applications */ - unsigned version; /* HID version */ - unsigned country; /* HID country */ - struct hid_report_enum report_enum[HID_REPORT_TYPES]; - - struct usb_device *dev; /* USB device */ - struct usb_interface *intf; /* USB interface */ - int ifnum; /* USB interface number */ - - unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ - struct timer_list io_retry; /* Retry timer */ - unsigned long stop_retry; /* Time to give up, in jiffies */ - unsigned int retry_delay; /* Delay length in ms */ - struct work_struct reset_work; /* Task context for resets */ - - unsigned int bufsize; /* URB buffer size */ - - struct urb *urbin; /* Input URB */ - char *inbuf; /* Input buffer */ - dma_addr_t inbuf_dma; /* Input buffer dma */ - spinlock_t inlock; /* Input fifo spinlock */ - - struct urb *urbctrl; /* Control URB */ - struct usb_ctrlrequest *cr; /* Control request struct */ - dma_addr_t cr_dma; /* Control request struct dma */ - struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE]; /* Control fifo */ - unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */ - char *ctrlbuf; /* Control buffer */ - dma_addr_t ctrlbuf_dma; /* Control buffer dma */ - spinlock_t ctrllock; /* Control fifo spinlock */ - - struct urb *urbout; /* Output URB */ - struct hid_report *out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */ - unsigned char outhead, outtail; /* Output pipe fifo head & tail */ - char *outbuf; /* Output buffer */ - dma_addr_t outbuf_dma; /* Output buffer dma */ - spinlock_t outlock; /* Output fifo spinlock */ - - unsigned claimed; /* Claimed by hidinput, hiddev? */ - unsigned quirks; /* Various quirks the device can pull on us */ - - struct list_head inputs; /* The list of inputs */ - void *hiddev; /* The hiddev structure */ - int minor; /* Hiddev minor number */ - - wait_queue_head_t wait; /* For sleeping */ - - int open; /* is the device open by anyone? */ - char name[128]; /* Device name */ - char phys[64]; /* Device physical location */ - char uniq[64]; /* Device unique identifier (serial #) */ - -#ifdef CONFIG_USB_HIDINPUT_POWERBOOK - unsigned long pb_pressed_fn[NBITS(KEY_MAX)]; - unsigned long pb_pressed_numlock[NBITS(KEY_MAX)]; -#endif -}; - -#define HID_GLOBAL_STACK_SIZE 4 -#define HID_COLLECTION_STACK_SIZE 4 - -struct hid_parser { - struct hid_global global; - struct hid_global global_stack[HID_GLOBAL_STACK_SIZE]; - unsigned global_stack_ptr; - struct hid_local local; - unsigned collection_stack[HID_COLLECTION_STACK_SIZE]; - unsigned collection_stack_ptr; - struct hid_device *device; -}; - -struct hid_class_descriptor { - __u8 bDescriptorType; - __u16 wDescriptorLength; -} __attribute__ ((packed)); - -struct hid_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u16 bcdHID; - __u8 bCountryCode; - __u8 bNumDescriptors; - - struct hid_class_descriptor desc[1]; -} __attribute__ ((packed)); - -#ifdef DEBUG -#include "hid-debug.h" -#else -#define hid_dump_input(a,b) do { } while (0) -#define hid_dump_device(c) do { } while (0) -#define hid_dump_field(a,b) do { } while (0) -#define resolv_usage(a) do { } while (0) -#define resolv_event(a,b) do { } while (0) -#endif - -#endif - -#ifdef CONFIG_USB_HIDINPUT -/* Applications from HID Usage Tables 4/8/99 Version 1.1 */ -/* We ignore a few input applications that are not widely used */ -#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001)) -extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32); -extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report); -extern int hidinput_connect(struct hid_device *); -extern void hidinput_disconnect(struct hid_device *); -#else -#define IS_INPUT_APPLICATION(a) (0) -static inline void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { } -static inline void hidinput_report_event(struct hid_device *hid, struct hid_report *report) { } -static inline int hidinput_connect(struct hid_device *hid) { return -ENODEV; } -static inline void hidinput_disconnect(struct hid_device *hid) { } -#endif - -int hid_open(struct hid_device *); -void hid_close(struct hid_device *); -int hid_set_field(struct hid_field *, unsigned, __s32); -void hid_submit_report(struct hid_device *, struct hid_report *, unsigned char dir); -void hid_init_reports(struct hid_device *hid); -int hid_wait_io(struct hid_device* hid); - - -#ifdef CONFIG_HID_FF -int hid_ff_init(struct hid_device *hid); - -int hid_lgff_init(struct hid_device *hid); -int hid_tmff_init(struct hid_device *hid); -int hid_zpff_init(struct hid_device *hid); -#ifdef CONFIG_HID_PID -int hid_pidff_init(struct hid_device *hid); -#else -static inline int hid_pidff_init(struct hid_device *hid) { return -ENODEV; } -#endif - -#else -static inline int hid_ff_init(struct hid_device *hid) { return -1; } -#endif - diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c deleted file mode 100644 index 7dc14d0cacc..00000000000 --- a/drivers/usb/input/hiddev.c +++ /dev/null @@ -1,842 +0,0 @@ -/* - * Copyright (c) 2001 Paul Stewart - * Copyright (c) 2001 Vojtech Pavlik - * - * HID char devices, giving access to raw HID device events. - * - */ - -/* - * 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 - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to Paul Stewart <stewart@wetlogic.net> - */ - -#include <linux/poll.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/smp_lock.h> -#include <linux/input.h> -#include <linux/usb.h> -#include "hid.h" -#include <linux/hiddev.h> - -#ifdef CONFIG_USB_DYNAMIC_MINORS -#define HIDDEV_MINOR_BASE 0 -#define HIDDEV_MINORS 256 -#else -#define HIDDEV_MINOR_BASE 96 -#define HIDDEV_MINORS 16 -#endif -#define HIDDEV_BUFFER_SIZE 64 - -struct hiddev { - int exist; - int open; - wait_queue_head_t wait; - struct hid_device *hid; - struct list_head list; -}; - -struct hiddev_list { - struct hiddev_usage_ref buffer[HIDDEV_BUFFER_SIZE]; - int head; - int tail; - unsigned flags; - struct fasync_struct *fasync; - struct hiddev *hiddev; - struct list_head node; -}; - -static struct hiddev *hiddev_table[HIDDEV_MINORS]; - -/* - * Find a report, given the report's type and ID. The ID can be specified - * indirectly by REPORT_ID_FIRST (which returns the first report of the given - * type) or by (REPORT_ID_NEXT | old_id), which returns the next report of the - * given type which follows old_id. - */ -static struct hid_report * -hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) -{ - unsigned int flags = rinfo->report_id & ~HID_REPORT_ID_MASK; - unsigned int rid = rinfo->report_id & HID_REPORT_ID_MASK; - struct hid_report_enum *report_enum; - struct hid_report *report; - struct list_head *list; - - if (rinfo->report_type < HID_REPORT_TYPE_MIN || - rinfo->report_type > HID_REPORT_TYPE_MAX) - return NULL; - - report_enum = hid->report_enum + - (rinfo->report_type - HID_REPORT_TYPE_MIN); - - switch (flags) { - case 0: /* Nothing to do -- report_id is already set correctly */ - break; - - case HID_REPORT_ID_FIRST: - if (list_empty(&report_enum->report_list)) - return NULL; - - list = report_enum->report_list.next; - report = list_entry(list, struct hid_report, list); - rinfo->report_id = report->id; - break; - - case HID_REPORT_ID_NEXT: - report = report_enum->report_id_hash[rid]; - if (!report) - return NULL; - - list = report->list.next; - if (list == &report_enum->report_list) - return NULL; - - report = list_entry(list, struct hid_report, list); - rinfo->report_id = report->id; - break; - - default: - return NULL; - } - - return report_enum->report_id_hash[rinfo->report_id]; -} - -/* - * Perform an exhaustive search of the report table for a usage, given its - * type and usage id. - */ -static struct hid_field * -hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref) -{ - int i, j; - struct hid_report *report; - struct hid_report_enum *report_enum; - struct hid_field *field; - - if (uref->report_type < HID_REPORT_TYPE_MIN || - uref->report_type > HID_REPORT_TYPE_MAX) - return NULL; - - report_enum = hid->report_enum + - (uref->report_type - HID_REPORT_TYPE_MIN); - - list_for_each_entry(report, &report_enum->report_list, list) { - for (i = 0; i < report->maxfield; i++) { - field = report->field[i]; - for (j = 0; j < field->maxusage; j++) { - if (field->usage[j].hid == uref->usage_code) { - uref->report_id = report->id; - uref->field_index = i; - uref->usage_index = j; - return field; - } - } - } - } - - return NULL; -} - -static void hiddev_send_event(struct hid_device *hid, - struct hiddev_usage_ref *uref) -{ - struct hiddev *hiddev = hid->hiddev; - struct hiddev_list *list; - - list_for_each_entry(list, &hiddev->list, node) { - if (uref->field_index != HID_FIELD_INDEX_NONE || - (list->flags & HIDDEV_FLAG_REPORT) != 0) { - list->buffer[list->head] = *uref; - list->head = (list->head + 1) & - (HIDDEV_BUFFER_SIZE - 1); - kill_fasync(&list->fasync, SIGIO, POLL_IN); - } - } - - wake_up_interruptible(&hiddev->wait); -} - -/* - * This is where hid.c calls into hiddev to pass an event that occurred over - * the interrupt pipe - */ -void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - unsigned type = field->report_type; - struct hiddev_usage_ref uref; - - uref.report_type = - (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : - ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : - ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); - uref.report_id = field->report->id; - uref.field_index = field->index; - uref.usage_index = (usage - field->usage); - uref.usage_code = usage->hid; - uref.value = value; - - hiddev_send_event(hid, &uref); -} - - -void hiddev_report_event(struct hid_device *hid, struct hid_report *report) -{ - unsigned type = report->type; - struct hiddev_usage_ref uref; - - memset(&uref, 0, sizeof(uref)); - uref.report_type = - (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : - ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : - ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); - uref.report_id = report->id; - uref.field_index = HID_FIELD_INDEX_NONE; - - hiddev_send_event(hid, &uref); -} -/* - * fasync file op - */ -static int hiddev_fasync(int fd, struct file *file, int on) -{ - int retval; - struct hiddev_list *list = file->private_data; - - retval = fasync_helper(fd, file, on, &list->fasync); - - return retval < 0 ? retval : 0; -} - - -/* - * release file op - */ -static int hiddev_release(struct inode * inode, struct file * file) -{ - struct hiddev_list *list = file->private_data; - - hiddev_fasync(-1, file, 0); - list_del(&list->node); - - if (!--list->hiddev->open) { - if (list->hiddev->exist) - hid_close(list->hiddev->hid); - else - kfree(list->hiddev); - } - - kfree(list); - - return 0; -} - -/* - * open file op - */ -static int hiddev_open(struct inode *inode, struct file *file) -{ - struct hiddev_list *list; - - int i = iminor(inode) - HIDDEV_MINOR_BASE; - - if (i >= HIDDEV_MINORS || !hiddev_table[i]) - return -ENODEV; - - if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL))) - return -ENOMEM; - - list->hiddev = hiddev_table[i]; - list_add_tail(&list->node, &hiddev_table[i]->list); - file->private_data = list; - - if (!list->hiddev->open++) - if (list->hiddev->exist) - hid_open(hiddev_table[i]->hid); - - return 0; -} - -/* - * "write" file op - */ -static ssize_t hiddev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) -{ - return -EINVAL; -} - -/* - * "read" file op - */ -static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) -{ - DECLARE_WAITQUEUE(wait, current); - struct hiddev_list *list = file->private_data; - int event_size; - int retval = 0; - - event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ? - sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event); - - if (count < event_size) - return 0; - - while (retval == 0) { - if (list->head == list->tail) { - add_wait_queue(&list->hiddev->wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - while (list->head == list->tail) { - if (file->f_flags & O_NONBLOCK) { - retval = -EAGAIN; - break; - } - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - if (!list->hiddev->exist) { - retval = -EIO; - break; - } - - schedule(); - set_current_state(TASK_INTERRUPTIBLE); - } - - set_current_state(TASK_RUNNING); - remove_wait_queue(&list->hiddev->wait, &wait); - } - - if (retval) - return retval; - - - while (list->head != list->tail && - retval + event_size <= count) { - if ((list->flags & HIDDEV_FLAG_UREF) == 0) { - if (list->buffer[list->tail].field_index != - HID_FIELD_INDEX_NONE) { - struct hiddev_event event; - event.hid = list->buffer[list->tail].usage_code; - event.value = list->buffer[list->tail].value; - if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event))) - return -EFAULT; - retval += sizeof(struct hiddev_event); - } - } else { - if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE || - (list->flags & HIDDEV_FLAG_REPORT) != 0) { - if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref))) - return -EFAULT; - retval += sizeof(struct hiddev_usage_ref); - } - } - list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1); - } - - } - - return retval; -} - -/* - * "poll" file op - * No kernel lock - fine - */ -static unsigned int hiddev_poll(struct file *file, poll_table *wait) -{ - struct hiddev_list *list = file->private_data; - - poll_wait(file, &list->hiddev->wait, wait); - if (list->head != list->tail) - return POLLIN | POLLRDNORM; - if (!list->hiddev->exist) - return POLLERR | POLLHUP; - return 0; -} - -/* - * "ioctl" file op - */ -static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct hiddev_list *list = file->private_data; - struct hiddev *hiddev = list->hiddev; - struct hid_device *hid = hiddev->hid; - struct usb_device *dev = hid->dev; - struct hiddev_collection_info cinfo; - struct hiddev_report_info rinfo; - struct hiddev_field_info finfo; - struct hiddev_usage_ref_multi *uref_multi = NULL; - struct hiddev_usage_ref *uref; - struct hiddev_devinfo dinfo; - struct hid_report *report; - struct hid_field *field; - void __user *user_arg = (void __user *)arg; - int i; - - if (!hiddev->exist) - return -EIO; - - switch (cmd) { - - case HIDIOCGVERSION: - return put_user(HID_VERSION, (int __user *)arg); - - case HIDIOCAPPLICATION: - if (arg < 0 || arg >= hid->maxapplication) - return -EINVAL; - - for (i = 0; i < hid->maxcollection; i++) - if (hid->collection[i].type == - HID_COLLECTION_APPLICATION && arg-- == 0) - break; - - if (i == hid->maxcollection) - return -EINVAL; - - return hid->collection[i].usage; - - case HIDIOCGDEVINFO: - dinfo.bustype = BUS_USB; - dinfo.busnum = dev->bus->busnum; - dinfo.devnum = dev->devnum; - dinfo.ifnum = hid->ifnum; - dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor); - dinfo.product = le16_to_cpu(dev->descriptor.idProduct); - dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice); - dinfo.num_applications = hid->maxapplication; - if (copy_to_user(user_arg, &dinfo, sizeof(dinfo))) - return -EFAULT; - - return 0; - - case HIDIOCGFLAG: - if (put_user(list->flags, (int __user *)arg)) - return -EFAULT; - - return 0; - - case HIDIOCSFLAG: - { - int newflags; - if (get_user(newflags, (int __user *)arg)) - return -EFAULT; - - if ((newflags & ~HIDDEV_FLAGS) != 0 || - ((newflags & HIDDEV_FLAG_REPORT) != 0 && - (newflags & HIDDEV_FLAG_UREF) == 0)) - return -EINVAL; - - list->flags = newflags; - - return 0; - } - - case HIDIOCGSTRING: - { - int idx, len; - char *buf; - - if (get_user(idx, (int __user *)arg)) - return -EFAULT; - - if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL) - return -ENOMEM; - - if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) { - kfree(buf); - return -EINVAL; - } - - if (copy_to_user(user_arg+sizeof(int), buf, len+1)) { - kfree(buf); - return -EFAULT; - } - - kfree(buf); - - return len; - } - - case HIDIOCINITREPORT: - hid_init_reports(hid); - - return 0; - - case HIDIOCGREPORT: - if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) - return -EFAULT; - - if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT) - return -EINVAL; - - if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) - return -EINVAL; - - hid_submit_report(hid, report, USB_DIR_IN); - hid_wait_io(hid); - - return 0; - - case HIDIOCSREPORT: - if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) - return -EFAULT; - - if (rinfo.report_type == HID_REPORT_TYPE_INPUT) - return -EINVAL; - - if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) - return -EINVAL; - - hid_submit_report(hid, report, USB_DIR_OUT); - hid_wait_io(hid); - - return 0; - - case HIDIOCGREPORTINFO: - if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) - return -EFAULT; - - if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) - return -EINVAL; - - rinfo.num_fields = report->maxfield; - - if (copy_to_user(user_arg, &rinfo, sizeof(rinfo))) - return -EFAULT; - - return 0; - - case HIDIOCGFIELDINFO: - if (copy_from_user(&finfo, user_arg, sizeof(finfo))) - return -EFAULT; - rinfo.report_type = finfo.report_type; - rinfo.report_id = finfo.report_id; - if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) - return -EINVAL; - - if (finfo.field_index >= report->maxfield) - return -EINVAL; - - field = report->field[finfo.field_index]; - memset(&finfo, 0, sizeof(finfo)); - finfo.report_type = rinfo.report_type; - finfo.report_id = rinfo.report_id; - finfo.field_index = field->report_count - 1; - finfo.maxusage = field->maxusage; - finfo.flags = field->flags; - finfo.physical = field->physical; - finfo.logical = field->logical; - finfo.application = field->application; - finfo.logical_minimum = field->logical_minimum; - finfo.logical_maximum = field->logical_maximum; - finfo.physical_minimum = field->physical_minimum; - finfo.physical_maximum = field->physical_maximum; - finfo.unit_exponent = field->unit_exponent; - finfo.unit = field->unit; - - if (copy_to_user(user_arg, &finfo, sizeof(finfo))) - return -EFAULT; - - return 0; - - case HIDIOCGUCODE: - uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL); - if (!uref_multi) - return -ENOMEM; - uref = &uref_multi->uref; - if (copy_from_user(uref, user_arg, sizeof(*uref))) - goto fault; - - rinfo.report_type = uref->report_type; - rinfo.report_id = uref->report_id; - if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) - goto inval; - - if (uref->field_index >= report->maxfield) - goto inval; - - field = report->field[uref->field_index]; - if (uref->usage_index >= field->maxusage) - goto inval; - - uref->usage_code = field->usage[uref->usage_index].hid; - - if (copy_to_user(user_arg, uref, sizeof(*uref))) - goto fault; - - kfree(uref_multi); - return 0; - - case HIDIOCGUSAGE: - case HIDIOCSUSAGE: - case HIDIOCGUSAGES: - case HIDIOCSUSAGES: - case HIDIOCGCOLLECTIONINDEX: - uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL); - if (!uref_multi) - return -ENOMEM; - uref = &uref_multi->uref; - if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { - if (copy_from_user(uref_multi, user_arg, - sizeof(*uref_multi))) - goto fault; - } else { - if (copy_from_user(uref, user_arg, sizeof(*uref))) - goto fault; - } - - if (cmd != HIDIOCGUSAGE && - cmd != HIDIOCGUSAGES && - uref->report_type == HID_REPORT_TYPE_INPUT) - goto inval; - - if (uref->report_id == HID_REPORT_ID_UNKNOWN) { - field = hiddev_lookup_usage(hid, uref); - if (field == NULL) - goto inval; - } else { - rinfo.report_type = uref->report_type; - rinfo.report_id = uref->report_id; - if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) - goto inval; - - if (uref->field_index >= report->maxfield) - goto inval; - - field = report->field[uref->field_index]; - - if (cmd == HIDIOCGCOLLECTIONINDEX) { - if (uref->usage_index >= field->maxusage) - goto inval; - } else if (uref->usage_index >= field->report_count) - goto inval; - - else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && - (uref_multi->num_values > HID_MAX_MULTI_USAGES || - uref->usage_index + uref_multi->num_values > field->report_count)) - goto inval; - } - - switch (cmd) { - case HIDIOCGUSAGE: - uref->value = field->value[uref->usage_index]; - if (copy_to_user(user_arg, uref, sizeof(*uref))) - goto fault; - goto goodreturn; - - case HIDIOCSUSAGE: - field->value[uref->usage_index] = uref->value; - goto goodreturn; - - case HIDIOCGCOLLECTIONINDEX: - kfree(uref_multi); - return field->usage[uref->usage_index].collection_index; - case HIDIOCGUSAGES: - for (i = 0; i < uref_multi->num_values; i++) - uref_multi->values[i] = - field->value[uref->usage_index + i]; - if (copy_to_user(user_arg, uref_multi, - sizeof(*uref_multi))) - goto fault; - goto goodreturn; - case HIDIOCSUSAGES: - for (i = 0; i < uref_multi->num_values; i++) - field->value[uref->usage_index + i] = - uref_multi->values[i]; - goto goodreturn; - } - -goodreturn: - kfree(uref_multi); - return 0; -fault: - kfree(uref_multi); - return -EFAULT; -inval: - kfree(uref_multi); - return -EINVAL; - - case HIDIOCGCOLLECTIONINFO: - if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) - return -EFAULT; - - if (cinfo.index >= hid->maxcollection) - return -EINVAL; - - cinfo.type = hid->collection[cinfo.index].type; - cinfo.usage = hid->collection[cinfo.index].usage; - cinfo.level = hid->collection[cinfo.index].level; - - if (copy_to_user(user_arg, &cinfo, sizeof(cinfo))) - return -EFAULT; - return 0; - - default: - - if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) - return -EINVAL; - - if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) { - int len; - if (!hid->name) - return 0; - len = strlen(hid->name) + 1; - if (len > _IOC_SIZE(cmd)) - len = _IOC_SIZE(cmd); - return copy_to_user(user_arg, hid->name, len) ? - -EFAULT : len; - } - - if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGPHYS(0))) { - int len; - if (!hid->phys) - return 0; - len = strlen(hid->phys) + 1; - if (len > _IOC_SIZE(cmd)) - len = _IOC_SIZE(cmd); - return copy_to_user(user_arg, hid->phys, len) ? - -EFAULT : len; - } - } - return -EINVAL; -} - -static const struct file_operations hiddev_fops = { - .owner = THIS_MODULE, - .read = hiddev_read, - .write = hiddev_write, - .poll = hiddev_poll, - .open = hiddev_open, - .release = hiddev_release, - .ioctl = hiddev_ioctl, - .fasync = hiddev_fasync, -}; - -static struct usb_class_driver hiddev_class = { - .name = "hiddev%d", - .fops = &hiddev_fops, - .minor_base = HIDDEV_MINOR_BASE, -}; - -/* - * This is where hid.c calls us to connect a hid device to the hiddev driver - */ -int hiddev_connect(struct hid_device *hid) -{ - struct hiddev *hiddev; - int i; - int retval; - - for (i = 0; i < hid->maxcollection; i++) - if (hid->collection[i].type == - HID_COLLECTION_APPLICATION && - !IS_INPUT_APPLICATION(hid->collection[i].usage)) - break; - - if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0) - return -1; - - if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL))) - return -1; - - retval = usb_register_dev(hid->intf, &hiddev_class); - if (retval) { - err("Not able to get a minor for this device."); - kfree(hiddev); - return -1; - } - - init_waitqueue_head(&hiddev->wait); - INIT_LIST_HEAD(&hiddev->list); - hiddev->hid = hid; - hiddev->exist = 1; - - hid->minor = hid->intf->minor; - hid->hiddev = hiddev; - - hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; - - return 0; -} - -/* - * This is where hid.c calls us to disconnect a hiddev device from the - * corresponding hid device (usually because the usb device has disconnected) - */ -static struct usb_class_driver hiddev_class; -void hiddev_disconnect(struct hid_device *hid) -{ - struct hiddev *hiddev = hid->hiddev; - - hiddev->exist = 0; - - hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL; - usb_deregister_dev(hiddev->hid->intf, &hiddev_class); - - if (hiddev->open) { - hid_close(hiddev->hid); - wake_up_interruptible(&hiddev->wait); - } else { - kfree(hiddev); - } -} - -/* Currently this driver is a USB driver. It's not a conventional one in - * the sense that it doesn't probe at the USB level. Instead it waits to - * be connected by HID through the hiddev_connect / hiddev_disconnect - * routines. The reason to register as a USB device is to gain part of the - * minor number space from the USB major. - * - * In theory, should the HID code be generalized to more than one physical - * medium (say, IEEE 1384), this driver will probably need to register its - * own major number, and in doing so, no longer need to register with USB. - * At that point the probe routine and hiddev_driver struct below will no - * longer be useful. - */ - - -/* We never attach in this manner, and rely on HID to connect us. This - * is why there is no disconnect routine defined in the usb_driver either. - */ -static int hiddev_usbd_probe(struct usb_interface *intf, - const struct usb_device_id *hiddev_info) -{ - return -ENODEV; -} - - -static /* const */ struct usb_driver hiddev_driver = { - .name = "hiddev", - .probe = hiddev_usbd_probe, -}; - -int __init hiddev_init(void) -{ - return usb_register(&hiddev_driver); -} - -void hiddev_exit(void) -{ - usb_deregister(&hiddev_driver); -} diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c deleted file mode 100644 index aac968aab86..00000000000 --- a/drivers/usb/input/itmtouch.c +++ /dev/null @@ -1,271 +0,0 @@ -/****************************************************************************** - * itmtouch.c -- Driver for ITM touchscreen panel - * - * 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. - * - * Based upon original work by Chris Collins <xfire-itmtouch@xware.cx>. - * - * Kudos to ITM for providing me with the datasheet for the panel, - * even though it was a day later than I had finished writing this - * driver. - * - * It has meant that I've been able to correct my interpretation of the - * protocol packets however. - * - * CC -- 2003/9/29 - * - * History - * 1.0 & 1.1 2003 (CC) vojtech@suse.cz - * Original version for 2.4.x kernels - * - * 1.2 02/03/2005 (HCE) hc@mivu.no - * Complete rewrite to support Linux 2.6.10, thanks to mtouchusb.c for hints. - * Unfortunately no calibration support at this time. - * - * 1.2.1 09/03/2005 (HCE) hc@mivu.no - * Code cleanup and adjusting syntax to start matching kernel standards - * - * 1.2.2 10/05/2006 (MJA) massad@gmail.com - * Flag for detecting if the screen was being touch was incorrectly - * inverted, so no touch events were being detected. - * - *****************************************************************************/ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/usb/input.h> - -/* only an 8 byte buffer necessary for a single packet */ -#define ITM_BUFSIZE 8 -#define PATH_SIZE 64 - -#define USB_VENDOR_ID_ITMINC 0x0403 -#define USB_PRODUCT_ID_TOUCHPANEL 0xf9e9 - -#define DRIVER_AUTHOR "Hans-Christian Egtvedt <hc@mivu.no>" -#define DRIVER_VERSION "v1.2.2" -#define DRIVER_DESC "USB ITM Inc Touch Panel Driver" -#define DRIVER_LICENSE "GPL" - -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_LICENSE( DRIVER_LICENSE ); - -struct itmtouch_dev { - struct usb_device *usbdev; /* usb device */ - struct input_dev *inputdev; /* input device */ - struct urb *readurb; /* urb */ - char rbuf[ITM_BUFSIZE]; /* data */ - int users; - char name[128]; - char phys[64]; -}; - -static struct usb_device_id itmtouch_ids [] = { - { USB_DEVICE(USB_VENDOR_ID_ITMINC, USB_PRODUCT_ID_TOUCHPANEL) }, - { } -}; - -static void itmtouch_irq(struct urb *urb) -{ - struct itmtouch_dev *itmtouch = urb->context; - unsigned char *data = urb->transfer_buffer; - struct input_dev *dev = itmtouch->inputdev; - 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; - } - - /* if pressure has been released, then don't report X/Y */ - if (!(data[7] & 0x20)) { - input_report_abs(dev, ABS_X, (data[0] & 0x1F) << 7 | (data[3] & 0x7F)); - input_report_abs(dev, ABS_Y, (data[1] & 0x1F) << 7 | (data[4] & 0x7F)); - } - - input_report_abs(dev, ABS_PRESSURE, (data[2] & 1) << 7 | (data[5] & 0x7F)); - input_report_key(dev, BTN_TOUCH, ~data[7] & 0x20); - input_sync(dev); - -exit: - retval = usb_submit_urb (urb, GFP_ATOMIC); - if (retval) - printk(KERN_ERR "%s - usb_submit_urb failed with result: %d", - __FUNCTION__, retval); -} - -static int itmtouch_open(struct input_dev *input) -{ - struct itmtouch_dev *itmtouch = input->private; - - itmtouch->readurb->dev = itmtouch->usbdev; - - if (usb_submit_urb(itmtouch->readurb, GFP_KERNEL)) - return -EIO; - - return 0; -} - -static void itmtouch_close(struct input_dev *input) -{ - struct itmtouch_dev *itmtouch = input->private; - - usb_kill_urb(itmtouch->readurb); -} - -static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct itmtouch_dev *itmtouch; - struct input_dev *input_dev; - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct usb_device *udev = interface_to_usbdev(intf); - unsigned int pipe; - unsigned int maxp; - - interface = intf->cur_altsetting; - endpoint = &interface->endpoint[0].desc; - - itmtouch = kzalloc(sizeof(struct itmtouch_dev), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!itmtouch || !input_dev) { - err("%s - Out of memory.", __FUNCTION__); - goto fail; - } - - itmtouch->usbdev = udev; - itmtouch->inputdev = input_dev; - - if (udev->manufacturer) - strlcpy(itmtouch->name, udev->manufacturer, sizeof(itmtouch->name)); - - if (udev->product) { - if (udev->manufacturer) - strlcat(itmtouch->name, " ", sizeof(itmtouch->name)); - strlcat(itmtouch->name, udev->product, sizeof(itmtouch->name)); - } - - if (!strlen(itmtouch->name)) - sprintf(itmtouch->name, "USB ITM touchscreen"); - - usb_make_path(udev, itmtouch->phys, sizeof(itmtouch->phys)); - strlcpy(itmtouch->phys, "/input0", sizeof(itmtouch->phys)); - - input_dev->name = itmtouch->name; - input_dev->phys = itmtouch->phys; - usb_to_input_id(udev, &input_dev->id); - input_dev->cdev.dev = &intf->dev; - input_dev->private = itmtouch; - - input_dev->open = itmtouch_open; - input_dev->close = itmtouch_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_TOUCH)] = BIT(BTN_TOUCH); - - /* device limits */ - /* as specified by the ITM datasheet, X and Y are 12bit, - * Z (pressure) is 8 bit. However, the fields are defined up - * to 14 bits for future possible expansion. - */ - input_set_abs_params(input_dev, ABS_X, 0, 0x0FFF, 2, 0); - input_set_abs_params(input_dev, ABS_Y, 0, 0x0FFF, 2, 0); - input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xFF, 2, 0); - - /* initialise the URB so we can read from the transport stream */ - pipe = usb_rcvintpipe(itmtouch->usbdev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); - - if (maxp > ITM_BUFSIZE) - maxp = ITM_BUFSIZE; - - itmtouch->readurb = usb_alloc_urb(0, GFP_KERNEL); - if (!itmtouch->readurb) { - dbg("%s - usb_alloc_urb failed: itmtouch->readurb", __FUNCTION__); - goto fail; - } - - usb_fill_int_urb(itmtouch->readurb, itmtouch->usbdev, pipe, itmtouch->rbuf, - maxp, itmtouch_irq, itmtouch, endpoint->bInterval); - - input_register_device(itmtouch->inputdev); - - usb_set_intfdata(intf, itmtouch); - - return 0; - - fail: input_free_device(input_dev); - kfree(itmtouch); - return -ENOMEM; -} - -static void itmtouch_disconnect(struct usb_interface *intf) -{ - struct itmtouch_dev *itmtouch = usb_get_intfdata(intf); - - usb_set_intfdata(intf, NULL); - - if (itmtouch) { - input_unregister_device(itmtouch->inputdev); - usb_kill_urb(itmtouch->readurb); - usb_free_urb(itmtouch->readurb); - kfree(itmtouch); - } -} - -MODULE_DEVICE_TABLE(usb, itmtouch_ids); - -static struct usb_driver itmtouch_driver = { - .name = "itmtouch", - .probe = itmtouch_probe, - .disconnect = itmtouch_disconnect, - .id_table = itmtouch_ids, -}; - -static int __init itmtouch_init(void) -{ - info(DRIVER_DESC " " DRIVER_VERSION); - info(DRIVER_AUTHOR); - return usb_register(&itmtouch_driver); -} - -static void __exit itmtouch_exit(void) -{ - usb_deregister(&itmtouch_driver); -} - -module_init(itmtouch_init); -module_exit(itmtouch_exit); diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c deleted file mode 100644 index fedbcb127c2..00000000000 --- a/drivers/usb/input/kbtab.c +++ /dev/null @@ -1,220 +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 = dev->private; - - 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 = dev->private; - - 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; - - 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->cdev.dev = &intf->dev; - input_dev->private = 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; - - input_register_device(kbtab->dev); - - usb_set_intfdata(intf, kbtab); - return 0; - -fail2: usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma); -fail1: input_free_device(input_dev); - kfree(kbtab); - return -ENOMEM; -} - -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 98bd323369c..00000000000 --- a/drivers/usb/input/keyspan_remote.c +++ /dev/null @@ -1,589 +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 = dev->private; - - 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 = dev->private; - - 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, retval; - - 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) { - retval = -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) { - retval = -ENOMEM; - goto fail1; - } - - remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!remote->irq_urb) { - retval = -ENOMEM; - goto fail2; - } - - retval = keyspan_setup(udev); - if (retval) { - retval = -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->cdev.dev = &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_dev->private = 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 */ - input_register_device(remote->input); - - /* 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 retval; -} - -/* - * 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/mtouchusb.c b/drivers/usb/input/mtouchusb.c deleted file mode 100644 index 92c4e07da4c..00000000000 --- a/drivers/usb/input/mtouchusb.c +++ /dev/null @@ -1,332 +0,0 @@ -/****************************************************************************** - * mtouchusb.c -- Driver for Microtouch (Now 3M) USB Touchscreens - * - * 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. - * - * Based upon original work by Radoslaw Garbacz (usb-support@ite.pl) - * (http://freshmeat.net/projects/3mtouchscreendriver) - * - * History - * - * 0.3 & 0.4 2002 (TEJ) tejohnson@yahoo.com - * Updated to 2.4.18, then 2.4.19 - * Old version still relied on stealing a minor - * - * 0.5 02/26/2004 (TEJ) tejohnson@yahoo.com - * Complete rewrite using Linux Input in 2.6.3 - * Unfortunately no calibration support at this time - * - * 1.4 04/25/2004 (TEJ) tejohnson@yahoo.com - * Changed reset from standard USB dev reset to vendor reset - * Changed data sent to host from compensated to raw coordinates - * Eliminated vendor/product module params - * Performed multiple successful tests with an EXII-5010UC - * - * 1.5 02/27/2005 ddstreet@ieee.org - * Added module parameter to select raw or hw-calibrated coordinate reporting - * - *****************************************************************************/ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/usb/input.h> - -#define MTOUCHUSB_MIN_XC 0x0 -#define MTOUCHUSB_MAX_RAW_XC 0x4000 -#define MTOUCHUSB_MAX_CALIB_XC 0xffff -#define MTOUCHUSB_XC_FUZZ 0x0 -#define MTOUCHUSB_XC_FLAT 0x0 -#define MTOUCHUSB_MIN_YC 0x0 -#define MTOUCHUSB_MAX_RAW_YC 0x4000 -#define MTOUCHUSB_MAX_CALIB_YC 0xffff -#define MTOUCHUSB_YC_FUZZ 0x0 -#define MTOUCHUSB_YC_FLAT 0x0 - -#define MTOUCHUSB_ASYNC_REPORT 1 -#define MTOUCHUSB_RESET 7 -#define MTOUCHUSB_REPORT_DATA_SIZE 11 -#define MTOUCHUSB_REQ_CTRLLR_ID 10 - -#define MTOUCHUSB_GET_RAW_XC(data) (data[8]<<8 | data[7]) -#define MTOUCHUSB_GET_CALIB_XC(data) (data[4]<<8 | data[3]) -#define MTOUCHUSB_GET_RAW_YC(data) (data[10]<<8 | data[9]) -#define MTOUCHUSB_GET_CALIB_YC(data) (data[6]<<8 | data[5]) -#define MTOUCHUSB_GET_XC(data) (raw_coordinates ? \ - MTOUCHUSB_GET_RAW_XC(data) : \ - MTOUCHUSB_GET_CALIB_XC(data)) -#define MTOUCHUSB_GET_YC(data) (raw_coordinates ? \ - MTOUCHUSB_GET_RAW_YC(data) : \ - MTOUCHUSB_GET_CALIB_YC(data)) -#define MTOUCHUSB_GET_TOUCHED(data) ((data[2] & 0x40) ? 1:0) - -#define DRIVER_VERSION "v1.5" -#define DRIVER_AUTHOR "Todd E. Johnson, tejohnson@yahoo.com" -#define DRIVER_DESC "3M USB Touchscreen Driver" -#define DRIVER_LICENSE "GPL" - -static int raw_coordinates = 1; - -module_param(raw_coordinates, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(raw_coordinates, "report raw coordinate values (y, default) or hardware-calibrated coordinate values (n)"); - -struct mtouch_usb { - unsigned char *data; - dma_addr_t data_dma; - struct urb *irq; - struct usb_device *udev; - struct input_dev *input; - char name[128]; - char phys[64]; -}; - -static struct usb_device_id mtouchusb_devices[] = { - { USB_DEVICE(0x0596, 0x0001) }, - { } -}; - -static void mtouchusb_irq(struct urb *urb) -{ - struct mtouch_usb *mtouch = 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; - } - - input_report_key(mtouch->input, BTN_TOUCH, - MTOUCHUSB_GET_TOUCHED(mtouch->data)); - input_report_abs(mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data)); - input_report_abs(mtouch->input, ABS_Y, - (raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC) - - MTOUCHUSB_GET_YC(mtouch->data)); - input_sync(mtouch->input); - -exit: - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - err("%s - usb_submit_urb failed with result: %d", - __FUNCTION__, retval); -} - -static int mtouchusb_open(struct input_dev *input) -{ - struct mtouch_usb *mtouch = input->private; - - mtouch->irq->dev = mtouch->udev; - - if (usb_submit_urb(mtouch->irq, GFP_ATOMIC)) - return -EIO; - - return 0; -} - -static void mtouchusb_close(struct input_dev *input) -{ - struct mtouch_usb *mtouch = input->private; - - usb_kill_urb(mtouch->irq); -} - -static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) -{ - dbg("%s - called", __FUNCTION__); - - mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_DATA_SIZE, - GFP_ATOMIC, &mtouch->data_dma); - - if (!mtouch->data) - return -1; - - return 0; -} - -static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) -{ - dbg("%s - called", __FUNCTION__); - - if (mtouch->data) - usb_buffer_free(udev, MTOUCHUSB_REPORT_DATA_SIZE, - mtouch->data, mtouch->data_dma); -} - -static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct mtouch_usb *mtouch; - struct input_dev *input_dev; - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct usb_device *udev = interface_to_usbdev(intf); - int nRet; - - dbg("%s - called", __FUNCTION__); - - dbg("%s - setting interface", __FUNCTION__); - interface = intf->cur_altsetting; - - dbg("%s - setting endpoint", __FUNCTION__); - endpoint = &interface->endpoint[0].desc; - - mtouch = kzalloc(sizeof(struct mtouch_usb), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!mtouch || !input_dev) { - err("%s - Out of memory.", __FUNCTION__); - goto fail1; - } - - dbg("%s - allocating buffers", __FUNCTION__); - if (mtouchusb_alloc_buffers(udev, mtouch)) - goto fail2; - - mtouch->udev = udev; - mtouch->input = input_dev; - - if (udev->manufacturer) - strlcpy(mtouch->name, udev->manufacturer, sizeof(mtouch->name)); - - if (udev->product) { - if (udev->manufacturer) - strlcat(mtouch->name, " ", sizeof(mtouch->name)); - strlcat(mtouch->name, udev->product, sizeof(mtouch->name)); - } - - if (!strlen(mtouch->name)) - snprintf(mtouch->name, sizeof(mtouch->name), - "USB Touchscreen %04x:%04x", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); - - usb_make_path(udev, mtouch->phys, sizeof(mtouch->phys)); - strlcpy(mtouch->phys, "/input0", sizeof(mtouch->phys)); - - input_dev->name = mtouch->name; - input_dev->phys = mtouch->phys; - usb_to_input_id(udev, &input_dev->id); - input_dev->cdev.dev = &intf->dev; - input_dev->private = mtouch; - - input_dev->open = mtouchusb_open; - input_dev->close = mtouchusb_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, MTOUCHUSB_MIN_XC, - raw_coordinates ? MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC, - MTOUCHUSB_XC_FUZZ, MTOUCHUSB_XC_FLAT); - input_set_abs_params(input_dev, ABS_Y, MTOUCHUSB_MIN_YC, - raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC, - MTOUCHUSB_YC_FUZZ, MTOUCHUSB_YC_FLAT); - - nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(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__, nRet); - - dbg("%s - usb_alloc_urb: mtouch->irq", __FUNCTION__); - mtouch->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!mtouch->irq) { - dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__); - goto fail2; - } - - dbg("%s - usb_fill_int_urb", __FUNCTION__); - usb_fill_int_urb(mtouch->irq, mtouch->udev, - usb_rcvintpipe(mtouch->udev, 0x81), - mtouch->data, MTOUCHUSB_REPORT_DATA_SIZE, - mtouchusb_irq, mtouch, endpoint->bInterval); - - dbg("%s - input_register_device", __FUNCTION__); - input_register_device(mtouch->input); - - nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(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__, nRet); - - usb_set_intfdata(intf, mtouch); - return 0; - -fail2: mtouchusb_free_buffers(udev, mtouch); -fail1: input_free_device(input_dev); - kfree(mtouch); - return -ENOMEM; -} - -static void mtouchusb_disconnect(struct usb_interface *intf) -{ - struct mtouch_usb *mtouch = usb_get_intfdata(intf); - - dbg("%s - called", __FUNCTION__); - usb_set_intfdata(intf, NULL); - if (mtouch) { - dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__); - usb_kill_urb(mtouch->irq); - input_unregister_device(mtouch->input); - usb_free_urb(mtouch->irq); - mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch); - kfree(mtouch); - } -} - -MODULE_DEVICE_TABLE(usb, mtouchusb_devices); - -static struct usb_driver mtouchusb_driver = { - .name = "mtouchusb", - .probe = mtouchusb_probe, - .disconnect = mtouchusb_disconnect, - .id_table = mtouchusb_devices, -}; - -static int __init mtouchusb_init(void) -{ - dbg("%s - called", __FUNCTION__); - return usb_register(&mtouchusb_driver); -} - -static void __exit mtouchusb_cleanup(void) -{ - dbg("%s - called", __FUNCTION__); - usb_deregister(&mtouchusb_driver); -} - -module_init(mtouchusb_init); -module_exit(mtouchusb_cleanup); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c deleted file mode 100644 index fea97e5437f..00000000000 --- a/drivers/usb/input/powermate.c +++ /dev/null @@ -1,460 +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 = dev->private; - - 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 err = -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->cdev.dev = &intf->dev; - input_dev->private = 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)) { - err = -EIO; - goto fail4; - } - - input_register_device(pm->input); - - /* 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; - -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 err; -} - -/* 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/touchkitusb.c b/drivers/usb/input/touchkitusb.c deleted file mode 100644 index 2a314b06592..00000000000 --- a/drivers/usb/input/touchkitusb.c +++ /dev/null @@ -1,392 +0,0 @@ -/****************************************************************************** - * touchkitusb.c -- Driver for eGalax TouchKit USB Touchscreens - * - * Copyright (C) 2004-2005 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. - * - * Based upon mtouchusb.c - * - *****************************************************************************/ - -//#define DEBUG - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/usb/input.h> - -#define TOUCHKIT_MIN_XC 0x0 -#define TOUCHKIT_MAX_XC 0x07ff -#define TOUCHKIT_XC_FUZZ 0x0 -#define TOUCHKIT_XC_FLAT 0x0 -#define TOUCHKIT_MIN_YC 0x0 -#define TOUCHKIT_MAX_YC 0x07ff -#define TOUCHKIT_YC_FUZZ 0x0 -#define TOUCHKIT_YC_FLAT 0x0 -#define TOUCHKIT_REPORT_DATA_SIZE 16 - -#define TOUCHKIT_DOWN 0x01 - -#define TOUCHKIT_PKT_TYPE_MASK 0xFE -#define TOUCHKIT_PKT_TYPE_REPT 0x80 -#define TOUCHKIT_PKT_TYPE_DIAG 0x0A - -#define DRIVER_VERSION "v0.1" -#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" -#define DRIVER_DESC "eGalax TouchKit USB HID 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."); - -struct touchkit_usb { - unsigned char *data; - dma_addr_t data_dma; - char buffer[TOUCHKIT_REPORT_DATA_SIZE]; - int buf_len; - struct urb *irq; - struct usb_device *udev; - struct input_dev *input; - char name[128]; - char phys[64]; -}; - -static struct usb_device_id touchkit_devices[] = { - {USB_DEVICE(0x3823, 0x0001)}, - {USB_DEVICE(0x0123, 0x0001)}, - {USB_DEVICE(0x0eef, 0x0001)}, - {USB_DEVICE(0x0eef, 0x0002)}, - {} -}; - -/* helpers to read the data */ -static inline int touchkit_get_touched(char *data) -{ - return (data[0] & TOUCHKIT_DOWN) ? 1 : 0; -} - -static inline int touchkit_get_x(char *data) -{ - return ((data[3] & 0x0F) << 7) | (data[4] & 0x7F); -} - -static inline int touchkit_get_y(char *data) -{ - return ((data[1] & 0x0F) << 7) | (data[2] & 0x7F); -} - - -/* processes one input packet. */ -static void touchkit_process_pkt(struct touchkit_usb *touchkit, char *pkt) -{ - int x, y; - - /* only process report packets */ - if ((pkt[0] & TOUCHKIT_PKT_TYPE_MASK) != TOUCHKIT_PKT_TYPE_REPT) - return; - - if (swap_xy) { - y = touchkit_get_x(pkt); - x = touchkit_get_y(pkt); - } else { - x = touchkit_get_x(pkt); - y = touchkit_get_y(pkt); - } - - input_report_key(touchkit->input, BTN_TOUCH, touchkit_get_touched(pkt)); - input_report_abs(touchkit->input, ABS_X, x); - input_report_abs(touchkit->input, ABS_Y, y); - input_sync(touchkit->input); -} - - -static int touchkit_get_pkt_len(char *buf) -{ - switch (buf[0] & TOUCHKIT_PKT_TYPE_MASK) { - case TOUCHKIT_PKT_TYPE_REPT: - return 5; - - case TOUCHKIT_PKT_TYPE_DIAG: - return buf[1] + 2; - } - - return 0; -} - -static void touchkit_process(struct touchkit_usb *touchkit, int len) -{ - char *buffer; - int pkt_len, buf_len, pos; - - /* if the buffer contains data, append */ - if (unlikely(touchkit->buf_len)) { - int tmp; - - /* if only 1 byte in buffer, add another one to get length */ - if (touchkit->buf_len == 1) - touchkit->buffer[1] = touchkit->data[0]; - - pkt_len = touchkit_get_pkt_len(touchkit->buffer); - - /* unknown packet: drop everything */ - if (!pkt_len) - return; - - /* append, process */ - tmp = pkt_len - touchkit->buf_len; - memcpy(touchkit->buffer + touchkit->buf_len, touchkit->data, tmp); - touchkit_process_pkt(touchkit, touchkit->buffer); - - buffer = touchkit->data + tmp; - buf_len = len - tmp; - } else { - buffer = touchkit->data; - buf_len = len; - } - - /* only one byte left in buffer */ - if (unlikely(buf_len == 1)) { - touchkit->buffer[0] = buffer[0]; - touchkit->buf_len = 1; - return; - } - - /* loop over the buffer */ - pos = 0; - while (pos < buf_len) { - /* get packet len */ - pkt_len = touchkit_get_pkt_len(buffer + pos); - - /* unknown packet: drop everything */ - if (unlikely(!pkt_len)) - return; - - /* full packet: process */ - if (likely(pkt_len <= buf_len)) { - touchkit_process_pkt(touchkit, buffer + pos); - } else { - /* incomplete packet: save in buffer */ - memcpy(touchkit->buffer, buffer + pos, buf_len - pos); - touchkit->buf_len = buf_len - pos; - } - pos += pkt_len; - } -} - - -static void touchkit_irq(struct urb *urb) -{ - struct touchkit_usb *touchkit = 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; - } - - touchkit_process(touchkit, 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 touchkit_open(struct input_dev *input) -{ - struct touchkit_usb *touchkit = input->private; - - touchkit->irq->dev = touchkit->udev; - - if (usb_submit_urb(touchkit->irq, GFP_ATOMIC)) - return -EIO; - - return 0; -} - -static void touchkit_close(struct input_dev *input) -{ - struct touchkit_usb *touchkit = input->private; - - usb_kill_urb(touchkit->irq); -} - -static int touchkit_alloc_buffers(struct usb_device *udev, - struct touchkit_usb *touchkit) -{ - touchkit->data = usb_buffer_alloc(udev, TOUCHKIT_REPORT_DATA_SIZE, - GFP_ATOMIC, &touchkit->data_dma); - - if (!touchkit->data) - return -1; - - return 0; -} - -static void touchkit_free_buffers(struct usb_device *udev, - struct touchkit_usb *touchkit) -{ - if (touchkit->data) - usb_buffer_free(udev, TOUCHKIT_REPORT_DATA_SIZE, - touchkit->data, touchkit->data_dma); -} - -static int touchkit_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct touchkit_usb *touchkit; - struct input_dev *input_dev; - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct usb_device *udev = interface_to_usbdev(intf); - - interface = intf->cur_altsetting; - endpoint = &interface->endpoint[0].desc; - - touchkit = kzalloc(sizeof(struct touchkit_usb), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!touchkit || !input_dev) - goto out_free; - - if (touchkit_alloc_buffers(udev, touchkit)) - goto out_free; - - touchkit->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!touchkit->irq) { - dbg("%s - usb_alloc_urb failed: touchkit->irq", __FUNCTION__); - goto out_free_buffers; - } - - touchkit->udev = udev; - touchkit->input = input_dev; - - if (udev->manufacturer) - strlcpy(touchkit->name, udev->manufacturer, sizeof(touchkit->name)); - - if (udev->product) { - if (udev->manufacturer) - strlcat(touchkit->name, " ", sizeof(touchkit->name)); - strlcat(touchkit->name, udev->product, sizeof(touchkit->name)); - } - - if (!strlen(touchkit->name)) - snprintf(touchkit->name, sizeof(touchkit->name), - "USB Touchscreen %04x:%04x", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); - - usb_make_path(udev, touchkit->phys, sizeof(touchkit->phys)); - strlcpy(touchkit->phys, "/input0", sizeof(touchkit->phys)); - - input_dev->name = touchkit->name; - input_dev->phys = touchkit->phys; - usb_to_input_id(udev, &input_dev->id); - input_dev->cdev.dev = &intf->dev; - input_dev->private = touchkit; - input_dev->open = touchkit_open; - input_dev->close = touchkit_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, TOUCHKIT_MIN_XC, TOUCHKIT_MAX_XC, - TOUCHKIT_XC_FUZZ, TOUCHKIT_XC_FLAT); - input_set_abs_params(input_dev, ABS_Y, TOUCHKIT_MIN_YC, TOUCHKIT_MAX_YC, - TOUCHKIT_YC_FUZZ, TOUCHKIT_YC_FLAT); - - usb_fill_int_urb(touchkit->irq, touchkit->udev, - usb_rcvintpipe(touchkit->udev, 0x81), - touchkit->data, TOUCHKIT_REPORT_DATA_SIZE, - touchkit_irq, touchkit, endpoint->bInterval); - - touchkit->irq->transfer_dma = touchkit->data_dma; - touchkit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - input_register_device(touchkit->input); - - usb_set_intfdata(intf, touchkit); - return 0; - -out_free_buffers: - touchkit_free_buffers(udev, touchkit); -out_free: - input_free_device(input_dev); - kfree(touchkit); - return -ENOMEM; -} - -static void touchkit_disconnect(struct usb_interface *intf) -{ - struct touchkit_usb *touchkit = usb_get_intfdata(intf); - - dbg("%s - called", __FUNCTION__); - - if (!touchkit) - return; - - dbg("%s - touchkit is initialized, cleaning up", __FUNCTION__); - usb_set_intfdata(intf, NULL); - usb_kill_urb(touchkit->irq); - input_unregister_device(touchkit->input); - usb_free_urb(touchkit->irq); - touchkit_free_buffers(interface_to_usbdev(intf), touchkit); - kfree(touchkit); -} - -MODULE_DEVICE_TABLE(usb, touchkit_devices); - -static struct usb_driver touchkit_driver = { - .name = "touchkitusb", - .probe = touchkit_probe, - .disconnect = touchkit_disconnect, - .id_table = touchkit_devices, -}; - -static int __init touchkit_init(void) -{ - return usb_register(&touchkit_driver); -} - -static void __exit touchkit_cleanup(void) -{ - usb_deregister(&touchkit_driver); -} - -module_init(touchkit_init); -module_exit(touchkit_cleanup); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c deleted file mode 100644 index 8505824848f..00000000000 --- a/drivers/usb/input/usbkbd.c +++ /dev/null @@ -1,360 +0,0 @@ -/* - * $Id: usbkbd.c,v 1.27 2001/12/27 10:37:41 vojtech Exp $ - * - * Copyright (c) 1999-2001 Vojtech Pavlik - * - * USB HIDBP Keyboard 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 - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#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 "" -#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" -#define DRIVER_DESC "USB HID Boot Protocol keyboard driver" -#define DRIVER_LICENSE "GPL" - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENSE); - -static unsigned char usb_kbd_keycode[256] = { - 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, - 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, - 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, - 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, - 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, - 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, - 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0, - 122,123, 90, 91, 85, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, - 150,158,159,128,136,177,178,176,142,152,173,140 -}; - -struct usb_kbd { - struct input_dev *dev; - struct usb_device *usbdev; - unsigned char old[8]; - struct urb *irq, *led; - unsigned char newleds; - char name[128]; - char phys[64]; - - unsigned char *new; - struct usb_ctrlrequest *cr; - unsigned char *leds; - dma_addr_t cr_dma; - dma_addr_t new_dma; - dma_addr_t leds_dma; -}; - -static void usb_kbd_irq(struct urb *urb) -{ - struct usb_kbd *kbd = urb->context; - int i; - - switch (urb->status) { - case 0: /* success */ - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: - return; - /* -EPIPE: should clear the halt */ - default: /* error */ - goto resubmit; - } - - for (i = 0; i < 8; i++) - input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1); - - for (i = 2; i < 8; i++) { - - if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) { - if (usb_kbd_keycode[kbd->old[i]]) - input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0); - else - info("Unknown key (scancode %#x) released.", kbd->old[i]); - } - - if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) { - if (usb_kbd_keycode[kbd->new[i]]) - input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1); - else - info("Unknown key (scancode %#x) pressed.", kbd->new[i]); - } - } - - input_sync(kbd->dev); - - memcpy(kbd->old, kbd->new, 8); - -resubmit: - i = usb_submit_urb (urb, GFP_ATOMIC); - if (i) - err ("can't resubmit intr, %s-%s/input0, status %d", - kbd->usbdev->bus->bus_name, - kbd->usbdev->devpath, i); -} - -static int usb_kbd_event(struct input_dev *dev, unsigned int type, - unsigned int code, int value) -{ - struct usb_kbd *kbd = dev->private; - - if (type != EV_LED) - return -1; - - - kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) | - (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) | - (!!test_bit(LED_NUML, dev->led)); - - if (kbd->led->status == -EINPROGRESS) - return 0; - - if (*(kbd->leds) == kbd->newleds) - return 0; - - *(kbd->leds) = kbd->newleds; - kbd->led->dev = kbd->usbdev; - if (usb_submit_urb(kbd->led, GFP_ATOMIC)) - err("usb_submit_urb(leds) failed"); - - return 0; -} - -static void usb_kbd_led(struct urb *urb) -{ - struct usb_kbd *kbd = urb->context; - - if (urb->status) - warn("led urb status %d received", urb->status); - - if (*(kbd->leds) == kbd->newleds) - return; - - *(kbd->leds) = kbd->newleds; - kbd->led->dev = kbd->usbdev; - if (usb_submit_urb(kbd->led, GFP_ATOMIC)) - err("usb_submit_urb(leds) failed"); -} - -static int usb_kbd_open(struct input_dev *dev) -{ - struct usb_kbd *kbd = dev->private; - - kbd->irq->dev = kbd->usbdev; - if (usb_submit_urb(kbd->irq, GFP_KERNEL)) - return -EIO; - - return 0; -} - -static void usb_kbd_close(struct input_dev *dev) -{ - struct usb_kbd *kbd = dev->private; - - usb_kill_urb(kbd->irq); -} - -static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) -{ - if (!(kbd->irq = usb_alloc_urb(0, GFP_KERNEL))) - return -1; - if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL))) - return -1; - if (!(kbd->new = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &kbd->new_dma))) - return -1; - if (!(kbd->cr = usb_buffer_alloc(dev, sizeof(struct usb_ctrlrequest), GFP_ATOMIC, &kbd->cr_dma))) - return -1; - if (!(kbd->leds = usb_buffer_alloc(dev, 1, GFP_ATOMIC, &kbd->leds_dma))) - return -1; - - return 0; -} - -static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd) -{ - usb_free_urb(kbd->irq); - usb_free_urb(kbd->led); - if (kbd->new) - usb_buffer_free(dev, 8, kbd->new, kbd->new_dma); - if (kbd->cr) - usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma); - if (kbd->leds) - usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma); -} - -static int usb_kbd_probe(struct usb_interface *iface, - const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(iface); - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct usb_kbd *kbd; - struct input_dev *input_dev; - int i, pipe, maxp; - - interface = iface->cur_altsetting; - - 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)); - - kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!kbd || !input_dev) - goto fail1; - - if (usb_kbd_alloc_mem(dev, kbd)) - goto fail2; - - kbd->usbdev = dev; - kbd->dev = input_dev; - - if (dev->manufacturer) - strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name)); - - if (dev->product) { - if (dev->manufacturer) - strlcat(kbd->name, " ", sizeof(kbd->name)); - strlcat(kbd->name, dev->product, sizeof(kbd->name)); - } - - if (!strlen(kbd->name)) - snprintf(kbd->name, sizeof(kbd->name), - "USB HIDBP Keyboard %04x:%04x", - le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - - usb_make_path(dev, kbd->phys, sizeof(kbd->phys)); - strlcpy(kbd->phys, "/input0", sizeof(kbd->phys)); - - input_dev->name = kbd->name; - input_dev->phys = kbd->phys; - usb_to_input_id(dev, &input_dev->id); - input_dev->cdev.dev = &iface->dev; - input_dev->private = kbd; - - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP); - input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA); - - for (i = 0; i < 255; i++) - set_bit(usb_kbd_keycode[i], input_dev->keybit); - clear_bit(0, input_dev->keybit); - - input_dev->event = usb_kbd_event; - input_dev->open = usb_kbd_open; - input_dev->close = usb_kbd_close; - - usb_fill_int_urb(kbd->irq, dev, pipe, - kbd->new, (maxp > 8 ? 8 : maxp), - usb_kbd_irq, kbd, endpoint->bInterval); - kbd->irq->transfer_dma = kbd->new_dma; - kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - kbd->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE; - kbd->cr->bRequest = 0x09; - kbd->cr->wValue = cpu_to_le16(0x200); - kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber); - kbd->cr->wLength = cpu_to_le16(1); - - usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0), - (void *) kbd->cr, kbd->leds, 1, - usb_kbd_led, kbd); - kbd->led->setup_dma = kbd->cr_dma; - kbd->led->transfer_dma = kbd->leds_dma; - kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); - - input_register_device(kbd->dev); - - usb_set_intfdata(iface, kbd); - return 0; - -fail2: usb_kbd_free_mem(dev, kbd); -fail1: input_free_device(input_dev); - kfree(kbd); - return -ENOMEM; -} - -static void usb_kbd_disconnect(struct usb_interface *intf) -{ - struct usb_kbd *kbd = usb_get_intfdata (intf); - - usb_set_intfdata(intf, NULL); - if (kbd) { - usb_kill_urb(kbd->irq); - input_unregister_device(kbd->dev); - usb_kbd_free_mem(interface_to_usbdev(intf), kbd); - kfree(kbd); - } -} - -static struct usb_device_id usb_kbd_id_table [] = { - { USB_INTERFACE_INFO(3, 1, 1) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, usb_kbd_id_table); - -static struct usb_driver usb_kbd_driver = { - .name = "usbkbd", - .probe = usb_kbd_probe, - .disconnect = usb_kbd_disconnect, - .id_table = usb_kbd_id_table, -}; - -static int __init usb_kbd_init(void) -{ - int result = usb_register(&usb_kbd_driver); - if (result == 0) - info(DRIVER_VERSION ":" DRIVER_DESC); - return result; -} - -static void __exit usb_kbd_exit(void) -{ - usb_deregister(&usb_kbd_driver); -} - -module_init(usb_kbd_init); -module_exit(usb_kbd_exit); diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c deleted file mode 100644 index 64a33e420cf..00000000000 --- a/drivers/usb/input/usbmouse.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * $Id: usbmouse.c,v 1.15 2001/12/27 10:37:41 vojtech Exp $ - * - * Copyright (c) 1999-2001 Vojtech Pavlik - * - * USB HIDBP Mouse 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 - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#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 "v1.6" -#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" -#define DRIVER_DESC "USB HID Boot Protocol mouse driver" -#define DRIVER_LICENSE "GPL" - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENSE); - -struct usb_mouse { - char name[128]; - char phys[64]; - struct usb_device *usbdev; - struct input_dev *dev; - struct urb *irq; - - signed char *data; - dma_addr_t data_dma; -}; - -static void usb_mouse_irq(struct urb *urb) -{ - struct usb_mouse *mouse = urb->context; - signed char *data = mouse->data; - struct input_dev *dev = mouse->dev; - int status; - - switch (urb->status) { - case 0: /* success */ - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: - return; - /* -EPIPE: should clear the halt */ - default: /* error */ - goto resubmit; - } - - input_report_key(dev, BTN_LEFT, data[0] & 0x01); - input_report_key(dev, BTN_RIGHT, data[0] & 0x02); - input_report_key(dev, BTN_MIDDLE, data[0] & 0x04); - input_report_key(dev, BTN_SIDE, data[0] & 0x08); - input_report_key(dev, BTN_EXTRA, data[0] & 0x10); - - input_report_rel(dev, REL_X, data[1]); - input_report_rel(dev, REL_Y, data[2]); - input_report_rel(dev, REL_WHEEL, data[3]); - - input_sync(dev); -resubmit: - status = usb_submit_urb (urb, GFP_ATOMIC); - if (status) - err ("can't resubmit intr, %s-%s/input0, status %d", - mouse->usbdev->bus->bus_name, - mouse->usbdev->devpath, status); -} - -static int usb_mouse_open(struct input_dev *dev) -{ - struct usb_mouse *mouse = dev->private; - - mouse->irq->dev = mouse->usbdev; - if (usb_submit_urb(mouse->irq, GFP_KERNEL)) - return -EIO; - - return 0; -} - -static void usb_mouse_close(struct input_dev *dev) -{ - struct usb_mouse *mouse = dev->private; - - usb_kill_urb(mouse->irq); -} - -static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct usb_mouse *mouse; - struct input_dev *input_dev; - int pipe, maxp; - - interface = intf->cur_altsetting; - - 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)); - - mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!mouse || !input_dev) - goto fail1; - - mouse->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &mouse->data_dma); - if (!mouse->data) - goto fail1; - - mouse->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!mouse->irq) - goto fail2; - - mouse->usbdev = dev; - mouse->dev = input_dev; - - if (dev->manufacturer) - strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name)); - - if (dev->product) { - if (dev->manufacturer) - strlcat(mouse->name, " ", sizeof(mouse->name)); - strlcat(mouse->name, dev->product, sizeof(mouse->name)); - } - - if (!strlen(mouse->name)) - snprintf(mouse->name, sizeof(mouse->name), - "USB HIDBP Mouse %04x:%04x", - le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - - usb_make_path(dev, mouse->phys, sizeof(mouse->phys)); - strlcat(mouse->phys, "/input0", sizeof(mouse->phys)); - - input_dev->name = mouse->name; - input_dev->phys = mouse->phys; - usb_to_input_id(dev, &input_dev->id); - input_dev->cdev.dev = &intf->dev; - - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); - input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); - input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); - input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA); - input_dev->relbit[0] |= BIT(REL_WHEEL); - - input_dev->private = mouse; - input_dev->open = usb_mouse_open; - input_dev->close = usb_mouse_close; - - usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data, - (maxp > 8 ? 8 : maxp), - usb_mouse_irq, mouse, endpoint->bInterval); - mouse->irq->transfer_dma = mouse->data_dma; - mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - input_register_device(mouse->dev); - - usb_set_intfdata(intf, mouse); - return 0; - -fail2: usb_buffer_free(dev, 8, mouse->data, mouse->data_dma); -fail1: input_free_device(input_dev); - kfree(mouse); - return -ENOMEM; -} - -static void usb_mouse_disconnect(struct usb_interface *intf) -{ - struct usb_mouse *mouse = usb_get_intfdata (intf); - - usb_set_intfdata(intf, NULL); - if (mouse) { - usb_kill_urb(mouse->irq); - input_unregister_device(mouse->dev); - usb_free_urb(mouse->irq); - usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma); - kfree(mouse); - } -} - -static struct usb_device_id usb_mouse_id_table [] = { - { USB_INTERFACE_INFO(3, 1, 2) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, usb_mouse_id_table); - -static struct usb_driver usb_mouse_driver = { - .name = "usbmouse", - .probe = usb_mouse_probe, - .disconnect = usb_mouse_disconnect, - .id_table = usb_mouse_id_table, -}; - -static int __init usb_mouse_init(void) -{ - int retval = usb_register(&usb_mouse_driver); - if (retval == 0) - info(DRIVER_VERSION ":" DRIVER_DESC); - return retval; -} - -static void __exit usb_mouse_exit(void) -{ - usb_deregister(&usb_mouse_driver); -} - -module_init(usb_mouse_init); -module_exit(usb_mouse_exit); diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c deleted file mode 100644 index 7f3c57da9bc..00000000000 --- a/drivers/usb/input/usbtouchscreen.c +++ /dev/null @@ -1,818 +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) (unsigned char *pkt, int *x, int *y, int *touch, int *press); - 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]; -}; - - -#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(unsigned char *pkt, int *x, int *y, int *touch, int *press) -{ - if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) - return 0; - - *x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F); - *y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F); - *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(unsigned char *pkt, int *x, int *y, int *touch, int *press) -{ - *x = ((pkt[2] & 0x0F) << 8) | pkt[1]; - *y = ((pkt[4] & 0x0F) << 8) | pkt[3]; - *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(unsigned char *pkt, int *x, int *y, int *touch, int *press) -{ - *x = (pkt[8] << 8) | pkt[7]; - *y = (pkt[10] << 8) | pkt[9]; - *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(unsigned char *pkt, int *x, int *y, int *touch, int *press) -{ - *x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F); - *y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F); - *press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F); - *touch = ~pkt[7] & 0x20; - - return *touch; -} -#endif - - -/***************************************************************************** - * eTurboTouch part - */ -#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO -static int eturbo_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press) -{ - unsigned int shift; - - /* packets should start with sync */ - if (!(pkt[0] & 0x80)) - return 0; - - shift = (6 - (pkt[0] & 0x03)); - *x = ((pkt[3] << 7) | pkt[4]) >> shift; - *y = ((pkt[1] << 7) | pkt[2]) >> shift; - *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(unsigned char *pkt, int *x, int *y, int *touch, int *press) -{ - if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80)) - return 0; - - *x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F); - *y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F); - *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(unsigned char *pkt, int *x, int *y, int *touch, int *press) -{ - *x = ((pkt[2] & 0x03) << 8) | pkt[1]; - *y = ((pkt[4] & 0x03) << 8) | pkt[3]; - *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) -{ - int x, y, touch, press; - struct usbtouch_device_info *type = usbtouch->type; - - if (!type->read_data(pkt, &x, &y, &touch, &press)) - return; - - input_report_key(usbtouch->input, BTN_TOUCH, touch); - - if (swap_xy) { - input_report_abs(usbtouch->input, ABS_X, y); - input_report_abs(usbtouch->input, ABS_Y, x); - } else { - input_report_abs(usbtouch->input, ABS_X, x); - input_report_abs(usbtouch->input, ABS_Y, y); - } - if (type->max_press) - input_report_abs(usbtouch->input, ABS_PRESSURE, 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->private; - - 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->private; - - 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->cdev.dev = &intf->dev; - input_dev->private = 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 e7cc20ab815..00000000000 --- a/drivers/usb/input/wacom_sys.c +++ /dev/null @@ -1,312 +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 = dev->private; - - 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 = dev->private; - - 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, 4097, 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, 4097, 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; - 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->cdev.dev = &intf->dev; - input_dev->private = wacom; - input_dev->open = wacom_open; - input_dev->close = wacom_close; - - input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS); - input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS); - input_set_abs_params(input_dev, ABS_X, 0, wacom_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; - - input_register_device(wacom->dev); - - /* Ask the tablet to report tablet data. Repeat until it succeeds */ - do { - rep_data[0] = 2; - rep_data[1] = 2; - usb_set_report(intf, 3, 2, rep_data, 2); - usb_get_report(intf, 3, 2, rep_data, 2); - } while (rep_data[1] != 2 && limit++ < 5); - - usb_set_intfdata(intf, wacom); - return 0; - -fail2: usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma); -fail1: input_free_device(input_dev); - kfree(wacom); - kfree(wacom_wac); - return -ENOMEM; -} - -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 92726fe8937..00000000000 --- a/drivers/usb/input/wacom_wac.c +++ /dev/null @@ -1,648 +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] & 0x10) { /* 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; - } - } - - if (data[1] & 0x90) { - 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); - } - } - - if (data[1] & 0x10) - wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */ - else - wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ - wacom_report_key(wcombo, wacom->tool[0], data[1] & 0x10); - wacom_input_sync(wcombo); - - /* send pad data */ - if (wacom->features->type == WACOM_G4) { - if ( (wacom->serial[1] & 0xc0) != (data[7] & 0xf8) ) { - wacom->id[1] = 1; - wacom->serial[1] = (data[7] & 0xf8); - 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_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); - } else if (wacom->id[1]) { - wacom->id[1] = 0; - wacom_report_key(wcombo, BTN_TOOL_FINGER, 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; - } - /* only large I3 support Lens Cursor */ - if(!((wacom->tool[idx] == BTN_TOOL_LENS) - && ((wacom->features->type == INTUOS3) - || (wacom->features->type == INTUOS3S)))) { - 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 2; - } - return 1; - } - - /* Exit report */ - if ((data[1] & 0xfe) == 0x80) { - if(!((wacom->tool[idx] == BTN_TOOL_LENS) - && ((wacom->features->type == INTUOS3) - || (wacom->features->type == INTUOS3S)))) { - 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_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; - - /* 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 >= INTUOS3) { - 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 >= INTUOS3) { - /* I3 marker pen rotation reported as wheel - * due to valuator limitation - */ - t = (data[6] << 3) | ((data[7] >> 5) & 7); - t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : - ((t-1) / 2 + 450)) : (450 - t / 2) ; - 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, 0, GRAPHIRE }, - { "Wacom PenStation2", 8, 3250, 2320, 255, 0, GRAPHIRE }, - { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 0, GRAPHIRE }, - { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 0, GRAPHIRE }, - { "Wacom PenPartner2", 8, 3250, 2320, 255, 0, GRAPHIRE }, - { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 63, INTUOS }, - { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 63, INTUOS }, - { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 63, INTUOS }, - { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 63, INTUOS }, - { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 63, 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, 63, INTUOS }, - { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 63, INTUOS }, - { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 63, INTUOS }, - { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 63, INTUOS }, - { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 63, 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, 15, INTUOS3S }, - { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ }, - { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 63, 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 a1d9ce00797..00000000000 --- a/drivers/usb/input/wacom_wac.h +++ /dev/null @@ -1,48 +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 - -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 e4bc76ebc83..00000000000 --- a/drivers/usb/input/xpad.c +++ /dev/null @@ -1,428 +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/smp_lock.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 = dev->private; - - 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 = dev->private; - - 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; - - 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->cdev.dev = &intf->dev; - input_dev->private = 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; - - input_register_device(xpad->dev); - - usb_set_intfdata(intf, xpad); - return 0; - -fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); -fail1: input_free_device(input_dev); - kfree(xpad); - return -ENOMEM; - -} - -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 caff8e6d744..00000000000 --- a/drivers/usb/input/yealink.c +++ /dev/null @@ -1,1002 +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 = dev->private; - 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 = dev->private; - - 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->cdev.dev = &intf->dev; - - input_dev->private = 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); - } - } - - input_register_device(yld->idev); - - 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 */ |
