aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hid/Kconfig19
-rw-r--r--drivers/hid/Makefile5
-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
28 files changed, 1450 insertions, 410 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 3fda8c87f02c..00445bc3019c 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -193,10 +193,12 @@ config HID_EZKEY
193 Support for Ezkey BTC 8193 keyboard. 193 Support for Ezkey BTC 8193 keyboard.
194 194
195config HID_HOLTEK 195config HID_HOLTEK
196 tristate "Holtek On Line Grip based game controller support" 196 tristate "Holtek HID devices"
197 depends on USB_HID 197 depends on USB_HID
198 ---help--- 198 ---help---
199 Say Y here if you have a Holtek On Line Grip based game controller. 199 Support for Holtek based devices:
200 - Holtek On Line Grip based game controller
201 - Trust GXT 18 Gaming Keyboard
200 202
201config HOLTEK_FF 203config HOLTEK_FF
202 bool "Holtek On Line Grip force feedback support" 204 bool "Holtek On Line Grip force feedback support"
@@ -261,6 +263,19 @@ config HID_LCPOWER
261 ---help--- 263 ---help---
262 Support for LC-Power RC1000MCE RF remote control. 264 Support for LC-Power RC1000MCE RF remote control.
263 265
266config HID_LENOVO_TPKBD
267 tristate "Lenovo ThinkPad USB Keyboard with TrackPoint"
268 depends on USB_HID
269 select NEW_LEDS
270 select LEDS_CLASS
271 ---help---
272 Support for the Lenovo ThinkPad USB Keyboard with TrackPoint.
273
274 Say Y here if you have a Lenovo ThinkPad USB Keyboard with TrackPoint
275 and would like to use device-specific features like changing the
276 sensitivity of the trackpoint, using the microphone mute button or
277 controlling the mute and microphone mute LEDs.
278
264config HID_LOGITECH 279config HID_LOGITECH
265 tristate "Logitech devices" if EXPERT 280 tristate "Logitech devices" if EXPERT
266 depends on USB_HID 281 depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index ca6cc9f0485c..02fa93896951 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -48,12 +48,14 @@ obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o
48obj-$(CONFIG_HID_ELECOM) += hid-elecom.o 48obj-$(CONFIG_HID_ELECOM) += hid-elecom.o
49obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o 49obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
50obj-$(CONFIG_HID_GYRATION) += hid-gyration.o 50obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
51obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
51obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o 52obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o
52obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o 53obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o
53obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o 54obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
54obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o 55obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o
55obj-$(CONFIG_HID_KYE) += hid-kye.o 56obj-$(CONFIG_HID_KYE) += hid-kye.o
56obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o 57obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o
58obj-$(CONFIG_HID_LENOVO_TPKBD) += hid-lenovo-tpkbd.o
57obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o 59obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
58obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o 60obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o
59obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o 61obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o
@@ -69,7 +71,8 @@ obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o
69obj-$(CONFIG_HID_PRIMAX) += hid-primax.o 71obj-$(CONFIG_HID_PRIMAX) += hid-primax.o
70obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ 72obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \
71 hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ 73 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 74 hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-pyra.o \
75 hid-roccat-savu.o
73obj-$(CONFIG_HID_SAITEK) += hid-saitek.o 76obj-$(CONFIG_HID_SAITEK) += hid-saitek.o
74obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o 77obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
75obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o 78obj-$(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