diff options
| author | Jiri Kosina <jkosina@suse.cz> | 2007-03-08 10:47:49 -0500 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2007-04-11 04:36:02 -0400 |
| commit | 6db3dfefa28739e7c9c60809c3a5aef7cc088b97 (patch) | |
| tree | 9f88649e7a53af36a94db34ff8f1a0f47316260e /drivers/usb/input | |
| parent | a21bd69e1509b43823c317c3bf3f7ffa99884356 (diff) | |
USB HID: move usbhid code from drivers/usb/input to drivers/hid/usbhid
Separate usbhid code into dedicated drivers/hid/usbhid directory as
discussed previously with Greg, so that it eases maintaineance process.
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/input')
| -rw-r--r-- | drivers/usb/input/Kconfig | 145 | ||||
| -rw-r--r-- | drivers/usb/input/Makefile | 28 | ||||
| -rw-r--r-- | drivers/usb/input/hid-core.c | 1477 | ||||
| -rw-r--r-- | drivers/usb/input/hid-ff.c | 89 | ||||
| -rw-r--r-- | drivers/usb/input/hid-lgff.c | 150 | ||||
| -rw-r--r-- | drivers/usb/input/hid-pidff.c | 1331 | ||||
| -rw-r--r-- | drivers/usb/input/hid-plff.c | 129 | ||||
| -rw-r--r-- | drivers/usb/input/hid-tmff.c | 147 | ||||
| -rw-r--r-- | drivers/usb/input/hid-zpff.c | 111 | ||||
| -rw-r--r-- | drivers/usb/input/hiddev.c | 847 | ||||
| -rw-r--r-- | drivers/usb/input/usbhid.h | 87 | ||||
| -rw-r--r-- | drivers/usb/input/usbkbd.c | 362 | ||||
| -rw-r--r-- | drivers/usb/input/usbmouse.c | 245 |
13 files changed, 0 insertions, 5148 deletions
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index 69a9f3b6d0a9..a792e42f58af 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig | |||
| @@ -4,151 +4,6 @@ | |||
| 4 | comment "USB Input Devices" | 4 | comment "USB Input Devices" |
| 5 | depends on USB | 5 | depends on USB |
| 6 | 6 | ||
| 7 | config USB_HID | ||
| 8 | tristate "USB Human Interface Device (full HID) support" | ||
| 9 | default y | ||
| 10 | depends on USB && INPUT | ||
| 11 | select HID | ||
| 12 | ---help--- | ||
| 13 | Say Y here if you want full HID support to connect USB keyboards, | ||
| 14 | mice, joysticks, graphic tablets, or any other HID based devices | ||
| 15 | to your computer via USB, as well as Uninterruptible Power Supply | ||
| 16 | (UPS) and monitor control devices. | ||
| 17 | |||
| 18 | You can't use this driver and the HIDBP (Boot Protocol) keyboard | ||
| 19 | and mouse drivers at the same time. More information is available: | ||
| 20 | <file:Documentation/input/input.txt>. | ||
| 21 | |||
| 22 | If unsure, say Y. | ||
| 23 | |||
| 24 | To compile this driver as a module, choose M here: the | ||
| 25 | module will be called usbhid. | ||
| 26 | |||
| 27 | comment "Input core support is needed for USB HID input layer or HIDBP support" | ||
| 28 | depends on USB_HID && INPUT=n | ||
| 29 | |||
| 30 | config USB_HIDINPUT_POWERBOOK | ||
| 31 | bool "Enable support for iBook/PowerBook special keys" | ||
| 32 | default n | ||
| 33 | depends on USB_HID | ||
| 34 | help | ||
| 35 | Say Y here if you want support for the special keys (Fn, Numlock) on | ||
| 36 | Apple iBooks and PowerBooks. | ||
| 37 | |||
| 38 | If unsure, say N. | ||
| 39 | |||
| 40 | config HID_FF | ||
| 41 | bool "Force feedback support (EXPERIMENTAL)" | ||
| 42 | depends on USB_HID && EXPERIMENTAL | ||
| 43 | help | ||
| 44 | Say Y here is you want force feedback support for a few HID devices. | ||
| 45 | See below for a list of supported devices. | ||
| 46 | |||
| 47 | See <file:Documentation/input/ff.txt> for a description of the force | ||
| 48 | feedback API. | ||
| 49 | |||
| 50 | If unsure, say N. | ||
| 51 | |||
| 52 | config HID_PID | ||
| 53 | bool "PID device support" | ||
| 54 | depends on HID_FF | ||
| 55 | help | ||
| 56 | Say Y here if you have a PID-compliant device and wish to enable force | ||
| 57 | feedback for it. Microsoft Sidewinder Force Feedback 2 is one of such | ||
| 58 | devices. | ||
| 59 | |||
| 60 | config LOGITECH_FF | ||
| 61 | bool "Logitech devices support" | ||
| 62 | depends on HID_FF | ||
| 63 | select INPUT_FF_MEMLESS if USB_HID | ||
| 64 | help | ||
| 65 | Say Y here if you have one of these devices: | ||
| 66 | - Logitech WingMan Cordless RumblePad | ||
| 67 | - Logitech WingMan Cordless RumblePad 2 | ||
| 68 | - Logitech WingMan Force 3D | ||
| 69 | - Logitech Formula Force EX | ||
| 70 | - Logitech MOMO Force wheel | ||
| 71 | |||
| 72 | and if you want to enable force feedback for them. | ||
| 73 | Note: if you say N here, this device will still be supported, but without | ||
| 74 | force feedback. | ||
| 75 | |||
| 76 | config PANTHERLORD_FF | ||
| 77 | bool "PantherLord USB/PS2 2in1 Adapter support" | ||
| 78 | depends on HID_FF | ||
| 79 | select INPUT_FF_MEMLESS if USB_HID | ||
| 80 | help | ||
| 81 | Say Y here if you have a PantherLord USB/PS2 2in1 Adapter and want | ||
| 82 | to enable force feedback support for it. | ||
| 83 | |||
| 84 | config THRUSTMASTER_FF | ||
| 85 | bool "ThrustMaster FireStorm Dual Power 2 support (EXPERIMENTAL)" | ||
| 86 | depends on HID_FF && EXPERIMENTAL | ||
| 87 | select INPUT_FF_MEMLESS if USB_HID | ||
| 88 | help | ||
| 89 | Say Y here if you have a THRUSTMASTER FireStore Dual Power 2, | ||
| 90 | and want to enable force feedback support for it. | ||
| 91 | Note: if you say N here, this device will still be supported, but without | ||
| 92 | force feedback. | ||
| 93 | |||
| 94 | config ZEROPLUS_FF | ||
| 95 | bool "Zeroplus based game controller support" | ||
| 96 | depends on HID_FF | ||
| 97 | select INPUT_FF_MEMLESS if USB_HID | ||
| 98 | help | ||
| 99 | Say Y here if you have a Zeroplus based game controller and want to | ||
| 100 | enable force feedback for it. | ||
| 101 | |||
| 102 | config USB_HIDDEV | ||
| 103 | bool "/dev/hiddev raw HID device support" | ||
| 104 | depends on USB_HID | ||
| 105 | help | ||
| 106 | Say Y here if you want to support HID devices (from the USB | ||
| 107 | specification standpoint) that aren't strictly user interface | ||
| 108 | devices, like monitor controls and Uninterruptable Power Supplies. | ||
| 109 | |||
| 110 | This module supports these devices separately using a separate | ||
| 111 | event interface on /dev/usb/hiddevX (char 180:96 to 180:111). | ||
| 112 | |||
| 113 | If unsure, say Y. | ||
| 114 | |||
| 115 | menu "USB HID Boot Protocol drivers" | ||
| 116 | depends on USB!=n && USB_HID!=y | ||
| 117 | |||
| 118 | config USB_KBD | ||
| 119 | tristate "USB HIDBP Keyboard (simple Boot) support" | ||
| 120 | depends on USB && INPUT | ||
| 121 | ---help--- | ||
| 122 | Say Y here only if you are absolutely sure that you don't want | ||
| 123 | to use the generic HID driver for your USB keyboard and prefer | ||
| 124 | to use the keyboard in its limited Boot Protocol mode instead. | ||
| 125 | |||
| 126 | This is almost certainly not what you want. This is mostly | ||
| 127 | useful for embedded applications or simple keyboards. | ||
| 128 | |||
| 129 | To compile this driver as a module, choose M here: the | ||
| 130 | module will be called usbkbd. | ||
| 131 | |||
| 132 | If even remotely unsure, say N. | ||
| 133 | |||
| 134 | config USB_MOUSE | ||
| 135 | tristate "USB HIDBP Mouse (simple Boot) support" | ||
| 136 | depends on USB && INPUT | ||
| 137 | ---help--- | ||
| 138 | Say Y here only if you are absolutely sure that you don't want | ||
| 139 | to use the generic HID driver for your USB mouse and prefer | ||
| 140 | to use the mouse in its limited Boot Protocol mode instead. | ||
| 141 | |||
| 142 | This is almost certainly not what you want. This is mostly | ||
| 143 | useful for embedded applications or simple mice. | ||
| 144 | |||
| 145 | To compile this driver as a module, choose M here: the | ||
| 146 | module will be called usbmouse. | ||
| 147 | |||
| 148 | If even remotely unsure, say N. | ||
| 149 | |||
| 150 | endmenu | ||
| 151 | |||
| 152 | config USB_AIPTEK | 7 | config USB_AIPTEK |
| 153 | tristate "Aiptek 6000U/8000U tablet support" | 8 | tristate "Aiptek 6000U/8000U tablet support" |
| 154 | depends on USB && INPUT | 9 | depends on USB && INPUT |
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile index a9d206c945e9..9bf420eef77f 100644 --- a/drivers/usb/input/Makefile +++ b/drivers/usb/input/Makefile | |||
| @@ -4,40 +4,12 @@ | |||
| 4 | 4 | ||
| 5 | # Multipart objects. | 5 | # Multipart objects. |
| 6 | wacom-objs := wacom_wac.o wacom_sys.o | 6 | wacom-objs := wacom_wac.o wacom_sys.o |
| 7 | usbhid-objs := hid-core.o | ||
| 8 | |||
| 9 | # Optional parts of multipart objects. | ||
| 10 | |||
| 11 | ifeq ($(CONFIG_USB_HIDDEV),y) | ||
| 12 | usbhid-objs += hiddev.o | ||
| 13 | endif | ||
| 14 | ifeq ($(CONFIG_HID_PID),y) | ||
| 15 | usbhid-objs += hid-pidff.o | ||
| 16 | endif | ||
| 17 | ifeq ($(CONFIG_LOGITECH_FF),y) | ||
| 18 | usbhid-objs += hid-lgff.o | ||
| 19 | endif | ||
| 20 | ifeq ($(CONFIG_PANTHERLORD_FF),y) | ||
| 21 | usbhid-objs += hid-plff.o | ||
| 22 | endif | ||
| 23 | ifeq ($(CONFIG_THRUSTMASTER_FF),y) | ||
| 24 | usbhid-objs += hid-tmff.o | ||
| 25 | endif | ||
| 26 | ifeq ($(CONFIG_ZEROPLUS_FF),y) | ||
| 27 | usbhid-objs += hid-zpff.o | ||
| 28 | endif | ||
| 29 | ifeq ($(CONFIG_HID_FF),y) | ||
| 30 | usbhid-objs += hid-ff.o | ||
| 31 | endif | ||
| 32 | 7 | ||
| 33 | obj-$(CONFIG_USB_AIPTEK) += aiptek.o | 8 | obj-$(CONFIG_USB_AIPTEK) += aiptek.o |
| 34 | obj-$(CONFIG_USB_ATI_REMOTE) += ati_remote.o | 9 | obj-$(CONFIG_USB_ATI_REMOTE) += ati_remote.o |
| 35 | obj-$(CONFIG_USB_ATI_REMOTE2) += ati_remote2.o | 10 | obj-$(CONFIG_USB_ATI_REMOTE2) += ati_remote2.o |
| 36 | obj-$(CONFIG_USB_HID) += usbhid.o | ||
| 37 | obj-$(CONFIG_USB_KBD) += usbkbd.o | ||
| 38 | obj-$(CONFIG_USB_KBTAB) += kbtab.o | 11 | obj-$(CONFIG_USB_KBTAB) += kbtab.o |
| 39 | obj-$(CONFIG_USB_KEYSPAN_REMOTE) += keyspan_remote.o | 12 | obj-$(CONFIG_USB_KEYSPAN_REMOTE) += keyspan_remote.o |
| 40 | obj-$(CONFIG_USB_MOUSE) += usbmouse.o | ||
| 41 | obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o | 13 | obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o |
| 42 | obj-$(CONFIG_USB_ITMTOUCH) += itmtouch.o | 14 | obj-$(CONFIG_USB_ITMTOUCH) += itmtouch.o |
| 43 | obj-$(CONFIG_USB_EGALAX) += touchkitusb.o | 15 | obj-$(CONFIG_USB_EGALAX) += touchkitusb.o |
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c deleted file mode 100644 index 827a75a186ba..000000000000 --- a/drivers/usb/input/hid-core.c +++ /dev/null | |||
| @@ -1,1477 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * USB HID support for Linux | ||
| 3 | * | ||
| 4 | * Copyright (c) 1999 Andreas Gal | ||
| 5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> | ||
| 6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc | ||
| 7 | * Copyright (c) 2006-2007 Jiri Kosina | ||
| 8 | */ | ||
| 9 | |||
| 10 | /* | ||
| 11 | * This program is free software; you can redistribute it and/or modify it | ||
| 12 | * under the terms of the GNU General Public License as published by the Free | ||
| 13 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 14 | * any later version. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/slab.h> | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/kernel.h> | ||
| 21 | #include <linux/list.h> | ||
| 22 | #include <linux/mm.h> | ||
| 23 | #include <linux/smp_lock.h> | ||
| 24 | #include <linux/spinlock.h> | ||
| 25 | #include <asm/unaligned.h> | ||
| 26 | #include <asm/byteorder.h> | ||
| 27 | #include <linux/input.h> | ||
| 28 | #include <linux/wait.h> | ||
| 29 | |||
| 30 | #include <linux/usb.h> | ||
| 31 | |||
| 32 | #include <linux/hid.h> | ||
| 33 | #include <linux/hiddev.h> | ||
| 34 | #include <linux/hid-debug.h> | ||
| 35 | #include "usbhid.h" | ||
| 36 | |||
| 37 | /* | ||
| 38 | * Version Information | ||
| 39 | */ | ||
| 40 | |||
| 41 | #define DRIVER_VERSION "v2.6" | ||
| 42 | #define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik" | ||
| 43 | #define DRIVER_DESC "USB HID core driver" | ||
| 44 | #define DRIVER_LICENSE "GPL" | ||
| 45 | |||
| 46 | static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick", | ||
| 47 | "Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"}; | ||
| 48 | /* | ||
| 49 | * Module parameters. | ||
| 50 | */ | ||
| 51 | |||
| 52 | static unsigned int hid_mousepoll_interval; | ||
| 53 | module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); | ||
| 54 | MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); | ||
| 55 | |||
| 56 | /* | ||
| 57 | * Input submission and I/O error handler. | ||
| 58 | */ | ||
| 59 | |||
| 60 | static void hid_io_error(struct hid_device *hid); | ||
| 61 | |||
| 62 | /* Start up the input URB */ | ||
| 63 | static int hid_start_in(struct hid_device *hid) | ||
| 64 | { | ||
| 65 | unsigned long flags; | ||
| 66 | int rc = 0; | ||
| 67 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 68 | |||
| 69 | spin_lock_irqsave(&usbhid->inlock, flags); | ||
| 70 | if (hid->open > 0 && !test_bit(HID_SUSPENDED, &usbhid->iofl) && | ||
| 71 | !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { | ||
| 72 | rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC); | ||
| 73 | if (rc != 0) | ||
| 74 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | ||
| 75 | } | ||
| 76 | spin_unlock_irqrestore(&usbhid->inlock, flags); | ||
| 77 | return rc; | ||
| 78 | } | ||
| 79 | |||
| 80 | /* I/O retry timer routine */ | ||
| 81 | static void hid_retry_timeout(unsigned long _hid) | ||
| 82 | { | ||
| 83 | struct hid_device *hid = (struct hid_device *) _hid; | ||
| 84 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 85 | |||
| 86 | dev_dbg(&usbhid->intf->dev, "retrying intr urb\n"); | ||
| 87 | if (hid_start_in(hid)) | ||
| 88 | hid_io_error(hid); | ||
| 89 | } | ||
| 90 | |||
| 91 | /* Workqueue routine to reset the device or clear a halt */ | ||
| 92 | static void hid_reset(struct work_struct *work) | ||
| 93 | { | ||
| 94 | struct usbhid_device *usbhid = | ||
| 95 | container_of(work, struct usbhid_device, reset_work); | ||
| 96 | struct hid_device *hid = usbhid->hid; | ||
| 97 | int rc_lock, rc = 0; | ||
| 98 | |||
| 99 | if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) { | ||
| 100 | dev_dbg(&usbhid->intf->dev, "clear halt\n"); | ||
| 101 | rc = usb_clear_halt(hid_to_usb_dev(hid), usbhid->urbin->pipe); | ||
| 102 | clear_bit(HID_CLEAR_HALT, &usbhid->iofl); | ||
| 103 | hid_start_in(hid); | ||
| 104 | } | ||
| 105 | |||
| 106 | else if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) { | ||
| 107 | dev_dbg(&usbhid->intf->dev, "resetting device\n"); | ||
| 108 | rc = rc_lock = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid->intf); | ||
| 109 | if (rc_lock >= 0) { | ||
| 110 | rc = usb_reset_composite_device(hid_to_usb_dev(hid), usbhid->intf); | ||
| 111 | if (rc_lock) | ||
| 112 | usb_unlock_device(hid_to_usb_dev(hid)); | ||
| 113 | } | ||
| 114 | clear_bit(HID_RESET_PENDING, &usbhid->iofl); | ||
| 115 | } | ||
| 116 | |||
| 117 | switch (rc) { | ||
| 118 | case 0: | ||
| 119 | if (!test_bit(HID_IN_RUNNING, &usbhid->iofl)) | ||
| 120 | hid_io_error(hid); | ||
| 121 | break; | ||
| 122 | default: | ||
| 123 | err("can't reset device, %s-%s/input%d, status %d", | ||
| 124 | hid_to_usb_dev(hid)->bus->bus_name, | ||
| 125 | hid_to_usb_dev(hid)->devpath, | ||
| 126 | usbhid->ifnum, rc); | ||
| 127 | /* FALLTHROUGH */ | ||
| 128 | case -EHOSTUNREACH: | ||
| 129 | case -ENODEV: | ||
| 130 | case -EINTR: | ||
| 131 | break; | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | /* Main I/O error handler */ | ||
| 136 | static void hid_io_error(struct hid_device *hid) | ||
| 137 | { | ||
| 138 | unsigned long flags; | ||
| 139 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 140 | |||
| 141 | spin_lock_irqsave(&usbhid->inlock, flags); | ||
| 142 | |||
| 143 | /* Stop when disconnected */ | ||
| 144 | if (usb_get_intfdata(usbhid->intf) == NULL) | ||
| 145 | goto done; | ||
| 146 | |||
| 147 | /* When an error occurs, retry at increasing intervals */ | ||
| 148 | if (usbhid->retry_delay == 0) { | ||
| 149 | usbhid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */ | ||
| 150 | usbhid->stop_retry = jiffies + msecs_to_jiffies(1000); | ||
| 151 | } else if (usbhid->retry_delay < 100) | ||
| 152 | usbhid->retry_delay *= 2; | ||
| 153 | |||
| 154 | if (time_after(jiffies, usbhid->stop_retry)) { | ||
| 155 | |||
| 156 | /* Retries failed, so do a port reset */ | ||
| 157 | if (!test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) { | ||
| 158 | schedule_work(&usbhid->reset_work); | ||
| 159 | goto done; | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | mod_timer(&usbhid->io_retry, | ||
| 164 | jiffies + msecs_to_jiffies(usbhid->retry_delay)); | ||
| 165 | done: | ||
| 166 | spin_unlock_irqrestore(&usbhid->inlock, flags); | ||
| 167 | } | ||
| 168 | |||
| 169 | /* | ||
| 170 | * Input interrupt completion handler. | ||
| 171 | */ | ||
| 172 | |||
| 173 | static void hid_irq_in(struct urb *urb) | ||
| 174 | { | ||
| 175 | struct hid_device *hid = urb->context; | ||
| 176 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 177 | int status; | ||
| 178 | |||
| 179 | switch (urb->status) { | ||
| 180 | case 0: /* success */ | ||
| 181 | usbhid->retry_delay = 0; | ||
| 182 | hid_input_report(urb->context, HID_INPUT_REPORT, | ||
| 183 | urb->transfer_buffer, | ||
| 184 | urb->actual_length, 1); | ||
| 185 | break; | ||
| 186 | case -EPIPE: /* stall */ | ||
| 187 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | ||
| 188 | set_bit(HID_CLEAR_HALT, &usbhid->iofl); | ||
| 189 | schedule_work(&usbhid->reset_work); | ||
| 190 | return; | ||
| 191 | case -ECONNRESET: /* unlink */ | ||
| 192 | case -ENOENT: | ||
| 193 | case -ESHUTDOWN: /* unplug */ | ||
| 194 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | ||
| 195 | return; | ||
| 196 | case -EILSEQ: /* protocol error or unplug */ | ||
| 197 | case -EPROTO: /* protocol error or unplug */ | ||
| 198 | case -ETIME: /* protocol error or unplug */ | ||
| 199 | case -ETIMEDOUT: /* Should never happen, but... */ | ||
| 200 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | ||
| 201 | hid_io_error(hid); | ||
| 202 | return; | ||
| 203 | default: /* error */ | ||
| 204 | warn("input irq status %d received", urb->status); | ||
| 205 | } | ||
| 206 | |||
| 207 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
| 208 | if (status) { | ||
| 209 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | ||
| 210 | if (status != -EPERM) { | ||
| 211 | err("can't resubmit intr, %s-%s/input%d, status %d", | ||
| 212 | hid_to_usb_dev(hid)->bus->bus_name, | ||
| 213 | hid_to_usb_dev(hid)->devpath, | ||
| 214 | usbhid->ifnum, status); | ||
| 215 | hid_io_error(hid); | ||
| 216 | } | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | static int hid_submit_out(struct hid_device *hid) | ||
| 221 | { | ||
| 222 | struct hid_report *report; | ||
| 223 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 224 | |||
| 225 | report = usbhid->out[usbhid->outtail]; | ||
| 226 | |||
| 227 | hid_output_report(report, usbhid->outbuf); | ||
| 228 | usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); | ||
| 229 | usbhid->urbout->dev = hid_to_usb_dev(hid); | ||
| 230 | |||
| 231 | dbg("submitting out urb"); | ||
| 232 | |||
| 233 | if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) { | ||
| 234 | err("usb_submit_urb(out) failed"); | ||
| 235 | return -1; | ||
| 236 | } | ||
| 237 | |||
| 238 | return 0; | ||
| 239 | } | ||
| 240 | |||
| 241 | static int hid_submit_ctrl(struct hid_device *hid) | ||
| 242 | { | ||
| 243 | struct hid_report *report; | ||
| 244 | unsigned char dir; | ||
| 245 | int len; | ||
| 246 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 247 | |||
| 248 | report = usbhid->ctrl[usbhid->ctrltail].report; | ||
| 249 | dir = usbhid->ctrl[usbhid->ctrltail].dir; | ||
| 250 | |||
| 251 | len = ((report->size - 1) >> 3) + 1 + (report->id > 0); | ||
| 252 | if (dir == USB_DIR_OUT) { | ||
| 253 | hid_output_report(report, usbhid->ctrlbuf); | ||
| 254 | usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0); | ||
| 255 | usbhid->urbctrl->transfer_buffer_length = len; | ||
| 256 | } else { | ||
| 257 | int maxpacket, padlen; | ||
| 258 | |||
| 259 | usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0); | ||
| 260 | maxpacket = usb_maxpacket(hid_to_usb_dev(hid), usbhid->urbctrl->pipe, 0); | ||
| 261 | if (maxpacket > 0) { | ||
| 262 | padlen = (len + maxpacket - 1) / maxpacket; | ||
| 263 | padlen *= maxpacket; | ||
| 264 | if (padlen > usbhid->bufsize) | ||
| 265 | padlen = usbhid->bufsize; | ||
| 266 | } else | ||
| 267 | padlen = 0; | ||
| 268 | usbhid->urbctrl->transfer_buffer_length = padlen; | ||
| 269 | } | ||
| 270 | usbhid->urbctrl->dev = hid_to_usb_dev(hid); | ||
| 271 | |||
| 272 | usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir; | ||
| 273 | usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT; | ||
| 274 | usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id); | ||
| 275 | usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum); | ||
| 276 | usbhid->cr->wLength = cpu_to_le16(len); | ||
| 277 | |||
| 278 | dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u", | ||
| 279 | usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report", | ||
| 280 | usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); | ||
| 281 | |||
| 282 | if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) { | ||
| 283 | err("usb_submit_urb(ctrl) failed"); | ||
| 284 | return -1; | ||
| 285 | } | ||
| 286 | |||
| 287 | return 0; | ||
| 288 | } | ||
| 289 | |||
| 290 | /* | ||
| 291 | * Output interrupt completion handler. | ||
| 292 | */ | ||
| 293 | |||
| 294 | static void hid_irq_out(struct urb *urb) | ||
| 295 | { | ||
| 296 | struct hid_device *hid = urb->context; | ||
| 297 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 298 | unsigned long flags; | ||
| 299 | int unplug = 0; | ||
| 300 | |||
| 301 | switch (urb->status) { | ||
| 302 | case 0: /* success */ | ||
| 303 | break; | ||
| 304 | case -ESHUTDOWN: /* unplug */ | ||
| 305 | unplug = 1; | ||
| 306 | case -EILSEQ: /* protocol error or unplug */ | ||
| 307 | case -EPROTO: /* protocol error or unplug */ | ||
| 308 | case -ECONNRESET: /* unlink */ | ||
| 309 | case -ENOENT: | ||
| 310 | break; | ||
| 311 | default: /* error */ | ||
| 312 | warn("output irq status %d received", urb->status); | ||
| 313 | } | ||
| 314 | |||
| 315 | spin_lock_irqsave(&usbhid->outlock, flags); | ||
| 316 | |||
| 317 | if (unplug) | ||
| 318 | usbhid->outtail = usbhid->outhead; | ||
| 319 | else | ||
| 320 | usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1); | ||
| 321 | |||
| 322 | if (usbhid->outhead != usbhid->outtail) { | ||
| 323 | if (hid_submit_out(hid)) { | ||
| 324 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | ||
| 325 | wake_up(&hid->wait); | ||
| 326 | } | ||
| 327 | spin_unlock_irqrestore(&usbhid->outlock, flags); | ||
| 328 | return; | ||
| 329 | } | ||
| 330 | |||
| 331 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | ||
| 332 | spin_unlock_irqrestore(&usbhid->outlock, flags); | ||
| 333 | wake_up(&hid->wait); | ||
| 334 | } | ||
| 335 | |||
| 336 | /* | ||
| 337 | * Control pipe completion handler. | ||
| 338 | */ | ||
| 339 | |||
| 340 | static void hid_ctrl(struct urb *urb) | ||
| 341 | { | ||
| 342 | struct hid_device *hid = urb->context; | ||
| 343 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 344 | unsigned long flags; | ||
| 345 | int unplug = 0; | ||
| 346 | |||
| 347 | spin_lock_irqsave(&usbhid->ctrllock, flags); | ||
| 348 | |||
| 349 | switch (urb->status) { | ||
| 350 | case 0: /* success */ | ||
| 351 | if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN) | ||
| 352 | hid_input_report(urb->context, usbhid->ctrl[usbhid->ctrltail].report->type, | ||
| 353 | urb->transfer_buffer, urb->actual_length, 0); | ||
| 354 | break; | ||
| 355 | case -ESHUTDOWN: /* unplug */ | ||
| 356 | unplug = 1; | ||
| 357 | case -EILSEQ: /* protocol error or unplug */ | ||
| 358 | case -EPROTO: /* protocol error or unplug */ | ||
| 359 | case -ECONNRESET: /* unlink */ | ||
| 360 | case -ENOENT: | ||
| 361 | case -EPIPE: /* report not available */ | ||
| 362 | break; | ||
| 363 | default: /* error */ | ||
| 364 | warn("ctrl urb status %d received", urb->status); | ||
| 365 | } | ||
| 366 | |||
| 367 | if (unplug) | ||
| 368 | usbhid->ctrltail = usbhid->ctrlhead; | ||
| 369 | else | ||
| 370 | usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); | ||
| 371 | |||
| 372 | if (usbhid->ctrlhead != usbhid->ctrltail) { | ||
| 373 | if (hid_submit_ctrl(hid)) { | ||
| 374 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | ||
| 375 | wake_up(&hid->wait); | ||
| 376 | } | ||
| 377 | spin_unlock_irqrestore(&usbhid->ctrllock, flags); | ||
| 378 | return; | ||
| 379 | } | ||
| 380 | |||
| 381 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | ||
| 382 | spin_unlock_irqrestore(&usbhid->ctrllock, flags); | ||
| 383 | wake_up(&hid->wait); | ||
| 384 | } | ||
| 385 | |||
| 386 | void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) | ||
| 387 | { | ||
| 388 | int head; | ||
| 389 | unsigned long flags; | ||
| 390 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 391 | |||
| 392 | if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN) | ||
| 393 | return; | ||
| 394 | |||
| 395 | if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) { | ||
| 396 | |||
| 397 | spin_lock_irqsave(&usbhid->outlock, flags); | ||
| 398 | |||
| 399 | if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) { | ||
| 400 | spin_unlock_irqrestore(&usbhid->outlock, flags); | ||
| 401 | warn("output queue full"); | ||
| 402 | return; | ||
| 403 | } | ||
| 404 | |||
| 405 | usbhid->out[usbhid->outhead] = report; | ||
| 406 | usbhid->outhead = head; | ||
| 407 | |||
| 408 | if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) | ||
| 409 | if (hid_submit_out(hid)) | ||
| 410 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | ||
| 411 | |||
| 412 | spin_unlock_irqrestore(&usbhid->outlock, flags); | ||
| 413 | return; | ||
| 414 | } | ||
| 415 | |||
| 416 | spin_lock_irqsave(&usbhid->ctrllock, flags); | ||
| 417 | |||
| 418 | if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) { | ||
| 419 | spin_unlock_irqrestore(&usbhid->ctrllock, flags); | ||
| 420 | warn("control queue full"); | ||
| 421 | return; | ||
| 422 | } | ||
| 423 | |||
| 424 | usbhid->ctrl[usbhid->ctrlhead].report = report; | ||
| 425 | usbhid->ctrl[usbhid->ctrlhead].dir = dir; | ||
| 426 | usbhid->ctrlhead = head; | ||
| 427 | |||
| 428 | if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) | ||
| 429 | if (hid_submit_ctrl(hid)) | ||
| 430 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | ||
| 431 | |||
| 432 | spin_unlock_irqrestore(&usbhid->ctrllock, flags); | ||
| 433 | } | ||
| 434 | |||
| 435 | static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | ||
| 436 | { | ||
| 437 | struct hid_device *hid = dev->private; | ||
| 438 | struct hid_field *field; | ||
| 439 | int offset; | ||
| 440 | |||
| 441 | if (type == EV_FF) | ||
| 442 | return input_ff_event(dev, type, code, value); | ||
| 443 | |||
| 444 | if (type != EV_LED) | ||
| 445 | return -1; | ||
| 446 | |||
| 447 | if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) { | ||
| 448 | warn("event field not found"); | ||
| 449 | return -1; | ||
| 450 | } | ||
| 451 | |||
| 452 | hid_set_field(field, offset, value); | ||
| 453 | usbhid_submit_report(hid, field->report, USB_DIR_OUT); | ||
| 454 | |||
| 455 | return 0; | ||
| 456 | } | ||
| 457 | |||
| 458 | int usbhid_wait_io(struct hid_device *hid) | ||
| 459 | { | ||
| 460 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 461 | |||
| 462 | if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) && | ||
| 463 | !test_bit(HID_OUT_RUNNING, &usbhid->iofl)), | ||
| 464 | 10*HZ)) { | ||
| 465 | dbg("timeout waiting for ctrl or out queue to clear"); | ||
| 466 | return -1; | ||
| 467 | } | ||
| 468 | |||
| 469 | return 0; | ||
| 470 | } | ||
| 471 | |||
| 472 | static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle) | ||
| 473 | { | ||
| 474 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
| 475 | HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (idle << 8) | report, | ||
| 476 | ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
| 477 | } | ||
| 478 | |||
| 479 | static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, | ||
| 480 | unsigned char type, void *buf, int size) | ||
| 481 | { | ||
| 482 | int result, retries = 4; | ||
| 483 | |||
| 484 | memset(buf, 0, size); | ||
| 485 | |||
| 486 | do { | ||
| 487 | result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
| 488 | USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, | ||
| 489 | (type << 8), ifnum, buf, size, USB_CTRL_GET_TIMEOUT); | ||
| 490 | retries--; | ||
| 491 | } while (result < size && retries); | ||
| 492 | return result; | ||
| 493 | } | ||
| 494 | |||
| 495 | int usbhid_open(struct hid_device *hid) | ||
| 496 | { | ||
| 497 | ++hid->open; | ||
| 498 | if (hid_start_in(hid)) | ||
| 499 | hid_io_error(hid); | ||
| 500 | return 0; | ||
| 501 | } | ||
| 502 | |||
| 503 | void usbhid_close(struct hid_device *hid) | ||
| 504 | { | ||
| 505 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 506 | |||
| 507 | if (!--hid->open) | ||
| 508 | usb_kill_urb(usbhid->urbin); | ||
| 509 | } | ||
| 510 | |||
| 511 | #define USB_VENDOR_ID_PANJIT 0x134c | ||
| 512 | |||
| 513 | #define USB_VENDOR_ID_TURBOX 0x062a | ||
| 514 | #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 | ||
| 515 | #define USB_VENDOR_ID_CIDC 0x1677 | ||
| 516 | |||
| 517 | /* | ||
| 518 | * Initialize all reports | ||
| 519 | */ | ||
| 520 | |||
| 521 | void usbhid_init_reports(struct hid_device *hid) | ||
| 522 | { | ||
| 523 | struct hid_report *report; | ||
| 524 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 525 | int err, ret; | ||
| 526 | |||
| 527 | list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) | ||
| 528 | usbhid_submit_report(hid, report, USB_DIR_IN); | ||
| 529 | |||
| 530 | list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list) | ||
| 531 | usbhid_submit_report(hid, report, USB_DIR_IN); | ||
| 532 | |||
| 533 | err = 0; | ||
| 534 | ret = usbhid_wait_io(hid); | ||
| 535 | while (ret) { | ||
| 536 | err |= ret; | ||
| 537 | if (test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) | ||
| 538 | usb_kill_urb(usbhid->urbctrl); | ||
| 539 | if (test_bit(HID_OUT_RUNNING, &usbhid->iofl)) | ||
| 540 | usb_kill_urb(usbhid->urbout); | ||
| 541 | ret = usbhid_wait_io(hid); | ||
| 542 | } | ||
| 543 | |||
| 544 | if (err) | ||
| 545 | warn("timeout initializing reports"); | ||
| 546 | } | ||
| 547 | |||
| 548 | #define USB_VENDOR_ID_GTCO 0x078c | ||
| 549 | #define USB_DEVICE_ID_GTCO_90 0x0090 | ||
| 550 | #define USB_DEVICE_ID_GTCO_100 0x0100 | ||
| 551 | #define USB_DEVICE_ID_GTCO_101 0x0101 | ||
| 552 | #define USB_DEVICE_ID_GTCO_103 0x0103 | ||
| 553 | #define USB_DEVICE_ID_GTCO_104 0x0104 | ||
| 554 | #define USB_DEVICE_ID_GTCO_105 0x0105 | ||
| 555 | #define USB_DEVICE_ID_GTCO_106 0x0106 | ||
| 556 | #define USB_DEVICE_ID_GTCO_107 0x0107 | ||
| 557 | #define USB_DEVICE_ID_GTCO_108 0x0108 | ||
| 558 | #define USB_DEVICE_ID_GTCO_200 0x0200 | ||
| 559 | #define USB_DEVICE_ID_GTCO_201 0x0201 | ||
| 560 | #define USB_DEVICE_ID_GTCO_202 0x0202 | ||
| 561 | #define USB_DEVICE_ID_GTCO_203 0x0203 | ||
| 562 | #define USB_DEVICE_ID_GTCO_204 0x0204 | ||
| 563 | #define USB_DEVICE_ID_GTCO_205 0x0205 | ||
| 564 | #define USB_DEVICE_ID_GTCO_206 0x0206 | ||
| 565 | #define USB_DEVICE_ID_GTCO_207 0x0207 | ||
| 566 | #define USB_DEVICE_ID_GTCO_300 0x0300 | ||
| 567 | #define USB_DEVICE_ID_GTCO_301 0x0301 | ||
| 568 | #define USB_DEVICE_ID_GTCO_302 0x0302 | ||
| 569 | #define USB_DEVICE_ID_GTCO_303 0x0303 | ||
| 570 | #define USB_DEVICE_ID_GTCO_304 0x0304 | ||
| 571 | #define USB_DEVICE_ID_GTCO_305 0x0305 | ||
| 572 | #define USB_DEVICE_ID_GTCO_306 0x0306 | ||
| 573 | #define USB_DEVICE_ID_GTCO_307 0x0307 | ||
| 574 | #define USB_DEVICE_ID_GTCO_308 0x0308 | ||
| 575 | #define USB_DEVICE_ID_GTCO_309 0x0309 | ||
| 576 | #define USB_DEVICE_ID_GTCO_400 0x0400 | ||
| 577 | #define USB_DEVICE_ID_GTCO_401 0x0401 | ||
| 578 | #define USB_DEVICE_ID_GTCO_402 0x0402 | ||
| 579 | #define USB_DEVICE_ID_GTCO_403 0x0403 | ||
| 580 | #define USB_DEVICE_ID_GTCO_404 0x0404 | ||
| 581 | #define USB_DEVICE_ID_GTCO_405 0x0405 | ||
| 582 | #define USB_DEVICE_ID_GTCO_500 0x0500 | ||
| 583 | #define USB_DEVICE_ID_GTCO_501 0x0501 | ||
| 584 | #define USB_DEVICE_ID_GTCO_502 0x0502 | ||
| 585 | #define USB_DEVICE_ID_GTCO_503 0x0503 | ||
| 586 | #define USB_DEVICE_ID_GTCO_504 0x0504 | ||
| 587 | #define USB_DEVICE_ID_GTCO_1000 0x1000 | ||
| 588 | #define USB_DEVICE_ID_GTCO_1001 0x1001 | ||
| 589 | #define USB_DEVICE_ID_GTCO_1002 0x1002 | ||
| 590 | #define USB_DEVICE_ID_GTCO_1003 0x1003 | ||
| 591 | #define USB_DEVICE_ID_GTCO_1004 0x1004 | ||
| 592 | #define USB_DEVICE_ID_GTCO_1005 0x1005 | ||
| 593 | #define USB_DEVICE_ID_GTCO_1006 0x1006 | ||
| 594 | |||
| 595 | #define USB_VENDOR_ID_WACOM 0x056a | ||
| 596 | |||
| 597 | #define USB_VENDOR_ID_ACECAD 0x0460 | ||
| 598 | #define USB_DEVICE_ID_ACECAD_FLAIR 0x0004 | ||
| 599 | #define USB_DEVICE_ID_ACECAD_302 0x0008 | ||
| 600 | |||
| 601 | #define USB_VENDOR_ID_KBGEAR 0x084e | ||
| 602 | #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 | ||
| 603 | |||
| 604 | #define USB_VENDOR_ID_AIPTEK 0x08ca | ||
| 605 | #define USB_DEVICE_ID_AIPTEK_01 0x0001 | ||
| 606 | #define USB_DEVICE_ID_AIPTEK_10 0x0010 | ||
| 607 | #define USB_DEVICE_ID_AIPTEK_20 0x0020 | ||
| 608 | #define USB_DEVICE_ID_AIPTEK_21 0x0021 | ||
| 609 | #define USB_DEVICE_ID_AIPTEK_22 0x0022 | ||
| 610 | #define USB_DEVICE_ID_AIPTEK_23 0x0023 | ||
| 611 | #define USB_DEVICE_ID_AIPTEK_24 0x0024 | ||
| 612 | |||
| 613 | #define USB_VENDOR_ID_GRIFFIN 0x077d | ||
| 614 | #define USB_DEVICE_ID_POWERMATE 0x0410 | ||
| 615 | #define USB_DEVICE_ID_SOUNDKNOB 0x04AA | ||
| 616 | |||
| 617 | #define USB_VENDOR_ID_ATEN 0x0557 | ||
| 618 | #define USB_DEVICE_ID_ATEN_UC100KM 0x2004 | ||
| 619 | #define USB_DEVICE_ID_ATEN_CS124U 0x2202 | ||
| 620 | #define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204 | ||
| 621 | #define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205 | ||
| 622 | #define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208 | ||
| 623 | |||
| 624 | #define USB_VENDOR_ID_TOPMAX 0x0663 | ||
| 625 | #define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 | ||
| 626 | |||
| 627 | #define USB_VENDOR_ID_HAPP 0x078b | ||
| 628 | #define USB_DEVICE_ID_UGCI_DRIVING 0x0010 | ||
| 629 | #define USB_DEVICE_ID_UGCI_FLYING 0x0020 | ||
| 630 | #define USB_DEVICE_ID_UGCI_FIGHTING 0x0030 | ||
| 631 | |||
| 632 | #define USB_VENDOR_ID_MGE 0x0463 | ||
| 633 | #define USB_DEVICE_ID_MGE_UPS 0xffff | ||
| 634 | #define USB_DEVICE_ID_MGE_UPS1 0x0001 | ||
| 635 | |||
| 636 | #define USB_VENDOR_ID_ONTRAK 0x0a07 | ||
| 637 | #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 | ||
| 638 | |||
| 639 | #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f | ||
| 640 | #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 | ||
| 641 | |||
| 642 | #define USB_VENDOR_ID_A4TECH 0x09da | ||
| 643 | #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 | ||
| 644 | |||
| 645 | #define USB_VENDOR_ID_AASHIMA 0x06d6 | ||
| 646 | #define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025 | ||
| 647 | #define USB_DEVICE_ID_AASHIMA_PREDATOR 0x0026 | ||
| 648 | |||
| 649 | #define USB_VENDOR_ID_CYPRESS 0x04b4 | ||
| 650 | #define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001 | ||
| 651 | #define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500 | ||
| 652 | #define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE 0x7417 | ||
| 653 | |||
| 654 | #define USB_VENDOR_ID_BERKSHIRE 0x0c98 | ||
| 655 | #define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140 | ||
| 656 | |||
| 657 | #define USB_VENDOR_ID_ALPS 0x0433 | ||
| 658 | #define USB_DEVICE_ID_IBM_GAMEPAD 0x1101 | ||
| 659 | |||
| 660 | #define USB_VENDOR_ID_SAITEK 0x06a3 | ||
| 661 | #define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 | ||
| 662 | |||
| 663 | #define USB_VENDOR_ID_NEC 0x073e | ||
| 664 | #define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301 | ||
| 665 | |||
| 666 | #define USB_VENDOR_ID_CHIC 0x05fe | ||
| 667 | #define USB_DEVICE_ID_CHIC_GAMEPAD 0x0014 | ||
| 668 | |||
| 669 | #define USB_VENDOR_ID_GLAB 0x06c2 | ||
| 670 | #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 | ||
| 671 | #define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 | ||
| 672 | #define USB_DEVICE_ID_0_0_4_IF_KIT 0x0040 | ||
| 673 | #define USB_DEVICE_ID_0_16_16_IF_KIT 0x0044 | ||
| 674 | #define USB_DEVICE_ID_8_8_8_IF_KIT 0x0045 | ||
| 675 | #define USB_DEVICE_ID_0_8_7_IF_KIT 0x0051 | ||
| 676 | #define USB_DEVICE_ID_0_8_8_IF_KIT 0x0053 | ||
| 677 | #define USB_DEVICE_ID_PHIDGET_MOTORCONTROL 0x0058 | ||
| 678 | |||
| 679 | #define USB_VENDOR_ID_WISEGROUP 0x0925 | ||
| 680 | #define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 | ||
| 681 | #define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104 | ||
| 682 | #define USB_DEVICE_ID_8_8_4_IF_KIT 0x8201 | ||
| 683 | #define USB_DEVICE_ID_DUAL_USB_JOYPAD 0x8866 | ||
| 684 | |||
| 685 | #define USB_VENDOR_ID_WISEGROUP_LTD 0x6677 | ||
| 686 | #define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802 | ||
| 687 | |||
| 688 | #define USB_VENDOR_ID_CODEMERCS 0x07c0 | ||
| 689 | #define USB_DEVICE_ID_CODEMERCS_IOW_FIRST 0x1500 | ||
| 690 | #define USB_DEVICE_ID_CODEMERCS_IOW_LAST 0x15ff | ||
| 691 | |||
| 692 | #define USB_VENDOR_ID_DELORME 0x1163 | ||
| 693 | #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 | ||
| 694 | #define USB_DEVICE_ID_DELORME_EM_LT20 0x0200 | ||
| 695 | |||
| 696 | #define USB_VENDOR_ID_MCC 0x09db | ||
| 697 | #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 | ||
| 698 | #define USB_DEVICE_ID_MCC_PMD1208LS 0x007a | ||
| 699 | |||
| 700 | #define USB_VENDOR_ID_VERNIER 0x08f7 | ||
| 701 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 | ||
| 702 | #define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 | ||
| 703 | #define USB_DEVICE_ID_VERNIER_SKIP 0x0003 | ||
| 704 | #define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 | ||
| 705 | |||
| 706 | #define USB_VENDOR_ID_LD 0x0f11 | ||
| 707 | #define USB_DEVICE_ID_LD_CASSY 0x1000 | ||
| 708 | #define USB_DEVICE_ID_LD_POCKETCASSY 0x1010 | ||
| 709 | #define USB_DEVICE_ID_LD_MOBILECASSY 0x1020 | ||
| 710 | #define USB_DEVICE_ID_LD_JWM 0x1080 | ||
| 711 | #define USB_DEVICE_ID_LD_DMMP 0x1081 | ||
| 712 | #define USB_DEVICE_ID_LD_UMIP 0x1090 | ||
| 713 | #define USB_DEVICE_ID_LD_XRAY1 0x1100 | ||
| 714 | #define USB_DEVICE_ID_LD_XRAY2 0x1101 | ||
| 715 | #define USB_DEVICE_ID_LD_VIDEOCOM 0x1200 | ||
| 716 | #define USB_DEVICE_ID_LD_COM3LAB 0x2000 | ||
| 717 | #define USB_DEVICE_ID_LD_TELEPORT 0x2010 | ||
| 718 | #define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020 | ||
| 719 | #define USB_DEVICE_ID_LD_POWERCONTROL 0x2030 | ||
| 720 | #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 | ||
| 721 | |||
| 722 | #define USB_VENDOR_ID_APPLE 0x05ac | ||
| 723 | #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 | ||
| 724 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e | ||
| 725 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f | ||
| 726 | #define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214 | ||
| 727 | #define USB_DEVICE_ID_APPLE_GEYSER_ISO 0x0215 | ||
| 728 | #define USB_DEVICE_ID_APPLE_GEYSER_JIS 0x0216 | ||
| 729 | #define USB_DEVICE_ID_APPLE_GEYSER3_ANSI 0x0217 | ||
| 730 | #define USB_DEVICE_ID_APPLE_GEYSER3_ISO 0x0218 | ||
| 731 | #define USB_DEVICE_ID_APPLE_GEYSER3_JIS 0x0219 | ||
| 732 | #define USB_DEVICE_ID_APPLE_GEYSER4_ANSI 0x021a | ||
| 733 | #define USB_DEVICE_ID_APPLE_GEYSER4_ISO 0x021b | ||
| 734 | #define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c | ||
| 735 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a | ||
| 736 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b | ||
| 737 | #define USB_DEVICE_ID_APPLE_IR 0x8240 | ||
| 738 | |||
| 739 | #define USB_VENDOR_ID_CHERRY 0x046a | ||
| 740 | #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 | ||
| 741 | |||
| 742 | #define USB_VENDOR_ID_YEALINK 0x6993 | ||
| 743 | #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001 | ||
| 744 | |||
| 745 | #define USB_VENDOR_ID_ALCOR 0x058f | ||
| 746 | #define USB_DEVICE_ID_ALCOR_USBRS232 0x9720 | ||
| 747 | |||
| 748 | #define USB_VENDOR_ID_SUN 0x0430 | ||
| 749 | #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab | ||
| 750 | |||
| 751 | #define USB_VENDOR_ID_AIRCABLE 0x16CA | ||
| 752 | #define USB_DEVICE_ID_AIRCABLE1 0x1502 | ||
| 753 | |||
| 754 | #define USB_VENDOR_ID_LOGITECH 0x046d | ||
| 755 | #define USB_DEVICE_ID_LOGITECH_USB_RECEIVER 0xc101 | ||
| 756 | #define USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2 0xc517 | ||
| 757 | #define USB_DEVICE_ID_DINOVO_EDGE 0xc714 | ||
| 758 | |||
| 759 | #define USB_VENDOR_ID_IMATION 0x0718 | ||
| 760 | #define USB_DEVICE_ID_DISC_STAKKA 0xd000 | ||
| 761 | |||
| 762 | #define USB_VENDOR_ID_PANTHERLORD 0x0810 | ||
| 763 | #define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001 | ||
| 764 | |||
| 765 | #define USB_VENDOR_ID_SONY 0x054c | ||
| 766 | #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 | ||
| 767 | |||
| 768 | /* | ||
| 769 | * Alphabetically sorted blacklist by quirk type. | ||
| 770 | */ | ||
| 771 | |||
| 772 | static const struct hid_blacklist { | ||
| 773 | __u16 idVendor; | ||
| 774 | __u16 idProduct; | ||
| 775 | unsigned quirks; | ||
| 776 | } hid_blacklist[] = { | ||
| 777 | |||
| 778 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES }, | ||
| 779 | |||
| 780 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE }, | ||
| 781 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE }, | ||
| 782 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE }, | ||
| 783 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_21, HID_QUIRK_IGNORE }, | ||
| 784 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE }, | ||
| 785 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE }, | ||
| 786 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE }, | ||
| 787 | { USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1, HID_QUIRK_IGNORE }, | ||
| 788 | { USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232, HID_QUIRK_IGNORE }, | ||
| 789 | { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE }, | ||
| 790 | { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE }, | ||
| 791 | { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE }, | ||
| 792 | { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE }, | ||
| 793 | { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20, HID_QUIRK_IGNORE }, | ||
| 794 | { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE }, | ||
| 795 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, | ||
| 796 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, | ||
| 797 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE }, | ||
| 798 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_16_16_IF_KIT, HID_QUIRK_IGNORE }, | ||
| 799 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE }, | ||
| 800 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT, HID_QUIRK_IGNORE }, | ||
| 801 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE }, | ||
| 802 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL, HID_QUIRK_IGNORE }, | ||
| 803 | { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE }, | ||
| 804 | { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE }, | ||
| 805 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE }, | ||
| 806 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100, HID_QUIRK_IGNORE }, | ||
| 807 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101, HID_QUIRK_IGNORE }, | ||
| 808 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_103, HID_QUIRK_IGNORE }, | ||
| 809 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_104, HID_QUIRK_IGNORE }, | ||
| 810 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_105, HID_QUIRK_IGNORE }, | ||
| 811 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_106, HID_QUIRK_IGNORE }, | ||
| 812 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_107, HID_QUIRK_IGNORE }, | ||
| 813 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_108, HID_QUIRK_IGNORE }, | ||
| 814 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_200, HID_QUIRK_IGNORE }, | ||
| 815 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_201, HID_QUIRK_IGNORE }, | ||
| 816 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_202, HID_QUIRK_IGNORE }, | ||
| 817 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_203, HID_QUIRK_IGNORE }, | ||
| 818 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_204, HID_QUIRK_IGNORE }, | ||
| 819 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_205, HID_QUIRK_IGNORE }, | ||
| 820 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_206, HID_QUIRK_IGNORE }, | ||
| 821 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_207, HID_QUIRK_IGNORE }, | ||
| 822 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_300, HID_QUIRK_IGNORE }, | ||
| 823 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_301, HID_QUIRK_IGNORE }, | ||
| 824 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_302, HID_QUIRK_IGNORE }, | ||
| 825 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_303, HID_QUIRK_IGNORE }, | ||
| 826 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_304, HID_QUIRK_IGNORE }, | ||
| 827 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_305, HID_QUIRK_IGNORE }, | ||
| 828 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_306, HID_QUIRK_IGNORE }, | ||
| 829 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_307, HID_QUIRK_IGNORE }, | ||
| 830 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_308, HID_QUIRK_IGNORE }, | ||
| 831 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_309, HID_QUIRK_IGNORE }, | ||
| 832 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_400, HID_QUIRK_IGNORE }, | ||
| 833 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_401, HID_QUIRK_IGNORE }, | ||
| 834 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_402, HID_QUIRK_IGNORE }, | ||
| 835 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_403, HID_QUIRK_IGNORE }, | ||
| 836 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404, HID_QUIRK_IGNORE }, | ||
| 837 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_405, HID_QUIRK_IGNORE }, | ||
| 838 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_500, HID_QUIRK_IGNORE }, | ||
| 839 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_501, HID_QUIRK_IGNORE }, | ||
| 840 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502, HID_QUIRK_IGNORE }, | ||
| 841 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503, HID_QUIRK_IGNORE }, | ||
| 842 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504, HID_QUIRK_IGNORE }, | ||
| 843 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000, HID_QUIRK_IGNORE }, | ||
| 844 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001, HID_QUIRK_IGNORE }, | ||
| 845 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002, HID_QUIRK_IGNORE }, | ||
| 846 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1003, HID_QUIRK_IGNORE }, | ||
| 847 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE }, | ||
| 848 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE }, | ||
| 849 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE }, | ||
| 850 | { USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA, HID_QUIRK_IGNORE }, | ||
| 851 | { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE }, | ||
| 852 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE }, | ||
| 853 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY, HID_QUIRK_IGNORE }, | ||
| 854 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY, HID_QUIRK_IGNORE }, | ||
| 855 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM, HID_QUIRK_IGNORE }, | ||
| 856 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP, HID_QUIRK_IGNORE }, | ||
| 857 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP, HID_QUIRK_IGNORE }, | ||
| 858 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1, HID_QUIRK_IGNORE }, | ||
| 859 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2, HID_QUIRK_IGNORE }, | ||
| 860 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM, HID_QUIRK_IGNORE }, | ||
| 861 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB, HID_QUIRK_IGNORE }, | ||
| 862 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT, HID_QUIRK_IGNORE }, | ||
| 863 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER, HID_QUIRK_IGNORE }, | ||
| 864 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL, HID_QUIRK_IGNORE }, | ||
| 865 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST, HID_QUIRK_IGNORE }, | ||
| 866 | { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS, HID_QUIRK_IGNORE }, | ||
| 867 | { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS, HID_QUIRK_IGNORE }, | ||
| 868 | { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE }, | ||
| 869 | { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE }, | ||
| 870 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE }, | ||
| 871 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20, HID_QUIRK_IGNORE }, | ||
| 872 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 30, HID_QUIRK_IGNORE }, | ||
| 873 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE }, | ||
| 874 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 108, HID_QUIRK_IGNORE }, | ||
| 875 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 118, HID_QUIRK_IGNORE }, | ||
| 876 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE }, | ||
| 877 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE }, | ||
| 878 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE }, | ||
| 879 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE }, | ||
| 880 | { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO, HID_QUIRK_IGNORE }, | ||
| 881 | { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP, HID_QUIRK_IGNORE }, | ||
| 882 | { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP, HID_QUIRK_IGNORE }, | ||
| 883 | { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE }, | ||
| 884 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, | ||
| 885 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, | ||
| 886 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT, HID_QUIRK_IGNORE }, | ||
| 887 | { USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE }, | ||
| 888 | |||
| 889 | { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE }, | ||
| 890 | { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE }, | ||
| 891 | |||
| 892 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, | ||
| 893 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, | ||
| 894 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, | ||
| 895 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, | ||
| 896 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, | ||
| 897 | { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, | ||
| 898 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | ||
| 899 | { USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | ||
| 900 | |||
| 901 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL }, | ||
| 902 | { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 }, | ||
| 903 | { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 }, | ||
| 904 | |||
| 905 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD }, | ||
| 906 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, | ||
| 907 | { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, | ||
| 908 | { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, | ||
| 909 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | ||
| 910 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | ||
| 911 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | ||
| 912 | { USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD, HID_QUIRK_BADPAD }, | ||
| 913 | { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, | ||
| 914 | { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, | ||
| 915 | |||
| 916 | { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION }, | ||
| 917 | |||
| 918 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
| 919 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
| 920 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
| 921 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, | ||
| 922 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
| 923 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
| 924 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, | ||
| 925 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
| 926 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
| 927 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, | ||
| 928 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
| 929 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
| 930 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
| 931 | |||
| 932 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IR, HID_QUIRK_IGNORE }, | ||
| 933 | |||
| 934 | { USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE }, | ||
| 935 | { USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE }, | ||
| 936 | { USB_VENDOR_ID_PANJIT, 0x0003, HID_QUIRK_IGNORE }, | ||
| 937 | { USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE }, | ||
| 938 | |||
| 939 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, | ||
| 940 | |||
| 941 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS }, | ||
| 942 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2, HID_QUIRK_LOGITECH_S510_DESCRIPTOR }, | ||
| 943 | |||
| 944 | { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | ||
| 945 | |||
| 946 | { USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER }, | ||
| 947 | |||
| 948 | { USB_VENDOR_ID_CIDC, 0x0103, HID_QUIRK_IGNORE }, | ||
| 949 | |||
| 950 | { 0, 0 } | ||
| 951 | }; | ||
| 952 | |||
| 953 | /* | ||
| 954 | * Traverse the supplied list of reports and find the longest | ||
| 955 | */ | ||
| 956 | static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *max) | ||
| 957 | { | ||
| 958 | struct hid_report *report; | ||
| 959 | int size; | ||
| 960 | |||
| 961 | list_for_each_entry(report, &hid->report_enum[type].report_list, list) { | ||
| 962 | size = ((report->size - 1) >> 3) + 1; | ||
| 963 | if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered) | ||
| 964 | size++; | ||
| 965 | if (*max < size) | ||
| 966 | *max = size; | ||
| 967 | } | ||
| 968 | } | ||
| 969 | |||
| 970 | static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) | ||
| 971 | { | ||
| 972 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 973 | |||
| 974 | if (!(usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->inbuf_dma))) | ||
| 975 | return -1; | ||
| 976 | if (!(usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->outbuf_dma))) | ||
| 977 | return -1; | ||
| 978 | if (!(usbhid->cr = usb_buffer_alloc(dev, sizeof(*(usbhid->cr)), GFP_ATOMIC, &usbhid->cr_dma))) | ||
| 979 | return -1; | ||
| 980 | if (!(usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->ctrlbuf_dma))) | ||
| 981 | return -1; | ||
| 982 | |||
| 983 | return 0; | ||
| 984 | } | ||
| 985 | |||
| 986 | static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) | ||
| 987 | { | ||
| 988 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 989 | |||
| 990 | if (usbhid->inbuf) | ||
| 991 | usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma); | ||
| 992 | if (usbhid->outbuf) | ||
| 993 | usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma); | ||
| 994 | if (usbhid->cr) | ||
| 995 | usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma); | ||
| 996 | if (usbhid->ctrlbuf) | ||
| 997 | usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma); | ||
| 998 | } | ||
| 999 | |||
| 1000 | /* | ||
| 1001 | * Cherry Cymotion keyboard have an invalid HID report descriptor, | ||
| 1002 | * that needs fixing before we can parse it. | ||
| 1003 | */ | ||
| 1004 | |||
| 1005 | static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize) | ||
| 1006 | { | ||
| 1007 | if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { | ||
| 1008 | info("Fixing up Cherry Cymotion report descriptor"); | ||
| 1009 | rdesc[11] = rdesc[16] = 0xff; | ||
| 1010 | rdesc[12] = rdesc[17] = 0x03; | ||
| 1011 | } | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | /* | ||
| 1015 | * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller | ||
| 1016 | * to "operational". Without this, the ps3 controller will not report any | ||
| 1017 | * events. | ||
| 1018 | */ | ||
| 1019 | static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum) | ||
| 1020 | { | ||
| 1021 | int result; | ||
| 1022 | char *buf = kmalloc(18, GFP_KERNEL); | ||
| 1023 | |||
| 1024 | if (!buf) | ||
| 1025 | return; | ||
| 1026 | |||
| 1027 | result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
| 1028 | HID_REQ_GET_REPORT, | ||
| 1029 | USB_DIR_IN | USB_TYPE_CLASS | | ||
| 1030 | USB_RECIP_INTERFACE, | ||
| 1031 | (3 << 8) | 0xf2, ifnum, buf, 17, | ||
| 1032 | USB_CTRL_GET_TIMEOUT); | ||
| 1033 | |||
| 1034 | if (result < 0) | ||
| 1035 | err("%s failed: %d\n", __func__, result); | ||
| 1036 | |||
| 1037 | kfree(buf); | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | /* | ||
| 1041 | * Logitech S510 keyboard sends in report #3 keys which are far | ||
| 1042 | * above the logical maximum described in descriptor. This extends | ||
| 1043 | * the original value of 0x28c of logical maximum to 0x104d | ||
| 1044 | */ | ||
| 1045 | static void hid_fixup_s510_descriptor(unsigned char *rdesc, int rsize) | ||
| 1046 | { | ||
| 1047 | if (rsize >= 90 && rdesc[83] == 0x26 | ||
| 1048 | && rdesc[84] == 0x8c | ||
| 1049 | && rdesc[85] == 0x02) { | ||
| 1050 | info("Fixing up Logitech S510 report descriptor"); | ||
| 1051 | rdesc[84] = rdesc[89] = 0x4d; | ||
| 1052 | rdesc[85] = rdesc[90] = 0x10; | ||
| 1053 | } | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) | ||
| 1057 | { | ||
| 1058 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
| 1059 | struct usb_device *dev = interface_to_usbdev (intf); | ||
| 1060 | struct hid_descriptor *hdesc; | ||
| 1061 | struct hid_device *hid; | ||
| 1062 | unsigned quirks = 0, rsize = 0; | ||
| 1063 | char *rdesc; | ||
| 1064 | int n, len, insize = 0; | ||
| 1065 | struct usbhid_device *usbhid; | ||
| 1066 | |||
| 1067 | /* Ignore all Wacom devices */ | ||
| 1068 | if (le16_to_cpu(dev->descriptor.idVendor) == USB_VENDOR_ID_WACOM) | ||
| 1069 | return NULL; | ||
| 1070 | /* ignore all Code Mercenaries IOWarrior devices */ | ||
| 1071 | if (le16_to_cpu(dev->descriptor.idVendor) == USB_VENDOR_ID_CODEMERCS) | ||
| 1072 | if (le16_to_cpu(dev->descriptor.idProduct) >= USB_DEVICE_ID_CODEMERCS_IOW_FIRST && | ||
| 1073 | le16_to_cpu(dev->descriptor.idProduct) <= USB_DEVICE_ID_CODEMERCS_IOW_LAST) | ||
| 1074 | return NULL; | ||
| 1075 | |||
| 1076 | for (n = 0; hid_blacklist[n].idVendor; n++) | ||
| 1077 | if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) && | ||
| 1078 | (hid_blacklist[n].idProduct == le16_to_cpu(dev->descriptor.idProduct))) | ||
| 1079 | quirks = hid_blacklist[n].quirks; | ||
| 1080 | |||
| 1081 | /* Many keyboards and mice don't like to be polled for reports, | ||
| 1082 | * so we will always set the HID_QUIRK_NOGET flag for them. */ | ||
| 1083 | if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) { | ||
| 1084 | if (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD || | ||
| 1085 | interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) | ||
| 1086 | quirks |= HID_QUIRK_NOGET; | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | if (quirks & HID_QUIRK_IGNORE) | ||
| 1090 | return NULL; | ||
| 1091 | |||
| 1092 | if ((quirks & HID_QUIRK_IGNORE_MOUSE) && | ||
| 1093 | (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)) | ||
| 1094 | return NULL; | ||
| 1095 | |||
| 1096 | |||
| 1097 | if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && | ||
| 1098 | (!interface->desc.bNumEndpoints || | ||
| 1099 | usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) { | ||
| 1100 | dbg("class descriptor not present\n"); | ||
| 1101 | return NULL; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | for (n = 0; n < hdesc->bNumDescriptors; n++) | ||
| 1105 | if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) | ||
| 1106 | rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); | ||
| 1107 | |||
| 1108 | if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) { | ||
| 1109 | dbg("weird size of report descriptor (%u)", rsize); | ||
| 1110 | return NULL; | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) { | ||
| 1114 | dbg("couldn't allocate rdesc memory"); | ||
| 1115 | return NULL; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0); | ||
| 1119 | |||
| 1120 | if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) { | ||
| 1121 | dbg("reading report descriptor failed"); | ||
| 1122 | kfree(rdesc); | ||
| 1123 | return NULL; | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | if ((quirks & HID_QUIRK_CYMOTION)) | ||
| 1127 | hid_fixup_cymotion_descriptor(rdesc, rsize); | ||
| 1128 | |||
| 1129 | if (quirks & HID_QUIRK_LOGITECH_S510_DESCRIPTOR) | ||
| 1130 | hid_fixup_s510_descriptor(rdesc, rsize); | ||
| 1131 | |||
| 1132 | #ifdef CONFIG_HID_DEBUG | ||
| 1133 | printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); | ||
| 1134 | for (n = 0; n < rsize; n++) | ||
| 1135 | printk(" %02x", (unsigned char) rdesc[n]); | ||
| 1136 | printk("\n"); | ||
| 1137 | #endif | ||
| 1138 | |||
| 1139 | if (!(hid = hid_parse_report(rdesc, n))) { | ||
| 1140 | dbg("parsing report descriptor failed"); | ||
| 1141 | kfree(rdesc); | ||
| 1142 | return NULL; | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | kfree(rdesc); | ||
| 1146 | hid->quirks = quirks; | ||
| 1147 | |||
| 1148 | if (!(usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL))) | ||
| 1149 | goto fail; | ||
| 1150 | |||
| 1151 | hid->driver_data = usbhid; | ||
| 1152 | usbhid->hid = hid; | ||
| 1153 | |||
| 1154 | usbhid->bufsize = HID_MIN_BUFFER_SIZE; | ||
| 1155 | hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize); | ||
| 1156 | hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize); | ||
| 1157 | hid_find_max_report(hid, HID_FEATURE_REPORT, &usbhid->bufsize); | ||
| 1158 | |||
| 1159 | if (usbhid->bufsize > HID_MAX_BUFFER_SIZE) | ||
| 1160 | usbhid->bufsize = HID_MAX_BUFFER_SIZE; | ||
| 1161 | |||
| 1162 | hid_find_max_report(hid, HID_INPUT_REPORT, &insize); | ||
| 1163 | |||
| 1164 | if (insize > HID_MAX_BUFFER_SIZE) | ||
| 1165 | insize = HID_MAX_BUFFER_SIZE; | ||
| 1166 | |||
| 1167 | if (hid_alloc_buffers(dev, hid)) { | ||
| 1168 | hid_free_buffers(dev, hid); | ||
| 1169 | goto fail; | ||
| 1170 | } | ||
| 1171 | |||
| 1172 | for (n = 0; n < interface->desc.bNumEndpoints; n++) { | ||
| 1173 | |||
| 1174 | struct usb_endpoint_descriptor *endpoint; | ||
| 1175 | int pipe; | ||
| 1176 | int interval; | ||
| 1177 | |||
| 1178 | endpoint = &interface->endpoint[n].desc; | ||
| 1179 | if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */ | ||
| 1180 | continue; | ||
| 1181 | |||
| 1182 | interval = endpoint->bInterval; | ||
| 1183 | |||
| 1184 | /* Change the polling interval of mice. */ | ||
| 1185 | if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) | ||
| 1186 | interval = hid_mousepoll_interval; | ||
| 1187 | |||
| 1188 | if (usb_endpoint_dir_in(endpoint)) { | ||
| 1189 | if (usbhid->urbin) | ||
| 1190 | continue; | ||
| 1191 | if (!(usbhid->urbin = usb_alloc_urb(0, GFP_KERNEL))) | ||
| 1192 | goto fail; | ||
| 1193 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | ||
| 1194 | usb_fill_int_urb(usbhid->urbin, dev, pipe, usbhid->inbuf, insize, | ||
| 1195 | hid_irq_in, hid, interval); | ||
| 1196 | usbhid->urbin->transfer_dma = usbhid->inbuf_dma; | ||
| 1197 | usbhid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
| 1198 | } else { | ||
| 1199 | if (usbhid->urbout) | ||
| 1200 | continue; | ||
| 1201 | if (!(usbhid->urbout = usb_alloc_urb(0, GFP_KERNEL))) | ||
| 1202 | goto fail; | ||
| 1203 | pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress); | ||
| 1204 | usb_fill_int_urb(usbhid->urbout, dev, pipe, usbhid->outbuf, 0, | ||
| 1205 | hid_irq_out, hid, interval); | ||
| 1206 | usbhid->urbout->transfer_dma = usbhid->outbuf_dma; | ||
| 1207 | usbhid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
| 1208 | } | ||
| 1209 | } | ||
| 1210 | |||
| 1211 | if (!usbhid->urbin) { | ||
| 1212 | err("couldn't find an input interrupt endpoint"); | ||
| 1213 | goto fail; | ||
| 1214 | } | ||
| 1215 | |||
| 1216 | init_waitqueue_head(&hid->wait); | ||
| 1217 | |||
| 1218 | INIT_WORK(&usbhid->reset_work, hid_reset); | ||
| 1219 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); | ||
| 1220 | |||
| 1221 | spin_lock_init(&usbhid->inlock); | ||
| 1222 | spin_lock_init(&usbhid->outlock); | ||
| 1223 | spin_lock_init(&usbhid->ctrllock); | ||
| 1224 | |||
| 1225 | hid->version = le16_to_cpu(hdesc->bcdHID); | ||
| 1226 | hid->country = hdesc->bCountryCode; | ||
| 1227 | hid->dev = &intf->dev; | ||
| 1228 | usbhid->intf = intf; | ||
| 1229 | usbhid->ifnum = interface->desc.bInterfaceNumber; | ||
| 1230 | |||
| 1231 | hid->name[0] = 0; | ||
| 1232 | |||
| 1233 | if (dev->manufacturer) | ||
| 1234 | strlcpy(hid->name, dev->manufacturer, sizeof(hid->name)); | ||
| 1235 | |||
| 1236 | if (dev->product) { | ||
| 1237 | if (dev->manufacturer) | ||
| 1238 | strlcat(hid->name, " ", sizeof(hid->name)); | ||
| 1239 | strlcat(hid->name, dev->product, sizeof(hid->name)); | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | if (!strlen(hid->name)) | ||
| 1243 | snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x", | ||
| 1244 | le16_to_cpu(dev->descriptor.idVendor), | ||
| 1245 | le16_to_cpu(dev->descriptor.idProduct)); | ||
| 1246 | |||
| 1247 | hid->bus = BUS_USB; | ||
| 1248 | hid->vendor = le16_to_cpu(dev->descriptor.idVendor); | ||
| 1249 | hid->product = le16_to_cpu(dev->descriptor.idProduct); | ||
| 1250 | |||
| 1251 | usb_make_path(dev, hid->phys, sizeof(hid->phys)); | ||
| 1252 | strlcat(hid->phys, "/input", sizeof(hid->phys)); | ||
| 1253 | len = strlen(hid->phys); | ||
| 1254 | if (len < sizeof(hid->phys) - 1) | ||
| 1255 | snprintf(hid->phys + len, sizeof(hid->phys) - len, | ||
| 1256 | "%d", intf->altsetting[0].desc.bInterfaceNumber); | ||
| 1257 | |||
| 1258 | if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0) | ||
| 1259 | hid->uniq[0] = 0; | ||
| 1260 | |||
| 1261 | usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL); | ||
| 1262 | if (!usbhid->urbctrl) | ||
| 1263 | goto fail; | ||
| 1264 | |||
| 1265 | usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr, | ||
| 1266 | usbhid->ctrlbuf, 1, hid_ctrl, hid); | ||
| 1267 | usbhid->urbctrl->setup_dma = usbhid->cr_dma; | ||
| 1268 | usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma; | ||
| 1269 | usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); | ||
| 1270 | hid->hidinput_input_event = usb_hidinput_input_event; | ||
| 1271 | hid->hid_open = usbhid_open; | ||
| 1272 | hid->hid_close = usbhid_close; | ||
| 1273 | #ifdef CONFIG_USB_HIDDEV | ||
| 1274 | hid->hiddev_hid_event = hiddev_hid_event; | ||
| 1275 | hid->hiddev_report_event = hiddev_report_event; | ||
| 1276 | #endif | ||
| 1277 | return hid; | ||
| 1278 | |||
| 1279 | fail: | ||
| 1280 | usb_free_urb(usbhid->urbin); | ||
| 1281 | usb_free_urb(usbhid->urbout); | ||
| 1282 | usb_free_urb(usbhid->urbctrl); | ||
| 1283 | hid_free_buffers(dev, hid); | ||
| 1284 | hid_free_device(hid); | ||
| 1285 | |||
| 1286 | return NULL; | ||
| 1287 | } | ||
| 1288 | |||
| 1289 | static void hid_disconnect(struct usb_interface *intf) | ||
| 1290 | { | ||
| 1291 | struct hid_device *hid = usb_get_intfdata (intf); | ||
| 1292 | struct usbhid_device *usbhid; | ||
| 1293 | |||
| 1294 | if (!hid) | ||
| 1295 | return; | ||
| 1296 | |||
| 1297 | usbhid = hid->driver_data; | ||
| 1298 | |||
| 1299 | spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ | ||
| 1300 | usb_set_intfdata(intf, NULL); | ||
| 1301 | spin_unlock_irq(&usbhid->inlock); | ||
| 1302 | usb_kill_urb(usbhid->urbin); | ||
| 1303 | usb_kill_urb(usbhid->urbout); | ||
| 1304 | usb_kill_urb(usbhid->urbctrl); | ||
| 1305 | |||
| 1306 | del_timer_sync(&usbhid->io_retry); | ||
| 1307 | flush_scheduled_work(); | ||
| 1308 | |||
| 1309 | if (hid->claimed & HID_CLAIMED_INPUT) | ||
| 1310 | hidinput_disconnect(hid); | ||
| 1311 | if (hid->claimed & HID_CLAIMED_HIDDEV) | ||
| 1312 | hiddev_disconnect(hid); | ||
| 1313 | |||
| 1314 | usb_free_urb(usbhid->urbin); | ||
| 1315 | usb_free_urb(usbhid->urbctrl); | ||
| 1316 | usb_free_urb(usbhid->urbout); | ||
| 1317 | |||
| 1318 | hid_free_buffers(hid_to_usb_dev(hid), hid); | ||
| 1319 | hid_free_device(hid); | ||
| 1320 | } | ||
| 1321 | |||
| 1322 | static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
| 1323 | { | ||
| 1324 | struct hid_device *hid; | ||
| 1325 | char path[64]; | ||
| 1326 | int i; | ||
| 1327 | char *c; | ||
| 1328 | |||
| 1329 | dbg("HID probe called for ifnum %d", | ||
| 1330 | intf->altsetting->desc.bInterfaceNumber); | ||
| 1331 | |||
| 1332 | if (!(hid = usb_hid_configure(intf))) | ||
| 1333 | return -ENODEV; | ||
| 1334 | |||
| 1335 | usbhid_init_reports(hid); | ||
| 1336 | hid_dump_device(hid); | ||
| 1337 | |||
| 1338 | if (!hidinput_connect(hid)) | ||
| 1339 | hid->claimed |= HID_CLAIMED_INPUT; | ||
| 1340 | if (!hiddev_connect(hid)) | ||
| 1341 | hid->claimed |= HID_CLAIMED_HIDDEV; | ||
| 1342 | |||
| 1343 | usb_set_intfdata(intf, hid); | ||
| 1344 | |||
| 1345 | if (!hid->claimed) { | ||
| 1346 | printk ("HID device not claimed by input or hiddev\n"); | ||
| 1347 | hid_disconnect(intf); | ||
| 1348 | return -ENODEV; | ||
| 1349 | } | ||
| 1350 | |||
| 1351 | if ((hid->claimed & HID_CLAIMED_INPUT)) | ||
| 1352 | hid_ff_init(hid); | ||
| 1353 | |||
| 1354 | if (hid->quirks & HID_QUIRK_SONY_PS3_CONTROLLER) | ||
| 1355 | hid_fixup_sony_ps3_controller(interface_to_usbdev(intf), | ||
| 1356 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
| 1357 | |||
| 1358 | printk(KERN_INFO); | ||
| 1359 | |||
| 1360 | if (hid->claimed & HID_CLAIMED_INPUT) | ||
| 1361 | printk("input"); | ||
| 1362 | if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV)) | ||
| 1363 | printk(","); | ||
| 1364 | if (hid->claimed & HID_CLAIMED_HIDDEV) | ||
| 1365 | printk("hiddev%d", hid->minor); | ||
| 1366 | |||
| 1367 | c = "Device"; | ||
| 1368 | for (i = 0; i < hid->maxcollection; i++) { | ||
| 1369 | if (hid->collection[i].type == HID_COLLECTION_APPLICATION && | ||
| 1370 | (hid->collection[i].usage & HID_USAGE_PAGE) == HID_UP_GENDESK && | ||
| 1371 | (hid->collection[i].usage & 0xffff) < ARRAY_SIZE(hid_types)) { | ||
| 1372 | c = hid_types[hid->collection[i].usage & 0xffff]; | ||
| 1373 | break; | ||
| 1374 | } | ||
| 1375 | } | ||
| 1376 | |||
| 1377 | usb_make_path(interface_to_usbdev(intf), path, 63); | ||
| 1378 | |||
| 1379 | printk(": USB HID v%x.%02x %s [%s] on %s\n", | ||
| 1380 | hid->version >> 8, hid->version & 0xff, c, hid->name, path); | ||
| 1381 | |||
| 1382 | return 0; | ||
| 1383 | } | ||
| 1384 | |||
| 1385 | static int hid_suspend(struct usb_interface *intf, pm_message_t message) | ||
| 1386 | { | ||
| 1387 | struct hid_device *hid = usb_get_intfdata (intf); | ||
| 1388 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 1389 | |||
| 1390 | spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ | ||
| 1391 | set_bit(HID_SUSPENDED, &usbhid->iofl); | ||
| 1392 | spin_unlock_irq(&usbhid->inlock); | ||
| 1393 | del_timer(&usbhid->io_retry); | ||
| 1394 | usb_kill_urb(usbhid->urbin); | ||
| 1395 | dev_dbg(&intf->dev, "suspend\n"); | ||
| 1396 | return 0; | ||
| 1397 | } | ||
| 1398 | |||
| 1399 | static int hid_resume(struct usb_interface *intf) | ||
| 1400 | { | ||
| 1401 | struct hid_device *hid = usb_get_intfdata (intf); | ||
| 1402 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 1403 | int status; | ||
| 1404 | |||
| 1405 | clear_bit(HID_SUSPENDED, &usbhid->iofl); | ||
| 1406 | usbhid->retry_delay = 0; | ||
| 1407 | status = hid_start_in(hid); | ||
| 1408 | dev_dbg(&intf->dev, "resume status %d\n", status); | ||
| 1409 | return status; | ||
| 1410 | } | ||
| 1411 | |||
| 1412 | /* Treat USB reset pretty much the same as suspend/resume */ | ||
| 1413 | static void hid_pre_reset(struct usb_interface *intf) | ||
| 1414 | { | ||
| 1415 | /* FIXME: What if the interface is already suspended? */ | ||
| 1416 | hid_suspend(intf, PMSG_ON); | ||
| 1417 | } | ||
| 1418 | |||
| 1419 | static void hid_post_reset(struct usb_interface *intf) | ||
| 1420 | { | ||
| 1421 | struct usb_device *dev = interface_to_usbdev (intf); | ||
| 1422 | |||
| 1423 | hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0); | ||
| 1424 | /* FIXME: Any more reinitialization needed? */ | ||
| 1425 | |||
| 1426 | hid_resume(intf); | ||
| 1427 | } | ||
| 1428 | |||
| 1429 | static struct usb_device_id hid_usb_ids [] = { | ||
| 1430 | { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, | ||
| 1431 | .bInterfaceClass = USB_INTERFACE_CLASS_HID }, | ||
| 1432 | { } /* Terminating entry */ | ||
| 1433 | }; | ||
| 1434 | |||
| 1435 | MODULE_DEVICE_TABLE (usb, hid_usb_ids); | ||
| 1436 | |||
| 1437 | static struct usb_driver hid_driver = { | ||
| 1438 | .name = "usbhid", | ||
| 1439 | .probe = hid_probe, | ||
| 1440 | .disconnect = hid_disconnect, | ||
| 1441 | .suspend = hid_suspend, | ||
| 1442 | .resume = hid_resume, | ||
| 1443 | .pre_reset = hid_pre_reset, | ||
| 1444 | .post_reset = hid_post_reset, | ||
| 1445 | .id_table = hid_usb_ids, | ||
| 1446 | }; | ||
| 1447 | |||
| 1448 | static int __init hid_init(void) | ||
| 1449 | { | ||
| 1450 | int retval; | ||
| 1451 | retval = hiddev_init(); | ||
| 1452 | if (retval) | ||
| 1453 | goto hiddev_init_fail; | ||
| 1454 | retval = usb_register(&hid_driver); | ||
| 1455 | if (retval) | ||
| 1456 | goto usb_register_fail; | ||
| 1457 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
| 1458 | |||
| 1459 | return 0; | ||
| 1460 | usb_register_fail: | ||
| 1461 | hiddev_exit(); | ||
| 1462 | hiddev_init_fail: | ||
| 1463 | return retval; | ||
| 1464 | } | ||
| 1465 | |||
| 1466 | static void __exit hid_exit(void) | ||
| 1467 | { | ||
| 1468 | usb_deregister(&hid_driver); | ||
| 1469 | hiddev_exit(); | ||
| 1470 | } | ||
| 1471 | |||
| 1472 | module_init(hid_init); | ||
| 1473 | module_exit(hid_exit); | ||
| 1474 | |||
| 1475 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
| 1476 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 1477 | MODULE_LICENSE(DRIVER_LICENSE); | ||
diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c deleted file mode 100644 index e431faaa6abc..000000000000 --- a/drivers/usb/input/hid-ff.c +++ /dev/null | |||
| @@ -1,89 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * $Id: hid-ff.c,v 1.2 2002/04/18 22:02:47 jdeneux Exp $ | ||
| 3 | * | ||
| 4 | * Force feedback support for hid devices. | ||
| 5 | * Not all hid devices use the same protocol. For example, some use PID, | ||
| 6 | * other use their own proprietary procotol. | ||
| 7 | * | ||
| 8 | * Copyright (c) 2002-2004 Johann Deneux | ||
| 9 | */ | ||
| 10 | |||
| 11 | /* | ||
| 12 | * This program is free software; you can redistribute it and/or modify | ||
| 13 | * it under the terms of the GNU General Public License as published by | ||
| 14 | * the Free Software Foundation; either version 2 of the License, or | ||
| 15 | * (at your option) any later version. | ||
| 16 | * | ||
| 17 | * This program is distributed in the hope that it will be useful, | ||
| 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | * GNU General Public License for more details. | ||
| 21 | * | ||
| 22 | * You should have received a copy of the GNU General Public License | ||
| 23 | * along with this program; if not, write to the Free Software | ||
| 24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 25 | * | ||
| 26 | * Should you need to contact me, the author, you can do so by | ||
| 27 | * e-mail - mail your message to <johann.deneux@it.uu.se> | ||
| 28 | */ | ||
| 29 | |||
| 30 | #include <linux/input.h> | ||
| 31 | |||
| 32 | #undef DEBUG | ||
| 33 | #include <linux/usb.h> | ||
| 34 | |||
| 35 | #include <linux/hid.h> | ||
| 36 | #include "usbhid.h" | ||
| 37 | |||
| 38 | /* | ||
| 39 | * This table contains pointers to initializers. To add support for new | ||
| 40 | * devices, you need to add the USB vendor and product ids here. | ||
| 41 | */ | ||
| 42 | struct hid_ff_initializer { | ||
| 43 | u16 idVendor; | ||
| 44 | u16 idProduct; | ||
| 45 | int (*init)(struct hid_device*); | ||
| 46 | }; | ||
| 47 | |||
| 48 | /* | ||
| 49 | * We try pidff when no other driver is found because PID is the | ||
| 50 | * standards compliant way of implementing force feedback in HID. | ||
| 51 | * pidff_init() will quickly abort if the device doesn't appear to | ||
| 52 | * be a PID device | ||
| 53 | */ | ||
| 54 | static struct hid_ff_initializer inits[] = { | ||
| 55 | #ifdef CONFIG_LOGITECH_FF | ||
| 56 | { 0x46d, 0xc211, hid_lgff_init }, /* Logitech Cordless rumble pad */ | ||
| 57 | { 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */ | ||
| 58 | { 0x46d, 0xc283, hid_lgff_init }, /* Logitech Wingman Force 3d */ | ||
| 59 | { 0x46d, 0xc294, hid_lgff_init }, /* Logitech Formula Force EX */ | ||
| 60 | { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */ | ||
| 61 | { 0x46d, 0xca03, hid_lgff_init }, /* Logitech MOMO force wheel */ | ||
| 62 | #endif | ||
| 63 | #ifdef CONFIG_PANTHERLORD_FF | ||
| 64 | { 0x810, 0x0001, hid_plff_init }, | ||
| 65 | #endif | ||
| 66 | #ifdef CONFIG_THRUSTMASTER_FF | ||
| 67 | { 0x44f, 0xb304, hid_tmff_init }, | ||
| 68 | #endif | ||
| 69 | #ifdef CONFIG_ZEROPLUS_FF | ||
| 70 | { 0xc12, 0x0005, hid_zpff_init }, | ||
| 71 | { 0xc12, 0x0030, hid_zpff_init }, | ||
| 72 | #endif | ||
| 73 | { 0, 0, hid_pidff_init} /* Matches anything */ | ||
| 74 | }; | ||
| 75 | |||
| 76 | int hid_ff_init(struct hid_device* hid) | ||
| 77 | { | ||
| 78 | struct hid_ff_initializer *init; | ||
| 79 | int vendor = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idVendor); | ||
| 80 | int product = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idProduct); | ||
| 81 | |||
| 82 | for (init = inits; init->idVendor; init++) | ||
| 83 | if (init->idVendor == vendor && init->idProduct == product) | ||
| 84 | break; | ||
| 85 | |||
| 86 | return init->init(hid); | ||
| 87 | } | ||
| 88 | EXPORT_SYMBOL_GPL(hid_ff_init); | ||
| 89 | |||
diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c deleted file mode 100644 index e6f3af3e66d1..000000000000 --- a/drivers/usb/input/hid-lgff.c +++ /dev/null | |||
| @@ -1,150 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Force feedback support for hid-compliant for some of the devices from | ||
| 3 | * Logitech, namely: | ||
| 4 | * - WingMan Cordless RumblePad | ||
| 5 | * - WingMan Force 3D | ||
| 6 | * | ||
| 7 | * Copyright (c) 2002-2004 Johann Deneux | ||
| 8 | * Copyright (c) 2006 Anssi Hannula <anssi.hannula@gmail.com> | ||
| 9 | */ | ||
| 10 | |||
| 11 | /* | ||
| 12 | * This program is free software; you can redistribute it and/or modify | ||
| 13 | * it under the terms of the GNU General Public License as published by | ||
| 14 | * the Free Software Foundation; either version 2 of the License, or | ||
| 15 | * (at your option) any later version. | ||
| 16 | * | ||
| 17 | * This program is distributed in the hope that it will be useful, | ||
| 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | * GNU General Public License for more details. | ||
| 21 | * | ||
| 22 | * You should have received a copy of the GNU General Public License | ||
| 23 | * along with this program; if not, write to the Free Software | ||
| 24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 25 | * | ||
| 26 | * Should you need to contact me, the author, you can do so by | ||
| 27 | * e-mail - mail your message to <johann.deneux@it.uu.se> | ||
| 28 | */ | ||
| 29 | |||
| 30 | #include <linux/input.h> | ||
| 31 | #include <linux/usb.h> | ||
| 32 | #include <linux/hid.h> | ||
| 33 | #include "usbhid.h" | ||
| 34 | |||
| 35 | struct dev_type { | ||
| 36 | u16 idVendor; | ||
| 37 | u16 idProduct; | ||
| 38 | const signed short *ff; | ||
| 39 | }; | ||
| 40 | |||
| 41 | static const signed short ff_rumble[] = { | ||
| 42 | FF_RUMBLE, | ||
| 43 | -1 | ||
| 44 | }; | ||
| 45 | |||
| 46 | static const signed short ff_joystick[] = { | ||
| 47 | FF_CONSTANT, | ||
| 48 | -1 | ||
| 49 | }; | ||
| 50 | |||
| 51 | static const struct dev_type devices[] = { | ||
| 52 | { 0x046d, 0xc211, ff_rumble }, | ||
| 53 | { 0x046d, 0xc219, ff_rumble }, | ||
| 54 | { 0x046d, 0xc283, ff_joystick }, | ||
| 55 | { 0x046d, 0xc294, ff_joystick }, | ||
| 56 | { 0x046d, 0xc295, ff_joystick }, | ||
| 57 | { 0x046d, 0xca03, ff_joystick }, | ||
| 58 | }; | ||
| 59 | |||
| 60 | static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect) | ||
| 61 | { | ||
| 62 | struct hid_device *hid = dev->private; | ||
| 63 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
| 64 | struct hid_report *report = list_entry(report_list->next, struct hid_report, list); | ||
| 65 | int x, y; | ||
| 66 | unsigned int left, right; | ||
| 67 | |||
| 68 | #define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff | ||
| 69 | |||
| 70 | switch (effect->type) { | ||
| 71 | case FF_CONSTANT: | ||
| 72 | x = effect->u.ramp.start_level + 0x7f; /* 0x7f is center */ | ||
| 73 | y = effect->u.ramp.end_level + 0x7f; | ||
| 74 | CLAMP(x); | ||
| 75 | CLAMP(y); | ||
| 76 | report->field[0]->value[0] = 0x51; | ||
| 77 | report->field[0]->value[1] = 0x08; | ||
| 78 | report->field[0]->value[2] = x; | ||
| 79 | report->field[0]->value[3] = y; | ||
| 80 | dbg("(x, y)=(%04x, %04x)", x, y); | ||
| 81 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
| 82 | break; | ||
| 83 | |||
| 84 | case FF_RUMBLE: | ||
| 85 | right = effect->u.rumble.strong_magnitude; | ||
| 86 | left = effect->u.rumble.weak_magnitude; | ||
| 87 | right = right * 0xff / 0xffff; | ||
| 88 | left = left * 0xff / 0xffff; | ||
| 89 | CLAMP(left); | ||
| 90 | CLAMP(right); | ||
| 91 | report->field[0]->value[0] = 0x42; | ||
| 92 | report->field[0]->value[1] = 0x00; | ||
| 93 | report->field[0]->value[2] = left; | ||
| 94 | report->field[0]->value[3] = right; | ||
| 95 | dbg("(left, right)=(%04x, %04x)", left, right); | ||
| 96 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
| 97 | break; | ||
| 98 | } | ||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | int hid_lgff_init(struct hid_device* hid) | ||
| 103 | { | ||
| 104 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); | ||
| 105 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
| 106 | struct input_dev *dev = hidinput->input; | ||
| 107 | struct hid_report *report; | ||
| 108 | struct hid_field *field; | ||
| 109 | const signed short *ff_bits = ff_joystick; | ||
| 110 | int error; | ||
| 111 | int i; | ||
| 112 | |||
| 113 | /* Find the report to use */ | ||
| 114 | if (list_empty(report_list)) { | ||
| 115 | err("No output report found"); | ||
| 116 | return -1; | ||
| 117 | } | ||
| 118 | |||
| 119 | /* Check that the report looks ok */ | ||
| 120 | report = list_entry(report_list->next, struct hid_report, list); | ||
| 121 | if (!report) { | ||
| 122 | err("NULL output report"); | ||
| 123 | return -1; | ||
| 124 | } | ||
| 125 | |||
| 126 | field = report->field[0]; | ||
| 127 | if (!field) { | ||
| 128 | err("NULL field"); | ||
| 129 | return -1; | ||
| 130 | } | ||
| 131 | |||
| 132 | for (i = 0; i < ARRAY_SIZE(devices); i++) { | ||
| 133 | if (dev->id.vendor == devices[i].idVendor && | ||
| 134 | dev->id.product == devices[i].idProduct) { | ||
| 135 | ff_bits = devices[i].ff; | ||
| 136 | break; | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | for (i = 0; ff_bits[i] >= 0; i++) | ||
| 141 | set_bit(ff_bits[i], dev->ffbit); | ||
| 142 | |||
| 143 | error = input_ff_create_memless(dev, NULL, hid_lgff_play); | ||
| 144 | if (error) | ||
| 145 | return error; | ||
| 146 | |||
| 147 | printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n"); | ||
| 148 | |||
| 149 | return 0; | ||
| 150 | } | ||
diff --git a/drivers/usb/input/hid-pidff.c b/drivers/usb/input/hid-pidff.c deleted file mode 100644 index f5a90e950e6b..000000000000 --- a/drivers/usb/input/hid-pidff.c +++ /dev/null | |||
| @@ -1,1331 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Force feedback driver for USB HID PID compliant devices | ||
| 3 | * | ||
| 4 | * Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.com> | ||
| 5 | */ | ||
| 6 | |||
| 7 | /* | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 21 | */ | ||
| 22 | |||
| 23 | /* #define DEBUG */ | ||
| 24 | |||
| 25 | #define debug(format, arg...) pr_debug("hid-pidff: " format "\n" , ## arg) | ||
| 26 | |||
| 27 | #include <linux/input.h> | ||
| 28 | #include <linux/usb.h> | ||
| 29 | |||
| 30 | #include <linux/hid.h> | ||
| 31 | |||
| 32 | #include "usbhid.h" | ||
| 33 | |||
| 34 | #define PID_EFFECTS_MAX 64 | ||
| 35 | |||
| 36 | /* Report usage table used to put reports into an array */ | ||
| 37 | |||
| 38 | #define PID_SET_EFFECT 0 | ||
| 39 | #define PID_EFFECT_OPERATION 1 | ||
| 40 | #define PID_DEVICE_GAIN 2 | ||
| 41 | #define PID_POOL 3 | ||
| 42 | #define PID_BLOCK_LOAD 4 | ||
| 43 | #define PID_BLOCK_FREE 5 | ||
| 44 | #define PID_DEVICE_CONTROL 6 | ||
| 45 | #define PID_CREATE_NEW_EFFECT 7 | ||
| 46 | |||
| 47 | #define PID_REQUIRED_REPORTS 7 | ||
| 48 | |||
| 49 | #define PID_SET_ENVELOPE 8 | ||
| 50 | #define PID_SET_CONDITION 9 | ||
| 51 | #define PID_SET_PERIODIC 10 | ||
| 52 | #define PID_SET_CONSTANT 11 | ||
| 53 | #define PID_SET_RAMP 12 | ||
| 54 | static const u8 pidff_reports[] = { | ||
| 55 | 0x21, 0x77, 0x7d, 0x7f, 0x89, 0x90, 0x96, 0xab, | ||
| 56 | 0x5a, 0x5f, 0x6e, 0x73, 0x74 | ||
| 57 | }; | ||
| 58 | |||
| 59 | /* device_control is really 0x95, but 0x96 specified as it is the usage of | ||
| 60 | the only field in that report */ | ||
| 61 | |||
| 62 | /* Value usage tables used to put fields and values into arrays */ | ||
| 63 | |||
| 64 | #define PID_EFFECT_BLOCK_INDEX 0 | ||
| 65 | |||
| 66 | #define PID_DURATION 1 | ||
| 67 | #define PID_GAIN 2 | ||
| 68 | #define PID_TRIGGER_BUTTON 3 | ||
| 69 | #define PID_TRIGGER_REPEAT_INT 4 | ||
| 70 | #define PID_DIRECTION_ENABLE 5 | ||
| 71 | #define PID_START_DELAY 6 | ||
| 72 | static const u8 pidff_set_effect[] = { | ||
| 73 | 0x22, 0x50, 0x52, 0x53, 0x54, 0x56, 0xa7 | ||
| 74 | }; | ||
| 75 | |||
| 76 | #define PID_ATTACK_LEVEL 1 | ||
| 77 | #define PID_ATTACK_TIME 2 | ||
| 78 | #define PID_FADE_LEVEL 3 | ||
| 79 | #define PID_FADE_TIME 4 | ||
| 80 | static const u8 pidff_set_envelope[] = { 0x22, 0x5b, 0x5c, 0x5d, 0x5e }; | ||
| 81 | |||
| 82 | #define PID_PARAM_BLOCK_OFFSET 1 | ||
| 83 | #define PID_CP_OFFSET 2 | ||
| 84 | #define PID_POS_COEFFICIENT 3 | ||
| 85 | #define PID_NEG_COEFFICIENT 4 | ||
| 86 | #define PID_POS_SATURATION 5 | ||
| 87 | #define PID_NEG_SATURATION 6 | ||
| 88 | #define PID_DEAD_BAND 7 | ||
| 89 | static const u8 pidff_set_condition[] = { | ||
| 90 | 0x22, 0x23, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65 | ||
| 91 | }; | ||
| 92 | |||
| 93 | #define PID_MAGNITUDE 1 | ||
| 94 | #define PID_OFFSET 2 | ||
| 95 | #define PID_PHASE 3 | ||
| 96 | #define PID_PERIOD 4 | ||
| 97 | static const u8 pidff_set_periodic[] = { 0x22, 0x70, 0x6f, 0x71, 0x72 }; | ||
| 98 | static const u8 pidff_set_constant[] = { 0x22, 0x70 }; | ||
| 99 | |||
| 100 | #define PID_RAMP_START 1 | ||
| 101 | #define PID_RAMP_END 2 | ||
| 102 | static const u8 pidff_set_ramp[] = { 0x22, 0x75, 0x76 }; | ||
| 103 | |||
| 104 | #define PID_RAM_POOL_AVAILABLE 1 | ||
| 105 | static const u8 pidff_block_load[] = { 0x22, 0xac }; | ||
| 106 | |||
| 107 | #define PID_LOOP_COUNT 1 | ||
| 108 | static const u8 pidff_effect_operation[] = { 0x22, 0x7c }; | ||
| 109 | |||
| 110 | static const u8 pidff_block_free[] = { 0x22 }; | ||
| 111 | |||
| 112 | #define PID_DEVICE_GAIN_FIELD 0 | ||
| 113 | static const u8 pidff_device_gain[] = { 0x7e }; | ||
| 114 | |||
| 115 | #define PID_RAM_POOL_SIZE 0 | ||
| 116 | #define PID_SIMULTANEOUS_MAX 1 | ||
| 117 | #define PID_DEVICE_MANAGED_POOL 2 | ||
| 118 | static const u8 pidff_pool[] = { 0x80, 0x83, 0xa9 }; | ||
| 119 | |||
| 120 | /* Special field key tables used to put special field keys into arrays */ | ||
| 121 | |||
| 122 | #define PID_ENABLE_ACTUATORS 0 | ||
| 123 | #define PID_RESET 1 | ||
| 124 | static const u8 pidff_device_control[] = { 0x97, 0x9a }; | ||
| 125 | |||
| 126 | #define PID_CONSTANT 0 | ||
| 127 | #define PID_RAMP 1 | ||
| 128 | #define PID_SQUARE 2 | ||
| 129 | #define PID_SINE 3 | ||
| 130 | #define PID_TRIANGLE 4 | ||
| 131 | #define PID_SAW_UP 5 | ||
| 132 | #define PID_SAW_DOWN 6 | ||
| 133 | #define PID_SPRING 7 | ||
| 134 | #define PID_DAMPER 8 | ||
| 135 | #define PID_INERTIA 9 | ||
| 136 | #define PID_FRICTION 10 | ||
| 137 | static const u8 pidff_effect_types[] = { | ||
| 138 | 0x26, 0x27, 0x30, 0x31, 0x32, 0x33, 0x34, | ||
| 139 | 0x40, 0x41, 0x42, 0x43 | ||
| 140 | }; | ||
| 141 | |||
| 142 | #define PID_BLOCK_LOAD_SUCCESS 0 | ||
| 143 | #define PID_BLOCK_LOAD_FULL 1 | ||
| 144 | static const u8 pidff_block_load_status[] = { 0x8c, 0x8d }; | ||
| 145 | |||
| 146 | #define PID_EFFECT_START 0 | ||
| 147 | #define PID_EFFECT_STOP 1 | ||
| 148 | static const u8 pidff_effect_operation_status[] = { 0x79, 0x7b }; | ||
| 149 | |||
| 150 | struct pidff_usage { | ||
| 151 | struct hid_field *field; | ||
| 152 | s32 *value; | ||
| 153 | }; | ||
| 154 | |||
| 155 | struct pidff_device { | ||
| 156 | struct hid_device *hid; | ||
| 157 | |||
| 158 | struct hid_report *reports[sizeof(pidff_reports)]; | ||
| 159 | |||
| 160 | struct pidff_usage set_effect[sizeof(pidff_set_effect)]; | ||
| 161 | struct pidff_usage set_envelope[sizeof(pidff_set_envelope)]; | ||
| 162 | struct pidff_usage set_condition[sizeof(pidff_set_condition)]; | ||
| 163 | struct pidff_usage set_periodic[sizeof(pidff_set_periodic)]; | ||
| 164 | struct pidff_usage set_constant[sizeof(pidff_set_constant)]; | ||
| 165 | struct pidff_usage set_ramp[sizeof(pidff_set_ramp)]; | ||
| 166 | |||
| 167 | struct pidff_usage device_gain[sizeof(pidff_device_gain)]; | ||
| 168 | struct pidff_usage block_load[sizeof(pidff_block_load)]; | ||
| 169 | struct pidff_usage pool[sizeof(pidff_pool)]; | ||
| 170 | struct pidff_usage effect_operation[sizeof(pidff_effect_operation)]; | ||
| 171 | struct pidff_usage block_free[sizeof(pidff_block_free)]; | ||
| 172 | |||
| 173 | /* Special field is a field that is not composed of | ||
| 174 | usage<->value pairs that pidff_usage values are */ | ||
| 175 | |||
| 176 | /* Special field in create_new_effect */ | ||
| 177 | struct hid_field *create_new_effect_type; | ||
| 178 | |||
| 179 | /* Special fields in set_effect */ | ||
| 180 | struct hid_field *set_effect_type; | ||
| 181 | struct hid_field *effect_direction; | ||
| 182 | |||
| 183 | /* Special field in device_control */ | ||
| 184 | struct hid_field *device_control; | ||
| 185 | |||
| 186 | /* Special field in block_load */ | ||
| 187 | struct hid_field *block_load_status; | ||
| 188 | |||
| 189 | /* Special field in effect_operation */ | ||
| 190 | struct hid_field *effect_operation_status; | ||
| 191 | |||
| 192 | int control_id[sizeof(pidff_device_control)]; | ||
| 193 | int type_id[sizeof(pidff_effect_types)]; | ||
| 194 | int status_id[sizeof(pidff_block_load_status)]; | ||
| 195 | int operation_id[sizeof(pidff_effect_operation_status)]; | ||
| 196 | |||
| 197 | int pid_id[PID_EFFECTS_MAX]; | ||
| 198 | }; | ||
| 199 | |||
| 200 | /* | ||
| 201 | * Scale an unsigned value with range 0..max for the given field | ||
| 202 | */ | ||
| 203 | static int pidff_rescale(int i, int max, struct hid_field *field) | ||
| 204 | { | ||
| 205 | return i * (field->logical_maximum - field->logical_minimum) / max + | ||
| 206 | field->logical_minimum; | ||
| 207 | } | ||
| 208 | |||
| 209 | /* | ||
| 210 | * Scale a signed value in range -0x8000..0x7fff for the given field | ||
| 211 | */ | ||
| 212 | static int pidff_rescale_signed(int i, struct hid_field *field) | ||
| 213 | { | ||
| 214 | return i == 0 ? 0 : i > | ||
| 215 | 0 ? i * field->logical_maximum / 0x7fff : i * | ||
| 216 | field->logical_minimum / -0x8000; | ||
| 217 | } | ||
| 218 | |||
| 219 | static void pidff_set(struct pidff_usage *usage, u16 value) | ||
| 220 | { | ||
| 221 | usage->value[0] = pidff_rescale(value, 0xffff, usage->field); | ||
| 222 | debug("calculated from %d to %d", value, usage->value[0]); | ||
| 223 | } | ||
| 224 | |||
| 225 | static void pidff_set_signed(struct pidff_usage *usage, s16 value) | ||
| 226 | { | ||
| 227 | if (usage->field->logical_minimum < 0) | ||
| 228 | usage->value[0] = pidff_rescale_signed(value, usage->field); | ||
| 229 | else { | ||
| 230 | if (value < 0) | ||
| 231 | usage->value[0] = | ||
| 232 | pidff_rescale(-value, 0x8000, usage->field); | ||
| 233 | else | ||
| 234 | usage->value[0] = | ||
| 235 | pidff_rescale(value, 0x7fff, usage->field); | ||
| 236 | } | ||
| 237 | debug("calculated from %d to %d", value, usage->value[0]); | ||
| 238 | } | ||
| 239 | |||
| 240 | /* | ||
| 241 | * Send envelope report to the device | ||
| 242 | */ | ||
| 243 | static void pidff_set_envelope_report(struct pidff_device *pidff, | ||
| 244 | struct ff_envelope *envelope) | ||
| 245 | { | ||
| 246 | pidff->set_envelope[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
| 247 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
| 248 | |||
| 249 | pidff->set_envelope[PID_ATTACK_LEVEL].value[0] = | ||
| 250 | pidff_rescale(envelope->attack_level > | ||
| 251 | 0x7fff ? 0x7fff : envelope->attack_level, 0x7fff, | ||
| 252 | pidff->set_envelope[PID_ATTACK_LEVEL].field); | ||
| 253 | pidff->set_envelope[PID_FADE_LEVEL].value[0] = | ||
| 254 | pidff_rescale(envelope->fade_level > | ||
| 255 | 0x7fff ? 0x7fff : envelope->fade_level, 0x7fff, | ||
| 256 | pidff->set_envelope[PID_FADE_LEVEL].field); | ||
| 257 | |||
| 258 | pidff->set_envelope[PID_ATTACK_TIME].value[0] = envelope->attack_length; | ||
| 259 | pidff->set_envelope[PID_FADE_TIME].value[0] = envelope->fade_length; | ||
| 260 | |||
| 261 | debug("attack %u => %d", envelope->attack_level, | ||
| 262 | pidff->set_envelope[PID_ATTACK_LEVEL].value[0]); | ||
| 263 | |||
| 264 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE], | ||
| 265 | USB_DIR_OUT); | ||
| 266 | } | ||
| 267 | |||
| 268 | /* | ||
| 269 | * Test if the new envelope differs from old one | ||
| 270 | */ | ||
| 271 | static int pidff_needs_set_envelope(struct ff_envelope *envelope, | ||
| 272 | struct ff_envelope *old) | ||
| 273 | { | ||
| 274 | return envelope->attack_level != old->attack_level || | ||
| 275 | envelope->fade_level != old->fade_level || | ||
| 276 | envelope->attack_length != old->attack_length || | ||
| 277 | envelope->fade_length != old->fade_length; | ||
| 278 | } | ||
| 279 | |||
| 280 | /* | ||
| 281 | * Send constant force report to the device | ||
| 282 | */ | ||
| 283 | static void pidff_set_constant_force_report(struct pidff_device *pidff, | ||
| 284 | struct ff_effect *effect) | ||
| 285 | { | ||
| 286 | pidff->set_constant[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
| 287 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
| 288 | pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE], | ||
| 289 | effect->u.constant.level); | ||
| 290 | |||
| 291 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT], | ||
| 292 | USB_DIR_OUT); | ||
| 293 | } | ||
| 294 | |||
| 295 | /* | ||
| 296 | * Test if the constant parameters have changed between effects | ||
| 297 | */ | ||
| 298 | static int pidff_needs_set_constant(struct ff_effect *effect, | ||
| 299 | struct ff_effect *old) | ||
| 300 | { | ||
| 301 | return effect->u.constant.level != old->u.constant.level; | ||
| 302 | } | ||
| 303 | |||
| 304 | /* | ||
| 305 | * Send set effect report to the device | ||
| 306 | */ | ||
| 307 | static void pidff_set_effect_report(struct pidff_device *pidff, | ||
| 308 | struct ff_effect *effect) | ||
| 309 | { | ||
| 310 | pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
| 311 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
| 312 | pidff->set_effect_type->value[0] = | ||
| 313 | pidff->create_new_effect_type->value[0]; | ||
| 314 | pidff->set_effect[PID_DURATION].value[0] = effect->replay.length; | ||
| 315 | pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = effect->trigger.button; | ||
| 316 | pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = | ||
| 317 | effect->trigger.interval; | ||
| 318 | pidff->set_effect[PID_GAIN].value[0] = | ||
| 319 | pidff->set_effect[PID_GAIN].field->logical_maximum; | ||
| 320 | pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1; | ||
| 321 | pidff->effect_direction->value[0] = | ||
| 322 | pidff_rescale(effect->direction, 0xffff, | ||
| 323 | pidff->effect_direction); | ||
| 324 | pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay; | ||
| 325 | |||
| 326 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], | ||
| 327 | USB_DIR_OUT); | ||
| 328 | } | ||
| 329 | |||
| 330 | /* | ||
| 331 | * Test if the values used in set_effect have changed | ||
| 332 | */ | ||
| 333 | static int pidff_needs_set_effect(struct ff_effect *effect, | ||
| 334 | struct ff_effect *old) | ||
| 335 | { | ||
| 336 | return effect->replay.length != old->replay.length || | ||
| 337 | effect->trigger.interval != old->trigger.interval || | ||
| 338 | effect->trigger.button != old->trigger.button || | ||
| 339 | effect->direction != old->direction || | ||
| 340 | effect->replay.delay != old->replay.delay; | ||
| 341 | } | ||
| 342 | |||
| 343 | /* | ||
| 344 | * Send periodic effect report to the device | ||
| 345 | */ | ||
| 346 | static void pidff_set_periodic_report(struct pidff_device *pidff, | ||
| 347 | struct ff_effect *effect) | ||
| 348 | { | ||
| 349 | pidff->set_periodic[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
| 350 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
| 351 | pidff_set_signed(&pidff->set_periodic[PID_MAGNITUDE], | ||
| 352 | effect->u.periodic.magnitude); | ||
| 353 | pidff_set_signed(&pidff->set_periodic[PID_OFFSET], | ||
| 354 | effect->u.periodic.offset); | ||
| 355 | pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase); | ||
| 356 | pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period; | ||
| 357 | |||
| 358 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC], | ||
| 359 | USB_DIR_OUT); | ||
| 360 | |||
| 361 | } | ||
| 362 | |||
| 363 | /* | ||
| 364 | * Test if periodic effect parameters have changed | ||
| 365 | */ | ||
| 366 | static int pidff_needs_set_periodic(struct ff_effect *effect, | ||
| 367 | struct ff_effect *old) | ||
| 368 | { | ||
| 369 | return effect->u.periodic.magnitude != old->u.periodic.magnitude || | ||
| 370 | effect->u.periodic.offset != old->u.periodic.offset || | ||
| 371 | effect->u.periodic.phase != old->u.periodic.phase || | ||
| 372 | effect->u.periodic.period != old->u.periodic.period; | ||
| 373 | } | ||
| 374 | |||
| 375 | /* | ||
| 376 | * Send condition effect reports to the device | ||
| 377 | */ | ||
| 378 | static void pidff_set_condition_report(struct pidff_device *pidff, | ||
| 379 | struct ff_effect *effect) | ||
| 380 | { | ||
| 381 | int i; | ||
| 382 | |||
| 383 | pidff->set_condition[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
| 384 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
| 385 | |||
| 386 | for (i = 0; i < 2; i++) { | ||
| 387 | pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i; | ||
| 388 | pidff_set_signed(&pidff->set_condition[PID_CP_OFFSET], | ||
| 389 | effect->u.condition[i].center); | ||
| 390 | pidff_set_signed(&pidff->set_condition[PID_POS_COEFFICIENT], | ||
| 391 | effect->u.condition[i].right_coeff); | ||
| 392 | pidff_set_signed(&pidff->set_condition[PID_NEG_COEFFICIENT], | ||
| 393 | effect->u.condition[i].left_coeff); | ||
| 394 | pidff_set(&pidff->set_condition[PID_POS_SATURATION], | ||
| 395 | effect->u.condition[i].right_saturation); | ||
| 396 | pidff_set(&pidff->set_condition[PID_NEG_SATURATION], | ||
| 397 | effect->u.condition[i].left_saturation); | ||
| 398 | pidff_set(&pidff->set_condition[PID_DEAD_BAND], | ||
| 399 | effect->u.condition[i].deadband); | ||
| 400 | usbhid_wait_io(pidff->hid); | ||
| 401 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION], | ||
| 402 | USB_DIR_OUT); | ||
| 403 | } | ||
| 404 | } | ||
| 405 | |||
| 406 | /* | ||
| 407 | * Test if condition effect parameters have changed | ||
| 408 | */ | ||
| 409 | static int pidff_needs_set_condition(struct ff_effect *effect, | ||
| 410 | struct ff_effect *old) | ||
| 411 | { | ||
| 412 | int i; | ||
| 413 | int ret = 0; | ||
| 414 | |||
| 415 | for (i = 0; i < 2; i++) { | ||
| 416 | struct ff_condition_effect *cond = &effect->u.condition[i]; | ||
| 417 | struct ff_condition_effect *old_cond = &old->u.condition[i]; | ||
| 418 | |||
| 419 | ret |= cond->center != old_cond->center || | ||
| 420 | cond->right_coeff != old_cond->right_coeff || | ||
| 421 | cond->left_coeff != old_cond->left_coeff || | ||
| 422 | cond->right_saturation != old_cond->right_saturation || | ||
| 423 | cond->left_saturation != old_cond->left_saturation || | ||
| 424 | cond->deadband != old_cond->deadband; | ||
| 425 | } | ||
| 426 | |||
| 427 | return ret; | ||
| 428 | } | ||
| 429 | |||
| 430 | /* | ||
| 431 | * Send ramp force report to the device | ||
| 432 | */ | ||
| 433 | static void pidff_set_ramp_force_report(struct pidff_device *pidff, | ||
| 434 | struct ff_effect *effect) | ||
| 435 | { | ||
| 436 | pidff->set_ramp[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
| 437 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
| 438 | pidff_set_signed(&pidff->set_ramp[PID_RAMP_START], | ||
| 439 | effect->u.ramp.start_level); | ||
| 440 | pidff_set_signed(&pidff->set_ramp[PID_RAMP_END], | ||
| 441 | effect->u.ramp.end_level); | ||
| 442 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP], | ||
| 443 | USB_DIR_OUT); | ||
| 444 | } | ||
| 445 | |||
| 446 | /* | ||
| 447 | * Test if ramp force parameters have changed | ||
| 448 | */ | ||
| 449 | static int pidff_needs_set_ramp(struct ff_effect *effect, struct ff_effect *old) | ||
| 450 | { | ||
| 451 | return effect->u.ramp.start_level != old->u.ramp.start_level || | ||
| 452 | effect->u.ramp.end_level != old->u.ramp.end_level; | ||
| 453 | } | ||
| 454 | |||
| 455 | /* | ||
| 456 | * Send a request for effect upload to the device | ||
| 457 | * | ||
| 458 | * Returns 0 if device reported success, -ENOSPC if the device reported memory | ||
| 459 | * is full. Upon unknown response the function will retry for 60 times, if | ||
| 460 | * still unsuccessful -EIO is returned. | ||
| 461 | */ | ||
| 462 | static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum) | ||
| 463 | { | ||
| 464 | int j; | ||
| 465 | |||
| 466 | pidff->create_new_effect_type->value[0] = efnum; | ||
| 467 | usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT], | ||
| 468 | USB_DIR_OUT); | ||
| 469 | debug("create_new_effect sent, type: %d", efnum); | ||
| 470 | |||
| 471 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0; | ||
| 472 | pidff->block_load_status->value[0] = 0; | ||
| 473 | usbhid_wait_io(pidff->hid); | ||
| 474 | |||
| 475 | for (j = 0; j < 60; j++) { | ||
| 476 | debug("pid_block_load requested"); | ||
| 477 | usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD], | ||
| 478 | USB_DIR_IN); | ||
| 479 | usbhid_wait_io(pidff->hid); | ||
| 480 | if (pidff->block_load_status->value[0] == | ||
| 481 | pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) { | ||
| 482 | debug("device reported free memory: %d bytes", | ||
| 483 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? | ||
| 484 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); | ||
| 485 | return 0; | ||
| 486 | } | ||
| 487 | if (pidff->block_load_status->value[0] == | ||
| 488 | pidff->status_id[PID_BLOCK_LOAD_FULL]) { | ||
| 489 | debug("not enough memory free: %d bytes", | ||
| 490 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? | ||
| 491 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); | ||
| 492 | return -ENOSPC; | ||
| 493 | } | ||
| 494 | } | ||
| 495 | printk(KERN_ERR "hid-pidff: pid_block_load failed 60 times\n"); | ||
| 496 | return -EIO; | ||
| 497 | } | ||
| 498 | |||
| 499 | /* | ||
| 500 | * Play the effect with PID id n times | ||
| 501 | */ | ||
| 502 | static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n) | ||
| 503 | { | ||
| 504 | pidff->effect_operation[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id; | ||
| 505 | |||
| 506 | if (n == 0) { | ||
| 507 | pidff->effect_operation_status->value[0] = | ||
| 508 | pidff->operation_id[PID_EFFECT_STOP]; | ||
| 509 | } else { | ||
| 510 | pidff->effect_operation_status->value[0] = | ||
| 511 | pidff->operation_id[PID_EFFECT_START]; | ||
| 512 | pidff->effect_operation[PID_LOOP_COUNT].value[0] = n; | ||
| 513 | } | ||
| 514 | |||
| 515 | usbhid_wait_io(pidff->hid); | ||
| 516 | usbhid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION], | ||
| 517 | USB_DIR_OUT); | ||
| 518 | } | ||
| 519 | |||
| 520 | /** | ||
| 521 | * Play the effect with effect id @effect_id for @value times | ||
| 522 | */ | ||
| 523 | static int pidff_playback(struct input_dev *dev, int effect_id, int value) | ||
| 524 | { | ||
| 525 | struct pidff_device *pidff = dev->ff->private; | ||
| 526 | |||
| 527 | pidff_playback_pid(pidff, pidff->pid_id[effect_id], value); | ||
| 528 | |||
| 529 | return 0; | ||
| 530 | } | ||
| 531 | |||
| 532 | /* | ||
| 533 | * Erase effect with PID id | ||
| 534 | */ | ||
| 535 | static void pidff_erase_pid(struct pidff_device *pidff, int pid_id) | ||
| 536 | { | ||
| 537 | pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id; | ||
| 538 | usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE], | ||
| 539 | USB_DIR_OUT); | ||
| 540 | } | ||
| 541 | |||
| 542 | /* | ||
| 543 | * Stop and erase effect with effect_id | ||
| 544 | */ | ||
| 545 | static int pidff_erase_effect(struct input_dev *dev, int effect_id) | ||
| 546 | { | ||
| 547 | struct pidff_device *pidff = dev->ff->private; | ||
| 548 | int pid_id = pidff->pid_id[effect_id]; | ||
| 549 | |||
| 550 | debug("starting to erase %d/%d", effect_id, pidff->pid_id[effect_id]); | ||
| 551 | pidff_playback_pid(pidff, pid_id, 0); | ||
| 552 | pidff_erase_pid(pidff, pid_id); | ||
| 553 | |||
| 554 | return 0; | ||
| 555 | } | ||
| 556 | |||
| 557 | /* | ||
| 558 | * Effect upload handler | ||
| 559 | */ | ||
| 560 | static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect, | ||
| 561 | struct ff_effect *old) | ||
| 562 | { | ||
| 563 | struct pidff_device *pidff = dev->ff->private; | ||
| 564 | int type_id; | ||
| 565 | int error; | ||
| 566 | |||
| 567 | switch (effect->type) { | ||
| 568 | case FF_CONSTANT: | ||
| 569 | if (!old) { | ||
| 570 | error = pidff_request_effect_upload(pidff, | ||
| 571 | pidff->type_id[PID_CONSTANT]); | ||
| 572 | if (error) | ||
| 573 | return error; | ||
| 574 | } | ||
| 575 | if (!old || pidff_needs_set_effect(effect, old)) | ||
| 576 | pidff_set_effect_report(pidff, effect); | ||
| 577 | if (!old || pidff_needs_set_constant(effect, old)) | ||
| 578 | pidff_set_constant_force_report(pidff, effect); | ||
| 579 | if (!old || | ||
| 580 | pidff_needs_set_envelope(&effect->u.constant.envelope, | ||
| 581 | &old->u.constant.envelope)) | ||
| 582 | pidff_set_envelope_report(pidff, | ||
| 583 | &effect->u.constant.envelope); | ||
| 584 | break; | ||
| 585 | |||
| 586 | case FF_PERIODIC: | ||
| 587 | if (!old) { | ||
| 588 | switch (effect->u.periodic.waveform) { | ||
| 589 | case FF_SQUARE: | ||
| 590 | type_id = PID_SQUARE; | ||
| 591 | break; | ||
| 592 | case FF_TRIANGLE: | ||
| 593 | type_id = PID_TRIANGLE; | ||
| 594 | break; | ||
| 595 | case FF_SINE: | ||
| 596 | type_id = PID_SINE; | ||
| 597 | break; | ||
| 598 | case FF_SAW_UP: | ||
| 599 | type_id = PID_SAW_UP; | ||
| 600 | break; | ||
| 601 | case FF_SAW_DOWN: | ||
| 602 | type_id = PID_SAW_DOWN; | ||
| 603 | break; | ||
| 604 | default: | ||
| 605 | printk(KERN_ERR | ||
| 606 | "hid-pidff: invalid waveform\n"); | ||
| 607 | return -EINVAL; | ||
| 608 | } | ||
| 609 | |||
| 610 | error = pidff_request_effect_upload(pidff, | ||
| 611 | pidff->type_id[type_id]); | ||
| 612 | if (error) | ||
| 613 | return error; | ||
| 614 | } | ||
| 615 | if (!old || pidff_needs_set_effect(effect, old)) | ||
| 616 | pidff_set_effect_report(pidff, effect); | ||
| 617 | if (!old || pidff_needs_set_periodic(effect, old)) | ||
| 618 | pidff_set_periodic_report(pidff, effect); | ||
| 619 | if (!old || | ||
| 620 | pidff_needs_set_envelope(&effect->u.periodic.envelope, | ||
| 621 | &old->u.periodic.envelope)) | ||
| 622 | pidff_set_envelope_report(pidff, | ||
| 623 | &effect->u.periodic.envelope); | ||
| 624 | break; | ||
| 625 | |||
| 626 | case FF_RAMP: | ||
| 627 | if (!old) { | ||
| 628 | error = pidff_request_effect_upload(pidff, | ||
| 629 | pidff->type_id[PID_RAMP]); | ||
| 630 | if (error) | ||
| 631 | return error; | ||
| 632 | } | ||
| 633 | if (!old || pidff_needs_set_effect(effect, old)) | ||
| 634 | pidff_set_effect_report(pidff, effect); | ||
| 635 | if (!old || pidff_needs_set_ramp(effect, old)) | ||
| 636 | pidff_set_ramp_force_report(pidff, effect); | ||
| 637 | if (!old || | ||
| 638 | pidff_needs_set_envelope(&effect->u.ramp.envelope, | ||
| 639 | &old->u.ramp.envelope)) | ||
| 640 | pidff_set_envelope_report(pidff, | ||
| 641 | &effect->u.ramp.envelope); | ||
| 642 | break; | ||
| 643 | |||
| 644 | case FF_SPRING: | ||
| 645 | if (!old) { | ||
| 646 | error = pidff_request_effect_upload(pidff, | ||
| 647 | pidff->type_id[PID_SPRING]); | ||
| 648 | if (error) | ||
| 649 | return error; | ||
| 650 | } | ||
| 651 | if (!old || pidff_needs_set_effect(effect, old)) | ||
| 652 | pidff_set_effect_report(pidff, effect); | ||
| 653 | if (!old || pidff_needs_set_condition(effect, old)) | ||
| 654 | pidff_set_condition_report(pidff, effect); | ||
| 655 | break; | ||
| 656 | |||
| 657 | case FF_FRICTION: | ||
| 658 | if (!old) { | ||
| 659 | error = pidff_request_effect_upload(pidff, | ||
| 660 | pidff->type_id[PID_FRICTION]); | ||
| 661 | if (error) | ||
| 662 | return error; | ||
| 663 | } | ||
| 664 | if (!old || pidff_needs_set_effect(effect, old)) | ||
| 665 | pidff_set_effect_report(pidff, effect); | ||
| 666 | if (!old || pidff_needs_set_condition(effect, old)) | ||
| 667 | pidff_set_condition_report(pidff, effect); | ||
| 668 | break; | ||
| 669 | |||
| 670 | case FF_DAMPER: | ||
| 671 | if (!old) { | ||
| 672 | error = pidff_request_effect_upload(pidff, | ||
| 673 | pidff->type_id[PID_DAMPER]); | ||
| 674 | if (error) | ||
| 675 | return error; | ||
| 676 | } | ||
| 677 | if (!old || pidff_needs_set_effect(effect, old)) | ||
| 678 | pidff_set_effect_report(pidff, effect); | ||
| 679 | if (!old || pidff_needs_set_condition(effect, old)) | ||
| 680 | pidff_set_condition_report(pidff, effect); | ||
| 681 | break; | ||
| 682 | |||
| 683 | case FF_INERTIA: | ||
| 684 | if (!old) { | ||
| 685 | error = pidff_request_effect_upload(pidff, | ||
| 686 | pidff->type_id[PID_INERTIA]); | ||
| 687 | if (error) | ||
| 688 | return error; | ||
| 689 | } | ||
| 690 | if (!old || pidff_needs_set_effect(effect, old)) | ||
| 691 | pidff_set_effect_report(pidff, effect); | ||
| 692 | if (!old || pidff_needs_set_condition(effect, old)) | ||
| 693 | pidff_set_condition_report(pidff, effect); | ||
| 694 | break; | ||
| 695 | |||
| 696 | default: | ||
| 697 | printk(KERN_ERR "hid-pidff: invalid type\n"); | ||
| 698 | return -EINVAL; | ||
| 699 | } | ||
| 700 | |||
| 701 | if (!old) | ||
| 702 | pidff->pid_id[effect->id] = | ||
| 703 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
| 704 | |||
| 705 | debug("uploaded"); | ||
| 706 | |||
| 707 | return 0; | ||
| 708 | } | ||
| 709 | |||
| 710 | /* | ||
| 711 | * set_gain() handler | ||
| 712 | */ | ||
| 713 | static void pidff_set_gain(struct input_dev *dev, u16 gain) | ||
| 714 | { | ||
| 715 | struct pidff_device *pidff = dev->ff->private; | ||
| 716 | |||
| 717 | pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain); | ||
| 718 | usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], | ||
| 719 | USB_DIR_OUT); | ||
| 720 | } | ||
| 721 | |||
| 722 | static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude) | ||
| 723 | { | ||
| 724 | struct hid_field *field = | ||
| 725 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field; | ||
| 726 | |||
| 727 | if (!magnitude) { | ||
| 728 | pidff_playback_pid(pidff, field->logical_minimum, 0); | ||
| 729 | return; | ||
| 730 | } | ||
| 731 | |||
| 732 | pidff_playback_pid(pidff, field->logical_minimum, 1); | ||
| 733 | |||
| 734 | pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
| 735 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum; | ||
| 736 | pidff->set_effect_type->value[0] = pidff->type_id[PID_SPRING]; | ||
| 737 | pidff->set_effect[PID_DURATION].value[0] = 0; | ||
| 738 | pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0; | ||
| 739 | pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0; | ||
| 740 | pidff_set(&pidff->set_effect[PID_GAIN], magnitude); | ||
| 741 | pidff->set_effect[PID_START_DELAY].value[0] = 0; | ||
| 742 | |||
| 743 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], | ||
| 744 | USB_DIR_OUT); | ||
| 745 | } | ||
| 746 | |||
| 747 | /* | ||
| 748 | * pidff_set_autocenter() handler | ||
| 749 | */ | ||
| 750 | static void pidff_set_autocenter(struct input_dev *dev, u16 magnitude) | ||
| 751 | { | ||
| 752 | struct pidff_device *pidff = dev->ff->private; | ||
| 753 | |||
| 754 | pidff_autocenter(pidff, magnitude); | ||
| 755 | } | ||
| 756 | |||
| 757 | /* | ||
| 758 | * Find fields from a report and fill a pidff_usage | ||
| 759 | */ | ||
| 760 | static int pidff_find_fields(struct pidff_usage *usage, const u8 *table, | ||
| 761 | struct hid_report *report, int count, int strict) | ||
| 762 | { | ||
| 763 | int i, j, k, found; | ||
| 764 | |||
| 765 | for (k = 0; k < count; k++) { | ||
| 766 | found = 0; | ||
| 767 | for (i = 0; i < report->maxfield; i++) { | ||
| 768 | if (report->field[i]->maxusage != | ||
| 769 | report->field[i]->report_count) { | ||
| 770 | debug("maxusage and report_count do not match, " | ||
| 771 | "skipping"); | ||
| 772 | continue; | ||
| 773 | } | ||
| 774 | for (j = 0; j < report->field[i]->maxusage; j++) { | ||
| 775 | if (report->field[i]->usage[j].hid == | ||
| 776 | (HID_UP_PID | table[k])) { | ||
| 777 | debug("found %d at %d->%d", k, i, j); | ||
| 778 | usage[k].field = report->field[i]; | ||
| 779 | usage[k].value = | ||
| 780 | &report->field[i]->value[j]; | ||
| 781 | found = 1; | ||
| 782 | break; | ||
| 783 | } | ||
| 784 | } | ||
| 785 | if (found) | ||
| 786 | break; | ||
| 787 | } | ||
| 788 | if (!found && strict) { | ||
| 789 | debug("failed to locate %d", k); | ||
| 790 | return -1; | ||
| 791 | } | ||
| 792 | } | ||
| 793 | return 0; | ||
| 794 | } | ||
| 795 | |||
| 796 | /* | ||
| 797 | * Return index into pidff_reports for the given usage | ||
| 798 | */ | ||
| 799 | static int pidff_check_usage(int usage) | ||
| 800 | { | ||
| 801 | int i; | ||
| 802 | |||
| 803 | for (i = 0; i < sizeof(pidff_reports); i++) | ||
| 804 | if (usage == (HID_UP_PID | pidff_reports[i])) | ||
| 805 | return i; | ||
| 806 | |||
| 807 | return -1; | ||
| 808 | } | ||
| 809 | |||
| 810 | /* | ||
| 811 | * Find the reports and fill pidff->reports[] | ||
| 812 | * report_type specifies either OUTPUT or FEATURE reports | ||
| 813 | */ | ||
| 814 | static void pidff_find_reports(struct hid_device *hid, int report_type, | ||
| 815 | struct pidff_device *pidff) | ||
| 816 | { | ||
| 817 | struct hid_report *report; | ||
| 818 | int i, ret; | ||
| 819 | |||
| 820 | list_for_each_entry(report, | ||
| 821 | &hid->report_enum[report_type].report_list, list) { | ||
| 822 | if (report->maxfield < 1) | ||
| 823 | continue; | ||
| 824 | ret = pidff_check_usage(report->field[0]->logical); | ||
| 825 | if (ret != -1) { | ||
| 826 | debug("found usage 0x%02x from field->logical", | ||
| 827 | pidff_reports[ret]); | ||
| 828 | pidff->reports[ret] = report; | ||
| 829 | continue; | ||
| 830 | } | ||
| 831 | |||
| 832 | /* | ||
| 833 | * Sometimes logical collections are stacked to indicate | ||
| 834 | * different usages for the report and the field, in which | ||
| 835 | * case we want the usage of the parent. However, Linux HID | ||
| 836 | * implementation hides this fact, so we have to dig it up | ||
| 837 | * ourselves | ||
| 838 | */ | ||
| 839 | i = report->field[0]->usage[0].collection_index; | ||
| 840 | if (i <= 0 || | ||
| 841 | hid->collection[i - 1].type != HID_COLLECTION_LOGICAL) | ||
| 842 | continue; | ||
| 843 | ret = pidff_check_usage(hid->collection[i - 1].usage); | ||
| 844 | if (ret != -1 && !pidff->reports[ret]) { | ||
| 845 | debug("found usage 0x%02x from collection array", | ||
| 846 | pidff_reports[ret]); | ||
| 847 | pidff->reports[ret] = report; | ||
| 848 | } | ||
| 849 | } | ||
| 850 | } | ||
| 851 | |||
| 852 | /* | ||
| 853 | * Test if the required reports have been found | ||
| 854 | */ | ||
| 855 | static int pidff_reports_ok(struct pidff_device *pidff) | ||
| 856 | { | ||
| 857 | int i; | ||
| 858 | |||
| 859 | for (i = 0; i <= PID_REQUIRED_REPORTS; i++) { | ||
| 860 | if (!pidff->reports[i]) { | ||
| 861 | debug("%d missing", i); | ||
| 862 | return 0; | ||
| 863 | } | ||
| 864 | } | ||
| 865 | |||
| 866 | return 1; | ||
| 867 | } | ||
| 868 | |||
| 869 | /* | ||
| 870 | * Find a field with a specific usage within a report | ||
| 871 | */ | ||
| 872 | static struct hid_field *pidff_find_special_field(struct hid_report *report, | ||
| 873 | int usage, int enforce_min) | ||
| 874 | { | ||
| 875 | int i; | ||
| 876 | |||
| 877 | for (i = 0; i < report->maxfield; i++) { | ||
| 878 | if (report->field[i]->logical == (HID_UP_PID | usage) && | ||
| 879 | report->field[i]->report_count > 0) { | ||
| 880 | if (!enforce_min || | ||
| 881 | report->field[i]->logical_minimum == 1) | ||
| 882 | return report->field[i]; | ||
| 883 | else { | ||
| 884 | printk(KERN_ERR "hid-pidff: logical_minimum " | ||
| 885 | "is not 1 as it should be\n"); | ||
| 886 | return NULL; | ||
| 887 | } | ||
| 888 | } | ||
| 889 | } | ||
| 890 | return NULL; | ||
| 891 | } | ||
| 892 | |||
| 893 | /* | ||
| 894 | * Fill a pidff->*_id struct table | ||
| 895 | */ | ||
| 896 | static int pidff_find_special_keys(int *keys, struct hid_field *fld, | ||
| 897 | const u8 *usagetable, int count) | ||
| 898 | { | ||
| 899 | |||
| 900 | int i, j; | ||
| 901 | int found = 0; | ||
| 902 | |||
| 903 | for (i = 0; i < count; i++) { | ||
| 904 | for (j = 0; j < fld->maxusage; j++) { | ||
| 905 | if (fld->usage[j].hid == (HID_UP_PID | usagetable[i])) { | ||
| 906 | keys[i] = j + 1; | ||
| 907 | found++; | ||
| 908 | break; | ||
| 909 | } | ||
| 910 | } | ||
| 911 | } | ||
| 912 | return found; | ||
| 913 | } | ||
| 914 | |||
| 915 | #define PIDFF_FIND_SPECIAL_KEYS(keys, field, name) \ | ||
| 916 | pidff_find_special_keys(pidff->keys, pidff->field, pidff_ ## name, \ | ||
| 917 | sizeof(pidff_ ## name)) | ||
| 918 | |||
| 919 | /* | ||
| 920 | * Find and check the special fields | ||
| 921 | */ | ||
| 922 | static int pidff_find_special_fields(struct pidff_device *pidff) | ||
| 923 | { | ||
| 924 | debug("finding special fields"); | ||
| 925 | |||
| 926 | pidff->create_new_effect_type = | ||
| 927 | pidff_find_special_field(pidff->reports[PID_CREATE_NEW_EFFECT], | ||
| 928 | 0x25, 1); | ||
| 929 | pidff->set_effect_type = | ||
| 930 | pidff_find_special_field(pidff->reports[PID_SET_EFFECT], | ||
| 931 | 0x25, 1); | ||
| 932 | pidff->effect_direction = | ||
| 933 | pidff_find_special_field(pidff->reports[PID_SET_EFFECT], | ||
| 934 | 0x57, 0); | ||
| 935 | pidff->device_control = | ||
| 936 | pidff_find_special_field(pidff->reports[PID_DEVICE_CONTROL], | ||
| 937 | 0x96, 1); | ||
| 938 | pidff->block_load_status = | ||
| 939 | pidff_find_special_field(pidff->reports[PID_BLOCK_LOAD], | ||
| 940 | 0x8b, 1); | ||
| 941 | pidff->effect_operation_status = | ||
| 942 | pidff_find_special_field(pidff->reports[PID_EFFECT_OPERATION], | ||
| 943 | 0x78, 1); | ||
| 944 | |||
| 945 | debug("search done"); | ||
| 946 | |||
| 947 | if (!pidff->create_new_effect_type || !pidff->set_effect_type) { | ||
| 948 | printk(KERN_ERR "hid-pidff: effect lists not found\n"); | ||
| 949 | return -1; | ||
| 950 | } | ||
| 951 | |||
| 952 | if (!pidff->effect_direction) { | ||
| 953 | printk(KERN_ERR "hid-pidff: direction field not found\n"); | ||
| 954 | return -1; | ||
| 955 | } | ||
| 956 | |||
| 957 | if (!pidff->device_control) { | ||
| 958 | printk(KERN_ERR "hid-pidff: device control field not found\n"); | ||
| 959 | return -1; | ||
| 960 | } | ||
| 961 | |||
| 962 | if (!pidff->block_load_status) { | ||
| 963 | printk(KERN_ERR | ||
| 964 | "hid-pidff: block load status field not found\n"); | ||
| 965 | return -1; | ||
| 966 | } | ||
| 967 | |||
| 968 | if (!pidff->effect_operation_status) { | ||
| 969 | printk(KERN_ERR | ||
| 970 | "hid-pidff: effect operation field not found\n"); | ||
| 971 | return -1; | ||
| 972 | } | ||
| 973 | |||
| 974 | pidff_find_special_keys(pidff->control_id, pidff->device_control, | ||
| 975 | pidff_device_control, | ||
| 976 | sizeof(pidff_device_control)); | ||
| 977 | |||
| 978 | PIDFF_FIND_SPECIAL_KEYS(control_id, device_control, device_control); | ||
| 979 | |||
| 980 | if (!PIDFF_FIND_SPECIAL_KEYS(type_id, create_new_effect_type, | ||
| 981 | effect_types)) { | ||
| 982 | printk(KERN_ERR "hid-pidff: no effect types found\n"); | ||
| 983 | return -1; | ||
| 984 | } | ||
| 985 | |||
| 986 | if (PIDFF_FIND_SPECIAL_KEYS(status_id, block_load_status, | ||
| 987 | block_load_status) != | ||
| 988 | sizeof(pidff_block_load_status)) { | ||
| 989 | printk(KERN_ERR | ||
| 990 | "hidpidff: block load status identifiers not found\n"); | ||
| 991 | return -1; | ||
| 992 | } | ||
| 993 | |||
| 994 | if (PIDFF_FIND_SPECIAL_KEYS(operation_id, effect_operation_status, | ||
| 995 | effect_operation_status) != | ||
| 996 | sizeof(pidff_effect_operation_status)) { | ||
| 997 | printk(KERN_ERR | ||
| 998 | "hidpidff: effect operation identifiers not found\n"); | ||
| 999 | return -1; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | return 0; | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | /** | ||
| 1006 | * Find the implemented effect types | ||
| 1007 | */ | ||
| 1008 | static int pidff_find_effects(struct pidff_device *pidff, | ||
| 1009 | struct input_dev *dev) | ||
| 1010 | { | ||
| 1011 | int i; | ||
| 1012 | |||
| 1013 | for (i = 0; i < sizeof(pidff_effect_types); i++) { | ||
| 1014 | int pidff_type = pidff->type_id[i]; | ||
| 1015 | if (pidff->set_effect_type->usage[pidff_type].hid != | ||
| 1016 | pidff->create_new_effect_type->usage[pidff_type].hid) { | ||
| 1017 | printk(KERN_ERR "hid-pidff: " | ||
| 1018 | "effect type number %d is invalid\n", i); | ||
| 1019 | return -1; | ||
| 1020 | } | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | if (pidff->type_id[PID_CONSTANT]) | ||
| 1024 | set_bit(FF_CONSTANT, dev->ffbit); | ||
| 1025 | if (pidff->type_id[PID_RAMP]) | ||
| 1026 | set_bit(FF_RAMP, dev->ffbit); | ||
| 1027 | if (pidff->type_id[PID_SQUARE]) { | ||
| 1028 | set_bit(FF_SQUARE, dev->ffbit); | ||
| 1029 | set_bit(FF_PERIODIC, dev->ffbit); | ||
| 1030 | } | ||
| 1031 | if (pidff->type_id[PID_SINE]) { | ||
| 1032 | set_bit(FF_SINE, dev->ffbit); | ||
| 1033 | set_bit(FF_PERIODIC, dev->ffbit); | ||
| 1034 | } | ||
| 1035 | if (pidff->type_id[PID_TRIANGLE]) { | ||
| 1036 | set_bit(FF_TRIANGLE, dev->ffbit); | ||
| 1037 | set_bit(FF_PERIODIC, dev->ffbit); | ||
| 1038 | } | ||
| 1039 | if (pidff->type_id[PID_SAW_UP]) { | ||
| 1040 | set_bit(FF_SAW_UP, dev->ffbit); | ||
| 1041 | set_bit(FF_PERIODIC, dev->ffbit); | ||
| 1042 | } | ||
| 1043 | if (pidff->type_id[PID_SAW_DOWN]) { | ||
| 1044 | set_bit(FF_SAW_DOWN, dev->ffbit); | ||
| 1045 | set_bit(FF_PERIODIC, dev->ffbit); | ||
| 1046 | } | ||
| 1047 | if (pidff->type_id[PID_SPRING]) | ||
| 1048 | set_bit(FF_SPRING, dev->ffbit); | ||
| 1049 | if (pidff->type_id[PID_DAMPER]) | ||
| 1050 | set_bit(FF_DAMPER, dev->ffbit); | ||
| 1051 | if (pidff->type_id[PID_INERTIA]) | ||
| 1052 | set_bit(FF_INERTIA, dev->ffbit); | ||
| 1053 | if (pidff->type_id[PID_FRICTION]) | ||
| 1054 | set_bit(FF_FRICTION, dev->ffbit); | ||
| 1055 | |||
| 1056 | return 0; | ||
| 1057 | |||
| 1058 | } | ||
| 1059 | |||
| 1060 | #define PIDFF_FIND_FIELDS(name, report, strict) \ | ||
| 1061 | pidff_find_fields(pidff->name, pidff_ ## name, \ | ||
| 1062 | pidff->reports[report], \ | ||
| 1063 | sizeof(pidff_ ## name), strict) | ||
| 1064 | |||
| 1065 | /* | ||
| 1066 | * Fill and check the pidff_usages | ||
| 1067 | */ | ||
| 1068 | static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) | ||
| 1069 | { | ||
| 1070 | int envelope_ok = 0; | ||
| 1071 | |||
| 1072 | if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) { | ||
| 1073 | printk(KERN_ERR | ||
| 1074 | "hid-pidff: unknown set_effect report layout\n"); | ||
| 1075 | return -ENODEV; | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0); | ||
| 1079 | if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) { | ||
| 1080 | printk(KERN_ERR | ||
| 1081 | "hid-pidff: unknown pid_block_load report layout\n"); | ||
| 1082 | return -ENODEV; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | if (PIDFF_FIND_FIELDS(effect_operation, PID_EFFECT_OPERATION, 1)) { | ||
| 1086 | printk(KERN_ERR | ||
| 1087 | "hid-pidff: unknown effect_operation report layout\n"); | ||
| 1088 | return -ENODEV; | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | if (PIDFF_FIND_FIELDS(block_free, PID_BLOCK_FREE, 1)) { | ||
| 1092 | printk(KERN_ERR | ||
| 1093 | "hid-pidff: unknown pid_block_free report layout\n"); | ||
| 1094 | return -ENODEV; | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | if (!PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1)) | ||
| 1098 | envelope_ok = 1; | ||
| 1099 | |||
| 1100 | if (pidff_find_special_fields(pidff) || pidff_find_effects(pidff, dev)) | ||
| 1101 | return -ENODEV; | ||
| 1102 | |||
| 1103 | if (!envelope_ok) { | ||
| 1104 | if (test_and_clear_bit(FF_CONSTANT, dev->ffbit)) | ||
| 1105 | printk(KERN_WARNING "hid-pidff: " | ||
| 1106 | "has constant effect but no envelope\n"); | ||
| 1107 | if (test_and_clear_bit(FF_RAMP, dev->ffbit)) | ||
| 1108 | printk(KERN_WARNING "hid-pidff: " | ||
| 1109 | "has ramp effect but no envelope\n"); | ||
| 1110 | |||
| 1111 | if (test_and_clear_bit(FF_PERIODIC, dev->ffbit)) | ||
| 1112 | printk(KERN_WARNING "hid-pidff: " | ||
| 1113 | "has periodic effect but no envelope\n"); | ||
| 1114 | } | ||
| 1115 | |||
| 1116 | if (test_bit(FF_CONSTANT, dev->ffbit) && | ||
| 1117 | PIDFF_FIND_FIELDS(set_constant, PID_SET_CONSTANT, 1)) { | ||
| 1118 | printk(KERN_WARNING | ||
| 1119 | "hid-pidff: unknown constant effect layout\n"); | ||
| 1120 | clear_bit(FF_CONSTANT, dev->ffbit); | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | if (test_bit(FF_RAMP, dev->ffbit) && | ||
| 1124 | PIDFF_FIND_FIELDS(set_ramp, PID_SET_RAMP, 1)) { | ||
| 1125 | printk(KERN_WARNING "hid-pidff: unknown ramp effect layout\n"); | ||
| 1126 | clear_bit(FF_RAMP, dev->ffbit); | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | if ((test_bit(FF_SPRING, dev->ffbit) || | ||
| 1130 | test_bit(FF_DAMPER, dev->ffbit) || | ||
| 1131 | test_bit(FF_FRICTION, dev->ffbit) || | ||
| 1132 | test_bit(FF_INERTIA, dev->ffbit)) && | ||
| 1133 | PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) { | ||
| 1134 | printk(KERN_WARNING | ||
| 1135 | "hid-pidff: unknown condition effect layout\n"); | ||
| 1136 | clear_bit(FF_SPRING, dev->ffbit); | ||
| 1137 | clear_bit(FF_DAMPER, dev->ffbit); | ||
| 1138 | clear_bit(FF_FRICTION, dev->ffbit); | ||
| 1139 | clear_bit(FF_INERTIA, dev->ffbit); | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | if (test_bit(FF_PERIODIC, dev->ffbit) && | ||
| 1143 | PIDFF_FIND_FIELDS(set_periodic, PID_SET_PERIODIC, 1)) { | ||
| 1144 | printk(KERN_WARNING | ||
| 1145 | "hid-pidff: unknown periodic effect layout\n"); | ||
| 1146 | clear_bit(FF_PERIODIC, dev->ffbit); | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | PIDFF_FIND_FIELDS(pool, PID_POOL, 0); | ||
| 1150 | |||
| 1151 | if (!PIDFF_FIND_FIELDS(device_gain, PID_DEVICE_GAIN, 1)) | ||
| 1152 | set_bit(FF_GAIN, dev->ffbit); | ||
| 1153 | |||
| 1154 | return 0; | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | /* | ||
| 1158 | * Reset the device | ||
| 1159 | */ | ||
| 1160 | static void pidff_reset(struct pidff_device *pidff) | ||
| 1161 | { | ||
| 1162 | struct hid_device *hid = pidff->hid; | ||
| 1163 | int i = 0; | ||
| 1164 | |||
| 1165 | pidff->device_control->value[0] = pidff->control_id[PID_RESET]; | ||
| 1166 | /* We reset twice as sometimes hid_wait_io isn't waiting long enough */ | ||
| 1167 | usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); | ||
| 1168 | usbhid_wait_io(hid); | ||
| 1169 | usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); | ||
| 1170 | usbhid_wait_io(hid); | ||
| 1171 | |||
| 1172 | pidff->device_control->value[0] = | ||
| 1173 | pidff->control_id[PID_ENABLE_ACTUATORS]; | ||
| 1174 | usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); | ||
| 1175 | usbhid_wait_io(hid); | ||
| 1176 | |||
| 1177 | /* pool report is sometimes messed up, refetch it */ | ||
| 1178 | usbhid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN); | ||
| 1179 | usbhid_wait_io(hid); | ||
| 1180 | |||
| 1181 | if (pidff->pool[PID_SIMULTANEOUS_MAX].value) { | ||
| 1182 | int sim_effects = pidff->pool[PID_SIMULTANEOUS_MAX].value[0]; | ||
| 1183 | while (sim_effects < 2) { | ||
| 1184 | if (i++ > 20) { | ||
| 1185 | printk(KERN_WARNING "hid-pidff: device reports " | ||
| 1186 | "%d simultaneous effects\n", | ||
| 1187 | sim_effects); | ||
| 1188 | break; | ||
| 1189 | } | ||
| 1190 | debug("pid_pool requested again"); | ||
| 1191 | usbhid_submit_report(hid, pidff->reports[PID_POOL], | ||
| 1192 | USB_DIR_IN); | ||
| 1193 | usbhid_wait_io(hid); | ||
| 1194 | } | ||
| 1195 | } | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | /* | ||
| 1199 | * Test if autocenter modification is using the supported method | ||
| 1200 | */ | ||
| 1201 | static int pidff_check_autocenter(struct pidff_device *pidff, | ||
| 1202 | struct input_dev *dev) | ||
| 1203 | { | ||
| 1204 | int error; | ||
| 1205 | |||
| 1206 | /* | ||
| 1207 | * Let's find out if autocenter modification is supported | ||
| 1208 | * Specification doesn't specify anything, so we request an | ||
| 1209 | * effect upload and cancel it immediately. If the approved | ||
| 1210 | * effect id was one above the minimum, then we assume the first | ||
| 1211 | * effect id is a built-in spring type effect used for autocenter | ||
| 1212 | */ | ||
| 1213 | |||
| 1214 | error = pidff_request_effect_upload(pidff, 1); | ||
| 1215 | if (error) { | ||
| 1216 | printk(KERN_ERR "hid-pidff: upload request failed\n"); | ||
| 1217 | return error; | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | if (pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] == | ||
| 1221 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + 1) { | ||
| 1222 | pidff_autocenter(pidff, 0xffff); | ||
| 1223 | set_bit(FF_AUTOCENTER, dev->ffbit); | ||
| 1224 | } else { | ||
| 1225 | printk(KERN_NOTICE "hid-pidff: " | ||
| 1226 | "device has unknown autocenter control method\n"); | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | pidff_erase_pid(pidff, | ||
| 1230 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]); | ||
| 1231 | |||
| 1232 | return 0; | ||
| 1233 | |||
| 1234 | } | ||
| 1235 | |||
| 1236 | /* | ||
| 1237 | * Check if the device is PID and initialize it | ||
| 1238 | */ | ||
| 1239 | int hid_pidff_init(struct hid_device *hid) | ||
| 1240 | { | ||
| 1241 | struct pidff_device *pidff; | ||
| 1242 | struct hid_input *hidinput = list_entry(hid->inputs.next, | ||
| 1243 | struct hid_input, list); | ||
| 1244 | struct input_dev *dev = hidinput->input; | ||
| 1245 | struct ff_device *ff; | ||
| 1246 | int max_effects; | ||
| 1247 | int error; | ||
| 1248 | |||
| 1249 | debug("starting pid init"); | ||
| 1250 | |||
| 1251 | if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) { | ||
| 1252 | debug("not a PID device, no output report"); | ||
| 1253 | return -ENODEV; | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | pidff = kzalloc(sizeof(*pidff), GFP_KERNEL); | ||
| 1257 | if (!pidff) | ||
| 1258 | return -ENOMEM; | ||
| 1259 | |||
| 1260 | pidff->hid = hid; | ||
| 1261 | |||
| 1262 | pidff_find_reports(hid, HID_OUTPUT_REPORT, pidff); | ||
| 1263 | pidff_find_reports(hid, HID_FEATURE_REPORT, pidff); | ||
| 1264 | |||
| 1265 | if (!pidff_reports_ok(pidff)) { | ||
| 1266 | debug("reports not ok, aborting"); | ||
| 1267 | error = -ENODEV; | ||
| 1268 | goto fail; | ||
| 1269 | } | ||
| 1270 | |||
| 1271 | error = pidff_init_fields(pidff, dev); | ||
| 1272 | if (error) | ||
| 1273 | goto fail; | ||
| 1274 | |||
| 1275 | pidff_reset(pidff); | ||
| 1276 | |||
| 1277 | if (test_bit(FF_GAIN, dev->ffbit)) { | ||
| 1278 | pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff); | ||
| 1279 | usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], | ||
| 1280 | USB_DIR_OUT); | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | error = pidff_check_autocenter(pidff, dev); | ||
| 1284 | if (error) | ||
| 1285 | goto fail; | ||
| 1286 | |||
| 1287 | max_effects = | ||
| 1288 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_maximum - | ||
| 1289 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + | ||
| 1290 | 1; | ||
| 1291 | debug("max effects is %d", max_effects); | ||
| 1292 | |||
| 1293 | if (max_effects > PID_EFFECTS_MAX) | ||
| 1294 | max_effects = PID_EFFECTS_MAX; | ||
| 1295 | |||
| 1296 | if (pidff->pool[PID_SIMULTANEOUS_MAX].value) | ||
| 1297 | debug("max simultaneous effects is %d", | ||
| 1298 | pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); | ||
| 1299 | |||
| 1300 | if (pidff->pool[PID_RAM_POOL_SIZE].value) | ||
| 1301 | debug("device memory size is %d bytes", | ||
| 1302 | pidff->pool[PID_RAM_POOL_SIZE].value[0]); | ||
| 1303 | |||
| 1304 | if (pidff->pool[PID_DEVICE_MANAGED_POOL].value && | ||
| 1305 | pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) { | ||
| 1306 | printk(KERN_NOTICE "hid-pidff: " | ||
| 1307 | "device does not support device managed pool\n"); | ||
| 1308 | goto fail; | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | error = input_ff_create(dev, max_effects); | ||
| 1312 | if (error) | ||
| 1313 | goto fail; | ||
| 1314 | |||
| 1315 | ff = dev->ff; | ||
| 1316 | ff->private = pidff; | ||
| 1317 | ff->upload = pidff_upload_effect; | ||
| 1318 | ff->erase = pidff_erase_effect; | ||
| 1319 | ff->set_gain = pidff_set_gain; | ||
| 1320 | ff->set_autocenter = pidff_set_autocenter; | ||
| 1321 | ff->playback = pidff_playback; | ||
| 1322 | |||
| 1323 | printk(KERN_INFO "Force feedback for USB HID PID devices by " | ||
| 1324 | "Anssi Hannula <anssi.hannula@gmail.com>\n"); | ||
| 1325 | |||
| 1326 | return 0; | ||
| 1327 | |||
| 1328 | fail: | ||
| 1329 | kfree(pidff); | ||
| 1330 | return error; | ||
| 1331 | } | ||
diff --git a/drivers/usb/input/hid-plff.c b/drivers/usb/input/hid-plff.c deleted file mode 100644 index 76d2e6e14db4..000000000000 --- a/drivers/usb/input/hid-plff.c +++ /dev/null | |||
| @@ -1,129 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Force feedback support for PantherLord USB/PS2 2in1 Adapter devices | ||
| 3 | * | ||
| 4 | * Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.com> | ||
| 5 | */ | ||
| 6 | |||
| 7 | /* | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 21 | */ | ||
| 22 | |||
| 23 | |||
| 24 | /* #define DEBUG */ | ||
| 25 | |||
| 26 | #define debug(format, arg...) pr_debug("hid-plff: " format "\n" , ## arg) | ||
| 27 | |||
| 28 | #include <linux/input.h> | ||
| 29 | #include <linux/usb.h> | ||
| 30 | #include <linux/hid.h> | ||
| 31 | #include "usbhid.h" | ||
| 32 | |||
| 33 | struct plff_device { | ||
| 34 | struct hid_report *report; | ||
| 35 | }; | ||
| 36 | |||
| 37 | static int hid_plff_play(struct input_dev *dev, void *data, | ||
| 38 | struct ff_effect *effect) | ||
| 39 | { | ||
| 40 | struct hid_device *hid = dev->private; | ||
| 41 | struct plff_device *plff = data; | ||
| 42 | int left, right; | ||
| 43 | |||
| 44 | left = effect->u.rumble.strong_magnitude; | ||
| 45 | right = effect->u.rumble.weak_magnitude; | ||
| 46 | debug("called with 0x%04x 0x%04x", left, right); | ||
| 47 | |||
| 48 | left = left * 0x7f / 0xffff; | ||
| 49 | right = right * 0x7f / 0xffff; | ||
| 50 | |||
| 51 | plff->report->field[0]->value[2] = left; | ||
| 52 | plff->report->field[0]->value[3] = right; | ||
| 53 | debug("running with 0x%02x 0x%02x", left, right); | ||
| 54 | usbhid_submit_report(hid, plff->report, USB_DIR_OUT); | ||
| 55 | |||
| 56 | return 0; | ||
| 57 | } | ||
| 58 | |||
| 59 | int hid_plff_init(struct hid_device *hid) | ||
| 60 | { | ||
| 61 | struct plff_device *plff; | ||
| 62 | struct hid_report *report; | ||
| 63 | struct hid_input *hidinput; | ||
| 64 | struct list_head *report_list = | ||
| 65 | &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
| 66 | struct list_head *report_ptr = report_list; | ||
| 67 | struct input_dev *dev; | ||
| 68 | int error; | ||
| 69 | |||
| 70 | /* The device contains 2 output reports (one for each | ||
| 71 | HID_QUIRK_MULTI_INPUT device), both containing 1 field, which | ||
| 72 | contains 4 ff00.0002 usages and 4 16bit absolute values. | ||
| 73 | |||
| 74 | The 2 input reports also contain a field which contains | ||
| 75 | 8 ff00.0001 usages and 8 boolean values. Their meaning is | ||
| 76 | currently unknown. */ | ||
| 77 | |||
| 78 | if (list_empty(report_list)) { | ||
| 79 | printk(KERN_ERR "hid-plff: no output reports found\n"); | ||
| 80 | return -ENODEV; | ||
| 81 | } | ||
| 82 | |||
| 83 | list_for_each_entry(hidinput, &hid->inputs, list) { | ||
| 84 | |||
| 85 | report_ptr = report_ptr->next; | ||
| 86 | |||
| 87 | if (report_ptr == report_list) { | ||
| 88 | printk(KERN_ERR "hid-plff: required output report is missing\n"); | ||
| 89 | return -ENODEV; | ||
| 90 | } | ||
| 91 | |||
| 92 | report = list_entry(report_ptr, struct hid_report, list); | ||
| 93 | if (report->maxfield < 1) { | ||
| 94 | printk(KERN_ERR "hid-plff: no fields in the report\n"); | ||
| 95 | return -ENODEV; | ||
| 96 | } | ||
| 97 | |||
| 98 | if (report->field[0]->report_count < 4) { | ||
| 99 | printk(KERN_ERR "hid-plff: not enough values in the field\n"); | ||
| 100 | return -ENODEV; | ||
| 101 | } | ||
| 102 | |||
| 103 | plff = kzalloc(sizeof(struct plff_device), GFP_KERNEL); | ||
| 104 | if (!plff) | ||
| 105 | return -ENOMEM; | ||
| 106 | |||
| 107 | dev = hidinput->input; | ||
| 108 | |||
| 109 | set_bit(FF_RUMBLE, dev->ffbit); | ||
| 110 | |||
| 111 | error = input_ff_create_memless(dev, plff, hid_plff_play); | ||
| 112 | if (error) { | ||
| 113 | kfree(plff); | ||
| 114 | return error; | ||
| 115 | } | ||
| 116 | |||
| 117 | plff->report = report; | ||
| 118 | plff->report->field[0]->value[0] = 0x00; | ||
| 119 | plff->report->field[0]->value[1] = 0x00; | ||
| 120 | plff->report->field[0]->value[2] = 0x00; | ||
| 121 | plff->report->field[0]->value[3] = 0x00; | ||
| 122 | usbhid_submit_report(hid, plff->report, USB_DIR_OUT); | ||
| 123 | } | ||
| 124 | |||
| 125 | printk(KERN_INFO "hid-plff: Force feedback for PantherLord USB/PS2 " | ||
| 126 | "2in1 Adapters by Anssi Hannula <anssi.hannula@gmail.com>\n"); | ||
| 127 | |||
| 128 | return 0; | ||
| 129 | } | ||
diff --git a/drivers/usb/input/hid-tmff.c b/drivers/usb/input/hid-tmff.c deleted file mode 100644 index ab67331620d0..000000000000 --- a/drivers/usb/input/hid-tmff.c +++ /dev/null | |||
| @@ -1,147 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Force feedback support for various HID compliant devices by ThrustMaster: | ||
| 3 | * ThrustMaster FireStorm Dual Power 2 | ||
| 4 | * and possibly others whose device ids haven't been added. | ||
| 5 | * | ||
| 6 | * Modified to support ThrustMaster devices by Zinx Verituse | ||
| 7 | * on 2003-01-25 from the Logitech force feedback driver, | ||
| 8 | * which is by Johann Deneux. | ||
| 9 | * | ||
| 10 | * Copyright (c) 2003 Zinx Verituse <zinx@epicsol.org> | ||
| 11 | * Copyright (c) 2002 Johann Deneux | ||
| 12 | */ | ||
| 13 | |||
| 14 | /* | ||
| 15 | * This program is free software; you can redistribute it and/or modify | ||
| 16 | * it under the terms of the GNU General Public License as published by | ||
| 17 | * the Free Software Foundation; either version 2 of the License, or | ||
| 18 | * (at your option) any later version. | ||
| 19 | * | ||
| 20 | * This program is distributed in the hope that it will be useful, | ||
| 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 23 | * GNU General Public License for more details. | ||
| 24 | * | ||
| 25 | * You should have received a copy of the GNU General Public License | ||
| 26 | * along with this program; if not, write to the Free Software | ||
| 27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 28 | */ | ||
| 29 | |||
| 30 | #include <linux/input.h> | ||
| 31 | |||
| 32 | #undef DEBUG | ||
| 33 | #include <linux/usb.h> | ||
| 34 | |||
| 35 | #include <linux/hid.h> | ||
| 36 | #include "usbhid.h" | ||
| 37 | |||
| 38 | /* Usages for thrustmaster devices I know about */ | ||
| 39 | #define THRUSTMASTER_USAGE_RUMBLE_LR (HID_UP_GENDESK | 0xbb) | ||
| 40 | |||
| 41 | |||
| 42 | struct tmff_device { | ||
| 43 | struct hid_report *report; | ||
| 44 | struct hid_field *rumble; | ||
| 45 | }; | ||
| 46 | |||
| 47 | /* Changes values from 0 to 0xffff into values from minimum to maximum */ | ||
| 48 | static inline int hid_tmff_scale(unsigned int in, int minimum, int maximum) | ||
| 49 | { | ||
| 50 | int ret; | ||
| 51 | |||
| 52 | ret = (in * (maximum - minimum) / 0xffff) + minimum; | ||
| 53 | if (ret < minimum) | ||
| 54 | return minimum; | ||
| 55 | if (ret > maximum) | ||
| 56 | return maximum; | ||
| 57 | return ret; | ||
| 58 | } | ||
| 59 | |||
| 60 | static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *effect) | ||
| 61 | { | ||
| 62 | struct hid_device *hid = dev->private; | ||
| 63 | struct tmff_device *tmff = data; | ||
| 64 | int left, right; /* Rumbling */ | ||
| 65 | |||
| 66 | left = hid_tmff_scale(effect->u.rumble.weak_magnitude, | ||
| 67 | tmff->rumble->logical_minimum, tmff->rumble->logical_maximum); | ||
| 68 | right = hid_tmff_scale(effect->u.rumble.strong_magnitude, | ||
| 69 | tmff->rumble->logical_minimum, tmff->rumble->logical_maximum); | ||
| 70 | |||
| 71 | tmff->rumble->value[0] = left; | ||
| 72 | tmff->rumble->value[1] = right; | ||
| 73 | dbg("(left,right)=(%08x, %08x)", left, right); | ||
| 74 | usbhid_submit_report(hid, tmff->report, USB_DIR_OUT); | ||
| 75 | |||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 79 | int hid_tmff_init(struct hid_device *hid) | ||
| 80 | { | ||
| 81 | struct tmff_device *tmff; | ||
| 82 | struct list_head *pos; | ||
| 83 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); | ||
| 84 | struct input_dev *input_dev = hidinput->input; | ||
| 85 | int error; | ||
| 86 | |||
| 87 | tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL); | ||
| 88 | if (!tmff) | ||
| 89 | return -ENOMEM; | ||
| 90 | |||
| 91 | /* Find the report to use */ | ||
| 92 | __list_for_each(pos, &hid->report_enum[HID_OUTPUT_REPORT].report_list) { | ||
| 93 | struct hid_report *report = (struct hid_report *)pos; | ||
| 94 | int fieldnum; | ||
| 95 | |||
| 96 | for (fieldnum = 0; fieldnum < report->maxfield; ++fieldnum) { | ||
| 97 | struct hid_field *field = report->field[fieldnum]; | ||
| 98 | |||
| 99 | if (field->maxusage <= 0) | ||
| 100 | continue; | ||
| 101 | |||
| 102 | switch (field->usage[0].hid) { | ||
| 103 | case THRUSTMASTER_USAGE_RUMBLE_LR: | ||
| 104 | if (field->report_count < 2) { | ||
| 105 | warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR with report_count < 2"); | ||
| 106 | continue; | ||
| 107 | } | ||
| 108 | |||
| 109 | if (field->logical_maximum == field->logical_minimum) { | ||
| 110 | warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR with logical_maximum == logical_minimum"); | ||
| 111 | continue; | ||
| 112 | } | ||
| 113 | |||
| 114 | if (tmff->report && tmff->report != report) { | ||
| 115 | warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR in other report"); | ||
| 116 | continue; | ||
| 117 | } | ||
| 118 | |||
| 119 | if (tmff->rumble && tmff->rumble != field) { | ||
| 120 | warn("ignoring duplicate THRUSTMASTER_USAGE_RUMBLE_LR"); | ||
| 121 | continue; | ||
| 122 | } | ||
| 123 | |||
| 124 | tmff->report = report; | ||
| 125 | tmff->rumble = field; | ||
| 126 | |||
| 127 | set_bit(FF_RUMBLE, input_dev->ffbit); | ||
| 128 | break; | ||
| 129 | |||
| 130 | default: | ||
| 131 | warn("ignoring unknown output usage %08x", field->usage[0].hid); | ||
| 132 | continue; | ||
| 133 | } | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | error = input_ff_create_memless(input_dev, tmff, hid_tmff_play); | ||
| 138 | if (error) { | ||
| 139 | kfree(tmff); | ||
| 140 | return error; | ||
| 141 | } | ||
| 142 | |||
| 143 | info("Force feedback for ThrustMaster rumble pad devices by Zinx Verituse <zinx@epicsol.org>"); | ||
| 144 | |||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
diff --git a/drivers/usb/input/hid-zpff.c b/drivers/usb/input/hid-zpff.c deleted file mode 100644 index 7bd8238ca212..000000000000 --- a/drivers/usb/input/hid-zpff.c +++ /dev/null | |||
| @@ -1,111 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Force feedback support for Zeroplus based devices | ||
| 3 | * | ||
| 4 | * Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.com> | ||
| 5 | */ | ||
| 6 | |||
| 7 | /* | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 21 | */ | ||
| 22 | |||
| 23 | |||
| 24 | /* #define DEBUG */ | ||
| 25 | |||
| 26 | #define debug(format, arg...) pr_debug("hid-zpff: " format "\n" , ## arg) | ||
| 27 | |||
| 28 | #include <linux/input.h> | ||
| 29 | #include <linux/usb.h> | ||
| 30 | #include <linux/hid.h> | ||
| 31 | #include "usbhid.h" | ||
| 32 | |||
| 33 | struct zpff_device { | ||
| 34 | struct hid_report *report; | ||
| 35 | }; | ||
| 36 | |||
| 37 | static int hid_zpff_play(struct input_dev *dev, void *data, | ||
| 38 | struct ff_effect *effect) | ||
| 39 | { | ||
| 40 | struct hid_device *hid = dev->private; | ||
| 41 | struct zpff_device *zpff = data; | ||
| 42 | int left, right; | ||
| 43 | |||
| 44 | /* | ||
| 45 | * The following is specified the other way around in the Zeroplus | ||
| 46 | * datasheet but the order below is correct for the XFX Executioner; | ||
| 47 | * however it is possible that the XFX Executioner is an exception | ||
| 48 | */ | ||
| 49 | |||
| 50 | left = effect->u.rumble.strong_magnitude; | ||
| 51 | right = effect->u.rumble.weak_magnitude; | ||
| 52 | debug("called with 0x%04x 0x%04x", left, right); | ||
| 53 | |||
| 54 | left = left * 0x7f / 0xffff; | ||
| 55 | right = right * 0x7f / 0xffff; | ||
| 56 | |||
| 57 | zpff->report->field[2]->value[0] = left; | ||
| 58 | zpff->report->field[3]->value[0] = right; | ||
| 59 | debug("running with 0x%02x 0x%02x", left, right); | ||
| 60 | usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); | ||
| 61 | |||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | |||
| 65 | int hid_zpff_init(struct hid_device *hid) | ||
| 66 | { | ||
| 67 | struct zpff_device *zpff; | ||
| 68 | struct hid_report *report; | ||
| 69 | struct hid_input *hidinput = list_entry(hid->inputs.next, | ||
| 70 | struct hid_input, list); | ||
| 71 | struct list_head *report_list = | ||
| 72 | &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
| 73 | struct input_dev *dev = hidinput->input; | ||
| 74 | int error; | ||
| 75 | |||
| 76 | if (list_empty(report_list)) { | ||
| 77 | printk(KERN_ERR "hid-zpff: no output report found\n"); | ||
| 78 | return -ENODEV; | ||
| 79 | } | ||
| 80 | |||
| 81 | report = list_entry(report_list->next, struct hid_report, list); | ||
| 82 | |||
| 83 | if (report->maxfield < 4) { | ||
| 84 | printk(KERN_ERR "hid-zpff: not enough fields in report\n"); | ||
| 85 | return -ENODEV; | ||
| 86 | } | ||
| 87 | |||
| 88 | zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL); | ||
| 89 | if (!zpff) | ||
| 90 | return -ENOMEM; | ||
| 91 | |||
| 92 | set_bit(FF_RUMBLE, dev->ffbit); | ||
| 93 | |||
| 94 | error = input_ff_create_memless(dev, zpff, hid_zpff_play); | ||
| 95 | if (error) { | ||
| 96 | kfree(zpff); | ||
| 97 | return error; | ||
| 98 | } | ||
| 99 | |||
| 100 | zpff->report = report; | ||
| 101 | zpff->report->field[0]->value[0] = 0x00; | ||
| 102 | zpff->report->field[1]->value[0] = 0x02; | ||
| 103 | zpff->report->field[2]->value[0] = 0x00; | ||
| 104 | zpff->report->field[3]->value[0] = 0x00; | ||
| 105 | usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); | ||
| 106 | |||
| 107 | printk(KERN_INFO "Force feedback for Zeroplus based devices by " | ||
| 108 | "Anssi Hannula <anssi.hannula@gmail.com>\n"); | ||
| 109 | |||
| 110 | return 0; | ||
| 111 | } | ||
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c deleted file mode 100644 index a8b3d66cd498..000000000000 --- a/drivers/usb/input/hiddev.c +++ /dev/null | |||
| @@ -1,847 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2001 Paul Stewart | ||
| 3 | * Copyright (c) 2001 Vojtech Pavlik | ||
| 4 | * | ||
| 5 | * HID char devices, giving access to raw HID device events. | ||
| 6 | * | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or | ||
| 13 | * (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * GNU General Public License for more details. | ||
| 19 | * | ||
| 20 | * You should have received a copy of the GNU General Public License | ||
| 21 | * along with this program; if not, write to the Free Software | ||
| 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 23 | * | ||
| 24 | * Should you need to contact me, the author, you can do so either by | ||
| 25 | * e-mail - mail your message to Paul Stewart <stewart@wetlogic.net> | ||
| 26 | */ | ||
| 27 | |||
| 28 | #include <linux/poll.h> | ||
| 29 | #include <linux/slab.h> | ||
| 30 | #include <linux/module.h> | ||
| 31 | #include <linux/init.h> | ||
| 32 | #include <linux/smp_lock.h> | ||
| 33 | #include <linux/input.h> | ||
| 34 | #include <linux/usb.h> | ||
| 35 | #include <linux/hid.h> | ||
| 36 | #include <linux/hiddev.h> | ||
| 37 | #include "usbhid.h" | ||
| 38 | |||
| 39 | #ifdef CONFIG_USB_DYNAMIC_MINORS | ||
| 40 | #define HIDDEV_MINOR_BASE 0 | ||
| 41 | #define HIDDEV_MINORS 256 | ||
| 42 | #else | ||
| 43 | #define HIDDEV_MINOR_BASE 96 | ||
| 44 | #define HIDDEV_MINORS 16 | ||
| 45 | #endif | ||
| 46 | #define HIDDEV_BUFFER_SIZE 64 | ||
| 47 | |||
| 48 | struct hiddev { | ||
| 49 | int exist; | ||
| 50 | int open; | ||
| 51 | wait_queue_head_t wait; | ||
| 52 | struct hid_device *hid; | ||
| 53 | struct list_head list; | ||
| 54 | }; | ||
| 55 | |||
| 56 | struct hiddev_list { | ||
| 57 | struct hiddev_usage_ref buffer[HIDDEV_BUFFER_SIZE]; | ||
| 58 | int head; | ||
| 59 | int tail; | ||
| 60 | unsigned flags; | ||
| 61 | struct fasync_struct *fasync; | ||
| 62 | struct hiddev *hiddev; | ||
| 63 | struct list_head node; | ||
| 64 | }; | ||
| 65 | |||
| 66 | static struct hiddev *hiddev_table[HIDDEV_MINORS]; | ||
| 67 | |||
| 68 | /* | ||
| 69 | * Find a report, given the report's type and ID. The ID can be specified | ||
| 70 | * indirectly by REPORT_ID_FIRST (which returns the first report of the given | ||
| 71 | * type) or by (REPORT_ID_NEXT | old_id), which returns the next report of the | ||
| 72 | * given type which follows old_id. | ||
| 73 | */ | ||
| 74 | static struct hid_report * | ||
| 75 | hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) | ||
| 76 | { | ||
| 77 | unsigned int flags = rinfo->report_id & ~HID_REPORT_ID_MASK; | ||
| 78 | unsigned int rid = rinfo->report_id & HID_REPORT_ID_MASK; | ||
| 79 | struct hid_report_enum *report_enum; | ||
| 80 | struct hid_report *report; | ||
| 81 | struct list_head *list; | ||
| 82 | |||
| 83 | if (rinfo->report_type < HID_REPORT_TYPE_MIN || | ||
| 84 | rinfo->report_type > HID_REPORT_TYPE_MAX) | ||
| 85 | return NULL; | ||
| 86 | |||
| 87 | report_enum = hid->report_enum + | ||
| 88 | (rinfo->report_type - HID_REPORT_TYPE_MIN); | ||
| 89 | |||
| 90 | switch (flags) { | ||
| 91 | case 0: /* Nothing to do -- report_id is already set correctly */ | ||
| 92 | break; | ||
| 93 | |||
| 94 | case HID_REPORT_ID_FIRST: | ||
| 95 | if (list_empty(&report_enum->report_list)) | ||
| 96 | return NULL; | ||
| 97 | |||
| 98 | list = report_enum->report_list.next; | ||
| 99 | report = list_entry(list, struct hid_report, list); | ||
| 100 | rinfo->report_id = report->id; | ||
| 101 | break; | ||
| 102 | |||
| 103 | case HID_REPORT_ID_NEXT: | ||
| 104 | report = report_enum->report_id_hash[rid]; | ||
| 105 | if (!report) | ||
| 106 | return NULL; | ||
| 107 | |||
| 108 | list = report->list.next; | ||
| 109 | if (list == &report_enum->report_list) | ||
| 110 | return NULL; | ||
| 111 | |||
| 112 | report = list_entry(list, struct hid_report, list); | ||
| 113 | rinfo->report_id = report->id; | ||
| 114 | break; | ||
| 115 | |||
| 116 | default: | ||
| 117 | return NULL; | ||
| 118 | } | ||
| 119 | |||
| 120 | return report_enum->report_id_hash[rinfo->report_id]; | ||
| 121 | } | ||
| 122 | |||
| 123 | /* | ||
| 124 | * Perform an exhaustive search of the report table for a usage, given its | ||
| 125 | * type and usage id. | ||
| 126 | */ | ||
| 127 | static struct hid_field * | ||
| 128 | hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref) | ||
| 129 | { | ||
| 130 | int i, j; | ||
| 131 | struct hid_report *report; | ||
| 132 | struct hid_report_enum *report_enum; | ||
| 133 | struct hid_field *field; | ||
| 134 | |||
| 135 | if (uref->report_type < HID_REPORT_TYPE_MIN || | ||
| 136 | uref->report_type > HID_REPORT_TYPE_MAX) | ||
| 137 | return NULL; | ||
| 138 | |||
| 139 | report_enum = hid->report_enum + | ||
| 140 | (uref->report_type - HID_REPORT_TYPE_MIN); | ||
| 141 | |||
| 142 | list_for_each_entry(report, &report_enum->report_list, list) { | ||
| 143 | for (i = 0; i < report->maxfield; i++) { | ||
| 144 | field = report->field[i]; | ||
| 145 | for (j = 0; j < field->maxusage; j++) { | ||
| 146 | if (field->usage[j].hid == uref->usage_code) { | ||
| 147 | uref->report_id = report->id; | ||
| 148 | uref->field_index = i; | ||
| 149 | uref->usage_index = j; | ||
| 150 | return field; | ||
| 151 | } | ||
| 152 | } | ||
| 153 | } | ||
| 154 | } | ||
| 155 | |||
| 156 | return NULL; | ||
| 157 | } | ||
| 158 | |||
| 159 | static void hiddev_send_event(struct hid_device *hid, | ||
| 160 | struct hiddev_usage_ref *uref) | ||
| 161 | { | ||
| 162 | struct hiddev *hiddev = hid->hiddev; | ||
| 163 | struct hiddev_list *list; | ||
| 164 | |||
| 165 | list_for_each_entry(list, &hiddev->list, node) { | ||
| 166 | if (uref->field_index != HID_FIELD_INDEX_NONE || | ||
| 167 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { | ||
| 168 | list->buffer[list->head] = *uref; | ||
| 169 | list->head = (list->head + 1) & | ||
| 170 | (HIDDEV_BUFFER_SIZE - 1); | ||
| 171 | kill_fasync(&list->fasync, SIGIO, POLL_IN); | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | wake_up_interruptible(&hiddev->wait); | ||
| 176 | } | ||
| 177 | |||
| 178 | /* | ||
| 179 | * This is where hid.c calls into hiddev to pass an event that occurred over | ||
| 180 | * the interrupt pipe | ||
| 181 | */ | ||
| 182 | void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, | ||
| 183 | struct hid_usage *usage, __s32 value) | ||
| 184 | { | ||
| 185 | unsigned type = field->report_type; | ||
| 186 | struct hiddev_usage_ref uref; | ||
| 187 | |||
| 188 | uref.report_type = | ||
| 189 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : | ||
| 190 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : | ||
| 191 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); | ||
| 192 | uref.report_id = field->report->id; | ||
| 193 | uref.field_index = field->index; | ||
| 194 | uref.usage_index = (usage - field->usage); | ||
| 195 | uref.usage_code = usage->hid; | ||
| 196 | uref.value = value; | ||
| 197 | |||
| 198 | hiddev_send_event(hid, &uref); | ||
| 199 | } | ||
| 200 | EXPORT_SYMBOL_GPL(hiddev_hid_event); | ||
| 201 | |||
| 202 | void hiddev_report_event(struct hid_device *hid, struct hid_report *report) | ||
| 203 | { | ||
| 204 | unsigned type = report->type; | ||
| 205 | struct hiddev_usage_ref uref; | ||
| 206 | |||
| 207 | memset(&uref, 0, sizeof(uref)); | ||
| 208 | uref.report_type = | ||
| 209 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : | ||
| 210 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : | ||
| 211 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); | ||
| 212 | uref.report_id = report->id; | ||
| 213 | uref.field_index = HID_FIELD_INDEX_NONE; | ||
| 214 | |||
| 215 | hiddev_send_event(hid, &uref); | ||
| 216 | } | ||
| 217 | |||
| 218 | /* | ||
| 219 | * fasync file op | ||
| 220 | */ | ||
| 221 | static int hiddev_fasync(int fd, struct file *file, int on) | ||
| 222 | { | ||
| 223 | int retval; | ||
| 224 | struct hiddev_list *list = file->private_data; | ||
| 225 | |||
| 226 | retval = fasync_helper(fd, file, on, &list->fasync); | ||
| 227 | |||
| 228 | return retval < 0 ? retval : 0; | ||
| 229 | } | ||
| 230 | |||
| 231 | |||
| 232 | /* | ||
| 233 | * release file op | ||
| 234 | */ | ||
| 235 | static int hiddev_release(struct inode * inode, struct file * file) | ||
| 236 | { | ||
| 237 | struct hiddev_list *list = file->private_data; | ||
| 238 | |||
| 239 | hiddev_fasync(-1, file, 0); | ||
| 240 | list_del(&list->node); | ||
| 241 | |||
| 242 | if (!--list->hiddev->open) { | ||
| 243 | if (list->hiddev->exist) | ||
| 244 | usbhid_close(list->hiddev->hid); | ||
| 245 | else | ||
| 246 | kfree(list->hiddev); | ||
| 247 | } | ||
| 248 | |||
| 249 | kfree(list); | ||
| 250 | |||
| 251 | return 0; | ||
| 252 | } | ||
| 253 | |||
| 254 | /* | ||
| 255 | * open file op | ||
| 256 | */ | ||
| 257 | static int hiddev_open(struct inode *inode, struct file *file) | ||
| 258 | { | ||
| 259 | struct hiddev_list *list; | ||
| 260 | |||
| 261 | int i = iminor(inode) - HIDDEV_MINOR_BASE; | ||
| 262 | |||
| 263 | if (i >= HIDDEV_MINORS || !hiddev_table[i]) | ||
| 264 | return -ENODEV; | ||
| 265 | |||
| 266 | if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL))) | ||
| 267 | return -ENOMEM; | ||
| 268 | |||
| 269 | list->hiddev = hiddev_table[i]; | ||
| 270 | list_add_tail(&list->node, &hiddev_table[i]->list); | ||
| 271 | file->private_data = list; | ||
| 272 | |||
| 273 | if (!list->hiddev->open++) | ||
| 274 | if (list->hiddev->exist) | ||
| 275 | usbhid_open(hiddev_table[i]->hid); | ||
| 276 | |||
| 277 | return 0; | ||
| 278 | } | ||
| 279 | |||
| 280 | /* | ||
| 281 | * "write" file op | ||
| 282 | */ | ||
| 283 | static ssize_t hiddev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) | ||
| 284 | { | ||
| 285 | return -EINVAL; | ||
| 286 | } | ||
| 287 | |||
| 288 | /* | ||
| 289 | * "read" file op | ||
| 290 | */ | ||
| 291 | static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) | ||
| 292 | { | ||
| 293 | DECLARE_WAITQUEUE(wait, current); | ||
| 294 | struct hiddev_list *list = file->private_data; | ||
| 295 | int event_size; | ||
| 296 | int retval = 0; | ||
| 297 | |||
| 298 | event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ? | ||
| 299 | sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event); | ||
| 300 | |||
| 301 | if (count < event_size) | ||
| 302 | return 0; | ||
| 303 | |||
| 304 | while (retval == 0) { | ||
| 305 | if (list->head == list->tail) { | ||
| 306 | add_wait_queue(&list->hiddev->wait, &wait); | ||
| 307 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 308 | |||
| 309 | while (list->head == list->tail) { | ||
| 310 | if (file->f_flags & O_NONBLOCK) { | ||
| 311 | retval = -EAGAIN; | ||
| 312 | break; | ||
| 313 | } | ||
| 314 | if (signal_pending(current)) { | ||
| 315 | retval = -ERESTARTSYS; | ||
| 316 | break; | ||
| 317 | } | ||
| 318 | if (!list->hiddev->exist) { | ||
| 319 | retval = -EIO; | ||
| 320 | break; | ||
| 321 | } | ||
| 322 | |||
| 323 | schedule(); | ||
| 324 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 325 | } | ||
| 326 | |||
| 327 | set_current_state(TASK_RUNNING); | ||
| 328 | remove_wait_queue(&list->hiddev->wait, &wait); | ||
| 329 | } | ||
| 330 | |||
| 331 | if (retval) | ||
| 332 | return retval; | ||
| 333 | |||
| 334 | |||
| 335 | while (list->head != list->tail && | ||
| 336 | retval + event_size <= count) { | ||
| 337 | if ((list->flags & HIDDEV_FLAG_UREF) == 0) { | ||
| 338 | if (list->buffer[list->tail].field_index != | ||
| 339 | HID_FIELD_INDEX_NONE) { | ||
| 340 | struct hiddev_event event; | ||
| 341 | event.hid = list->buffer[list->tail].usage_code; | ||
| 342 | event.value = list->buffer[list->tail].value; | ||
| 343 | if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event))) | ||
| 344 | return -EFAULT; | ||
| 345 | retval += sizeof(struct hiddev_event); | ||
| 346 | } | ||
| 347 | } else { | ||
| 348 | if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE || | ||
| 349 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { | ||
| 350 | if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref))) | ||
| 351 | return -EFAULT; | ||
| 352 | retval += sizeof(struct hiddev_usage_ref); | ||
| 353 | } | ||
| 354 | } | ||
| 355 | list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1); | ||
| 356 | } | ||
| 357 | |||
| 358 | } | ||
| 359 | |||
| 360 | return retval; | ||
| 361 | } | ||
| 362 | |||
| 363 | /* | ||
| 364 | * "poll" file op | ||
| 365 | * No kernel lock - fine | ||
| 366 | */ | ||
| 367 | static unsigned int hiddev_poll(struct file *file, poll_table *wait) | ||
| 368 | { | ||
| 369 | struct hiddev_list *list = file->private_data; | ||
| 370 | |||
| 371 | poll_wait(file, &list->hiddev->wait, wait); | ||
| 372 | if (list->head != list->tail) | ||
| 373 | return POLLIN | POLLRDNORM; | ||
| 374 | if (!list->hiddev->exist) | ||
| 375 | return POLLERR | POLLHUP; | ||
| 376 | return 0; | ||
| 377 | } | ||
| 378 | |||
| 379 | /* | ||
| 380 | * "ioctl" file op | ||
| 381 | */ | ||
| 382 | static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | ||
| 383 | { | ||
| 384 | struct hiddev_list *list = file->private_data; | ||
| 385 | struct hiddev *hiddev = list->hiddev; | ||
| 386 | struct hid_device *hid = hiddev->hid; | ||
| 387 | struct usb_device *dev = hid_to_usb_dev(hid); | ||
| 388 | struct hiddev_collection_info cinfo; | ||
| 389 | struct hiddev_report_info rinfo; | ||
| 390 | struct hiddev_field_info finfo; | ||
| 391 | struct hiddev_usage_ref_multi *uref_multi = NULL; | ||
| 392 | struct hiddev_usage_ref *uref; | ||
| 393 | struct hiddev_devinfo dinfo; | ||
| 394 | struct hid_report *report; | ||
| 395 | struct hid_field *field; | ||
| 396 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 397 | void __user *user_arg = (void __user *)arg; | ||
| 398 | int i; | ||
| 399 | |||
| 400 | if (!hiddev->exist) | ||
| 401 | return -EIO; | ||
| 402 | |||
| 403 | switch (cmd) { | ||
| 404 | |||
| 405 | case HIDIOCGVERSION: | ||
| 406 | return put_user(HID_VERSION, (int __user *)arg); | ||
| 407 | |||
| 408 | case HIDIOCAPPLICATION: | ||
| 409 | if (arg < 0 || arg >= hid->maxapplication) | ||
| 410 | return -EINVAL; | ||
| 411 | |||
| 412 | for (i = 0; i < hid->maxcollection; i++) | ||
| 413 | if (hid->collection[i].type == | ||
| 414 | HID_COLLECTION_APPLICATION && arg-- == 0) | ||
| 415 | break; | ||
| 416 | |||
| 417 | if (i == hid->maxcollection) | ||
| 418 | return -EINVAL; | ||
| 419 | |||
| 420 | return hid->collection[i].usage; | ||
| 421 | |||
| 422 | case HIDIOCGDEVINFO: | ||
| 423 | dinfo.bustype = BUS_USB; | ||
| 424 | dinfo.busnum = dev->bus->busnum; | ||
| 425 | dinfo.devnum = dev->devnum; | ||
| 426 | dinfo.ifnum = usbhid->ifnum; | ||
| 427 | dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor); | ||
| 428 | dinfo.product = le16_to_cpu(dev->descriptor.idProduct); | ||
| 429 | dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice); | ||
| 430 | dinfo.num_applications = hid->maxapplication; | ||
| 431 | if (copy_to_user(user_arg, &dinfo, sizeof(dinfo))) | ||
| 432 | return -EFAULT; | ||
| 433 | |||
| 434 | return 0; | ||
| 435 | |||
| 436 | case HIDIOCGFLAG: | ||
| 437 | if (put_user(list->flags, (int __user *)arg)) | ||
| 438 | return -EFAULT; | ||
| 439 | |||
| 440 | return 0; | ||
| 441 | |||
| 442 | case HIDIOCSFLAG: | ||
| 443 | { | ||
| 444 | int newflags; | ||
| 445 | if (get_user(newflags, (int __user *)arg)) | ||
| 446 | return -EFAULT; | ||
| 447 | |||
| 448 | if ((newflags & ~HIDDEV_FLAGS) != 0 || | ||
| 449 | ((newflags & HIDDEV_FLAG_REPORT) != 0 && | ||
| 450 | (newflags & HIDDEV_FLAG_UREF) == 0)) | ||
| 451 | return -EINVAL; | ||
| 452 | |||
| 453 | list->flags = newflags; | ||
| 454 | |||
| 455 | return 0; | ||
| 456 | } | ||
| 457 | |||
| 458 | case HIDIOCGSTRING: | ||
| 459 | { | ||
| 460 | int idx, len; | ||
| 461 | char *buf; | ||
| 462 | |||
| 463 | if (get_user(idx, (int __user *)arg)) | ||
| 464 | return -EFAULT; | ||
| 465 | |||
| 466 | if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL) | ||
| 467 | return -ENOMEM; | ||
| 468 | |||
| 469 | if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) { | ||
| 470 | kfree(buf); | ||
| 471 | return -EINVAL; | ||
| 472 | } | ||
| 473 | |||
| 474 | if (copy_to_user(user_arg+sizeof(int), buf, len+1)) { | ||
| 475 | kfree(buf); | ||
| 476 | return -EFAULT; | ||
| 477 | } | ||
| 478 | |||
| 479 | kfree(buf); | ||
| 480 | |||
| 481 | return len; | ||
| 482 | } | ||
| 483 | |||
| 484 | case HIDIOCINITREPORT: | ||
| 485 | usbhid_init_reports(hid); | ||
| 486 | |||
| 487 | return 0; | ||
| 488 | |||
| 489 | case HIDIOCGREPORT: | ||
| 490 | if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) | ||
| 491 | return -EFAULT; | ||
| 492 | |||
| 493 | if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT) | ||
| 494 | return -EINVAL; | ||
| 495 | |||
| 496 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
| 497 | return -EINVAL; | ||
| 498 | |||
| 499 | usbhid_submit_report(hid, report, USB_DIR_IN); | ||
| 500 | usbhid_wait_io(hid); | ||
| 501 | |||
| 502 | return 0; | ||
| 503 | |||
| 504 | case HIDIOCSREPORT: | ||
| 505 | if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) | ||
| 506 | return -EFAULT; | ||
| 507 | |||
| 508 | if (rinfo.report_type == HID_REPORT_TYPE_INPUT) | ||
| 509 | return -EINVAL; | ||
| 510 | |||
| 511 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
| 512 | return -EINVAL; | ||
| 513 | |||
| 514 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
| 515 | usbhid_wait_io(hid); | ||
| 516 | |||
| 517 | return 0; | ||
| 518 | |||
| 519 | case HIDIOCGREPORTINFO: | ||
| 520 | if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) | ||
| 521 | return -EFAULT; | ||
| 522 | |||
| 523 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
| 524 | return -EINVAL; | ||
| 525 | |||
| 526 | rinfo.num_fields = report->maxfield; | ||
| 527 | |||
| 528 | if (copy_to_user(user_arg, &rinfo, sizeof(rinfo))) | ||
| 529 | return -EFAULT; | ||
| 530 | |||
| 531 | return 0; | ||
| 532 | |||
| 533 | case HIDIOCGFIELDINFO: | ||
| 534 | if (copy_from_user(&finfo, user_arg, sizeof(finfo))) | ||
| 535 | return -EFAULT; | ||
| 536 | rinfo.report_type = finfo.report_type; | ||
| 537 | rinfo.report_id = finfo.report_id; | ||
| 538 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
| 539 | return -EINVAL; | ||
| 540 | |||
| 541 | if (finfo.field_index >= report->maxfield) | ||
| 542 | return -EINVAL; | ||
| 543 | |||
| 544 | field = report->field[finfo.field_index]; | ||
| 545 | memset(&finfo, 0, sizeof(finfo)); | ||
| 546 | finfo.report_type = rinfo.report_type; | ||
| 547 | finfo.report_id = rinfo.report_id; | ||
| 548 | finfo.field_index = field->report_count - 1; | ||
| 549 | finfo.maxusage = field->maxusage; | ||
| 550 | finfo.flags = field->flags; | ||
| 551 | finfo.physical = field->physical; | ||
| 552 | finfo.logical = field->logical; | ||
| 553 | finfo.application = field->application; | ||
| 554 | finfo.logical_minimum = field->logical_minimum; | ||
| 555 | finfo.logical_maximum = field->logical_maximum; | ||
| 556 | finfo.physical_minimum = field->physical_minimum; | ||
| 557 | finfo.physical_maximum = field->physical_maximum; | ||
| 558 | finfo.unit_exponent = field->unit_exponent; | ||
| 559 | finfo.unit = field->unit; | ||
| 560 | |||
| 561 | if (copy_to_user(user_arg, &finfo, sizeof(finfo))) | ||
| 562 | return -EFAULT; | ||
| 563 | |||
| 564 | return 0; | ||
| 565 | |||
| 566 | case HIDIOCGUCODE: | ||
| 567 | uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL); | ||
| 568 | if (!uref_multi) | ||
| 569 | return -ENOMEM; | ||
| 570 | uref = &uref_multi->uref; | ||
| 571 | if (copy_from_user(uref, user_arg, sizeof(*uref))) | ||
| 572 | goto fault; | ||
| 573 | |||
| 574 | rinfo.report_type = uref->report_type; | ||
| 575 | rinfo.report_id = uref->report_id; | ||
| 576 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
| 577 | goto inval; | ||
| 578 | |||
| 579 | if (uref->field_index >= report->maxfield) | ||
| 580 | goto inval; | ||
| 581 | |||
| 582 | field = report->field[uref->field_index]; | ||
| 583 | if (uref->usage_index >= field->maxusage) | ||
| 584 | goto inval; | ||
| 585 | |||
| 586 | uref->usage_code = field->usage[uref->usage_index].hid; | ||
| 587 | |||
| 588 | if (copy_to_user(user_arg, uref, sizeof(*uref))) | ||
| 589 | goto fault; | ||
| 590 | |||
| 591 | kfree(uref_multi); | ||
| 592 | return 0; | ||
| 593 | |||
| 594 | case HIDIOCGUSAGE: | ||
| 595 | case HIDIOCSUSAGE: | ||
| 596 | case HIDIOCGUSAGES: | ||
| 597 | case HIDIOCSUSAGES: | ||
| 598 | case HIDIOCGCOLLECTIONINDEX: | ||
| 599 | uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL); | ||
| 600 | if (!uref_multi) | ||
| 601 | return -ENOMEM; | ||
| 602 | uref = &uref_multi->uref; | ||
| 603 | if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { | ||
| 604 | if (copy_from_user(uref_multi, user_arg, | ||
| 605 | sizeof(*uref_multi))) | ||
| 606 | goto fault; | ||
| 607 | } else { | ||
| 608 | if (copy_from_user(uref, user_arg, sizeof(*uref))) | ||
| 609 | goto fault; | ||
| 610 | } | ||
| 611 | |||
| 612 | if (cmd != HIDIOCGUSAGE && | ||
| 613 | cmd != HIDIOCGUSAGES && | ||
| 614 | uref->report_type == HID_REPORT_TYPE_INPUT) | ||
| 615 | goto inval; | ||
| 616 | |||
| 617 | if (uref->report_id == HID_REPORT_ID_UNKNOWN) { | ||
| 618 | field = hiddev_lookup_usage(hid, uref); | ||
| 619 | if (field == NULL) | ||
| 620 | goto inval; | ||
| 621 | } else { | ||
| 622 | rinfo.report_type = uref->report_type; | ||
| 623 | rinfo.report_id = uref->report_id; | ||
| 624 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
| 625 | goto inval; | ||
| 626 | |||
| 627 | if (uref->field_index >= report->maxfield) | ||
| 628 | goto inval; | ||
| 629 | |||
| 630 | field = report->field[uref->field_index]; | ||
| 631 | |||
| 632 | if (cmd == HIDIOCGCOLLECTIONINDEX) { | ||
| 633 | if (uref->usage_index >= field->maxusage) | ||
| 634 | goto inval; | ||
| 635 | } else if (uref->usage_index >= field->report_count) | ||
| 636 | goto inval; | ||
| 637 | |||
| 638 | else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && | ||
| 639 | (uref_multi->num_values > HID_MAX_MULTI_USAGES || | ||
| 640 | uref->usage_index + uref_multi->num_values > field->report_count)) | ||
| 641 | goto inval; | ||
| 642 | } | ||
| 643 | |||
| 644 | switch (cmd) { | ||
| 645 | case HIDIOCGUSAGE: | ||
| 646 | uref->value = field->value[uref->usage_index]; | ||
| 647 | if (copy_to_user(user_arg, uref, sizeof(*uref))) | ||
| 648 | goto fault; | ||
| 649 | goto goodreturn; | ||
| 650 | |||
| 651 | case HIDIOCSUSAGE: | ||
| 652 | field->value[uref->usage_index] = uref->value; | ||
| 653 | goto goodreturn; | ||
| 654 | |||
| 655 | case HIDIOCGCOLLECTIONINDEX: | ||
| 656 | kfree(uref_multi); | ||
| 657 | return field->usage[uref->usage_index].collection_index; | ||
| 658 | case HIDIOCGUSAGES: | ||
| 659 | for (i = 0; i < uref_multi->num_values; i++) | ||
| 660 | uref_multi->values[i] = | ||
| 661 | field->value[uref->usage_index + i]; | ||
| 662 | if (copy_to_user(user_arg, uref_multi, | ||
| 663 | sizeof(*uref_multi))) | ||
| 664 | goto fault; | ||
| 665 | goto goodreturn; | ||
| 666 | case HIDIOCSUSAGES: | ||
| 667 | for (i = 0; i < uref_multi->num_values; i++) | ||
| 668 | field->value[uref->usage_index + i] = | ||
| 669 | uref_multi->values[i]; | ||
| 670 | goto goodreturn; | ||
| 671 | } | ||
| 672 | |||
| 673 | goodreturn: | ||
| 674 | kfree(uref_multi); | ||
| 675 | return 0; | ||
| 676 | fault: | ||
| 677 | kfree(uref_multi); | ||
| 678 | return -EFAULT; | ||
| 679 | inval: | ||
| 680 | kfree(uref_multi); | ||
| 681 | return -EINVAL; | ||
| 682 | |||
| 683 | case HIDIOCGCOLLECTIONINFO: | ||
| 684 | if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) | ||
| 685 | return -EFAULT; | ||
| 686 | |||
| 687 | if (cinfo.index >= hid->maxcollection) | ||
| 688 | return -EINVAL; | ||
| 689 | |||
| 690 | cinfo.type = hid->collection[cinfo.index].type; | ||
| 691 | cinfo.usage = hid->collection[cinfo.index].usage; | ||
| 692 | cinfo.level = hid->collection[cinfo.index].level; | ||
| 693 | |||
| 694 | if (copy_to_user(user_arg, &cinfo, sizeof(cinfo))) | ||
| 695 | return -EFAULT; | ||
| 696 | return 0; | ||
| 697 | |||
| 698 | default: | ||
| 699 | |||
| 700 | if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) | ||
| 701 | return -EINVAL; | ||
| 702 | |||
| 703 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) { | ||
| 704 | int len; | ||
| 705 | if (!hid->name) | ||
| 706 | return 0; | ||
| 707 | len = strlen(hid->name) + 1; | ||
| 708 | if (len > _IOC_SIZE(cmd)) | ||
| 709 | len = _IOC_SIZE(cmd); | ||
| 710 | return copy_to_user(user_arg, hid->name, len) ? | ||
| 711 | -EFAULT : len; | ||
| 712 | } | ||
| 713 | |||
| 714 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGPHYS(0))) { | ||
| 715 | int len; | ||
| 716 | if (!hid->phys) | ||
| 717 | return 0; | ||
| 718 | len = strlen(hid->phys) + 1; | ||
| 719 | if (len > _IOC_SIZE(cmd)) | ||
| 720 | len = _IOC_SIZE(cmd); | ||
| 721 | return copy_to_user(user_arg, hid->phys, len) ? | ||
| 722 | -EFAULT : len; | ||
| 723 | } | ||
| 724 | } | ||
| 725 | return -EINVAL; | ||
| 726 | } | ||
| 727 | |||
| 728 | static const struct file_operations hiddev_fops = { | ||
| 729 | .owner = THIS_MODULE, | ||
| 730 | .read = hiddev_read, | ||
| 731 | .write = hiddev_write, | ||
| 732 | .poll = hiddev_poll, | ||
| 733 | .open = hiddev_open, | ||
| 734 | .release = hiddev_release, | ||
| 735 | .ioctl = hiddev_ioctl, | ||
| 736 | .fasync = hiddev_fasync, | ||
| 737 | }; | ||
| 738 | |||
| 739 | static struct usb_class_driver hiddev_class = { | ||
| 740 | .name = "hiddev%d", | ||
| 741 | .fops = &hiddev_fops, | ||
| 742 | .minor_base = HIDDEV_MINOR_BASE, | ||
| 743 | }; | ||
| 744 | |||
| 745 | /* | ||
| 746 | * This is where hid.c calls us to connect a hid device to the hiddev driver | ||
| 747 | */ | ||
| 748 | int hiddev_connect(struct hid_device *hid) | ||
| 749 | { | ||
| 750 | struct hiddev *hiddev; | ||
| 751 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 752 | int i; | ||
| 753 | int retval; | ||
| 754 | |||
| 755 | for (i = 0; i < hid->maxcollection; i++) | ||
| 756 | if (hid->collection[i].type == | ||
| 757 | HID_COLLECTION_APPLICATION && | ||
| 758 | !IS_INPUT_APPLICATION(hid->collection[i].usage)) | ||
| 759 | break; | ||
| 760 | |||
| 761 | if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0) | ||
| 762 | return -1; | ||
| 763 | |||
| 764 | if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL))) | ||
| 765 | return -1; | ||
| 766 | |||
| 767 | retval = usb_register_dev(usbhid->intf, &hiddev_class); | ||
| 768 | if (retval) { | ||
| 769 | err("Not able to get a minor for this device."); | ||
| 770 | kfree(hiddev); | ||
| 771 | return -1; | ||
| 772 | } | ||
| 773 | |||
| 774 | init_waitqueue_head(&hiddev->wait); | ||
| 775 | INIT_LIST_HEAD(&hiddev->list); | ||
| 776 | hiddev->hid = hid; | ||
| 777 | hiddev->exist = 1; | ||
| 778 | |||
| 779 | hid->minor = usbhid->intf->minor; | ||
| 780 | hid->hiddev = hiddev; | ||
| 781 | |||
| 782 | hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; | ||
| 783 | |||
| 784 | return 0; | ||
| 785 | } | ||
| 786 | |||
| 787 | /* | ||
| 788 | * This is where hid.c calls us to disconnect a hiddev device from the | ||
| 789 | * corresponding hid device (usually because the usb device has disconnected) | ||
| 790 | */ | ||
| 791 | static struct usb_class_driver hiddev_class; | ||
| 792 | void hiddev_disconnect(struct hid_device *hid) | ||
| 793 | { | ||
| 794 | struct hiddev *hiddev = hid->hiddev; | ||
| 795 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 796 | |||
| 797 | hiddev->exist = 0; | ||
| 798 | |||
| 799 | hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL; | ||
| 800 | usb_deregister_dev(usbhid->intf, &hiddev_class); | ||
| 801 | |||
| 802 | if (hiddev->open) { | ||
| 803 | usbhid_close(hiddev->hid); | ||
| 804 | wake_up_interruptible(&hiddev->wait); | ||
| 805 | } else { | ||
| 806 | kfree(hiddev); | ||
| 807 | } | ||
| 808 | } | ||
| 809 | |||
| 810 | /* Currently this driver is a USB driver. It's not a conventional one in | ||
| 811 | * the sense that it doesn't probe at the USB level. Instead it waits to | ||
| 812 | * be connected by HID through the hiddev_connect / hiddev_disconnect | ||
| 813 | * routines. The reason to register as a USB device is to gain part of the | ||
| 814 | * minor number space from the USB major. | ||
| 815 | * | ||
| 816 | * In theory, should the HID code be generalized to more than one physical | ||
| 817 | * medium (say, IEEE 1384), this driver will probably need to register its | ||
| 818 | * own major number, and in doing so, no longer need to register with USB. | ||
| 819 | * At that point the probe routine and hiddev_driver struct below will no | ||
| 820 | * longer be useful. | ||
| 821 | */ | ||
| 822 | |||
| 823 | |||
| 824 | /* We never attach in this manner, and rely on HID to connect us. This | ||
| 825 | * is why there is no disconnect routine defined in the usb_driver either. | ||
| 826 | */ | ||
| 827 | static int hiddev_usbd_probe(struct usb_interface *intf, | ||
| 828 | const struct usb_device_id *hiddev_info) | ||
| 829 | { | ||
| 830 | return -ENODEV; | ||
| 831 | } | ||
| 832 | |||
| 833 | |||
| 834 | static /* const */ struct usb_driver hiddev_driver = { | ||
| 835 | .name = "hiddev", | ||
| 836 | .probe = hiddev_usbd_probe, | ||
| 837 | }; | ||
| 838 | |||
| 839 | int __init hiddev_init(void) | ||
| 840 | { | ||
| 841 | return usb_register(&hiddev_driver); | ||
| 842 | } | ||
| 843 | |||
| 844 | void hiddev_exit(void) | ||
| 845 | { | ||
| 846 | usb_deregister(&hiddev_driver); | ||
| 847 | } | ||
diff --git a/drivers/usb/input/usbhid.h b/drivers/usb/input/usbhid.h deleted file mode 100644 index 0023f96d4294..000000000000 --- a/drivers/usb/input/usbhid.h +++ /dev/null | |||
| @@ -1,87 +0,0 @@ | |||
| 1 | #ifndef __USBHID_H | ||
| 2 | #define __USBHID_H | ||
| 3 | |||
| 4 | /* | ||
| 5 | * Copyright (c) 1999 Andreas Gal | ||
| 6 | * Copyright (c) 2000-2001 Vojtech Pavlik | ||
| 7 | * Copyright (c) 2006 Jiri Kosina | ||
| 8 | */ | ||
| 9 | |||
| 10 | /* | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License as published by | ||
| 13 | * the Free Software Foundation; either version 2 of the License, or | ||
| 14 | * (at your option) any later version. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, | ||
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, write to the Free Software | ||
| 23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 24 | * | ||
| 25 | */ | ||
| 26 | |||
| 27 | #include <linux/types.h> | ||
| 28 | #include <linux/slab.h> | ||
| 29 | #include <linux/list.h> | ||
| 30 | #include <linux/timer.h> | ||
| 31 | #include <linux/workqueue.h> | ||
| 32 | #include <linux/input.h> | ||
| 33 | |||
| 34 | /* API provided by hid-core.c for USB HID drivers */ | ||
| 35 | int usbhid_wait_io(struct hid_device* hid); | ||
| 36 | void usbhid_close(struct hid_device *hid); | ||
| 37 | int usbhid_open(struct hid_device *hid); | ||
| 38 | void usbhid_init_reports(struct hid_device *hid); | ||
| 39 | void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir); | ||
| 40 | |||
| 41 | /* | ||
| 42 | * USB-specific HID struct, to be pointed to | ||
| 43 | * from struct hid_device->driver_data | ||
| 44 | */ | ||
| 45 | |||
| 46 | struct usbhid_device { | ||
| 47 | struct hid_device *hid; /* pointer to corresponding HID dev */ | ||
| 48 | |||
| 49 | struct usb_interface *intf; /* USB interface */ | ||
| 50 | int ifnum; /* USB interface number */ | ||
| 51 | |||
| 52 | unsigned int bufsize; /* URB buffer size */ | ||
| 53 | |||
| 54 | struct urb *urbin; /* Input URB */ | ||
| 55 | char *inbuf; /* Input buffer */ | ||
| 56 | dma_addr_t inbuf_dma; /* Input buffer dma */ | ||
| 57 | spinlock_t inlock; /* Input fifo spinlock */ | ||
| 58 | |||
| 59 | struct urb *urbctrl; /* Control URB */ | ||
| 60 | struct usb_ctrlrequest *cr; /* Control request struct */ | ||
| 61 | dma_addr_t cr_dma; /* Control request struct dma */ | ||
| 62 | struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE]; /* Control fifo */ | ||
| 63 | unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */ | ||
| 64 | char *ctrlbuf; /* Control buffer */ | ||
| 65 | dma_addr_t ctrlbuf_dma; /* Control buffer dma */ | ||
| 66 | spinlock_t ctrllock; /* Control fifo spinlock */ | ||
| 67 | |||
| 68 | struct urb *urbout; /* Output URB */ | ||
| 69 | struct hid_report *out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */ | ||
| 70 | unsigned char outhead, outtail; /* Output pipe fifo head & tail */ | ||
| 71 | char *outbuf; /* Output buffer */ | ||
| 72 | dma_addr_t outbuf_dma; /* Output buffer dma */ | ||
| 73 | spinlock_t outlock; /* Output fifo spinlock */ | ||
| 74 | |||
| 75 | unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ | ||
| 76 | struct timer_list io_retry; /* Retry timer */ | ||
| 77 | unsigned long stop_retry; /* Time to give up, in jiffies */ | ||
| 78 | unsigned int retry_delay; /* Delay length in ms */ | ||
| 79 | struct work_struct reset_work; /* Task context for resets */ | ||
| 80 | |||
| 81 | }; | ||
| 82 | |||
| 83 | #define hid_to_usb_dev(hid_dev) \ | ||
| 84 | container_of(hid_dev->dev->parent, struct usb_device, dev) | ||
| 85 | |||
| 86 | #endif | ||
| 87 | |||
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c deleted file mode 100644 index 3749f4a235f9..000000000000 --- a/drivers/usb/input/usbkbd.c +++ /dev/null | |||
| @@ -1,362 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * $Id: usbkbd.c,v 1.27 2001/12/27 10:37:41 vojtech Exp $ | ||
| 3 | * | ||
| 4 | * Copyright (c) 1999-2001 Vojtech Pavlik | ||
| 5 | * | ||
| 6 | * USB HIDBP Keyboard support | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or | ||
| 13 | * (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * GNU General Public License for more details. | ||
| 19 | * | ||
| 20 | * You should have received a copy of the GNU General Public License | ||
| 21 | * along with this program; if not, write to the Free Software | ||
| 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 23 | * | ||
| 24 | * Should you need to contact me, the author, you can do so either by | ||
| 25 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | ||
| 26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | ||
| 27 | */ | ||
| 28 | |||
| 29 | #include <linux/kernel.h> | ||
| 30 | #include <linux/slab.h> | ||
| 31 | #include <linux/module.h> | ||
| 32 | #include <linux/init.h> | ||
| 33 | #include <linux/usb/input.h> | ||
| 34 | #include <linux/hid.h> | ||
| 35 | |||
| 36 | /* | ||
| 37 | * Version Information | ||
| 38 | */ | ||
| 39 | #define DRIVER_VERSION "" | ||
| 40 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | ||
| 41 | #define DRIVER_DESC "USB HID Boot Protocol keyboard driver" | ||
| 42 | #define DRIVER_LICENSE "GPL" | ||
| 43 | |||
| 44 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
| 45 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 46 | MODULE_LICENSE(DRIVER_LICENSE); | ||
| 47 | |||
| 48 | static unsigned char usb_kbd_keycode[256] = { | ||
| 49 | 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, | ||
| 50 | 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, | ||
| 51 | 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, | ||
| 52 | 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, | ||
| 53 | 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, | ||
| 54 | 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, | ||
| 55 | 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, | ||
| 56 | 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, | ||
| 57 | 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0, | ||
| 58 | 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 59 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 60 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 61 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 62 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 63 | 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, | ||
| 64 | 150,158,159,128,136,177,178,176,142,152,173,140 | ||
| 65 | }; | ||
| 66 | |||
| 67 | struct usb_kbd { | ||
| 68 | struct input_dev *dev; | ||
| 69 | struct usb_device *usbdev; | ||
| 70 | unsigned char old[8]; | ||
| 71 | struct urb *irq, *led; | ||
| 72 | unsigned char newleds; | ||
| 73 | char name[128]; | ||
| 74 | char phys[64]; | ||
| 75 | |||
| 76 | unsigned char *new; | ||
| 77 | struct usb_ctrlrequest *cr; | ||
| 78 | unsigned char *leds; | ||
| 79 | dma_addr_t cr_dma; | ||
| 80 | dma_addr_t new_dma; | ||
| 81 | dma_addr_t leds_dma; | ||
| 82 | }; | ||
| 83 | |||
| 84 | static void usb_kbd_irq(struct urb *urb) | ||
| 85 | { | ||
| 86 | struct usb_kbd *kbd = urb->context; | ||
| 87 | int i; | ||
| 88 | |||
| 89 | switch (urb->status) { | ||
| 90 | case 0: /* success */ | ||
| 91 | break; | ||
| 92 | case -ECONNRESET: /* unlink */ | ||
| 93 | case -ENOENT: | ||
| 94 | case -ESHUTDOWN: | ||
| 95 | return; | ||
| 96 | /* -EPIPE: should clear the halt */ | ||
| 97 | default: /* error */ | ||
| 98 | goto resubmit; | ||
| 99 | } | ||
| 100 | |||
| 101 | for (i = 0; i < 8; i++) | ||
| 102 | input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1); | ||
| 103 | |||
| 104 | for (i = 2; i < 8; i++) { | ||
| 105 | |||
| 106 | if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) { | ||
| 107 | if (usb_kbd_keycode[kbd->old[i]]) | ||
| 108 | input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0); | ||
| 109 | else | ||
| 110 | info("Unknown key (scancode %#x) released.", kbd->old[i]); | ||
| 111 | } | ||
| 112 | |||
| 113 | if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) { | ||
| 114 | if (usb_kbd_keycode[kbd->new[i]]) | ||
| 115 | input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1); | ||
| 116 | else | ||
| 117 | info("Unknown key (scancode %#x) pressed.", kbd->new[i]); | ||
| 118 | } | ||
| 119 | } | ||
| 120 | |||
| 121 | input_sync(kbd->dev); | ||
| 122 | |||
| 123 | memcpy(kbd->old, kbd->new, 8); | ||
| 124 | |||
| 125 | resubmit: | ||
| 126 | i = usb_submit_urb (urb, GFP_ATOMIC); | ||
| 127 | if (i) | ||
| 128 | err ("can't resubmit intr, %s-%s/input0, status %d", | ||
| 129 | kbd->usbdev->bus->bus_name, | ||
| 130 | kbd->usbdev->devpath, i); | ||
| 131 | } | ||
| 132 | |||
| 133 | static int usb_kbd_event(struct input_dev *dev, unsigned int type, | ||
| 134 | unsigned int code, int value) | ||
| 135 | { | ||
| 136 | struct usb_kbd *kbd = dev->private; | ||
| 137 | |||
| 138 | if (type != EV_LED) | ||
| 139 | return -1; | ||
| 140 | |||
| 141 | |||
| 142 | kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) | | ||
| 143 | (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) | | ||
| 144 | (!!test_bit(LED_NUML, dev->led)); | ||
| 145 | |||
| 146 | if (kbd->led->status == -EINPROGRESS) | ||
| 147 | return 0; | ||
| 148 | |||
| 149 | if (*(kbd->leds) == kbd->newleds) | ||
| 150 | return 0; | ||
| 151 | |||
| 152 | *(kbd->leds) = kbd->newleds; | ||
| 153 | kbd->led->dev = kbd->usbdev; | ||
| 154 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)) | ||
| 155 | err("usb_submit_urb(leds) failed"); | ||
| 156 | |||
| 157 | return 0; | ||
| 158 | } | ||
| 159 | |||
| 160 | static void usb_kbd_led(struct urb *urb) | ||
| 161 | { | ||
| 162 | struct usb_kbd *kbd = urb->context; | ||
| 163 | |||
| 164 | if (urb->status) | ||
| 165 | warn("led urb status %d received", urb->status); | ||
| 166 | |||
| 167 | if (*(kbd->leds) == kbd->newleds) | ||
| 168 | return; | ||
| 169 | |||
| 170 | *(kbd->leds) = kbd->newleds; | ||
| 171 | kbd->led->dev = kbd->usbdev; | ||
| 172 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)) | ||
| 173 | err("usb_submit_urb(leds) failed"); | ||
| 174 | } | ||
| 175 | |||
| 176 | static int usb_kbd_open(struct input_dev *dev) | ||
| 177 | { | ||
| 178 | struct usb_kbd *kbd = dev->private; | ||
| 179 | |||
| 180 | kbd->irq->dev = kbd->usbdev; | ||
| 181 | if (usb_submit_urb(kbd->irq, GFP_KERNEL)) | ||
| 182 | return -EIO; | ||
| 183 | |||
| 184 | return 0; | ||
| 185 | } | ||
| 186 | |||
| 187 | static void usb_kbd_close(struct input_dev *dev) | ||
| 188 | { | ||
| 189 | struct usb_kbd *kbd = dev->private; | ||
| 190 | |||
| 191 | usb_kill_urb(kbd->irq); | ||
| 192 | } | ||
| 193 | |||
| 194 | static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) | ||
| 195 | { | ||
| 196 | if (!(kbd->irq = usb_alloc_urb(0, GFP_KERNEL))) | ||
| 197 | return -1; | ||
| 198 | if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL))) | ||
| 199 | return -1; | ||
| 200 | if (!(kbd->new = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &kbd->new_dma))) | ||
| 201 | return -1; | ||
| 202 | if (!(kbd->cr = usb_buffer_alloc(dev, sizeof(struct usb_ctrlrequest), GFP_ATOMIC, &kbd->cr_dma))) | ||
| 203 | return -1; | ||
| 204 | if (!(kbd->leds = usb_buffer_alloc(dev, 1, GFP_ATOMIC, &kbd->leds_dma))) | ||
| 205 | return -1; | ||
| 206 | |||
| 207 | return 0; | ||
| 208 | } | ||
| 209 | |||
| 210 | static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd) | ||
| 211 | { | ||
| 212 | usb_free_urb(kbd->irq); | ||
| 213 | usb_free_urb(kbd->led); | ||
| 214 | if (kbd->new) | ||
| 215 | usb_buffer_free(dev, 8, kbd->new, kbd->new_dma); | ||
| 216 | if (kbd->cr) | ||
| 217 | usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma); | ||
| 218 | if (kbd->leds) | ||
| 219 | usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma); | ||
| 220 | } | ||
| 221 | |||
| 222 | static int usb_kbd_probe(struct usb_interface *iface, | ||
| 223 | const struct usb_device_id *id) | ||
| 224 | { | ||
| 225 | struct usb_device *dev = interface_to_usbdev(iface); | ||
| 226 | struct usb_host_interface *interface; | ||
| 227 | struct usb_endpoint_descriptor *endpoint; | ||
| 228 | struct usb_kbd *kbd; | ||
| 229 | struct input_dev *input_dev; | ||
| 230 | int i, pipe, maxp; | ||
| 231 | |||
| 232 | interface = iface->cur_altsetting; | ||
| 233 | |||
| 234 | if (interface->desc.bNumEndpoints != 1) | ||
| 235 | return -ENODEV; | ||
| 236 | |||
| 237 | endpoint = &interface->endpoint[0].desc; | ||
| 238 | if (!usb_endpoint_is_int_in(endpoint)) | ||
| 239 | return -ENODEV; | ||
| 240 | |||
| 241 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | ||
| 242 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | ||
| 243 | |||
| 244 | kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL); | ||
| 245 | input_dev = input_allocate_device(); | ||
| 246 | if (!kbd || !input_dev) | ||
| 247 | goto fail1; | ||
| 248 | |||
| 249 | if (usb_kbd_alloc_mem(dev, kbd)) | ||
| 250 | goto fail2; | ||
| 251 | |||
| 252 | kbd->usbdev = dev; | ||
| 253 | kbd->dev = input_dev; | ||
| 254 | |||
| 255 | if (dev->manufacturer) | ||
| 256 | strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name)); | ||
| 257 | |||
| 258 | if (dev->product) { | ||
| 259 | if (dev->manufacturer) | ||
| 260 | strlcat(kbd->name, " ", sizeof(kbd->name)); | ||
| 261 | strlcat(kbd->name, dev->product, sizeof(kbd->name)); | ||
| 262 | } | ||
| 263 | |||
| 264 | if (!strlen(kbd->name)) | ||
| 265 | snprintf(kbd->name, sizeof(kbd->name), | ||
| 266 | "USB HIDBP Keyboard %04x:%04x", | ||
| 267 | le16_to_cpu(dev->descriptor.idVendor), | ||
| 268 | le16_to_cpu(dev->descriptor.idProduct)); | ||
| 269 | |||
| 270 | usb_make_path(dev, kbd->phys, sizeof(kbd->phys)); | ||
| 271 | strlcpy(kbd->phys, "/input0", sizeof(kbd->phys)); | ||
| 272 | |||
| 273 | input_dev->name = kbd->name; | ||
| 274 | input_dev->phys = kbd->phys; | ||
| 275 | usb_to_input_id(dev, &input_dev->id); | ||
| 276 | input_dev->cdev.dev = &iface->dev; | ||
| 277 | input_dev->private = kbd; | ||
| 278 | |||
| 279 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP); | ||
| 280 | input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA); | ||
| 281 | |||
| 282 | for (i = 0; i < 255; i++) | ||
| 283 | set_bit(usb_kbd_keycode[i], input_dev->keybit); | ||
| 284 | clear_bit(0, input_dev->keybit); | ||
| 285 | |||
| 286 | input_dev->event = usb_kbd_event; | ||
| 287 | input_dev->open = usb_kbd_open; | ||
| 288 | input_dev->close = usb_kbd_close; | ||
| 289 | |||
| 290 | usb_fill_int_urb(kbd->irq, dev, pipe, | ||
| 291 | kbd->new, (maxp > 8 ? 8 : maxp), | ||
| 292 | usb_kbd_irq, kbd, endpoint->bInterval); | ||
| 293 | kbd->irq->transfer_dma = kbd->new_dma; | ||
| 294 | kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
| 295 | |||
| 296 | kbd->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE; | ||
| 297 | kbd->cr->bRequest = 0x09; | ||
| 298 | kbd->cr->wValue = cpu_to_le16(0x200); | ||
| 299 | kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber); | ||
| 300 | kbd->cr->wLength = cpu_to_le16(1); | ||
| 301 | |||
| 302 | usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0), | ||
| 303 | (void *) kbd->cr, kbd->leds, 1, | ||
| 304 | usb_kbd_led, kbd); | ||
| 305 | kbd->led->setup_dma = kbd->cr_dma; | ||
| 306 | kbd->led->transfer_dma = kbd->leds_dma; | ||
| 307 | kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); | ||
| 308 | |||
| 309 | input_register_device(kbd->dev); | ||
| 310 | |||
| 311 | usb_set_intfdata(iface, kbd); | ||
| 312 | return 0; | ||
| 313 | |||
| 314 | fail2: usb_kbd_free_mem(dev, kbd); | ||
| 315 | fail1: input_free_device(input_dev); | ||
| 316 | kfree(kbd); | ||
| 317 | return -ENOMEM; | ||
| 318 | } | ||
| 319 | |||
| 320 | static void usb_kbd_disconnect(struct usb_interface *intf) | ||
| 321 | { | ||
| 322 | struct usb_kbd *kbd = usb_get_intfdata (intf); | ||
| 323 | |||
| 324 | usb_set_intfdata(intf, NULL); | ||
| 325 | if (kbd) { | ||
| 326 | usb_kill_urb(kbd->irq); | ||
| 327 | input_unregister_device(kbd->dev); | ||
| 328 | usb_kbd_free_mem(interface_to_usbdev(intf), kbd); | ||
| 329 | kfree(kbd); | ||
| 330 | } | ||
| 331 | } | ||
| 332 | |||
| 333 | static struct usb_device_id usb_kbd_id_table [] = { | ||
| 334 | { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, | ||
| 335 | USB_INTERFACE_PROTOCOL_KEYBOARD) }, | ||
| 336 | { } /* Terminating entry */ | ||
| 337 | }; | ||
| 338 | |||
| 339 | MODULE_DEVICE_TABLE (usb, usb_kbd_id_table); | ||
| 340 | |||
| 341 | static struct usb_driver usb_kbd_driver = { | ||
| 342 | .name = "usbkbd", | ||
| 343 | .probe = usb_kbd_probe, | ||
| 344 | .disconnect = usb_kbd_disconnect, | ||
| 345 | .id_table = usb_kbd_id_table, | ||
| 346 | }; | ||
| 347 | |||
| 348 | static int __init usb_kbd_init(void) | ||
| 349 | { | ||
| 350 | int result = usb_register(&usb_kbd_driver); | ||
| 351 | if (result == 0) | ||
| 352 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
| 353 | return result; | ||
| 354 | } | ||
| 355 | |||
| 356 | static void __exit usb_kbd_exit(void) | ||
| 357 | { | ||
| 358 | usb_deregister(&usb_kbd_driver); | ||
| 359 | } | ||
| 360 | |||
| 361 | module_init(usb_kbd_init); | ||
| 362 | module_exit(usb_kbd_exit); | ||
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c deleted file mode 100644 index 692fd6087779..000000000000 --- a/drivers/usb/input/usbmouse.c +++ /dev/null | |||
| @@ -1,245 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * $Id: usbmouse.c,v 1.15 2001/12/27 10:37:41 vojtech Exp $ | ||
| 3 | * | ||
| 4 | * Copyright (c) 1999-2001 Vojtech Pavlik | ||
| 5 | * | ||
| 6 | * USB HIDBP Mouse support | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or | ||
| 13 | * (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * GNU General Public License for more details. | ||
| 19 | * | ||
| 20 | * You should have received a copy of the GNU General Public License | ||
| 21 | * along with this program; if not, write to the Free Software | ||
| 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 23 | * | ||
| 24 | * Should you need to contact me, the author, you can do so either by | ||
| 25 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | ||
| 26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | ||
| 27 | */ | ||
| 28 | |||
| 29 | #include <linux/kernel.h> | ||
| 30 | #include <linux/slab.h> | ||
| 31 | #include <linux/module.h> | ||
| 32 | #include <linux/init.h> | ||
| 33 | #include <linux/usb/input.h> | ||
| 34 | #include <linux/hid.h> | ||
| 35 | |||
| 36 | /* | ||
| 37 | * Version Information | ||
| 38 | */ | ||
| 39 | #define DRIVER_VERSION "v1.6" | ||
| 40 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | ||
| 41 | #define DRIVER_DESC "USB HID Boot Protocol mouse driver" | ||
| 42 | #define DRIVER_LICENSE "GPL" | ||
| 43 | |||
| 44 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
| 45 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 46 | MODULE_LICENSE(DRIVER_LICENSE); | ||
| 47 | |||
| 48 | struct usb_mouse { | ||
| 49 | char name[128]; | ||
| 50 | char phys[64]; | ||
| 51 | struct usb_device *usbdev; | ||
| 52 | struct input_dev *dev; | ||
| 53 | struct urb *irq; | ||
| 54 | |||
| 55 | signed char *data; | ||
| 56 | dma_addr_t data_dma; | ||
| 57 | }; | ||
| 58 | |||
| 59 | static void usb_mouse_irq(struct urb *urb) | ||
| 60 | { | ||
| 61 | struct usb_mouse *mouse = urb->context; | ||
| 62 | signed char *data = mouse->data; | ||
| 63 | struct input_dev *dev = mouse->dev; | ||
| 64 | int status; | ||
| 65 | |||
| 66 | switch (urb->status) { | ||
| 67 | case 0: /* success */ | ||
| 68 | break; | ||
| 69 | case -ECONNRESET: /* unlink */ | ||
| 70 | case -ENOENT: | ||
| 71 | case -ESHUTDOWN: | ||
| 72 | return; | ||
| 73 | /* -EPIPE: should clear the halt */ | ||
| 74 | default: /* error */ | ||
| 75 | goto resubmit; | ||
| 76 | } | ||
| 77 | |||
| 78 | input_report_key(dev, BTN_LEFT, data[0] & 0x01); | ||
| 79 | input_report_key(dev, BTN_RIGHT, data[0] & 0x02); | ||
| 80 | input_report_key(dev, BTN_MIDDLE, data[0] & 0x04); | ||
| 81 | input_report_key(dev, BTN_SIDE, data[0] & 0x08); | ||
| 82 | input_report_key(dev, BTN_EXTRA, data[0] & 0x10); | ||
| 83 | |||
| 84 | input_report_rel(dev, REL_X, data[1]); | ||
| 85 | input_report_rel(dev, REL_Y, data[2]); | ||
| 86 | input_report_rel(dev, REL_WHEEL, data[3]); | ||
| 87 | |||
| 88 | input_sync(dev); | ||
| 89 | resubmit: | ||
| 90 | status = usb_submit_urb (urb, GFP_ATOMIC); | ||
| 91 | if (status) | ||
| 92 | err ("can't resubmit intr, %s-%s/input0, status %d", | ||
| 93 | mouse->usbdev->bus->bus_name, | ||
| 94 | mouse->usbdev->devpath, status); | ||
| 95 | } | ||
| 96 | |||
| 97 | static int usb_mouse_open(struct input_dev *dev) | ||
| 98 | { | ||
| 99 | struct usb_mouse *mouse = dev->private; | ||
| 100 | |||
| 101 | mouse->irq->dev = mouse->usbdev; | ||
| 102 | if (usb_submit_urb(mouse->irq, GFP_KERNEL)) | ||
| 103 | return -EIO; | ||
| 104 | |||
| 105 | return 0; | ||
| 106 | } | ||
| 107 | |||
| 108 | static void usb_mouse_close(struct input_dev *dev) | ||
| 109 | { | ||
| 110 | struct usb_mouse *mouse = dev->private; | ||
| 111 | |||
| 112 | usb_kill_urb(mouse->irq); | ||
| 113 | } | ||
| 114 | |||
| 115 | static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
| 116 | { | ||
| 117 | struct usb_device *dev = interface_to_usbdev(intf); | ||
| 118 | struct usb_host_interface *interface; | ||
| 119 | struct usb_endpoint_descriptor *endpoint; | ||
| 120 | struct usb_mouse *mouse; | ||
| 121 | struct input_dev *input_dev; | ||
| 122 | int pipe, maxp; | ||
| 123 | |||
| 124 | interface = intf->cur_altsetting; | ||
| 125 | |||
| 126 | if (interface->desc.bNumEndpoints != 1) | ||
| 127 | return -ENODEV; | ||
| 128 | |||
| 129 | endpoint = &interface->endpoint[0].desc; | ||
| 130 | if (!usb_endpoint_is_int_in(endpoint)) | ||
| 131 | return -ENODEV; | ||
| 132 | |||
| 133 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | ||
| 134 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | ||
| 135 | |||
| 136 | mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL); | ||
| 137 | input_dev = input_allocate_device(); | ||
| 138 | if (!mouse || !input_dev) | ||
| 139 | goto fail1; | ||
| 140 | |||
| 141 | mouse->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &mouse->data_dma); | ||
| 142 | if (!mouse->data) | ||
| 143 | goto fail1; | ||
| 144 | |||
| 145 | mouse->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
| 146 | if (!mouse->irq) | ||
| 147 | goto fail2; | ||
| 148 | |||
| 149 | mouse->usbdev = dev; | ||
| 150 | mouse->dev = input_dev; | ||
| 151 | |||
| 152 | if (dev->manufacturer) | ||
| 153 | strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name)); | ||
| 154 | |||
| 155 | if (dev->product) { | ||
| 156 | if (dev->manufacturer) | ||
| 157 | strlcat(mouse->name, " ", sizeof(mouse->name)); | ||
| 158 | strlcat(mouse->name, dev->product, sizeof(mouse->name)); | ||
| 159 | } | ||
| 160 | |||
| 161 | if (!strlen(mouse->name)) | ||
| 162 | snprintf(mouse->name, sizeof(mouse->name), | ||
| 163 | "USB HIDBP Mouse %04x:%04x", | ||
| 164 | le16_to_cpu(dev->descriptor.idVendor), | ||
| 165 | le16_to_cpu(dev->descriptor.idProduct)); | ||
| 166 | |||
| 167 | usb_make_path(dev, mouse->phys, sizeof(mouse->phys)); | ||
| 168 | strlcat(mouse->phys, "/input0", sizeof(mouse->phys)); | ||
| 169 | |||
| 170 | input_dev->name = mouse->name; | ||
| 171 | input_dev->phys = mouse->phys; | ||
| 172 | usb_to_input_id(dev, &input_dev->id); | ||
| 173 | input_dev->cdev.dev = &intf->dev; | ||
| 174 | |||
| 175 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | ||
| 176 | input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
| 177 | input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
| 178 | input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA); | ||
| 179 | input_dev->relbit[0] |= BIT(REL_WHEEL); | ||
| 180 | |||
| 181 | input_dev->private = mouse; | ||
| 182 | input_dev->open = usb_mouse_open; | ||
| 183 | input_dev->close = usb_mouse_close; | ||
| 184 | |||
| 185 | usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data, | ||
| 186 | (maxp > 8 ? 8 : maxp), | ||
| 187 | usb_mouse_irq, mouse, endpoint->bInterval); | ||
| 188 | mouse->irq->transfer_dma = mouse->data_dma; | ||
| 189 | mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
| 190 | |||
| 191 | input_register_device(mouse->dev); | ||
| 192 | |||
| 193 | usb_set_intfdata(intf, mouse); | ||
| 194 | return 0; | ||
| 195 | |||
| 196 | fail2: usb_buffer_free(dev, 8, mouse->data, mouse->data_dma); | ||
| 197 | fail1: input_free_device(input_dev); | ||
| 198 | kfree(mouse); | ||
| 199 | return -ENOMEM; | ||
| 200 | } | ||
| 201 | |||
| 202 | static void usb_mouse_disconnect(struct usb_interface *intf) | ||
| 203 | { | ||
| 204 | struct usb_mouse *mouse = usb_get_intfdata (intf); | ||
| 205 | |||
| 206 | usb_set_intfdata(intf, NULL); | ||
| 207 | if (mouse) { | ||
| 208 | usb_kill_urb(mouse->irq); | ||
| 209 | input_unregister_device(mouse->dev); | ||
| 210 | usb_free_urb(mouse->irq); | ||
| 211 | usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma); | ||
| 212 | kfree(mouse); | ||
| 213 | } | ||
| 214 | } | ||
| 215 | |||
| 216 | static struct usb_device_id usb_mouse_id_table [] = { | ||
| 217 | { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, | ||
| 218 | USB_INTERFACE_PROTOCOL_MOUSE) }, | ||
| 219 | { } /* Terminating entry */ | ||
| 220 | }; | ||
| 221 | |||
| 222 | MODULE_DEVICE_TABLE (usb, usb_mouse_id_table); | ||
| 223 | |||
| 224 | static struct usb_driver usb_mouse_driver = { | ||
| 225 | .name = "usbmouse", | ||
| 226 | .probe = usb_mouse_probe, | ||
| 227 | .disconnect = usb_mouse_disconnect, | ||
| 228 | .id_table = usb_mouse_id_table, | ||
| 229 | }; | ||
| 230 | |||
| 231 | static int __init usb_mouse_init(void) | ||
| 232 | { | ||
| 233 | int retval = usb_register(&usb_mouse_driver); | ||
| 234 | if (retval == 0) | ||
| 235 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
| 236 | return retval; | ||
| 237 | } | ||
| 238 | |||
| 239 | static void __exit usb_mouse_exit(void) | ||
| 240 | { | ||
| 241 | usb_deregister(&usb_mouse_driver); | ||
| 242 | } | ||
| 243 | |||
| 244 | module_init(usb_mouse_init); | ||
| 245 | module_exit(usb_mouse_exit); | ||
