aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-07-24 16:30:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-24 16:30:14 -0400
commite8ff13b0bf88b5e696323a1eec877783d965b3c6 (patch)
treeaa55093da5ee435f0d2fa8ffede8973f426dbd67
parent0cd5ff591ab6473355d5a6a47f7694def28e451d (diff)
parentc062c4d1de57789bf15f7641a24c429eeb8a1c6a (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID updates from Jiri Kosina: "The list of changes worth pointing out explicitly: - We are getting 'UHID', which is a new framework for implementing HID transport drivers in userspace (this is different from HIDRAW, which is transport-independent and provides report parsing facilities; uhid is for the other (transport) part of the pipeline). It's needed for (and currently being used by) Bluetooth-LowEnergy, as its specification mandates things we don't want in the kernel. Written by David Herrmann. - there have been quite a few bugs in runtime suspend/resume paths (probably never reported to actually happen in the wild, but still). Alan Stern fixed those. - a few other driver updates and fixes and random new device support." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (45 commits) HID: add ASUS AIO keyboard model AK1D HID: add support for Cypress barcode scanner 04B4:ED81 HID: Allow drivers to be their own listener HID: usbhid: fix error paths in suspend HID: usbhid: check for suspend or reset before restarting HID: usbhid: replace HID_REPORTED_IDLE with HID_SUSPENDED HID: usbhid: inline some simple routines HID: usbhid: fix autosuspend calls HID: usbhid: fix use-after-free bug HID: hid-core: optimize in case of hidraw HID: hidraw: fix list->buffer memleak HID: uhid: Fix sending events with invalid data HID: roccat: added sensor sysfs attribute for Savu HID: Add driver for Holtek based keyboards with broken HID HID: Add suport for the brightness control keys on HP keyboards HID: magicmouse: Implement Multi-touch Protocol B (MT-B) HID: magicmouse: Removing report_touches switch HID: roccat: rename roccat_common functions to roccat_common2 HID: roccat: fix wrong hid_err usage on struct usb_device HID: roccat: move functionality to roccat-common ...
-rw-r--r--Documentation/ABI/testing/sysfs-driver-hid-lenovo-tpkbd38
-rw-r--r--Documentation/ABI/testing/sysfs-driver-hid-roccat-savu77
-rw-r--r--Documentation/hid/uhid.txt169
-rw-r--r--MAINTAINERS7
-rw-r--r--drivers/hid/Kconfig40
-rw-r--r--drivers/hid/Makefile6
-rw-r--r--drivers/hid/hid-chicony.c1
-rw-r--r--drivers/hid/hid-core.c21
-rw-r--r--drivers/hid/hid-cypress.c2
-rw-r--r--drivers/hid/hid-holtek-kbd.c183
-rw-r--r--drivers/hid/hid-ids.h12
-rw-r--r--drivers/hid/hid-input.c9
-rw-r--r--drivers/hid/hid-lenovo-tpkbd.c564
-rw-r--r--drivers/hid/hid-magicmouse.c157
-rw-r--r--drivers/hid/hid-multitouch.c18
-rw-r--r--drivers/hid/hid-picolcd.c6
-rw-r--r--drivers/hid/hid-roccat-arvo.c16
-rw-r--r--drivers/hid/hid-roccat-common.c72
-rw-r--r--drivers/hid/hid-roccat-common.h16
-rw-r--r--drivers/hid/hid-roccat-isku.c52
-rw-r--r--drivers/hid/hid-roccat-isku.h7
-rw-r--r--drivers/hid/hid-roccat-kone.c6
-rw-r--r--drivers/hid/hid-roccat-koneplus.c98
-rw-r--r--drivers/hid/hid-roccat-koneplus.h22
-rw-r--r--drivers/hid/hid-roccat-kovaplus.c71
-rw-r--r--drivers/hid/hid-roccat-kovaplus.h15
-rw-r--r--drivers/hid/hid-roccat-pyra.c59
-rw-r--r--drivers/hid/hid-roccat-pyra.h12
-rw-r--r--drivers/hid/hid-roccat-savu.c316
-rw-r--r--drivers/hid/hid-roccat-savu.h87
-rw-r--r--drivers/hid/hid-wiimote-ext.c2
-rw-r--r--drivers/hid/hidraw.c12
-rw-r--r--drivers/hid/uhid.c572
-rw-r--r--drivers/hid/usbhid/hid-core.c294
-rw-r--r--drivers/hid/usbhid/usbhid.h1
-rw-r--r--include/linux/Kbuild1
-rw-r--r--include/linux/hid.h1
-rw-r--r--include/linux/uhid.h104
-rw-r--r--samples/uhid/Makefile10
-rw-r--r--samples/uhid/uhid-example.c381
40 files changed, 2983 insertions, 554 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-lenovo-tpkbd b/Documentation/ABI/testing/sysfs-driver-hid-lenovo-tpkbd
new file mode 100644
index 000000000000..57b92cbdceae
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-hid-lenovo-tpkbd
@@ -0,0 +1,38 @@
1What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/press_to_select
2Date: July 2011
3Contact: linux-input@vger.kernel.org
4Description: This controls if mouse clicks should be generated if the trackpoint is quickly pressed. How fast this press has to be
5 is being controlled by press_speed.
6 Values are 0 or 1.
7
8What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/dragging
9Date: July 2011
10Contact: linux-input@vger.kernel.org
11Description: If this setting is enabled, it is possible to do dragging by pressing the trackpoint. This requires press_to_select to be enabled.
12 Values are 0 or 1.
13
14What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/release_to_select
15Date: July 2011
16Contact: linux-input@vger.kernel.org
17Description: For details regarding this setting please refer to http://www.pc.ibm.com/ww/healthycomputing/trkpntb.html
18 Values are 0 or 1.
19
20What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/select_right
21Date: July 2011
22Contact: linux-input@vger.kernel.org
23Description: This setting controls if the mouse click events generated by pressing the trackpoint (if press_to_select is enabled) generate
24 a left or right mouse button click.
25 Values are 0 or 1.
26
27What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/sensitivity
28Date: July 2011
29Contact: linux-input@vger.kernel.org
30Description: This file contains the trackpoint sensitivity.
31 Values are decimal integers from 1 (lowest sensitivity) to 255 (highest sensitivity).
32
33What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/press_speed
34Date: July 2011
35Contact: linux-input@vger.kernel.org
36Description: This setting controls how fast the trackpoint needs to be pressed to generate a mouse click if press_to_select is enabled.
37 Values are decimal integers from 1 (slowest) to 255 (fastest).
38
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu b/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu
new file mode 100644
index 000000000000..b42922cf6b1f
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu
@@ -0,0 +1,77 @@
1What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/buttons
2Date: Mai 2012
3Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
4Description: The mouse can store 5 profiles which can be switched by the
5 press of a button. A profile is split into general settings and
6 button settings. buttons holds informations about button layout.
7 When written, this file lets one write the respective profile
8 buttons to the mouse. The data has to be 47 bytes long.
9 The mouse will reject invalid data.
10 Which profile to write is determined by the profile number
11 contained in the data.
12 Before reading this file, control has to be written to select
13 which profile to read.
14Users: http://roccat.sourceforge.net
15
16What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/control
17Date: Mai 2012
18Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
19Description: When written, this file lets one select which data from which
20 profile will be read next. The data has to be 3 bytes long.
21 This file is writeonly.
22Users: http://roccat.sourceforge.net
23
24What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/general
25Date: Mai 2012
26Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
27Description: The mouse can store 5 profiles which can be switched by the
28 press of a button. A profile is split into general settings and
29 button settings. profile holds informations like resolution, sensitivity
30 and light effects.
31 When written, this file lets one write the respective profile
32 settings back to the mouse. The data has to be 43 bytes long.
33 The mouse will reject invalid data.
34 Which profile to write is determined by the profile number
35 contained in the data.
36 This file is writeonly.
37Users: http://roccat.sourceforge.net
38
39What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/info
40Date: Mai 2012
41Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
42Description: When read, this file returns general data like firmware version.
43 The data is 8 bytes long.
44 This file is readonly.
45Users: http://roccat.sourceforge.net
46
47What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/macro
48Date: Mai 2012
49Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
50Description: When written, this file lets one store macros with max 500
51 keystrokes for a specific button for a specific profile.
52 Button and profile numbers are included in written data.
53 The data has to be 2083 bytes long.
54 Before reading this file, control has to be written to select
55 which profile and key to read.
56Users: http://roccat.sourceforge.net
57
58What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/profile
59Date: Mai 2012
60Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
61Description: The mouse can store 5 profiles which can be switched by the
62 press of a button. profile holds number of actual profile.
63 This value is persistent, so its value determines the profile
64 that's active when the mouse is powered on next time.
65 When written, the mouse activates the set profile immediately.
66 The data has to be 3 bytes long.
67 The mouse will reject invalid data.
68Users: http://roccat.sourceforge.net
69
70What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/sensor
71Date: July 2012
72Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
73Description: The mouse has a Avago ADNS-3090 sensor.
74 This file allows reading and writing of the mouse sensors registers.
75 The data has to be 4 bytes long.
76Users: http://roccat.sourceforge.net
77
diff --git a/Documentation/hid/uhid.txt b/Documentation/hid/uhid.txt
new file mode 100644
index 000000000000..4627c4241ece
--- /dev/null
+++ b/Documentation/hid/uhid.txt
@@ -0,0 +1,169 @@
1 UHID - User-space I/O driver support for HID subsystem
2 ========================================================
3
4The HID subsystem needs two kinds of drivers. In this document we call them:
5
6 1. The "HID I/O Driver" is the driver that performs raw data I/O to the
7 low-level device. Internally, they register an hid_ll_driver structure with
8 the HID core. They perform device setup, read raw data from the device and
9 push it into the HID subsystem and they provide a callback so the HID
10 subsystem can send data to the device.
11
12 2. The "HID Device Driver" is the driver that parses HID reports and reacts on
13 them. There are generic drivers like "generic-usb" and "generic-bluetooth"
14 which adhere to the HID specification and provide the standardizes features.
15 But there may be special drivers and quirks for each non-standard device out
16 there. Internally, they use the hid_driver structure.
17
18Historically, the USB stack was the first subsystem to provide an HID I/O
19Driver. However, other standards like Bluetooth have adopted the HID specs and
20may provide HID I/O Drivers, too. The UHID driver allows to implement HID I/O
21Drivers in user-space and feed the data into the kernel HID-subsystem.
22
23This allows user-space to operate on the same level as USB-HID, Bluetooth-HID
24and similar. It does not provide a way to write HID Device Drivers, though. Use
25hidraw for this purpose.
26
27There is an example user-space application in ./samples/uhid/uhid-example.c
28
29The UHID API
30------------
31
32UHID is accessed through a character misc-device. The minor-number is allocated
33dynamically so you need to rely on udev (or similar) to create the device node.
34This is /dev/uhid by default.
35
36If a new device is detected by your HID I/O Driver and you want to register this
37device with the HID subsystem, then you need to open /dev/uhid once for each
38device you want to register. All further communication is done by read()'ing or
39write()'ing "struct uhid_event" objects. Non-blocking operations are supported
40by setting O_NONBLOCK.
41
42struct uhid_event {
43 __u32 type;
44 union {
45 struct uhid_create_req create;
46 struct uhid_data_req data;
47 ...
48 } u;
49};
50
51The "type" field contains the ID of the event. Depending on the ID different
52payloads are sent. You must not split a single event across multiple read()'s or
53multiple write()'s. A single event must always be sent as a whole. Furthermore,
54only a single event can be sent per read() or write(). Pending data is ignored.
55If you want to handle multiple events in a single syscall, then use vectored
56I/O with readv()/writev().
57
58The first thing you should do is sending an UHID_CREATE event. This will
59register the device. UHID will respond with an UHID_START event. You can now
60start sending data to and reading data from UHID. However, unless UHID sends the
61UHID_OPEN event, the internally attached HID Device Driver has no user attached.
62That is, you might put your device asleep unless you receive the UHID_OPEN
63event. If you receive the UHID_OPEN event, you should start I/O. If the last
64user closes the HID device, you will receive an UHID_CLOSE event. This may be
65followed by an UHID_OPEN event again and so on. There is no need to perform
66reference-counting in user-space. That is, you will never receive multiple
67UHID_OPEN events without an UHID_CLOSE event. The HID subsystem performs
68ref-counting for you.
69You may decide to ignore UHID_OPEN/UHID_CLOSE, though. I/O is allowed even
70though the device may have no users.
71
72If you want to send data to the HID subsystem, you send an HID_INPUT event with
73your raw data payload. If the kernel wants to send data to the device, you will
74read an UHID_OUTPUT or UHID_OUTPUT_EV event.
75
76If your device disconnects, you should send an UHID_DESTROY event. This will
77unregister the device. You can now send UHID_CREATE again to register a new
78device.
79If you close() the fd, the device is automatically unregistered and destroyed
80internally.
81
82write()
83-------
84write() allows you to modify the state of the device and feed input data into
85the kernel. The following types are supported: UHID_CREATE, UHID_DESTROY and
86UHID_INPUT. The kernel will parse the event immediately and if the event ID is
87not supported, it will return -EOPNOTSUPP. If the payload is invalid, then
88-EINVAL is returned, otherwise, the amount of data that was read is returned and
89the request was handled successfully.
90
91 UHID_CREATE:
92 This creates the internal HID device. No I/O is possible until you send this
93 event to the kernel. The payload is of type struct uhid_create_req and
94 contains information about your device. You can start I/O now.
95
96 UHID_DESTROY:
97 This destroys the internal HID device. No further I/O will be accepted. There
98 may still be pending messages that you can receive with read() but no further
99 UHID_INPUT events can be sent to the kernel.
100 You can create a new device by sending UHID_CREATE again. There is no need to
101 reopen the character device.
102
103 UHID_INPUT:
104 You must send UHID_CREATE before sending input to the kernel! This event
105 contains a data-payload. This is the raw data that you read from your device.
106 The kernel will parse the HID reports and react on it.
107
108 UHID_FEATURE_ANSWER:
109 If you receive a UHID_FEATURE request you must answer with this request. You
110 must copy the "id" field from the request into the answer. Set the "err" field
111 to 0 if no error occured or to EIO if an I/O error occurred.
112 If "err" is 0 then you should fill the buffer of the answer with the results
113 of the feature request and set "size" correspondingly.
114
115read()
116------
117read() will return a queued ouput report. These output reports can be of type
118UHID_START, UHID_STOP, UHID_OPEN, UHID_CLOSE, UHID_OUTPUT or UHID_OUTPUT_EV. No
119reaction is required to any of them but you should handle them according to your
120needs. Only UHID_OUTPUT and UHID_OUTPUT_EV have payloads.
121
122 UHID_START:
123 This is sent when the HID device is started. Consider this as an answer to
124 UHID_CREATE. This is always the first event that is sent.
125
126 UHID_STOP:
127 This is sent when the HID device is stopped. Consider this as an answer to
128 UHID_DESTROY.
129 If the kernel HID device driver closes the device manually (that is, you
130 didn't send UHID_DESTROY) then you should consider this device closed and send
131 an UHID_DESTROY event. You may want to reregister your device, though. This is
132 always the last message that is sent to you unless you reopen the device with
133 UHID_CREATE.
134
135 UHID_OPEN:
136 This is sent when the HID device is opened. That is, the data that the HID
137 device provides is read by some other process. You may ignore this event but
138 it is useful for power-management. As long as you haven't received this event
139 there is actually no other process that reads your data so there is no need to
140 send UHID_INPUT events to the kernel.
141
142 UHID_CLOSE:
143 This is sent when there are no more processes which read the HID data. It is
144 the counterpart of UHID_OPEN and you may as well ignore this event.
145
146 UHID_OUTPUT:
147 This is sent if the HID device driver wants to send raw data to the I/O
148 device. You should read the payload and forward it to the device. The payload
149 is of type "struct uhid_data_req".
150 This may be received even though you haven't received UHID_OPEN, yet.
151
152 UHID_OUTPUT_EV:
153 Same as UHID_OUTPUT but this contains a "struct input_event" as payload. This
154 is called for force-feedback, LED or similar events which are received through
155 an input device by the HID subsystem. You should convert this into raw reports
156 and send them to your device similar to events of type UHID_OUTPUT.
157
158 UHID_FEATURE:
159 This event is sent if the kernel driver wants to perform a feature request as
160 described in the HID specs. The report-type and report-number are available in
161 the payload.
162 The kernel serializes feature requests so there will never be two in parallel.
163 However, if you fail to respond with a UHID_FEATURE_ANSWER in a time-span of 5
164 seconds, then the requests will be dropped and a new one might be sent.
165 Therefore, the payload also contains an "id" field that identifies every
166 request.
167
168Document by:
169 David Herrmann <dh.herrmann@googlemail.com>
diff --git a/MAINTAINERS b/MAINTAINERS
index cda045337a9d..04ea1f23756f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6965,6 +6965,13 @@ S: Maintained
6965F: Documentation/filesystems/ufs.txt 6965F: Documentation/filesystems/ufs.txt
6966F: fs/ufs/ 6966F: fs/ufs/
6967 6967
6968UHID USERSPACE HID IO DRIVER:
6969M: David Herrmann <dh.herrmann@googlemail.com>
6970L: linux-input@vger.kernel.org
6971S: Maintained
6972F: drivers/hid/uhid.c
6973F: include/linux/uhid.h
6974
6968ULTRA-WIDEBAND (UWB) SUBSYSTEM: 6975ULTRA-WIDEBAND (UWB) SUBSYSTEM:
6969L: linux-usb@vger.kernel.org 6976L: linux-usb@vger.kernel.org
6970S: Orphan 6977S: Orphan
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 3fda8c87f02c..fbf49503508d 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -53,6 +53,27 @@ config HIDRAW
53 53
54 If unsure, say Y. 54 If unsure, say Y.
55 55
56config UHID
57 tristate "User-space I/O driver support for HID subsystem"
58 depends on HID
59 default n
60 ---help---
61 Say Y here if you want to provide HID I/O Drivers from user-space.
62 This allows to write I/O drivers in user-space and feed the data from
63 the device into the kernel. The kernel parses the HID reports, loads the
64 corresponding HID Device Driver or provides input devices on top of your
65 user-space device.
66
67 This driver cannot be used to parse HID-reports in user-space and write
68 special HID-drivers. You should use hidraw for that.
69 Instead, this driver allows to write the transport-layer driver in
70 user-space like USB-HID and Bluetooth-HID do in kernel-space.
71
72 If unsure, say N.
73
74 To compile this driver as a module, choose M here: the
75 module will be called uhid.
76
56config HID_GENERIC 77config HID_GENERIC
57 tristate "Generic HID driver" 78 tristate "Generic HID driver"
58 depends on HID 79 depends on HID
@@ -193,10 +214,12 @@ config HID_EZKEY
193 Support for Ezkey BTC 8193 keyboard. 214 Support for Ezkey BTC 8193 keyboard.
194 215
195config HID_HOLTEK 216config HID_HOLTEK
196 tristate "Holtek On Line Grip based game controller support" 217 tristate "Holtek HID devices"
197 depends on USB_HID 218 depends on USB_HID
198 ---help--- 219 ---help---
199 Say Y here if you have a Holtek On Line Grip based game controller. 220 Support for Holtek based devices:
221 - Holtek On Line Grip based game controller
222 - Trust GXT 18 Gaming Keyboard
200 223
201config HOLTEK_FF 224config HOLTEK_FF
202 bool "Holtek On Line Grip force feedback support" 225 bool "Holtek On Line Grip force feedback support"
@@ -261,6 +284,19 @@ config HID_LCPOWER
261 ---help--- 284 ---help---
262 Support for LC-Power RC1000MCE RF remote control. 285 Support for LC-Power RC1000MCE RF remote control.
263 286
287config HID_LENOVO_TPKBD
288 tristate "Lenovo ThinkPad USB Keyboard with TrackPoint"
289 depends on USB_HID
290 select NEW_LEDS
291 select LEDS_CLASS
292 ---help---
293 Support for the Lenovo ThinkPad USB Keyboard with TrackPoint.
294
295 Say Y here if you have a Lenovo ThinkPad USB Keyboard with TrackPoint
296 and would like to use device-specific features like changing the
297 sensitivity of the trackpoint, using the microphone mute button or
298 controlling the mute and microphone mute LEDs.
299
264config HID_LOGITECH 300config HID_LOGITECH
265 tristate "Logitech devices" if EXPERT 301 tristate "Logitech devices" if EXPERT
266 depends on USB_HID 302 depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index ca6cc9f0485c..f975485f88b2 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -8,6 +8,7 @@ ifdef CONFIG_DEBUG_FS
8endif 8endif
9 9
10obj-$(CONFIG_HID) += hid.o 10obj-$(CONFIG_HID) += hid.o
11obj-$(CONFIG_UHID) += uhid.o
11 12
12obj-$(CONFIG_HID_GENERIC) += hid-generic.o 13obj-$(CONFIG_HID_GENERIC) += hid-generic.o
13 14
@@ -48,12 +49,14 @@ obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o
48obj-$(CONFIG_HID_ELECOM) += hid-elecom.o 49obj-$(CONFIG_HID_ELECOM) += hid-elecom.o
49obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o 50obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
50obj-$(CONFIG_HID_GYRATION) += hid-gyration.o 51obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
52obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
51obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o 53obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o
52obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o 54obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o
53obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o 55obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
54obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o 56obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o
55obj-$(CONFIG_HID_KYE) += hid-kye.o 57obj-$(CONFIG_HID_KYE) += hid-kye.o
56obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o 58obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o
59obj-$(CONFIG_HID_LENOVO_TPKBD) += hid-lenovo-tpkbd.o
57obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o 60obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
58obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o 61obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o
59obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o 62obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o
@@ -69,7 +72,8 @@ obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o
69obj-$(CONFIG_HID_PRIMAX) += hid-primax.o 72obj-$(CONFIG_HID_PRIMAX) += hid-primax.o
70obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ 73obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \
71 hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ 74 hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
72 hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-pyra.o 75 hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-pyra.o \
76 hid-roccat-savu.o
73obj-$(CONFIG_HID_SAITEK) += hid-saitek.o 77obj-$(CONFIG_HID_SAITEK) += hid-saitek.o
74obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o 78obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
75obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o 79obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
diff --git a/drivers/hid/hid-chicony.c b/drivers/hid/hid-chicony.c
index b99af346fdff..a2abb8e15727 100644
--- a/drivers/hid/hid-chicony.c
+++ b/drivers/hid/hid-chicony.c
@@ -60,6 +60,7 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
60static const struct hid_device_id ch_devices[] = { 60static const struct hid_device_id ch_devices[] = {
61 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, 61 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
62 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, 62 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
63 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
63 { } 64 { }
64}; 65};
65MODULE_DEVICE_TABLE(hid, ch_devices); 66MODULE_DEVICE_TABLE(hid, ch_devices);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 4c87276c8ddb..500844f04f93 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1194,8 +1194,10 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
1194 goto out; 1194 goto out;
1195 } 1195 }
1196 1196
1197 for (a = 0; a < report->maxfield; a++) 1197 if (hid->claimed != HID_CLAIMED_HIDRAW) {
1198 hid_input_field(hid, report->field[a], cdata, interrupt); 1198 for (a = 0; a < report->maxfield; a++)
1199 hid_input_field(hid, report->field[a], cdata, interrupt);
1200 }
1199 1201
1200 if (hid->claimed & HID_CLAIMED_INPUT) 1202 if (hid->claimed & HID_CLAIMED_INPUT)
1201 hidinput_report_event(hid, report); 1203 hidinput_report_event(hid, report);
@@ -1243,6 +1245,10 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
1243 goto unlock; 1245 goto unlock;
1244 } 1246 }
1245 1247
1248 /* Avoid unnecessary overhead if debugfs is disabled */
1249 if (list_empty(&hid->debug_list))
1250 goto nomem;
1251
1246 buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC); 1252 buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
1247 1253
1248 if (!buf) 1254 if (!buf)
@@ -1373,8 +1379,10 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
1373 if ((connect_mask & HID_CONNECT_HIDRAW) && !hidraw_connect(hdev)) 1379 if ((connect_mask & HID_CONNECT_HIDRAW) && !hidraw_connect(hdev))
1374 hdev->claimed |= HID_CLAIMED_HIDRAW; 1380 hdev->claimed |= HID_CLAIMED_HIDRAW;
1375 1381
1376 if (!hdev->claimed) { 1382 /* Drivers with the ->raw_event callback set are not required to connect
1377 hid_err(hdev, "claimed by neither input, hiddev nor hidraw\n"); 1383 * to any other listener. */
1384 if (!hdev->claimed && !hdev->driver->raw_event) {
1385 hid_err(hdev, "device has no listeners, quitting\n");
1378 return -ENODEV; 1386 return -ENODEV;
1379 } 1387 }
1380 1388
@@ -1521,10 +1529,12 @@ static const struct hid_device_id hid_have_special_driver[] = {
1521 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, 1529 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
1522 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, 1530 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
1523 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, 1531 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
1532 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
1524 { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, 1533 { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
1525 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, 1534 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
1526 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, 1535 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
1527 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) }, 1536 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) },
1537 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_4) },
1528 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, 1538 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
1529 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, 1539 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
1530 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, 1540 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) },
@@ -1539,6 +1549,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1539 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, 1549 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
1540 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, 1550 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
1541 { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, 1551 { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) },
1552 { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) },
1542 { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, 1553 { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
1543 { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, 1554 { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
1544 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, 1555 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
@@ -1547,6 +1558,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1547 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) }, 1558 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) },
1548 { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, 1559 { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
1549 { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) }, 1560 { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
1561 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
1550 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, 1562 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
1551 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, 1563 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
1552 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, 1564 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
@@ -1620,6 +1632,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1620 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, 1632 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
1621 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, 1633 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
1622 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) }, 1634 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) },
1635 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) },
1623 { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, 1636 { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) },
1624 { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, 1637 { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
1625 { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, 1638 { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c
index 2f0be4c66af7..9e43aaca9774 100644
--- a/drivers/hid/hid-cypress.c
+++ b/drivers/hid/hid-cypress.c
@@ -129,6 +129,8 @@ static const struct hid_device_id cp_devices[] = {
129 .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, 129 .driver_data = CP_RDESC_SWAPPED_MIN_MAX },
130 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3), 130 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3),
131 .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, 131 .driver_data = CP_RDESC_SWAPPED_MIN_MAX },
132 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_4),
133 .driver_data = CP_RDESC_SWAPPED_MIN_MAX },
132 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE), 134 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE),
133 .driver_data = CP_2WHEEL_MOUSE_HACK }, 135 .driver_data = CP_2WHEEL_MOUSE_HACK },
134 { } 136 { }
diff --git a/drivers/hid/hid-holtek-kbd.c b/drivers/hid/hid-holtek-kbd.c
new file mode 100644
index 000000000000..e0a5d1739fc3
--- /dev/null
+++ b/drivers/hid/hid-holtek-kbd.c
@@ -0,0 +1,183 @@
1/*
2 * HID driver for Holtek keyboard
3 * Copyright (c) 2012 Tom Harwood
4*/
5
6/*
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 */
12
13#include <linux/device.h>
14#include <linux/hid.h>
15#include <linux/module.h>
16#include <linux/usb.h>
17
18#include "hid-ids.h"
19#include "usbhid/usbhid.h"
20
21/* Holtek based keyboards (USB ID 04d9:a055) have the following issues:
22 * - The report descriptor specifies an excessively large number of consumer
23 * usages (2^15), which is more than HID_MAX_USAGES. This prevents proper
24 * parsing of the report descriptor.
25 * - The report descriptor reports on caps/scroll/num lock key presses, but
26 * doesn't have an LED output usage block.
27 *
28 * The replacement descriptor below fixes the number of consumer usages,
29 * and provides an LED output usage block. LED output events are redirected
30 * to the boot interface.
31 */
32
33static __u8 holtek_kbd_rdesc_fixed[] = {
34 /* Original report descriptor, with reduced number of consumer usages */
35 0x05, 0x01, /* Usage Page (Desktop), */
36 0x09, 0x80, /* Usage (Sys Control), */
37 0xA1, 0x01, /* Collection (Application), */
38 0x85, 0x01, /* Report ID (1), */
39 0x19, 0x81, /* Usage Minimum (Sys Power Down), */
40 0x29, 0x83, /* Usage Maximum (Sys Wake Up), */
41 0x15, 0x00, /* Logical Minimum (0), */
42 0x25, 0x01, /* Logical Maximum (1), */
43 0x95, 0x03, /* Report Count (3), */
44 0x75, 0x01, /* Report Size (1), */
45 0x81, 0x02, /* Input (Variable), */
46 0x95, 0x01, /* Report Count (1), */
47 0x75, 0x05, /* Report Size (5), */
48 0x81, 0x01, /* Input (Constant), */
49 0xC0, /* End Collection, */
50 0x05, 0x0C, /* Usage Page (Consumer), */
51 0x09, 0x01, /* Usage (Consumer Control), */
52 0xA1, 0x01, /* Collection (Application), */
53 0x85, 0x02, /* Report ID (2), */
54 0x19, 0x00, /* Usage Minimum (00h), */
55 0x2A, 0xFF, 0x2F, /* Usage Maximum (0x2FFF), previously 0x7FFF */
56 0x15, 0x00, /* Logical Minimum (0), */
57 0x26, 0xFF, 0x2F, /* Logical Maximum (0x2FFF),previously 0x7FFF*/
58 0x95, 0x01, /* Report Count (1), */
59 0x75, 0x10, /* Report Size (16), */
60 0x81, 0x00, /* Input, */
61 0xC0, /* End Collection, */
62 0x05, 0x01, /* Usage Page (Desktop), */
63 0x09, 0x06, /* Usage (Keyboard), */
64 0xA1, 0x01, /* Collection (Application), */
65 0x85, 0x03, /* Report ID (3), */
66 0x95, 0x38, /* Report Count (56), */
67 0x75, 0x01, /* Report Size (1), */
68 0x15, 0x00, /* Logical Minimum (0), */
69 0x25, 0x01, /* Logical Maximum (1), */
70 0x05, 0x07, /* Usage Page (Keyboard), */
71 0x19, 0xE0, /* Usage Minimum (KB Leftcontrol), */
72 0x29, 0xE7, /* Usage Maximum (KB Right GUI), */
73 0x19, 0x00, /* Usage Minimum (None), */
74 0x29, 0x2F, /* Usage Maximum (KB Lboxbracket And Lbrace),*/
75 0x81, 0x02, /* Input (Variable), */
76 0xC0, /* End Collection, */
77 0x05, 0x01, /* Usage Page (Desktop), */
78 0x09, 0x06, /* Usage (Keyboard), */
79 0xA1, 0x01, /* Collection (Application), */
80 0x85, 0x04, /* Report ID (4), */
81 0x95, 0x38, /* Report Count (56), */
82 0x75, 0x01, /* Report Size (1), */
83 0x15, 0x00, /* Logical Minimum (0), */
84 0x25, 0x01, /* Logical Maximum (1), */
85 0x05, 0x07, /* Usage Page (Keyboard), */
86 0x19, 0x30, /* Usage Minimum (KB Rboxbracket And Rbrace),*/
87 0x29, 0x67, /* Usage Maximum (KP Equals), */
88 0x81, 0x02, /* Input (Variable), */
89 0xC0, /* End Collection */
90
91 /* LED usage for the boot protocol interface */
92 0x05, 0x01, /* Usage Page (Desktop), */
93 0x09, 0x06, /* Usage (Keyboard), */
94 0xA1, 0x01, /* Collection (Application), */
95 0x05, 0x08, /* Usage Page (LED), */
96 0x19, 0x01, /* Usage Minimum (01h), */
97 0x29, 0x03, /* Usage Maximum (03h), */
98 0x15, 0x00, /* Logical Minimum (0), */
99 0x25, 0x01, /* Logical Maximum (1), */
100 0x75, 0x01, /* Report Size (1), */
101 0x95, 0x03, /* Report Count (3), */
102 0x91, 0x02, /* Output (Variable), */
103 0x95, 0x05, /* Report Count (5), */
104 0x91, 0x01, /* Output (Constant), */
105 0xC0, /* End Collection */
106};
107
108static __u8 *holtek_kbd_report_fixup(struct hid_device *hdev, __u8 *rdesc,
109 unsigned int *rsize)
110{
111 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
112
113 if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
114 rdesc = holtek_kbd_rdesc_fixed;
115 *rsize = sizeof(holtek_kbd_rdesc_fixed);
116 }
117 return rdesc;
118}
119
120static int holtek_kbd_input_event(struct input_dev *dev, unsigned int type,
121 unsigned int code,
122 int value)
123{
124 struct hid_device *hid = input_get_drvdata(dev);
125 struct usb_device *usb_dev = hid_to_usb_dev(hid);
126
127 /* Locate the boot interface, to receive the LED change events */
128 struct usb_interface *boot_interface = usb_ifnum_to_if(usb_dev, 0);
129
130 struct hid_device *boot_hid = usb_get_intfdata(boot_interface);
131 struct hid_input *boot_hid_input = list_first_entry(&boot_hid->inputs,
132 struct hid_input, list);
133
134 return boot_hid_input->input->event(boot_hid_input->input, type, code,
135 value);
136}
137
138static int holtek_kbd_probe(struct hid_device *hdev,
139 const struct hid_device_id *id)
140{
141 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
142 int ret = hid_parse(hdev);
143
144 if (!ret)
145 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
146
147 if (!ret && intf->cur_altsetting->desc.bInterfaceNumber == 1) {
148 struct hid_input *hidinput;
149 list_for_each_entry(hidinput, &hdev->inputs, list) {
150 hidinput->input->event = holtek_kbd_input_event;
151 }
152 }
153
154 return ret;
155}
156
157static const struct hid_device_id holtek_kbd_devices[] = {
158 { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
159 USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) },
160 { }
161};
162MODULE_DEVICE_TABLE(hid, holtek_kbd_devices);
163
164static struct hid_driver holtek_kbd_driver = {
165 .name = "holtek_kbd",
166 .id_table = holtek_kbd_devices,
167 .report_fixup = holtek_kbd_report_fixup,
168 .probe = holtek_kbd_probe
169};
170
171static int __init holtek_kbd_init(void)
172{
173 return hid_register_driver(&holtek_kbd_driver);
174}
175
176static void __exit holtek_kbd_exit(void)
177{
178 hid_unregister_driver(&holtek_kbd_driver);
179}
180
181module_exit(holtek_kbd_exit);
182module_init(holtek_kbd_init);
183MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 32039235cfee..41c34f21bd00 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -208,6 +208,7 @@
208#define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d 208#define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d
209#define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618 209#define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618
210#define USB_DEVICE_ID_CHICONY_WIRELESS2 0x1123 210#define USB_DEVICE_ID_CHICONY_WIRELESS2 0x1123
211#define USB_DEVICE_ID_CHICONY_AK1D 0x1125
211 212
212#define USB_VENDOR_ID_CHUNGHWAT 0x2247 213#define USB_VENDOR_ID_CHUNGHWAT 0x2247
213#define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001 214#define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001
@@ -237,6 +238,7 @@
237#define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61 238#define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61
238#define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64 239#define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64
239#define USB_DEVICE_ID_CYPRESS_BARCODE_3 0xbca1 240#define USB_DEVICE_ID_CYPRESS_BARCODE_3 0xbca1
241#define USB_DEVICE_ID_CYPRESS_BARCODE_4 0xed81
240#define USB_DEVICE_ID_CYPRESS_TRUETOUCH 0xc001 242#define USB_DEVICE_ID_CYPRESS_TRUETOUCH 0xc001
241 243
242#define USB_VENDOR_ID_DEALEXTREAME 0x10c5 244#define USB_VENDOR_ID_DEALEXTREAME 0x10c5
@@ -410,6 +412,9 @@
410#define USB_VENDOR_ID_HOLTEK 0x1241 412#define USB_VENDOR_ID_HOLTEK 0x1241
411#define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP 0x5015 413#define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP 0x5015
412 414
415#define USB_VENDOR_ID_HOLTEK_ALT 0x04d9
416#define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD 0xa055
417
413#define USB_VENDOR_ID_IMATION 0x0718 418#define USB_VENDOR_ID_IMATION 0x0718
414#define USB_DEVICE_ID_DISC_STAKKA 0xd000 419#define USB_DEVICE_ID_DISC_STAKKA 0xd000
415 420
@@ -479,6 +484,9 @@
479#define USB_DEVICE_ID_LD_HYBRID 0x2090 484#define USB_DEVICE_ID_LD_HYBRID 0x2090
480#define USB_DEVICE_ID_LD_HEATCONTROL 0x20A0 485#define USB_DEVICE_ID_LD_HEATCONTROL 0x20A0
481 486
487#define USB_VENDOR_ID_LENOVO 0x17ef
488#define USB_DEVICE_ID_LENOVO_TPKBD 0x6009
489
482#define USB_VENDOR_ID_LG 0x1fd2 490#define USB_VENDOR_ID_LG 0x1fd2
483#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064 491#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064
484 492
@@ -573,6 +581,9 @@
573#define USB_VENDOR_ID_NINTENDO 0x057e 581#define USB_VENDOR_ID_NINTENDO 0x057e
574#define USB_DEVICE_ID_NINTENDO_WIIMOTE 0x0306 582#define USB_DEVICE_ID_NINTENDO_WIIMOTE 0x0306
575 583
584#define USB_VENDOR_ID_NOVATEK 0x0603
585#define USB_DEVICE_ID_NOVATEK_PCT 0x0600
586
576#define USB_VENDOR_ID_NTRIG 0x1b96 587#define USB_VENDOR_ID_NTRIG 0x1b96
577#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001 588#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001
578#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1 0x0003 589#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1 0x0003
@@ -650,6 +661,7 @@
650#define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50 661#define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50
651#define USB_DEVICE_ID_ROCCAT_PYRA_WIRED 0x2c24 662#define USB_DEVICE_ID_ROCCAT_PYRA_WIRED 0x2c24
652#define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS 0x2cf6 663#define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS 0x2cf6
664#define USB_DEVICE_ID_ROCCAT_SAVU 0x2d5a
653 665
654#define USB_VENDOR_ID_SAITEK 0x06a3 666#define USB_VENDOR_ID_SAITEK 0x06a3
655#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 667#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 5301006f6c15..811bfad64609 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -837,6 +837,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
837 } 837 }
838 break; 838 break;
839 839
840 case HID_UP_HPVENDOR2:
841 set_bit(EV_REP, input->evbit);
842 switch (usage->hid & HID_USAGE) {
843 case 0x003: map_key_clear(KEY_BRIGHTNESSDOWN); break;
844 case 0x004: map_key_clear(KEY_BRIGHTNESSUP); break;
845 default: goto ignore;
846 }
847 break;
848
840 case HID_UP_MSVENDOR: 849 case HID_UP_MSVENDOR:
841 goto ignore; 850 goto ignore;
842 851
diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c
new file mode 100644
index 000000000000..77d2df04c97b
--- /dev/null
+++ b/drivers/hid/hid-lenovo-tpkbd.c
@@ -0,0 +1,564 @@
1/*
2 * HID driver for Lenovo ThinkPad USB Keyboard with TrackPoint
3 *
4 * Copyright (c) 2012 Bernhard Seibold
5 */
6
7/*
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 */
13
14#include <linux/module.h>
15#include <linux/sysfs.h>
16#include <linux/device.h>
17#include <linux/usb.h>
18#include <linux/hid.h>
19#include <linux/input.h>
20#include <linux/leds.h>
21#include "usbhid/usbhid.h"
22
23#include "hid-ids.h"
24
25/* This is only used for the trackpoint part of the driver, hence _tp */
26struct tpkbd_data_pointer {
27 int led_state;
28 struct led_classdev led_mute;
29 struct led_classdev led_micmute;
30 int press_to_select;
31 int dragging;
32 int release_to_select;
33 int select_right;
34 int sensitivity;
35 int press_speed;
36};
37
38#define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
39
40static int tpkbd_input_mapping(struct hid_device *hdev,
41 struct hid_input *hi, struct hid_field *field,
42 struct hid_usage *usage, unsigned long **bit, int *max)
43{
44 struct usbhid_device *uhdev;
45
46 uhdev = (struct usbhid_device *) hdev->driver_data;
47 if (uhdev->ifnum == 1 && usage->hid == (HID_UP_BUTTON | 0x0010)) {
48 map_key_clear(KEY_MICMUTE);
49 return 1;
50 }
51 return 0;
52}
53
54#undef map_key_clear
55
56static int tpkbd_features_set(struct hid_device *hdev)
57{
58 struct hid_report *report;
59 struct tpkbd_data_pointer *data_pointer;
60
61 data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
62 report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4];
63
64 report->field[0]->value[0] = data_pointer->press_to_select ? 0x01 : 0x02;
65 report->field[0]->value[0] |= data_pointer->dragging ? 0x04 : 0x08;
66 report->field[0]->value[0] |= data_pointer->release_to_select ? 0x10 : 0x20;
67 report->field[0]->value[0] |= data_pointer->select_right ? 0x80 : 0x40;
68 report->field[1]->value[0] = 0x03; // unknown setting, imitate windows driver
69 report->field[2]->value[0] = data_pointer->sensitivity;
70 report->field[3]->value[0] = data_pointer->press_speed;
71
72 usbhid_submit_report(hdev, report, USB_DIR_OUT);
73 return 0;
74}
75
76static ssize_t pointer_press_to_select_show(struct device *dev,
77 struct device_attribute *attr,
78 char *buf)
79{
80 struct hid_device *hdev;
81 struct tpkbd_data_pointer *data_pointer;
82
83 hdev = container_of(dev, struct hid_device, dev);
84 if (hdev == NULL)
85 return -ENODEV;
86
87 data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
88
89 return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select);
90}
91
92static ssize_t pointer_press_to_select_store(struct device *dev,
93 struct device_attribute *attr,
94 const char *buf,
95 size_t count)
96{
97 struct hid_device *hdev;
98 struct tpkbd_data_pointer *data_pointer;
99 int value;
100
101 hdev = container_of(dev, struct hid_device, dev);
102 if (hdev == NULL)
103 return -ENODEV;
104
105 data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
106
107 if (kstrtoint(buf, 10, &value))
108 return -EINVAL;
109 if (value < 0 || value > 1)
110 return -EINVAL;
111
112 data_pointer->press_to_select = value;
113 tpkbd_features_set(hdev);
114
115 return count;
116}
117
118static ssize_t pointer_dragging_show(struct device *dev,
119 struct device_attribute *attr,
120 char *buf)
121{
122 struct hid_device *hdev;
123 struct tpkbd_data_pointer *data_pointer;
124
125 hdev = container_of(dev, struct hid_device, dev);
126 if (hdev == NULL)
127 return -ENODEV;
128
129 data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
130
131 return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging);
132}
133
134static ssize_t pointer_dragging_store(struct device *dev,
135 struct device_attribute *attr,
136 const char *buf,
137 size_t count)
138{
139 struct hid_device *hdev;
140 struct tpkbd_data_pointer *data_pointer;
141 int value;
142
143 hdev = container_of(dev, struct hid_device, dev);
144 if (hdev == NULL)
145 return -ENODEV;
146
147 data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
148
149 if (kstrtoint(buf, 10, &value))
150 return -EINVAL;
151 if (value < 0 || value > 1)
152 return -EINVAL;
153
154 data_pointer->dragging = value;
155 tpkbd_features_set(hdev);
156
157 return count;
158}
159
160static ssize_t pointer_release_to_select_show(struct device *dev,
161 struct device_attribute *attr,
162 char *buf)
163{
164 struct hid_device *hdev;
165 struct tpkbd_data_pointer *data_pointer;
166
167 hdev = container_of(dev, struct hid_device, dev);
168 if (hdev == NULL)
169 return -ENODEV;
170
171 data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
172
173 return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select);
174}
175
176static ssize_t pointer_release_to_select_store(struct device *dev,
177 struct device_attribute *attr,
178 const char *buf,
179 size_t count)
180{
181 struct hid_device *hdev;
182 struct tpkbd_data_pointer *data_pointer;
183 int value;
184
185 hdev = container_of(dev, struct hid_device, dev);
186 if (hdev == NULL)
187 return -ENODEV;
188
189 data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
190
191 if (kstrtoint(buf, 10, &value))
192 return -EINVAL;
193 if (value < 0 || value > 1)
194 return -EINVAL;
195
196 data_pointer->release_to_select = value;
197 tpkbd_features_set(hdev);
198
199 return count;
200}
201
202static ssize_t pointer_select_right_show(struct device *dev,
203 struct device_attribute *attr,
204 char *buf)
205{
206 struct hid_device *hdev;
207 struct tpkbd_data_pointer *data_pointer;
208
209 hdev = container_of(dev, struct hid_device, dev);
210 if (hdev == NULL)
211 return -ENODEV;
212
213 data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
214
215 return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right);
216}
217
218static ssize_t pointer_select_right_store(struct device *dev,
219 struct device_attribute *attr,
220 const char *buf,
221 size_t count)
222{
223 struct hid_device *hdev;
224 struct tpkbd_data_pointer *data_pointer;
225 int value;
226
227 hdev = container_of(dev, struct hid_device, dev);
228 if (hdev == NULL)
229 return -ENODEV;
230
231 data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
232
233 if (kstrtoint(buf, 10, &value))
234 return -EINVAL;
235 if (value < 0 || value > 1)
236 return -EINVAL;
237
238 data_pointer->select_right = value;
239 tpkbd_features_set(hdev);
240
241 return count;
242}
243
244static ssize_t pointer_sensitivity_show(struct device *dev,
245 struct device_attribute *attr,
246 char *buf)
247{
248 struct hid_device *hdev;
249 struct tpkbd_data_pointer *data_pointer;
250
251 hdev = container_of(dev, struct hid_device, dev);
252 if (hdev == NULL)
253 return -ENODEV;
254
255 data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
256
257 return snprintf(buf, PAGE_SIZE, "%u\n",
258 data_pointer->sensitivity);
259}
260
261static ssize_t pointer_sensitivity_store(struct device *dev,
262 struct device_attribute *attr,
263 const char *buf,
264 size_t count)
265{
266 struct hid_device *hdev;
267 struct tpkbd_data_pointer *data_pointer;
268 int value;
269
270 hdev = container_of(dev, struct hid_device, dev);
271 if (hdev == NULL)
272 return -ENODEV;
273
274 data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
275
276 if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
277 return -EINVAL;
278
279 data_pointer->sensitivity = value;
280 tpkbd_features_set(hdev);
281
282 return count;
283}
284
285static ssize_t pointer_press_speed_show(struct device *dev,
286 struct device_attribute *attr,
287 char *buf)
288{
289 struct hid_device *hdev;
290 struct tpkbd_data_pointer *data_pointer;
291
292 hdev = container_of(dev, struct hid_device, dev);
293 if (hdev == NULL)
294 return -ENODEV;
295
296 data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
297
298 return snprintf(buf, PAGE_SIZE, "%u\n",
299 data_pointer->press_speed);
300}
301
302static ssize_t pointer_press_speed_store(struct device *dev,
303 struct device_attribute *attr,
304 const char *buf,
305 size_t count)
306{
307 struct hid_device *hdev;
308 struct tpkbd_data_pointer *data_pointer;
309 int value;
310
311 hdev = container_of(dev, struct hid_device, dev);
312 if (hdev == NULL)
313 return -ENODEV;
314
315 data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
316
317 if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
318 return -EINVAL;
319
320 data_pointer->press_speed = value;
321 tpkbd_features_set(hdev);
322
323 return count;
324}
325
326static struct device_attribute dev_attr_pointer_press_to_select =
327 __ATTR(press_to_select, S_IWUSR | S_IRUGO,
328 pointer_press_to_select_show,
329 pointer_press_to_select_store);
330
331static struct device_attribute dev_attr_pointer_dragging =
332 __ATTR(dragging, S_IWUSR | S_IRUGO,
333 pointer_dragging_show,
334 pointer_dragging_store);
335
336static struct device_attribute dev_attr_pointer_release_to_select =
337 __ATTR(release_to_select, S_IWUSR | S_IRUGO,
338 pointer_release_to_select_show,
339 pointer_release_to_select_store);
340
341static struct device_attribute dev_attr_pointer_select_right =
342 __ATTR(select_right, S_IWUSR | S_IRUGO,
343 pointer_select_right_show,
344 pointer_select_right_store);
345
346static struct device_attribute dev_attr_pointer_sensitivity =
347 __ATTR(sensitivity, S_IWUSR | S_IRUGO,
348 pointer_sensitivity_show,
349 pointer_sensitivity_store);
350
351static struct device_attribute dev_attr_pointer_press_speed =
352 __ATTR(press_speed, S_IWUSR | S_IRUGO,
353 pointer_press_speed_show,
354 pointer_press_speed_store);
355
356static struct attribute *tpkbd_attributes_pointer[] = {
357 &dev_attr_pointer_press_to_select.attr,
358 &dev_attr_pointer_dragging.attr,
359 &dev_attr_pointer_release_to_select.attr,
360 &dev_attr_pointer_select_right.attr,
361 &dev_attr_pointer_sensitivity.attr,
362 &dev_attr_pointer_press_speed.attr,
363 NULL
364};
365
366static const struct attribute_group tpkbd_attr_group_pointer = {
367 .attrs = tpkbd_attributes_pointer,
368};
369
370static enum led_brightness tpkbd_led_brightness_get(
371 struct led_classdev *led_cdev)
372{
373 struct device *dev;
374 struct hid_device *hdev;
375 struct tpkbd_data_pointer *data_pointer;
376 int led_nr = 0;
377
378 dev = led_cdev->dev->parent;
379 hdev = container_of(dev, struct hid_device, dev);
380 data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
381
382 if (led_cdev == &data_pointer->led_micmute)
383 led_nr = 1;
384
385 return data_pointer->led_state & (1 << led_nr)
386 ? LED_FULL
387 : LED_OFF;
388}
389
390static void tpkbd_led_brightness_set(struct led_classdev *led_cdev,
391 enum led_brightness value)
392{
393 struct device *dev;
394 struct hid_device *hdev;
395 struct hid_report *report;
396 struct tpkbd_data_pointer *data_pointer;
397 int led_nr = 0;
398
399 dev = led_cdev->dev->parent;
400 hdev = container_of(dev, struct hid_device, dev);
401 data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
402
403 if (led_cdev == &data_pointer->led_micmute)
404 led_nr = 1;
405
406 if (value == LED_OFF)
407 data_pointer->led_state &= ~(1 << led_nr);
408 else
409 data_pointer->led_state |= 1 << led_nr;
410
411 report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3];
412 report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1;
413 report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1;
414 usbhid_submit_report(hdev, report, USB_DIR_OUT);
415}
416
417static int tpkbd_probe_tp(struct hid_device *hdev)
418{
419 struct device *dev = &hdev->dev;
420 struct tpkbd_data_pointer *data_pointer;
421 size_t name_sz = strlen(dev_name(dev)) + 16;
422 char *name_mute, *name_micmute;
423 int ret;
424
425 if (sysfs_create_group(&hdev->dev.kobj,
426 &tpkbd_attr_group_pointer)) {
427 hid_warn(hdev, "Could not create sysfs group\n");
428 }
429
430 data_pointer = kzalloc(sizeof(struct tpkbd_data_pointer), GFP_KERNEL);
431 if (data_pointer == NULL) {
432 hid_err(hdev, "Could not allocate memory for driver data\n");
433 return -ENOMEM;
434 }
435
436 // set same default values as windows driver
437 data_pointer->sensitivity = 0xa0;
438 data_pointer->press_speed = 0x38;
439
440 name_mute = kzalloc(name_sz, GFP_KERNEL);
441 if (name_mute == NULL) {
442 hid_err(hdev, "Could not allocate memory for led data\n");
443 ret = -ENOMEM;
444 goto err;
445 }
446 snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev));
447
448 name_micmute = kzalloc(name_sz, GFP_KERNEL);
449 if (name_micmute == NULL) {
450 hid_err(hdev, "Could not allocate memory for led data\n");
451 ret = -ENOMEM;
452 goto err2;
453 }
454 snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev));
455
456 hid_set_drvdata(hdev, data_pointer);
457
458 data_pointer->led_mute.name = name_mute;
459 data_pointer->led_mute.brightness_get = tpkbd_led_brightness_get;
460 data_pointer->led_mute.brightness_set = tpkbd_led_brightness_set;
461 data_pointer->led_mute.dev = dev;
462 led_classdev_register(dev, &data_pointer->led_mute);
463
464 data_pointer->led_micmute.name = name_micmute;
465 data_pointer->led_micmute.brightness_get = tpkbd_led_brightness_get;
466 data_pointer->led_micmute.brightness_set = tpkbd_led_brightness_set;
467 data_pointer->led_micmute.dev = dev;
468 led_classdev_register(dev, &data_pointer->led_micmute);
469
470 tpkbd_features_set(hdev);
471
472 return 0;
473
474err2:
475 kfree(name_mute);
476err:
477 kfree(data_pointer);
478 return ret;
479}
480
481static int tpkbd_probe(struct hid_device *hdev,
482 const struct hid_device_id *id)
483{
484 int ret;
485 struct usbhid_device *uhdev;
486
487 ret = hid_parse(hdev);
488 if (ret) {
489 hid_err(hdev, "hid_parse failed\n");
490 goto err_free;
491 }
492
493 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
494 if (ret) {
495 hid_err(hdev, "hid_hw_start failed\n");
496 goto err_free;
497 }
498
499 uhdev = (struct usbhid_device *) hdev->driver_data;
500
501 if (uhdev->ifnum == 1)
502 return tpkbd_probe_tp(hdev);
503
504 return 0;
505err_free:
506 return ret;
507}
508
509static void tpkbd_remove_tp(struct hid_device *hdev)
510{
511 struct tpkbd_data_pointer *data_pointer;
512
513 sysfs_remove_group(&hdev->dev.kobj,
514 &tpkbd_attr_group_pointer);
515
516 data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
517
518 led_classdev_unregister(&data_pointer->led_micmute);
519 led_classdev_unregister(&data_pointer->led_mute);
520
521 hid_set_drvdata(hdev, NULL);
522 kfree(data_pointer);
523}
524
525static void tpkbd_remove(struct hid_device *hdev)
526{
527 struct usbhid_device *uhdev;
528
529 uhdev = (struct usbhid_device *) hdev->driver_data;
530 if (uhdev->ifnum == 1)
531 tpkbd_remove_tp(hdev);
532
533 hid_hw_stop(hdev);
534}
535
536static const struct hid_device_id tpkbd_devices[] = {
537 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
538 { }
539};
540
541MODULE_DEVICE_TABLE(hid, tpkbd_devices);
542
543static struct hid_driver tpkbd_driver = {
544 .name = "lenovo_tpkbd",
545 .id_table = tpkbd_devices,
546 .input_mapping = tpkbd_input_mapping,
547 .probe = tpkbd_probe,
548 .remove = tpkbd_remove,
549};
550
551static int __init tpkbd_init(void)
552{
553 return hid_register_driver(&tpkbd_driver);
554}
555
556static void __exit tpkbd_exit(void)
557{
558 hid_unregister_driver(&tpkbd_driver);
559}
560
561module_init(tpkbd_init);
562module_exit(tpkbd_exit);
563
564MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 40ac6654f1d1..73647266daad 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -16,6 +16,7 @@
16 16
17#include <linux/device.h> 17#include <linux/device.h>
18#include <linux/hid.h> 18#include <linux/hid.h>
19#include <linux/input/mt.h>
19#include <linux/module.h> 20#include <linux/module.h>
20#include <linux/slab.h> 21#include <linux/slab.h>
21#include <linux/usb.h> 22#include <linux/usb.h>
@@ -48,10 +49,6 @@ static bool scroll_acceleration = false;
48module_param(scroll_acceleration, bool, 0644); 49module_param(scroll_acceleration, bool, 0644);
49MODULE_PARM_DESC(scroll_acceleration, "Accelerate sequential scroll events"); 50MODULE_PARM_DESC(scroll_acceleration, "Accelerate sequential scroll events");
50 51
51static bool report_touches = true;
52module_param(report_touches, bool, 0644);
53MODULE_PARM_DESC(report_touches, "Emit touch records (otherwise, only use them for emulation)");
54
55static bool report_undeciphered; 52static bool report_undeciphered;
56module_param(report_undeciphered, bool, 0644); 53module_param(report_undeciphered, bool, 0644);
57MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state field using a MSC_RAW event"); 54MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state field using a MSC_RAW event");
@@ -72,15 +69,6 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
72 69
73#define SCROLL_ACCEL_DEFAULT 7 70#define SCROLL_ACCEL_DEFAULT 7
74 71
75/* Single touch emulation should only begin when no touches are currently down.
76 * This is true when single_touch_id is equal to NO_TOUCHES. If multiple touches
77 * are down and the touch providing for single touch emulation is lifted,
78 * single_touch_id is equal to SINGLE_TOUCH_UP. While single touch emulation is
79 * occurring, single_touch_id corresponds with the tracking id of the touch used.
80 */
81#define NO_TOUCHES -1
82#define SINGLE_TOUCH_UP -2
83
84/* Touch surface information. Dimension is in hundredths of a mm, min and max 72/* Touch surface information. Dimension is in hundredths of a mm, min and max
85 * are in units. */ 73 * are in units. */
86#define MOUSE_DIMENSION_X (float)9056 74#define MOUSE_DIMENSION_X (float)9056
@@ -129,7 +117,6 @@ struct magicmouse_sc {
129 u8 size; 117 u8 size;
130 } touches[16]; 118 } touches[16];
131 int tracking_ids[16]; 119 int tracking_ids[16];
132 int single_touch_id;
133}; 120};
134 121
135static int magicmouse_firm_touch(struct magicmouse_sc *msc) 122static int magicmouse_firm_touch(struct magicmouse_sc *msc)
@@ -268,16 +255,14 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
268 } 255 }
269 } 256 }
270 257
271 if (down) { 258 if (down)
272 msc->ntouches++; 259 msc->ntouches++;
273 if (msc->single_touch_id == NO_TOUCHES) 260
274 msc->single_touch_id = id; 261 input_mt_slot(input, id);
275 } else if (msc->single_touch_id == id) 262 input_mt_report_slot_state(input, MT_TOOL_FINGER, down);
276 msc->single_touch_id = SINGLE_TOUCH_UP;
277 263
278 /* Generate the input events for this touch. */ 264 /* Generate the input events for this touch. */
279 if (report_touches && down) { 265 if (down) {
280 input_report_abs(input, ABS_MT_TRACKING_ID, id);
281 input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major << 2); 266 input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major << 2);
282 input_report_abs(input, ABS_MT_TOUCH_MINOR, touch_minor << 2); 267 input_report_abs(input, ABS_MT_TOUCH_MINOR, touch_minor << 2);
283 input_report_abs(input, ABS_MT_ORIENTATION, -orientation); 268 input_report_abs(input, ABS_MT_ORIENTATION, -orientation);
@@ -290,8 +275,6 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
290 else /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ 275 else /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
291 input_event(input, EV_MSC, MSC_RAW, tdata[8]); 276 input_event(input, EV_MSC, MSC_RAW, tdata[8]);
292 } 277 }
293
294 input_mt_sync(input);
295 } 278 }
296} 279}
297 280
@@ -312,12 +295,6 @@ static int magicmouse_raw_event(struct hid_device *hdev,
312 for (ii = 0; ii < npoints; ii++) 295 for (ii = 0; ii < npoints; ii++)
313 magicmouse_emit_touch(msc, ii, data + ii * 9 + 4); 296 magicmouse_emit_touch(msc, ii, data + ii * 9 + 4);
314 297
315 /* We don't need an MT sync here because trackpad emits a
316 * BTN_TOUCH event in a new frame when all touches are released.
317 */
318 if (msc->ntouches == 0)
319 msc->single_touch_id = NO_TOUCHES;
320
321 clicks = data[1]; 298 clicks = data[1];
322 299
323 /* The following bits provide a device specific timestamp. They 300 /* The following bits provide a device specific timestamp. They
@@ -335,9 +312,6 @@ static int magicmouse_raw_event(struct hid_device *hdev,
335 for (ii = 0; ii < npoints; ii++) 312 for (ii = 0; ii < npoints; ii++)
336 magicmouse_emit_touch(msc, ii, data + ii * 8 + 6); 313 magicmouse_emit_touch(msc, ii, data + ii * 8 + 6);
337 314
338 if (report_touches && msc->ntouches == 0)
339 input_mt_sync(input);
340
341 /* When emulating three-button mode, it is important 315 /* When emulating three-button mode, it is important
342 * to have the current touch information before 316 * to have the current touch information before
343 * generating a click event. 317 * generating a click event.
@@ -370,25 +344,17 @@ static int magicmouse_raw_event(struct hid_device *hdev,
370 input_report_rel(input, REL_Y, y); 344 input_report_rel(input, REL_Y, y);
371 } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ 345 } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
372 input_report_key(input, BTN_MOUSE, clicks & 1); 346 input_report_key(input, BTN_MOUSE, clicks & 1);
373 input_report_key(input, BTN_TOUCH, msc->ntouches > 0); 347 input_mt_report_pointer_emulation(input, true);
374 input_report_key(input, BTN_TOOL_FINGER, msc->ntouches == 1);
375 input_report_key(input, BTN_TOOL_DOUBLETAP, msc->ntouches == 2);
376 input_report_key(input, BTN_TOOL_TRIPLETAP, msc->ntouches == 3);
377 input_report_key(input, BTN_TOOL_QUADTAP, msc->ntouches == 4);
378 if (msc->single_touch_id >= 0) {
379 input_report_abs(input, ABS_X,
380 msc->touches[msc->single_touch_id].x);
381 input_report_abs(input, ABS_Y,
382 msc->touches[msc->single_touch_id].y);
383 }
384 } 348 }
385 349
386 input_sync(input); 350 input_sync(input);
387 return 1; 351 return 1;
388} 352}
389 353
390static void magicmouse_setup_input(struct input_dev *input, struct hid_device *hdev) 354static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hdev)
391{ 355{
356 int error;
357
392 __set_bit(EV_KEY, input->evbit); 358 __set_bit(EV_KEY, input->evbit);
393 359
394 if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { 360 if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) {
@@ -417,62 +383,66 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h
417 __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); 383 __set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
418 __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); 384 __set_bit(BTN_TOOL_TRIPLETAP, input->keybit);
419 __set_bit(BTN_TOOL_QUADTAP, input->keybit); 385 __set_bit(BTN_TOOL_QUADTAP, input->keybit);
386 __set_bit(BTN_TOOL_QUINTTAP, input->keybit);
420 __set_bit(BTN_TOUCH, input->keybit); 387 __set_bit(BTN_TOUCH, input->keybit);
421 __set_bit(INPUT_PROP_POINTER, input->propbit); 388 __set_bit(INPUT_PROP_POINTER, input->propbit);
422 __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); 389 __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
423 } 390 }
424 391
425 if (report_touches) {
426 __set_bit(EV_ABS, input->evbit);
427
428 input_set_abs_params(input, ABS_MT_TRACKING_ID, 0, 15, 0, 0);
429 input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255 << 2,
430 4, 0);
431 input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 255 << 2,
432 4, 0);
433 input_set_abs_params(input, ABS_MT_ORIENTATION, -31, 32, 1, 0);
434
435 /* Note: Touch Y position from the device is inverted relative
436 * to how pointer motion is reported (and relative to how USB
437 * HID recommends the coordinates work). This driver keeps
438 * the origin at the same position, and just uses the additive
439 * inverse of the reported Y.
440 */
441 if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) {
442 input_set_abs_params(input, ABS_MT_POSITION_X,
443 MOUSE_MIN_X, MOUSE_MAX_X, 4, 0);
444 input_set_abs_params(input, ABS_MT_POSITION_Y,
445 MOUSE_MIN_Y, MOUSE_MAX_Y, 4, 0);
446
447 input_abs_set_res(input, ABS_MT_POSITION_X,
448 MOUSE_RES_X);
449 input_abs_set_res(input, ABS_MT_POSITION_Y,
450 MOUSE_RES_Y);
451 } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
452 input_set_abs_params(input, ABS_X, TRACKPAD_MIN_X,
453 TRACKPAD_MAX_X, 4, 0);
454 input_set_abs_params(input, ABS_Y, TRACKPAD_MIN_Y,
455 TRACKPAD_MAX_Y, 4, 0);
456 input_set_abs_params(input, ABS_MT_POSITION_X,
457 TRACKPAD_MIN_X, TRACKPAD_MAX_X, 4, 0);
458 input_set_abs_params(input, ABS_MT_POSITION_Y,
459 TRACKPAD_MIN_Y, TRACKPAD_MAX_Y, 4, 0);
460
461 input_abs_set_res(input, ABS_X, TRACKPAD_RES_X);
462 input_abs_set_res(input, ABS_Y, TRACKPAD_RES_Y);
463 input_abs_set_res(input, ABS_MT_POSITION_X,
464 TRACKPAD_RES_X);
465 input_abs_set_res(input, ABS_MT_POSITION_Y,
466 TRACKPAD_RES_Y);
467 }
468 392
469 input_set_events_per_packet(input, 60); 393 __set_bit(EV_ABS, input->evbit);
394
395 error = input_mt_init_slots(input, 16);
396 if (error)
397 return error;
398 input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255 << 2,
399 4, 0);
400 input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 255 << 2,
401 4, 0);
402 input_set_abs_params(input, ABS_MT_ORIENTATION, -31, 32, 1, 0);
403
404 /* Note: Touch Y position from the device is inverted relative
405 * to how pointer motion is reported (and relative to how USB
406 * HID recommends the coordinates work). This driver keeps
407 * the origin at the same position, and just uses the additive
408 * inverse of the reported Y.
409 */
410 if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) {
411 input_set_abs_params(input, ABS_MT_POSITION_X,
412 MOUSE_MIN_X, MOUSE_MAX_X, 4, 0);
413 input_set_abs_params(input, ABS_MT_POSITION_Y,
414 MOUSE_MIN_Y, MOUSE_MAX_Y, 4, 0);
415
416 input_abs_set_res(input, ABS_MT_POSITION_X,
417 MOUSE_RES_X);
418 input_abs_set_res(input, ABS_MT_POSITION_Y,
419 MOUSE_RES_Y);
420 } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
421 input_set_abs_params(input, ABS_X, TRACKPAD_MIN_X,
422 TRACKPAD_MAX_X, 4, 0);
423 input_set_abs_params(input, ABS_Y, TRACKPAD_MIN_Y,
424 TRACKPAD_MAX_Y, 4, 0);
425 input_set_abs_params(input, ABS_MT_POSITION_X,
426 TRACKPAD_MIN_X, TRACKPAD_MAX_X, 4, 0);
427 input_set_abs_params(input, ABS_MT_POSITION_Y,
428 TRACKPAD_MIN_Y, TRACKPAD_MAX_Y, 4, 0);
429
430 input_abs_set_res(input, ABS_X, TRACKPAD_RES_X);
431 input_abs_set_res(input, ABS_Y, TRACKPAD_RES_Y);
432 input_abs_set_res(input, ABS_MT_POSITION_X,
433 TRACKPAD_RES_X);
434 input_abs_set_res(input, ABS_MT_POSITION_Y,
435 TRACKPAD_RES_Y);
470 } 436 }
471 437
438 input_set_events_per_packet(input, 60);
439
472 if (report_undeciphered) { 440 if (report_undeciphered) {
473 __set_bit(EV_MSC, input->evbit); 441 __set_bit(EV_MSC, input->evbit);
474 __set_bit(MSC_RAW, input->mscbit); 442 __set_bit(MSC_RAW, input->mscbit);
475 } 443 }
444
445 return 0;
476} 446}
477 447
478static int magicmouse_input_mapping(struct hid_device *hdev, 448static int magicmouse_input_mapping(struct hid_device *hdev,
@@ -511,8 +481,6 @@ static int magicmouse_probe(struct hid_device *hdev,
511 msc->quirks = id->driver_data; 481 msc->quirks = id->driver_data;
512 hid_set_drvdata(hdev, msc); 482 hid_set_drvdata(hdev, msc);
513 483
514 msc->single_touch_id = NO_TOUCHES;
515
516 ret = hid_parse(hdev); 484 ret = hid_parse(hdev);
517 if (ret) { 485 if (ret) {
518 hid_err(hdev, "magicmouse hid parse failed\n"); 486 hid_err(hdev, "magicmouse hid parse failed\n");
@@ -528,8 +496,13 @@ static int magicmouse_probe(struct hid_device *hdev,
528 /* We do this after hid-input is done parsing reports so that 496 /* We do this after hid-input is done parsing reports so that
529 * hid-input uses the most natural button and axis IDs. 497 * hid-input uses the most natural button and axis IDs.
530 */ 498 */
531 if (msc->input) 499 if (msc->input) {
532 magicmouse_setup_input(msc->input, hdev); 500 ret = magicmouse_setup_input(msc->input, hdev);
501 if (ret) {
502 hid_err(hdev, "magicmouse setup input failed (%d)\n", ret);
503 goto err_stop_hw;
504 }
505 }
533 506
534 if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE) 507 if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE)
535 report = hid_register_report(hdev, HID_INPUT_REPORT, 508 report = hid_register_report(hdev, HID_INPUT_REPORT,
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 76479246d4ee..59c8b5c1d2de 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -83,6 +83,7 @@ struct mt_device {
83 unsigned last_field_index; /* last field index of the report */ 83 unsigned last_field_index; /* last field index of the report */
84 unsigned last_slot_field; /* the last field of a slot */ 84 unsigned last_slot_field; /* the last field of a slot */
85 __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ 85 __s8 inputmode; /* InputMode HID feature, -1 if non-existent */
86 __s8 inputmode_index; /* InputMode HID feature index in the report */
86 __s8 maxcontact_report_id; /* Maximum Contact Number HID feature, 87 __s8 maxcontact_report_id; /* Maximum Contact Number HID feature,
87 -1 if non-existent */ 88 -1 if non-existent */
88 __u8 num_received; /* how many contacts we received */ 89 __u8 num_received; /* how many contacts we received */
@@ -260,10 +261,20 @@ static void mt_feature_mapping(struct hid_device *hdev,
260 struct hid_field *field, struct hid_usage *usage) 261 struct hid_field *field, struct hid_usage *usage)
261{ 262{
262 struct mt_device *td = hid_get_drvdata(hdev); 263 struct mt_device *td = hid_get_drvdata(hdev);
264 int i;
263 265
264 switch (usage->hid) { 266 switch (usage->hid) {
265 case HID_DG_INPUTMODE: 267 case HID_DG_INPUTMODE:
266 td->inputmode = field->report->id; 268 td->inputmode = field->report->id;
269 td->inputmode_index = 0; /* has to be updated below */
270
271 for (i=0; i < field->maxusage; i++) {
272 if (field->usage[i].hid == usage->hid) {
273 td->inputmode_index = i;
274 break;
275 }
276 }
277
267 break; 278 break;
268 case HID_DG_CONTACTMAX: 279 case HID_DG_CONTACTMAX:
269 td->maxcontact_report_id = field->report->id; 280 td->maxcontact_report_id = field->report->id;
@@ -618,7 +629,7 @@ static void mt_set_input_mode(struct hid_device *hdev)
618 re = &(hdev->report_enum[HID_FEATURE_REPORT]); 629 re = &(hdev->report_enum[HID_FEATURE_REPORT]);
619 r = re->report_id_hash[td->inputmode]; 630 r = re->report_id_hash[td->inputmode];
620 if (r) { 631 if (r) {
621 r->field[0]->value[0] = 0x02; 632 r->field[0]->value[td->inputmode_index] = 0x02;
622 usbhid_submit_report(hdev, r, USB_DIR_OUT); 633 usbhid_submit_report(hdev, r, USB_DIR_OUT);
623 } 634 }
624} 635}
@@ -951,6 +962,11 @@ static const struct hid_device_id mt_devices[] = {
951 MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC, 962 MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
952 USB_DEVICE_ID_PANABOARD_UBT880) }, 963 USB_DEVICE_ID_PANABOARD_UBT880) },
953 964
965 /* Novatek Panel */
966 { .driver_data = MT_CLS_DEFAULT,
967 MT_USB_DEVICE(USB_VENDOR_ID_NOVATEK,
968 USB_DEVICE_ID_NOVATEK_PCT) },
969
954 /* PenMount panels */ 970 /* PenMount panels */
955 { .driver_data = MT_CLS_CONFIDENCE, 971 { .driver_data = MT_CLS_CONFIDENCE,
956 MT_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, 972 MT_USB_DEVICE(USB_VENDOR_ID_PENMOUNT,
diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c
index 45c3433f7986..27c8ebdfad01 100644
--- a/drivers/hid/hid-picolcd.c
+++ b/drivers/hid/hid-picolcd.c
@@ -1846,7 +1846,7 @@ static void picolcd_debug_out_report(struct picolcd_data *data,
1846#define BUFF_SZ 256 1846#define BUFF_SZ 256
1847 1847
1848 /* Avoid unnecessary overhead if debugfs is disabled */ 1848 /* Avoid unnecessary overhead if debugfs is disabled */
1849 if (!hdev->debug_events) 1849 if (list_empty(&hdev->debug_list))
1850 return; 1850 return;
1851 1851
1852 buff = kmalloc(BUFF_SZ, GFP_ATOMIC); 1852 buff = kmalloc(BUFF_SZ, GFP_ATOMIC);
@@ -2613,11 +2613,7 @@ static int picolcd_probe(struct hid_device *hdev,
2613 goto err_cleanup_data; 2613 goto err_cleanup_data;
2614 } 2614 }
2615 2615
2616 /* We don't use hidinput but hid_hw_start() fails if nothing is
2617 * claimed. So spoof claimed input. */
2618 hdev->claimed = HID_CLAIMED_INPUT;
2619 error = hid_hw_start(hdev, 0); 2616 error = hid_hw_start(hdev, 0);
2620 hdev->claimed = 0;
2621 if (error) { 2617 if (error) {
2622 hid_err(hdev, "hardware start failed\n"); 2618 hid_err(hdev, "hardware start failed\n");
2623 goto err_cleanup_data; 2619 goto err_cleanup_data;
diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c
index 093bfad00b02..327f9b8ed1f4 100644
--- a/drivers/hid/hid-roccat-arvo.c
+++ b/drivers/hid/hid-roccat-arvo.c
@@ -39,7 +39,7 @@ static ssize_t arvo_sysfs_show_mode_key(struct device *dev,
39 int retval; 39 int retval;
40 40
41 mutex_lock(&arvo->arvo_lock); 41 mutex_lock(&arvo->arvo_lock);
42 retval = roccat_common_receive(usb_dev, ARVO_COMMAND_MODE_KEY, 42 retval = roccat_common2_receive(usb_dev, ARVO_COMMAND_MODE_KEY,
43 &temp_buf, sizeof(struct arvo_mode_key)); 43 &temp_buf, sizeof(struct arvo_mode_key));
44 mutex_unlock(&arvo->arvo_lock); 44 mutex_unlock(&arvo->arvo_lock);
45 if (retval) 45 if (retval)
@@ -67,7 +67,7 @@ static ssize_t arvo_sysfs_set_mode_key(struct device *dev,
67 temp_buf.state = state; 67 temp_buf.state = state;
68 68
69 mutex_lock(&arvo->arvo_lock); 69 mutex_lock(&arvo->arvo_lock);
70 retval = roccat_common_send(usb_dev, ARVO_COMMAND_MODE_KEY, 70 retval = roccat_common2_send(usb_dev, ARVO_COMMAND_MODE_KEY,
71 &temp_buf, sizeof(struct arvo_mode_key)); 71 &temp_buf, sizeof(struct arvo_mode_key));
72 mutex_unlock(&arvo->arvo_lock); 72 mutex_unlock(&arvo->arvo_lock);
73 if (retval) 73 if (retval)
@@ -87,7 +87,7 @@ static ssize_t arvo_sysfs_show_key_mask(struct device *dev,
87 int retval; 87 int retval;
88 88
89 mutex_lock(&arvo->arvo_lock); 89 mutex_lock(&arvo->arvo_lock);
90 retval = roccat_common_receive(usb_dev, ARVO_COMMAND_KEY_MASK, 90 retval = roccat_common2_receive(usb_dev, ARVO_COMMAND_KEY_MASK,
91 &temp_buf, sizeof(struct arvo_key_mask)); 91 &temp_buf, sizeof(struct arvo_key_mask));
92 mutex_unlock(&arvo->arvo_lock); 92 mutex_unlock(&arvo->arvo_lock);
93 if (retval) 93 if (retval)
@@ -115,7 +115,7 @@ static ssize_t arvo_sysfs_set_key_mask(struct device *dev,
115 temp_buf.key_mask = key_mask; 115 temp_buf.key_mask = key_mask;
116 116
117 mutex_lock(&arvo->arvo_lock); 117 mutex_lock(&arvo->arvo_lock);
118 retval = roccat_common_send(usb_dev, ARVO_COMMAND_KEY_MASK, 118 retval = roccat_common2_send(usb_dev, ARVO_COMMAND_KEY_MASK,
119 &temp_buf, sizeof(struct arvo_key_mask)); 119 &temp_buf, sizeof(struct arvo_key_mask));
120 mutex_unlock(&arvo->arvo_lock); 120 mutex_unlock(&arvo->arvo_lock);
121 if (retval) 121 if (retval)
@@ -130,7 +130,7 @@ static int arvo_get_actual_profile(struct usb_device *usb_dev)
130 struct arvo_actual_profile temp_buf; 130 struct arvo_actual_profile temp_buf;
131 int retval; 131 int retval;
132 132
133 retval = roccat_common_receive(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE, 133 retval = roccat_common2_receive(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE,
134 &temp_buf, sizeof(struct arvo_actual_profile)); 134 &temp_buf, sizeof(struct arvo_actual_profile));
135 135
136 if (retval) 136 if (retval)
@@ -170,7 +170,7 @@ static ssize_t arvo_sysfs_set_actual_profile(struct device *dev,
170 temp_buf.actual_profile = profile; 170 temp_buf.actual_profile = profile;
171 171
172 mutex_lock(&arvo->arvo_lock); 172 mutex_lock(&arvo->arvo_lock);
173 retval = roccat_common_send(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE, 173 retval = roccat_common2_send(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE,
174 &temp_buf, sizeof(struct arvo_actual_profile)); 174 &temp_buf, sizeof(struct arvo_actual_profile));
175 if (!retval) { 175 if (!retval) {
176 arvo->actual_profile = profile; 176 arvo->actual_profile = profile;
@@ -194,7 +194,7 @@ static ssize_t arvo_sysfs_write(struct file *fp,
194 return -EINVAL; 194 return -EINVAL;
195 195
196 mutex_lock(&arvo->arvo_lock); 196 mutex_lock(&arvo->arvo_lock);
197 retval = roccat_common_send(usb_dev, command, buf, real_size); 197 retval = roccat_common2_send(usb_dev, command, buf, real_size);
198 mutex_unlock(&arvo->arvo_lock); 198 mutex_unlock(&arvo->arvo_lock);
199 199
200 return (retval ? retval : real_size); 200 return (retval ? retval : real_size);
@@ -217,7 +217,7 @@ static ssize_t arvo_sysfs_read(struct file *fp,
217 return -EINVAL; 217 return -EINVAL;
218 218
219 mutex_lock(&arvo->arvo_lock); 219 mutex_lock(&arvo->arvo_lock);
220 retval = roccat_common_receive(usb_dev, command, buf, real_size); 220 retval = roccat_common2_receive(usb_dev, command, buf, real_size);
221 mutex_unlock(&arvo->arvo_lock); 221 mutex_unlock(&arvo->arvo_lock);
222 222
223 return (retval ? retval : real_size); 223 return (retval ? retval : real_size);
diff --git a/drivers/hid/hid-roccat-common.c b/drivers/hid/hid-roccat-common.c
index a6d93992c75a..74f704032627 100644
--- a/drivers/hid/hid-roccat-common.c
+++ b/drivers/hid/hid-roccat-common.c
@@ -16,12 +16,12 @@
16#include <linux/module.h> 16#include <linux/module.h>
17#include "hid-roccat-common.h" 17#include "hid-roccat-common.h"
18 18
19static inline uint16_t roccat_common_feature_report(uint8_t report_id) 19static inline uint16_t roccat_common2_feature_report(uint8_t report_id)
20{ 20{
21 return 0x300 | report_id; 21 return 0x300 | report_id;
22} 22}
23 23
24int roccat_common_receive(struct usb_device *usb_dev, uint report_id, 24int roccat_common2_receive(struct usb_device *usb_dev, uint report_id,
25 void *data, uint size) 25 void *data, uint size)
26{ 26{
27 char *buf; 27 char *buf;
@@ -34,16 +34,16 @@ int roccat_common_receive(struct usb_device *usb_dev, uint report_id,
34 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), 34 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
35 HID_REQ_GET_REPORT, 35 HID_REQ_GET_REPORT,
36 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, 36 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
37 roccat_common_feature_report(report_id), 37 roccat_common2_feature_report(report_id),
38 0, buf, size, USB_CTRL_SET_TIMEOUT); 38 0, buf, size, USB_CTRL_SET_TIMEOUT);
39 39
40 memcpy(data, buf, size); 40 memcpy(data, buf, size);
41 kfree(buf); 41 kfree(buf);
42 return ((len < 0) ? len : ((len != size) ? -EIO : 0)); 42 return ((len < 0) ? len : ((len != size) ? -EIO : 0));
43} 43}
44EXPORT_SYMBOL_GPL(roccat_common_receive); 44EXPORT_SYMBOL_GPL(roccat_common2_receive);
45 45
46int roccat_common_send(struct usb_device *usb_dev, uint report_id, 46int roccat_common2_send(struct usb_device *usb_dev, uint report_id,
47 void const *data, uint size) 47 void const *data, uint size)
48{ 48{
49 char *buf; 49 char *buf;
@@ -56,13 +56,71 @@ int roccat_common_send(struct usb_device *usb_dev, uint report_id,
56 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), 56 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
57 HID_REQ_SET_REPORT, 57 HID_REQ_SET_REPORT,
58 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, 58 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
59 roccat_common_feature_report(report_id), 59 roccat_common2_feature_report(report_id),
60 0, buf, size, USB_CTRL_SET_TIMEOUT); 60 0, buf, size, USB_CTRL_SET_TIMEOUT);
61 61
62 kfree(buf); 62 kfree(buf);
63 return ((len < 0) ? len : ((len != size) ? -EIO : 0)); 63 return ((len < 0) ? len : ((len != size) ? -EIO : 0));
64} 64}
65EXPORT_SYMBOL_GPL(roccat_common_send); 65EXPORT_SYMBOL_GPL(roccat_common2_send);
66
67enum roccat_common2_control_states {
68 ROCCAT_COMMON_CONTROL_STATUS_OVERLOAD = 0,
69 ROCCAT_COMMON_CONTROL_STATUS_OK = 1,
70 ROCCAT_COMMON_CONTROL_STATUS_INVALID = 2,
71 ROCCAT_COMMON_CONTROL_STATUS_WAIT = 3,
72};
73
74static int roccat_common2_receive_control_status(struct usb_device *usb_dev)
75{
76 int retval;
77 struct roccat_common2_control control;
78
79 do {
80 msleep(50);
81 retval = roccat_common2_receive(usb_dev,
82 ROCCAT_COMMON_COMMAND_CONTROL,
83 &control, sizeof(struct roccat_common2_control));
84
85 if (retval)
86 return retval;
87
88 switch (control.value) {
89 case ROCCAT_COMMON_CONTROL_STATUS_OK:
90 return 0;
91 case ROCCAT_COMMON_CONTROL_STATUS_WAIT:
92 msleep(500);
93 continue;
94 case ROCCAT_COMMON_CONTROL_STATUS_INVALID:
95
96 case ROCCAT_COMMON_CONTROL_STATUS_OVERLOAD:
97 /* seems to be critical - replug necessary */
98 return -EINVAL;
99 default:
100 dev_err(&usb_dev->dev,
101 "roccat_common2_receive_control_status: "
102 "unknown response value 0x%x\n",
103 control.value);
104 return -EINVAL;
105 }
106
107 } while (1);
108}
109
110int roccat_common2_send_with_status(struct usb_device *usb_dev,
111 uint command, void const *buf, uint size)
112{
113 int retval;
114
115 retval = roccat_common2_send(usb_dev, command, buf, size);
116 if (retval)
117 return retval;
118
119 msleep(100);
120
121 return roccat_common2_receive_control_status(usb_dev);
122}
123EXPORT_SYMBOL_GPL(roccat_common2_send_with_status);
66 124
67MODULE_AUTHOR("Stefan Achatz"); 125MODULE_AUTHOR("Stefan Achatz");
68MODULE_DESCRIPTION("USB Roccat common driver"); 126MODULE_DESCRIPTION("USB Roccat common driver");
diff --git a/drivers/hid/hid-roccat-common.h b/drivers/hid/hid-roccat-common.h
index 9a5bc61f9699..a97746a63b70 100644
--- a/drivers/hid/hid-roccat-common.h
+++ b/drivers/hid/hid-roccat-common.h
@@ -15,9 +15,21 @@
15#include <linux/usb.h> 15#include <linux/usb.h>
16#include <linux/types.h> 16#include <linux/types.h>
17 17
18int roccat_common_receive(struct usb_device *usb_dev, uint report_id, 18enum roccat_common2_commands {
19 ROCCAT_COMMON_COMMAND_CONTROL = 0x4,
20};
21
22struct roccat_common2_control {
23 uint8_t command;
24 uint8_t value;
25 uint8_t request; /* always 0 on requesting write check */
26} __packed;
27
28int roccat_common2_receive(struct usb_device *usb_dev, uint report_id,
19 void *data, uint size); 29 void *data, uint size);
20int roccat_common_send(struct usb_device *usb_dev, uint report_id, 30int roccat_common2_send(struct usb_device *usb_dev, uint report_id,
21 void const *data, uint size); 31 void const *data, uint size);
32int roccat_common2_send_with_status(struct usb_device *usb_dev,
33 uint command, void const *buf, uint size);
22 34
23#endif 35#endif
diff --git a/drivers/hid/hid-roccat-isku.c b/drivers/hid/hid-roccat-isku.c
index 0e4a0ab47142..5669916c2943 100644
--- a/drivers/hid/hid-roccat-isku.c
+++ b/drivers/hid/hid-roccat-isku.c
@@ -36,51 +36,7 @@ static void isku_profile_activated(struct isku_device *isku, uint new_profile)
36static int isku_receive(struct usb_device *usb_dev, uint command, 36static int isku_receive(struct usb_device *usb_dev, uint command,
37 void *buf, uint size) 37 void *buf, uint size)
38{ 38{
39 return roccat_common_receive(usb_dev, command, buf, size); 39 return roccat_common2_receive(usb_dev, command, buf, size);
40}
41
42static int isku_receive_control_status(struct usb_device *usb_dev)
43{
44 int retval;
45 struct isku_control control;
46
47 do {
48 msleep(50);
49 retval = isku_receive(usb_dev, ISKU_COMMAND_CONTROL,
50 &control, sizeof(struct isku_control));
51
52 if (retval)
53 return retval;
54
55 switch (control.value) {
56 case ISKU_CONTROL_VALUE_STATUS_OK:
57 return 0;
58 case ISKU_CONTROL_VALUE_STATUS_WAIT:
59 continue;
60 case ISKU_CONTROL_VALUE_STATUS_INVALID:
61 /* seems to be critical - replug necessary */
62 case ISKU_CONTROL_VALUE_STATUS_OVERLOAD:
63 return -EINVAL;
64 default:
65 hid_err(usb_dev, "isku_receive_control_status: "
66 "unknown response value 0x%x\n",
67 control.value);
68 return -EINVAL;
69 }
70
71 } while (1);
72}
73
74static int isku_send(struct usb_device *usb_dev, uint command,
75 void const *buf, uint size)
76{
77 int retval;
78
79 retval = roccat_common_send(usb_dev, command, buf, size);
80 if (retval)
81 return retval;
82
83 return isku_receive_control_status(usb_dev);
84} 40}
85 41
86static int isku_get_actual_profile(struct usb_device *usb_dev) 42static int isku_get_actual_profile(struct usb_device *usb_dev)
@@ -100,7 +56,8 @@ static int isku_set_actual_profile(struct usb_device *usb_dev, int new_profile)
100 buf.command = ISKU_COMMAND_ACTUAL_PROFILE; 56 buf.command = ISKU_COMMAND_ACTUAL_PROFILE;
101 buf.size = sizeof(struct isku_actual_profile); 57 buf.size = sizeof(struct isku_actual_profile);
102 buf.actual_profile = new_profile; 58 buf.actual_profile = new_profile;
103 return isku_send(usb_dev, ISKU_COMMAND_ACTUAL_PROFILE, &buf, 59 return roccat_common2_send_with_status(usb_dev,
60 ISKU_COMMAND_ACTUAL_PROFILE, &buf,
104 sizeof(struct isku_actual_profile)); 61 sizeof(struct isku_actual_profile));
105} 62}
106 63
@@ -197,7 +154,8 @@ static ssize_t isku_sysfs_write(struct file *fp, struct kobject *kobj,
197 return -EINVAL; 154 return -EINVAL;
198 155
199 mutex_lock(&isku->isku_lock); 156 mutex_lock(&isku->isku_lock);
200 retval = isku_send(usb_dev, command, (void *)buf, real_size); 157 retval = roccat_common2_send_with_status(usb_dev, command,
158 (void *)buf, real_size);
201 mutex_unlock(&isku->isku_lock); 159 mutex_unlock(&isku->isku_lock);
202 160
203 return retval ? retval : real_size; 161 return retval ? retval : real_size;
diff --git a/drivers/hid/hid-roccat-isku.h b/drivers/hid/hid-roccat-isku.h
index 075f6efaec58..605b3ce21638 100644
--- a/drivers/hid/hid-roccat-isku.h
+++ b/drivers/hid/hid-roccat-isku.h
@@ -25,13 +25,6 @@ struct isku_control {
25 uint8_t request; 25 uint8_t request;
26} __packed; 26} __packed;
27 27
28enum isku_control_values {
29 ISKU_CONTROL_VALUE_STATUS_OVERLOAD = 0,
30 ISKU_CONTROL_VALUE_STATUS_OK = 1,
31 ISKU_CONTROL_VALUE_STATUS_INVALID = 2,
32 ISKU_CONTROL_VALUE_STATUS_WAIT = 3,
33};
34
35struct isku_actual_profile { 28struct isku_actual_profile {
36 uint8_t command; /* ISKU_COMMAND_ACTUAL_PROFILE */ 29 uint8_t command; /* ISKU_COMMAND_ACTUAL_PROFILE */
37 uint8_t size; /* always 3 */ 30 uint8_t size; /* always 3 */
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c
index 40090d602158..9ce2d0b615a4 100644
--- a/drivers/hid/hid-roccat-kone.c
+++ b/drivers/hid/hid-roccat-kone.c
@@ -138,7 +138,7 @@ static int kone_check_write(struct usb_device *usb_dev)
138 return 0; 138 return 0;
139 139
140 /* unknown answer */ 140 /* unknown answer */
141 hid_err(usb_dev, "got retval %d when checking write\n", data); 141 dev_err(&usb_dev->dev, "got retval %d when checking write\n", data);
142 return -EIO; 142 return -EIO;
143} 143}
144 144
@@ -503,7 +503,7 @@ static ssize_t kone_sysfs_set_tcu(struct device *dev,
503 503
504 retval = kone_set_settings(usb_dev, &kone->settings); 504 retval = kone_set_settings(usb_dev, &kone->settings);
505 if (retval) { 505 if (retval) {
506 hid_err(usb_dev, "couldn't set tcu state\n"); 506 dev_err(&usb_dev->dev, "couldn't set tcu state\n");
507 /* 507 /*
508 * try to reread valid settings into buffer overwriting 508 * try to reread valid settings into buffer overwriting
509 * first error code 509 * first error code
@@ -519,7 +519,7 @@ static ssize_t kone_sysfs_set_tcu(struct device *dev,
519 519
520 retval = size; 520 retval = size;
521exit_no_settings: 521exit_no_settings:
522 hid_err(usb_dev, "couldn't read settings\n"); 522 dev_err(&usb_dev->dev, "couldn't read settings\n");
523exit_unlock: 523exit_unlock:
524 mutex_unlock(&kone->kone_lock); 524 mutex_unlock(&kone->kone_lock);
525 return retval; 525 return retval;
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c
index 59e47770fa10..f5602fec4865 100644
--- a/drivers/hid/hid-roccat-koneplus.c
+++ b/drivers/hid/hid-roccat-koneplus.c
@@ -39,88 +39,26 @@ static void koneplus_profile_activated(struct koneplus_device *koneplus,
39static int koneplus_send_control(struct usb_device *usb_dev, uint value, 39static int koneplus_send_control(struct usb_device *usb_dev, uint value,
40 enum koneplus_control_requests request) 40 enum koneplus_control_requests request)
41{ 41{
42 struct koneplus_control control; 42 struct roccat_common2_control control;
43 43
44 if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS || 44 if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS ||
45 request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) && 45 request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) &&
46 value > 4) 46 value > 4)
47 return -EINVAL; 47 return -EINVAL;
48 48
49 control.command = KONEPLUS_COMMAND_CONTROL; 49 control.command = ROCCAT_COMMON_COMMAND_CONTROL;
50 control.value = value; 50 control.value = value;
51 control.request = request; 51 control.request = request;
52 52
53 return roccat_common_send(usb_dev, KONEPLUS_COMMAND_CONTROL, 53 return roccat_common2_send_with_status(usb_dev,
54 &control, sizeof(struct koneplus_control)); 54 ROCCAT_COMMON_COMMAND_CONTROL,
55} 55 &control, sizeof(struct roccat_common2_control));
56
57static int koneplus_receive_control_status(struct usb_device *usb_dev)
58{
59 int retval;
60 struct koneplus_control control;
61
62 do {
63 retval = roccat_common_receive(usb_dev, KONEPLUS_COMMAND_CONTROL,
64 &control, sizeof(struct koneplus_control));
65
66 /* check if we get a completely wrong answer */
67 if (retval)
68 return retval;
69
70 if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OK)
71 return 0;
72
73 /* indicates that hardware needs some more time to complete action */
74 if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) {
75 msleep(500); /* windows driver uses 1000 */
76 continue;
77 }
78
79 /* seems to be critical - replug necessary */
80 if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD)
81 return -EINVAL;
82
83 hid_err(usb_dev, "koneplus_receive_control_status: "
84 "unknown response value 0x%x\n", control.value);
85 return -EINVAL;
86 } while (1);
87}
88
89static int koneplus_send(struct usb_device *usb_dev, uint command,
90 void const *buf, uint size)
91{
92 int retval;
93
94 retval = roccat_common_send(usb_dev, command, buf, size);
95 if (retval)
96 return retval;
97
98 return koneplus_receive_control_status(usb_dev);
99}
100
101static int koneplus_select_profile(struct usb_device *usb_dev, uint number,
102 enum koneplus_control_requests request)
103{
104 int retval;
105
106 retval = koneplus_send_control(usb_dev, number, request);
107 if (retval)
108 return retval;
109
110 /* allow time to settle things - windows driver uses 500 */
111 msleep(100);
112
113 retval = koneplus_receive_control_status(usb_dev);
114 if (retval)
115 return retval;
116
117 return 0;
118} 56}
119 57
120static int koneplus_get_info(struct usb_device *usb_dev, 58static int koneplus_get_info(struct usb_device *usb_dev,
121 struct koneplus_info *buf) 59 struct koneplus_info *buf)
122{ 60{
123 return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_INFO, 61 return roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_INFO,
124 buf, sizeof(struct koneplus_info)); 62 buf, sizeof(struct koneplus_info));
125} 63}
126 64
@@ -129,19 +67,20 @@ static int koneplus_get_profile_settings(struct usb_device *usb_dev,
129{ 67{
130 int retval; 68 int retval;
131 69
132 retval = koneplus_select_profile(usb_dev, number, 70 retval = koneplus_send_control(usb_dev, number,
133 KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS); 71 KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS);
134 if (retval) 72 if (retval)
135 return retval; 73 return retval;
136 74
137 return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS, 75 return roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS,
138 buf, sizeof(struct koneplus_profile_settings)); 76 buf, sizeof(struct koneplus_profile_settings));
139} 77}
140 78
141static int koneplus_set_profile_settings(struct usb_device *usb_dev, 79static int koneplus_set_profile_settings(struct usb_device *usb_dev,
142 struct koneplus_profile_settings const *settings) 80 struct koneplus_profile_settings const *settings)
143{ 81{
144 return koneplus_send(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS, 82 return roccat_common2_send_with_status(usb_dev,
83 KONEPLUS_COMMAND_PROFILE_SETTINGS,
145 settings, sizeof(struct koneplus_profile_settings)); 84 settings, sizeof(struct koneplus_profile_settings));
146} 85}
147 86
@@ -150,19 +89,20 @@ static int koneplus_get_profile_buttons(struct usb_device *usb_dev,
150{ 89{
151 int retval; 90 int retval;
152 91
153 retval = koneplus_select_profile(usb_dev, number, 92 retval = koneplus_send_control(usb_dev, number,
154 KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS); 93 KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS);
155 if (retval) 94 if (retval)
156 return retval; 95 return retval;
157 96
158 return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS, 97 return roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS,
159 buf, sizeof(struct koneplus_profile_buttons)); 98 buf, sizeof(struct koneplus_profile_buttons));
160} 99}
161 100
162static int koneplus_set_profile_buttons(struct usb_device *usb_dev, 101static int koneplus_set_profile_buttons(struct usb_device *usb_dev,
163 struct koneplus_profile_buttons const *buttons) 102 struct koneplus_profile_buttons const *buttons)
164{ 103{
165 return koneplus_send(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS, 104 return roccat_common2_send_with_status(usb_dev,
105 KONEPLUS_COMMAND_PROFILE_BUTTONS,
166 buttons, sizeof(struct koneplus_profile_buttons)); 106 buttons, sizeof(struct koneplus_profile_buttons));
167} 107}
168 108
@@ -172,7 +112,7 @@ static int koneplus_get_actual_profile(struct usb_device *usb_dev)
172 struct koneplus_actual_profile buf; 112 struct koneplus_actual_profile buf;
173 int retval; 113 int retval;
174 114
175 retval = roccat_common_receive(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE, 115 retval = roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE,
176 &buf, sizeof(struct koneplus_actual_profile)); 116 &buf, sizeof(struct koneplus_actual_profile));
177 117
178 return retval ? retval : buf.actual_profile; 118 return retval ? retval : buf.actual_profile;
@@ -187,7 +127,8 @@ static int koneplus_set_actual_profile(struct usb_device *usb_dev,
187 buf.size = sizeof(struct koneplus_actual_profile); 127 buf.size = sizeof(struct koneplus_actual_profile);
188 buf.actual_profile = new_profile; 128 buf.actual_profile = new_profile;
189 129
190 return koneplus_send(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE, 130 return roccat_common2_send_with_status(usb_dev,
131 KONEPLUS_COMMAND_ACTUAL_PROFILE,
191 &buf, sizeof(struct koneplus_actual_profile)); 132 &buf, sizeof(struct koneplus_actual_profile));
192} 133}
193 134
@@ -208,7 +149,7 @@ static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj,
208 return -EINVAL; 149 return -EINVAL;
209 150
210 mutex_lock(&koneplus->koneplus_lock); 151 mutex_lock(&koneplus->koneplus_lock);
211 retval = roccat_common_receive(usb_dev, command, buf, real_size); 152 retval = roccat_common2_receive(usb_dev, command, buf, real_size);
212 mutex_unlock(&koneplus->koneplus_lock); 153 mutex_unlock(&koneplus->koneplus_lock);
213 154
214 if (retval) 155 if (retval)
@@ -231,7 +172,8 @@ static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj,
231 return -EINVAL; 172 return -EINVAL;
232 173
233 mutex_lock(&koneplus->koneplus_lock); 174 mutex_lock(&koneplus->koneplus_lock);
234 retval = koneplus_send(usb_dev, command, buf, real_size); 175 retval = roccat_common2_send_with_status(usb_dev, command,
176 buf, real_size);
235 mutex_unlock(&koneplus->koneplus_lock); 177 mutex_unlock(&koneplus->koneplus_lock);
236 178
237 if (retval) 179 if (retval)
diff --git a/drivers/hid/hid-roccat-koneplus.h b/drivers/hid/hid-roccat-koneplus.h
index c03332a4fa9a..7074b2a4b94b 100644
--- a/drivers/hid/hid-roccat-koneplus.h
+++ b/drivers/hid/hid-roccat-koneplus.h
@@ -20,32 +20,11 @@ struct koneplus_talk {
20 uint8_t data[14]; 20 uint8_t data[14];
21} __packed; 21} __packed;
22 22
23/*
24 * case 1: writes request 80 and reads value 1
25 *
26 */
27struct koneplus_control {
28 uint8_t command; /* KONEPLUS_COMMAND_CONTROL */
29 /*
30 * value is profile number in range 0-4 for requesting settings and buttons
31 * 1 if status ok for requesting status
32 */
33 uint8_t value;
34 uint8_t request;
35} __attribute__ ((__packed__));
36
37enum koneplus_control_requests { 23enum koneplus_control_requests {
38 KONEPLUS_CONTROL_REQUEST_STATUS = 0x00,
39 KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x80, 24 KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x80,
40 KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x90, 25 KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x90,
41}; 26};
42 27
43enum koneplus_control_values {
44 KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD = 0,
45 KONEPLUS_CONTROL_REQUEST_STATUS_OK = 1,
46 KONEPLUS_CONTROL_REQUEST_STATUS_WAIT = 3,
47};
48
49struct koneplus_actual_profile { 28struct koneplus_actual_profile {
50 uint8_t command; /* KONEPLUS_COMMAND_ACTUAL_PROFILE */ 29 uint8_t command; /* KONEPLUS_COMMAND_ACTUAL_PROFILE */
51 uint8_t size; /* always 3 */ 30 uint8_t size; /* always 3 */
@@ -137,7 +116,6 @@ struct koneplus_tcu_image {
137} __attribute__ ((__packed__)); 116} __attribute__ ((__packed__));
138 117
139enum koneplus_commands { 118enum koneplus_commands {
140 KONEPLUS_COMMAND_CONTROL = 0x4,
141 KONEPLUS_COMMAND_ACTUAL_PROFILE = 0x5, 119 KONEPLUS_COMMAND_ACTUAL_PROFILE = 0x5,
142 KONEPLUS_COMMAND_PROFILE_SETTINGS = 0x6, 120 KONEPLUS_COMMAND_PROFILE_SETTINGS = 0x6,
143 KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7, 121 KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c
index 112d934132c8..ca6527ac655d 100644
--- a/drivers/hid/hid-roccat-kovaplus.c
+++ b/drivers/hid/hid-roccat-kovaplus.c
@@ -47,69 +47,23 @@ static int kovaplus_send_control(struct usb_device *usb_dev, uint value,
47 enum kovaplus_control_requests request) 47 enum kovaplus_control_requests request)
48{ 48{
49 int retval; 49 int retval;
50 struct kovaplus_control control; 50 struct roccat_common2_control control;
51 51
52 if ((request == KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS || 52 if ((request == KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS ||
53 request == KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) && 53 request == KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) &&
54 value > 4) 54 value > 4)
55 return -EINVAL; 55 return -EINVAL;
56 56
57 control.command = KOVAPLUS_COMMAND_CONTROL; 57 control.command = ROCCAT_COMMON_COMMAND_CONTROL;
58 control.value = value; 58 control.value = value;
59 control.request = request; 59 control.request = request;
60 60
61 retval = roccat_common_send(usb_dev, KOVAPLUS_COMMAND_CONTROL, 61 retval = roccat_common2_send(usb_dev, ROCCAT_COMMON_COMMAND_CONTROL,
62 &control, sizeof(struct kovaplus_control)); 62 &control, sizeof(struct roccat_common2_control));
63 63
64 return retval; 64 return retval;
65} 65}
66 66
67static int kovaplus_receive_control_status(struct usb_device *usb_dev)
68{
69 int retval;
70 struct kovaplus_control control;
71
72 do {
73 retval = roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_CONTROL,
74 &control, sizeof(struct kovaplus_control));
75
76 /* check if we get a completely wrong answer */
77 if (retval)
78 return retval;
79
80 if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_OK)
81 return 0;
82
83 /* indicates that hardware needs some more time to complete action */
84 if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_WAIT) {
85 msleep(500); /* windows driver uses 1000 */
86 continue;
87 }
88
89 /* seems to be critical - replug necessary */
90 if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_OVERLOAD)
91 return -EINVAL;
92
93 hid_err(usb_dev, "roccat_common_receive_control_status: "
94 "unknown response value 0x%x\n", control.value);
95 return -EINVAL;
96 } while (1);
97}
98
99static int kovaplus_send(struct usb_device *usb_dev, uint command,
100 void const *buf, uint size)
101{
102 int retval;
103
104 retval = roccat_common_send(usb_dev, command, buf, size);
105 if (retval)
106 return retval;
107
108 msleep(100);
109
110 return kovaplus_receive_control_status(usb_dev);
111}
112
113static int kovaplus_select_profile(struct usb_device *usb_dev, uint number, 67static int kovaplus_select_profile(struct usb_device *usb_dev, uint number,
114 enum kovaplus_control_requests request) 68 enum kovaplus_control_requests request)
115{ 69{
@@ -119,7 +73,7 @@ static int kovaplus_select_profile(struct usb_device *usb_dev, uint number,
119static int kovaplus_get_info(struct usb_device *usb_dev, 73static int kovaplus_get_info(struct usb_device *usb_dev,
120 struct kovaplus_info *buf) 74 struct kovaplus_info *buf)
121{ 75{
122 return roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_INFO, 76 return roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_INFO,
123 buf, sizeof(struct kovaplus_info)); 77 buf, sizeof(struct kovaplus_info));
124} 78}
125 79
@@ -133,14 +87,15 @@ static int kovaplus_get_profile_settings(struct usb_device *usb_dev,
133 if (retval) 87 if (retval)
134 return retval; 88 return retval;
135 89
136 return roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_SETTINGS, 90 return roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_SETTINGS,
137 buf, sizeof(struct kovaplus_profile_settings)); 91 buf, sizeof(struct kovaplus_profile_settings));
138} 92}
139 93
140static int kovaplus_set_profile_settings(struct usb_device *usb_dev, 94static int kovaplus_set_profile_settings(struct usb_device *usb_dev,
141 struct kovaplus_profile_settings const *settings) 95 struct kovaplus_profile_settings const *settings)
142{ 96{
143 return kovaplus_send(usb_dev, KOVAPLUS_COMMAND_PROFILE_SETTINGS, 97 return roccat_common2_send_with_status(usb_dev,
98 KOVAPLUS_COMMAND_PROFILE_SETTINGS,
144 settings, sizeof(struct kovaplus_profile_settings)); 99 settings, sizeof(struct kovaplus_profile_settings));
145} 100}
146 101
@@ -154,14 +109,15 @@ static int kovaplus_get_profile_buttons(struct usb_device *usb_dev,
154 if (retval) 109 if (retval)
155 return retval; 110 return retval;
156 111
157 return roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_BUTTONS, 112 return roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_BUTTONS,
158 buf, sizeof(struct kovaplus_profile_buttons)); 113 buf, sizeof(struct kovaplus_profile_buttons));
159} 114}
160 115
161static int kovaplus_set_profile_buttons(struct usb_device *usb_dev, 116static int kovaplus_set_profile_buttons(struct usb_device *usb_dev,
162 struct kovaplus_profile_buttons const *buttons) 117 struct kovaplus_profile_buttons const *buttons)
163{ 118{
164 return kovaplus_send(usb_dev, KOVAPLUS_COMMAND_PROFILE_BUTTONS, 119 return roccat_common2_send_with_status(usb_dev,
120 KOVAPLUS_COMMAND_PROFILE_BUTTONS,
165 buttons, sizeof(struct kovaplus_profile_buttons)); 121 buttons, sizeof(struct kovaplus_profile_buttons));
166} 122}
167 123
@@ -171,7 +127,7 @@ static int kovaplus_get_actual_profile(struct usb_device *usb_dev)
171 struct kovaplus_actual_profile buf; 127 struct kovaplus_actual_profile buf;
172 int retval; 128 int retval;
173 129
174 retval = roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_ACTUAL_PROFILE, 130 retval = roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_ACTUAL_PROFILE,
175 &buf, sizeof(struct kovaplus_actual_profile)); 131 &buf, sizeof(struct kovaplus_actual_profile));
176 132
177 return retval ? retval : buf.actual_profile; 133 return retval ? retval : buf.actual_profile;
@@ -186,7 +142,8 @@ static int kovaplus_set_actual_profile(struct usb_device *usb_dev,
186 buf.size = sizeof(struct kovaplus_actual_profile); 142 buf.size = sizeof(struct kovaplus_actual_profile);
187 buf.actual_profile = new_profile; 143 buf.actual_profile = new_profile;
188 144
189 return kovaplus_send(usb_dev, KOVAPLUS_COMMAND_ACTUAL_PROFILE, 145 return roccat_common2_send_with_status(usb_dev,
146 KOVAPLUS_COMMAND_ACTUAL_PROFILE,
190 &buf, sizeof(struct kovaplus_actual_profile)); 147 &buf, sizeof(struct kovaplus_actual_profile));
191} 148}
192 149
diff --git a/drivers/hid/hid-roccat-kovaplus.h b/drivers/hid/hid-roccat-kovaplus.h
index fb2aed44a8e0..f82daa1cdcb9 100644
--- a/drivers/hid/hid-roccat-kovaplus.h
+++ b/drivers/hid/hid-roccat-kovaplus.h
@@ -14,27 +14,13 @@
14 14
15#include <linux/types.h> 15#include <linux/types.h>
16 16
17struct kovaplus_control {
18 uint8_t command; /* KOVAPLUS_COMMAND_CONTROL */
19 uint8_t value;
20 uint8_t request;
21} __packed;
22
23enum kovaplus_control_requests { 17enum kovaplus_control_requests {
24 /* read after write; value = 1 */
25 KOVAPLUS_CONTROL_REQUEST_STATUS = 0x0,
26 /* write; value = profile number range 0-4 */ 18 /* write; value = profile number range 0-4 */
27 KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10, 19 KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10,
28 /* write; value = profile number range 0-4 */ 20 /* write; value = profile number range 0-4 */
29 KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20, 21 KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20,
30}; 22};
31 23
32enum kovaplus_control_values {
33 KOVAPLUS_CONTROL_REQUEST_STATUS_OVERLOAD = 0, /* supposed */
34 KOVAPLUS_CONTROL_REQUEST_STATUS_OK = 1,
35 KOVAPLUS_CONTROL_REQUEST_STATUS_WAIT = 3, /* supposed */
36};
37
38struct kovaplus_actual_profile { 24struct kovaplus_actual_profile {
39 uint8_t command; /* KOVAPLUS_COMMAND_ACTUAL_PROFILE */ 25 uint8_t command; /* KOVAPLUS_COMMAND_ACTUAL_PROFILE */
40 uint8_t size; /* always 3 */ 26 uint8_t size; /* always 3 */
@@ -75,7 +61,6 @@ struct kovaplus_a {
75} __packed; 61} __packed;
76 62
77enum kovaplus_commands { 63enum kovaplus_commands {
78 KOVAPLUS_COMMAND_CONTROL = 0x4,
79 KOVAPLUS_COMMAND_ACTUAL_PROFILE = 0x5, 64 KOVAPLUS_COMMAND_ACTUAL_PROFILE = 0x5,
80 KOVAPLUS_COMMAND_PROFILE_SETTINGS = 0x6, 65 KOVAPLUS_COMMAND_PROFILE_SETTINGS = 0x6,
81 KOVAPLUS_COMMAND_PROFILE_BUTTONS = 0x7, 66 KOVAPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c
index df05c1b1064f..1317c177a3e2 100644
--- a/drivers/hid/hid-roccat-pyra.c
+++ b/drivers/hid/hid-roccat-pyra.c
@@ -42,43 +42,19 @@ static void profile_activated(struct pyra_device *pyra,
42static int pyra_send_control(struct usb_device *usb_dev, int value, 42static int pyra_send_control(struct usb_device *usb_dev, int value,
43 enum pyra_control_requests request) 43 enum pyra_control_requests request)
44{ 44{
45 struct pyra_control control; 45 struct roccat_common2_control control;
46 46
47 if ((request == PYRA_CONTROL_REQUEST_PROFILE_SETTINGS || 47 if ((request == PYRA_CONTROL_REQUEST_PROFILE_SETTINGS ||
48 request == PYRA_CONTROL_REQUEST_PROFILE_BUTTONS) && 48 request == PYRA_CONTROL_REQUEST_PROFILE_BUTTONS) &&
49 (value < 0 || value > 4)) 49 (value < 0 || value > 4))
50 return -EINVAL; 50 return -EINVAL;
51 51
52 control.command = PYRA_COMMAND_CONTROL; 52 control.command = ROCCAT_COMMON_COMMAND_CONTROL;
53 control.value = value; 53 control.value = value;
54 control.request = request; 54 control.request = request;
55 55
56 return roccat_common_send(usb_dev, PYRA_COMMAND_CONTROL, 56 return roccat_common2_send(usb_dev, ROCCAT_COMMON_COMMAND_CONTROL,
57 &control, sizeof(struct pyra_control)); 57 &control, sizeof(struct roccat_common2_control));
58}
59
60static int pyra_receive_control_status(struct usb_device *usb_dev)
61{
62 int retval;
63 struct pyra_control control;
64
65 do {
66 msleep(10);
67 retval = roccat_common_receive(usb_dev, PYRA_COMMAND_CONTROL,
68 &control, sizeof(struct pyra_control));
69
70 /* requested too early, try again */
71 } while (retval == -EPROTO);
72
73 if (!retval && control.command == PYRA_COMMAND_CONTROL &&
74 control.request == PYRA_CONTROL_REQUEST_STATUS &&
75 control.value == 1)
76 return 0;
77 else {
78 hid_err(usb_dev, "receive control status: unknown response 0x%x 0x%x\n",
79 control.request, control.value);
80 return retval ? retval : -EINVAL;
81 }
82} 58}
83 59
84static int pyra_get_profile_settings(struct usb_device *usb_dev, 60static int pyra_get_profile_settings(struct usb_device *usb_dev,
@@ -89,7 +65,7 @@ static int pyra_get_profile_settings(struct usb_device *usb_dev,
89 PYRA_CONTROL_REQUEST_PROFILE_SETTINGS); 65 PYRA_CONTROL_REQUEST_PROFILE_SETTINGS);
90 if (retval) 66 if (retval)
91 return retval; 67 return retval;
92 return roccat_common_receive(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS, 68 return roccat_common2_receive(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS,
93 buf, sizeof(struct pyra_profile_settings)); 69 buf, sizeof(struct pyra_profile_settings));
94} 70}
95 71
@@ -101,51 +77,44 @@ static int pyra_get_profile_buttons(struct usb_device *usb_dev,
101 PYRA_CONTROL_REQUEST_PROFILE_BUTTONS); 77 PYRA_CONTROL_REQUEST_PROFILE_BUTTONS);
102 if (retval) 78 if (retval)
103 return retval; 79 return retval;
104 return roccat_common_receive(usb_dev, PYRA_COMMAND_PROFILE_BUTTONS, 80 return roccat_common2_receive(usb_dev, PYRA_COMMAND_PROFILE_BUTTONS,
105 buf, sizeof(struct pyra_profile_buttons)); 81 buf, sizeof(struct pyra_profile_buttons));
106} 82}
107 83
108static int pyra_get_settings(struct usb_device *usb_dev, 84static int pyra_get_settings(struct usb_device *usb_dev,
109 struct pyra_settings *buf) 85 struct pyra_settings *buf)
110{ 86{
111 return roccat_common_receive(usb_dev, PYRA_COMMAND_SETTINGS, 87 return roccat_common2_receive(usb_dev, PYRA_COMMAND_SETTINGS,
112 buf, sizeof(struct pyra_settings)); 88 buf, sizeof(struct pyra_settings));
113} 89}
114 90
115static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf) 91static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf)
116{ 92{
117 return roccat_common_receive(usb_dev, PYRA_COMMAND_INFO, 93 return roccat_common2_receive(usb_dev, PYRA_COMMAND_INFO,
118 buf, sizeof(struct pyra_info)); 94 buf, sizeof(struct pyra_info));
119} 95}
120 96
121static int pyra_send(struct usb_device *usb_dev, uint command,
122 void const *buf, uint size)
123{
124 int retval;
125 retval = roccat_common_send(usb_dev, command, buf, size);
126 if (retval)
127 return retval;
128 return pyra_receive_control_status(usb_dev);
129}
130
131static int pyra_set_profile_settings(struct usb_device *usb_dev, 97static int pyra_set_profile_settings(struct usb_device *usb_dev,
132 struct pyra_profile_settings const *settings) 98 struct pyra_profile_settings const *settings)
133{ 99{
134 return pyra_send(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS, settings, 100 return roccat_common2_send_with_status(usb_dev,
101 PYRA_COMMAND_PROFILE_SETTINGS, settings,
135 sizeof(struct pyra_profile_settings)); 102 sizeof(struct pyra_profile_settings));
136} 103}
137 104
138static int pyra_set_profile_buttons(struct usb_device *usb_dev, 105static int pyra_set_profile_buttons(struct usb_device *usb_dev,
139 struct pyra_profile_buttons const *buttons) 106 struct pyra_profile_buttons const *buttons)
140{ 107{
141 return pyra_send(usb_dev, PYRA_COMMAND_PROFILE_BUTTONS, buttons, 108 return roccat_common2_send_with_status(usb_dev,
109 PYRA_COMMAND_PROFILE_BUTTONS, buttons,
142 sizeof(struct pyra_profile_buttons)); 110 sizeof(struct pyra_profile_buttons));
143} 111}
144 112
145static int pyra_set_settings(struct usb_device *usb_dev, 113static int pyra_set_settings(struct usb_device *usb_dev,
146 struct pyra_settings const *settings) 114 struct pyra_settings const *settings)
147{ 115{
148 return pyra_send(usb_dev, PYRA_COMMAND_SETTINGS, settings, 116 return roccat_common2_send_with_status(usb_dev,
117 PYRA_COMMAND_SETTINGS, settings,
149 sizeof(struct pyra_settings)); 118 sizeof(struct pyra_settings));
150} 119}
151 120
diff --git a/drivers/hid/hid-roccat-pyra.h b/drivers/hid/hid-roccat-pyra.h
index 0442d7fa2dcf..eada7830fa99 100644
--- a/drivers/hid/hid-roccat-pyra.h
+++ b/drivers/hid/hid-roccat-pyra.h
@@ -20,18 +20,7 @@ struct pyra_b {
20 uint8_t unknown; /* 1 */ 20 uint8_t unknown; /* 1 */
21} __attribute__ ((__packed__)); 21} __attribute__ ((__packed__));
22 22
23struct pyra_control {
24 uint8_t command; /* PYRA_COMMAND_CONTROL */
25 /*
26 * value is profile number for request_settings and request_buttons
27 * 1 if status ok for request_status
28 */
29 uint8_t value; /* Range 0-4 */
30 uint8_t request;
31} __attribute__ ((__packed__));
32
33enum pyra_control_requests { 23enum pyra_control_requests {
34 PYRA_CONTROL_REQUEST_STATUS = 0x00,
35 PYRA_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10, 24 PYRA_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10,
36 PYRA_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20 25 PYRA_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20
37}; 26};
@@ -75,7 +64,6 @@ struct pyra_info {
75} __attribute__ ((__packed__)); 64} __attribute__ ((__packed__));
76 65
77enum pyra_commands { 66enum pyra_commands {
78 PYRA_COMMAND_CONTROL = 0x4,
79 PYRA_COMMAND_SETTINGS = 0x5, 67 PYRA_COMMAND_SETTINGS = 0x5,
80 PYRA_COMMAND_PROFILE_SETTINGS = 0x6, 68 PYRA_COMMAND_PROFILE_SETTINGS = 0x6,
81 PYRA_COMMAND_PROFILE_BUTTONS = 0x7, 69 PYRA_COMMAND_PROFILE_BUTTONS = 0x7,
diff --git a/drivers/hid/hid-roccat-savu.c b/drivers/hid/hid-roccat-savu.c
new file mode 100644
index 000000000000..014afba407e0
--- /dev/null
+++ b/drivers/hid/hid-roccat-savu.c
@@ -0,0 +1,316 @@
1/*
2 * Roccat Savu driver for Linux
3 *
4 * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net>
5 */
6
7/*
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 */
13
14/* Roccat Savu is a gamer mouse with macro keys that can be configured in
15 * 5 profiles.
16 */
17
18#include <linux/device.h>
19#include <linux/input.h>
20#include <linux/hid.h>
21#include <linux/module.h>
22#include <linux/slab.h>
23#include <linux/hid-roccat.h>
24#include "hid-ids.h"
25#include "hid-roccat-common.h"
26#include "hid-roccat-savu.h"
27
28static struct class *savu_class;
29
30static ssize_t savu_sysfs_read(struct file *fp, struct kobject *kobj,
31 char *buf, loff_t off, size_t count,
32 size_t real_size, uint command)
33{
34 struct device *dev =
35 container_of(kobj, struct device, kobj)->parent->parent;
36 struct savu_device *savu = hid_get_drvdata(dev_get_drvdata(dev));
37 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
38 int retval;
39
40 if (off >= real_size)
41 return 0;
42
43 if (off != 0 || count != real_size)
44 return -EINVAL;
45
46 mutex_lock(&savu->savu_lock);
47 retval = roccat_common2_receive(usb_dev, command, buf, real_size);
48 mutex_unlock(&savu->savu_lock);
49
50 return retval ? retval : real_size;
51}
52
53static ssize_t savu_sysfs_write(struct file *fp, struct kobject *kobj,
54 void const *buf, loff_t off, size_t count,
55 size_t real_size, uint command)
56{
57 struct device *dev =
58 container_of(kobj, struct device, kobj)->parent->parent;
59 struct savu_device *savu = hid_get_drvdata(dev_get_drvdata(dev));
60 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
61 int retval;
62
63 if (off != 0 || count != real_size)
64 return -EINVAL;
65
66 mutex_lock(&savu->savu_lock);
67 retval = roccat_common2_send_with_status(usb_dev, command,
68 (void *)buf, real_size);
69 mutex_unlock(&savu->savu_lock);
70
71 return retval ? retval : real_size;
72}
73
74#define SAVU_SYSFS_W(thingy, THINGY) \
75static ssize_t savu_sysfs_write_ ## thingy(struct file *fp, \
76 struct kobject *kobj, struct bin_attribute *attr, char *buf, \
77 loff_t off, size_t count) \
78{ \
79 return savu_sysfs_write(fp, kobj, buf, off, count, \
80 SAVU_SIZE_ ## THINGY, SAVU_COMMAND_ ## THINGY); \
81}
82
83#define SAVU_SYSFS_R(thingy, THINGY) \
84static ssize_t savu_sysfs_read_ ## thingy(struct file *fp, \
85 struct kobject *kobj, struct bin_attribute *attr, char *buf, \
86 loff_t off, size_t count) \
87{ \
88 return savu_sysfs_read(fp, kobj, buf, off, count, \
89 SAVU_SIZE_ ## THINGY, SAVU_COMMAND_ ## THINGY); \
90}
91
92#define SAVU_SYSFS_RW(thingy, THINGY) \
93SAVU_SYSFS_W(thingy, THINGY) \
94SAVU_SYSFS_R(thingy, THINGY)
95
96#define SAVU_BIN_ATTRIBUTE_RW(thingy, THINGY) \
97{ \
98 .attr = { .name = #thingy, .mode = 0660 }, \
99 .size = SAVU_SIZE_ ## THINGY, \
100 .read = savu_sysfs_read_ ## thingy, \
101 .write = savu_sysfs_write_ ## thingy \
102}
103
104#define SAVU_BIN_ATTRIBUTE_R(thingy, THINGY) \
105{ \
106 .attr = { .name = #thingy, .mode = 0440 }, \
107 .size = SAVU_SIZE_ ## THINGY, \
108 .read = savu_sysfs_read_ ## thingy, \
109}
110
111#define SAVU_BIN_ATTRIBUTE_W(thingy, THINGY) \
112{ \
113 .attr = { .name = #thingy, .mode = 0220 }, \
114 .size = SAVU_SIZE_ ## THINGY, \
115 .write = savu_sysfs_write_ ## thingy \
116}
117
118SAVU_SYSFS_W(control, CONTROL)
119SAVU_SYSFS_RW(profile, PROFILE)
120SAVU_SYSFS_RW(general, GENERAL)
121SAVU_SYSFS_RW(buttons, BUTTONS)
122SAVU_SYSFS_RW(macro, MACRO)
123SAVU_SYSFS_R(info, INFO)
124SAVU_SYSFS_RW(sensor, SENSOR)
125
126static struct bin_attribute savu_bin_attributes[] = {
127 SAVU_BIN_ATTRIBUTE_W(control, CONTROL),
128 SAVU_BIN_ATTRIBUTE_RW(profile, PROFILE),
129 SAVU_BIN_ATTRIBUTE_RW(general, GENERAL),
130 SAVU_BIN_ATTRIBUTE_RW(buttons, BUTTONS),
131 SAVU_BIN_ATTRIBUTE_RW(macro, MACRO),
132 SAVU_BIN_ATTRIBUTE_R(info, INFO),
133 SAVU_BIN_ATTRIBUTE_RW(sensor, SENSOR),
134 __ATTR_NULL
135};
136
137static int savu_init_savu_device_struct(struct usb_device *usb_dev,
138 struct savu_device *savu)
139{
140 mutex_init(&savu->savu_lock);
141
142 return 0;
143}
144
145static int savu_init_specials(struct hid_device *hdev)
146{
147 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
148 struct usb_device *usb_dev = interface_to_usbdev(intf);
149 struct savu_device *savu;
150 int retval;
151
152 if (intf->cur_altsetting->desc.bInterfaceProtocol
153 != USB_INTERFACE_PROTOCOL_MOUSE) {
154 hid_set_drvdata(hdev, NULL);
155 return 0;
156 }
157
158 savu = kzalloc(sizeof(*savu), GFP_KERNEL);
159 if (!savu) {
160 hid_err(hdev, "can't alloc device descriptor\n");
161 return -ENOMEM;
162 }
163 hid_set_drvdata(hdev, savu);
164
165 retval = savu_init_savu_device_struct(usb_dev, savu);
166 if (retval) {
167 hid_err(hdev, "couldn't init struct savu_device\n");
168 goto exit_free;
169 }
170
171 retval = roccat_connect(savu_class, hdev,
172 sizeof(struct savu_roccat_report));
173 if (retval < 0) {
174 hid_err(hdev, "couldn't init char dev\n");
175 } else {
176 savu->chrdev_minor = retval;
177 savu->roccat_claimed = 1;
178 }
179
180 return 0;
181exit_free:
182 kfree(savu);
183 return retval;
184}
185
186static void savu_remove_specials(struct hid_device *hdev)
187{
188 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
189 struct savu_device *savu;
190
191 if (intf->cur_altsetting->desc.bInterfaceProtocol
192 != USB_INTERFACE_PROTOCOL_MOUSE)
193 return;
194
195 savu = hid_get_drvdata(hdev);
196 if (savu->roccat_claimed)
197 roccat_disconnect(savu->chrdev_minor);
198 kfree(savu);
199}
200
201static int savu_probe(struct hid_device *hdev,
202 const struct hid_device_id *id)
203{
204 int retval;
205
206 retval = hid_parse(hdev);
207 if (retval) {
208 hid_err(hdev, "parse failed\n");
209 goto exit;
210 }
211
212 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
213 if (retval) {
214 hid_err(hdev, "hw start failed\n");
215 goto exit;
216 }
217
218 retval = savu_init_specials(hdev);
219 if (retval) {
220 hid_err(hdev, "couldn't install mouse\n");
221 goto exit_stop;
222 }
223
224 return 0;
225
226exit_stop:
227 hid_hw_stop(hdev);
228exit:
229 return retval;
230}
231
232static void savu_remove(struct hid_device *hdev)
233{
234 savu_remove_specials(hdev);
235 hid_hw_stop(hdev);
236}
237
238static void savu_report_to_chrdev(struct savu_device const *savu,
239 u8 const *data)
240{
241 struct savu_roccat_report roccat_report;
242 struct savu_mouse_report_special const *special_report;
243
244 if (data[0] != SAVU_MOUSE_REPORT_NUMBER_SPECIAL)
245 return;
246
247 special_report = (struct savu_mouse_report_special const *)data;
248
249 roccat_report.type = special_report->type;
250 roccat_report.data[0] = special_report->data[0];
251 roccat_report.data[1] = special_report->data[1];
252 roccat_report_event(savu->chrdev_minor,
253 (uint8_t const *)&roccat_report);
254}
255
256static int savu_raw_event(struct hid_device *hdev,
257 struct hid_report *report, u8 *data, int size)
258{
259 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
260 struct savu_device *savu = hid_get_drvdata(hdev);
261
262 if (intf->cur_altsetting->desc.bInterfaceProtocol
263 != USB_INTERFACE_PROTOCOL_MOUSE)
264 return 0;
265
266 if (savu == NULL)
267 return 0;
268
269 if (savu->roccat_claimed)
270 savu_report_to_chrdev(savu, data);
271
272 return 0;
273}
274
275static const struct hid_device_id savu_devices[] = {
276 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) },
277 { }
278};
279
280MODULE_DEVICE_TABLE(hid, savu_devices);
281
282static struct hid_driver savu_driver = {
283 .name = "savu",
284 .id_table = savu_devices,
285 .probe = savu_probe,
286 .remove = savu_remove,
287 .raw_event = savu_raw_event
288};
289
290static int __init savu_init(void)
291{
292 int retval;
293
294 savu_class = class_create(THIS_MODULE, "savu");
295 if (IS_ERR(savu_class))
296 return PTR_ERR(savu_class);
297 savu_class->dev_bin_attrs = savu_bin_attributes;
298
299 retval = hid_register_driver(&savu_driver);
300 if (retval)
301 class_destroy(savu_class);
302 return retval;
303}
304
305static void __exit savu_exit(void)
306{
307 hid_unregister_driver(&savu_driver);
308 class_destroy(savu_class);
309}
310
311module_init(savu_init);
312module_exit(savu_exit);
313
314MODULE_AUTHOR("Stefan Achatz");
315MODULE_DESCRIPTION("USB Roccat Savu driver");
316MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-savu.h b/drivers/hid/hid-roccat-savu.h
new file mode 100644
index 000000000000..9120ba72087f
--- /dev/null
+++ b/drivers/hid/hid-roccat-savu.h
@@ -0,0 +1,87 @@
1#ifndef __HID_ROCCAT_SAVU_H
2#define __HID_ROCCAT_SAVU_H
3
4/*
5 * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net>
6 */
7
8/*
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
12 * any later version.
13 */
14
15#include <linux/types.h>
16
17enum {
18 SAVU_SIZE_CONTROL = 0x03,
19 SAVU_SIZE_PROFILE = 0x03,
20 SAVU_SIZE_GENERAL = 0x10,
21 SAVU_SIZE_BUTTONS = 0x2f,
22 SAVU_SIZE_MACRO = 0x0823,
23 SAVU_SIZE_INFO = 0x08,
24 SAVU_SIZE_SENSOR = 0x04,
25};
26
27enum savu_control_requests {
28 SAVU_CONTROL_REQUEST_GENERAL = 0x80,
29 SAVU_CONTROL_REQUEST_BUTTONS = 0x90,
30};
31
32enum savu_commands {
33 SAVU_COMMAND_CONTROL = 0x4,
34 SAVU_COMMAND_PROFILE = 0x5,
35 SAVU_COMMAND_GENERAL = 0x6,
36 SAVU_COMMAND_BUTTONS = 0x7,
37 SAVU_COMMAND_MACRO = 0x8,
38 SAVU_COMMAND_INFO = 0x9,
39 SAVU_COMMAND_SENSOR = 0xc,
40};
41
42struct savu_mouse_report_special {
43 uint8_t report_number; /* always 3 */
44 uint8_t zero;
45 uint8_t type;
46 uint8_t data[2];
47} __packed;
48
49enum {
50 SAVU_MOUSE_REPORT_NUMBER_SPECIAL = 3,
51};
52
53enum savu_mouse_report_button_types {
54 /* data1 = new profile range 1-5 */
55 SAVU_MOUSE_REPORT_BUTTON_TYPE_PROFILE = 0x20,
56
57 /* data1 = button number range 1-24; data2 = action */
58 SAVU_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH = 0x60,
59
60 /* data1 = button number range 1-24; data2 = action */
61 SAVU_MOUSE_REPORT_BUTTON_TYPE_TIMER = 0x80,
62
63 /* data1 = setting number range 1-5 */
64 SAVU_MOUSE_REPORT_BUTTON_TYPE_CPI = 0xb0,
65
66 /* data1 and data2 = range 0x1-0xb */
67 SAVU_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY = 0xc0,
68
69 /* data1 = 22 = next track...
70 * data2 = action
71 */
72 SAVU_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0,
73};
74
75struct savu_roccat_report {
76 uint8_t type;
77 uint8_t data[2];
78} __packed;
79
80struct savu_device {
81 int roccat_claimed;
82 int chrdev_minor;
83
84 struct mutex savu_lock;
85};
86
87#endif
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c
index aa958706c0e5..0a1805c9b0e5 100644
--- a/drivers/hid/hid-wiimote-ext.c
+++ b/drivers/hid/hid-wiimote-ext.c
@@ -77,7 +77,7 @@ static __u16 wiiext_keymap[] = {
77 BTN_TR, /* WIIEXT_KEY_RT */ 77 BTN_TR, /* WIIEXT_KEY_RT */
78}; 78};
79 79
80/* diable all extensions */ 80/* disable all extensions */
81static void ext_disable(struct wiimote_ext *ext) 81static void ext_disable(struct wiimote_ext *ext)
82{ 82{
83 unsigned long flags; 83 unsigned long flags;
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 36fa77b40ffb..3b6f7bf5a77e 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -96,6 +96,7 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count,
96 } 96 }
97 97
98 kfree(list->buffer[list->tail].value); 98 kfree(list->buffer[list->tail].value);
99 list->buffer[list->tail].value = NULL;
99 list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1); 100 list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1);
100 } 101 }
101out: 102out:
@@ -300,6 +301,7 @@ static int hidraw_release(struct inode * inode, struct file * file)
300 struct hidraw *dev; 301 struct hidraw *dev;
301 struct hidraw_list *list = file->private_data; 302 struct hidraw_list *list = file->private_data;
302 int ret; 303 int ret;
304 int i;
303 305
304 mutex_lock(&minors_lock); 306 mutex_lock(&minors_lock);
305 if (!hidraw_table[minor]) { 307 if (!hidraw_table[minor]) {
@@ -317,6 +319,9 @@ static int hidraw_release(struct inode * inode, struct file * file)
317 kfree(list->hidraw); 319 kfree(list->hidraw);
318 } 320 }
319 } 321 }
322
323 for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i)
324 kfree(list->buffer[i].value);
320 kfree(list); 325 kfree(list);
321 ret = 0; 326 ret = 0;
322unlock: 327unlock:
@@ -446,12 +451,17 @@ int hidraw_report_event(struct hid_device *hid, u8 *data, int len)
446 int ret = 0; 451 int ret = 0;
447 452
448 list_for_each_entry(list, &dev->list, node) { 453 list_for_each_entry(list, &dev->list, node) {
454 int new_head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1);
455
456 if (new_head == list->tail)
457 continue;
458
449 if (!(list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC))) { 459 if (!(list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC))) {
450 ret = -ENOMEM; 460 ret = -ENOMEM;
451 break; 461 break;
452 } 462 }
453 list->buffer[list->head].len = len; 463 list->buffer[list->head].len = len;
454 list->head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1); 464 list->head = new_head;
455 kill_fasync(&list->fasync, SIGIO, POLL_IN); 465 kill_fasync(&list->fasync, SIGIO, POLL_IN);
456 } 466 }
457 467
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
new file mode 100644
index 000000000000..714cd8cc9579
--- /dev/null
+++ b/drivers/hid/uhid.c
@@ -0,0 +1,572 @@
1/*
2 * User-space I/O driver support for HID subsystem
3 * Copyright (c) 2012 David Herrmann
4 */
5
6/*
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 */
12
13#include <linux/atomic.h>
14#include <linux/device.h>
15#include <linux/fs.h>
16#include <linux/hid.h>
17#include <linux/input.h>
18#include <linux/miscdevice.h>
19#include <linux/module.h>
20#include <linux/mutex.h>
21#include <linux/poll.h>
22#include <linux/sched.h>
23#include <linux/spinlock.h>
24#include <linux/uhid.h>
25#include <linux/wait.h>
26
27#define UHID_NAME "uhid"
28#define UHID_BUFSIZE 32
29
30struct uhid_device {
31 struct mutex devlock;
32 bool running;
33
34 __u8 *rd_data;
35 uint rd_size;
36
37 struct hid_device *hid;
38 struct uhid_event input_buf;
39
40 wait_queue_head_t waitq;
41 spinlock_t qlock;
42 __u8 head;
43 __u8 tail;
44 struct uhid_event *outq[UHID_BUFSIZE];
45
46 struct mutex report_lock;
47 wait_queue_head_t report_wait;
48 atomic_t report_done;
49 atomic_t report_id;
50 struct uhid_event report_buf;
51};
52
53static struct miscdevice uhid_misc;
54
55static void uhid_queue(struct uhid_device *uhid, struct uhid_event *ev)
56{
57 __u8 newhead;
58
59 newhead = (uhid->head + 1) % UHID_BUFSIZE;
60
61 if (newhead != uhid->tail) {
62 uhid->outq[uhid->head] = ev;
63 uhid->head = newhead;
64 wake_up_interruptible(&uhid->waitq);
65 } else {
66 hid_warn(uhid->hid, "Output queue is full\n");
67 kfree(ev);
68 }
69}
70
71static int uhid_queue_event(struct uhid_device *uhid, __u32 event)
72{
73 unsigned long flags;
74 struct uhid_event *ev;
75
76 ev = kzalloc(sizeof(*ev), GFP_KERNEL);
77 if (!ev)
78 return -ENOMEM;
79
80 ev->type = event;
81
82 spin_lock_irqsave(&uhid->qlock, flags);
83 uhid_queue(uhid, ev);
84 spin_unlock_irqrestore(&uhid->qlock, flags);
85
86 return 0;
87}
88
89static int uhid_hid_start(struct hid_device *hid)
90{
91 struct uhid_device *uhid = hid->driver_data;
92
93 return uhid_queue_event(uhid, UHID_START);
94}
95
96static void uhid_hid_stop(struct hid_device *hid)
97{
98 struct uhid_device *uhid = hid->driver_data;
99
100 hid->claimed = 0;
101 uhid_queue_event(uhid, UHID_STOP);
102}
103
104static int uhid_hid_open(struct hid_device *hid)
105{
106 struct uhid_device *uhid = hid->driver_data;
107
108 return uhid_queue_event(uhid, UHID_OPEN);
109}
110
111static void uhid_hid_close(struct hid_device *hid)
112{
113 struct uhid_device *uhid = hid->driver_data;
114
115 uhid_queue_event(uhid, UHID_CLOSE);
116}
117
118static int uhid_hid_input(struct input_dev *input, unsigned int type,
119 unsigned int code, int value)
120{
121 struct hid_device *hid = input_get_drvdata(input);
122 struct uhid_device *uhid = hid->driver_data;
123 unsigned long flags;
124 struct uhid_event *ev;
125
126 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
127 if (!ev)
128 return -ENOMEM;
129
130 ev->type = UHID_OUTPUT_EV;
131 ev->u.output_ev.type = type;
132 ev->u.output_ev.code = code;
133 ev->u.output_ev.value = value;
134
135 spin_lock_irqsave(&uhid->qlock, flags);
136 uhid_queue(uhid, ev);
137 spin_unlock_irqrestore(&uhid->qlock, flags);
138
139 return 0;
140}
141
142static int uhid_hid_parse(struct hid_device *hid)
143{
144 struct uhid_device *uhid = hid->driver_data;
145
146 return hid_parse_report(hid, uhid->rd_data, uhid->rd_size);
147}
148
149static int uhid_hid_get_raw(struct hid_device *hid, unsigned char rnum,
150 __u8 *buf, size_t count, unsigned char rtype)
151{
152 struct uhid_device *uhid = hid->driver_data;
153 __u8 report_type;
154 struct uhid_event *ev;
155 unsigned long flags;
156 int ret;
157 size_t uninitialized_var(len);
158 struct uhid_feature_answer_req *req;
159
160 if (!uhid->running)
161 return -EIO;
162
163 switch (rtype) {
164 case HID_FEATURE_REPORT:
165 report_type = UHID_FEATURE_REPORT;
166 break;
167 case HID_OUTPUT_REPORT:
168 report_type = UHID_OUTPUT_REPORT;
169 break;
170 case HID_INPUT_REPORT:
171 report_type = UHID_INPUT_REPORT;
172 break;
173 default:
174 return -EINVAL;
175 }
176
177 ret = mutex_lock_interruptible(&uhid->report_lock);
178 if (ret)
179 return ret;
180
181 ev = kzalloc(sizeof(*ev), GFP_KERNEL);
182 if (!ev) {
183 ret = -ENOMEM;
184 goto unlock;
185 }
186
187 spin_lock_irqsave(&uhid->qlock, flags);
188 ev->type = UHID_FEATURE;
189 ev->u.feature.id = atomic_inc_return(&uhid->report_id);
190 ev->u.feature.rnum = rnum;
191 ev->u.feature.rtype = report_type;
192
193 atomic_set(&uhid->report_done, 0);
194 uhid_queue(uhid, ev);
195 spin_unlock_irqrestore(&uhid->qlock, flags);
196
197 ret = wait_event_interruptible_timeout(uhid->report_wait,
198 atomic_read(&uhid->report_done), 5 * HZ);
199
200 /*
201 * Make sure "uhid->running" is cleared on shutdown before
202 * "uhid->report_done" is set.
203 */
204 smp_rmb();
205 if (!ret || !uhid->running) {
206 ret = -EIO;
207 } else if (ret < 0) {
208 ret = -ERESTARTSYS;
209 } else {
210 spin_lock_irqsave(&uhid->qlock, flags);
211 req = &uhid->report_buf.u.feature_answer;
212
213 if (req->err) {
214 ret = -EIO;
215 } else {
216 ret = 0;
217 len = min(count,
218 min_t(size_t, req->size, UHID_DATA_MAX));
219 memcpy(buf, req->data, len);
220 }
221
222 spin_unlock_irqrestore(&uhid->qlock, flags);
223 }
224
225 atomic_set(&uhid->report_done, 1);
226
227unlock:
228 mutex_unlock(&uhid->report_lock);
229 return ret ? ret : len;
230}
231
232static int uhid_hid_output_raw(struct hid_device *hid, __u8 *buf, size_t count,
233 unsigned char report_type)
234{
235 struct uhid_device *uhid = hid->driver_data;
236 __u8 rtype;
237 unsigned long flags;
238 struct uhid_event *ev;
239
240 switch (report_type) {
241 case HID_FEATURE_REPORT:
242 rtype = UHID_FEATURE_REPORT;
243 break;
244 case HID_OUTPUT_REPORT:
245 rtype = UHID_OUTPUT_REPORT;
246 break;
247 default:
248 return -EINVAL;
249 }
250
251 if (count < 1 || count > UHID_DATA_MAX)
252 return -EINVAL;
253
254 ev = kzalloc(sizeof(*ev), GFP_KERNEL);
255 if (!ev)
256 return -ENOMEM;
257
258 ev->type = UHID_OUTPUT;
259 ev->u.output.size = count;
260 ev->u.output.rtype = rtype;
261 memcpy(ev->u.output.data, buf, count);
262
263 spin_lock_irqsave(&uhid->qlock, flags);
264 uhid_queue(uhid, ev);
265 spin_unlock_irqrestore(&uhid->qlock, flags);
266
267 return count;
268}
269
270static struct hid_ll_driver uhid_hid_driver = {
271 .start = uhid_hid_start,
272 .stop = uhid_hid_stop,
273 .open = uhid_hid_open,
274 .close = uhid_hid_close,
275 .hidinput_input_event = uhid_hid_input,
276 .parse = uhid_hid_parse,
277};
278
279static int uhid_dev_create(struct uhid_device *uhid,
280 const struct uhid_event *ev)
281{
282 struct hid_device *hid;
283 int ret;
284
285 if (uhid->running)
286 return -EALREADY;
287
288 uhid->rd_size = ev->u.create.rd_size;
289 if (uhid->rd_size <= 0 || uhid->rd_size > HID_MAX_DESCRIPTOR_SIZE)
290 return -EINVAL;
291
292 uhid->rd_data = kmalloc(uhid->rd_size, GFP_KERNEL);
293 if (!uhid->rd_data)
294 return -ENOMEM;
295
296 if (copy_from_user(uhid->rd_data, ev->u.create.rd_data,
297 uhid->rd_size)) {
298 ret = -EFAULT;
299 goto err_free;
300 }
301
302 hid = hid_allocate_device();
303 if (IS_ERR(hid)) {
304 ret = PTR_ERR(hid);
305 goto err_free;
306 }
307
308 strncpy(hid->name, ev->u.create.name, 127);
309 hid->name[127] = 0;
310 strncpy(hid->phys, ev->u.create.phys, 63);
311 hid->phys[63] = 0;
312 strncpy(hid->uniq, ev->u.create.uniq, 63);
313 hid->uniq[63] = 0;
314
315 hid->ll_driver = &uhid_hid_driver;
316 hid->hid_get_raw_report = uhid_hid_get_raw;
317 hid->hid_output_raw_report = uhid_hid_output_raw;
318 hid->bus = ev->u.create.bus;
319 hid->vendor = ev->u.create.vendor;
320 hid->product = ev->u.create.product;
321 hid->version = ev->u.create.version;
322 hid->country = ev->u.create.country;
323 hid->driver_data = uhid;
324 hid->dev.parent = uhid_misc.this_device;
325
326 uhid->hid = hid;
327 uhid->running = true;
328
329 ret = hid_add_device(hid);
330 if (ret) {
331 hid_err(hid, "Cannot register HID device\n");
332 goto err_hid;
333 }
334
335 return 0;
336
337err_hid:
338 hid_destroy_device(hid);
339 uhid->hid = NULL;
340 uhid->running = false;
341err_free:
342 kfree(uhid->rd_data);
343 return ret;
344}
345
346static int uhid_dev_destroy(struct uhid_device *uhid)
347{
348 if (!uhid->running)
349 return -EINVAL;
350
351 /* clear "running" before setting "report_done" */
352 uhid->running = false;
353 smp_wmb();
354 atomic_set(&uhid->report_done, 1);
355 wake_up_interruptible(&uhid->report_wait);
356
357 hid_destroy_device(uhid->hid);
358 kfree(uhid->rd_data);
359
360 return 0;
361}
362
363static int uhid_dev_input(struct uhid_device *uhid, struct uhid_event *ev)
364{
365 if (!uhid->running)
366 return -EINVAL;
367
368 hid_input_report(uhid->hid, HID_INPUT_REPORT, ev->u.input.data,
369 min_t(size_t, ev->u.input.size, UHID_DATA_MAX), 0);
370
371 return 0;
372}
373
374static int uhid_dev_feature_answer(struct uhid_device *uhid,
375 struct uhid_event *ev)
376{
377 unsigned long flags;
378
379 if (!uhid->running)
380 return -EINVAL;
381
382 spin_lock_irqsave(&uhid->qlock, flags);
383
384 /* id for old report; drop it silently */
385 if (atomic_read(&uhid->report_id) != ev->u.feature_answer.id)
386 goto unlock;
387 if (atomic_read(&uhid->report_done))
388 goto unlock;
389
390 memcpy(&uhid->report_buf, ev, sizeof(*ev));
391 atomic_set(&uhid->report_done, 1);
392 wake_up_interruptible(&uhid->report_wait);
393
394unlock:
395 spin_unlock_irqrestore(&uhid->qlock, flags);
396 return 0;
397}
398
399static int uhid_char_open(struct inode *inode, struct file *file)
400{
401 struct uhid_device *uhid;
402
403 uhid = kzalloc(sizeof(*uhid), GFP_KERNEL);
404 if (!uhid)
405 return -ENOMEM;
406
407 mutex_init(&uhid->devlock);
408 mutex_init(&uhid->report_lock);
409 spin_lock_init(&uhid->qlock);
410 init_waitqueue_head(&uhid->waitq);
411 init_waitqueue_head(&uhid->report_wait);
412 uhid->running = false;
413 atomic_set(&uhid->report_done, 1);
414
415 file->private_data = uhid;
416 nonseekable_open(inode, file);
417
418 return 0;
419}
420
421static int uhid_char_release(struct inode *inode, struct file *file)
422{
423 struct uhid_device *uhid = file->private_data;
424 unsigned int i;
425
426 uhid_dev_destroy(uhid);
427
428 for (i = 0; i < UHID_BUFSIZE; ++i)
429 kfree(uhid->outq[i]);
430
431 kfree(uhid);
432
433 return 0;
434}
435
436static ssize_t uhid_char_read(struct file *file, char __user *buffer,
437 size_t count, loff_t *ppos)
438{
439 struct uhid_device *uhid = file->private_data;
440 int ret;
441 unsigned long flags;
442 size_t len;
443
444 /* they need at least the "type" member of uhid_event */
445 if (count < sizeof(__u32))
446 return -EINVAL;
447
448try_again:
449 if (file->f_flags & O_NONBLOCK) {
450 if (uhid->head == uhid->tail)
451 return -EAGAIN;
452 } else {
453 ret = wait_event_interruptible(uhid->waitq,
454 uhid->head != uhid->tail);
455 if (ret)
456 return ret;
457 }
458
459 ret = mutex_lock_interruptible(&uhid->devlock);
460 if (ret)
461 return ret;
462
463 if (uhid->head == uhid->tail) {
464 mutex_unlock(&uhid->devlock);
465 goto try_again;
466 } else {
467 len = min(count, sizeof(**uhid->outq));
468 if (copy_to_user(buffer, uhid->outq[uhid->tail], len)) {
469 ret = -EFAULT;
470 } else {
471 kfree(uhid->outq[uhid->tail]);
472 uhid->outq[uhid->tail] = NULL;
473
474 spin_lock_irqsave(&uhid->qlock, flags);
475 uhid->tail = (uhid->tail + 1) % UHID_BUFSIZE;
476 spin_unlock_irqrestore(&uhid->qlock, flags);
477 }
478 }
479
480 mutex_unlock(&uhid->devlock);
481 return ret ? ret : len;
482}
483
484static ssize_t uhid_char_write(struct file *file, const char __user *buffer,
485 size_t count, loff_t *ppos)
486{
487 struct uhid_device *uhid = file->private_data;
488 int ret;
489 size_t len;
490
491 /* we need at least the "type" member of uhid_event */
492 if (count < sizeof(__u32))
493 return -EINVAL;
494
495 ret = mutex_lock_interruptible(&uhid->devlock);
496 if (ret)
497 return ret;
498
499 memset(&uhid->input_buf, 0, sizeof(uhid->input_buf));
500 len = min(count, sizeof(uhid->input_buf));
501 if (copy_from_user(&uhid->input_buf, buffer, len)) {
502 ret = -EFAULT;
503 goto unlock;
504 }
505
506 switch (uhid->input_buf.type) {
507 case UHID_CREATE:
508 ret = uhid_dev_create(uhid, &uhid->input_buf);
509 break;
510 case UHID_DESTROY:
511 ret = uhid_dev_destroy(uhid);
512 break;
513 case UHID_INPUT:
514 ret = uhid_dev_input(uhid, &uhid->input_buf);
515 break;
516 case UHID_FEATURE_ANSWER:
517 ret = uhid_dev_feature_answer(uhid, &uhid->input_buf);
518 break;
519 default:
520 ret = -EOPNOTSUPP;
521 }
522
523unlock:
524 mutex_unlock(&uhid->devlock);
525
526 /* return "count" not "len" to not confuse the caller */
527 return ret ? ret : count;
528}
529
530static unsigned int uhid_char_poll(struct file *file, poll_table *wait)
531{
532 struct uhid_device *uhid = file->private_data;
533
534 poll_wait(file, &uhid->waitq, wait);
535
536 if (uhid->head != uhid->tail)
537 return POLLIN | POLLRDNORM;
538
539 return 0;
540}
541
542static const struct file_operations uhid_fops = {
543 .owner = THIS_MODULE,
544 .open = uhid_char_open,
545 .release = uhid_char_release,
546 .read = uhid_char_read,
547 .write = uhid_char_write,
548 .poll = uhid_char_poll,
549 .llseek = no_llseek,
550};
551
552static struct miscdevice uhid_misc = {
553 .fops = &uhid_fops,
554 .minor = MISC_DYNAMIC_MINOR,
555 .name = UHID_NAME,
556};
557
558static int __init uhid_init(void)
559{
560 return misc_register(&uhid_misc);
561}
562
563static void __exit uhid_exit(void)
564{
565 misc_deregister(&uhid_misc);
566}
567
568module_init(uhid_init);
569module_exit(uhid_exit);
570MODULE_LICENSE("GPL");
571MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>");
572MODULE_DESCRIPTION("User-space I/O driver support for HID subsystem");
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 482f936fc29b..dedd8e4e5c6d 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -84,7 +84,7 @@ static int hid_start_in(struct hid_device *hid)
84 spin_lock_irqsave(&usbhid->lock, flags); 84 spin_lock_irqsave(&usbhid->lock, flags);
85 if (hid->open > 0 && 85 if (hid->open > 0 &&
86 !test_bit(HID_DISCONNECTED, &usbhid->iofl) && 86 !test_bit(HID_DISCONNECTED, &usbhid->iofl) &&
87 !test_bit(HID_REPORTED_IDLE, &usbhid->iofl) && 87 !test_bit(HID_SUSPENDED, &usbhid->iofl) &&
88 !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { 88 !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
89 rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC); 89 rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);
90 if (rc != 0) { 90 if (rc != 0) {
@@ -207,15 +207,27 @@ static int usbhid_restart_out_queue(struct usbhid_device *usbhid)
207 int kicked; 207 int kicked;
208 int r; 208 int r;
209 209
210 if (!hid) 210 if (!hid || test_bit(HID_RESET_PENDING, &usbhid->iofl) ||
211 test_bit(HID_SUSPENDED, &usbhid->iofl))
211 return 0; 212 return 0;
212 213
213 if ((kicked = (usbhid->outhead != usbhid->outtail))) { 214 if ((kicked = (usbhid->outhead != usbhid->outtail))) {
214 hid_dbg(hid, "Kicking head %d tail %d", usbhid->outhead, usbhid->outtail); 215 hid_dbg(hid, "Kicking head %d tail %d", usbhid->outhead, usbhid->outtail);
215 216
217 /* Try to wake up from autosuspend... */
216 r = usb_autopm_get_interface_async(usbhid->intf); 218 r = usb_autopm_get_interface_async(usbhid->intf);
217 if (r < 0) 219 if (r < 0)
218 return r; 220 return r;
221
222 /*
223 * If still suspended, don't submit. Submission will
224 * occur if/when resume drains the queue.
225 */
226 if (test_bit(HID_SUSPENDED, &usbhid->iofl)) {
227 usb_autopm_put_interface_no_suspend(usbhid->intf);
228 return r;
229 }
230
219 /* Asynchronously flush queue. */ 231 /* Asynchronously flush queue. */
220 set_bit(HID_OUT_RUNNING, &usbhid->iofl); 232 set_bit(HID_OUT_RUNNING, &usbhid->iofl);
221 if (hid_submit_out(hid)) { 233 if (hid_submit_out(hid)) {
@@ -234,15 +246,27 @@ static int usbhid_restart_ctrl_queue(struct usbhid_device *usbhid)
234 int r; 246 int r;
235 247
236 WARN_ON(hid == NULL); 248 WARN_ON(hid == NULL);
237 if (!hid) 249 if (!hid || test_bit(HID_RESET_PENDING, &usbhid->iofl) ||
250 test_bit(HID_SUSPENDED, &usbhid->iofl))
238 return 0; 251 return 0;
239 252
240 if ((kicked = (usbhid->ctrlhead != usbhid->ctrltail))) { 253 if ((kicked = (usbhid->ctrlhead != usbhid->ctrltail))) {
241 hid_dbg(hid, "Kicking head %d tail %d", usbhid->ctrlhead, usbhid->ctrltail); 254 hid_dbg(hid, "Kicking head %d tail %d", usbhid->ctrlhead, usbhid->ctrltail);
242 255
256 /* Try to wake up from autosuspend... */
243 r = usb_autopm_get_interface_async(usbhid->intf); 257 r = usb_autopm_get_interface_async(usbhid->intf);
244 if (r < 0) 258 if (r < 0)
245 return r; 259 return r;
260
261 /*
262 * If still suspended, don't submit. Submission will
263 * occur if/when resume drains the queue.
264 */
265 if (test_bit(HID_SUSPENDED, &usbhid->iofl)) {
266 usb_autopm_put_interface_no_suspend(usbhid->intf);
267 return r;
268 }
269
246 /* Asynchronously flush queue. */ 270 /* Asynchronously flush queue. */
247 set_bit(HID_CTRL_RUNNING, &usbhid->iofl); 271 set_bit(HID_CTRL_RUNNING, &usbhid->iofl);
248 if (hid_submit_ctrl(hid)) { 272 if (hid_submit_ctrl(hid)) {
@@ -331,9 +355,12 @@ static int hid_submit_out(struct hid_device *hid)
331 usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 355 usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) +
332 1 + (report->id > 0); 356 1 + (report->id > 0);
333 usbhid->urbout->dev = hid_to_usb_dev(hid); 357 usbhid->urbout->dev = hid_to_usb_dev(hid);
334 memcpy(usbhid->outbuf, raw_report, 358 if (raw_report) {
335 usbhid->urbout->transfer_buffer_length); 359 memcpy(usbhid->outbuf, raw_report,
336 kfree(raw_report); 360 usbhid->urbout->transfer_buffer_length);
361 kfree(raw_report);
362 usbhid->out[usbhid->outtail].raw_report = NULL;
363 }
337 364
338 dbg_hid("submitting out urb\n"); 365 dbg_hid("submitting out urb\n");
339 366
@@ -362,8 +389,11 @@ static int hid_submit_ctrl(struct hid_device *hid)
362 if (dir == USB_DIR_OUT) { 389 if (dir == USB_DIR_OUT) {
363 usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0); 390 usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0);
364 usbhid->urbctrl->transfer_buffer_length = len; 391 usbhid->urbctrl->transfer_buffer_length = len;
365 memcpy(usbhid->ctrlbuf, raw_report, len); 392 if (raw_report) {
366 kfree(raw_report); 393 memcpy(usbhid->ctrlbuf, raw_report, len);
394 kfree(raw_report);
395 usbhid->ctrl[usbhid->ctrltail].raw_report = NULL;
396 }
367 } else { 397 } else {
368 int maxpacket, padlen; 398 int maxpacket, padlen;
369 399
@@ -407,16 +437,6 @@ static int hid_submit_ctrl(struct hid_device *hid)
407 * Output interrupt completion handler. 437 * Output interrupt completion handler.
408 */ 438 */
409 439
410static int irq_out_pump_restart(struct hid_device *hid)
411{
412 struct usbhid_device *usbhid = hid->driver_data;
413
414 if (usbhid->outhead != usbhid->outtail)
415 return hid_submit_out(hid);
416 else
417 return -1;
418}
419
420static void hid_irq_out(struct urb *urb) 440static void hid_irq_out(struct urb *urb)
421{ 441{
422 struct hid_device *hid = urb->context; 442 struct hid_device *hid = urb->context;
@@ -441,15 +461,17 @@ static void hid_irq_out(struct urb *urb)
441 461
442 spin_lock_irqsave(&usbhid->lock, flags); 462 spin_lock_irqsave(&usbhid->lock, flags);
443 463
444 if (unplug) 464 if (unplug) {
445 usbhid->outtail = usbhid->outhead; 465 usbhid->outtail = usbhid->outhead;
446 else 466 } else {
447 usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1); 467 usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
448 468
449 if (!irq_out_pump_restart(hid)) { 469 if (usbhid->outhead != usbhid->outtail &&
450 /* Successfully submitted next urb in queue */ 470 hid_submit_out(hid) == 0) {
451 spin_unlock_irqrestore(&usbhid->lock, flags); 471 /* Successfully submitted next urb in queue */
452 return; 472 spin_unlock_irqrestore(&usbhid->lock, flags);
473 return;
474 }
453 } 475 }
454 476
455 clear_bit(HID_OUT_RUNNING, &usbhid->iofl); 477 clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
@@ -461,15 +483,6 @@ static void hid_irq_out(struct urb *urb)
461/* 483/*
462 * Control pipe completion handler. 484 * Control pipe completion handler.
463 */ 485 */
464static int ctrl_pump_restart(struct hid_device *hid)
465{
466 struct usbhid_device *usbhid = hid->driver_data;
467
468 if (usbhid->ctrlhead != usbhid->ctrltail)
469 return hid_submit_ctrl(hid);
470 else
471 return -1;
472}
473 486
474static void hid_ctrl(struct urb *urb) 487static void hid_ctrl(struct urb *urb)
475{ 488{
@@ -498,15 +511,17 @@ static void hid_ctrl(struct urb *urb)
498 hid_warn(urb->dev, "ctrl urb status %d received\n", status); 511 hid_warn(urb->dev, "ctrl urb status %d received\n", status);
499 } 512 }
500 513
501 if (unplug) 514 if (unplug) {
502 usbhid->ctrltail = usbhid->ctrlhead; 515 usbhid->ctrltail = usbhid->ctrlhead;
503 else 516 } else {
504 usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); 517 usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
505 518
506 if (!ctrl_pump_restart(hid)) { 519 if (usbhid->ctrlhead != usbhid->ctrltail &&
507 /* Successfully submitted next urb in queue */ 520 hid_submit_ctrl(hid) == 0) {
508 spin_unlock(&usbhid->lock); 521 /* Successfully submitted next urb in queue */
509 return; 522 spin_unlock(&usbhid->lock);
523 return;
524 }
510 } 525 }
511 526
512 clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); 527 clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
@@ -540,49 +555,36 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
540 usbhid->out[usbhid->outhead].report = report; 555 usbhid->out[usbhid->outhead].report = report;
541 usbhid->outhead = head; 556 usbhid->outhead = head;
542 557
543 /* Try to awake from autosuspend... */ 558 /* If the queue isn't running, restart it */
544 if (usb_autopm_get_interface_async(usbhid->intf) < 0) 559 if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl)) {
545 return; 560 usbhid_restart_out_queue(usbhid);
546 561
547 /* 562 /* Otherwise see if an earlier request has timed out */
548 * But if still suspended, leave urb enqueued, don't submit. 563 } else if (time_after(jiffies, usbhid->last_out + HZ * 5)) {
549 * Submission will occur if/when resume() drains the queue. 564
550 */ 565 /* Prevent autosuspend following the unlink */
551 if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) 566 usb_autopm_get_interface_no_resume(usbhid->intf);
552 return;
553 567
554 if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) {
555 if (hid_submit_out(hid)) {
556 clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
557 usb_autopm_put_interface_async(usbhid->intf);
558 }
559 wake_up(&usbhid->wait);
560 } else {
561 /* 568 /*
562 * the queue is known to run 569 * Prevent resubmission in case the URB completes
563 * but an earlier request may be stuck 570 * before we can unlink it. We don't want to cancel
564 * we may need to time out 571 * the wrong transfer!
565 * no race because the URB is blocked under
566 * spinlock
567 */ 572 */
568 if (time_after(jiffies, usbhid->last_out + HZ * 5)) { 573 usb_block_urb(usbhid->urbout);
569 usb_block_urb(usbhid->urbout);
570 /* drop lock to not deadlock if the callback is called */
571 spin_unlock(&usbhid->lock);
572 usb_unlink_urb(usbhid->urbout);
573 spin_lock(&usbhid->lock);
574 usb_unblock_urb(usbhid->urbout);
575 /*
576 * if the unlinking has already completed
577 * the pump will have been stopped
578 * it must be restarted now
579 */
580 if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl))
581 if (!irq_out_pump_restart(hid))
582 set_bit(HID_OUT_RUNNING, &usbhid->iofl);
583 574
575 /* Drop lock to avoid deadlock if the callback runs */
576 spin_unlock(&usbhid->lock);
584 577
585 } 578 usb_unlink_urb(usbhid->urbout);
579 spin_lock(&usbhid->lock);
580 usb_unblock_urb(usbhid->urbout);
581
582 /* Unlink might have stopped the queue */
583 if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl))
584 usbhid_restart_out_queue(usbhid);
585
586 /* Now we can allow autosuspend again */
587 usb_autopm_put_interface_async(usbhid->intf);
586 } 588 }
587 return; 589 return;
588 } 590 }
@@ -604,47 +606,36 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
604 usbhid->ctrl[usbhid->ctrlhead].dir = dir; 606 usbhid->ctrl[usbhid->ctrlhead].dir = dir;
605 usbhid->ctrlhead = head; 607 usbhid->ctrlhead = head;
606 608
607 /* Try to awake from autosuspend... */ 609 /* If the queue isn't running, restart it */
608 if (usb_autopm_get_interface_async(usbhid->intf) < 0) 610 if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) {
609 return; 611 usbhid_restart_ctrl_queue(usbhid);
610 612
611 /* 613 /* Otherwise see if an earlier request has timed out */
612 * If already suspended, leave urb enqueued, but don't submit. 614 } else if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) {
613 * Submission will occur if/when resume() drains the queue. 615
614 */ 616 /* Prevent autosuspend following the unlink */
615 if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) 617 usb_autopm_get_interface_no_resume(usbhid->intf);
616 return;
617 618
618 if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) {
619 if (hid_submit_ctrl(hid)) {
620 clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
621 usb_autopm_put_interface_async(usbhid->intf);
622 }
623 wake_up(&usbhid->wait);
624 } else {
625 /* 619 /*
626 * the queue is known to run 620 * Prevent resubmission in case the URB completes
627 * but an earlier request may be stuck 621 * before we can unlink it. We don't want to cancel
628 * we may need to time out 622 * the wrong transfer!
629 * no race because the URB is blocked under
630 * spinlock
631 */ 623 */
632 if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) { 624 usb_block_urb(usbhid->urbctrl);
633 usb_block_urb(usbhid->urbctrl); 625
634 /* drop lock to not deadlock if the callback is called */ 626 /* Drop lock to avoid deadlock if the callback runs */
635 spin_unlock(&usbhid->lock); 627 spin_unlock(&usbhid->lock);
636 usb_unlink_urb(usbhid->urbctrl); 628
637 spin_lock(&usbhid->lock); 629 usb_unlink_urb(usbhid->urbctrl);
638 usb_unblock_urb(usbhid->urbctrl); 630 spin_lock(&usbhid->lock);
639 /* 631 usb_unblock_urb(usbhid->urbctrl);
640 * if the unlinking has already completed 632
641 * the pump will have been stopped 633 /* Unlink might have stopped the queue */
642 * it must be restarted now 634 if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
643 */ 635 usbhid_restart_ctrl_queue(usbhid);
644 if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) 636
645 if (!ctrl_pump_restart(hid)) 637 /* Now we can allow autosuspend again */
646 set_bit(HID_CTRL_RUNNING, &usbhid->iofl); 638 usb_autopm_put_interface_async(usbhid->intf);
647 }
648 } 639 }
649} 640}
650 641
@@ -1002,9 +993,10 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co
1002 993
1003static void usbhid_restart_queues(struct usbhid_device *usbhid) 994static void usbhid_restart_queues(struct usbhid_device *usbhid)
1004{ 995{
1005 if (usbhid->urbout) 996 if (usbhid->urbout && !test_bit(HID_OUT_RUNNING, &usbhid->iofl))
1006 usbhid_restart_out_queue(usbhid); 997 usbhid_restart_out_queue(usbhid);
1007 usbhid_restart_ctrl_queue(usbhid); 998 if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
999 usbhid_restart_ctrl_queue(usbhid);
1008} 1000}
1009 1001
1010static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) 1002static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
@@ -1471,11 +1463,38 @@ void usbhid_put_power(struct hid_device *hid)
1471 1463
1472 1464
1473#ifdef CONFIG_PM 1465#ifdef CONFIG_PM
1466static int hid_resume_common(struct hid_device *hid, bool driver_suspended)
1467{
1468 struct usbhid_device *usbhid = hid->driver_data;
1469 int status;
1470
1471 spin_lock_irq(&usbhid->lock);
1472 clear_bit(HID_SUSPENDED, &usbhid->iofl);
1473 usbhid_mark_busy(usbhid);
1474
1475 if (test_bit(HID_CLEAR_HALT, &usbhid->iofl) ||
1476 test_bit(HID_RESET_PENDING, &usbhid->iofl))
1477 schedule_work(&usbhid->reset_work);
1478 usbhid->retry_delay = 0;
1479
1480 usbhid_restart_queues(usbhid);
1481 spin_unlock_irq(&usbhid->lock);
1482
1483 status = hid_start_in(hid);
1484 if (status < 0)
1485 hid_io_error(hid);
1486
1487 if (driver_suspended && hid->driver && hid->driver->resume)
1488 status = hid->driver->resume(hid);
1489 return status;
1490}
1491
1474static int hid_suspend(struct usb_interface *intf, pm_message_t message) 1492static int hid_suspend(struct usb_interface *intf, pm_message_t message)
1475{ 1493{
1476 struct hid_device *hid = usb_get_intfdata(intf); 1494 struct hid_device *hid = usb_get_intfdata(intf);
1477 struct usbhid_device *usbhid = hid->driver_data; 1495 struct usbhid_device *usbhid = hid->driver_data;
1478 int status; 1496 int status;
1497 bool driver_suspended = false;
1479 1498
1480 if (PMSG_IS_AUTO(message)) { 1499 if (PMSG_IS_AUTO(message)) {
1481 spin_lock_irq(&usbhid->lock); /* Sync with error handler */ 1500 spin_lock_irq(&usbhid->lock); /* Sync with error handler */
@@ -1486,13 +1505,14 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
1486 && !test_bit(HID_KEYS_PRESSED, &usbhid->iofl) 1505 && !test_bit(HID_KEYS_PRESSED, &usbhid->iofl)
1487 && (!usbhid->ledcount || ignoreled)) 1506 && (!usbhid->ledcount || ignoreled))
1488 { 1507 {
1489 set_bit(HID_REPORTED_IDLE, &usbhid->iofl); 1508 set_bit(HID_SUSPENDED, &usbhid->iofl);
1490 spin_unlock_irq(&usbhid->lock); 1509 spin_unlock_irq(&usbhid->lock);
1491 if (hid->driver && hid->driver->suspend) { 1510 if (hid->driver && hid->driver->suspend) {
1492 status = hid->driver->suspend(hid, message); 1511 status = hid->driver->suspend(hid, message);
1493 if (status < 0) 1512 if (status < 0)
1494 return status; 1513 goto failed;
1495 } 1514 }
1515 driver_suspended = true;
1496 } else { 1516 } else {
1497 usbhid_mark_busy(usbhid); 1517 usbhid_mark_busy(usbhid);
1498 spin_unlock_irq(&usbhid->lock); 1518 spin_unlock_irq(&usbhid->lock);
@@ -1505,11 +1525,14 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
1505 if (status < 0) 1525 if (status < 0)
1506 return status; 1526 return status;
1507 } 1527 }
1528 driver_suspended = true;
1508 spin_lock_irq(&usbhid->lock); 1529 spin_lock_irq(&usbhid->lock);
1509 set_bit(HID_REPORTED_IDLE, &usbhid->iofl); 1530 set_bit(HID_SUSPENDED, &usbhid->iofl);
1510 spin_unlock_irq(&usbhid->lock); 1531 spin_unlock_irq(&usbhid->lock);
1511 if (usbhid_wait_io(hid) < 0) 1532 if (usbhid_wait_io(hid) < 0) {
1512 return -EIO; 1533 status = -EIO;
1534 goto failed;
1535 }
1513 } 1536 }
1514 1537
1515 hid_cancel_delayed_stuff(usbhid); 1538 hid_cancel_delayed_stuff(usbhid);
@@ -1517,14 +1540,15 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
1517 1540
1518 if (PMSG_IS_AUTO(message) && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) { 1541 if (PMSG_IS_AUTO(message) && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) {
1519 /* lost race against keypresses */ 1542 /* lost race against keypresses */
1520 status = hid_start_in(hid); 1543 status = -EBUSY;
1521 if (status < 0) 1544 goto failed;
1522 hid_io_error(hid);
1523 usbhid_mark_busy(usbhid);
1524 return -EBUSY;
1525 } 1545 }
1526 dev_dbg(&intf->dev, "suspend\n"); 1546 dev_dbg(&intf->dev, "suspend\n");
1527 return 0; 1547 return 0;
1548
1549 failed:
1550 hid_resume_common(hid, driver_suspended);
1551 return status;
1528} 1552}
1529 1553
1530static int hid_resume(struct usb_interface *intf) 1554static int hid_resume(struct usb_interface *intf)
@@ -1536,23 +1560,7 @@ static int hid_resume(struct usb_interface *intf)
1536 if (!test_bit(HID_STARTED, &usbhid->iofl)) 1560 if (!test_bit(HID_STARTED, &usbhid->iofl))
1537 return 0; 1561 return 0;
1538 1562
1539 clear_bit(HID_REPORTED_IDLE, &usbhid->iofl); 1563 status = hid_resume_common(hid, true);
1540 usbhid_mark_busy(usbhid);
1541
1542 if (test_bit(HID_CLEAR_HALT, &usbhid->iofl) ||
1543 test_bit(HID_RESET_PENDING, &usbhid->iofl))
1544 schedule_work(&usbhid->reset_work);
1545 usbhid->retry_delay = 0;
1546 status = hid_start_in(hid);
1547 if (status < 0)
1548 hid_io_error(hid);
1549 usbhid_restart_queues(usbhid);
1550
1551 if (status >= 0 && hid->driver && hid->driver->resume) {
1552 int ret = hid->driver->resume(hid);
1553 if (ret < 0)
1554 status = ret;
1555 }
1556 dev_dbg(&intf->dev, "resume status %d\n", status); 1564 dev_dbg(&intf->dev, "resume status %d\n", status);
1557 return 0; 1565 return 0;
1558} 1566}
@@ -1563,7 +1571,7 @@ static int hid_reset_resume(struct usb_interface *intf)
1563 struct usbhid_device *usbhid = hid->driver_data; 1571 struct usbhid_device *usbhid = hid->driver_data;
1564 int status; 1572 int status;
1565 1573
1566 clear_bit(HID_REPORTED_IDLE, &usbhid->iofl); 1574 clear_bit(HID_SUSPENDED, &usbhid->iofl);
1567 status = hid_post_reset(intf); 1575 status = hid_post_reset(intf);
1568 if (status >= 0 && hid->driver && hid->driver->reset_resume) { 1576 if (status >= 0 && hid->driver && hid->driver->reset_resume) {
1569 int ret = hid->driver->reset_resume(hid); 1577 int ret = hid->driver->reset_resume(hid);
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
index 1883d7b94870..bd87a61e5303 100644
--- a/drivers/hid/usbhid/usbhid.h
+++ b/drivers/hid/usbhid/usbhid.h
@@ -53,7 +53,6 @@ struct usb_interface *usbhid_find_interface(int minor);
53#define HID_CLEAR_HALT 6 53#define HID_CLEAR_HALT 6
54#define HID_DISCONNECTED 7 54#define HID_DISCONNECTED 7
55#define HID_STARTED 8 55#define HID_STARTED 8
56#define HID_REPORTED_IDLE 9
57#define HID_KEYS_PRESSED 10 56#define HID_KEYS_PRESSED 10
58#define HID_NO_BANDWIDTH 11 57#define HID_NO_BANDWIDTH 11
59 58
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 8760be30b375..cb2a7d1ad47b 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -376,6 +376,7 @@ header-y += tty.h
376header-y += types.h 376header-y += types.h
377header-y += udf_fs_i.h 377header-y += udf_fs_i.h
378header-y += udp.h 378header-y += udp.h
379header-y += uhid.h
379header-y += uinput.h 380header-y += uinput.h
380header-y += uio.h 381header-y += uio.h
381header-y += ultrasound.h 382header-y += ultrasound.h
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 449fa385703d..42970de1b40c 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -200,6 +200,7 @@ struct hid_item {
200#define HID_UP_DIGITIZER 0x000d0000 200#define HID_UP_DIGITIZER 0x000d0000
201#define HID_UP_PID 0x000f0000 201#define HID_UP_PID 0x000f0000
202#define HID_UP_HPVENDOR 0xff7f0000 202#define HID_UP_HPVENDOR 0xff7f0000
203#define HID_UP_HPVENDOR2 0xff010000
203#define HID_UP_MSVENDOR 0xff000000 204#define HID_UP_MSVENDOR 0xff000000
204#define HID_UP_CUSTOM 0x00ff0000 205#define HID_UP_CUSTOM 0x00ff0000
205#define HID_UP_LOGIVENDOR 0xffbc0000 206#define HID_UP_LOGIVENDOR 0xffbc0000
diff --git a/include/linux/uhid.h b/include/linux/uhid.h
new file mode 100644
index 000000000000..9c6974f16966
--- /dev/null
+++ b/include/linux/uhid.h
@@ -0,0 +1,104 @@
1#ifndef __UHID_H_
2#define __UHID_H_
3
4/*
5 * User-space I/O driver support for HID subsystem
6 * Copyright (c) 2012 David Herrmann
7 */
8
9/*
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 2 of the License, or (at your option)
13 * any later version.
14 */
15
16/*
17 * Public header for user-space communication. We try to keep every structure
18 * aligned but to be safe we also use __attribute__((__packed__)). Therefore,
19 * the communication should be ABI compatible even between architectures.
20 */
21
22#include <linux/input.h>
23#include <linux/types.h>
24
25enum uhid_event_type {
26 UHID_CREATE,
27 UHID_DESTROY,
28 UHID_START,
29 UHID_STOP,
30 UHID_OPEN,
31 UHID_CLOSE,
32 UHID_OUTPUT,
33 UHID_OUTPUT_EV,
34 UHID_INPUT,
35 UHID_FEATURE,
36 UHID_FEATURE_ANSWER,
37};
38
39struct uhid_create_req {
40 __u8 name[128];
41 __u8 phys[64];
42 __u8 uniq[64];
43 __u8 __user *rd_data;
44 __u16 rd_size;
45
46 __u16 bus;
47 __u32 vendor;
48 __u32 product;
49 __u32 version;
50 __u32 country;
51} __attribute__((__packed__));
52
53#define UHID_DATA_MAX 4096
54
55enum uhid_report_type {
56 UHID_FEATURE_REPORT,
57 UHID_OUTPUT_REPORT,
58 UHID_INPUT_REPORT,
59};
60
61struct uhid_input_req {
62 __u8 data[UHID_DATA_MAX];
63 __u16 size;
64} __attribute__((__packed__));
65
66struct uhid_output_req {
67 __u8 data[UHID_DATA_MAX];
68 __u16 size;
69 __u8 rtype;
70} __attribute__((__packed__));
71
72struct uhid_output_ev_req {
73 __u16 type;
74 __u16 code;
75 __s32 value;
76} __attribute__((__packed__));
77
78struct uhid_feature_req {
79 __u32 id;
80 __u8 rnum;
81 __u8 rtype;
82} __attribute__((__packed__));
83
84struct uhid_feature_answer_req {
85 __u32 id;
86 __u16 err;
87 __u16 size;
88 __u8 data[UHID_DATA_MAX];
89};
90
91struct uhid_event {
92 __u32 type;
93
94 union {
95 struct uhid_create_req create;
96 struct uhid_input_req input;
97 struct uhid_output_req output;
98 struct uhid_output_ev_req output_ev;
99 struct uhid_feature_req feature;
100 struct uhid_feature_answer_req feature_answer;
101 } u;
102} __attribute__((__packed__));
103
104#endif /* __UHID_H_ */
diff --git a/samples/uhid/Makefile b/samples/uhid/Makefile
new file mode 100644
index 000000000000..c95a696560a7
--- /dev/null
+++ b/samples/uhid/Makefile
@@ -0,0 +1,10 @@
1# kbuild trick to avoid linker error. Can be omitted if a module is built.
2obj- := dummy.o
3
4# List of programs to build
5hostprogs-y := uhid-example
6
7# Tell kbuild to always build the programs
8always := $(hostprogs-y)
9
10HOSTCFLAGS_uhid-example.o += -I$(objtree)/usr/include
diff --git a/samples/uhid/uhid-example.c b/samples/uhid/uhid-example.c
new file mode 100644
index 000000000000..03ce3c059a5e
--- /dev/null
+++ b/samples/uhid/uhid-example.c
@@ -0,0 +1,381 @@
1/*
2 * UHID Example
3 *
4 * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com>
5 *
6 * The code may be used by anyone for any purpose,
7 * and can serve as a starting point for developing
8 * applications using uhid.
9 */
10
11/* UHID Example
12 * This example emulates a basic 3 buttons mouse with wheel over UHID. Run this
13 * program as root and then use the following keys to control the mouse:
14 * q: Quit the application
15 * 1: Toggle left button (down, up, ...)
16 * 2: Toggle right button
17 * 3: Toggle middle button
18 * a: Move mouse left
19 * d: Move mouse right
20 * w: Move mouse up
21 * s: Move mouse down
22 * r: Move wheel up
23 * f: Move wheel down
24 *
25 * If uhid is not available as /dev/uhid, then you can pass a different path as
26 * first argument.
27 * If <linux/uhid.h> is not installed in /usr, then compile this with:
28 * gcc -o ./uhid_test -Wall -I./include ./samples/uhid/uhid-example.c
29 * And ignore the warning about kernel headers. However, it is recommended to
30 * use the installed uhid.h if available.
31 */
32
33#include <errno.h>
34#include <fcntl.h>
35#include <poll.h>
36#include <stdbool.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <termios.h>
41#include <unistd.h>
42#include <linux/uhid.h>
43
44/* HID Report Desciptor
45 * We emulate a basic 3 button mouse with wheel. This is the report-descriptor
46 * as the kernel will parse it:
47 *
48 * INPUT[INPUT]
49 * Field(0)
50 * Physical(GenericDesktop.Pointer)
51 * Application(GenericDesktop.Mouse)
52 * Usage(3)
53 * Button.0001
54 * Button.0002
55 * Button.0003
56 * Logical Minimum(0)
57 * Logical Maximum(1)
58 * Report Size(1)
59 * Report Count(3)
60 * Report Offset(0)
61 * Flags( Variable Absolute )
62 * Field(1)
63 * Physical(GenericDesktop.Pointer)
64 * Application(GenericDesktop.Mouse)
65 * Usage(3)
66 * GenericDesktop.X
67 * GenericDesktop.Y
68 * GenericDesktop.Wheel
69 * Logical Minimum(-128)
70 * Logical Maximum(127)
71 * Report Size(8)
72 * Report Count(3)
73 * Report Offset(8)
74 * Flags( Variable Relative )
75 *
76 * This is the mapping that we expect:
77 * Button.0001 ---> Key.LeftBtn
78 * Button.0002 ---> Key.RightBtn
79 * Button.0003 ---> Key.MiddleBtn
80 * GenericDesktop.X ---> Relative.X
81 * GenericDesktop.Y ---> Relative.Y
82 * GenericDesktop.Wheel ---> Relative.Wheel
83 *
84 * This information can be verified by reading /sys/kernel/debug/hid/<dev>/rdesc
85 * This file should print the same information as showed above.
86 */
87
88static unsigned char rdesc[] = {
89 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x01,
90 0xa1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03,
91 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01,
92 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01,
93 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x38,
94 0x15, 0x80, 0x25, 0x7f, 0x75, 0x08, 0x95, 0x03,
95 0x81, 0x06, 0xc0, 0xc0,
96};
97
98static int uhid_write(int fd, const struct uhid_event *ev)
99{
100 ssize_t ret;
101
102 ret = write(fd, ev, sizeof(*ev));
103 if (ret < 0) {
104 fprintf(stderr, "Cannot write to uhid: %m\n");
105 return -errno;
106 } else if (ret != sizeof(*ev)) {
107 fprintf(stderr, "Wrong size written to uhid: %ld != %lu\n",
108 ret, sizeof(ev));
109 return -EFAULT;
110 } else {
111 return 0;
112 }
113}
114
115static int create(int fd)
116{
117 struct uhid_event ev;
118
119 memset(&ev, 0, sizeof(ev));
120 ev.type = UHID_CREATE;
121 strcpy((char*)ev.u.create.name, "test-uhid-device");
122 ev.u.create.rd_data = rdesc;
123 ev.u.create.rd_size = sizeof(rdesc);
124 ev.u.create.bus = BUS_USB;
125 ev.u.create.vendor = 0x15d9;
126 ev.u.create.product = 0x0a37;
127 ev.u.create.version = 0;
128 ev.u.create.country = 0;
129
130 return uhid_write(fd, &ev);
131}
132
133static void destroy(int fd)
134{
135 struct uhid_event ev;
136
137 memset(&ev, 0, sizeof(ev));
138 ev.type = UHID_DESTROY;
139
140 uhid_write(fd, &ev);
141}
142
143static int event(int fd)
144{
145 struct uhid_event ev;
146 ssize_t ret;
147
148 memset(&ev, 0, sizeof(ev));
149 ret = read(fd, &ev, sizeof(ev));
150 if (ret == 0) {
151 fprintf(stderr, "Read HUP on uhid-cdev\n");
152 return -EFAULT;
153 } else if (ret < 0) {
154 fprintf(stderr, "Cannot read uhid-cdev: %m\n");
155 return -errno;
156 } else if (ret != sizeof(ev)) {
157 fprintf(stderr, "Invalid size read from uhid-dev: %ld != %lu\n",
158 ret, sizeof(ev));
159 return -EFAULT;
160 }
161
162 switch (ev.type) {
163 case UHID_START:
164 fprintf(stderr, "UHID_START from uhid-dev\n");
165 break;
166 case UHID_STOP:
167 fprintf(stderr, "UHID_STOP from uhid-dev\n");
168 break;
169 case UHID_OPEN:
170 fprintf(stderr, "UHID_OPEN from uhid-dev\n");
171 break;
172 case UHID_CLOSE:
173 fprintf(stderr, "UHID_CLOSE from uhid-dev\n");
174 break;
175 case UHID_OUTPUT:
176 fprintf(stderr, "UHID_OUTPUT from uhid-dev\n");
177 break;
178 case UHID_OUTPUT_EV:
179 fprintf(stderr, "UHID_OUTPUT_EV from uhid-dev\n");
180 break;
181 default:
182 fprintf(stderr, "Invalid event from uhid-dev: %u\n", ev.type);
183 }
184
185 return 0;
186}
187
188static bool btn1_down;
189static bool btn2_down;
190static bool btn3_down;
191static signed char abs_hor;
192static signed char abs_ver;
193static signed char wheel;
194
195static int send_event(int fd)
196{
197 struct uhid_event ev;
198
199 memset(&ev, 0, sizeof(ev));
200 ev.type = UHID_INPUT;
201 ev.u.input.size = 4;
202
203 if (btn1_down)
204 ev.u.input.data[0] |= 0x1;
205 if (btn2_down)
206 ev.u.input.data[0] |= 0x2;
207 if (btn3_down)
208 ev.u.input.data[0] |= 0x4;
209
210 ev.u.input.data[1] = abs_hor;
211 ev.u.input.data[2] = abs_ver;
212 ev.u.input.data[3] = wheel;
213
214 return uhid_write(fd, &ev);
215}
216
217static int keyboard(int fd)
218{
219 char buf[128];
220 ssize_t ret, i;
221
222 ret = read(STDIN_FILENO, buf, sizeof(buf));
223 if (ret == 0) {
224 fprintf(stderr, "Read HUP on stdin\n");
225 return -EFAULT;
226 } else if (ret < 0) {
227 fprintf(stderr, "Cannot read stdin: %m\n");
228 return -errno;
229 }
230
231 for (i = 0; i < ret; ++i) {
232 switch (buf[i]) {
233 case '1':
234 btn1_down = !btn1_down;
235 ret = send_event(fd);
236 if (ret)
237 return ret;
238 break;
239 case '2':
240 btn2_down = !btn2_down;
241 ret = send_event(fd);
242 if (ret)
243 return ret;
244 break;
245 case '3':
246 btn3_down = !btn3_down;
247 ret = send_event(fd);
248 if (ret)
249 return ret;
250 break;
251 case 'a':
252 abs_hor = -20;
253 ret = send_event(fd);
254 abs_hor = 0;
255 if (ret)
256 return ret;
257 break;
258 case 'd':
259 abs_hor = 20;
260 ret = send_event(fd);
261 abs_hor = 0;
262 if (ret)
263 return ret;
264 break;
265 case 'w':
266 abs_ver = -20;
267 ret = send_event(fd);
268 abs_ver = 0;
269 if (ret)
270 return ret;
271 break;
272 case 's':
273 abs_ver = 20;
274 ret = send_event(fd);
275 abs_ver = 0;
276 if (ret)
277 return ret;
278 break;
279 case 'r':
280 wheel = 1;
281 ret = send_event(fd);
282 wheel = 0;
283 if (ret)
284 return ret;
285 break;
286 case 'f':
287 wheel = -1;
288 ret = send_event(fd);
289 wheel = 0;
290 if (ret)
291 return ret;
292 break;
293 case 'q':
294 return -ECANCELED;
295 default:
296 fprintf(stderr, "Invalid input: %c\n", buf[i]);
297 }
298 }
299
300 return 0;
301}
302
303int main(int argc, char **argv)
304{
305 int fd;
306 const char *path = "/dev/uhid";
307 struct pollfd pfds[2];
308 int ret;
309 struct termios state;
310
311 ret = tcgetattr(STDIN_FILENO, &state);
312 if (ret) {
313 fprintf(stderr, "Cannot get tty state\n");
314 } else {
315 state.c_lflag &= ~ICANON;
316 state.c_cc[VMIN] = 1;
317 ret = tcsetattr(STDIN_FILENO, TCSANOW, &state);
318 if (ret)
319 fprintf(stderr, "Cannot set tty state\n");
320 }
321
322 if (argc >= 2) {
323 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
324 fprintf(stderr, "Usage: %s [%s]\n", argv[0], path);
325 return EXIT_SUCCESS;
326 } else {
327 path = argv[1];
328 }
329 }
330
331 fprintf(stderr, "Open uhid-cdev %s\n", path);
332 fd = open(path, O_RDWR | O_CLOEXEC);
333 if (fd < 0) {
334 fprintf(stderr, "Cannot open uhid-cdev %s: %m\n", path);
335 return EXIT_FAILURE;
336 }
337
338 fprintf(stderr, "Create uhid device\n");
339 ret = create(fd);
340 if (ret) {
341 close(fd);
342 return EXIT_FAILURE;
343 }
344
345 pfds[0].fd = STDIN_FILENO;
346 pfds[0].events = POLLIN;
347 pfds[1].fd = fd;
348 pfds[1].events = POLLIN;
349
350 fprintf(stderr, "Press 'q' to quit...\n");
351 while (1) {
352 ret = poll(pfds, 2, -1);
353 if (ret < 0) {
354 fprintf(stderr, "Cannot poll for fds: %m\n");
355 break;
356 }
357 if (pfds[0].revents & POLLHUP) {
358 fprintf(stderr, "Received HUP on stdin\n");
359 break;
360 }
361 if (pfds[1].revents & POLLHUP) {
362 fprintf(stderr, "Received HUP on uhid-cdev\n");
363 break;
364 }
365
366 if (pfds[0].revents & POLLIN) {
367 ret = keyboard(fd);
368 if (ret)
369 break;
370 }
371 if (pfds[1].revents & POLLIN) {
372 ret = event(fd);
373 if (ret)
374 break;
375 }
376 }
377
378 fprintf(stderr, "Destroy uhid device\n");
379 destroy(fd);
380 return EXIT_SUCCESS;
381}