diff options
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/Kconfig | 19 | ||||
-rw-r--r-- | drivers/hid/Makefile | 2 | ||||
-rw-r--r-- | drivers/hid/hid-axff.c | 172 | ||||
-rw-r--r-- | drivers/hid/hid-core.c | 8 | ||||
-rw-r--r-- | drivers/hid/hid-elecom.c | 57 | ||||
-rw-r--r-- | drivers/hid/hid-ids.h | 91 | ||||
-rw-r--r-- | drivers/hid/hid-input.c | 21 | ||||
-rw-r--r-- | drivers/hid/hid-magicmouse.c | 96 | ||||
-rw-r--r-- | drivers/hid/hid-picolcd.c | 199 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-kone.c | 25 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-kone.h | 2 | ||||
-rw-r--r-- | drivers/hid/hid-roccat.c | 9 | ||||
-rw-r--r-- | drivers/hid/hid-roccat.h | 2 | ||||
-rw-r--r-- | drivers/hid/hid-topseed.c | 5 | ||||
-rw-r--r-- | drivers/hid/hid-wacom.c | 2 | ||||
-rw-r--r-- | drivers/hid/hidraw.c | 2 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-quirks.c | 2 | ||||
-rw-r--r-- | drivers/hid/usbhid/hiddev.c | 54 |
18 files changed, 585 insertions, 183 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 434099369058..6369ba7f96f8 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -68,6 +68,14 @@ config HID_A4TECH | |||
68 | ---help--- | 68 | ---help--- |
69 | Support for A4 tech X5 and WOP-35 / Trust 450L mice. | 69 | Support for A4 tech X5 and WOP-35 / Trust 450L mice. |
70 | 70 | ||
71 | config HID_ACRUX_FF | ||
72 | tristate "ACRUX force feedback support" | ||
73 | depends on USB_HID | ||
74 | select INPUT_FF_MEMLESS | ||
75 | ---help--- | ||
76 | Say Y here if you want to enable force feedback support for ACRUX | ||
77 | game controllers. | ||
78 | |||
71 | config HID_APPLE | 79 | config HID_APPLE |
72 | tristate "Apple" if EMBEDDED | 80 | tristate "Apple" if EMBEDDED |
73 | depends on (USB_HID || BT_HIDP) | 81 | depends on (USB_HID || BT_HIDP) |
@@ -148,6 +156,12 @@ config HID_EGALAX | |||
148 | ---help--- | 156 | ---help--- |
149 | Support for the eGalax dual-touch panel. | 157 | Support for the eGalax dual-touch panel. |
150 | 158 | ||
159 | config HID_ELECOM | ||
160 | tristate "ELECOM" | ||
161 | depends on BT_HIDP | ||
162 | ---help--- | ||
163 | Support for the ELECOM BM084 (bluetooth mouse). | ||
164 | |||
151 | config HID_EZKEY | 165 | config HID_EZKEY |
152 | tristate "Ezkey" if EMBEDDED | 166 | tristate "Ezkey" if EMBEDDED |
153 | depends on USB_HID | 167 | depends on USB_HID |
@@ -417,10 +431,11 @@ config SMARTJOYPLUS_FF | |||
417 | enable force feedback support for it. | 431 | enable force feedback support for it. |
418 | 432 | ||
419 | config HID_TOPSEED | 433 | config HID_TOPSEED |
420 | tristate "TopSeed Cyberlink remote control support" | 434 | tristate "TopSeed Cyberlink, BTC Emprex, Conceptronic remote control support" |
421 | depends on USB_HID | 435 | depends on USB_HID |
422 | ---help--- | 436 | ---help--- |
423 | Say Y if you have a TopSeed Cyberlink or BTC Emprex remote control. | 437 | Say Y if you have a TopSeed Cyberlink or BTC Emprex or Conceptronic |
438 | CLLRCMCE remote control. | ||
424 | 439 | ||
425 | config HID_THRUSTMASTER | 440 | config HID_THRUSTMASTER |
426 | tristate "ThrustMaster devices support" | 441 | tristate "ThrustMaster devices support" |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 987fa0627367..46f037f3df80 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
@@ -24,6 +24,7 @@ endif | |||
24 | 24 | ||
25 | obj-$(CONFIG_HID_3M_PCT) += hid-3m-pct.o | 25 | obj-$(CONFIG_HID_3M_PCT) += hid-3m-pct.o |
26 | obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o | 26 | obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o |
27 | obj-$(CONFIG_HID_ACRUX_FF) += hid-axff.o | ||
27 | obj-$(CONFIG_HID_APPLE) += hid-apple.o | 28 | obj-$(CONFIG_HID_APPLE) += hid-apple.o |
28 | obj-$(CONFIG_HID_BELKIN) += hid-belkin.o | 29 | obj-$(CONFIG_HID_BELKIN) += hid-belkin.o |
29 | obj-$(CONFIG_HID_CANDO) += hid-cando.o | 30 | obj-$(CONFIG_HID_CANDO) += hid-cando.o |
@@ -32,6 +33,7 @@ obj-$(CONFIG_HID_CHICONY) += hid-chicony.o | |||
32 | obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o | 33 | obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o |
33 | obj-$(CONFIG_HID_DRAGONRISE) += hid-drff.o | 34 | obj-$(CONFIG_HID_DRAGONRISE) += hid-drff.o |
34 | obj-$(CONFIG_HID_EGALAX) += hid-egalax.o | 35 | obj-$(CONFIG_HID_EGALAX) += hid-egalax.o |
36 | obj-$(CONFIG_HID_ELECOM) += hid-elecom.o | ||
35 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o | 37 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o |
36 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o | 38 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o |
37 | obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o | 39 | obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o |
diff --git a/drivers/hid/hid-axff.c b/drivers/hid/hid-axff.c new file mode 100644 index 000000000000..f42ee140738a --- /dev/null +++ b/drivers/hid/hid-axff.c | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * Force feedback support for ACRUX game controllers | ||
3 | * | ||
4 | * From what I have gathered, these devices are mass produced in China | ||
5 | * by several vendors. They often share the same design as the original | ||
6 | * Xbox 360 controller. | ||
7 | * | ||
8 | * 1a34:0802 "ACRUX USB GAMEPAD 8116" | ||
9 | * - tested with a EXEQ EQ-PCU-02090 game controller. | ||
10 | * | ||
11 | * Copyright (c) 2010 Sergei Kolzun <x0r@dv-life.ru> | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
28 | */ | ||
29 | |||
30 | #include <linux/input.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/usb.h> | ||
33 | #include <linux/hid.h> | ||
34 | |||
35 | #include "hid-ids.h" | ||
36 | #include "usbhid/usbhid.h" | ||
37 | |||
38 | struct axff_device { | ||
39 | struct hid_report *report; | ||
40 | }; | ||
41 | |||
42 | static int axff_play(struct input_dev *dev, void *data, struct ff_effect *effect) | ||
43 | { | ||
44 | struct hid_device *hid = input_get_drvdata(dev); | ||
45 | struct axff_device *axff = data; | ||
46 | int left, right; | ||
47 | |||
48 | left = effect->u.rumble.strong_magnitude; | ||
49 | right = effect->u.rumble.weak_magnitude; | ||
50 | |||
51 | dbg_hid("called with 0x%04x 0x%04x", left, right); | ||
52 | |||
53 | left = left * 0xff / 0xffff; | ||
54 | right = right * 0xff / 0xffff; | ||
55 | |||
56 | axff->report->field[0]->value[0] = left; | ||
57 | axff->report->field[1]->value[0] = right; | ||
58 | axff->report->field[2]->value[0] = left; | ||
59 | axff->report->field[3]->value[0] = right; | ||
60 | dbg_hid("running with 0x%02x 0x%02x", left, right); | ||
61 | usbhid_submit_report(hid, axff->report, USB_DIR_OUT); | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static int axff_init(struct hid_device *hid) | ||
67 | { | ||
68 | struct axff_device *axff; | ||
69 | struct hid_report *report; | ||
70 | struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input, list); | ||
71 | struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
72 | struct input_dev *dev = hidinput->input; | ||
73 | int error; | ||
74 | |||
75 | if (list_empty(report_list)) { | ||
76 | dev_err(&hid->dev, "no output reports found\n"); | ||
77 | return -ENODEV; | ||
78 | } | ||
79 | |||
80 | report = list_first_entry(report_list, struct hid_report, list); | ||
81 | |||
82 | if (report->maxfield < 4) { | ||
83 | dev_err(&hid->dev, "no fields in the report: %d\n", report->maxfield); | ||
84 | return -ENODEV; | ||
85 | } | ||
86 | |||
87 | axff = kzalloc(sizeof(struct axff_device), GFP_KERNEL); | ||
88 | if (!axff) | ||
89 | return -ENOMEM; | ||
90 | |||
91 | set_bit(FF_RUMBLE, dev->ffbit); | ||
92 | |||
93 | error = input_ff_create_memless(dev, axff, axff_play); | ||
94 | if (error) | ||
95 | goto err_free_mem; | ||
96 | |||
97 | axff->report = report; | ||
98 | axff->report->field[0]->value[0] = 0x00; | ||
99 | axff->report->field[1]->value[0] = 0x00; | ||
100 | axff->report->field[2]->value[0] = 0x00; | ||
101 | axff->report->field[3]->value[0] = 0x00; | ||
102 | usbhid_submit_report(hid, axff->report, USB_DIR_OUT); | ||
103 | |||
104 | dev_info(&hid->dev, "Force Feedback for ACRUX game controllers by Sergei Kolzun<x0r@dv-life.ru>\n"); | ||
105 | |||
106 | return 0; | ||
107 | |||
108 | err_free_mem: | ||
109 | kfree(axff); | ||
110 | return error; | ||
111 | } | ||
112 | |||
113 | static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
114 | { | ||
115 | int error; | ||
116 | |||
117 | dev_dbg(&hdev->dev, "ACRUX HID hardware probe..."); | ||
118 | |||
119 | error = hid_parse(hdev); | ||
120 | if (error) { | ||
121 | dev_err(&hdev->dev, "parse failed\n"); | ||
122 | return error; | ||
123 | } | ||
124 | |||
125 | error = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); | ||
126 | if (error) { | ||
127 | dev_err(&hdev->dev, "hw start failed\n"); | ||
128 | return error; | ||
129 | } | ||
130 | |||
131 | error = axff_init(hdev); | ||
132 | if (error) { | ||
133 | /* | ||
134 | * Do not fail device initialization completely as device | ||
135 | * may still be partially operable, just warn. | ||
136 | */ | ||
137 | dev_warn(&hdev->dev, | ||
138 | "Failed to enable force feedback support, error: %d\n", | ||
139 | error); | ||
140 | } | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static const struct hid_device_id ax_devices[] = { | ||
146 | { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802), }, | ||
147 | { } | ||
148 | }; | ||
149 | MODULE_DEVICE_TABLE(hid, ax_devices); | ||
150 | |||
151 | static struct hid_driver ax_driver = { | ||
152 | .name = "acrux", | ||
153 | .id_table = ax_devices, | ||
154 | .probe = ax_probe, | ||
155 | }; | ||
156 | |||
157 | static int __init ax_init(void) | ||
158 | { | ||
159 | return hid_register_driver(&ax_driver); | ||
160 | } | ||
161 | |||
162 | static void __exit ax_exit(void) | ||
163 | { | ||
164 | hid_unregister_driver(&ax_driver); | ||
165 | } | ||
166 | |||
167 | module_init(ax_init); | ||
168 | module_exit(ax_exit); | ||
169 | |||
170 | MODULE_AUTHOR("Sergei Kolzun"); | ||
171 | MODULE_DESCRIPTION("Force feedback support for ACRUX game controllers"); | ||
172 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index b54a9a608ac2..e635199a0cd2 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1157,6 +1157,8 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) | |||
1157 | 1157 | ||
1158 | if (hdev->quirks & HID_QUIRK_HIDDEV_FORCE) | 1158 | if (hdev->quirks & HID_QUIRK_HIDDEV_FORCE) |
1159 | connect_mask |= (HID_CONNECT_HIDDEV_FORCE | HID_CONNECT_HIDDEV); | 1159 | connect_mask |= (HID_CONNECT_HIDDEV_FORCE | HID_CONNECT_HIDDEV); |
1160 | if (hdev->quirks & HID_QUIRK_HIDINPUT_FORCE) | ||
1161 | connect_mask |= HID_CONNECT_HIDINPUT_FORCE; | ||
1160 | if (hdev->bus != BUS_USB) | 1162 | if (hdev->bus != BUS_USB) |
1161 | connect_mask &= ~HID_CONNECT_HIDDEV; | 1163 | connect_mask &= ~HID_CONNECT_HIDDEV; |
1162 | if (hid_hiddev(hdev)) | 1164 | if (hid_hiddev(hdev)) |
@@ -1239,6 +1241,9 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1239 | { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) }, | 1241 | { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) }, |
1240 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, | 1242 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, |
1241 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, | 1243 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, |
1244 | #if defined(CONFIG_HID_ACRUX_FF) || defined(CONFIG_HID_ACRUX_FF_MODULE) | ||
1245 | { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) }, | ||
1246 | #endif | ||
1242 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) }, | 1247 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) }, |
1243 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, | 1248 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, |
1244 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) }, | 1249 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) }, |
@@ -1294,6 +1299,7 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1294 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, | 1299 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, |
1295 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, | 1300 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, |
1296 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) }, | 1301 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) }, |
1302 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, | ||
1297 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, | 1303 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, |
1298 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, | 1304 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, |
1299 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, | 1305 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, |
@@ -1375,10 +1381,10 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1375 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb653) }, | 1381 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb653) }, |
1376 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) }, | 1382 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) }, |
1377 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, | 1383 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, |
1384 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, | ||
1378 | { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, | 1385 | { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, |
1379 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, | 1386 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, |
1380 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, | 1387 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, |
1381 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) }, | ||
1382 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, | 1388 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, |
1383 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, | 1389 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, |
1384 | { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) }, | 1390 | { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) }, |
diff --git a/drivers/hid/hid-elecom.c b/drivers/hid/hid-elecom.c new file mode 100644 index 000000000000..7a40878f46b4 --- /dev/null +++ b/drivers/hid/hid-elecom.c | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * HID driver for Elecom BM084 (bluetooth mouse). | ||
3 | * Removes a non-existing horizontal wheel from | ||
4 | * the HID descriptor. | ||
5 | * (This module is based on "hid-ortek".) | ||
6 | * | ||
7 | * Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com> | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the Free | ||
13 | * Software Foundation; either version 2 of the License, or (at your option) | ||
14 | * any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/device.h> | ||
18 | #include <linux/hid.h> | ||
19 | #include <linux/module.h> | ||
20 | |||
21 | #include "hid-ids.h" | ||
22 | |||
23 | static void elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, | ||
24 | unsigned int rsize) | ||
25 | { | ||
26 | if (rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) { | ||
27 | dev_info(&hdev->dev, "Fixing up Elecom BM084 " | ||
28 | "report descriptor.\n"); | ||
29 | rdesc[47] = 0x00; | ||
30 | } | ||
31 | } | ||
32 | |||
33 | static const struct hid_device_id elecom_devices[] = { | ||
34 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084)}, | ||
35 | { } | ||
36 | }; | ||
37 | MODULE_DEVICE_TABLE(hid, elecom_devices); | ||
38 | |||
39 | static struct hid_driver elecom_driver = { | ||
40 | .name = "elecom", | ||
41 | .id_table = elecom_devices, | ||
42 | .report_fixup = elecom_report_fixup | ||
43 | }; | ||
44 | |||
45 | static int __init elecom_init(void) | ||
46 | { | ||
47 | return hid_register_driver(&elecom_driver); | ||
48 | } | ||
49 | |||
50 | static void __exit elecom_exit(void) | ||
51 | { | ||
52 | hid_unregister_driver(&elecom_driver); | ||
53 | } | ||
54 | |||
55 | module_init(elecom_init); | ||
56 | module_exit(elecom_exit); | ||
57 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 8aee2577c1ad..d3fc13ae094d 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -34,6 +34,8 @@ | |||
34 | #define USB_DEVICE_ID_ACECAD_FLAIR 0x0004 | 34 | #define USB_DEVICE_ID_ACECAD_FLAIR 0x0004 |
35 | #define USB_DEVICE_ID_ACECAD_302 0x0008 | 35 | #define USB_DEVICE_ID_ACECAD_302 0x0008 |
36 | 36 | ||
37 | #define USB_VENDOR_ID_ACRUX 0x1a34 | ||
38 | |||
37 | #define USB_VENDOR_ID_ADS_TECH 0x06e1 | 39 | #define USB_VENDOR_ID_ADS_TECH 0x06e1 |
38 | #define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X 0xa155 | 40 | #define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X 0xa155 |
39 | 41 | ||
@@ -81,12 +83,12 @@ | |||
81 | #define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI 0x0223 | 83 | #define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI 0x0223 |
82 | #define USB_DEVICE_ID_APPLE_WELLSPRING_ISO 0x0224 | 84 | #define USB_DEVICE_ID_APPLE_WELLSPRING_ISO 0x0224 |
83 | #define USB_DEVICE_ID_APPLE_WELLSPRING_JIS 0x0225 | 85 | #define USB_DEVICE_ID_APPLE_WELLSPRING_JIS 0x0225 |
84 | #define USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI 0x0229 | 86 | #define USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI 0x0229 |
85 | #define USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO 0x022a | 87 | #define USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO 0x022a |
86 | #define USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS 0x022b | 88 | #define USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS 0x022b |
87 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI 0x022c | 89 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI 0x022c |
88 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO 0x022d | 90 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO 0x022d |
89 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS 0x022e | 91 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS 0x022e |
90 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 | 92 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 |
91 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 | 93 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 |
92 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 | 94 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 |
@@ -118,8 +120,8 @@ | |||
118 | #define USB_VENDOR_ID_AVERMEDIA 0x07ca | 120 | #define USB_VENDOR_ID_AVERMEDIA 0x07ca |
119 | #define USB_DEVICE_ID_AVER_FM_MR800 0xb800 | 121 | #define USB_DEVICE_ID_AVER_FM_MR800 0xb800 |
120 | 122 | ||
121 | #define USB_VENDOR_ID_BELKIN 0x050d | 123 | #define USB_VENDOR_ID_BELKIN 0x050d |
122 | #define USB_DEVICE_ID_FLIP_KVM 0x3201 | 124 | #define USB_DEVICE_ID_FLIP_KVM 0x3201 |
123 | 125 | ||
124 | #define USB_VENDOR_ID_BERKSHIRE 0x0c98 | 126 | #define USB_VENDOR_ID_BERKSHIRE 0x0c98 |
125 | #define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140 | 127 | #define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140 |
@@ -128,7 +130,7 @@ | |||
128 | #define USB_DEVICE_ID_BTC_EMPREX_REMOTE 0x5578 | 130 | #define USB_DEVICE_ID_BTC_EMPREX_REMOTE 0x5578 |
129 | 131 | ||
130 | #define USB_VENDOR_ID_CANDO 0x2087 | 132 | #define USB_VENDOR_ID_CANDO 0x2087 |
131 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 | 133 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 |
132 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03 | 134 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03 |
133 | 135 | ||
134 | #define USB_VENDOR_ID_CH 0x068e | 136 | #define USB_VENDOR_ID_CH 0x068e |
@@ -175,7 +177,7 @@ | |||
175 | #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a | 177 | #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a |
176 | 178 | ||
177 | #define USB_VENDOR_ID_DELORME 0x1163 | 179 | #define USB_VENDOR_ID_DELORME 0x1163 |
178 | #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 | 180 | #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 |
179 | #define USB_DEVICE_ID_DELORME_EM_LT20 0x0200 | 181 | #define USB_DEVICE_ID_DELORME_EM_LT20 0x0200 |
180 | 182 | ||
181 | #define USB_VENDOR_ID_DMI 0x0c0b | 183 | #define USB_VENDOR_ID_DMI 0x0c0b |
@@ -187,20 +189,23 @@ | |||
187 | #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 | 189 | #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 |
188 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH 0x480d | 190 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH 0x480d |
189 | 191 | ||
192 | #define USB_VENDOR_ID_ELECOM 0x056e | ||
193 | #define USB_DEVICE_ID_ELECOM_BM084 0x0061 | ||
194 | |||
190 | #define USB_VENDOR_ID_ELO 0x04E7 | 195 | #define USB_VENDOR_ID_ELO 0x04E7 |
191 | #define USB_DEVICE_ID_ELO_TS2700 0x0020 | 196 | #define USB_DEVICE_ID_ELO_TS2700 0x0020 |
192 | 197 | ||
193 | #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f | 198 | #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f |
194 | #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 | 199 | #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 |
195 | 200 | ||
196 | #define USB_VENDOR_ID_ETURBOTOUCH 0x22b9 | ||
197 | #define USB_DEVICE_ID_ETURBOTOUCH 0x0006 | ||
198 | |||
199 | #define USB_VENDOR_ID_ETT 0x0664 | 201 | #define USB_VENDOR_ID_ETT 0x0664 |
200 | #define USB_DEVICE_ID_TC5UH 0x0309 | 202 | #define USB_DEVICE_ID_TC5UH 0x0309 |
201 | #define USB_DEVICE_ID_TC4UM 0x0306 | 203 | #define USB_DEVICE_ID_TC4UM 0x0306 |
202 | 204 | ||
203 | #define USB_VENDOR_ID_EZKEY 0x0518 | 205 | #define USB_VENDOR_ID_ETURBOTOUCH 0x22b9 |
206 | #define USB_DEVICE_ID_ETURBOTOUCH 0x0006 | ||
207 | |||
208 | #define USB_VENDOR_ID_EZKEY 0x0518 | ||
204 | #define USB_DEVICE_ID_BTC_8193 0x0002 | 209 | #define USB_DEVICE_ID_BTC_8193 0x0002 |
205 | 210 | ||
206 | #define USB_VENDOR_ID_GAMERON 0x0810 | 211 | #define USB_VENDOR_ID_GAMERON 0x0810 |
@@ -297,9 +302,16 @@ | |||
297 | #define USB_VENDOR_ID_KBGEAR 0x084e | 302 | #define USB_VENDOR_ID_KBGEAR 0x084e |
298 | #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 | 303 | #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 |
299 | 304 | ||
305 | #define USB_VENDOR_ID_KENSINGTON 0x047d | ||
306 | #define USB_DEVICE_ID_KS_SLIMBLADE 0x2041 | ||
307 | |||
300 | #define USB_VENDOR_ID_KWORLD 0x1b80 | 308 | #define USB_VENDOR_ID_KWORLD 0x1b80 |
301 | #define USB_DEVICE_ID_KWORLD_RADIO_FM700 0xd700 | 309 | #define USB_DEVICE_ID_KWORLD_RADIO_FM700 0xd700 |
302 | 310 | ||
311 | #define USB_VENDOR_ID_KYE 0x0458 | ||
312 | #define USB_DEVICE_ID_KYE_ERGO_525V 0x0087 | ||
313 | #define USB_DEVICE_ID_KYE_GPEN_560 0x5003 | ||
314 | |||
303 | #define USB_VENDOR_ID_LABTEC 0x1020 | 315 | #define USB_VENDOR_ID_LABTEC 0x1020 |
304 | #define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006 | 316 | #define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006 |
305 | 317 | ||
@@ -319,9 +331,6 @@ | |||
319 | #define USB_DEVICE_ID_LD_POWERCONTROL 0x2030 | 331 | #define USB_DEVICE_ID_LD_POWERCONTROL 0x2030 |
320 | #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 | 332 | #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 |
321 | 333 | ||
322 | #define USB_VENDOR_ID_KENSINGTON 0x047d | ||
323 | #define USB_DEVICE_ID_KS_SLIMBLADE 0x2041 | ||
324 | |||
325 | #define USB_VENDOR_ID_LOGITECH 0x046d | 334 | #define USB_VENDOR_ID_LOGITECH 0x046d |
326 | #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 | 335 | #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 |
327 | #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 | 336 | #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 |
@@ -377,23 +386,23 @@ | |||
377 | #define USB_VENDOR_ID_MONTEREY 0x0566 | 386 | #define USB_VENDOR_ID_MONTEREY 0x0566 |
378 | #define USB_DEVICE_ID_GENIUS_KB29E 0x3004 | 387 | #define USB_DEVICE_ID_GENIUS_KB29E 0x3004 |
379 | 388 | ||
389 | #define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400 | ||
390 | #define USB_DEVICE_ID_N_S_HARMONY 0xc359 | ||
391 | |||
392 | #define USB_VENDOR_ID_NATSU 0x08b7 | ||
393 | #define USB_DEVICE_ID_NATSU_GAMEPAD 0x0001 | ||
394 | |||
380 | #define USB_VENDOR_ID_NCR 0x0404 | 395 | #define USB_VENDOR_ID_NCR 0x0404 |
381 | #define USB_DEVICE_ID_NCR_FIRST 0x0300 | 396 | #define USB_DEVICE_ID_NCR_FIRST 0x0300 |
382 | #define USB_DEVICE_ID_NCR_LAST 0x03ff | 397 | #define USB_DEVICE_ID_NCR_LAST 0x03ff |
383 | 398 | ||
384 | #define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400 | ||
385 | #define USB_DEVICE_ID_N_S_HARMONY 0xc359 | ||
386 | |||
387 | #define USB_VENDOR_ID_NATSU 0x08b7 | ||
388 | #define USB_DEVICE_ID_NATSU_GAMEPAD 0x0001 | ||
389 | |||
390 | #define USB_VENDOR_ID_NEC 0x073e | 399 | #define USB_VENDOR_ID_NEC 0x073e |
391 | #define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301 | 400 | #define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301 |
392 | 401 | ||
393 | #define USB_VENDOR_ID_NEXTWINDOW 0x1926 | 402 | #define USB_VENDOR_ID_NEXTWINDOW 0x1926 |
394 | #define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN 0x0003 | 403 | #define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN 0x0003 |
395 | 404 | ||
396 | #define USB_VENDOR_ID_NTRIG 0x1b96 | 405 | #define USB_VENDOR_ID_NTRIG 0x1b96 |
397 | #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001 | 406 | #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001 |
398 | #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1 0x0003 | 407 | #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1 0x0003 |
399 | #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2 0x0004 | 408 | #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2 0x0004 |
@@ -428,9 +437,12 @@ | |||
428 | #define USB_VENDOR_ID_PETALYNX 0x18b1 | 437 | #define USB_VENDOR_ID_PETALYNX 0x18b1 |
429 | #define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037 | 438 | #define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037 |
430 | 439 | ||
431 | #define USB_VENDOR_ID_PHILIPS 0x0471 | 440 | #define USB_VENDOR_ID_PHILIPS 0x0471 |
432 | #define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617 | 441 | #define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617 |
433 | 442 | ||
443 | #define USB_VENDOR_ID_PI_ENGINEERING 0x05f3 | ||
444 | #define USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL 0xff | ||
445 | |||
434 | #define USB_VENDOR_ID_PLAYDOTCOM 0x0b43 | 446 | #define USB_VENDOR_ID_PLAYDOTCOM 0x0b43 |
435 | #define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003 | 447 | #define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003 |
436 | 448 | ||
@@ -440,16 +452,16 @@ | |||
440 | #define USB_VENDOR_ID_PRODIGE 0x05af | 452 | #define USB_VENDOR_ID_PRODIGE 0x05af |
441 | #define USB_DEVICE_ID_PRODIGE_CORDLESS 0x3062 | 453 | #define USB_DEVICE_ID_PRODIGE_CORDLESS 0x3062 |
442 | 454 | ||
455 | #define USB_VENDOR_ID_QUANTA 0x0408 | ||
456 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH 0x3000 | ||
457 | #define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN 0x3001 | ||
458 | |||
443 | #define USB_VENDOR_ID_ROCCAT 0x1e7d | 459 | #define USB_VENDOR_ID_ROCCAT 0x1e7d |
444 | #define USB_DEVICE_ID_ROCCAT_KONE 0x2ced | 460 | #define USB_DEVICE_ID_ROCCAT_KONE 0x2ced |
445 | 461 | ||
446 | #define USB_VENDOR_ID_SAITEK 0x06a3 | 462 | #define USB_VENDOR_ID_SAITEK 0x06a3 |
447 | #define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 | 463 | #define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 |
448 | 464 | ||
449 | #define USB_VENDOR_ID_QUANTA 0x0408 | ||
450 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH 0x3000 | ||
451 | #define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN 0x3001 | ||
452 | |||
453 | #define USB_VENDOR_ID_SAMSUNG 0x0419 | 465 | #define USB_VENDOR_ID_SAMSUNG 0x0419 |
454 | #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001 | 466 | #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001 |
455 | #define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE 0x0600 | 467 | #define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE 0x0600 |
@@ -473,20 +485,23 @@ | |||
473 | 485 | ||
474 | #define USB_VENDOR_ID_THRUSTMASTER 0x044f | 486 | #define USB_VENDOR_ID_THRUSTMASTER 0x044f |
475 | 487 | ||
476 | #define USB_VENDOR_ID_TOUCHPACK 0x1bfd | 488 | #define USB_VENDOR_ID_TOPSEED 0x0766 |
477 | #define USB_DEVICE_ID_TOUCHPACK_RTS 0x1688 | 489 | #define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204 |
490 | |||
491 | #define USB_VENDOR_ID_TOPSEED2 0x1784 | ||
492 | #define USB_DEVICE_ID_TOPSEED2_RF_COMBO 0x0004 | ||
478 | 493 | ||
479 | #define USB_VENDOR_ID_TOPMAX 0x0663 | 494 | #define USB_VENDOR_ID_TOPMAX 0x0663 |
480 | #define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 | 495 | #define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 |
481 | 496 | ||
482 | #define USB_VENDOR_ID_TOPSEED 0x0766 | 497 | #define USB_VENDOR_ID_TOUCHPACK 0x1bfd |
483 | #define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204 | 498 | #define USB_DEVICE_ID_TOUCHPACK_RTS 0x1688 |
484 | 499 | ||
485 | #define USB_VENDOR_ID_TURBOX 0x062a | 500 | #define USB_VENDOR_ID_TURBOX 0x062a |
486 | #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 | 501 | #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 |
487 | 502 | ||
488 | #define USB_VENDOR_ID_TWINHAN 0x6253 | 503 | #define USB_VENDOR_ID_TWINHAN 0x6253 |
489 | #define USB_DEVICE_ID_TWINHAN_IR_REMOTE 0x0100 | 504 | #define USB_DEVICE_ID_TWINHAN_IR_REMOTE 0x0100 |
490 | 505 | ||
491 | #define USB_VENDOR_ID_UCLOGIC 0x5543 | 506 | #define USB_VENDOR_ID_UCLOGIC 0x5543 |
492 | #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 | 507 | #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 |
@@ -501,7 +516,6 @@ | |||
501 | 516 | ||
502 | #define USB_VENDOR_ID_WACOM 0x056a | 517 | #define USB_VENDOR_ID_WACOM 0x056a |
503 | #define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81 | 518 | #define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81 |
504 | #define USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH 0xbd | ||
505 | 519 | ||
506 | #define USB_VENDOR_ID_WISEGROUP 0x0925 | 520 | #define USB_VENDOR_ID_WISEGROUP 0x0925 |
507 | #define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005 | 521 | #define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005 |
@@ -523,9 +537,4 @@ | |||
523 | #define USB_VENDOR_ID_ZYDACRON 0x13EC | 537 | #define USB_VENDOR_ID_ZYDACRON 0x13EC |
524 | #define USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL 0x0006 | 538 | #define USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL 0x0006 |
525 | 539 | ||
526 | #define USB_VENDOR_ID_KYE 0x0458 | ||
527 | #define USB_DEVICE_ID_KYE_ERGO_525V 0x0087 | ||
528 | #define USB_DEVICE_ID_KYE_GPEN_560 0x5003 | ||
529 | |||
530 | |||
531 | #endif | 540 | #endif |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 69d152e16a6a..6c03dcc5760a 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -199,11 +199,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
199 | case HID_GD_MOUSE: | 199 | case HID_GD_MOUSE: |
200 | case HID_GD_POINTER: code += 0x110; break; | 200 | case HID_GD_POINTER: code += 0x110; break; |
201 | case HID_GD_JOYSTICK: | 201 | case HID_GD_JOYSTICK: |
202 | if (code <= 0xf) | 202 | if (code <= 0xf) |
203 | code += BTN_JOYSTICK; | 203 | code += BTN_JOYSTICK; |
204 | else | 204 | else |
205 | code += BTN_TRIGGER_HAPPY; | 205 | code += BTN_TRIGGER_HAPPY; |
206 | break; | 206 | break; |
207 | case HID_GD_GAMEPAD: code += 0x130; break; | 207 | case HID_GD_GAMEPAD: code += 0x130; break; |
208 | default: | 208 | default: |
209 | switch (field->physical) { | 209 | switch (field->physical) { |
@@ -301,6 +301,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
301 | 301 | ||
302 | case HID_UP_DIGITIZER: | 302 | case HID_UP_DIGITIZER: |
303 | switch (usage->hid & 0xff) { | 303 | switch (usage->hid & 0xff) { |
304 | case 0x00: /* Undefined */ | ||
305 | goto ignore; | ||
306 | |||
304 | case 0x30: /* TipPressure */ | 307 | case 0x30: /* TipPressure */ |
305 | if (!test_bit(BTN_TOUCH, input->keybit)) { | 308 | if (!test_bit(BTN_TOUCH, input->keybit)) { |
306 | device->quirks |= HID_QUIRK_NOTOUCH; | 309 | device->quirks |= HID_QUIRK_NOTOUCH; |
@@ -480,7 +483,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
480 | 483 | ||
481 | case HID_UP_LOGIVENDOR: | 484 | case HID_UP_LOGIVENDOR: |
482 | goto ignore; | 485 | goto ignore; |
483 | 486 | ||
484 | case HID_UP_PID: | 487 | case HID_UP_PID: |
485 | switch (usage->hid & HID_USAGE) { | 488 | switch (usage->hid & HID_USAGE) { |
486 | case 0xa4: map_key_clear(BTN_DEAD); break; | 489 | case 0xa4: map_key_clear(BTN_DEAD); break; |
@@ -589,9 +592,9 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct | |||
589 | hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; | 592 | hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; |
590 | if (hat_dir < 0 || hat_dir > 8) hat_dir = 0; | 593 | if (hat_dir < 0 || hat_dir > 8) hat_dir = 0; |
591 | input_event(input, usage->type, usage->code , hid_hat_to_axis[hat_dir].x); | 594 | input_event(input, usage->type, usage->code , hid_hat_to_axis[hat_dir].x); |
592 | input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[hat_dir].y); | 595 | input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[hat_dir].y); |
593 | return; | 596 | return; |
594 | } | 597 | } |
595 | 598 | ||
596 | if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */ | 599 | if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */ |
597 | *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT); | 600 | *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT); |
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index f10d56a15f21..319b0e57ee41 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c | |||
@@ -30,6 +30,21 @@ static bool emulate_scroll_wheel = true; | |||
30 | module_param(emulate_scroll_wheel, bool, 0644); | 30 | module_param(emulate_scroll_wheel, bool, 0644); |
31 | MODULE_PARM_DESC(emulate_scroll_wheel, "Emulate a scroll wheel"); | 31 | MODULE_PARM_DESC(emulate_scroll_wheel, "Emulate a scroll wheel"); |
32 | 32 | ||
33 | static unsigned int scroll_speed = 32; | ||
34 | static int param_set_scroll_speed(const char *val, struct kernel_param *kp) { | ||
35 | unsigned long speed; | ||
36 | if (!val || strict_strtoul(val, 0, &speed) || speed > 63) | ||
37 | return -EINVAL; | ||
38 | scroll_speed = speed; | ||
39 | return 0; | ||
40 | } | ||
41 | module_param_call(scroll_speed, param_set_scroll_speed, param_get_uint, &scroll_speed, 0644); | ||
42 | MODULE_PARM_DESC(scroll_speed, "Scroll speed, value from 0 (slow) to 63 (fast)"); | ||
43 | |||
44 | static bool scroll_acceleration = false; | ||
45 | module_param(scroll_acceleration, bool, 0644); | ||
46 | MODULE_PARM_DESC(scroll_acceleration, "Accelerate sequential scroll events"); | ||
47 | |||
33 | static bool report_touches = true; | 48 | static bool report_touches = true; |
34 | module_param(report_touches, bool, 0644); | 49 | module_param(report_touches, bool, 0644); |
35 | MODULE_PARM_DESC(report_touches, "Emit touch records (otherwise, only use them for emulation)"); | 50 | MODULE_PARM_DESC(report_touches, "Emit touch records (otherwise, only use them for emulation)"); |
@@ -50,6 +65,8 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie | |||
50 | #define TOUCH_STATE_START 0x30 | 65 | #define TOUCH_STATE_START 0x30 |
51 | #define TOUCH_STATE_DRAG 0x40 | 66 | #define TOUCH_STATE_DRAG 0x40 |
52 | 67 | ||
68 | #define SCROLL_ACCEL_DEFAULT 7 | ||
69 | |||
53 | /** | 70 | /** |
54 | * struct magicmouse_sc - Tracks Magic Mouse-specific data. | 71 | * struct magicmouse_sc - Tracks Magic Mouse-specific data. |
55 | * @input: Input device through which we report events. | 72 | * @input: Input device through which we report events. |
@@ -78,8 +95,10 @@ struct magicmouse_sc { | |||
78 | struct { | 95 | struct { |
79 | short x; | 96 | short x; |
80 | short y; | 97 | short y; |
98 | short scroll_x; | ||
81 | short scroll_y; | 99 | short scroll_y; |
82 | u8 size; | 100 | u8 size; |
101 | u8 down; | ||
83 | } touches[16]; | 102 | } touches[16]; |
84 | int tracking_ids[16]; | 103 | int tracking_ids[16]; |
85 | }; | 104 | }; |
@@ -141,7 +160,7 @@ static void magicmouse_emit_buttons(struct magicmouse_sc *msc, int state) | |||
141 | input_report_key(msc->input, BTN_RIGHT, state & 2); | 160 | input_report_key(msc->input, BTN_RIGHT, state & 2); |
142 | 161 | ||
143 | if (state != last_state) | 162 | if (state != last_state) |
144 | msc->scroll_accel = 0; | 163 | msc->scroll_accel = SCROLL_ACCEL_DEFAULT; |
145 | } | 164 | } |
146 | 165 | ||
147 | static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata) | 166 | static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata) |
@@ -152,6 +171,7 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda | |||
152 | int id = (misc >> 6) & 15; | 171 | int id = (misc >> 6) & 15; |
153 | int x = x_y << 12 >> 20; | 172 | int x = x_y << 12 >> 20; |
154 | int y = -(x_y >> 20); | 173 | int y = -(x_y >> 20); |
174 | int down = (tdata[7] & TOUCH_STATE_MASK) != TOUCH_STATE_NONE; | ||
155 | 175 | ||
156 | /* Store tracking ID and other fields. */ | 176 | /* Store tracking ID and other fields. */ |
157 | msc->tracking_ids[raw_id] = id; | 177 | msc->tracking_ids[raw_id] = id; |
@@ -160,42 +180,54 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda | |||
160 | msc->touches[id].size = misc & 63; | 180 | msc->touches[id].size = misc & 63; |
161 | 181 | ||
162 | /* If requested, emulate a scroll wheel by detecting small | 182 | /* If requested, emulate a scroll wheel by detecting small |
163 | * vertical touch motions along the middle of the mouse. | 183 | * vertical touch motions. |
164 | */ | 184 | */ |
165 | if (emulate_scroll_wheel && | 185 | if (emulate_scroll_wheel) { |
166 | middle_button_start < x && x < middle_button_stop) { | ||
167 | static const int accel_profile[] = { | ||
168 | 256, 228, 192, 160, 128, 96, 64, 32, | ||
169 | }; | ||
170 | unsigned long now = jiffies; | 186 | unsigned long now = jiffies; |
171 | int step = msc->touches[id].scroll_y - y; | 187 | int step_x = msc->touches[id].scroll_x - x; |
172 | 188 | int step_y = msc->touches[id].scroll_y - y; | |
173 | /* Reset acceleration after half a second. */ | ||
174 | if (time_after(now, msc->scroll_jiffies + HZ / 2)) | ||
175 | msc->scroll_accel = 0; | ||
176 | 189 | ||
177 | /* Calculate and apply the scroll motion. */ | 190 | /* Calculate and apply the scroll motion. */ |
178 | switch (tdata[7] & TOUCH_STATE_MASK) { | 191 | switch (tdata[7] & TOUCH_STATE_MASK) { |
179 | case TOUCH_STATE_START: | 192 | case TOUCH_STATE_START: |
193 | msc->touches[id].scroll_x = x; | ||
180 | msc->touches[id].scroll_y = y; | 194 | msc->touches[id].scroll_y = y; |
181 | msc->scroll_accel = min_t(int, msc->scroll_accel + 1, | 195 | |
182 | ARRAY_SIZE(accel_profile) - 1); | 196 | /* Reset acceleration after half a second. */ |
197 | if (scroll_acceleration && time_before(now, | ||
198 | msc->scroll_jiffies + HZ / 2)) | ||
199 | msc->scroll_accel = max_t(int, | ||
200 | msc->scroll_accel - 1, 1); | ||
201 | else | ||
202 | msc->scroll_accel = SCROLL_ACCEL_DEFAULT; | ||
203 | |||
183 | break; | 204 | break; |
184 | case TOUCH_STATE_DRAG: | 205 | case TOUCH_STATE_DRAG: |
185 | step = step / accel_profile[msc->scroll_accel]; | 206 | step_x /= (64 - (int)scroll_speed) * msc->scroll_accel; |
186 | if (step != 0) { | 207 | if (step_x != 0) { |
187 | msc->touches[id].scroll_y = y; | 208 | msc->touches[id].scroll_x -= step_x * |
209 | (64 - scroll_speed) * msc->scroll_accel; | ||
188 | msc->scroll_jiffies = now; | 210 | msc->scroll_jiffies = now; |
189 | input_report_rel(input, REL_WHEEL, step); | 211 | input_report_rel(input, REL_HWHEEL, -step_x); |
212 | } | ||
213 | |||
214 | step_y /= (64 - (int)scroll_speed) * msc->scroll_accel; | ||
215 | if (step_y != 0) { | ||
216 | msc->touches[id].scroll_y -= step_y * | ||
217 | (64 - scroll_speed) * msc->scroll_accel; | ||
218 | msc->scroll_jiffies = now; | ||
219 | input_report_rel(input, REL_WHEEL, step_y); | ||
190 | } | 220 | } |
191 | break; | 221 | break; |
192 | } | 222 | } |
193 | } | 223 | } |
194 | 224 | ||
195 | /* Generate the input events for this touch. */ | 225 | /* Generate the input events for this touch. */ |
196 | if (report_touches) { | 226 | if (report_touches && down) { |
197 | int orientation = (misc >> 10) - 32; | 227 | int orientation = (misc >> 10) - 32; |
198 | 228 | ||
229 | msc->touches[id].down = 1; | ||
230 | |||
199 | input_report_abs(input, ABS_MT_TRACKING_ID, id); | 231 | input_report_abs(input, ABS_MT_TRACKING_ID, id); |
200 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, tdata[3]); | 232 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, tdata[3]); |
201 | input_report_abs(input, ABS_MT_TOUCH_MINOR, tdata[4]); | 233 | input_report_abs(input, ABS_MT_TOUCH_MINOR, tdata[4]); |
@@ -215,7 +247,7 @@ static int magicmouse_raw_event(struct hid_device *hdev, | |||
215 | { | 247 | { |
216 | struct magicmouse_sc *msc = hid_get_drvdata(hdev); | 248 | struct magicmouse_sc *msc = hid_get_drvdata(hdev); |
217 | struct input_dev *input = msc->input; | 249 | struct input_dev *input = msc->input; |
218 | int x, y, ts, ii, clicks; | 250 | int x, y, ts, ii, clicks, last_up; |
219 | 251 | ||
220 | switch (data[0]) { | 252 | switch (data[0]) { |
221 | case 0x10: | 253 | case 0x10: |
@@ -235,12 +267,26 @@ static int magicmouse_raw_event(struct hid_device *hdev, | |||
235 | msc->ntouches = (size - 6) / 8; | 267 | msc->ntouches = (size - 6) / 8; |
236 | for (ii = 0; ii < msc->ntouches; ii++) | 268 | for (ii = 0; ii < msc->ntouches; ii++) |
237 | magicmouse_emit_touch(msc, ii, data + ii * 8 + 6); | 269 | magicmouse_emit_touch(msc, ii, data + ii * 8 + 6); |
270 | |||
271 | if (report_touches) { | ||
272 | last_up = 1; | ||
273 | for (ii = 0; ii < ARRAY_SIZE(msc->touches); ii++) { | ||
274 | if (msc->touches[ii].down) { | ||
275 | last_up = 0; | ||
276 | msc->touches[ii].down = 0; | ||
277 | } | ||
278 | } | ||
279 | if (last_up) { | ||
280 | input_mt_sync(input); | ||
281 | } | ||
282 | } | ||
283 | |||
238 | /* When emulating three-button mode, it is important | 284 | /* When emulating three-button mode, it is important |
239 | * to have the current touch information before | 285 | * to have the current touch information before |
240 | * generating a click event. | 286 | * generating a click event. |
241 | */ | 287 | */ |
242 | x = (signed char)data[1]; | 288 | x = (int)(((data[3] & 0x0c) << 28) | (data[1] << 22)) >> 22; |
243 | y = (signed char)data[2]; | 289 | y = (int)(((data[3] & 0x30) << 26) | (data[2] << 22)) >> 22; |
244 | clicks = data[3]; | 290 | clicks = data[3]; |
245 | break; | 291 | break; |
246 | case 0x20: /* Theoretically battery status (0-100), but I have | 292 | case 0x20: /* Theoretically battery status (0-100), but I have |
@@ -301,8 +347,10 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h | |||
301 | __set_bit(EV_REL, input->evbit); | 347 | __set_bit(EV_REL, input->evbit); |
302 | __set_bit(REL_X, input->relbit); | 348 | __set_bit(REL_X, input->relbit); |
303 | __set_bit(REL_Y, input->relbit); | 349 | __set_bit(REL_Y, input->relbit); |
304 | if (emulate_scroll_wheel) | 350 | if (emulate_scroll_wheel) { |
305 | __set_bit(REL_WHEEL, input->relbit); | 351 | __set_bit(REL_WHEEL, input->relbit); |
352 | __set_bit(REL_HWHEEL, input->relbit); | ||
353 | } | ||
306 | 354 | ||
307 | if (report_touches) { | 355 | if (report_touches) { |
308 | __set_bit(EV_ABS, input->evbit); | 356 | __set_bit(EV_ABS, input->evbit); |
@@ -345,6 +393,8 @@ static int magicmouse_probe(struct hid_device *hdev, | |||
345 | return -ENOMEM; | 393 | return -ENOMEM; |
346 | } | 394 | } |
347 | 395 | ||
396 | msc->scroll_accel = SCROLL_ACCEL_DEFAULT; | ||
397 | |||
348 | msc->quirks = id->driver_data; | 398 | msc->quirks = id->driver_data; |
349 | hid_set_drvdata(hdev, msc); | 399 | hid_set_drvdata(hdev, msc); |
350 | 400 | ||
diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c index 7aabf65c48ef..346f0e34987e 100644 --- a/drivers/hid/hid-picolcd.c +++ b/drivers/hid/hid-picolcd.c | |||
@@ -127,6 +127,26 @@ static const struct fb_var_screeninfo picolcdfb_var = { | |||
127 | .height = 26, | 127 | .height = 26, |
128 | .bits_per_pixel = 1, | 128 | .bits_per_pixel = 1, |
129 | .grayscale = 1, | 129 | .grayscale = 1, |
130 | .red = { | ||
131 | .offset = 0, | ||
132 | .length = 1, | ||
133 | .msb_right = 0, | ||
134 | }, | ||
135 | .green = { | ||
136 | .offset = 0, | ||
137 | .length = 1, | ||
138 | .msb_right = 0, | ||
139 | }, | ||
140 | .blue = { | ||
141 | .offset = 0, | ||
142 | .length = 1, | ||
143 | .msb_right = 0, | ||
144 | }, | ||
145 | .transp = { | ||
146 | .offset = 0, | ||
147 | .length = 0, | ||
148 | .msb_right = 0, | ||
149 | }, | ||
130 | }; | 150 | }; |
131 | #endif /* CONFIG_HID_PICOLCD_FB */ | 151 | #endif /* CONFIG_HID_PICOLCD_FB */ |
132 | 152 | ||
@@ -188,6 +208,7 @@ struct picolcd_data { | |||
188 | /* Framebuffer stuff */ | 208 | /* Framebuffer stuff */ |
189 | u8 fb_update_rate; | 209 | u8 fb_update_rate; |
190 | u8 fb_bpp; | 210 | u8 fb_bpp; |
211 | u8 fb_force; | ||
191 | u8 *fb_vbitmap; /* local copy of what was sent to PicoLCD */ | 212 | u8 *fb_vbitmap; /* local copy of what was sent to PicoLCD */ |
192 | u8 *fb_bitmap; /* framebuffer */ | 213 | u8 *fb_bitmap; /* framebuffer */ |
193 | struct fb_info *fb_info; | 214 | struct fb_info *fb_info; |
@@ -346,7 +367,7 @@ static int picolcd_fb_update_tile(u8 *vbitmap, const u8 *bitmap, int bpp, | |||
346 | const u8 *bdata = bitmap + tile * 256 + chip * 8 + b * 32; | 367 | const u8 *bdata = bitmap + tile * 256 + chip * 8 + b * 32; |
347 | for (i = 0; i < 64; i++) { | 368 | for (i = 0; i < 64; i++) { |
348 | tdata[i] <<= 1; | 369 | tdata[i] <<= 1; |
349 | tdata[i] |= (bdata[i/8] >> (7 - i % 8)) & 0x01; | 370 | tdata[i] |= (bdata[i/8] >> (i % 8)) & 0x01; |
350 | } | 371 | } |
351 | } | 372 | } |
352 | } else if (bpp == 8) { | 373 | } else if (bpp == 8) { |
@@ -399,13 +420,10 @@ static int picolcd_fb_reset(struct picolcd_data *data, int clear) | |||
399 | 420 | ||
400 | if (data->fb_bitmap) { | 421 | if (data->fb_bitmap) { |
401 | if (clear) { | 422 | if (clear) { |
402 | memset(data->fb_vbitmap, 0xff, PICOLCDFB_SIZE); | 423 | memset(data->fb_vbitmap, 0, PICOLCDFB_SIZE); |
403 | memset(data->fb_bitmap, 0, PICOLCDFB_SIZE*data->fb_bpp); | 424 | memset(data->fb_bitmap, 0, PICOLCDFB_SIZE*data->fb_bpp); |
404 | } else { | ||
405 | /* invert 1 byte in each tile to force resend */ | ||
406 | for (i = 0; i < PICOLCDFB_SIZE; i += 64) | ||
407 | data->fb_vbitmap[i] = ~data->fb_vbitmap[i]; | ||
408 | } | 425 | } |
426 | data->fb_force = 1; | ||
409 | } | 427 | } |
410 | 428 | ||
411 | /* schedule first output of framebuffer */ | 429 | /* schedule first output of framebuffer */ |
@@ -421,6 +439,9 @@ static void picolcd_fb_update(struct picolcd_data *data) | |||
421 | int chip, tile, n; | 439 | int chip, tile, n; |
422 | unsigned long flags; | 440 | unsigned long flags; |
423 | 441 | ||
442 | if (!data) | ||
443 | return; | ||
444 | |||
424 | spin_lock_irqsave(&data->lock, flags); | 445 | spin_lock_irqsave(&data->lock, flags); |
425 | if (!(data->status & PICOLCD_READY_FB)) { | 446 | if (!(data->status & PICOLCD_READY_FB)) { |
426 | spin_unlock_irqrestore(&data->lock, flags); | 447 | spin_unlock_irqrestore(&data->lock, flags); |
@@ -440,14 +461,18 @@ static void picolcd_fb_update(struct picolcd_data *data) | |||
440 | for (chip = 0; chip < 4; chip++) | 461 | for (chip = 0; chip < 4; chip++) |
441 | for (tile = 0; tile < 8; tile++) | 462 | for (tile = 0; tile < 8; tile++) |
442 | if (picolcd_fb_update_tile(data->fb_vbitmap, | 463 | if (picolcd_fb_update_tile(data->fb_vbitmap, |
443 | data->fb_bitmap, data->fb_bpp, chip, tile)) { | 464 | data->fb_bitmap, data->fb_bpp, chip, tile) || |
465 | data->fb_force) { | ||
444 | n += 2; | 466 | n += 2; |
467 | if (!data->fb_info->par) | ||
468 | return; /* device lost! */ | ||
445 | if (n >= HID_OUTPUT_FIFO_SIZE / 2) { | 469 | if (n >= HID_OUTPUT_FIFO_SIZE / 2) { |
446 | usbhid_wait_io(data->hdev); | 470 | usbhid_wait_io(data->hdev); |
447 | n = 0; | 471 | n = 0; |
448 | } | 472 | } |
449 | picolcd_fb_send_tile(data->hdev, chip, tile); | 473 | picolcd_fb_send_tile(data->hdev, chip, tile); |
450 | } | 474 | } |
475 | data->fb_force = false; | ||
451 | if (n) | 476 | if (n) |
452 | usbhid_wait_io(data->hdev); | 477 | usbhid_wait_io(data->hdev); |
453 | } | 478 | } |
@@ -511,11 +536,23 @@ static int picolcd_fb_blank(int blank, struct fb_info *info) | |||
511 | static void picolcd_fb_destroy(struct fb_info *info) | 536 | static void picolcd_fb_destroy(struct fb_info *info) |
512 | { | 537 | { |
513 | struct picolcd_data *data = info->par; | 538 | struct picolcd_data *data = info->par; |
539 | u32 *ref_cnt = info->pseudo_palette; | ||
540 | int may_release; | ||
541 | |||
514 | info->par = NULL; | 542 | info->par = NULL; |
515 | if (data) | 543 | if (data) |
516 | data->fb_info = NULL; | 544 | data->fb_info = NULL; |
517 | fb_deferred_io_cleanup(info); | 545 | fb_deferred_io_cleanup(info); |
518 | framebuffer_release(info); | 546 | |
547 | ref_cnt--; | ||
548 | mutex_lock(&info->lock); | ||
549 | (*ref_cnt)--; | ||
550 | may_release = !ref_cnt; | ||
551 | mutex_unlock(&info->lock); | ||
552 | if (may_release) { | ||
553 | framebuffer_release(info); | ||
554 | vfree((u8 *)info->fix.smem_start); | ||
555 | } | ||
519 | } | 556 | } |
520 | 557 | ||
521 | static int picolcd_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | 558 | static int picolcd_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) |
@@ -526,29 +563,37 @@ static int picolcd_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *i | |||
526 | /* only allow 1/8 bit depth (8-bit is grayscale) */ | 563 | /* only allow 1/8 bit depth (8-bit is grayscale) */ |
527 | *var = picolcdfb_var; | 564 | *var = picolcdfb_var; |
528 | var->activate = activate; | 565 | var->activate = activate; |
529 | if (bpp >= 8) | 566 | if (bpp >= 8) { |
530 | var->bits_per_pixel = 8; | 567 | var->bits_per_pixel = 8; |
531 | else | 568 | var->red.length = 8; |
569 | var->green.length = 8; | ||
570 | var->blue.length = 8; | ||
571 | } else { | ||
532 | var->bits_per_pixel = 1; | 572 | var->bits_per_pixel = 1; |
573 | var->red.length = 1; | ||
574 | var->green.length = 1; | ||
575 | var->blue.length = 1; | ||
576 | } | ||
533 | return 0; | 577 | return 0; |
534 | } | 578 | } |
535 | 579 | ||
536 | static int picolcd_set_par(struct fb_info *info) | 580 | static int picolcd_set_par(struct fb_info *info) |
537 | { | 581 | { |
538 | struct picolcd_data *data = info->par; | 582 | struct picolcd_data *data = info->par; |
539 | u8 *o_fb, *n_fb; | 583 | u8 *tmp_fb, *o_fb; |
584 | if (!data) | ||
585 | return -ENODEV; | ||
540 | if (info->var.bits_per_pixel == data->fb_bpp) | 586 | if (info->var.bits_per_pixel == data->fb_bpp) |
541 | return 0; | 587 | return 0; |
542 | /* switch between 1/8 bit depths */ | 588 | /* switch between 1/8 bit depths */ |
543 | if (info->var.bits_per_pixel != 1 && info->var.bits_per_pixel != 8) | 589 | if (info->var.bits_per_pixel != 1 && info->var.bits_per_pixel != 8) |
544 | return -EINVAL; | 590 | return -EINVAL; |
545 | 591 | ||
546 | o_fb = data->fb_bitmap; | 592 | o_fb = data->fb_bitmap; |
547 | n_fb = vmalloc(PICOLCDFB_SIZE*info->var.bits_per_pixel); | 593 | tmp_fb = kmalloc(PICOLCDFB_SIZE*info->var.bits_per_pixel, GFP_KERNEL); |
548 | if (!n_fb) | 594 | if (!tmp_fb) |
549 | return -ENOMEM; | 595 | return -ENOMEM; |
550 | 596 | ||
551 | fb_deferred_io_cleanup(info); | ||
552 | /* translate FB content to new bits-per-pixel */ | 597 | /* translate FB content to new bits-per-pixel */ |
553 | if (info->var.bits_per_pixel == 1) { | 598 | if (info->var.bits_per_pixel == 1) { |
554 | int i, b; | 599 | int i, b; |
@@ -558,24 +603,87 @@ static int picolcd_set_par(struct fb_info *info) | |||
558 | p <<= 1; | 603 | p <<= 1; |
559 | p |= o_fb[i*8+b] ? 0x01 : 0x00; | 604 | p |= o_fb[i*8+b] ? 0x01 : 0x00; |
560 | } | 605 | } |
606 | tmp_fb[i] = p; | ||
561 | } | 607 | } |
608 | memcpy(o_fb, tmp_fb, PICOLCDFB_SIZE); | ||
562 | info->fix.visual = FB_VISUAL_MONO01; | 609 | info->fix.visual = FB_VISUAL_MONO01; |
563 | info->fix.line_length = PICOLCDFB_WIDTH / 8; | 610 | info->fix.line_length = PICOLCDFB_WIDTH / 8; |
564 | } else { | 611 | } else { |
565 | int i; | 612 | int i; |
613 | memcpy(tmp_fb, o_fb, PICOLCDFB_SIZE); | ||
566 | for (i = 0; i < PICOLCDFB_SIZE * 8; i++) | 614 | for (i = 0; i < PICOLCDFB_SIZE * 8; i++) |
567 | n_fb[i] = o_fb[i/8] & (0x01 << (7 - i % 8)) ? 0xff : 0x00; | 615 | o_fb[i] = tmp_fb[i/8] & (0x01 << (7 - i % 8)) ? 0xff : 0x00; |
568 | info->fix.visual = FB_VISUAL_TRUECOLOR; | 616 | info->fix.visual = FB_VISUAL_DIRECTCOLOR; |
569 | info->fix.line_length = PICOLCDFB_WIDTH; | 617 | info->fix.line_length = PICOLCDFB_WIDTH; |
570 | } | 618 | } |
571 | 619 | ||
572 | data->fb_bitmap = n_fb; | 620 | kfree(tmp_fb); |
573 | data->fb_bpp = info->var.bits_per_pixel; | 621 | data->fb_bpp = info->var.bits_per_pixel; |
574 | info->screen_base = (char __force __iomem *)n_fb; | 622 | return 0; |
575 | info->fix.smem_start = (unsigned long)n_fb; | 623 | } |
576 | info->fix.smem_len = PICOLCDFB_SIZE*data->fb_bpp; | 624 | |
577 | fb_deferred_io_init(info); | 625 | /* Do refcounting on our FB and cleanup per worker if FB is |
578 | vfree(o_fb); | 626 | * closed after unplug of our device |
627 | * (fb_release holds info->lock and still touches info after | ||
628 | * we return so we can't release it immediately. | ||
629 | */ | ||
630 | struct picolcd_fb_cleanup_item { | ||
631 | struct fb_info *info; | ||
632 | struct picolcd_fb_cleanup_item *next; | ||
633 | }; | ||
634 | static struct picolcd_fb_cleanup_item *fb_pending; | ||
635 | DEFINE_SPINLOCK(fb_pending_lock); | ||
636 | |||
637 | static void picolcd_fb_do_cleanup(struct work_struct *data) | ||
638 | { | ||
639 | struct picolcd_fb_cleanup_item *item; | ||
640 | unsigned long flags; | ||
641 | |||
642 | do { | ||
643 | spin_lock_irqsave(&fb_pending_lock, flags); | ||
644 | item = fb_pending; | ||
645 | fb_pending = item ? item->next : NULL; | ||
646 | spin_unlock_irqrestore(&fb_pending_lock, flags); | ||
647 | |||
648 | if (item) { | ||
649 | u8 *fb = (u8 *)item->info->fix.smem_start; | ||
650 | /* make sure we do not race against fb core when | ||
651 | * releasing */ | ||
652 | mutex_lock(&item->info->lock); | ||
653 | mutex_unlock(&item->info->lock); | ||
654 | framebuffer_release(item->info); | ||
655 | vfree(fb); | ||
656 | } | ||
657 | } while (item); | ||
658 | } | ||
659 | |||
660 | DECLARE_WORK(picolcd_fb_cleanup, picolcd_fb_do_cleanup); | ||
661 | |||
662 | static int picolcd_fb_open(struct fb_info *info, int u) | ||
663 | { | ||
664 | u32 *ref_cnt = info->pseudo_palette; | ||
665 | ref_cnt--; | ||
666 | |||
667 | (*ref_cnt)++; | ||
668 | return 0; | ||
669 | } | ||
670 | |||
671 | static int picolcd_fb_release(struct fb_info *info, int u) | ||
672 | { | ||
673 | u32 *ref_cnt = info->pseudo_palette; | ||
674 | ref_cnt--; | ||
675 | |||
676 | (*ref_cnt)++; | ||
677 | if (!*ref_cnt) { | ||
678 | unsigned long flags; | ||
679 | struct picolcd_fb_cleanup_item *item = (struct picolcd_fb_cleanup_item *)ref_cnt; | ||
680 | item--; | ||
681 | spin_lock_irqsave(&fb_pending_lock, flags); | ||
682 | item->next = fb_pending; | ||
683 | fb_pending = item; | ||
684 | spin_unlock_irqrestore(&fb_pending_lock, flags); | ||
685 | schedule_work(&picolcd_fb_cleanup); | ||
686 | } | ||
579 | return 0; | 687 | return 0; |
580 | } | 688 | } |
581 | 689 | ||
@@ -583,6 +691,8 @@ static int picolcd_set_par(struct fb_info *info) | |||
583 | static struct fb_ops picolcdfb_ops = { | 691 | static struct fb_ops picolcdfb_ops = { |
584 | .owner = THIS_MODULE, | 692 | .owner = THIS_MODULE, |
585 | .fb_destroy = picolcd_fb_destroy, | 693 | .fb_destroy = picolcd_fb_destroy, |
694 | .fb_open = picolcd_fb_open, | ||
695 | .fb_release = picolcd_fb_release, | ||
586 | .fb_read = fb_sys_read, | 696 | .fb_read = fb_sys_read, |
587 | .fb_write = picolcd_fb_write, | 697 | .fb_write = picolcd_fb_write, |
588 | .fb_blank = picolcd_fb_blank, | 698 | .fb_blank = picolcd_fb_blank, |
@@ -660,11 +770,12 @@ static int picolcd_init_framebuffer(struct picolcd_data *data) | |||
660 | { | 770 | { |
661 | struct device *dev = &data->hdev->dev; | 771 | struct device *dev = &data->hdev->dev; |
662 | struct fb_info *info = NULL; | 772 | struct fb_info *info = NULL; |
663 | int error = -ENOMEM; | 773 | int i, error = -ENOMEM; |
664 | u8 *fb_vbitmap = NULL; | 774 | u8 *fb_vbitmap = NULL; |
665 | u8 *fb_bitmap = NULL; | 775 | u8 *fb_bitmap = NULL; |
776 | u32 *palette; | ||
666 | 777 | ||
667 | fb_bitmap = vmalloc(PICOLCDFB_SIZE*picolcdfb_var.bits_per_pixel); | 778 | fb_bitmap = vmalloc(PICOLCDFB_SIZE*8); |
668 | if (fb_bitmap == NULL) { | 779 | if (fb_bitmap == NULL) { |
669 | dev_err(dev, "can't get a free page for framebuffer\n"); | 780 | dev_err(dev, "can't get a free page for framebuffer\n"); |
670 | goto err_nomem; | 781 | goto err_nomem; |
@@ -678,18 +789,29 @@ static int picolcd_init_framebuffer(struct picolcd_data *data) | |||
678 | 789 | ||
679 | data->fb_update_rate = PICOLCDFB_UPDATE_RATE_DEFAULT; | 790 | data->fb_update_rate = PICOLCDFB_UPDATE_RATE_DEFAULT; |
680 | data->fb_defio = picolcd_fb_defio; | 791 | data->fb_defio = picolcd_fb_defio; |
681 | info = framebuffer_alloc(0, dev); | 792 | /* The extra memory is: |
793 | * - struct picolcd_fb_cleanup_item | ||
794 | * - u32 for ref_count | ||
795 | * - 256*u32 for pseudo_palette | ||
796 | */ | ||
797 | info = framebuffer_alloc(257 * sizeof(u32) + sizeof(struct picolcd_fb_cleanup_item), dev); | ||
682 | if (info == NULL) { | 798 | if (info == NULL) { |
683 | dev_err(dev, "failed to allocate a framebuffer\n"); | 799 | dev_err(dev, "failed to allocate a framebuffer\n"); |
684 | goto err_nomem; | 800 | goto err_nomem; |
685 | } | 801 | } |
686 | 802 | ||
803 | palette = info->par + sizeof(struct picolcd_fb_cleanup_item); | ||
804 | *palette = 1; | ||
805 | palette++; | ||
806 | for (i = 0; i < 256; i++) | ||
807 | palette[i] = i > 0 && i < 16 ? 0xff : 0; | ||
808 | info->pseudo_palette = palette; | ||
687 | info->fbdefio = &data->fb_defio; | 809 | info->fbdefio = &data->fb_defio; |
688 | info->screen_base = (char __force __iomem *)fb_bitmap; | 810 | info->screen_base = (char __force __iomem *)fb_bitmap; |
689 | info->fbops = &picolcdfb_ops; | 811 | info->fbops = &picolcdfb_ops; |
690 | info->var = picolcdfb_var; | 812 | info->var = picolcdfb_var; |
691 | info->fix = picolcdfb_fix; | 813 | info->fix = picolcdfb_fix; |
692 | info->fix.smem_len = PICOLCDFB_SIZE; | 814 | info->fix.smem_len = PICOLCDFB_SIZE*8; |
693 | info->fix.smem_start = (unsigned long)fb_bitmap; | 815 | info->fix.smem_start = (unsigned long)fb_bitmap; |
694 | info->par = data; | 816 | info->par = data; |
695 | info->flags = FBINFO_FLAG_DEFAULT; | 817 | info->flags = FBINFO_FLAG_DEFAULT; |
@@ -707,18 +829,20 @@ static int picolcd_init_framebuffer(struct picolcd_data *data) | |||
707 | dev_err(dev, "failed to create sysfs attributes\n"); | 829 | dev_err(dev, "failed to create sysfs attributes\n"); |
708 | goto err_cleanup; | 830 | goto err_cleanup; |
709 | } | 831 | } |
832 | fb_deferred_io_init(info); | ||
710 | data->fb_info = info; | 833 | data->fb_info = info; |
711 | error = register_framebuffer(info); | 834 | error = register_framebuffer(info); |
712 | if (error) { | 835 | if (error) { |
713 | dev_err(dev, "failed to register framebuffer\n"); | 836 | dev_err(dev, "failed to register framebuffer\n"); |
714 | goto err_sysfs; | 837 | goto err_sysfs; |
715 | } | 838 | } |
716 | fb_deferred_io_init(info); | ||
717 | /* schedule first output of framebuffer */ | 839 | /* schedule first output of framebuffer */ |
840 | data->fb_force = 1; | ||
718 | schedule_delayed_work(&info->deferred_work, 0); | 841 | schedule_delayed_work(&info->deferred_work, 0); |
719 | return 0; | 842 | return 0; |
720 | 843 | ||
721 | err_sysfs: | 844 | err_sysfs: |
845 | fb_deferred_io_cleanup(info); | ||
722 | device_remove_file(dev, &dev_attr_fb_update_rate); | 846 | device_remove_file(dev, &dev_attr_fb_update_rate); |
723 | err_cleanup: | 847 | err_cleanup: |
724 | data->fb_vbitmap = NULL; | 848 | data->fb_vbitmap = NULL; |
@@ -737,19 +861,17 @@ static void picolcd_exit_framebuffer(struct picolcd_data *data) | |||
737 | { | 861 | { |
738 | struct fb_info *info = data->fb_info; | 862 | struct fb_info *info = data->fb_info; |
739 | u8 *fb_vbitmap = data->fb_vbitmap; | 863 | u8 *fb_vbitmap = data->fb_vbitmap; |
740 | u8 *fb_bitmap = data->fb_bitmap; | ||
741 | 864 | ||
742 | if (!info) | 865 | if (!info) |
743 | return; | 866 | return; |
744 | 867 | ||
868 | info->par = NULL; | ||
869 | device_remove_file(&data->hdev->dev, &dev_attr_fb_update_rate); | ||
870 | unregister_framebuffer(info); | ||
745 | data->fb_vbitmap = NULL; | 871 | data->fb_vbitmap = NULL; |
746 | data->fb_bitmap = NULL; | 872 | data->fb_bitmap = NULL; |
747 | data->fb_bpp = 0; | 873 | data->fb_bpp = 0; |
748 | data->fb_info = NULL; | 874 | data->fb_info = NULL; |
749 | device_remove_file(&data->hdev->dev, &dev_attr_fb_update_rate); | ||
750 | fb_deferred_io_cleanup(info); | ||
751 | unregister_framebuffer(info); | ||
752 | vfree(fb_bitmap); | ||
753 | kfree(fb_vbitmap); | 875 | kfree(fb_vbitmap); |
754 | } | 876 | } |
755 | 877 | ||
@@ -2566,6 +2688,13 @@ static void picolcd_remove(struct hid_device *hdev) | |||
2566 | spin_lock_irqsave(&data->lock, flags); | 2688 | spin_lock_irqsave(&data->lock, flags); |
2567 | data->status |= PICOLCD_FAILED; | 2689 | data->status |= PICOLCD_FAILED; |
2568 | spin_unlock_irqrestore(&data->lock, flags); | 2690 | spin_unlock_irqrestore(&data->lock, flags); |
2691 | #ifdef CONFIG_HID_PICOLCD_FB | ||
2692 | /* short-circuit FB as early as possible in order to | ||
2693 | * avoid long delays if we host console. | ||
2694 | */ | ||
2695 | if (data->fb_info) | ||
2696 | data->fb_info->par = NULL; | ||
2697 | #endif | ||
2569 | 2698 | ||
2570 | picolcd_exit_devfs(data); | 2699 | picolcd_exit_devfs(data); |
2571 | device_remove_file(&hdev->dev, &dev_attr_operation_mode); | 2700 | device_remove_file(&hdev->dev, &dev_attr_operation_mode); |
@@ -2623,6 +2752,10 @@ static int __init picolcd_init(void) | |||
2623 | static void __exit picolcd_exit(void) | 2752 | static void __exit picolcd_exit(void) |
2624 | { | 2753 | { |
2625 | hid_unregister_driver(&picolcd_driver); | 2754 | hid_unregister_driver(&picolcd_driver); |
2755 | #ifdef CONFIG_HID_PICOLCD_FB | ||
2756 | flush_scheduled_work(); | ||
2757 | WARN_ON(fb_pending); | ||
2758 | #endif | ||
2626 | } | 2759 | } |
2627 | 2760 | ||
2628 | module_init(picolcd_init); | 2761 | module_init(picolcd_init); |
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index 17f2dc04f883..f77695762cb5 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c | |||
@@ -22,11 +22,6 @@ | |||
22 | * Is it possible to remove and reinstall the urb in raw-event- or any | 22 | * Is it possible to remove and reinstall the urb in raw-event- or any |
23 | * other handler, or to defer this action to be executed somewhere else? | 23 | * other handler, or to defer this action to be executed somewhere else? |
24 | * | 24 | * |
25 | * TODO implement notification mechanism for overlong macro execution | ||
26 | * If user wants to execute an overlong macro only the names of macroset | ||
27 | * and macro are given. Should userland tap hidraw or is there an | ||
28 | * additional streaming mechanism? | ||
29 | * | ||
30 | * TODO is it possible to overwrite group for sysfs attributes via udev? | 25 | * TODO is it possible to overwrite group for sysfs attributes via udev? |
31 | */ | 26 | */ |
32 | 27 | ||
@@ -277,7 +272,7 @@ static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj, | |||
277 | count = sizeof(struct kone_settings) - off; | 272 | count = sizeof(struct kone_settings) - off; |
278 | 273 | ||
279 | mutex_lock(&kone->kone_lock); | 274 | mutex_lock(&kone->kone_lock); |
280 | memcpy(buf, &kone->settings + off, count); | 275 | memcpy(buf, ((char const *)&kone->settings) + off, count); |
281 | mutex_unlock(&kone->kone_lock); | 276 | mutex_unlock(&kone->kone_lock); |
282 | 277 | ||
283 | return count; | 278 | return count; |
@@ -337,7 +332,7 @@ static ssize_t kone_sysfs_read_profilex(struct kobject *kobj, | |||
337 | count = sizeof(struct kone_profile) - off; | 332 | count = sizeof(struct kone_profile) - off; |
338 | 333 | ||
339 | mutex_lock(&kone->kone_lock); | 334 | mutex_lock(&kone->kone_lock); |
340 | memcpy(buf, &kone->profiles[number - 1], sizeof(struct kone_profile)); | 335 | memcpy(buf, ((char const *)&kone->profiles[number - 1]) + off, count); |
341 | mutex_unlock(&kone->kone_lock); | 336 | mutex_unlock(&kone->kone_lock); |
342 | 337 | ||
343 | return count; | 338 | return count; |
@@ -623,18 +618,6 @@ static ssize_t kone_sysfs_set_startup_profile(struct device *dev, | |||
623 | } | 618 | } |
624 | 619 | ||
625 | /* | 620 | /* |
626 | * This file is used by userland software to find devices that are handled by | ||
627 | * this driver. This provides a consistent way for actual and older kernels | ||
628 | * where this driver replaced usbhid instead of generic-usb. | ||
629 | * Driver capabilities are determined by version number. | ||
630 | */ | ||
631 | static ssize_t kone_sysfs_show_driver_version(struct device *dev, | ||
632 | struct device_attribute *attr, char *buf) | ||
633 | { | ||
634 | return snprintf(buf, PAGE_SIZE, ROCCAT_KONE_DRIVER_VERSION "\n"); | ||
635 | } | ||
636 | |||
637 | /* | ||
638 | * Read actual dpi settings. | 621 | * Read actual dpi settings. |
639 | * Returns raw value for further processing. Refer to enum kone_polling_rates to | 622 | * Returns raw value for further processing. Refer to enum kone_polling_rates to |
640 | * get real value. | 623 | * get real value. |
@@ -671,9 +654,6 @@ static DEVICE_ATTR(startup_profile, 0660, | |||
671 | kone_sysfs_show_startup_profile, | 654 | kone_sysfs_show_startup_profile, |
672 | kone_sysfs_set_startup_profile); | 655 | kone_sysfs_set_startup_profile); |
673 | 656 | ||
674 | static DEVICE_ATTR(kone_driver_version, 0440, | ||
675 | kone_sysfs_show_driver_version, NULL); | ||
676 | |||
677 | static struct attribute *kone_attributes[] = { | 657 | static struct attribute *kone_attributes[] = { |
678 | &dev_attr_actual_dpi.attr, | 658 | &dev_attr_actual_dpi.attr, |
679 | &dev_attr_actual_profile.attr, | 659 | &dev_attr_actual_profile.attr, |
@@ -681,7 +661,6 @@ static struct attribute *kone_attributes[] = { | |||
681 | &dev_attr_firmware_version.attr, | 661 | &dev_attr_firmware_version.attr, |
682 | &dev_attr_tcu.attr, | 662 | &dev_attr_tcu.attr, |
683 | &dev_attr_startup_profile.attr, | 663 | &dev_attr_startup_profile.attr, |
684 | &dev_attr_kone_driver_version.attr, | ||
685 | NULL | 664 | NULL |
686 | }; | 665 | }; |
687 | 666 | ||
diff --git a/drivers/hid/hid-roccat-kone.h b/drivers/hid/hid-roccat-kone.h index 003e6f81c195..130d6566ea82 100644 --- a/drivers/hid/hid-roccat-kone.h +++ b/drivers/hid/hid-roccat-kone.h | |||
@@ -14,8 +14,6 @@ | |||
14 | 14 | ||
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
16 | 16 | ||
17 | #define ROCCAT_KONE_DRIVER_VERSION "v0.3.1" | ||
18 | |||
19 | #pragma pack(push) | 17 | #pragma pack(push) |
20 | #pragma pack(1) | 18 | #pragma pack(1) |
21 | 19 | ||
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c index e05d48edb66f..f6e80c7ca61e 100644 --- a/drivers/hid/hid-roccat.c +++ b/drivers/hid/hid-roccat.c | |||
@@ -168,7 +168,7 @@ static int roccat_open(struct inode *inode, struct file *file) | |||
168 | printk(KERN_EMERG "roccat device with minor %d doesn't exist\n", | 168 | printk(KERN_EMERG "roccat device with minor %d doesn't exist\n", |
169 | minor); | 169 | minor); |
170 | error = -ENODEV; | 170 | error = -ENODEV; |
171 | goto exit_unlock; | 171 | goto exit_err; |
172 | } | 172 | } |
173 | 173 | ||
174 | if (!device->open++) { | 174 | if (!device->open++) { |
@@ -178,7 +178,7 @@ static int roccat_open(struct inode *inode, struct file *file) | |||
178 | PM_HINT_FULLON); | 178 | PM_HINT_FULLON); |
179 | if (error < 0) { | 179 | if (error < 0) { |
180 | --device->open; | 180 | --device->open; |
181 | goto exit_unlock; | 181 | goto exit_err; |
182 | } | 182 | } |
183 | } | 183 | } |
184 | error = device->hid->ll_driver->open(device->hid); | 184 | error = device->hid->ll_driver->open(device->hid); |
@@ -187,7 +187,7 @@ static int roccat_open(struct inode *inode, struct file *file) | |||
187 | device->hid->ll_driver->power(device->hid, | 187 | device->hid->ll_driver->power(device->hid, |
188 | PM_HINT_NORMAL); | 188 | PM_HINT_NORMAL); |
189 | --device->open; | 189 | --device->open; |
190 | goto exit_unlock; | 190 | goto exit_err; |
191 | } | 191 | } |
192 | } | 192 | } |
193 | 193 | ||
@@ -202,6 +202,9 @@ exit_unlock: | |||
202 | mutex_unlock(&device->readers_lock); | 202 | mutex_unlock(&device->readers_lock); |
203 | mutex_unlock(&devices_lock); | 203 | mutex_unlock(&devices_lock); |
204 | return error; | 204 | return error; |
205 | exit_err: | ||
206 | kfree(reader); | ||
207 | goto exit_unlock; | ||
205 | } | 208 | } |
206 | 209 | ||
207 | static int roccat_release(struct inode *inode, struct file *file) | 210 | static int roccat_release(struct inode *inode, struct file *file) |
diff --git a/drivers/hid/hid-roccat.h b/drivers/hid/hid-roccat.h index d8aae0c1fa7e..09e864e9f79d 100644 --- a/drivers/hid/hid-roccat.h +++ b/drivers/hid/hid-roccat.h | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/hid.h> | 15 | #include <linux/hid.h> |
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | 17 | ||
18 | #if defined(CONFIG_HID_ROCCAT) || defined (CONFIG_HID_ROCCAT_MODULE) | 18 | #if defined(CONFIG_HID_ROCCAT) || defined(CONFIG_HID_ROCCAT_MODULE) |
19 | int roccat_connect(struct hid_device *hid); | 19 | int roccat_connect(struct hid_device *hid); |
20 | void roccat_disconnect(int minor); | 20 | void roccat_disconnect(int minor); |
21 | int roccat_report_event(int minor, u8 const *data, int len); | 21 | int roccat_report_event(int minor, u8 const *data, int len); |
diff --git a/drivers/hid/hid-topseed.c b/drivers/hid/hid-topseed.c index 2eebdcc57bcf..5771f851f856 100644 --- a/drivers/hid/hid-topseed.c +++ b/drivers/hid/hid-topseed.c | |||
@@ -6,6 +6,9 @@ | |||
6 | * | 6 | * |
7 | * Modified to also support BTC "Emprex 3009URF III Vista MCE Remote" by | 7 | * Modified to also support BTC "Emprex 3009URF III Vista MCE Remote" by |
8 | * Wayne Thomas 2010. | 8 | * Wayne Thomas 2010. |
9 | * | ||
10 | * Modified to support Conceptronic CLLRCMCE by | ||
11 | * Kees Bakker 2010. | ||
9 | */ | 12 | */ |
10 | 13 | ||
11 | /* | 14 | /* |
@@ -34,6 +37,7 @@ static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
34 | case 0x00d: ts_map_key_clear(KEY_MEDIA); break; | 37 | case 0x00d: ts_map_key_clear(KEY_MEDIA); break; |
35 | case 0x024: ts_map_key_clear(KEY_MENU); break; | 38 | case 0x024: ts_map_key_clear(KEY_MENU); break; |
36 | case 0x025: ts_map_key_clear(KEY_TV); break; | 39 | case 0x025: ts_map_key_clear(KEY_TV); break; |
40 | case 0x027: ts_map_key_clear(KEY_MODE); break; | ||
37 | case 0x031: ts_map_key_clear(KEY_AUDIO); break; | 41 | case 0x031: ts_map_key_clear(KEY_AUDIO); break; |
38 | case 0x032: ts_map_key_clear(KEY_TEXT); break; | 42 | case 0x032: ts_map_key_clear(KEY_TEXT); break; |
39 | case 0x033: ts_map_key_clear(KEY_CHANNEL); break; | 43 | case 0x033: ts_map_key_clear(KEY_CHANNEL); break; |
@@ -60,6 +64,7 @@ static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
60 | static const struct hid_device_id ts_devices[] = { | 64 | static const struct hid_device_id ts_devices[] = { |
61 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, | 65 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, |
62 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, | 66 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, |
67 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, | ||
63 | { } | 68 | { } |
64 | }; | 69 | }; |
65 | MODULE_DEVICE_TABLE(hid, ts_devices); | 70 | MODULE_DEVICE_TABLE(hid, ts_devices); |
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 1e051f1171e4..807dcd1555a6 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c | |||
@@ -436,7 +436,7 @@ static void wacom_remove(struct hid_device *hdev) | |||
436 | 436 | ||
437 | static const struct hid_device_id wacom_devices[] = { | 437 | static const struct hid_device_id wacom_devices[] = { |
438 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, | 438 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, |
439 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) }, | 439 | |
440 | { } | 440 | { } |
441 | }; | 441 | }; |
442 | MODULE_DEVICE_TABLE(hid, wacom_devices); | 442 | MODULE_DEVICE_TABLE(hid, wacom_devices); |
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 3ccd47850677..47d70c523d93 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
@@ -46,7 +46,6 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, | |||
46 | { | 46 | { |
47 | struct hidraw_list *list = file->private_data; | 47 | struct hidraw_list *list = file->private_data; |
48 | int ret = 0, len; | 48 | int ret = 0, len; |
49 | char *report; | ||
50 | DECLARE_WAITQUEUE(wait, current); | 49 | DECLARE_WAITQUEUE(wait, current); |
51 | 50 | ||
52 | mutex_lock(&list->read_mutex); | 51 | mutex_lock(&list->read_mutex); |
@@ -84,7 +83,6 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, | |||
84 | if (ret) | 83 | if (ret) |
85 | goto out; | 84 | goto out; |
86 | 85 | ||
87 | report = list->buffer[list->tail].value; | ||
88 | len = list->buffer[list->tail].len > count ? | 86 | len = list->buffer[list->tail].len > count ? |
89 | count : list->buffer[list->tail].len; | 87 | count : list->buffer[list->tail].len; |
90 | 88 | ||
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 5f5aa39b3988..2643d3147621 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -75,6 +75,8 @@ static const struct hid_blacklist { | |||
75 | { USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | 75 | { USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, |
76 | { USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | 76 | { USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, |
77 | 77 | ||
78 | { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE }, | ||
79 | |||
78 | { 0, 0 } | 80 | { 0, 0 } |
79 | }; | 81 | }; |
80 | 82 | ||
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index c24d2fa3e3b6..254a003af048 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c | |||
@@ -67,7 +67,7 @@ struct hiddev_list { | |||
67 | struct mutex thread_lock; | 67 | struct mutex thread_lock; |
68 | }; | 68 | }; |
69 | 69 | ||
70 | static struct hiddev *hiddev_table[HIDDEV_MINORS]; | 70 | static struct usb_driver hiddev_driver; |
71 | 71 | ||
72 | /* | 72 | /* |
73 | * Find a report, given the report's type and ID. The ID can be specified | 73 | * Find a report, given the report's type and ID. The ID can be specified |
@@ -265,22 +265,19 @@ static int hiddev_release(struct inode * inode, struct file * file) | |||
265 | static int hiddev_open(struct inode *inode, struct file *file) | 265 | static int hiddev_open(struct inode *inode, struct file *file) |
266 | { | 266 | { |
267 | struct hiddev_list *list; | 267 | struct hiddev_list *list; |
268 | int res, i; | 268 | struct usb_interface *intf; |
269 | 269 | struct hiddev *hiddev; | |
270 | /* See comment in hiddev_connect() for BKL explanation */ | 270 | int res; |
271 | lock_kernel(); | ||
272 | i = iminor(inode) - HIDDEV_MINOR_BASE; | ||
273 | 271 | ||
274 | if (i >= HIDDEV_MINORS || i < 0 || !hiddev_table[i]) | 272 | intf = usb_find_interface(&hiddev_driver, iminor(inode)); |
273 | if (!intf) | ||
275 | return -ENODEV; | 274 | return -ENODEV; |
275 | hiddev = usb_get_intfdata(intf); | ||
276 | 276 | ||
277 | if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL))) | 277 | if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL))) |
278 | return -ENOMEM; | 278 | return -ENOMEM; |
279 | mutex_init(&list->thread_lock); | 279 | mutex_init(&list->thread_lock); |
280 | 280 | list->hiddev = hiddev; | |
281 | list->hiddev = hiddev_table[i]; | ||
282 | |||
283 | |||
284 | file->private_data = list; | 281 | file->private_data = list; |
285 | 282 | ||
286 | /* | 283 | /* |
@@ -289,7 +286,7 @@ static int hiddev_open(struct inode *inode, struct file *file) | |||
289 | */ | 286 | */ |
290 | if (list->hiddev->exist) { | 287 | if (list->hiddev->exist) { |
291 | if (!list->hiddev->open++) { | 288 | if (!list->hiddev->open++) { |
292 | res = usbhid_open(hiddev_table[i]->hid); | 289 | res = usbhid_open(hiddev->hid); |
293 | if (res < 0) { | 290 | if (res < 0) { |
294 | res = -EIO; | 291 | res = -EIO; |
295 | goto bail; | 292 | goto bail; |
@@ -301,12 +298,12 @@ static int hiddev_open(struct inode *inode, struct file *file) | |||
301 | } | 298 | } |
302 | 299 | ||
303 | spin_lock_irq(&list->hiddev->list_lock); | 300 | spin_lock_irq(&list->hiddev->list_lock); |
304 | list_add_tail(&list->node, &hiddev_table[i]->list); | 301 | list_add_tail(&list->node, &hiddev->list); |
305 | spin_unlock_irq(&list->hiddev->list_lock); | 302 | spin_unlock_irq(&list->hiddev->list_lock); |
306 | 303 | ||
307 | if (!list->hiddev->open++) | 304 | if (!list->hiddev->open++) |
308 | if (list->hiddev->exist) { | 305 | if (list->hiddev->exist) { |
309 | struct hid_device *hid = hiddev_table[i]->hid; | 306 | struct hid_device *hid = hiddev->hid; |
310 | res = usbhid_get_power(hid); | 307 | res = usbhid_get_power(hid); |
311 | if (res < 0) { | 308 | if (res < 0) { |
312 | res = -EIO; | 309 | res = -EIO; |
@@ -314,13 +311,10 @@ static int hiddev_open(struct inode *inode, struct file *file) | |||
314 | } | 311 | } |
315 | usbhid_open(hid); | 312 | usbhid_open(hid); |
316 | } | 313 | } |
317 | |||
318 | unlock_kernel(); | ||
319 | return 0; | 314 | return 0; |
320 | bail: | 315 | bail: |
321 | file->private_data = NULL; | 316 | file->private_data = NULL; |
322 | kfree(list); | 317 | kfree(list); |
323 | unlock_kernel(); | ||
324 | return res; | 318 | return res; |
325 | } | 319 | } |
326 | 320 | ||
@@ -894,37 +888,14 @@ int hiddev_connect(struct hid_device *hid, unsigned int force) | |||
894 | hid->hiddev = hiddev; | 888 | hid->hiddev = hiddev; |
895 | hiddev->hid = hid; | 889 | hiddev->hid = hid; |
896 | hiddev->exist = 1; | 890 | hiddev->exist = 1; |
897 | 891 | usb_set_intfdata(usbhid->intf, usbhid); | |
898 | /* | ||
899 | * BKL here is used to avoid race after usb_register_dev(). | ||
900 | * Once the device node has been created, open() could happen on it. | ||
901 | * The code below will then fail, as hiddev_table hasn't been | ||
902 | * updated. | ||
903 | * | ||
904 | * The obvious fix -- introducing mutex to guard hiddev_table[] | ||
905 | * doesn't work, as usb_open() and usb_register_dev() both take | ||
906 | * minor_rwsem, thus we'll have ABBA deadlock. | ||
907 | * | ||
908 | * Before BKL pushdown, usb_open() had been acquiring it in right | ||
909 | * order, so _open() was safe to use it to protect from this race. | ||
910 | * Now the order is different, but AB-BA deadlock still doesn't occur | ||
911 | * as BKL is dropped on schedule() (i.e. while sleeping on | ||
912 | * minor_rwsem). Fugly. | ||
913 | */ | ||
914 | lock_kernel(); | ||
915 | retval = usb_register_dev(usbhid->intf, &hiddev_class); | 892 | retval = usb_register_dev(usbhid->intf, &hiddev_class); |
916 | if (retval) { | 893 | if (retval) { |
917 | err_hid("Not able to get a minor for this device."); | 894 | err_hid("Not able to get a minor for this device."); |
918 | hid->hiddev = NULL; | 895 | hid->hiddev = NULL; |
919 | unlock_kernel(); | ||
920 | kfree(hiddev); | 896 | kfree(hiddev); |
921 | return -1; | 897 | return -1; |
922 | } else { | ||
923 | hid->minor = usbhid->intf->minor; | ||
924 | hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; | ||
925 | } | 898 | } |
926 | unlock_kernel(); | ||
927 | |||
928 | return 0; | 899 | return 0; |
929 | } | 900 | } |
930 | 901 | ||
@@ -942,7 +913,6 @@ void hiddev_disconnect(struct hid_device *hid) | |||
942 | hiddev->exist = 0; | 913 | hiddev->exist = 0; |
943 | mutex_unlock(&hiddev->existancelock); | 914 | mutex_unlock(&hiddev->existancelock); |
944 | 915 | ||
945 | hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL; | ||
946 | usb_deregister_dev(usbhid->intf, &hiddev_class); | 916 | usb_deregister_dev(usbhid->intf, &hiddev_class); |
947 | 917 | ||
948 | if (hiddev->open) { | 918 | if (hiddev->open) { |