diff options
Diffstat (limited to 'drivers/hid')
39 files changed, 3053 insertions, 346 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 306b15f39c9c..22a4a051f221 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -69,7 +69,7 @@ config HID_ACRUX | |||
69 | Say Y here if you want to enable support for ACRUX game controllers. | 69 | Say Y here if you want to enable support for ACRUX game controllers. |
70 | 70 | ||
71 | config HID_ACRUX_FF | 71 | config HID_ACRUX_FF |
72 | tristate "ACRUX force feedback support" | 72 | bool "ACRUX force feedback support" |
73 | depends on HID_ACRUX | 73 | depends on HID_ACRUX |
74 | select INPUT_FF_MEMLESS | 74 | select INPUT_FF_MEMLESS |
75 | ---help--- | 75 | ---help--- |
@@ -245,6 +245,15 @@ config HID_LOGITECH | |||
245 | ---help--- | 245 | ---help--- |
246 | Support for Logitech devices that are not fully compliant with HID standard. | 246 | Support for Logitech devices that are not fully compliant with HID standard. |
247 | 247 | ||
248 | config HID_LOGITECH_DJ | ||
249 | tristate "Logitech Unifying receivers full support" | ||
250 | depends on HID_LOGITECH | ||
251 | default m | ||
252 | ---help--- | ||
253 | Say Y if you want support for Logitech Unifying receivers and devices. | ||
254 | Unifying receivers are capable of pairing up to 6 Logitech compliant | ||
255 | devices to the same receiver. | ||
256 | |||
248 | config LOGITECH_FF | 257 | config LOGITECH_FF |
249 | bool "Logitech force feedback support" | 258 | bool "Logitech force feedback support" |
250 | depends on HID_LOGITECH | 259 | depends on HID_LOGITECH |
@@ -278,13 +287,21 @@ config LOGIG940_FF | |||
278 | Say Y here if you want to enable force feedback support for Logitech | 287 | Say Y here if you want to enable force feedback support for Logitech |
279 | Flight System G940 devices. | 288 | Flight System G940 devices. |
280 | 289 | ||
281 | config LOGIWII_FF | 290 | config LOGIWHEELS_FF |
282 | bool "Logitech Speed Force Wireless force feedback support" | 291 | bool "Logitech wheels configuration and force feedback support" |
283 | depends on HID_LOGITECH | 292 | depends on HID_LOGITECH |
284 | select INPUT_FF_MEMLESS | 293 | select INPUT_FF_MEMLESS |
294 | default LOGITECH_FF | ||
285 | help | 295 | help |
286 | Say Y here if you want to enable force feedback support for Logitech | 296 | Say Y here if you want to enable force feedback and range setting |
287 | Speed Force Wireless (Wii) devices. | 297 | support for following Logitech wheels: |
298 | - Logitech Driving Force | ||
299 | - Logitech Driving Force Pro | ||
300 | - Logitech Driving Force GT | ||
301 | - Logitech G25 | ||
302 | - Logitech G27 | ||
303 | - Logitech MOMO/MOMO 2 | ||
304 | - Logitech Formula Force EX | ||
288 | 305 | ||
289 | config HID_MAGICMOUSE | 306 | config HID_MAGICMOUSE |
290 | tristate "Apple MagicMouse multi-touch support" | 307 | tristate "Apple MagicMouse multi-touch support" |
@@ -328,6 +345,7 @@ config HID_MULTITOUCH | |||
328 | - Hanvon dual touch panels | 345 | - Hanvon dual touch panels |
329 | - Ilitek dual touch panels | 346 | - Ilitek dual touch panels |
330 | - IrTouch Infrared USB panels | 347 | - IrTouch Infrared USB panels |
348 | - LG Display panels (Dell ST2220Tc) | ||
331 | - Lumio CrystalTouch panels | 349 | - Lumio CrystalTouch panels |
332 | - MosArt dual-touch panels | 350 | - MosArt dual-touch panels |
333 | - PenMount dual touch panels | 351 | - PenMount dual touch panels |
@@ -441,6 +459,13 @@ config HID_PICOLCD_LEDS | |||
441 | ---help--- | 459 | ---help--- |
442 | Provide access to PicoLCD's GPO pins via leds class. | 460 | Provide access to PicoLCD's GPO pins via leds class. |
443 | 461 | ||
462 | config HID_PRIMAX | ||
463 | tristate "Primax non-fully HID-compliant devices" | ||
464 | depends on USB_HID | ||
465 | ---help--- | ||
466 | Support for Primax devices that are not fully compliant with the | ||
467 | HID standard. | ||
468 | |||
444 | config HID_QUANTA | 469 | config HID_QUANTA |
445 | tristate "Quanta Optical Touch panels" | 470 | tristate "Quanta Optical Touch panels" |
446 | depends on USB_HID | 471 | depends on USB_HID |
@@ -539,7 +564,11 @@ config HID_SMARTJOYPLUS | |||
539 | tristate "SmartJoy PLUS PS2/USB adapter support" | 564 | tristate "SmartJoy PLUS PS2/USB adapter support" |
540 | depends on USB_HID | 565 | depends on USB_HID |
541 | ---help--- | 566 | ---help--- |
542 | Support for SmartJoy PLUS PS2/USB adapter. | 567 | Support for SmartJoy PLUS PS2/USB adapter, Super Dual Box, |
568 | Super Joy Box 3 Pro, Super Dual Box Pro, and Super Joy Box 5 Pro. | ||
569 | |||
570 | Note that DDR (Dance Dance Revolution) mode is not supported, nor | ||
571 | is pressure sensitive buttons on the pro models. | ||
543 | 572 | ||
544 | config SMARTJOYPLUS_FF | 573 | config SMARTJOYPLUS_FF |
545 | bool "SmartJoy PLUS PS2/USB adapter force feedback support" | 574 | bool "SmartJoy PLUS PS2/USB adapter force feedback support" |
@@ -589,6 +618,8 @@ config HID_WACOM_POWER_SUPPLY | |||
589 | config HID_WIIMOTE | 618 | config HID_WIIMOTE |
590 | tristate "Nintendo Wii Remote support" | 619 | tristate "Nintendo Wii Remote support" |
591 | depends on BT_HIDP | 620 | depends on BT_HIDP |
621 | depends on LEDS_CLASS | ||
622 | select POWER_SUPPLY | ||
592 | ---help--- | 623 | ---help--- |
593 | Support for the Nintendo Wii Remote bluetooth device. | 624 | Support for the Nintendo Wii Remote bluetooth device. |
594 | 625 | ||
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 0a0a38e9fd28..1e0d2a638b28 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
@@ -21,7 +21,7 @@ endif | |||
21 | ifdef CONFIG_LOGIG940_FF | 21 | ifdef CONFIG_LOGIG940_FF |
22 | hid-logitech-y += hid-lg3ff.o | 22 | hid-logitech-y += hid-lg3ff.o |
23 | endif | 23 | endif |
24 | ifdef CONFIG_LOGIWII_FF | 24 | ifdef CONFIG_LOGIWHEELS_FF |
25 | hid-logitech-y += hid-lg4ff.o | 25 | hid-logitech-y += hid-lg4ff.o |
26 | endif | 26 | endif |
27 | 27 | ||
@@ -43,6 +43,7 @@ obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o | |||
43 | obj-$(CONFIG_HID_KYE) += hid-kye.o | 43 | obj-$(CONFIG_HID_KYE) += hid-kye.o |
44 | obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o | 44 | obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o |
45 | obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o | 45 | obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o |
46 | obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o | ||
46 | obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o | 47 | obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o |
47 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o | 48 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o |
48 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o | 49 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o |
@@ -54,6 +55,7 @@ obj-$(CONFIG_HID_QUANTA) += hid-quanta.o | |||
54 | obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o | 55 | obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o |
55 | obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o | 56 | obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o |
56 | obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o | 57 | obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o |
58 | obj-$(CONFIG_HID_PRIMAX) += hid-primax.o | ||
57 | obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o | 59 | obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o |
58 | obj-$(CONFIG_HID_ROCCAT_COMMON) += hid-roccat-common.o | 60 | obj-$(CONFIG_HID_ROCCAT_COMMON) += hid-roccat-common.o |
59 | obj-$(CONFIG_HID_ROCCAT_ARVO) += hid-roccat-arvo.o | 61 | obj-$(CONFIG_HID_ROCCAT_ARVO) += hid-roccat-arvo.o |
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index b85744fe8464..299d23871122 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c | |||
@@ -444,11 +444,20 @@ static const struct hid_device_id apple_devices[] = { | |||
444 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS), | 444 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS), |
445 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | | 445 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | |
446 | APPLE_RDESC_JIS }, | 446 | APPLE_RDESC_JIS }, |
447 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI), | ||
448 | .driver_data = APPLE_HAS_FN }, | ||
449 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO), | ||
450 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, | ||
451 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS), | ||
452 | .driver_data = APPLE_HAS_FN }, | ||
447 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI), | 453 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI), |
448 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, | 454 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, |
449 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO), | 455 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO), |
450 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | | 456 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | |
451 | APPLE_ISO_KEYBOARD }, | 457 | APPLE_ISO_KEYBOARD }, |
458 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO), | ||
459 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | | ||
460 | APPLE_ISO_KEYBOARD }, | ||
452 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS), | 461 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS), |
453 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, | 462 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, |
454 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI), | 463 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI), |
@@ -487,6 +496,24 @@ static const struct hid_device_id apple_devices[] = { | |||
487 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, | 496 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, |
488 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), | 497 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), |
489 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, | 498 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, |
499 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI), | ||
500 | .driver_data = APPLE_HAS_FN }, | ||
501 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO), | ||
502 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, | ||
503 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS), | ||
504 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, | ||
505 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI), | ||
506 | .driver_data = APPLE_HAS_FN }, | ||
507 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO), | ||
508 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, | ||
509 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS), | ||
510 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, | ||
511 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI), | ||
512 | .driver_data = APPLE_HAS_FN }, | ||
513 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO), | ||
514 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, | ||
515 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS), | ||
516 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, | ||
490 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), | 517 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), |
491 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, | 518 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, |
492 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), | 519 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), |
diff --git a/drivers/hid/hid-axff.c b/drivers/hid/hid-axff.c index 121514149e0b..5be858dd9a15 100644 --- a/drivers/hid/hid-axff.c +++ b/drivers/hid/hid-axff.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Xbox 360 controller. | 6 | * Xbox 360 controller. |
7 | * | 7 | * |
8 | * 1a34:0802 "ACRUX USB GAMEPAD 8116" | 8 | * 1a34:0802 "ACRUX USB GAMEPAD 8116" |
9 | * - tested with a EXEQ EQ-PCU-02090 game controller. | 9 | * - tested with an EXEQ EQ-PCU-02090 game controller. |
10 | * | 10 | * |
11 | * Copyright (c) 2010 Sergei Kolzun <x0r@dv-life.ru> | 11 | * Copyright (c) 2010 Sergei Kolzun <x0r@dv-life.ru> |
12 | */ | 12 | */ |
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/usb.h> | 32 | #include <linux/usb.h> |
33 | #include <linux/hid.h> | 33 | #include <linux/hid.h> |
34 | #include <linux/module.h> | ||
34 | 35 | ||
35 | #include "hid-ids.h" | 36 | #include "hid-ids.h" |
36 | 37 | ||
@@ -45,7 +46,10 @@ static int axff_play(struct input_dev *dev, void *data, struct ff_effect *effect | |||
45 | { | 46 | { |
46 | struct hid_device *hid = input_get_drvdata(dev); | 47 | struct hid_device *hid = input_get_drvdata(dev); |
47 | struct axff_device *axff = data; | 48 | struct axff_device *axff = data; |
49 | struct hid_report *report = axff->report; | ||
50 | int field_count = 0; | ||
48 | int left, right; | 51 | int left, right; |
52 | int i, j; | ||
49 | 53 | ||
50 | left = effect->u.rumble.strong_magnitude; | 54 | left = effect->u.rumble.strong_magnitude; |
51 | right = effect->u.rumble.weak_magnitude; | 55 | right = effect->u.rumble.weak_magnitude; |
@@ -55,10 +59,14 @@ static int axff_play(struct input_dev *dev, void *data, struct ff_effect *effect | |||
55 | left = left * 0xff / 0xffff; | 59 | left = left * 0xff / 0xffff; |
56 | right = right * 0xff / 0xffff; | 60 | right = right * 0xff / 0xffff; |
57 | 61 | ||
58 | axff->report->field[0]->value[0] = left; | 62 | for (i = 0; i < report->maxfield; i++) { |
59 | axff->report->field[1]->value[0] = right; | 63 | for (j = 0; j < report->field[i]->report_count; j++) { |
60 | axff->report->field[2]->value[0] = left; | 64 | report->field[i]->value[j] = |
61 | axff->report->field[3]->value[0] = right; | 65 | field_count % 2 ? right : left; |
66 | field_count++; | ||
67 | } | ||
68 | } | ||
69 | |||
62 | dbg_hid("running with 0x%02x 0x%02x", left, right); | 70 | dbg_hid("running with 0x%02x 0x%02x", left, right); |
63 | usbhid_submit_report(hid, axff->report, USB_DIR_OUT); | 71 | usbhid_submit_report(hid, axff->report, USB_DIR_OUT); |
64 | 72 | ||
@@ -72,6 +80,8 @@ static int axff_init(struct hid_device *hid) | |||
72 | struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input, list); | 80 | struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input, list); |
73 | struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT].report_list; | 81 | struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT].report_list; |
74 | struct input_dev *dev = hidinput->input; | 82 | struct input_dev *dev = hidinput->input; |
83 | int field_count = 0; | ||
84 | int i, j; | ||
75 | int error; | 85 | int error; |
76 | 86 | ||
77 | if (list_empty(report_list)) { | 87 | if (list_empty(report_list)) { |
@@ -80,9 +90,16 @@ static int axff_init(struct hid_device *hid) | |||
80 | } | 90 | } |
81 | 91 | ||
82 | report = list_first_entry(report_list, struct hid_report, list); | 92 | report = list_first_entry(report_list, struct hid_report, list); |
93 | for (i = 0; i < report->maxfield; i++) { | ||
94 | for (j = 0; j < report->field[i]->report_count; j++) { | ||
95 | report->field[i]->value[j] = 0x00; | ||
96 | field_count++; | ||
97 | } | ||
98 | } | ||
83 | 99 | ||
84 | if (report->maxfield < 4) { | 100 | if (field_count < 4) { |
85 | hid_err(hid, "no fields in the report: %d\n", report->maxfield); | 101 | hid_err(hid, "not enough fields in the report: %d\n", |
102 | field_count); | ||
86 | return -ENODEV; | 103 | return -ENODEV; |
87 | } | 104 | } |
88 | 105 | ||
@@ -97,13 +114,9 @@ static int axff_init(struct hid_device *hid) | |||
97 | goto err_free_mem; | 114 | goto err_free_mem; |
98 | 115 | ||
99 | axff->report = report; | 116 | axff->report = report; |
100 | axff->report->field[0]->value[0] = 0x00; | ||
101 | axff->report->field[1]->value[0] = 0x00; | ||
102 | axff->report->field[2]->value[0] = 0x00; | ||
103 | axff->report->field[3]->value[0] = 0x00; | ||
104 | usbhid_submit_report(hid, axff->report, USB_DIR_OUT); | 117 | usbhid_submit_report(hid, axff->report, USB_DIR_OUT); |
105 | 118 | ||
106 | hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun<x0r@dv-life.ru>\n"); | 119 | hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun <x0r@dv-life.ru>\n"); |
107 | 120 | ||
108 | return 0; | 121 | return 0; |
109 | 122 | ||
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 1a5cf0c9cfca..848a56c0279c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/wait.h> | 29 | #include <linux/wait.h> |
30 | #include <linux/vmalloc.h> | 30 | #include <linux/vmalloc.h> |
31 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
32 | #include <linux/semaphore.h> | ||
32 | 33 | ||
33 | #include <linux/hid.h> | 34 | #include <linux/hid.h> |
34 | #include <linux/hiddev.h> | 35 | #include <linux/hiddev.h> |
@@ -1085,16 +1086,25 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i | |||
1085 | struct hid_report *report; | 1086 | struct hid_report *report; |
1086 | char *buf; | 1087 | char *buf; |
1087 | unsigned int i; | 1088 | unsigned int i; |
1088 | int ret; | 1089 | int ret = 0; |
1089 | 1090 | ||
1090 | if (!hid || !hid->driver) | 1091 | if (!hid) |
1091 | return -ENODEV; | 1092 | return -ENODEV; |
1093 | |||
1094 | if (down_trylock(&hid->driver_lock)) | ||
1095 | return -EBUSY; | ||
1096 | |||
1097 | if (!hid->driver) { | ||
1098 | ret = -ENODEV; | ||
1099 | goto unlock; | ||
1100 | } | ||
1092 | report_enum = hid->report_enum + type; | 1101 | report_enum = hid->report_enum + type; |
1093 | hdrv = hid->driver; | 1102 | hdrv = hid->driver; |
1094 | 1103 | ||
1095 | if (!size) { | 1104 | if (!size) { |
1096 | dbg_hid("empty report\n"); | 1105 | dbg_hid("empty report\n"); |
1097 | return -1; | 1106 | ret = -1; |
1107 | goto unlock; | ||
1098 | } | 1108 | } |
1099 | 1109 | ||
1100 | buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC); | 1110 | buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC); |
@@ -1118,18 +1128,24 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i | |||
1118 | nomem: | 1128 | nomem: |
1119 | report = hid_get_report(report_enum, data); | 1129 | report = hid_get_report(report_enum, data); |
1120 | 1130 | ||
1121 | if (!report) | 1131 | if (!report) { |
1122 | return -1; | 1132 | ret = -1; |
1133 | goto unlock; | ||
1134 | } | ||
1123 | 1135 | ||
1124 | if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) { | 1136 | if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) { |
1125 | ret = hdrv->raw_event(hid, report, data, size); | 1137 | ret = hdrv->raw_event(hid, report, data, size); |
1126 | if (ret != 0) | 1138 | if (ret != 0) { |
1127 | return ret < 0 ? ret : 0; | 1139 | ret = ret < 0 ? ret : 0; |
1140 | goto unlock; | ||
1141 | } | ||
1128 | } | 1142 | } |
1129 | 1143 | ||
1130 | hid_report_raw_event(hid, type, data, size, interrupt); | 1144 | hid_report_raw_event(hid, type, data, size, interrupt); |
1131 | 1145 | ||
1132 | return 0; | 1146 | unlock: |
1147 | up(&hid->driver_lock); | ||
1148 | return ret; | ||
1133 | } | 1149 | } |
1134 | EXPORT_SYMBOL_GPL(hid_input_report); | 1150 | EXPORT_SYMBOL_GPL(hid_input_report); |
1135 | 1151 | ||
@@ -1212,6 +1228,12 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) | |||
1212 | if ((connect_mask & HID_CONNECT_HIDINPUT) && !hidinput_connect(hdev, | 1228 | if ((connect_mask & HID_CONNECT_HIDINPUT) && !hidinput_connect(hdev, |
1213 | connect_mask & HID_CONNECT_HIDINPUT_FORCE)) | 1229 | connect_mask & HID_CONNECT_HIDINPUT_FORCE)) |
1214 | hdev->claimed |= HID_CLAIMED_INPUT; | 1230 | hdev->claimed |= HID_CLAIMED_INPUT; |
1231 | if (hdev->quirks & HID_QUIRK_MULTITOUCH) { | ||
1232 | /* this device should be handled by hid-multitouch, skip it */ | ||
1233 | hdev->quirks &= ~HID_QUIRK_MULTITOUCH; | ||
1234 | return -ENODEV; | ||
1235 | } | ||
1236 | |||
1215 | if ((connect_mask & HID_CONNECT_HIDDEV) && hdev->hiddev_connect && | 1237 | if ((connect_mask & HID_CONNECT_HIDDEV) && hdev->hiddev_connect && |
1216 | !hdev->hiddev_connect(hdev, | 1238 | !hdev->hiddev_connect(hdev, |
1217 | connect_mask & HID_CONNECT_HIDDEV_FORCE)) | 1239 | connect_mask & HID_CONNECT_HIDDEV_FORCE)) |
@@ -1340,9 +1362,22 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1340 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, | 1362 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, |
1341 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, | 1363 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, |
1342 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, | 1364 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, |
1365 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI) }, | ||
1366 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO) }, | ||
1367 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS) }, | ||
1368 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI) }, | ||
1369 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO) }, | ||
1370 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS) }, | ||
1371 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI) }, | ||
1372 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO) }, | ||
1373 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) }, | ||
1374 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) }, | ||
1375 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, | ||
1376 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, | ||
1343 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, | 1377 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, |
1344 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, | 1378 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, |
1345 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, | 1379 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, |
1380 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) }, | ||
1346 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1381 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
1347 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1382 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
1348 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, | 1383 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, |
@@ -1388,6 +1423,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1388 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, | 1423 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, |
1389 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, | 1424 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, |
1390 | { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) }, | 1425 | { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) }, |
1426 | { HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6650) }, | ||
1391 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, | 1427 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, |
1392 | { HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) }, | 1428 | { HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) }, |
1393 | { HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, | 1429 | { HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, |
@@ -1396,6 +1432,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1396 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, | 1432 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, |
1397 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, | 1433 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, |
1398 | { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) }, | 1434 | { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) }, |
1435 | { HID_USB_DEVICE(USB_VENDOR_ID_LG, USB_DEVICE_ID_LG_MULTITOUCH) }, | ||
1399 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, | 1436 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, |
1400 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, | 1437 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, |
1401 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, | 1438 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, |
@@ -1417,8 +1454,11 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1417 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) }, | 1454 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) }, |
1418 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) }, | 1455 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) }, |
1419 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL) }, | 1456 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL) }, |
1457 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL) }, | ||
1420 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) }, | 1458 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) }, |
1421 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL) }, | 1459 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL) }, |
1460 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER) }, | ||
1461 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2) }, | ||
1422 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL) }, | 1462 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL) }, |
1423 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) }, | 1463 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) }, |
1424 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) }, | 1464 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) }, |
@@ -1458,6 +1498,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1458 | { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, | 1498 | { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, |
1459 | { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) }, | 1499 | { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) }, |
1460 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, | 1500 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, |
1501 | { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, | ||
1461 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, | 1502 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, |
1462 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, | 1503 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, |
1463 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, | 1504 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, |
@@ -1498,6 +1539,10 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1498 | { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) }, | 1539 | { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) }, |
1499 | { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) }, | 1540 | { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) }, |
1500 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, | 1541 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, |
1542 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) }, | ||
1543 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) }, | ||
1544 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) }, | ||
1545 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) }, | ||
1501 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, | 1546 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, |
1502 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, | 1547 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, |
1503 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, | 1548 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, |
@@ -1617,10 +1662,15 @@ static int hid_device_probe(struct device *dev) | |||
1617 | const struct hid_device_id *id; | 1662 | const struct hid_device_id *id; |
1618 | int ret = 0; | 1663 | int ret = 0; |
1619 | 1664 | ||
1665 | if (down_interruptible(&hdev->driver_lock)) | ||
1666 | return -EINTR; | ||
1667 | |||
1620 | if (!hdev->driver) { | 1668 | if (!hdev->driver) { |
1621 | id = hid_match_device(hdev, hdrv); | 1669 | id = hid_match_device(hdev, hdrv); |
1622 | if (id == NULL) | 1670 | if (id == NULL) { |
1623 | return -ENODEV; | 1671 | ret = -ENODEV; |
1672 | goto unlock; | ||
1673 | } | ||
1624 | 1674 | ||
1625 | hdev->driver = hdrv; | 1675 | hdev->driver = hdrv; |
1626 | if (hdrv->probe) { | 1676 | if (hdrv->probe) { |
@@ -1633,14 +1683,20 @@ static int hid_device_probe(struct device *dev) | |||
1633 | if (ret) | 1683 | if (ret) |
1634 | hdev->driver = NULL; | 1684 | hdev->driver = NULL; |
1635 | } | 1685 | } |
1686 | unlock: | ||
1687 | up(&hdev->driver_lock); | ||
1636 | return ret; | 1688 | return ret; |
1637 | } | 1689 | } |
1638 | 1690 | ||
1639 | static int hid_device_remove(struct device *dev) | 1691 | static int hid_device_remove(struct device *dev) |
1640 | { | 1692 | { |
1641 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); | 1693 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); |
1642 | struct hid_driver *hdrv = hdev->driver; | 1694 | struct hid_driver *hdrv; |
1695 | |||
1696 | if (down_interruptible(&hdev->driver_lock)) | ||
1697 | return -EINTR; | ||
1643 | 1698 | ||
1699 | hdrv = hdev->driver; | ||
1644 | if (hdrv) { | 1700 | if (hdrv) { |
1645 | if (hdrv->remove) | 1701 | if (hdrv->remove) |
1646 | hdrv->remove(hdev); | 1702 | hdrv->remove(hdev); |
@@ -1649,6 +1705,7 @@ static int hid_device_remove(struct device *dev) | |||
1649 | hdev->driver = NULL; | 1705 | hdev->driver = NULL; |
1650 | } | 1706 | } |
1651 | 1707 | ||
1708 | up(&hdev->driver_lock); | ||
1652 | return 0; | 1709 | return 0; |
1653 | } | 1710 | } |
1654 | 1711 | ||
@@ -1889,6 +1946,15 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { | |||
1889 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, | 1946 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, |
1890 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, | 1947 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, |
1891 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, | 1948 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, |
1949 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI) }, | ||
1950 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO) }, | ||
1951 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS) }, | ||
1952 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI) }, | ||
1953 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO) }, | ||
1954 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) }, | ||
1955 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) }, | ||
1956 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, | ||
1957 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, | ||
1892 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1958 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
1893 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1959 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
1894 | { } | 1960 | { } |
@@ -1996,6 +2062,7 @@ struct hid_device *hid_allocate_device(void) | |||
1996 | 2062 | ||
1997 | init_waitqueue_head(&hdev->debug_wait); | 2063 | init_waitqueue_head(&hdev->debug_wait); |
1998 | INIT_LIST_HEAD(&hdev->debug_list); | 2064 | INIT_LIST_HEAD(&hdev->debug_list); |
2065 | sema_init(&hdev->driver_lock, 1); | ||
1999 | 2066 | ||
2000 | return hdev; | 2067 | return hdev; |
2001 | err: | 2068 | err: |
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index bae48745bb42..ee80d733801d 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/debugfs.h> | 31 | #include <linux/debugfs.h> |
32 | #include <linux/seq_file.h> | 32 | #include <linux/seq_file.h> |
33 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
34 | #include <linux/export.h> | ||
34 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
35 | #include <linux/uaccess.h> | 36 | #include <linux/uaccess.h> |
36 | #include <linux/poll.h> | 37 | #include <linux/poll.h> |
@@ -450,6 +451,11 @@ void hid_dump_field(struct hid_field *field, int n, struct seq_file *f) { | |||
450 | seq_printf(f, "Logical("); | 451 | seq_printf(f, "Logical("); |
451 | hid_resolv_usage(field->logical, f); seq_printf(f, ")\n"); | 452 | hid_resolv_usage(field->logical, f); seq_printf(f, ")\n"); |
452 | } | 453 | } |
454 | if (field->application) { | ||
455 | tab(n, f); | ||
456 | seq_printf(f, "Application("); | ||
457 | hid_resolv_usage(field->application, f); seq_printf(f, ")\n"); | ||
458 | } | ||
453 | tab(n, f); seq_printf(f, "Usage(%d)\n", field->maxusage); | 459 | tab(n, f); seq_printf(f, "Usage(%d)\n", field->maxusage); |
454 | for (j = 0; j < field->maxusage; j++) { | 460 | for (j = 0; j < field->maxusage; j++) { |
455 | tab(n+2, f); hid_resolv_usage(field->usage[j].hid, f); seq_printf(f, "\n"); | 461 | tab(n+2, f); hid_resolv_usage(field->usage[j].hid, f); seq_printf(f, "\n"); |
diff --git a/drivers/hid/hid-dr.c b/drivers/hid/hid-dr.c index 61eece47204d..e832f44ae383 100644 --- a/drivers/hid/hid-dr.c +++ b/drivers/hid/hid-dr.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/usb.h> | 32 | #include <linux/usb.h> |
33 | #include <linux/hid.h> | 33 | #include <linux/hid.h> |
34 | #include <linux/module.h> | ||
34 | 35 | ||
35 | #include "hid-ids.h" | 36 | #include "hid-ids.h" |
36 | 37 | ||
diff --git a/drivers/hid/hid-emsff.c b/drivers/hid/hid-emsff.c index a5dc13fe367b..9bdde867a02f 100644 --- a/drivers/hid/hid-emsff.c +++ b/drivers/hid/hid-emsff.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/hid.h> | 24 | #include <linux/hid.h> |
25 | #include <linux/input.h> | 25 | #include <linux/input.h> |
26 | #include <linux/usb.h> | 26 | #include <linux/usb.h> |
27 | #include <linux/module.h> | ||
27 | 28 | ||
28 | #include "hid-ids.h" | 29 | #include "hid-ids.h" |
29 | #include "usbhid/usbhid.h" | 30 | #include "usbhid/usbhid.h" |
diff --git a/drivers/hid/hid-gaff.c b/drivers/hid/hid-gaff.c index 279ba530003c..f1e1bcf67427 100644 --- a/drivers/hid/hid-gaff.c +++ b/drivers/hid/hid-gaff.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/usb.h> | 32 | #include <linux/usb.h> |
33 | #include <linux/hid.h> | 33 | #include <linux/hid.h> |
34 | #include <linux/module.h> | ||
34 | #include "hid-ids.h" | 35 | #include "hid-ids.h" |
35 | 36 | ||
36 | #ifdef CONFIG_GREENASIA_FF | 37 | #ifdef CONFIG_GREENASIA_FF |
diff --git a/drivers/hid/hid-holtekff.c b/drivers/hid/hid-holtekff.c index 91e3a032112b..4e7542151e22 100644 --- a/drivers/hid/hid-holtekff.c +++ b/drivers/hid/hid-holtekff.c | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #include <linux/hid.h> | 26 | #include <linux/hid.h> |
27 | #include <linux/input.h> | 27 | #include <linux/input.h> |
28 | #include <linux/module.h> | ||
28 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
29 | #include <linux/usb.h> | 30 | #include <linux/usb.h> |
30 | 31 | ||
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index db63ccf21cc8..06ce996b8b65 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -109,9 +109,22 @@ | |||
109 | #define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 | 109 | #define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 |
110 | #define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 | 110 | #define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 |
111 | #define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 | 111 | #define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 |
112 | #define USB_DEVICE_ID_APPLE_ALU_REVB_ANSI 0x024f | ||
113 | #define USB_DEVICE_ID_APPLE_ALU_REVB_ISO 0x0250 | ||
114 | #define USB_DEVICE_ID_APPLE_ALU_REVB_JIS 0x0251 | ||
115 | #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252 | ||
116 | #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253 | ||
117 | #define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS 0x0254 | ||
118 | #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249 | ||
119 | #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a | ||
120 | #define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b | ||
121 | #define USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI 0x024c | ||
122 | #define USB_DEVICE_ID_APPLE_WELLSPRING6_ISO 0x024d | ||
123 | #define USB_DEVICE_ID_APPLE_WELLSPRING6_JIS 0x024e | ||
112 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 | 124 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 |
113 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a | 125 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a |
114 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b | 126 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b |
127 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO 0x0256 | ||
115 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a | 128 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a |
116 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b | 129 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b |
117 | #define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241 | 130 | #define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241 |
@@ -274,6 +287,7 @@ | |||
274 | #define USB_DEVICE_ID_PENPOWER 0x00f4 | 287 | #define USB_DEVICE_ID_PENPOWER 0x00f4 |
275 | 288 | ||
276 | #define USB_VENDOR_ID_GREENASIA 0x0e8f | 289 | #define USB_VENDOR_ID_GREENASIA 0x0e8f |
290 | #define USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD 0x3013 | ||
277 | 291 | ||
278 | #define USB_VENDOR_ID_GRETAGMACBETH 0x0971 | 292 | #define USB_VENDOR_ID_GRETAGMACBETH 0x0971 |
279 | #define USB_DEVICE_ID_GRETAGMACBETH_HUEY 0x2005 | 293 | #define USB_DEVICE_ID_GRETAGMACBETH_HUEY 0x2005 |
@@ -347,6 +361,9 @@ | |||
347 | #define USB_DEVICE_ID_UGCI_FLYING 0x0020 | 361 | #define USB_DEVICE_ID_UGCI_FLYING 0x0020 |
348 | #define USB_DEVICE_ID_UGCI_FIGHTING 0x0030 | 362 | #define USB_DEVICE_ID_UGCI_FIGHTING 0x0030 |
349 | 363 | ||
364 | #define USB_VENDOR_ID_IDEACOM 0x1cb6 | ||
365 | #define USB_DEVICE_ID_IDEACOM_IDC6650 0x6650 | ||
366 | |||
350 | #define USB_VENDOR_ID_ILITEK 0x222a | 367 | #define USB_VENDOR_ID_ILITEK 0x222a |
351 | #define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001 | 368 | #define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001 |
352 | 369 | ||
@@ -419,6 +436,9 @@ | |||
419 | #define USB_DEVICE_ID_LD_HYBRID 0x2090 | 436 | #define USB_DEVICE_ID_LD_HYBRID 0x2090 |
420 | #define USB_DEVICE_ID_LD_HEATCONTROL 0x20A0 | 437 | #define USB_DEVICE_ID_LD_HEATCONTROL 0x20A0 |
421 | 438 | ||
439 | #define USB_VENDOR_ID_LG 0x1fd2 | ||
440 | #define USB_DEVICE_ID_LG_MULTITOUCH 0x0064 | ||
441 | |||
422 | #define USB_VENDOR_ID_LOGITECH 0x046d | 442 | #define USB_VENDOR_ID_LOGITECH 0x046d |
423 | #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 | 443 | #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 |
424 | #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 | 444 | #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 |
@@ -436,6 +456,7 @@ | |||
436 | #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 | 456 | #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 |
437 | #define USB_DEVICE_ID_LOGITECH_DFP_WHEEL 0xc298 | 457 | #define USB_DEVICE_ID_LOGITECH_DFP_WHEEL 0xc298 |
438 | #define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299 | 458 | #define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299 |
459 | #define USB_DEVICE_ID_LOGITECH_DFGT_WHEEL 0xc29a | ||
439 | #define USB_DEVICE_ID_LOGITECH_G27_WHEEL 0xc29b | 460 | #define USB_DEVICE_ID_LOGITECH_G27_WHEEL 0xc29b |
440 | #define USB_DEVICE_ID_LOGITECH_WII_WHEEL 0xc29c | 461 | #define USB_DEVICE_ID_LOGITECH_WII_WHEEL 0xc29c |
441 | #define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a | 462 | #define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a |
@@ -443,6 +464,8 @@ | |||
443 | #define USB_DEVICE_ID_S510_RECEIVER_2 0xc517 | 464 | #define USB_DEVICE_ID_S510_RECEIVER_2 0xc517 |
444 | #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512 | 465 | #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512 |
445 | #define USB_DEVICE_ID_MX3000_RECEIVER 0xc513 | 466 | #define USB_DEVICE_ID_MX3000_RECEIVER 0xc513 |
467 | #define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER 0xc52b | ||
468 | #define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2 0xc532 | ||
446 | #define USB_DEVICE_ID_SPACETRAVELLER 0xc623 | 469 | #define USB_DEVICE_ID_SPACETRAVELLER 0xc623 |
447 | #define USB_DEVICE_ID_SPACENAVIGATOR 0xc626 | 470 | #define USB_DEVICE_ID_SPACENAVIGATOR 0xc626 |
448 | #define USB_DEVICE_ID_DINOVO_DESKTOP 0xc704 | 471 | #define USB_DEVICE_ID_DINOVO_DESKTOP 0xc704 |
@@ -576,6 +599,9 @@ | |||
576 | #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001 | 599 | #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001 |
577 | #define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE 0x0600 | 600 | #define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE 0x0600 |
578 | 601 | ||
602 | #define USB_VENDOR_ID_SIGMA_MICRO 0x1c4f | ||
603 | #define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD 0x0002 | ||
604 | |||
579 | #define USB_VENDOR_ID_SKYCABLE 0x1223 | 605 | #define USB_VENDOR_ID_SKYCABLE 0x1223 |
580 | #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 | 606 | #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 |
581 | 607 | ||
@@ -671,6 +697,9 @@ | |||
671 | #define USB_VENDOR_ID_WISEGROUP_LTD 0x6666 | 697 | #define USB_VENDOR_ID_WISEGROUP_LTD 0x6666 |
672 | #define USB_VENDOR_ID_WISEGROUP_LTD2 0x6677 | 698 | #define USB_VENDOR_ID_WISEGROUP_LTD2 0x6677 |
673 | #define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802 | 699 | #define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802 |
700 | #define USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO 0x8801 | ||
701 | #define USB_DEVICE_ID_SUPER_DUAL_BOX_PRO 0x8802 | ||
702 | #define USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO 0x8804 | ||
674 | 703 | ||
675 | #define USB_VENDOR_ID_X_TENSIONS 0x1ae7 | 704 | #define USB_VENDOR_ID_X_TENSIONS 0x1ae7 |
676 | #define USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE 0x9001 | 705 | #define USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE 0x9001 |
@@ -686,4 +715,7 @@ | |||
686 | #define USB_VENDOR_ID_ZYDACRON 0x13EC | 715 | #define USB_VENDOR_ID_ZYDACRON 0x13EC |
687 | #define USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL 0x0006 | 716 | #define USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL 0x0006 |
688 | 717 | ||
718 | #define USB_VENDOR_ID_PRIMAX 0x0461 | ||
719 | #define USB_DEVICE_ID_PRIMAX_KEYBOARD 0x4e05 | ||
720 | |||
689 | #endif | 721 | #endif |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 6559e2e3364e..f333139d1a48 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -474,6 +474,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
474 | map_key_clear(BTN_STYLUS2); | 474 | map_key_clear(BTN_STYLUS2); |
475 | break; | 475 | break; |
476 | 476 | ||
477 | case 0x51: /* ContactID */ | ||
478 | device->quirks |= HID_QUIRK_MULTITOUCH; | ||
479 | goto unknown; | ||
480 | |||
477 | default: goto unknown; | 481 | default: goto unknown; |
478 | } | 482 | } |
479 | break; | 483 | break; |
@@ -978,6 +982,13 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
978 | } | 982 | } |
979 | } | 983 | } |
980 | 984 | ||
985 | if (hid->quirks & HID_QUIRK_MULTITOUCH) { | ||
986 | /* generic hid does not know how to handle multitouch devices */ | ||
987 | if (hidinput) | ||
988 | goto out_cleanup; | ||
989 | goto out_unwind; | ||
990 | } | ||
991 | |||
981 | if (hidinput && input_register_device(hidinput->input)) | 992 | if (hidinput && input_register_device(hidinput->input)) |
982 | goto out_cleanup; | 993 | goto out_cleanup; |
983 | 994 | ||
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index a7f916e8fc32..e7a7bd1eb34a 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c | |||
@@ -363,7 +363,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
363 | goto err_free; | 363 | goto err_free; |
364 | } | 364 | } |
365 | 365 | ||
366 | if (quirks & (LG_FF | LG_FF2 | LG_FF3)) | 366 | if (quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4)) |
367 | connect_mask &= ~HID_CONNECT_FF; | 367 | connect_mask &= ~HID_CONNECT_FF; |
368 | 368 | ||
369 | ret = hid_hw_start(hdev, connect_mask); | 369 | ret = hid_hw_start(hdev, connect_mask); |
@@ -372,7 +372,8 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
372 | goto err_free; | 372 | goto err_free; |
373 | } | 373 | } |
374 | 374 | ||
375 | if (quirks & LG_FF4) { | 375 | /* Setup wireless link with Logitech Wii wheel */ |
376 | if(hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) { | ||
376 | unsigned char buf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | 377 | unsigned char buf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; |
377 | 378 | ||
378 | ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); | 379 | ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); |
@@ -405,6 +406,15 @@ err_free: | |||
405 | return ret; | 406 | return ret; |
406 | } | 407 | } |
407 | 408 | ||
409 | static void lg_remove(struct hid_device *hdev) | ||
410 | { | ||
411 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | ||
412 | if(quirks & LG_FF4) | ||
413 | lg4ff_deinit(hdev); | ||
414 | |||
415 | hid_hw_stop(hdev); | ||
416 | } | ||
417 | |||
408 | static const struct hid_device_id lg_devices[] = { | 418 | static const struct hid_device_id lg_devices[] = { |
409 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER), | 419 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER), |
410 | .driver_data = LG_RDESC | LG_WIRELESS }, | 420 | .driver_data = LG_RDESC | LG_WIRELESS }, |
@@ -431,7 +441,7 @@ static const struct hid_device_id lg_devices[] = { | |||
431 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D), | 441 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D), |
432 | .driver_data = LG_NOGET }, | 442 | .driver_data = LG_NOGET }, |
433 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL), | 443 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL), |
434 | .driver_data = LG_NOGET | LG_FF }, | 444 | .driver_data = LG_NOGET | LG_FF4 }, |
435 | 445 | ||
436 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD), | 446 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD), |
437 | .driver_data = LG_FF2 }, | 447 | .driver_data = LG_FF2 }, |
@@ -444,15 +454,17 @@ static const struct hid_device_id lg_devices[] = { | |||
444 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO), | 454 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO), |
445 | .driver_data = LG_FF }, | 455 | .driver_data = LG_FF }, |
446 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL), | 456 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL), |
447 | .driver_data = LG_FF }, | 457 | .driver_data = LG_FF4 }, |
448 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2), | 458 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2), |
449 | .driver_data = LG_FF }, | 459 | .driver_data = LG_FF4 }, |
450 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL), | 460 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL), |
451 | .driver_data = LG_FF }, | 461 | .driver_data = LG_FF4 }, |
462 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL), | ||
463 | .driver_data = LG_FF4 }, | ||
452 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL), | 464 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL), |
453 | .driver_data = LG_FF }, | 465 | .driver_data = LG_FF4 }, |
454 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL), | 466 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL), |
455 | .driver_data = LG_NOGET | LG_FF }, | 467 | .driver_data = LG_NOGET | LG_FF4 }, |
456 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL), | 468 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL), |
457 | .driver_data = LG_FF4 }, | 469 | .driver_data = LG_FF4 }, |
458 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ), | 470 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ), |
@@ -478,6 +490,7 @@ static struct hid_driver lg_driver = { | |||
478 | .input_mapped = lg_input_mapped, | 490 | .input_mapped = lg_input_mapped, |
479 | .event = lg_event, | 491 | .event = lg_event, |
480 | .probe = lg_probe, | 492 | .probe = lg_probe, |
493 | .remove = lg_remove, | ||
481 | }; | 494 | }; |
482 | 495 | ||
483 | static int __init lg_init(void) | 496 | static int __init lg_init(void) |
diff --git a/drivers/hid/hid-lg.h b/drivers/hid/hid-lg.h index b0100ba2ae0b..4b097286dc78 100644 --- a/drivers/hid/hid-lg.h +++ b/drivers/hid/hid-lg.h | |||
@@ -19,10 +19,12 @@ int lg3ff_init(struct hid_device *hdev); | |||
19 | static inline int lg3ff_init(struct hid_device *hdev) { return -1; } | 19 | static inline int lg3ff_init(struct hid_device *hdev) { return -1; } |
20 | #endif | 20 | #endif |
21 | 21 | ||
22 | #ifdef CONFIG_LOGIWII_FF | 22 | #ifdef CONFIG_LOGIWHEELS_FF |
23 | int lg4ff_init(struct hid_device *hdev); | 23 | int lg4ff_init(struct hid_device *hdev); |
24 | int lg4ff_deinit(struct hid_device *hdev); | ||
24 | #else | 25 | #else |
25 | static inline int lg4ff_init(struct hid_device *hdev) { return -1; } | 26 | static inline int lg4ff_init(struct hid_device *hdev) { return -1; } |
27 | static inline int lg4ff_deinit(struct hid_device *hdev) { return -1; } | ||
26 | #endif | 28 | #endif |
27 | 29 | ||
28 | #endif | 30 | #endif |
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index fa550c8e1d1b..103f30d93f76 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c | |||
@@ -29,19 +29,108 @@ | |||
29 | 29 | ||
30 | #include "usbhid/usbhid.h" | 30 | #include "usbhid/usbhid.h" |
31 | #include "hid-lg.h" | 31 | #include "hid-lg.h" |
32 | #include "hid-ids.h" | ||
32 | 33 | ||
33 | struct lg4ff_device { | 34 | #define DFGT_REV_MAJ 0x13 |
34 | struct hid_report *report; | 35 | #define DFGT_REV_MIN 0x22 |
36 | #define DFP_REV_MAJ 0x11 | ||
37 | #define DFP_REV_MIN 0x06 | ||
38 | #define FFEX_REV_MAJ 0x21 | ||
39 | #define FFEX_REV_MIN 0x00 | ||
40 | #define G25_REV_MAJ 0x12 | ||
41 | #define G25_REV_MIN 0x22 | ||
42 | #define G27_REV_MAJ 0x12 | ||
43 | #define G27_REV_MIN 0x38 | ||
44 | |||
45 | #define to_hid_device(pdev) container_of(pdev, struct hid_device, dev) | ||
46 | |||
47 | static void hid_lg4ff_set_range_dfp(struct hid_device *hid, u16 range); | ||
48 | static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range); | ||
49 | static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, char *buf); | ||
50 | static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); | ||
51 | |||
52 | static DEVICE_ATTR(range, S_IRWXU | S_IRWXG | S_IRWXO, lg4ff_range_show, lg4ff_range_store); | ||
53 | |||
54 | static bool list_inited; | ||
55 | |||
56 | struct lg4ff_device_entry { | ||
57 | char *device_id; /* Use name in respective kobject structure's address as the ID */ | ||
58 | __u16 range; | ||
59 | __u16 min_range; | ||
60 | __u16 max_range; | ||
61 | __u8 leds; | ||
62 | struct list_head list; | ||
63 | void (*set_range)(struct hid_device *hid, u16 range); | ||
35 | }; | 64 | }; |
36 | 65 | ||
37 | static const signed short ff4_wheel_ac[] = { | 66 | static struct lg4ff_device_entry device_list; |
67 | |||
68 | static const signed short lg4ff_wheel_effects[] = { | ||
38 | FF_CONSTANT, | 69 | FF_CONSTANT, |
39 | FF_AUTOCENTER, | 70 | FF_AUTOCENTER, |
40 | -1 | 71 | -1 |
41 | }; | 72 | }; |
42 | 73 | ||
43 | static int hid_lg4ff_play(struct input_dev *dev, void *data, | 74 | struct lg4ff_wheel { |
44 | struct ff_effect *effect) | 75 | const __u32 product_id; |
76 | const signed short *ff_effects; | ||
77 | const __u16 min_range; | ||
78 | const __u16 max_range; | ||
79 | void (*set_range)(struct hid_device *hid, u16 range); | ||
80 | }; | ||
81 | |||
82 | static const struct lg4ff_wheel lg4ff_devices[] = { | ||
83 | {USB_DEVICE_ID_LOGITECH_WHEEL, lg4ff_wheel_effects, 40, 270, NULL}, | ||
84 | {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL, lg4ff_wheel_effects, 40, 270, NULL}, | ||
85 | {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_dfp}, | ||
86 | {USB_DEVICE_ID_LOGITECH_G25_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25}, | ||
87 | {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25}, | ||
88 | {USB_DEVICE_ID_LOGITECH_G27_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25}, | ||
89 | {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270, NULL}, | ||
90 | {USB_DEVICE_ID_LOGITECH_WII_WHEEL, lg4ff_wheel_effects, 40, 270, NULL} | ||
91 | }; | ||
92 | |||
93 | struct lg4ff_native_cmd { | ||
94 | const __u8 cmd_num; /* Number of commands to send */ | ||
95 | const __u8 cmd[]; | ||
96 | }; | ||
97 | |||
98 | struct lg4ff_usb_revision { | ||
99 | const __u16 rev_maj; | ||
100 | const __u16 rev_min; | ||
101 | const struct lg4ff_native_cmd *command; | ||
102 | }; | ||
103 | |||
104 | static const struct lg4ff_native_cmd native_dfp = { | ||
105 | 1, | ||
106 | {0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00} | ||
107 | }; | ||
108 | |||
109 | static const struct lg4ff_native_cmd native_dfgt = { | ||
110 | 2, | ||
111 | {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1st command */ | ||
112 | 0xf8, 0x09, 0x03, 0x01, 0x00, 0x00, 0x00} /* 2nd command */ | ||
113 | }; | ||
114 | |||
115 | static const struct lg4ff_native_cmd native_g25 = { | ||
116 | 1, | ||
117 | {0xf8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00} | ||
118 | }; | ||
119 | |||
120 | static const struct lg4ff_native_cmd native_g27 = { | ||
121 | 2, | ||
122 | {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1st command */ | ||
123 | 0xf8, 0x09, 0x04, 0x01, 0x00, 0x00, 0x00} /* 2nd command */ | ||
124 | }; | ||
125 | |||
126 | static const struct lg4ff_usb_revision lg4ff_revs[] = { | ||
127 | {DFGT_REV_MAJ, DFGT_REV_MIN, &native_dfgt}, /* Driving Force GT */ | ||
128 | {DFP_REV_MAJ, DFP_REV_MIN, &native_dfp}, /* Driving Force Pro */ | ||
129 | {G25_REV_MAJ, G25_REV_MIN, &native_g25}, /* G25 */ | ||
130 | {G27_REV_MAJ, G27_REV_MIN, &native_g27}, /* G27 */ | ||
131 | }; | ||
132 | |||
133 | static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effect) | ||
45 | { | 134 | { |
46 | struct hid_device *hid = input_get_drvdata(dev); | 135 | struct hid_device *hid = input_get_drvdata(dev); |
47 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | 136 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; |
@@ -55,13 +144,12 @@ static int hid_lg4ff_play(struct input_dev *dev, void *data, | |||
55 | x = effect->u.ramp.start_level + 0x80; /* 0x80 is no force */ | 144 | x = effect->u.ramp.start_level + 0x80; /* 0x80 is no force */ |
56 | CLAMP(x); | 145 | CLAMP(x); |
57 | report->field[0]->value[0] = 0x11; /* Slot 1 */ | 146 | report->field[0]->value[0] = 0x11; /* Slot 1 */ |
58 | report->field[0]->value[1] = 0x10; | 147 | report->field[0]->value[1] = 0x08; |
59 | report->field[0]->value[2] = x; | 148 | report->field[0]->value[2] = x; |
60 | report->field[0]->value[3] = 0x00; | 149 | report->field[0]->value[3] = 0x80; |
61 | report->field[0]->value[4] = 0x00; | 150 | report->field[0]->value[4] = 0x00; |
62 | report->field[0]->value[5] = 0x08; | 151 | report->field[0]->value[5] = 0x00; |
63 | report->field[0]->value[6] = 0x00; | 152 | report->field[0]->value[6] = 0x00; |
64 | dbg_hid("Autocenter, x=0x%02X\n", x); | ||
65 | 153 | ||
66 | usbhid_submit_report(hid, report, USB_DIR_OUT); | 154 | usbhid_submit_report(hid, report, USB_DIR_OUT); |
67 | break; | 155 | break; |
@@ -69,24 +157,184 @@ static int hid_lg4ff_play(struct input_dev *dev, void *data, | |||
69 | return 0; | 157 | return 0; |
70 | } | 158 | } |
71 | 159 | ||
72 | static void hid_lg4ff_set_autocenter(struct input_dev *dev, u16 magnitude) | 160 | /* Sends default autocentering command compatible with |
161 | * all wheels except Formula Force EX */ | ||
162 | static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude) | ||
73 | { | 163 | { |
74 | struct hid_device *hid = input_get_drvdata(dev); | 164 | struct hid_device *hid = input_get_drvdata(dev); |
75 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | 165 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; |
76 | struct hid_report *report = list_entry(report_list->next, struct hid_report, list); | 166 | struct hid_report *report = list_entry(report_list->next, struct hid_report, list); |
77 | __s32 *value = report->field[0]->value; | ||
78 | 167 | ||
79 | *value++ = 0xfe; | 168 | report->field[0]->value[0] = 0xfe; |
80 | *value++ = 0x0d; | 169 | report->field[0]->value[1] = 0x0d; |
81 | *value++ = 0x07; | 170 | report->field[0]->value[2] = magnitude >> 13; |
82 | *value++ = 0x07; | 171 | report->field[0]->value[3] = magnitude >> 13; |
83 | *value++ = (magnitude >> 8) & 0xff; | 172 | report->field[0]->value[4] = magnitude >> 8; |
84 | *value++ = 0x00; | 173 | report->field[0]->value[5] = 0x00; |
85 | *value = 0x00; | 174 | report->field[0]->value[6] = 0x00; |
175 | |||
176 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
177 | } | ||
178 | |||
179 | /* Sends autocentering command compatible with Formula Force EX */ | ||
180 | static void hid_lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude) | ||
181 | { | ||
182 | struct hid_device *hid = input_get_drvdata(dev); | ||
183 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
184 | struct hid_report *report = list_entry(report_list->next, struct hid_report, list); | ||
185 | magnitude = magnitude * 90 / 65535; | ||
186 | |||
187 | |||
188 | report->field[0]->value[0] = 0xfe; | ||
189 | report->field[0]->value[1] = 0x03; | ||
190 | report->field[0]->value[2] = magnitude >> 14; | ||
191 | report->field[0]->value[3] = magnitude >> 14; | ||
192 | report->field[0]->value[4] = magnitude; | ||
193 | report->field[0]->value[5] = 0x00; | ||
194 | report->field[0]->value[6] = 0x00; | ||
195 | |||
196 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
197 | } | ||
198 | |||
199 | /* Sends command to set range compatible with G25/G27/Driving Force GT */ | ||
200 | static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range) | ||
201 | { | ||
202 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
203 | struct hid_report *report = list_entry(report_list->next, struct hid_report, list); | ||
204 | dbg_hid("G25/G27/DFGT: setting range to %u\n", range); | ||
205 | |||
206 | report->field[0]->value[0] = 0xf8; | ||
207 | report->field[0]->value[1] = 0x81; | ||
208 | report->field[0]->value[2] = range & 0x00ff; | ||
209 | report->field[0]->value[3] = (range & 0xff00) >> 8; | ||
210 | report->field[0]->value[4] = 0x00; | ||
211 | report->field[0]->value[5] = 0x00; | ||
212 | report->field[0]->value[6] = 0x00; | ||
213 | |||
214 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
215 | } | ||
216 | |||
217 | /* Sends commands to set range compatible with Driving Force Pro wheel */ | ||
218 | static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range) | ||
219 | { | ||
220 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
221 | struct hid_report *report = list_entry(report_list->next, struct hid_report, list); | ||
222 | int start_left, start_right, full_range; | ||
223 | dbg_hid("Driving Force Pro: setting range to %u\n", range); | ||
224 | |||
225 | /* Prepare "coarse" limit command */ | ||
226 | report->field[0]->value[0] = 0xf8; | ||
227 | report->field[0]->value[1] = 0x00; /* Set later */ | ||
228 | report->field[0]->value[2] = 0x00; | ||
229 | report->field[0]->value[3] = 0x00; | ||
230 | report->field[0]->value[4] = 0x00; | ||
231 | report->field[0]->value[5] = 0x00; | ||
232 | report->field[0]->value[6] = 0x00; | ||
233 | |||
234 | if (range > 200) { | ||
235 | report->field[0]->value[1] = 0x03; | ||
236 | full_range = 900; | ||
237 | } else { | ||
238 | report->field[0]->value[1] = 0x02; | ||
239 | full_range = 200; | ||
240 | } | ||
241 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
242 | |||
243 | /* Prepare "fine" limit command */ | ||
244 | report->field[0]->value[0] = 0x81; | ||
245 | report->field[0]->value[1] = 0x0b; | ||
246 | report->field[0]->value[2] = 0x00; | ||
247 | report->field[0]->value[3] = 0x00; | ||
248 | report->field[0]->value[4] = 0x00; | ||
249 | report->field[0]->value[5] = 0x00; | ||
250 | report->field[0]->value[6] = 0x00; | ||
251 | |||
252 | if (range == 200 || range == 900) { /* Do not apply any fine limit */ | ||
253 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
254 | return; | ||
255 | } | ||
256 | |||
257 | /* Construct fine limit command */ | ||
258 | start_left = (((full_range - range + 1) * 2047) / full_range); | ||
259 | start_right = 0xfff - start_left; | ||
260 | |||
261 | report->field[0]->value[2] = start_left >> 4; | ||
262 | report->field[0]->value[3] = start_right >> 4; | ||
263 | report->field[0]->value[4] = 0xff; | ||
264 | report->field[0]->value[5] = (start_right & 0xe) << 4 | (start_left & 0xe); | ||
265 | report->field[0]->value[6] = 0xff; | ||
86 | 266 | ||
87 | usbhid_submit_report(hid, report, USB_DIR_OUT); | 267 | usbhid_submit_report(hid, report, USB_DIR_OUT); |
88 | } | 268 | } |
89 | 269 | ||
270 | static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_native_cmd *cmd) | ||
271 | { | ||
272 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
273 | struct hid_report *report = list_entry(report_list->next, struct hid_report, list); | ||
274 | __u8 i, j; | ||
275 | |||
276 | j = 0; | ||
277 | while (j < 7*cmd->cmd_num) { | ||
278 | for (i = 0; i < 7; i++) | ||
279 | report->field[0]->value[i] = cmd->cmd[j++]; | ||
280 | |||
281 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
282 | } | ||
283 | } | ||
284 | |||
285 | /* Read current range and display it in terminal */ | ||
286 | static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
287 | { | ||
288 | struct lg4ff_device_entry *uninitialized_var(entry); | ||
289 | struct list_head *h; | ||
290 | struct hid_device *hid = to_hid_device(dev); | ||
291 | size_t count; | ||
292 | |||
293 | list_for_each(h, &device_list.list) { | ||
294 | entry = list_entry(h, struct lg4ff_device_entry, list); | ||
295 | if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0) | ||
296 | break; | ||
297 | } | ||
298 | if (h == &device_list.list) { | ||
299 | dbg_hid("Device not found!"); | ||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->range); | ||
304 | return count; | ||
305 | } | ||
306 | |||
307 | /* Set range to user specified value, call appropriate function | ||
308 | * according to the type of the wheel */ | ||
309 | static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
310 | { | ||
311 | struct lg4ff_device_entry *uninitialized_var(entry); | ||
312 | struct list_head *h; | ||
313 | struct hid_device *hid = to_hid_device(dev); | ||
314 | __u16 range = simple_strtoul(buf, NULL, 10); | ||
315 | |||
316 | list_for_each(h, &device_list.list) { | ||
317 | entry = list_entry(h, struct lg4ff_device_entry, list); | ||
318 | if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0) | ||
319 | break; | ||
320 | } | ||
321 | if (h == &device_list.list) { | ||
322 | dbg_hid("Device not found!"); | ||
323 | return count; | ||
324 | } | ||
325 | |||
326 | if (range == 0) | ||
327 | range = entry->max_range; | ||
328 | |||
329 | /* Check if the wheel supports range setting | ||
330 | * and that the range is within limits for the wheel */ | ||
331 | if (entry->set_range != NULL && range >= entry->min_range && range <= entry->max_range) { | ||
332 | entry->set_range(hid, range); | ||
333 | entry->range = range; | ||
334 | } | ||
335 | |||
336 | return count; | ||
337 | } | ||
90 | 338 | ||
91 | int lg4ff_init(struct hid_device *hid) | 339 | int lg4ff_init(struct hid_device *hid) |
92 | { | 340 | { |
@@ -95,9 +343,10 @@ int lg4ff_init(struct hid_device *hid) | |||
95 | struct input_dev *dev = hidinput->input; | 343 | struct input_dev *dev = hidinput->input; |
96 | struct hid_report *report; | 344 | struct hid_report *report; |
97 | struct hid_field *field; | 345 | struct hid_field *field; |
98 | const signed short *ff_bits = ff4_wheel_ac; | 346 | struct lg4ff_device_entry *entry; |
99 | int error; | 347 | struct usb_device_descriptor *udesc; |
100 | int i; | 348 | int error, i, j; |
349 | __u16 bcdDevice, rev_maj, rev_min; | ||
101 | 350 | ||
102 | /* Find the report to use */ | 351 | /* Find the report to use */ |
103 | if (list_empty(report_list)) { | 352 | if (list_empty(report_list)) { |
@@ -118,18 +367,122 @@ int lg4ff_init(struct hid_device *hid) | |||
118 | return -1; | 367 | return -1; |
119 | } | 368 | } |
120 | 369 | ||
121 | for (i = 0; ff_bits[i] >= 0; i++) | 370 | /* Check what wheel has been connected */ |
122 | set_bit(ff_bits[i], dev->ffbit); | 371 | for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) { |
372 | if (hid->product == lg4ff_devices[i].product_id) { | ||
373 | dbg_hid("Found compatible device, product ID %04X\n", lg4ff_devices[i].product_id); | ||
374 | break; | ||
375 | } | ||
376 | } | ||
377 | |||
378 | if (i == ARRAY_SIZE(lg4ff_devices)) { | ||
379 | hid_err(hid, "Device is not supported by lg4ff driver. If you think it should be, consider reporting a bug to" | ||
380 | "LKML, Simon Wood <simon@mungewell.org> or Michal Maly <madcatxster@gmail.com>\n"); | ||
381 | return -1; | ||
382 | } | ||
383 | |||
384 | /* Attempt to switch wheel to native mode when applicable */ | ||
385 | udesc = &(hid_to_usb_dev(hid)->descriptor); | ||
386 | if (!udesc) { | ||
387 | hid_err(hid, "NULL USB device descriptor\n"); | ||
388 | return -1; | ||
389 | } | ||
390 | bcdDevice = le16_to_cpu(udesc->bcdDevice); | ||
391 | rev_maj = bcdDevice >> 8; | ||
392 | rev_min = bcdDevice & 0xff; | ||
393 | |||
394 | if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_WHEEL) { | ||
395 | dbg_hid("Generic wheel detected, can it do native?\n"); | ||
396 | dbg_hid("USB revision: %2x.%02x\n", rev_maj, rev_min); | ||
397 | |||
398 | for (j = 0; j < ARRAY_SIZE(lg4ff_revs); j++) { | ||
399 | if (lg4ff_revs[j].rev_maj == rev_maj && lg4ff_revs[j].rev_min == rev_min) { | ||
400 | hid_lg4ff_switch_native(hid, lg4ff_revs[j].command); | ||
401 | hid_info(hid, "Switched to native mode\n"); | ||
402 | } | ||
403 | } | ||
404 | } | ||
405 | |||
406 | /* Set supported force feedback capabilities */ | ||
407 | for (j = 0; lg4ff_devices[i].ff_effects[j] >= 0; j++) | ||
408 | set_bit(lg4ff_devices[i].ff_effects[j], dev->ffbit); | ||
123 | 409 | ||
124 | error = input_ff_create_memless(dev, NULL, hid_lg4ff_play); | 410 | error = input_ff_create_memless(dev, NULL, hid_lg4ff_play); |
125 | 411 | ||
126 | if (error) | 412 | if (error) |
127 | return error; | 413 | return error; |
128 | 414 | ||
129 | if (test_bit(FF_AUTOCENTER, dev->ffbit)) | 415 | /* Check if autocentering is available and |
130 | dev->ff->set_autocenter = hid_lg4ff_set_autocenter; | 416 | * set the centering force to zero by default */ |
417 | if (test_bit(FF_AUTOCENTER, dev->ffbit)) { | ||
418 | if(rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN) /* Formula Force EX expects different autocentering command */ | ||
419 | dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex; | ||
420 | else | ||
421 | dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default; | ||
422 | |||
423 | dev->ff->set_autocenter(dev, 0); | ||
424 | } | ||
425 | |||
426 | /* Initialize device_list if this is the first device to handle by lg4ff */ | ||
427 | if (!list_inited) { | ||
428 | INIT_LIST_HEAD(&device_list.list); | ||
429 | list_inited = 1; | ||
430 | } | ||
431 | |||
432 | /* Add the device to device_list */ | ||
433 | entry = (struct lg4ff_device_entry *)kzalloc(sizeof(struct lg4ff_device_entry), GFP_KERNEL); | ||
434 | if (!entry) { | ||
435 | hid_err(hid, "Cannot add device, insufficient memory.\n"); | ||
436 | return -ENOMEM; | ||
437 | } | ||
438 | entry->device_id = kstrdup((&hid->dev)->kobj.name, GFP_KERNEL); | ||
439 | if (!entry->device_id) { | ||
440 | hid_err(hid, "Cannot set device_id, insufficient memory.\n"); | ||
441 | kfree(entry); | ||
442 | return -ENOMEM; | ||
443 | } | ||
444 | entry->min_range = lg4ff_devices[i].min_range; | ||
445 | entry->max_range = lg4ff_devices[i].max_range; | ||
446 | entry->set_range = lg4ff_devices[i].set_range; | ||
447 | list_add(&entry->list, &device_list.list); | ||
448 | |||
449 | /* Create sysfs interface */ | ||
450 | error = device_create_file(&hid->dev, &dev_attr_range); | ||
451 | if (error) | ||
452 | return error; | ||
453 | dbg_hid("sysfs interface created\n"); | ||
454 | |||
455 | /* Set the maximum range to start with */ | ||
456 | entry->range = entry->max_range; | ||
457 | if (entry->set_range != NULL) | ||
458 | entry->set_range(hid, entry->range); | ||
131 | 459 | ||
132 | hid_info(hid, "Force feedback for Logitech Speed Force Wireless by Simon Wood <simon@mungewell.org>\n"); | 460 | hid_info(hid, "Force feedback for Logitech Speed Force Wireless by Simon Wood <simon@mungewell.org>\n"); |
133 | return 0; | 461 | return 0; |
134 | } | 462 | } |
135 | 463 | ||
464 | int lg4ff_deinit(struct hid_device *hid) | ||
465 | { | ||
466 | bool found = 0; | ||
467 | struct lg4ff_device_entry *entry; | ||
468 | struct list_head *h, *g; | ||
469 | list_for_each_safe(h, g, &device_list.list) { | ||
470 | entry = list_entry(h, struct lg4ff_device_entry, list); | ||
471 | if (strcmp(entry->device_id, (&hid->dev)->kobj.name) == 0) { | ||
472 | list_del(h); | ||
473 | kfree(entry->device_id); | ||
474 | kfree(entry); | ||
475 | found = 1; | ||
476 | break; | ||
477 | } | ||
478 | } | ||
479 | |||
480 | if (!found) { | ||
481 | dbg_hid("Device entry not found!\n"); | ||
482 | return -1; | ||
483 | } | ||
484 | |||
485 | device_remove_file(&hid->dev, &dev_attr_range); | ||
486 | dbg_hid("Device successfully unregistered\n"); | ||
487 | return 0; | ||
488 | } | ||
diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c index 088f85049290..27bc54f92f44 100644 --- a/drivers/hid/hid-lgff.c +++ b/drivers/hid/hid-lgff.c | |||
@@ -58,12 +58,6 @@ static const signed short ff_joystick_ac[] = { | |||
58 | -1 | 58 | -1 |
59 | }; | 59 | }; |
60 | 60 | ||
61 | static const signed short ff_wheel[] = { | ||
62 | FF_CONSTANT, | ||
63 | FF_AUTOCENTER, | ||
64 | -1 | ||
65 | }; | ||
66 | |||
67 | static const struct dev_type devices[] = { | 61 | static const struct dev_type devices[] = { |
68 | { 0x046d, 0xc211, ff_rumble }, | 62 | { 0x046d, 0xc211, ff_rumble }, |
69 | { 0x046d, 0xc219, ff_rumble }, | 63 | { 0x046d, 0xc219, ff_rumble }, |
@@ -71,14 +65,7 @@ static const struct dev_type devices[] = { | |||
71 | { 0x046d, 0xc286, ff_joystick_ac }, | 65 | { 0x046d, 0xc286, ff_joystick_ac }, |
72 | { 0x046d, 0xc287, ff_joystick_ac }, | 66 | { 0x046d, 0xc287, ff_joystick_ac }, |
73 | { 0x046d, 0xc293, ff_joystick }, | 67 | { 0x046d, 0xc293, ff_joystick }, |
74 | { 0x046d, 0xc294, ff_wheel }, | ||
75 | { 0x046d, 0xc298, ff_wheel }, | ||
76 | { 0x046d, 0xc299, ff_wheel }, | ||
77 | { 0x046d, 0xc29b, ff_wheel }, | ||
78 | { 0x046d, 0xc295, ff_joystick }, | 68 | { 0x046d, 0xc295, ff_joystick }, |
79 | { 0x046d, 0xc298, ff_wheel }, | ||
80 | { 0x046d, 0xc299, ff_wheel }, | ||
81 | { 0x046d, 0xca03, ff_wheel }, | ||
82 | }; | 69 | }; |
83 | 70 | ||
84 | static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect) | 71 | static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect) |
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c new file mode 100644 index 000000000000..38b12e45780c --- /dev/null +++ b/drivers/hid/hid-logitech-dj.c | |||
@@ -0,0 +1,922 @@ | |||
1 | /* | ||
2 | * HID driver for Logitech Unifying receivers | ||
3 | * | ||
4 | * Copyright (c) 2011 Logitech | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | |||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | |||
25 | #include <linux/device.h> | ||
26 | #include <linux/hid.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/usb.h> | ||
29 | #include "usbhid/usbhid.h" | ||
30 | #include "hid-ids.h" | ||
31 | #include "hid-logitech-dj.h" | ||
32 | |||
33 | /* Keyboard descriptor (1) */ | ||
34 | static const char kbd_descriptor[] = { | ||
35 | 0x05, 0x01, /* USAGE_PAGE (generic Desktop) */ | ||
36 | 0x09, 0x06, /* USAGE (Keyboard) */ | ||
37 | 0xA1, 0x01, /* COLLECTION (Application) */ | ||
38 | 0x85, 0x01, /* REPORT_ID (1) */ | ||
39 | 0x95, 0x08, /* REPORT_COUNT (8) */ | ||
40 | 0x75, 0x01, /* REPORT_SIZE (1) */ | ||
41 | 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ | ||
42 | 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ | ||
43 | 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ | ||
44 | 0x19, 0xE0, /* USAGE_MINIMUM (Left Control) */ | ||
45 | 0x29, 0xE7, /* USAGE_MAXIMUM (Right GUI) */ | ||
46 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ | ||
47 | 0x95, 0x05, /* REPORT COUNT (5) */ | ||
48 | 0x05, 0x08, /* USAGE PAGE (LED page) */ | ||
49 | 0x19, 0x01, /* USAGE MINIMUM (1) */ | ||
50 | 0x29, 0x05, /* USAGE MAXIMUM (5) */ | ||
51 | 0x91, 0x02, /* OUTPUT (Data, Variable, Absolute) */ | ||
52 | 0x95, 0x01, /* REPORT COUNT (1) */ | ||
53 | 0x75, 0x03, /* REPORT SIZE (3) */ | ||
54 | 0x91, 0x01, /* OUTPUT (Constant) */ | ||
55 | 0x95, 0x06, /* REPORT_COUNT (6) */ | ||
56 | 0x75, 0x08, /* REPORT_SIZE (8) */ | ||
57 | 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ | ||
58 | 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */ | ||
59 | 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ | ||
60 | 0x19, 0x00, /* USAGE_MINIMUM (no event) */ | ||
61 | 0x2A, 0xFF, 0x00, /* USAGE_MAXIMUM (reserved) */ | ||
62 | 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ | ||
63 | 0xC0 | ||
64 | }; | ||
65 | |||
66 | /* Mouse descriptor (2) */ | ||
67 | static const char mse_descriptor[] = { | ||
68 | 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ | ||
69 | 0x09, 0x02, /* USAGE (Mouse) */ | ||
70 | 0xA1, 0x01, /* COLLECTION (Application) */ | ||
71 | 0x85, 0x02, /* REPORT_ID = 2 */ | ||
72 | 0x09, 0x01, /* USAGE (pointer) */ | ||
73 | 0xA1, 0x00, /* COLLECTION (physical) */ | ||
74 | 0x05, 0x09, /* USAGE_PAGE (buttons) */ | ||
75 | 0x19, 0x01, /* USAGE_MIN (1) */ | ||
76 | 0x29, 0x10, /* USAGE_MAX (16) */ | ||
77 | 0x15, 0x00, /* LOGICAL_MIN (0) */ | ||
78 | 0x25, 0x01, /* LOGICAL_MAX (1) */ | ||
79 | 0x95, 0x10, /* REPORT_COUNT (16) */ | ||
80 | 0x75, 0x01, /* REPORT_SIZE (1) */ | ||
81 | 0x81, 0x02, /* INPUT (data var abs) */ | ||
82 | 0x05, 0x01, /* USAGE_PAGE (generic desktop) */ | ||
83 | 0x16, 0x01, 0xF8, /* LOGICAL_MIN (-2047) */ | ||
84 | 0x26, 0xFF, 0x07, /* LOGICAL_MAX (2047) */ | ||
85 | 0x75, 0x0C, /* REPORT_SIZE (12) */ | ||
86 | 0x95, 0x02, /* REPORT_COUNT (2) */ | ||
87 | 0x09, 0x30, /* USAGE (X) */ | ||
88 | 0x09, 0x31, /* USAGE (Y) */ | ||
89 | 0x81, 0x06, /* INPUT */ | ||
90 | 0x15, 0x81, /* LOGICAL_MIN (-127) */ | ||
91 | 0x25, 0x7F, /* LOGICAL_MAX (127) */ | ||
92 | 0x75, 0x08, /* REPORT_SIZE (8) */ | ||
93 | 0x95, 0x01, /* REPORT_COUNT (1) */ | ||
94 | 0x09, 0x38, /* USAGE (wheel) */ | ||
95 | 0x81, 0x06, /* INPUT */ | ||
96 | 0x05, 0x0C, /* USAGE_PAGE(consumer) */ | ||
97 | 0x0A, 0x38, 0x02, /* USAGE(AC Pan) */ | ||
98 | 0x95, 0x01, /* REPORT_COUNT (1) */ | ||
99 | 0x81, 0x06, /* INPUT */ | ||
100 | 0xC0, /* END_COLLECTION */ | ||
101 | 0xC0, /* END_COLLECTION */ | ||
102 | }; | ||
103 | |||
104 | /* Consumer Control descriptor (3) */ | ||
105 | static const char consumer_descriptor[] = { | ||
106 | 0x05, 0x0C, /* USAGE_PAGE (Consumer Devices) */ | ||
107 | 0x09, 0x01, /* USAGE (Consumer Control) */ | ||
108 | 0xA1, 0x01, /* COLLECTION (Application) */ | ||
109 | 0x85, 0x03, /* REPORT_ID = 3 */ | ||
110 | 0x75, 0x10, /* REPORT_SIZE (16) */ | ||
111 | 0x95, 0x02, /* REPORT_COUNT (2) */ | ||
112 | 0x15, 0x01, /* LOGICAL_MIN (1) */ | ||
113 | 0x26, 0x8C, 0x02, /* LOGICAL_MAX (652) */ | ||
114 | 0x19, 0x01, /* USAGE_MIN (1) */ | ||
115 | 0x2A, 0x8C, 0x02, /* USAGE_MAX (652) */ | ||
116 | 0x81, 0x00, /* INPUT (Data Ary Abs) */ | ||
117 | 0xC0, /* END_COLLECTION */ | ||
118 | }; /* */ | ||
119 | |||
120 | /* System control descriptor (4) */ | ||
121 | static const char syscontrol_descriptor[] = { | ||
122 | 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ | ||
123 | 0x09, 0x80, /* USAGE (System Control) */ | ||
124 | 0xA1, 0x01, /* COLLECTION (Application) */ | ||
125 | 0x85, 0x04, /* REPORT_ID = 4 */ | ||
126 | 0x75, 0x02, /* REPORT_SIZE (2) */ | ||
127 | 0x95, 0x01, /* REPORT_COUNT (1) */ | ||
128 | 0x15, 0x01, /* LOGICAL_MIN (1) */ | ||
129 | 0x25, 0x03, /* LOGICAL_MAX (3) */ | ||
130 | 0x09, 0x82, /* USAGE (System Sleep) */ | ||
131 | 0x09, 0x81, /* USAGE (System Power Down) */ | ||
132 | 0x09, 0x83, /* USAGE (System Wake Up) */ | ||
133 | 0x81, 0x60, /* INPUT (Data Ary Abs NPrf Null) */ | ||
134 | 0x75, 0x06, /* REPORT_SIZE (6) */ | ||
135 | 0x81, 0x03, /* INPUT (Cnst Var Abs) */ | ||
136 | 0xC0, /* END_COLLECTION */ | ||
137 | }; | ||
138 | |||
139 | /* Media descriptor (8) */ | ||
140 | static const char media_descriptor[] = { | ||
141 | 0x06, 0xbc, 0xff, /* Usage Page 0xffbc */ | ||
142 | 0x09, 0x88, /* Usage 0x0088 */ | ||
143 | 0xa1, 0x01, /* BeginCollection */ | ||
144 | 0x85, 0x08, /* Report ID 8 */ | ||
145 | 0x19, 0x01, /* Usage Min 0x0001 */ | ||
146 | 0x29, 0xff, /* Usage Max 0x00ff */ | ||
147 | 0x15, 0x01, /* Logical Min 1 */ | ||
148 | 0x26, 0xff, 0x00, /* Logical Max 255 */ | ||
149 | 0x75, 0x08, /* Report Size 8 */ | ||
150 | 0x95, 0x01, /* Report Count 1 */ | ||
151 | 0x81, 0x00, /* Input */ | ||
152 | 0xc0, /* EndCollection */ | ||
153 | }; /* */ | ||
154 | |||
155 | /* Maximum size of all defined hid reports in bytes (including report id) */ | ||
156 | #define MAX_REPORT_SIZE 8 | ||
157 | |||
158 | /* Number of possible hid report types that can be created by this driver. | ||
159 | * | ||
160 | * Right now, RF report types have the same report types (or report id's) | ||
161 | * than the hid report created from those RF reports. In the future | ||
162 | * this doesnt have to be true. | ||
163 | * | ||
164 | * For instance, RF report type 0x01 which has a size of 8 bytes, corresponds | ||
165 | * to hid report id 0x01, this is standard keyboard. Same thing applies to mice | ||
166 | * reports and consumer control, etc. If a new RF report is created, it doesn't | ||
167 | * has to have the same report id as its corresponding hid report, so an | ||
168 | * translation may have to take place for future report types. | ||
169 | */ | ||
170 | #define NUMBER_OF_HID_REPORTS 32 | ||
171 | static const u8 hid_reportid_size_map[NUMBER_OF_HID_REPORTS] = { | ||
172 | [1] = 8, /* Standard keyboard */ | ||
173 | [2] = 8, /* Standard mouse */ | ||
174 | [3] = 5, /* Consumer control */ | ||
175 | [4] = 2, /* System control */ | ||
176 | [8] = 2, /* Media Center */ | ||
177 | }; | ||
178 | |||
179 | |||
180 | #define LOGITECH_DJ_INTERFACE_NUMBER 0x02 | ||
181 | |||
182 | static struct hid_ll_driver logi_dj_ll_driver; | ||
183 | |||
184 | static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, | ||
185 | size_t count, | ||
186 | unsigned char report_type); | ||
187 | |||
188 | static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, | ||
189 | struct dj_report *dj_report) | ||
190 | { | ||
191 | /* Called in delayed work context */ | ||
192 | struct dj_device *dj_dev; | ||
193 | unsigned long flags; | ||
194 | |||
195 | spin_lock_irqsave(&djrcv_dev->lock, flags); | ||
196 | dj_dev = djrcv_dev->paired_dj_devices[dj_report->device_index]; | ||
197 | djrcv_dev->paired_dj_devices[dj_report->device_index] = NULL; | ||
198 | spin_unlock_irqrestore(&djrcv_dev->lock, flags); | ||
199 | |||
200 | if (dj_dev != NULL) { | ||
201 | hid_destroy_device(dj_dev->hdev); | ||
202 | kfree(dj_dev); | ||
203 | } else { | ||
204 | dev_err(&djrcv_dev->hdev->dev, "%s: can't destroy a NULL device\n", | ||
205 | __func__); | ||
206 | } | ||
207 | } | ||
208 | |||
209 | static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, | ||
210 | struct dj_report *dj_report) | ||
211 | { | ||
212 | /* Called in delayed work context */ | ||
213 | struct hid_device *djrcv_hdev = djrcv_dev->hdev; | ||
214 | struct usb_interface *intf = to_usb_interface(djrcv_hdev->dev.parent); | ||
215 | struct usb_device *usbdev = interface_to_usbdev(intf); | ||
216 | struct hid_device *dj_hiddev; | ||
217 | struct dj_device *dj_dev; | ||
218 | |||
219 | /* Device index goes from 1 to 6, we need 3 bytes to store the | ||
220 | * semicolon, the index, and a null terminator | ||
221 | */ | ||
222 | unsigned char tmpstr[3]; | ||
223 | |||
224 | if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] & | ||
225 | SPFUNCTION_DEVICE_LIST_EMPTY) { | ||
226 | dbg_hid("%s: device list is empty\n", __func__); | ||
227 | return; | ||
228 | } | ||
229 | |||
230 | if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) || | ||
231 | (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) { | ||
232 | dev_err(&djrcv_hdev->dev, "%s: invalid device index:%d\n", | ||
233 | __func__, dj_report->device_index); | ||
234 | return; | ||
235 | } | ||
236 | |||
237 | dj_hiddev = hid_allocate_device(); | ||
238 | if (IS_ERR(dj_hiddev)) { | ||
239 | dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n", | ||
240 | __func__); | ||
241 | return; | ||
242 | } | ||
243 | |||
244 | dj_hiddev->ll_driver = &logi_dj_ll_driver; | ||
245 | dj_hiddev->hid_output_raw_report = logi_dj_output_hidraw_report; | ||
246 | |||
247 | dj_hiddev->dev.parent = &djrcv_hdev->dev; | ||
248 | dj_hiddev->bus = BUS_USB; | ||
249 | dj_hiddev->vendor = le16_to_cpu(usbdev->descriptor.idVendor); | ||
250 | dj_hiddev->product = le16_to_cpu(usbdev->descriptor.idProduct); | ||
251 | snprintf(dj_hiddev->name, sizeof(dj_hiddev->name), | ||
252 | "Logitech Unifying Device. Wireless PID:%02x%02x", | ||
253 | dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB], | ||
254 | dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_LSB]); | ||
255 | |||
256 | usb_make_path(usbdev, dj_hiddev->phys, sizeof(dj_hiddev->phys)); | ||
257 | snprintf(tmpstr, sizeof(tmpstr), ":%d", dj_report->device_index); | ||
258 | strlcat(dj_hiddev->phys, tmpstr, sizeof(dj_hiddev->phys)); | ||
259 | |||
260 | dj_dev = kzalloc(sizeof(struct dj_device), GFP_KERNEL); | ||
261 | |||
262 | if (!dj_dev) { | ||
263 | dev_err(&djrcv_hdev->dev, "%s: failed allocating dj_device\n", | ||
264 | __func__); | ||
265 | goto dj_device_allocate_fail; | ||
266 | } | ||
267 | |||
268 | dj_dev->reports_supported = le32_to_cpu( | ||
269 | dj_report->report_params[DEVICE_PAIRED_RF_REPORT_TYPE]); | ||
270 | dj_dev->hdev = dj_hiddev; | ||
271 | dj_dev->dj_receiver_dev = djrcv_dev; | ||
272 | dj_dev->device_index = dj_report->device_index; | ||
273 | dj_hiddev->driver_data = dj_dev; | ||
274 | |||
275 | djrcv_dev->paired_dj_devices[dj_report->device_index] = dj_dev; | ||
276 | |||
277 | if (hid_add_device(dj_hiddev)) { | ||
278 | dev_err(&djrcv_hdev->dev, "%s: failed adding dj_device\n", | ||
279 | __func__); | ||
280 | goto hid_add_device_fail; | ||
281 | } | ||
282 | |||
283 | return; | ||
284 | |||
285 | hid_add_device_fail: | ||
286 | djrcv_dev->paired_dj_devices[dj_report->device_index] = NULL; | ||
287 | kfree(dj_dev); | ||
288 | dj_device_allocate_fail: | ||
289 | hid_destroy_device(dj_hiddev); | ||
290 | } | ||
291 | |||
292 | static void delayedwork_callback(struct work_struct *work) | ||
293 | { | ||
294 | struct dj_receiver_dev *djrcv_dev = | ||
295 | container_of(work, struct dj_receiver_dev, work); | ||
296 | |||
297 | struct dj_report dj_report; | ||
298 | unsigned long flags; | ||
299 | int count; | ||
300 | |||
301 | dbg_hid("%s\n", __func__); | ||
302 | |||
303 | spin_lock_irqsave(&djrcv_dev->lock, flags); | ||
304 | |||
305 | count = kfifo_out(&djrcv_dev->notif_fifo, &dj_report, | ||
306 | sizeof(struct dj_report)); | ||
307 | |||
308 | if (count != sizeof(struct dj_report)) { | ||
309 | dev_err(&djrcv_dev->hdev->dev, "%s: workitem triggered without " | ||
310 | "notifications available\n", __func__); | ||
311 | spin_unlock_irqrestore(&djrcv_dev->lock, flags); | ||
312 | return; | ||
313 | } | ||
314 | |||
315 | if (!kfifo_is_empty(&djrcv_dev->notif_fifo)) { | ||
316 | if (schedule_work(&djrcv_dev->work) == 0) { | ||
317 | dbg_hid("%s: did not schedule the work item, was " | ||
318 | "already queued\n", __func__); | ||
319 | } | ||
320 | } | ||
321 | |||
322 | spin_unlock_irqrestore(&djrcv_dev->lock, flags); | ||
323 | |||
324 | switch (dj_report.report_type) { | ||
325 | case REPORT_TYPE_NOTIF_DEVICE_PAIRED: | ||
326 | logi_dj_recv_add_djhid_device(djrcv_dev, &dj_report); | ||
327 | break; | ||
328 | case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED: | ||
329 | logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report); | ||
330 | break; | ||
331 | default: | ||
332 | dbg_hid("%s: unexpected report type\n", __func__); | ||
333 | } | ||
334 | } | ||
335 | |||
336 | static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev, | ||
337 | struct dj_report *dj_report) | ||
338 | { | ||
339 | /* We are called from atomic context (tasklet && djrcv->lock held) */ | ||
340 | |||
341 | kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); | ||
342 | |||
343 | if (schedule_work(&djrcv_dev->work) == 0) { | ||
344 | dbg_hid("%s: did not schedule the work item, was already " | ||
345 | "queued\n", __func__); | ||
346 | } | ||
347 | } | ||
348 | |||
349 | static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev, | ||
350 | struct dj_report *dj_report) | ||
351 | { | ||
352 | /* We are called from atomic context (tasklet && djrcv->lock held) */ | ||
353 | unsigned int i; | ||
354 | u8 reportbuffer[MAX_REPORT_SIZE]; | ||
355 | struct dj_device *djdev; | ||
356 | |||
357 | djdev = djrcv_dev->paired_dj_devices[dj_report->device_index]; | ||
358 | |||
359 | if (!djdev) { | ||
360 | dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" | ||
361 | " is NULL, index %d\n", dj_report->device_index); | ||
362 | return; | ||
363 | } | ||
364 | |||
365 | memset(reportbuffer, 0, sizeof(reportbuffer)); | ||
366 | |||
367 | for (i = 0; i < NUMBER_OF_HID_REPORTS; i++) { | ||
368 | if (djdev->reports_supported & (1 << i)) { | ||
369 | reportbuffer[0] = i; | ||
370 | if (hid_input_report(djdev->hdev, | ||
371 | HID_INPUT_REPORT, | ||
372 | reportbuffer, | ||
373 | hid_reportid_size_map[i], 1)) { | ||
374 | dbg_hid("hid_input_report error sending null " | ||
375 | "report\n"); | ||
376 | } | ||
377 | } | ||
378 | } | ||
379 | } | ||
380 | |||
381 | static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev, | ||
382 | struct dj_report *dj_report) | ||
383 | { | ||
384 | /* We are called from atomic context (tasklet && djrcv->lock held) */ | ||
385 | struct dj_device *dj_device; | ||
386 | |||
387 | dj_device = djrcv_dev->paired_dj_devices[dj_report->device_index]; | ||
388 | |||
389 | if (dj_device == NULL) { | ||
390 | dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" | ||
391 | " is NULL, index %d\n", dj_report->device_index); | ||
392 | return; | ||
393 | } | ||
394 | |||
395 | if ((dj_report->report_type > ARRAY_SIZE(hid_reportid_size_map) - 1) || | ||
396 | (hid_reportid_size_map[dj_report->report_type] == 0)) { | ||
397 | dbg_hid("invalid report type:%x\n", dj_report->report_type); | ||
398 | return; | ||
399 | } | ||
400 | |||
401 | if (hid_input_report(dj_device->hdev, | ||
402 | HID_INPUT_REPORT, &dj_report->report_type, | ||
403 | hid_reportid_size_map[dj_report->report_type], 1)) { | ||
404 | dbg_hid("hid_input_report error\n"); | ||
405 | } | ||
406 | } | ||
407 | |||
408 | |||
409 | static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, | ||
410 | struct dj_report *dj_report) | ||
411 | { | ||
412 | struct hid_device *hdev = djrcv_dev->hdev; | ||
413 | int sent_bytes; | ||
414 | |||
415 | if (!hdev->hid_output_raw_report) { | ||
416 | dev_err(&hdev->dev, "%s:" | ||
417 | "hid_output_raw_report is null\n", __func__); | ||
418 | return -ENODEV; | ||
419 | } | ||
420 | |||
421 | sent_bytes = hdev->hid_output_raw_report(hdev, (u8 *) dj_report, | ||
422 | sizeof(struct dj_report), | ||
423 | HID_OUTPUT_REPORT); | ||
424 | |||
425 | return (sent_bytes < 0) ? sent_bytes : 0; | ||
426 | } | ||
427 | |||
428 | static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) | ||
429 | { | ||
430 | struct dj_report dj_report; | ||
431 | |||
432 | memset(&dj_report, 0, sizeof(dj_report)); | ||
433 | dj_report.report_id = REPORT_ID_DJ_SHORT; | ||
434 | dj_report.device_index = 0xFF; | ||
435 | dj_report.report_type = REPORT_TYPE_CMD_GET_PAIRED_DEVICES; | ||
436 | return logi_dj_recv_send_report(djrcv_dev, &dj_report); | ||
437 | } | ||
438 | |||
439 | static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, | ||
440 | unsigned timeout) | ||
441 | { | ||
442 | struct dj_report dj_report; | ||
443 | |||
444 | memset(&dj_report, 0, sizeof(dj_report)); | ||
445 | dj_report.report_id = REPORT_ID_DJ_SHORT; | ||
446 | dj_report.device_index = 0xFF; | ||
447 | dj_report.report_type = REPORT_TYPE_CMD_SWITCH; | ||
448 | dj_report.report_params[CMD_SWITCH_PARAM_DEVBITFIELD] = 0x1F; | ||
449 | dj_report.report_params[CMD_SWITCH_PARAM_TIMEOUT_SECONDS] = (u8)timeout; | ||
450 | return logi_dj_recv_send_report(djrcv_dev, &dj_report); | ||
451 | } | ||
452 | |||
453 | |||
454 | static int logi_dj_ll_open(struct hid_device *hid) | ||
455 | { | ||
456 | dbg_hid("%s:%s\n", __func__, hid->phys); | ||
457 | return 0; | ||
458 | |||
459 | } | ||
460 | |||
461 | static void logi_dj_ll_close(struct hid_device *hid) | ||
462 | { | ||
463 | dbg_hid("%s:%s\n", __func__, hid->phys); | ||
464 | } | ||
465 | |||
466 | static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, | ||
467 | size_t count, | ||
468 | unsigned char report_type) | ||
469 | { | ||
470 | /* Called by hid raw to send data */ | ||
471 | dbg_hid("%s\n", __func__); | ||
472 | |||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | static int logi_dj_ll_parse(struct hid_device *hid) | ||
477 | { | ||
478 | struct dj_device *djdev = hid->driver_data; | ||
479 | int retval; | ||
480 | |||
481 | dbg_hid("%s\n", __func__); | ||
482 | |||
483 | djdev->hdev->version = 0x0111; | ||
484 | djdev->hdev->country = 0x00; | ||
485 | |||
486 | if (djdev->reports_supported & STD_KEYBOARD) { | ||
487 | dbg_hid("%s: sending a kbd descriptor, reports_supported: %x\n", | ||
488 | __func__, djdev->reports_supported); | ||
489 | retval = hid_parse_report(hid, | ||
490 | (u8 *) kbd_descriptor, | ||
491 | sizeof(kbd_descriptor)); | ||
492 | if (retval) { | ||
493 | dbg_hid("%s: sending a kbd descriptor, hid_parse failed" | ||
494 | " error: %d\n", __func__, retval); | ||
495 | return retval; | ||
496 | } | ||
497 | } | ||
498 | |||
499 | if (djdev->reports_supported & STD_MOUSE) { | ||
500 | dbg_hid("%s: sending a mouse descriptor, reports_supported: " | ||
501 | "%x\n", __func__, djdev->reports_supported); | ||
502 | retval = hid_parse_report(hid, | ||
503 | (u8 *) mse_descriptor, | ||
504 | sizeof(mse_descriptor)); | ||
505 | if (retval) { | ||
506 | dbg_hid("%s: sending a mouse descriptor, hid_parse " | ||
507 | "failed error: %d\n", __func__, retval); | ||
508 | return retval; | ||
509 | } | ||
510 | } | ||
511 | |||
512 | if (djdev->reports_supported & MULTIMEDIA) { | ||
513 | dbg_hid("%s: sending a multimedia report descriptor: %x\n", | ||
514 | __func__, djdev->reports_supported); | ||
515 | retval = hid_parse_report(hid, | ||
516 | (u8 *) consumer_descriptor, | ||
517 | sizeof(consumer_descriptor)); | ||
518 | if (retval) { | ||
519 | dbg_hid("%s: sending a consumer_descriptor, hid_parse " | ||
520 | "failed error: %d\n", __func__, retval); | ||
521 | return retval; | ||
522 | } | ||
523 | } | ||
524 | |||
525 | if (djdev->reports_supported & POWER_KEYS) { | ||
526 | dbg_hid("%s: sending a power keys report descriptor: %x\n", | ||
527 | __func__, djdev->reports_supported); | ||
528 | retval = hid_parse_report(hid, | ||
529 | (u8 *) syscontrol_descriptor, | ||
530 | sizeof(syscontrol_descriptor)); | ||
531 | if (retval) { | ||
532 | dbg_hid("%s: sending a syscontrol_descriptor, " | ||
533 | "hid_parse failed error: %d\n", | ||
534 | __func__, retval); | ||
535 | return retval; | ||
536 | } | ||
537 | } | ||
538 | |||
539 | if (djdev->reports_supported & MEDIA_CENTER) { | ||
540 | dbg_hid("%s: sending a media center report descriptor: %x\n", | ||
541 | __func__, djdev->reports_supported); | ||
542 | retval = hid_parse_report(hid, | ||
543 | (u8 *) media_descriptor, | ||
544 | sizeof(media_descriptor)); | ||
545 | if (retval) { | ||
546 | dbg_hid("%s: sending a media_descriptor, hid_parse " | ||
547 | "failed error: %d\n", __func__, retval); | ||
548 | return retval; | ||
549 | } | ||
550 | } | ||
551 | |||
552 | if (djdev->reports_supported & KBD_LEDS) { | ||
553 | dbg_hid("%s: need to send kbd leds report descriptor: %x\n", | ||
554 | __func__, djdev->reports_supported); | ||
555 | } | ||
556 | |||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type, | ||
561 | unsigned int code, int value) | ||
562 | { | ||
563 | /* Sent by the input layer to handle leds and Force Feedback */ | ||
564 | struct hid_device *dj_hiddev = input_get_drvdata(dev); | ||
565 | struct dj_device *dj_dev = dj_hiddev->driver_data; | ||
566 | |||
567 | struct dj_receiver_dev *djrcv_dev = | ||
568 | dev_get_drvdata(dj_hiddev->dev.parent); | ||
569 | struct hid_device *dj_rcv_hiddev = djrcv_dev->hdev; | ||
570 | struct hid_report_enum *output_report_enum; | ||
571 | |||
572 | struct hid_field *field; | ||
573 | struct hid_report *report; | ||
574 | unsigned char data[8]; | ||
575 | int offset; | ||
576 | |||
577 | dbg_hid("%s: %s, type:%d | code:%d | value:%d\n", | ||
578 | __func__, dev->phys, type, code, value); | ||
579 | |||
580 | if (type != EV_LED) | ||
581 | return -1; | ||
582 | |||
583 | offset = hidinput_find_field(dj_hiddev, type, code, &field); | ||
584 | |||
585 | if (offset == -1) { | ||
586 | dev_warn(&dev->dev, "event field not found\n"); | ||
587 | return -1; | ||
588 | } | ||
589 | hid_set_field(field, offset, value); | ||
590 | hid_output_report(field->report, &data[0]); | ||
591 | |||
592 | output_report_enum = &dj_rcv_hiddev->report_enum[HID_OUTPUT_REPORT]; | ||
593 | report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; | ||
594 | hid_set_field(report->field[0], 0, dj_dev->device_index); | ||
595 | hid_set_field(report->field[0], 1, REPORT_TYPE_LEDS); | ||
596 | hid_set_field(report->field[0], 2, data[1]); | ||
597 | |||
598 | usbhid_submit_report(dj_rcv_hiddev, report, USB_DIR_OUT); | ||
599 | |||
600 | return 0; | ||
601 | |||
602 | } | ||
603 | |||
604 | static int logi_dj_ll_start(struct hid_device *hid) | ||
605 | { | ||
606 | dbg_hid("%s\n", __func__); | ||
607 | return 0; | ||
608 | } | ||
609 | |||
610 | static void logi_dj_ll_stop(struct hid_device *hid) | ||
611 | { | ||
612 | dbg_hid("%s\n", __func__); | ||
613 | } | ||
614 | |||
615 | |||
616 | static struct hid_ll_driver logi_dj_ll_driver = { | ||
617 | .parse = logi_dj_ll_parse, | ||
618 | .start = logi_dj_ll_start, | ||
619 | .stop = logi_dj_ll_stop, | ||
620 | .open = logi_dj_ll_open, | ||
621 | .close = logi_dj_ll_close, | ||
622 | .hidinput_input_event = logi_dj_ll_input_event, | ||
623 | }; | ||
624 | |||
625 | |||
626 | static int logi_dj_raw_event(struct hid_device *hdev, | ||
627 | struct hid_report *report, u8 *data, | ||
628 | int size) | ||
629 | { | ||
630 | struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); | ||
631 | struct dj_report *dj_report = (struct dj_report *) data; | ||
632 | unsigned long flags; | ||
633 | bool report_processed = false; | ||
634 | |||
635 | dbg_hid("%s, size:%d\n", __func__, size); | ||
636 | |||
637 | /* Here we receive all data coming from iface 2, there are 4 cases: | ||
638 | * | ||
639 | * 1) Data should continue its normal processing i.e. data does not | ||
640 | * come from the DJ collection, in which case we do nothing and | ||
641 | * return 0, so hid-core can continue normal processing (will forward | ||
642 | * to associated hidraw device) | ||
643 | * | ||
644 | * 2) Data is from DJ collection, and is intended for this driver i. e. | ||
645 | * data contains arrival, departure, etc notifications, in which case | ||
646 | * we queue them for delayed processing by the work queue. We return 1 | ||
647 | * to hid-core as no further processing is required from it. | ||
648 | * | ||
649 | * 3) Data is from DJ collection, and informs a connection change, | ||
650 | * if the change means rf link loss, then we must send a null report | ||
651 | * to the upper layer to discard potentially pressed keys that may be | ||
652 | * repeated forever by the input layer. Return 1 to hid-core as no | ||
653 | * further processing is required. | ||
654 | * | ||
655 | * 4) Data is from DJ collection and is an actual input event from | ||
656 | * a paired DJ device in which case we forward it to the correct hid | ||
657 | * device (via hid_input_report() ) and return 1 so hid-core does not do | ||
658 | * anything else with it. | ||
659 | */ | ||
660 | |||
661 | spin_lock_irqsave(&djrcv_dev->lock, flags); | ||
662 | if (dj_report->report_id == REPORT_ID_DJ_SHORT) { | ||
663 | switch (dj_report->report_type) { | ||
664 | case REPORT_TYPE_NOTIF_DEVICE_PAIRED: | ||
665 | case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED: | ||
666 | logi_dj_recv_queue_notification(djrcv_dev, dj_report); | ||
667 | break; | ||
668 | case REPORT_TYPE_NOTIF_CONNECTION_STATUS: | ||
669 | if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] == | ||
670 | STATUS_LINKLOSS) { | ||
671 | logi_dj_recv_forward_null_report(djrcv_dev, dj_report); | ||
672 | } | ||
673 | break; | ||
674 | default: | ||
675 | logi_dj_recv_forward_report(djrcv_dev, dj_report); | ||
676 | } | ||
677 | report_processed = true; | ||
678 | } | ||
679 | spin_unlock_irqrestore(&djrcv_dev->lock, flags); | ||
680 | |||
681 | return report_processed; | ||
682 | } | ||
683 | |||
684 | static int logi_dj_probe(struct hid_device *hdev, | ||
685 | const struct hid_device_id *id) | ||
686 | { | ||
687 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
688 | struct dj_receiver_dev *djrcv_dev; | ||
689 | int retval; | ||
690 | |||
691 | if (is_dj_device((struct dj_device *)hdev->driver_data)) | ||
692 | return -ENODEV; | ||
693 | |||
694 | dbg_hid("%s called for ifnum %d\n", __func__, | ||
695 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
696 | |||
697 | /* Ignore interfaces 0 and 1, they will not carry any data, dont create | ||
698 | * any hid_device for them */ | ||
699 | if (intf->cur_altsetting->desc.bInterfaceNumber != | ||
700 | LOGITECH_DJ_INTERFACE_NUMBER) { | ||
701 | dbg_hid("%s: ignoring ifnum %d\n", __func__, | ||
702 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
703 | return -ENODEV; | ||
704 | } | ||
705 | |||
706 | /* Treat interface 2 */ | ||
707 | |||
708 | djrcv_dev = kzalloc(sizeof(struct dj_receiver_dev), GFP_KERNEL); | ||
709 | if (!djrcv_dev) { | ||
710 | dev_err(&hdev->dev, | ||
711 | "%s:failed allocating dj_receiver_dev\n", __func__); | ||
712 | return -ENOMEM; | ||
713 | } | ||
714 | djrcv_dev->hdev = hdev; | ||
715 | INIT_WORK(&djrcv_dev->work, delayedwork_callback); | ||
716 | spin_lock_init(&djrcv_dev->lock); | ||
717 | if (kfifo_alloc(&djrcv_dev->notif_fifo, | ||
718 | DJ_MAX_NUMBER_NOTIFICATIONS * sizeof(struct dj_report), | ||
719 | GFP_KERNEL)) { | ||
720 | dev_err(&hdev->dev, | ||
721 | "%s:failed allocating notif_fifo\n", __func__); | ||
722 | kfree(djrcv_dev); | ||
723 | return -ENOMEM; | ||
724 | } | ||
725 | hid_set_drvdata(hdev, djrcv_dev); | ||
726 | |||
727 | /* Call to usbhid to fetch the HID descriptors of interface 2 and | ||
728 | * subsequently call to the hid/hid-core to parse the fetched | ||
729 | * descriptors, this will in turn create the hidraw and hiddev nodes | ||
730 | * for interface 2 of the receiver */ | ||
731 | retval = hid_parse(hdev); | ||
732 | if (retval) { | ||
733 | dev_err(&hdev->dev, | ||
734 | "%s:parse of interface 2 failed\n", __func__); | ||
735 | goto hid_parse_fail; | ||
736 | } | ||
737 | |||
738 | /* Starts the usb device and connects to upper interfaces hiddev and | ||
739 | * hidraw */ | ||
740 | retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
741 | if (retval) { | ||
742 | dev_err(&hdev->dev, | ||
743 | "%s:hid_hw_start returned error\n", __func__); | ||
744 | goto hid_hw_start_fail; | ||
745 | } | ||
746 | |||
747 | retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0); | ||
748 | if (retval < 0) { | ||
749 | dev_err(&hdev->dev, | ||
750 | "%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n", | ||
751 | __func__, retval); | ||
752 | goto switch_to_dj_mode_fail; | ||
753 | } | ||
754 | |||
755 | /* This is enabling the polling urb on the IN endpoint */ | ||
756 | retval = hdev->ll_driver->open(hdev); | ||
757 | if (retval < 0) { | ||
758 | dev_err(&hdev->dev, "%s:hdev->ll_driver->open returned " | ||
759 | "error:%d\n", __func__, retval); | ||
760 | goto llopen_failed; | ||
761 | } | ||
762 | |||
763 | retval = logi_dj_recv_query_paired_devices(djrcv_dev); | ||
764 | if (retval < 0) { | ||
765 | dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices " | ||
766 | "error:%d\n", __func__, retval); | ||
767 | goto logi_dj_recv_query_paired_devices_failed; | ||
768 | } | ||
769 | |||
770 | return retval; | ||
771 | |||
772 | logi_dj_recv_query_paired_devices_failed: | ||
773 | hdev->ll_driver->close(hdev); | ||
774 | |||
775 | llopen_failed: | ||
776 | switch_to_dj_mode_fail: | ||
777 | hid_hw_stop(hdev); | ||
778 | |||
779 | hid_hw_start_fail: | ||
780 | hid_parse_fail: | ||
781 | kfifo_free(&djrcv_dev->notif_fifo); | ||
782 | kfree(djrcv_dev); | ||
783 | hid_set_drvdata(hdev, NULL); | ||
784 | return retval; | ||
785 | |||
786 | } | ||
787 | |||
788 | #ifdef CONFIG_PM | ||
789 | static int logi_dj_reset_resume(struct hid_device *hdev) | ||
790 | { | ||
791 | int retval; | ||
792 | struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); | ||
793 | |||
794 | retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0); | ||
795 | if (retval < 0) { | ||
796 | dev_err(&hdev->dev, | ||
797 | "%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n", | ||
798 | __func__, retval); | ||
799 | } | ||
800 | |||
801 | return 0; | ||
802 | } | ||
803 | #endif | ||
804 | |||
805 | static void logi_dj_remove(struct hid_device *hdev) | ||
806 | { | ||
807 | struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); | ||
808 | struct dj_device *dj_dev; | ||
809 | int i; | ||
810 | |||
811 | dbg_hid("%s\n", __func__); | ||
812 | |||
813 | cancel_work_sync(&djrcv_dev->work); | ||
814 | |||
815 | hdev->ll_driver->close(hdev); | ||
816 | hid_hw_stop(hdev); | ||
817 | |||
818 | /* I suppose that at this point the only context that can access | ||
819 | * the djrecv_data is this thread as the work item is guaranteed to | ||
820 | * have finished and no more raw_event callbacks should arrive after | ||
821 | * the remove callback was triggered so no locks are put around the | ||
822 | * code below */ | ||
823 | for (i = 0; i < (DJ_MAX_PAIRED_DEVICES + DJ_DEVICE_INDEX_MIN); i++) { | ||
824 | dj_dev = djrcv_dev->paired_dj_devices[i]; | ||
825 | if (dj_dev != NULL) { | ||
826 | hid_destroy_device(dj_dev->hdev); | ||
827 | kfree(dj_dev); | ||
828 | djrcv_dev->paired_dj_devices[i] = NULL; | ||
829 | } | ||
830 | } | ||
831 | |||
832 | kfifo_free(&djrcv_dev->notif_fifo); | ||
833 | kfree(djrcv_dev); | ||
834 | hid_set_drvdata(hdev, NULL); | ||
835 | } | ||
836 | |||
837 | static int logi_djdevice_probe(struct hid_device *hdev, | ||
838 | const struct hid_device_id *id) | ||
839 | { | ||
840 | int ret; | ||
841 | struct dj_device *dj_dev = hdev->driver_data; | ||
842 | |||
843 | if (!is_dj_device(dj_dev)) | ||
844 | return -ENODEV; | ||
845 | |||
846 | ret = hid_parse(hdev); | ||
847 | if (!ret) | ||
848 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
849 | |||
850 | return ret; | ||
851 | } | ||
852 | |||
853 | static const struct hid_device_id logi_dj_receivers[] = { | ||
854 | {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, | ||
855 | USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)}, | ||
856 | {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, | ||
857 | USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2)}, | ||
858 | {} | ||
859 | }; | ||
860 | |||
861 | MODULE_DEVICE_TABLE(hid, logi_dj_receivers); | ||
862 | |||
863 | static struct hid_driver logi_djreceiver_driver = { | ||
864 | .name = "logitech-djreceiver", | ||
865 | .id_table = logi_dj_receivers, | ||
866 | .probe = logi_dj_probe, | ||
867 | .remove = logi_dj_remove, | ||
868 | .raw_event = logi_dj_raw_event, | ||
869 | #ifdef CONFIG_PM | ||
870 | .reset_resume = logi_dj_reset_resume, | ||
871 | #endif | ||
872 | }; | ||
873 | |||
874 | |||
875 | static const struct hid_device_id logi_dj_devices[] = { | ||
876 | {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, | ||
877 | USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)}, | ||
878 | {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, | ||
879 | USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2)}, | ||
880 | {} | ||
881 | }; | ||
882 | |||
883 | static struct hid_driver logi_djdevice_driver = { | ||
884 | .name = "logitech-djdevice", | ||
885 | .id_table = logi_dj_devices, | ||
886 | .probe = logi_djdevice_probe, | ||
887 | }; | ||
888 | |||
889 | |||
890 | static int __init logi_dj_init(void) | ||
891 | { | ||
892 | int retval; | ||
893 | |||
894 | dbg_hid("Logitech-DJ:%s\n", __func__); | ||
895 | |||
896 | retval = hid_register_driver(&logi_djreceiver_driver); | ||
897 | if (retval) | ||
898 | return retval; | ||
899 | |||
900 | retval = hid_register_driver(&logi_djdevice_driver); | ||
901 | if (retval) | ||
902 | hid_unregister_driver(&logi_djreceiver_driver); | ||
903 | |||
904 | return retval; | ||
905 | |||
906 | } | ||
907 | |||
908 | static void __exit logi_dj_exit(void) | ||
909 | { | ||
910 | dbg_hid("Logitech-DJ:%s\n", __func__); | ||
911 | |||
912 | hid_unregister_driver(&logi_djdevice_driver); | ||
913 | hid_unregister_driver(&logi_djreceiver_driver); | ||
914 | |||
915 | } | ||
916 | |||
917 | module_init(logi_dj_init); | ||
918 | module_exit(logi_dj_exit); | ||
919 | MODULE_LICENSE("GPL"); | ||
920 | MODULE_AUTHOR("Logitech"); | ||
921 | MODULE_AUTHOR("Nestor Lopez Casado"); | ||
922 | MODULE_AUTHOR("nlopezcasad@logitech.com"); | ||
diff --git a/drivers/hid/hid-logitech-dj.h b/drivers/hid/hid-logitech-dj.h new file mode 100644 index 000000000000..fd28a5e0ca3b --- /dev/null +++ b/drivers/hid/hid-logitech-dj.h | |||
@@ -0,0 +1,123 @@ | |||
1 | #ifndef __HID_LOGITECH_DJ_H | ||
2 | #define __HID_LOGITECH_DJ_H | ||
3 | |||
4 | /* | ||
5 | * HID driver for Logitech Unifying receivers | ||
6 | * | ||
7 | * Copyright (c) 2011 Logitech | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include <linux/kfifo.h> | ||
27 | |||
28 | #define DJ_MAX_PAIRED_DEVICES 6 | ||
29 | #define DJ_MAX_NUMBER_NOTIFICATIONS 8 | ||
30 | #define DJ_DEVICE_INDEX_MIN 1 | ||
31 | #define DJ_DEVICE_INDEX_MAX 6 | ||
32 | |||
33 | #define DJREPORT_SHORT_LENGTH 15 | ||
34 | #define DJREPORT_LONG_LENGTH 32 | ||
35 | |||
36 | #define REPORT_ID_DJ_SHORT 0x20 | ||
37 | #define REPORT_ID_DJ_LONG 0x21 | ||
38 | |||
39 | #define REPORT_TYPE_RFREPORT_FIRST 0x01 | ||
40 | #define REPORT_TYPE_RFREPORT_LAST 0x1F | ||
41 | |||
42 | /* Command Switch to DJ mode */ | ||
43 | #define REPORT_TYPE_CMD_SWITCH 0x80 | ||
44 | #define CMD_SWITCH_PARAM_DEVBITFIELD 0x00 | ||
45 | #define CMD_SWITCH_PARAM_TIMEOUT_SECONDS 0x01 | ||
46 | #define TIMEOUT_NO_KEEPALIVE 0x00 | ||
47 | |||
48 | /* Command to Get the list of Paired devices */ | ||
49 | #define REPORT_TYPE_CMD_GET_PAIRED_DEVICES 0x81 | ||
50 | |||
51 | /* Device Paired Notification */ | ||
52 | #define REPORT_TYPE_NOTIF_DEVICE_PAIRED 0x41 | ||
53 | #define SPFUNCTION_MORE_NOTIF_EXPECTED 0x01 | ||
54 | #define SPFUNCTION_DEVICE_LIST_EMPTY 0x02 | ||
55 | #define DEVICE_PAIRED_PARAM_SPFUNCTION 0x00 | ||
56 | #define DEVICE_PAIRED_PARAM_EQUAD_ID_LSB 0x01 | ||
57 | #define DEVICE_PAIRED_PARAM_EQUAD_ID_MSB 0x02 | ||
58 | #define DEVICE_PAIRED_RF_REPORT_TYPE 0x03 | ||
59 | |||
60 | /* Device Un-Paired Notification */ | ||
61 | #define REPORT_TYPE_NOTIF_DEVICE_UNPAIRED 0x40 | ||
62 | |||
63 | |||
64 | /* Connection Status Notification */ | ||
65 | #define REPORT_TYPE_NOTIF_CONNECTION_STATUS 0x42 | ||
66 | #define CONNECTION_STATUS_PARAM_STATUS 0x00 | ||
67 | #define STATUS_LINKLOSS 0x01 | ||
68 | |||
69 | /* Error Notification */ | ||
70 | #define REPORT_TYPE_NOTIF_ERROR 0x7F | ||
71 | #define NOTIF_ERROR_PARAM_ETYPE 0x00 | ||
72 | #define ETYPE_KEEPALIVE_TIMEOUT 0x01 | ||
73 | |||
74 | /* supported DJ HID && RF report types */ | ||
75 | #define REPORT_TYPE_KEYBOARD 0x01 | ||
76 | #define REPORT_TYPE_MOUSE 0x02 | ||
77 | #define REPORT_TYPE_CONSUMER_CONTROL 0x03 | ||
78 | #define REPORT_TYPE_SYSTEM_CONTROL 0x04 | ||
79 | #define REPORT_TYPE_MEDIA_CENTER 0x08 | ||
80 | #define REPORT_TYPE_LEDS 0x0E | ||
81 | |||
82 | /* RF Report types bitfield */ | ||
83 | #define STD_KEYBOARD 0x00000002 | ||
84 | #define STD_MOUSE 0x00000004 | ||
85 | #define MULTIMEDIA 0x00000008 | ||
86 | #define POWER_KEYS 0x00000010 | ||
87 | #define MEDIA_CENTER 0x00000100 | ||
88 | #define KBD_LEDS 0x00004000 | ||
89 | |||
90 | struct dj_report { | ||
91 | u8 report_id; | ||
92 | u8 device_index; | ||
93 | u8 report_type; | ||
94 | u8 report_params[DJREPORT_SHORT_LENGTH - 3]; | ||
95 | }; | ||
96 | |||
97 | struct dj_receiver_dev { | ||
98 | struct hid_device *hdev; | ||
99 | struct dj_device *paired_dj_devices[DJ_MAX_PAIRED_DEVICES + | ||
100 | DJ_DEVICE_INDEX_MIN]; | ||
101 | struct work_struct work; | ||
102 | struct kfifo notif_fifo; | ||
103 | spinlock_t lock; | ||
104 | }; | ||
105 | |||
106 | struct dj_device { | ||
107 | struct hid_device *hdev; | ||
108 | struct dj_receiver_dev *dj_receiver_dev; | ||
109 | u32 reports_supported; | ||
110 | u8 device_index; | ||
111 | }; | ||
112 | |||
113 | /** | ||
114 | * is_dj_device - know if the given dj_device is not the receiver. | ||
115 | * @dj_dev: the dj device to test | ||
116 | * | ||
117 | * This macro tests if a struct dj_device pointer is a device created | ||
118 | * by the bus enumarator. | ||
119 | */ | ||
120 | #define is_dj_device(dj_dev) \ | ||
121 | (&(dj_dev)->dj_receiver_dev->hdev->dev == (dj_dev)->hdev->dev.parent) | ||
122 | |||
123 | #endif | ||
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index 0ec91c18a421..2ab71758e2e2 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c | |||
@@ -81,6 +81,28 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie | |||
81 | #define NO_TOUCHES -1 | 81 | #define NO_TOUCHES -1 |
82 | #define SINGLE_TOUCH_UP -2 | 82 | #define SINGLE_TOUCH_UP -2 |
83 | 83 | ||
84 | /* Touch surface information. Dimension is in hundredths of a mm, min and max | ||
85 | * are in units. */ | ||
86 | #define MOUSE_DIMENSION_X (float)9056 | ||
87 | #define MOUSE_MIN_X -1100 | ||
88 | #define MOUSE_MAX_X 1258 | ||
89 | #define MOUSE_RES_X ((MOUSE_MAX_X - MOUSE_MIN_X) / (MOUSE_DIMENSION_X / 100)) | ||
90 | #define MOUSE_DIMENSION_Y (float)5152 | ||
91 | #define MOUSE_MIN_Y -1589 | ||
92 | #define MOUSE_MAX_Y 2047 | ||
93 | #define MOUSE_RES_Y ((MOUSE_MAX_Y - MOUSE_MIN_Y) / (MOUSE_DIMENSION_Y / 100)) | ||
94 | |||
95 | #define TRACKPAD_DIMENSION_X (float)13000 | ||
96 | #define TRACKPAD_MIN_X -2909 | ||
97 | #define TRACKPAD_MAX_X 3167 | ||
98 | #define TRACKPAD_RES_X \ | ||
99 | ((TRACKPAD_MAX_X - TRACKPAD_MIN_X) / (TRACKPAD_DIMENSION_X / 100)) | ||
100 | #define TRACKPAD_DIMENSION_Y (float)11000 | ||
101 | #define TRACKPAD_MIN_Y -2456 | ||
102 | #define TRACKPAD_MAX_Y 2565 | ||
103 | #define TRACKPAD_RES_Y \ | ||
104 | ((TRACKPAD_MAX_Y - TRACKPAD_MIN_Y) / (TRACKPAD_DIMENSION_Y / 100)) | ||
105 | |||
84 | /** | 106 | /** |
85 | * struct magicmouse_sc - Tracks Magic Mouse-specific data. | 107 | * struct magicmouse_sc - Tracks Magic Mouse-specific data. |
86 | * @input: Input device through which we report events. | 108 | * @input: Input device through which we report events. |
@@ -383,6 +405,13 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h | |||
383 | __set_bit(REL_HWHEEL, input->relbit); | 405 | __set_bit(REL_HWHEEL, input->relbit); |
384 | } | 406 | } |
385 | } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | 407 | } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ |
408 | /* input->keybit is initialized with incorrect button info | ||
409 | * for Magic Trackpad. There really is only one physical | ||
410 | * button (BTN_LEFT == BTN_MOUSE). Make sure we don't | ||
411 | * advertise buttons that don't exist... | ||
412 | */ | ||
413 | __clear_bit(BTN_RIGHT, input->keybit); | ||
414 | __clear_bit(BTN_MIDDLE, input->keybit); | ||
386 | __set_bit(BTN_MOUSE, input->keybit); | 415 | __set_bit(BTN_MOUSE, input->keybit); |
387 | __set_bit(BTN_TOOL_FINGER, input->keybit); | 416 | __set_bit(BTN_TOOL_FINGER, input->keybit); |
388 | __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); | 417 | __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); |
@@ -406,17 +435,31 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h | |||
406 | * inverse of the reported Y. | 435 | * inverse of the reported Y. |
407 | */ | 436 | */ |
408 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { | 437 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { |
409 | input_set_abs_params(input, ABS_MT_POSITION_X, -1100, | 438 | input_set_abs_params(input, ABS_MT_POSITION_X, |
410 | 1358, 4, 0); | 439 | MOUSE_MIN_X, MOUSE_MAX_X, 4, 0); |
411 | input_set_abs_params(input, ABS_MT_POSITION_Y, -1589, | 440 | input_set_abs_params(input, ABS_MT_POSITION_Y, |
412 | 2047, 4, 0); | 441 | MOUSE_MIN_Y, MOUSE_MAX_Y, 4, 0); |
442 | |||
443 | input_abs_set_res(input, ABS_MT_POSITION_X, | ||
444 | MOUSE_RES_X); | ||
445 | input_abs_set_res(input, ABS_MT_POSITION_Y, | ||
446 | MOUSE_RES_Y); | ||
413 | } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | 447 | } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ |
414 | input_set_abs_params(input, ABS_X, -2909, 3167, 4, 0); | 448 | input_set_abs_params(input, ABS_X, TRACKPAD_MIN_X, |
415 | input_set_abs_params(input, ABS_Y, -2456, 2565, 4, 0); | 449 | TRACKPAD_MAX_X, 4, 0); |
416 | input_set_abs_params(input, ABS_MT_POSITION_X, -2909, | 450 | input_set_abs_params(input, ABS_Y, TRACKPAD_MIN_Y, |
417 | 3167, 4, 0); | 451 | TRACKPAD_MAX_Y, 4, 0); |
418 | input_set_abs_params(input, ABS_MT_POSITION_Y, -2456, | 452 | input_set_abs_params(input, ABS_MT_POSITION_X, |
419 | 2565, 4, 0); | 453 | TRACKPAD_MIN_X, TRACKPAD_MAX_X, 4, 0); |
454 | input_set_abs_params(input, ABS_MT_POSITION_Y, | ||
455 | TRACKPAD_MIN_Y, TRACKPAD_MAX_Y, 4, 0); | ||
456 | |||
457 | input_abs_set_res(input, ABS_X, TRACKPAD_RES_X); | ||
458 | input_abs_set_res(input, ABS_Y, TRACKPAD_RES_Y); | ||
459 | input_abs_set_res(input, ABS_MT_POSITION_X, | ||
460 | TRACKPAD_RES_X); | ||
461 | input_abs_set_res(input, ABS_MT_POSITION_Y, | ||
462 | TRACKPAD_RES_Y); | ||
420 | } | 463 | } |
421 | 464 | ||
422 | input_set_events_per_packet(input, 60); | 465 | input_set_events_per_packet(input, 60); |
@@ -501,9 +544,17 @@ static int magicmouse_probe(struct hid_device *hdev, | |||
501 | } | 544 | } |
502 | report->size = 6; | 545 | report->size = 6; |
503 | 546 | ||
547 | /* | ||
548 | * Some devices repond with 'invalid report id' when feature | ||
549 | * report switching it into multitouch mode is sent to it. | ||
550 | * | ||
551 | * This results in -EIO from the _raw low-level transport callback, | ||
552 | * but there seems to be no other way of switching the mode. | ||
553 | * Thus the super-ugly hacky success check below. | ||
554 | */ | ||
504 | ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature), | 555 | ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature), |
505 | HID_FEATURE_REPORT); | 556 | HID_FEATURE_REPORT); |
506 | if (ret != sizeof(feature)) { | 557 | if (ret != -EIO && ret != sizeof(feature)) { |
507 | hid_err(hdev, "unable to request touch data (%d)\n", ret); | 558 | hid_err(hdev, "unable to request touch data (%d)\n", ret); |
508 | goto err_stop_hw; | 559 | goto err_stop_hw; |
509 | } | 560 | } |
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 58d0e7aaf088..f1c909f1b239 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
@@ -47,10 +47,11 @@ MODULE_LICENSE("GPL"); | |||
47 | #define MT_QUIRK_SLOT_IS_CONTACTID (1 << 1) | 47 | #define MT_QUIRK_SLOT_IS_CONTACTID (1 << 1) |
48 | #define MT_QUIRK_CYPRESS (1 << 2) | 48 | #define MT_QUIRK_CYPRESS (1 << 2) |
49 | #define MT_QUIRK_SLOT_IS_CONTACTNUMBER (1 << 3) | 49 | #define MT_QUIRK_SLOT_IS_CONTACTNUMBER (1 << 3) |
50 | #define MT_QUIRK_VALID_IS_INRANGE (1 << 4) | 50 | #define MT_QUIRK_ALWAYS_VALID (1 << 4) |
51 | #define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 5) | 51 | #define MT_QUIRK_VALID_IS_INRANGE (1 << 5) |
52 | #define MT_QUIRK_EGALAX_XYZ_FIXUP (1 << 6) | 52 | #define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 6) |
53 | #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 7) | 53 | #define MT_QUIRK_EGALAX_XYZ_FIXUP (1 << 7) |
54 | #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8) | ||
54 | 55 | ||
55 | struct mt_slot { | 56 | struct mt_slot { |
56 | __s32 x, y, p, w, h; | 57 | __s32 x, y, p, w, h; |
@@ -86,11 +87,12 @@ struct mt_class { | |||
86 | /* classes of device behavior */ | 87 | /* classes of device behavior */ |
87 | #define MT_CLS_DEFAULT 0x0001 | 88 | #define MT_CLS_DEFAULT 0x0001 |
88 | 89 | ||
89 | #define MT_CLS_CONFIDENCE 0x0002 | 90 | #define MT_CLS_SERIAL 0x0002 |
90 | #define MT_CLS_CONFIDENCE_MINUS_ONE 0x0003 | 91 | #define MT_CLS_CONFIDENCE 0x0003 |
91 | #define MT_CLS_DUAL_INRANGE_CONTACTID 0x0004 | 92 | #define MT_CLS_CONFIDENCE_MINUS_ONE 0x0004 |
92 | #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 0x0005 | 93 | #define MT_CLS_DUAL_INRANGE_CONTACTID 0x0005 |
93 | #define MT_CLS_DUAL_NSMU_CONTACTID 0x0006 | 94 | #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 0x0006 |
95 | #define MT_CLS_DUAL_NSMU_CONTACTID 0x0007 | ||
94 | 96 | ||
95 | /* vendor specific classes */ | 97 | /* vendor specific classes */ |
96 | #define MT_CLS_3M 0x0101 | 98 | #define MT_CLS_3M 0x0101 |
@@ -134,6 +136,8 @@ static int find_slot_from_contactid(struct mt_device *td) | |||
134 | struct mt_class mt_classes[] = { | 136 | struct mt_class mt_classes[] = { |
135 | { .name = MT_CLS_DEFAULT, | 137 | { .name = MT_CLS_DEFAULT, |
136 | .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP }, | 138 | .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP }, |
139 | { .name = MT_CLS_SERIAL, | ||
140 | .quirks = MT_QUIRK_ALWAYS_VALID}, | ||
137 | { .name = MT_CLS_CONFIDENCE, | 141 | { .name = MT_CLS_CONFIDENCE, |
138 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE }, | 142 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE }, |
139 | { .name = MT_CLS_CONFIDENCE_MINUS_ONE, | 143 | { .name = MT_CLS_CONFIDENCE_MINUS_ONE, |
@@ -213,6 +217,16 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
213 | struct mt_class *cls = td->mtclass; | 217 | struct mt_class *cls = td->mtclass; |
214 | __s32 quirks = cls->quirks; | 218 | __s32 quirks = cls->quirks; |
215 | 219 | ||
220 | /* Only map fields from TouchScreen or TouchPad collections. | ||
221 | * We need to ignore fields that belong to other collections | ||
222 | * such as Mouse that might have the same GenericDesktop usages. */ | ||
223 | if (field->application == HID_DG_TOUCHSCREEN) | ||
224 | set_bit(INPUT_PROP_DIRECT, hi->input->propbit); | ||
225 | else if (field->application == HID_DG_TOUCHPAD) | ||
226 | set_bit(INPUT_PROP_POINTER, hi->input->propbit); | ||
227 | else | ||
228 | return 0; | ||
229 | |||
216 | switch (usage->hid & HID_USAGE_PAGE) { | 230 | switch (usage->hid & HID_USAGE_PAGE) { |
217 | 231 | ||
218 | case HID_UP_GENDESK: | 232 | case HID_UP_GENDESK: |
@@ -435,7 +449,9 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, | |||
435 | if (hid->claimed & HID_CLAIMED_INPUT && td->slots) { | 449 | if (hid->claimed & HID_CLAIMED_INPUT && td->slots) { |
436 | switch (usage->hid) { | 450 | switch (usage->hid) { |
437 | case HID_DG_INRANGE: | 451 | case HID_DG_INRANGE: |
438 | if (quirks & MT_QUIRK_VALID_IS_INRANGE) | 452 | if (quirks & MT_QUIRK_ALWAYS_VALID) |
453 | td->curvalid = true; | ||
454 | else if (quirks & MT_QUIRK_VALID_IS_INRANGE) | ||
439 | td->curvalid = value; | 455 | td->curvalid = value; |
440 | break; | 456 | break; |
441 | case HID_DG_TIPSWITCH: | 457 | case HID_DG_TIPSWITCH: |
@@ -662,6 +678,11 @@ static const struct hid_device_id mt_devices[] = { | |||
662 | HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH, | 678 | HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH, |
663 | USB_DEVICE_ID_GOODTOUCH_000f) }, | 679 | USB_DEVICE_ID_GOODTOUCH_000f) }, |
664 | 680 | ||
681 | /* Ideacom panel */ | ||
682 | { .driver_data = MT_CLS_SERIAL, | ||
683 | HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, | ||
684 | USB_DEVICE_ID_IDEACOM_IDC6650) }, | ||
685 | |||
665 | /* Ilitek dual touch panel */ | 686 | /* Ilitek dual touch panel */ |
666 | { .driver_data = MT_CLS_DEFAULT, | 687 | { .driver_data = MT_CLS_DEFAULT, |
667 | HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, | 688 | HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, |
@@ -672,6 +693,11 @@ static const struct hid_device_id mt_devices[] = { | |||
672 | HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, | 693 | HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, |
673 | USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, | 694 | USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, |
674 | 695 | ||
696 | /* LG Display panels */ | ||
697 | { .driver_data = MT_CLS_DEFAULT, | ||
698 | HID_USB_DEVICE(USB_VENDOR_ID_LG, | ||
699 | USB_DEVICE_ID_LG_MULTITOUCH) }, | ||
700 | |||
675 | /* Lumio panels */ | 701 | /* Lumio panels */ |
676 | { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, | 702 | { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, |
677 | HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, | 703 | HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, |
diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c index 9d8710f8bc79..01e7d2cd7c26 100644 --- a/drivers/hid/hid-picolcd.c +++ b/drivers/hid/hid-picolcd.c | |||
@@ -36,6 +36,7 @@ | |||
36 | 36 | ||
37 | #include <linux/completion.h> | 37 | #include <linux/completion.h> |
38 | #include <linux/uaccess.h> | 38 | #include <linux/uaccess.h> |
39 | #include <linux/module.h> | ||
39 | 40 | ||
40 | #define PICOLCD_NAME "PicoLCD (graphic)" | 41 | #define PICOLCD_NAME "PicoLCD (graphic)" |
41 | 42 | ||
@@ -2409,7 +2410,7 @@ static int picolcd_raw_event(struct hid_device *hdev, | |||
2409 | #ifdef CONFIG_PM | 2410 | #ifdef CONFIG_PM |
2410 | static int picolcd_suspend(struct hid_device *hdev, pm_message_t message) | 2411 | static int picolcd_suspend(struct hid_device *hdev, pm_message_t message) |
2411 | { | 2412 | { |
2412 | if (message.event & PM_EVENT_AUTO) | 2413 | if (PMSG_IS_AUTO(message)) |
2413 | return 0; | 2414 | return 0; |
2414 | 2415 | ||
2415 | picolcd_suspend_backlight(hid_get_drvdata(hdev)); | 2416 | picolcd_suspend_backlight(hid_get_drvdata(hdev)); |
diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c index 06e5300d43d2..070f93a5c11b 100644 --- a/drivers/hid/hid-pl.c +++ b/drivers/hid/hid-pl.c | |||
@@ -40,6 +40,7 @@ | |||
40 | 40 | ||
41 | #include <linux/input.h> | 41 | #include <linux/input.h> |
42 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
43 | #include <linux/module.h> | ||
43 | #include <linux/usb.h> | 44 | #include <linux/usb.h> |
44 | #include <linux/hid.h> | 45 | #include <linux/hid.h> |
45 | 46 | ||
diff --git a/drivers/hid/hid-primax.c b/drivers/hid/hid-primax.c new file mode 100644 index 000000000000..4d3c60d88318 --- /dev/null +++ b/drivers/hid/hid-primax.c | |||
@@ -0,0 +1,117 @@ | |||
1 | /* | ||
2 | * HID driver for primax and similar keyboards with in-band modifiers | ||
3 | * | ||
4 | * Copyright 2011 Google Inc. All Rights Reserved | ||
5 | * | ||
6 | * Author: | ||
7 | * Terry Lambert <tlambert@google.com> | ||
8 | * | ||
9 | * This software is licensed under the terms of the GNU General Public | ||
10 | * License version 2, as published by the Free Software Foundation, and | ||
11 | * may be copied, distributed, and modified under those terms. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | */ | ||
18 | |||
19 | #include <linux/device.h> | ||
20 | #include <linux/hid.h> | ||
21 | #include <linux/module.h> | ||
22 | |||
23 | #include "hid-ids.h" | ||
24 | |||
25 | static int px_raw_event(struct hid_device *hid, struct hid_report *report, | ||
26 | u8 *data, int size) | ||
27 | { | ||
28 | int idx = size; | ||
29 | |||
30 | switch (report->id) { | ||
31 | case 0: /* keyboard input */ | ||
32 | /* | ||
33 | * Convert in-band modifier key values into out of band | ||
34 | * modifier bits and pull the key strokes from the report. | ||
35 | * Thus a report data set which looked like: | ||
36 | * | ||
37 | * [00][00][E0][30][00][00][00][00] | ||
38 | * (no modifier bits + "Left Shift" key + "1" key) | ||
39 | * | ||
40 | * Would be converted to: | ||
41 | * | ||
42 | * [01][00][00][30][00][00][00][00] | ||
43 | * (Left Shift modifier bit + "1" key) | ||
44 | * | ||
45 | * As long as it's in the size range, the upper level | ||
46 | * drivers don't particularly care if there are in-band | ||
47 | * 0-valued keys, so they don't stop parsing. | ||
48 | */ | ||
49 | while (--idx > 1) { | ||
50 | if (data[idx] < 0xE0 || data[idx] > 0xE7) | ||
51 | continue; | ||
52 | data[0] |= (1 << (data[idx] - 0xE0)); | ||
53 | data[idx] = 0; | ||
54 | } | ||
55 | hid_report_raw_event(hid, HID_INPUT_REPORT, data, size, 0); | ||
56 | return 1; | ||
57 | |||
58 | default: /* unknown report */ | ||
59 | /* Unknown report type; pass upstream */ | ||
60 | hid_info(hid, "unknown report type %d\n", report->id); | ||
61 | break; | ||
62 | } | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static int px_probe(struct hid_device *hid, const struct hid_device_id *id) | ||
68 | { | ||
69 | int ret; | ||
70 | |||
71 | ret = hid_parse(hid); | ||
72 | if (ret) { | ||
73 | hid_err(hid, "parse failed\n"); | ||
74 | goto fail; | ||
75 | } | ||
76 | |||
77 | ret = hid_hw_start(hid, HID_CONNECT_DEFAULT); | ||
78 | if (ret) | ||
79 | hid_err(hid, "hw start failed\n"); | ||
80 | |||
81 | fail: | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | static void px_remove(struct hid_device *hid) | ||
86 | { | ||
87 | hid_hw_stop(hid); | ||
88 | } | ||
89 | |||
90 | static const struct hid_device_id px_devices[] = { | ||
91 | { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, | ||
92 | { } | ||
93 | }; | ||
94 | MODULE_DEVICE_TABLE(hid, px_devices); | ||
95 | |||
96 | static struct hid_driver px_driver = { | ||
97 | .name = "primax", | ||
98 | .id_table = px_devices, | ||
99 | .raw_event = px_raw_event, | ||
100 | .probe = px_probe, | ||
101 | .remove = px_remove, | ||
102 | }; | ||
103 | |||
104 | static int __init px_init(void) | ||
105 | { | ||
106 | return hid_register_driver(&px_driver); | ||
107 | } | ||
108 | |||
109 | static void __exit px_exit(void) | ||
110 | { | ||
111 | hid_unregister_driver(&px_driver); | ||
112 | } | ||
113 | |||
114 | module_init(px_init); | ||
115 | module_exit(px_exit); | ||
116 | MODULE_AUTHOR("Terry Lambert <tlambert@google.com>"); | ||
117 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c index 158b389d0fb7..f779009104eb 100644 --- a/drivers/hid/hid-prodikeys.c +++ b/drivers/hid/hid-prodikeys.c | |||
@@ -816,7 +816,7 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
816 | if (pm == NULL) { | 816 | if (pm == NULL) { |
817 | hid_err(hdev, "can't alloc descriptor\n"); | 817 | hid_err(hdev, "can't alloc descriptor\n"); |
818 | ret = -ENOMEM; | 818 | ret = -ENOMEM; |
819 | goto err_free; | 819 | goto err_free_pk; |
820 | } | 820 | } |
821 | 821 | ||
822 | pm->pk = pk; | 822 | pm->pk = pk; |
@@ -849,10 +849,10 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
849 | err_stop: | 849 | err_stop: |
850 | hid_hw_stop(hdev); | 850 | hid_hw_stop(hdev); |
851 | err_free: | 851 | err_free: |
852 | if (pm != NULL) | 852 | kfree(pm); |
853 | kfree(pm); | 853 | err_free_pk: |
854 | |||
855 | kfree(pk); | 854 | kfree(pk); |
855 | |||
856 | return ret; | 856 | return ret; |
857 | } | 857 | } |
858 | 858 | ||
diff --git a/drivers/hid/hid-roccat-common.c b/drivers/hid/hid-roccat-common.c index edf898dee28b..b07e7f96a358 100644 --- a/drivers/hid/hid-roccat-common.c +++ b/drivers/hid/hid-roccat-common.c | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | #include <linux/hid.h> | 14 | #include <linux/hid.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/module.h> | ||
16 | #include "hid-roccat-common.h" | 17 | #include "hid-roccat-common.h" |
17 | 18 | ||
18 | static inline uint16_t roccat_common_feature_report(uint8_t report_id) | 19 | static inline uint16_t roccat_common_feature_report(uint8_t report_id) |
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index 2b8f3a31ffb3..e2072afb34bb 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c | |||
@@ -37,6 +37,21 @@ | |||
37 | 37 | ||
38 | static uint profile_numbers[5] = {0, 1, 2, 3, 4}; | 38 | static uint profile_numbers[5] = {0, 1, 2, 3, 4}; |
39 | 39 | ||
40 | static void kone_profile_activated(struct kone_device *kone, uint new_profile) | ||
41 | { | ||
42 | kone->actual_profile = new_profile; | ||
43 | kone->actual_dpi = kone->profiles[new_profile - 1].startup_dpi; | ||
44 | } | ||
45 | |||
46 | static void kone_profile_report(struct kone_device *kone, uint new_profile) | ||
47 | { | ||
48 | struct kone_roccat_report roccat_report; | ||
49 | roccat_report.event = kone_mouse_event_switch_profile; | ||
50 | roccat_report.value = new_profile; | ||
51 | roccat_report.key = 0; | ||
52 | roccat_report_event(kone->chrdev_minor, (uint8_t *)&roccat_report); | ||
53 | } | ||
54 | |||
40 | static int kone_receive(struct usb_device *usb_dev, uint usb_command, | 55 | static int kone_receive(struct usb_device *usb_dev, uint usb_command, |
41 | void *data, uint size) | 56 | void *data, uint size) |
42 | { | 57 | { |
@@ -283,7 +298,7 @@ static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj, | |||
283 | container_of(kobj, struct device, kobj)->parent->parent; | 298 | container_of(kobj, struct device, kobj)->parent->parent; |
284 | struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); | 299 | struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); |
285 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | 300 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); |
286 | int retval = 0, difference; | 301 | int retval = 0, difference, old_profile; |
287 | 302 | ||
288 | /* I need to get my data in one piece */ | 303 | /* I need to get my data in one piece */ |
289 | if (off != 0 || count != sizeof(struct kone_settings)) | 304 | if (off != 0 || count != sizeof(struct kone_settings)) |
@@ -294,21 +309,20 @@ static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj, | |||
294 | if (difference) { | 309 | if (difference) { |
295 | retval = kone_set_settings(usb_dev, | 310 | retval = kone_set_settings(usb_dev, |
296 | (struct kone_settings const *)buf); | 311 | (struct kone_settings const *)buf); |
297 | if (!retval) | 312 | if (retval) { |
298 | memcpy(&kone->settings, buf, | 313 | mutex_unlock(&kone->kone_lock); |
299 | sizeof(struct kone_settings)); | 314 | return retval; |
300 | } | 315 | } |
301 | mutex_unlock(&kone->kone_lock); | ||
302 | 316 | ||
303 | if (retval) | 317 | old_profile = kone->settings.startup_profile; |
304 | return retval; | 318 | memcpy(&kone->settings, buf, sizeof(struct kone_settings)); |
305 | 319 | ||
306 | /* | 320 | kone_profile_activated(kone, kone->settings.startup_profile); |
307 | * If we get here, treat settings as okay and update actual values | 321 | |
308 | * according to startup_profile | 322 | if (kone->settings.startup_profile != old_profile) |
309 | */ | 323 | kone_profile_report(kone, kone->settings.startup_profile); |
310 | kone->actual_profile = kone->settings.startup_profile; | 324 | } |
311 | kone->actual_dpi = kone->profiles[kone->actual_profile - 1].startup_dpi; | 325 | mutex_unlock(&kone->kone_lock); |
312 | 326 | ||
313 | return sizeof(struct kone_settings); | 327 | return sizeof(struct kone_settings); |
314 | } | 328 | } |
@@ -501,6 +515,8 @@ static ssize_t kone_sysfs_set_tcu(struct device *dev, | |||
501 | goto exit_no_settings; | 515 | goto exit_no_settings; |
502 | goto exit_unlock; | 516 | goto exit_unlock; |
503 | } | 517 | } |
518 | /* calibration resets profile */ | ||
519 | kone_profile_activated(kone, kone->settings.startup_profile); | ||
504 | } | 520 | } |
505 | 521 | ||
506 | retval = size; | 522 | retval = size; |
@@ -544,16 +560,16 @@ static ssize_t kone_sysfs_set_startup_profile(struct device *dev, | |||
544 | kone_set_settings_checksum(&kone->settings); | 560 | kone_set_settings_checksum(&kone->settings); |
545 | 561 | ||
546 | retval = kone_set_settings(usb_dev, &kone->settings); | 562 | retval = kone_set_settings(usb_dev, &kone->settings); |
547 | 563 | if (retval) { | |
548 | mutex_unlock(&kone->kone_lock); | 564 | mutex_unlock(&kone->kone_lock); |
549 | |||
550 | if (retval) | ||
551 | return retval; | 565 | return retval; |
566 | } | ||
552 | 567 | ||
553 | /* changing the startup profile immediately activates this profile */ | 568 | /* changing the startup profile immediately activates this profile */ |
554 | kone->actual_profile = new_startup_profile; | 569 | kone_profile_activated(kone, new_startup_profile); |
555 | kone->actual_dpi = kone->profiles[kone->actual_profile - 1].startup_dpi; | 570 | kone_profile_report(kone, new_startup_profile); |
556 | 571 | ||
572 | mutex_unlock(&kone->kone_lock); | ||
557 | return size; | 573 | return size; |
558 | } | 574 | } |
559 | 575 | ||
@@ -665,8 +681,7 @@ static int kone_init_kone_device_struct(struct usb_device *usb_dev, | |||
665 | if (retval) | 681 | if (retval) |
666 | return retval; | 682 | return retval; |
667 | 683 | ||
668 | kone->actual_profile = kone->settings.startup_profile; | 684 | kone_profile_activated(kone, kone->settings.startup_profile); |
669 | kone->actual_dpi = kone->profiles[kone->actual_profile].startup_dpi; | ||
670 | 685 | ||
671 | return 0; | 686 | return 0; |
672 | } | 687 | } |
@@ -776,10 +791,10 @@ static void kone_keep_values_up_to_date(struct kone_device *kone, | |||
776 | { | 791 | { |
777 | switch (event->event) { | 792 | switch (event->event) { |
778 | case kone_mouse_event_switch_profile: | 793 | case kone_mouse_event_switch_profile: |
794 | kone->actual_dpi = kone->profiles[event->value - 1]. | ||
795 | startup_dpi; | ||
779 | case kone_mouse_event_osd_profile: | 796 | case kone_mouse_event_osd_profile: |
780 | kone->actual_profile = event->value; | 797 | kone->actual_profile = event->value; |
781 | kone->actual_dpi = kone->profiles[kone->actual_profile - 1]. | ||
782 | startup_dpi; | ||
783 | break; | 798 | break; |
784 | case kone_mouse_event_switch_dpi: | 799 | case kone_mouse_event_switch_dpi: |
785 | case kone_mouse_event_osd_dpi: | 800 | case kone_mouse_event_osd_dpi: |
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c index 1f8336e3f584..112d934132c8 100644 --- a/drivers/hid/hid-roccat-kovaplus.c +++ b/drivers/hid/hid-roccat-kovaplus.c | |||
@@ -323,6 +323,7 @@ static ssize_t kovaplus_sysfs_set_actual_profile(struct device *dev, | |||
323 | struct usb_device *usb_dev; | 323 | struct usb_device *usb_dev; |
324 | unsigned long profile; | 324 | unsigned long profile; |
325 | int retval; | 325 | int retval; |
326 | struct kovaplus_roccat_report roccat_report; | ||
326 | 327 | ||
327 | dev = dev->parent->parent; | 328 | dev = dev->parent->parent; |
328 | kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); | 329 | kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); |
@@ -337,10 +338,22 @@ static ssize_t kovaplus_sysfs_set_actual_profile(struct device *dev, | |||
337 | 338 | ||
338 | mutex_lock(&kovaplus->kovaplus_lock); | 339 | mutex_lock(&kovaplus->kovaplus_lock); |
339 | retval = kovaplus_set_actual_profile(usb_dev, profile); | 340 | retval = kovaplus_set_actual_profile(usb_dev, profile); |
341 | if (retval) { | ||
342 | mutex_unlock(&kovaplus->kovaplus_lock); | ||
343 | return retval; | ||
344 | } | ||
345 | |||
340 | kovaplus_profile_activated(kovaplus, profile); | 346 | kovaplus_profile_activated(kovaplus, profile); |
347 | |||
348 | roccat_report.type = KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_1; | ||
349 | roccat_report.profile = profile + 1; | ||
350 | roccat_report.button = 0; | ||
351 | roccat_report.data1 = profile + 1; | ||
352 | roccat_report.data2 = 0; | ||
353 | roccat_report_event(kovaplus->chrdev_minor, | ||
354 | (uint8_t const *)&roccat_report); | ||
355 | |||
341 | mutex_unlock(&kovaplus->kovaplus_lock); | 356 | mutex_unlock(&kovaplus->kovaplus_lock); |
342 | if (retval) | ||
343 | return retval; | ||
344 | 357 | ||
345 | return size; | 358 | return size; |
346 | } | 359 | } |
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c index 8140776bd8c5..df05c1b1064f 100644 --- a/drivers/hid/hid-roccat-pyra.c +++ b/drivers/hid/hid-roccat-pyra.c | |||
@@ -298,6 +298,7 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp, | |||
298 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | 298 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); |
299 | int retval = 0; | 299 | int retval = 0; |
300 | int difference; | 300 | int difference; |
301 | struct pyra_roccat_report roccat_report; | ||
301 | 302 | ||
302 | if (off != 0 || count != sizeof(struct pyra_settings)) | 303 | if (off != 0 || count != sizeof(struct pyra_settings)) |
303 | return -EINVAL; | 304 | return -EINVAL; |
@@ -307,17 +308,23 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp, | |||
307 | if (difference) { | 308 | if (difference) { |
308 | retval = pyra_set_settings(usb_dev, | 309 | retval = pyra_set_settings(usb_dev, |
309 | (struct pyra_settings const *)buf); | 310 | (struct pyra_settings const *)buf); |
310 | if (!retval) | 311 | if (retval) { |
311 | memcpy(&pyra->settings, buf, | 312 | mutex_unlock(&pyra->pyra_lock); |
312 | sizeof(struct pyra_settings)); | 313 | return retval; |
313 | } | 314 | } |
314 | mutex_unlock(&pyra->pyra_lock); | ||
315 | 315 | ||
316 | if (retval) | 316 | memcpy(&pyra->settings, buf, |
317 | return retval; | 317 | sizeof(struct pyra_settings)); |
318 | 318 | ||
319 | profile_activated(pyra, pyra->settings.startup_profile); | 319 | profile_activated(pyra, pyra->settings.startup_profile); |
320 | 320 | ||
321 | roccat_report.type = PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2; | ||
322 | roccat_report.value = pyra->settings.startup_profile + 1; | ||
323 | roccat_report.key = 0; | ||
324 | roccat_report_event(pyra->chrdev_minor, | ||
325 | (uint8_t const *)&roccat_report); | ||
326 | } | ||
327 | mutex_unlock(&pyra->pyra_lock); | ||
321 | return sizeof(struct pyra_settings); | 328 | return sizeof(struct pyra_settings); |
322 | } | 329 | } |
323 | 330 | ||
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c index 5666e7587b18..b685b04dbf9d 100644 --- a/drivers/hid/hid-roccat.c +++ b/drivers/hid/hid-roccat.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/poll.h> | 27 | #include <linux/poll.h> |
28 | #include <linux/sched.h> | 28 | #include <linux/sched.h> |
29 | #include <linux/hid-roccat.h> | 29 | #include <linux/hid-roccat.h> |
30 | #include <linux/module.h> | ||
30 | 31 | ||
31 | #define ROCCAT_FIRST_MINOR 0 | 32 | #define ROCCAT_FIRST_MINOR 0 |
32 | #define ROCCAT_MAX_DEVICES 8 | 33 | #define ROCCAT_MAX_DEVICES 8 |
@@ -162,27 +163,27 @@ static int roccat_open(struct inode *inode, struct file *file) | |||
162 | 163 | ||
163 | device = devices[minor]; | 164 | device = devices[minor]; |
164 | 165 | ||
165 | mutex_lock(&device->readers_lock); | ||
166 | |||
167 | if (!device) { | 166 | if (!device) { |
168 | pr_emerg("roccat device with minor %d doesn't exist\n", minor); | 167 | pr_emerg("roccat device with minor %d doesn't exist\n", minor); |
169 | error = -ENODEV; | 168 | error = -ENODEV; |
170 | goto exit_err; | 169 | goto exit_err_devices; |
171 | } | 170 | } |
172 | 171 | ||
172 | mutex_lock(&device->readers_lock); | ||
173 | |||
173 | if (!device->open++) { | 174 | if (!device->open++) { |
174 | /* power on device on adding first reader */ | 175 | /* power on device on adding first reader */ |
175 | error = hid_hw_power(device->hid, PM_HINT_FULLON); | 176 | error = hid_hw_power(device->hid, PM_HINT_FULLON); |
176 | if (error < 0) { | 177 | if (error < 0) { |
177 | --device->open; | 178 | --device->open; |
178 | goto exit_err; | 179 | goto exit_err_readers; |
179 | } | 180 | } |
180 | 181 | ||
181 | error = hid_hw_open(device->hid); | 182 | error = hid_hw_open(device->hid); |
182 | if (error < 0) { | 183 | if (error < 0) { |
183 | hid_hw_power(device->hid, PM_HINT_NORMAL); | 184 | hid_hw_power(device->hid, PM_HINT_NORMAL); |
184 | --device->open; | 185 | --device->open; |
185 | goto exit_err; | 186 | goto exit_err_readers; |
186 | } | 187 | } |
187 | } | 188 | } |
188 | 189 | ||
@@ -193,13 +194,13 @@ static int roccat_open(struct inode *inode, struct file *file) | |||
193 | list_add_tail(&reader->node, &device->readers); | 194 | list_add_tail(&reader->node, &device->readers); |
194 | file->private_data = reader; | 195 | file->private_data = reader; |
195 | 196 | ||
196 | exit_unlock: | 197 | exit_err_readers: |
197 | mutex_unlock(&device->readers_lock); | 198 | mutex_unlock(&device->readers_lock); |
199 | exit_err_devices: | ||
198 | mutex_unlock(&devices_lock); | 200 | mutex_unlock(&devices_lock); |
201 | if (error) | ||
202 | kfree(reader); | ||
199 | return error; | 203 | return error; |
200 | exit_err: | ||
201 | kfree(reader); | ||
202 | goto exit_unlock; | ||
203 | } | 204 | } |
204 | 205 | ||
205 | static int roccat_release(struct inode *inode, struct file *file) | 206 | static int roccat_release(struct inode *inode, struct file *file) |
diff --git a/drivers/hid/hid-sjoy.c b/drivers/hid/hid-sjoy.c index 16f7cafc9695..4b1448613ea6 100644 --- a/drivers/hid/hid-sjoy.c +++ b/drivers/hid/hid-sjoy.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/usb.h> | 31 | #include <linux/usb.h> |
32 | #include <linux/hid.h> | 32 | #include <linux/hid.h> |
33 | #include <linux/module.h> | ||
33 | #include "hid-ids.h" | 34 | #include "hid-ids.h" |
34 | 35 | ||
35 | #ifdef CONFIG_SMARTJOYPLUS_FF | 36 | #ifdef CONFIG_SMARTJOYPLUS_FF |
@@ -65,8 +66,7 @@ static int sjoyff_init(struct hid_device *hid) | |||
65 | { | 66 | { |
66 | struct sjoyff_device *sjoyff; | 67 | struct sjoyff_device *sjoyff; |
67 | struct hid_report *report; | 68 | struct hid_report *report; |
68 | struct hid_input *hidinput = list_entry(hid->inputs.next, | 69 | struct hid_input *hidinput; |
69 | struct hid_input, list); | ||
70 | struct list_head *report_list = | 70 | struct list_head *report_list = |
71 | &hid->report_enum[HID_OUTPUT_REPORT].report_list; | 71 | &hid->report_enum[HID_OUTPUT_REPORT].report_list; |
72 | struct list_head *report_ptr = report_list; | 72 | struct list_head *report_ptr = report_list; |
@@ -78,43 +78,45 @@ static int sjoyff_init(struct hid_device *hid) | |||
78 | return -ENODEV; | 78 | return -ENODEV; |
79 | } | 79 | } |
80 | 80 | ||
81 | report_ptr = report_ptr->next; | 81 | list_for_each_entry(hidinput, &hid->inputs, list) { |
82 | report_ptr = report_ptr->next; | ||
82 | 83 | ||
83 | if (report_ptr == report_list) { | 84 | if (report_ptr == report_list) { |
84 | hid_err(hid, "required output report is missing\n"); | 85 | hid_err(hid, "required output report is missing\n"); |
85 | return -ENODEV; | 86 | return -ENODEV; |
86 | } | 87 | } |
87 | 88 | ||
88 | report = list_entry(report_ptr, struct hid_report, list); | 89 | report = list_entry(report_ptr, struct hid_report, list); |
89 | if (report->maxfield < 1) { | 90 | if (report->maxfield < 1) { |
90 | hid_err(hid, "no fields in the report\n"); | 91 | hid_err(hid, "no fields in the report\n"); |
91 | return -ENODEV; | 92 | return -ENODEV; |
92 | } | 93 | } |
93 | 94 | ||
94 | if (report->field[0]->report_count < 3) { | 95 | if (report->field[0]->report_count < 3) { |
95 | hid_err(hid, "not enough values in the field\n"); | 96 | hid_err(hid, "not enough values in the field\n"); |
96 | return -ENODEV; | 97 | return -ENODEV; |
97 | } | 98 | } |
98 | 99 | ||
99 | sjoyff = kzalloc(sizeof(struct sjoyff_device), GFP_KERNEL); | 100 | sjoyff = kzalloc(sizeof(struct sjoyff_device), GFP_KERNEL); |
100 | if (!sjoyff) | 101 | if (!sjoyff) |
101 | return -ENOMEM; | 102 | return -ENOMEM; |
102 | 103 | ||
103 | dev = hidinput->input; | 104 | dev = hidinput->input; |
104 | 105 | ||
105 | set_bit(FF_RUMBLE, dev->ffbit); | 106 | set_bit(FF_RUMBLE, dev->ffbit); |
106 | 107 | ||
107 | error = input_ff_create_memless(dev, sjoyff, hid_sjoyff_play); | 108 | error = input_ff_create_memless(dev, sjoyff, hid_sjoyff_play); |
108 | if (error) { | 109 | if (error) { |
109 | kfree(sjoyff); | 110 | kfree(sjoyff); |
110 | return error; | 111 | return error; |
111 | } | 112 | } |
112 | 113 | ||
113 | sjoyff->report = report; | 114 | sjoyff->report = report; |
114 | sjoyff->report->field[0]->value[0] = 0x01; | 115 | sjoyff->report->field[0]->value[0] = 0x01; |
115 | sjoyff->report->field[0]->value[1] = 0x00; | 116 | sjoyff->report->field[0]->value[1] = 0x00; |
116 | sjoyff->report->field[0]->value[2] = 0x00; | 117 | sjoyff->report->field[0]->value[2] = 0x00; |
117 | usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT); | 118 | usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT); |
119 | } | ||
118 | 120 | ||
119 | hid_info(hid, "Force feedback for SmartJoy PLUS PS2/USB adapter\n"); | 121 | hid_info(hid, "Force feedback for SmartJoy PLUS PS2/USB adapter\n"); |
120 | 122 | ||
@@ -131,6 +133,8 @@ static int sjoy_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
131 | { | 133 | { |
132 | int ret; | 134 | int ret; |
133 | 135 | ||
136 | hdev->quirks |= id->driver_data; | ||
137 | |||
134 | ret = hid_parse(hdev); | 138 | ret = hid_parse(hdev); |
135 | if (ret) { | 139 | if (ret) { |
136 | hid_err(hdev, "parse failed\n"); | 140 | hid_err(hdev, "parse failed\n"); |
@@ -151,7 +155,17 @@ err: | |||
151 | } | 155 | } |
152 | 156 | ||
153 | static const struct hid_device_id sjoy_devices[] = { | 157 | static const struct hid_device_id sjoy_devices[] = { |
158 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) }, | ||
159 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO), | ||
160 | .driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET | | ||
161 | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | ||
162 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO), | ||
163 | .driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET | | ||
164 | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | ||
154 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, | 165 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, |
166 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD), | ||
167 | .driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET | | ||
168 | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | ||
155 | { } | 169 | { } |
156 | }; | 170 | }; |
157 | MODULE_DEVICE_TABLE(hid, sjoy_devices); | 171 | MODULE_DEVICE_TABLE(hid, sjoy_devices); |
diff --git a/drivers/hid/hid-tmff.c b/drivers/hid/hid-tmff.c index 575862b0688e..83a933b9c2e9 100644 --- a/drivers/hid/hid-tmff.c +++ b/drivers/hid/hid-tmff.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/input.h> | 31 | #include <linux/input.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/usb.h> | 33 | #include <linux/usb.h> |
34 | #include <linux/module.h> | ||
34 | 35 | ||
35 | #include "hid-ids.h" | 36 | #include "hid-ids.h" |
36 | 37 | ||
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 06888323828c..17bb88f782b6 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c | |||
@@ -304,11 +304,51 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, | |||
304 | return 1; | 304 | return 1; |
305 | } | 305 | } |
306 | 306 | ||
307 | static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, | ||
308 | struct hid_field *field, struct hid_usage *usage, unsigned long **bit, | ||
309 | int *max) | ||
310 | { | ||
311 | struct input_dev *input = hi->input; | ||
312 | |||
313 | __set_bit(INPUT_PROP_POINTER, input->propbit); | ||
314 | |||
315 | /* Basics */ | ||
316 | input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL); | ||
317 | |||
318 | __set_bit(REL_WHEEL, input->relbit); | ||
319 | |||
320 | __set_bit(BTN_TOOL_PEN, input->keybit); | ||
321 | __set_bit(BTN_TOUCH, input->keybit); | ||
322 | __set_bit(BTN_STYLUS, input->keybit); | ||
323 | __set_bit(BTN_STYLUS2, input->keybit); | ||
324 | __set_bit(BTN_LEFT, input->keybit); | ||
325 | __set_bit(BTN_RIGHT, input->keybit); | ||
326 | __set_bit(BTN_MIDDLE, input->keybit); | ||
327 | |||
328 | /* Pad */ | ||
329 | input->evbit[0] |= BIT(EV_MSC); | ||
330 | |||
331 | __set_bit(MSC_SERIAL, input->mscbit); | ||
332 | |||
333 | __set_bit(BTN_0, input->keybit); | ||
334 | __set_bit(BTN_1, input->keybit); | ||
335 | __set_bit(BTN_TOOL_FINGER, input->keybit); | ||
336 | |||
337 | /* Distance, rubber and mouse */ | ||
338 | __set_bit(BTN_TOOL_RUBBER, input->keybit); | ||
339 | __set_bit(BTN_TOOL_MOUSE, input->keybit); | ||
340 | |||
341 | input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); | ||
342 | input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); | ||
343 | input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); | ||
344 | input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); | ||
345 | |||
346 | return 0; | ||
347 | } | ||
348 | |||
307 | static int wacom_probe(struct hid_device *hdev, | 349 | static int wacom_probe(struct hid_device *hdev, |
308 | const struct hid_device_id *id) | 350 | const struct hid_device_id *id) |
309 | { | 351 | { |
310 | struct hid_input *hidinput; | ||
311 | struct input_dev *input; | ||
312 | struct wacom_data *wdata; | 352 | struct wacom_data *wdata; |
313 | int ret; | 353 | int ret; |
314 | 354 | ||
@@ -353,11 +393,7 @@ static int wacom_probe(struct hid_device *hdev, | |||
353 | if (ret) { | 393 | if (ret) { |
354 | hid_warn(hdev, "can't create sysfs battery attribute, err: %d\n", | 394 | hid_warn(hdev, "can't create sysfs battery attribute, err: %d\n", |
355 | ret); | 395 | ret); |
356 | /* | 396 | goto err_battery; |
357 | * battery attribute is not critical for the tablet, but if it | ||
358 | * failed then there is no need to create ac attribute | ||
359 | */ | ||
360 | goto move_on; | ||
361 | } | 397 | } |
362 | 398 | ||
363 | wdata->ac.properties = wacom_ac_props; | 399 | wdata->ac.properties = wacom_ac_props; |
@@ -371,51 +407,18 @@ static int wacom_probe(struct hid_device *hdev, | |||
371 | if (ret) { | 407 | if (ret) { |
372 | hid_warn(hdev, | 408 | hid_warn(hdev, |
373 | "can't create ac battery attribute, err: %d\n", ret); | 409 | "can't create ac battery attribute, err: %d\n", ret); |
374 | /* | 410 | goto err_ac; |
375 | * ac attribute is not critical for the tablet, but if it | ||
376 | * failed then we don't want to battery attribute to exist | ||
377 | */ | ||
378 | power_supply_unregister(&wdata->battery); | ||
379 | } | 411 | } |
380 | |||
381 | move_on: | ||
382 | #endif | 412 | #endif |
383 | hidinput = list_entry(hdev->inputs.next, struct hid_input, list); | ||
384 | input = hidinput->input; | ||
385 | |||
386 | /* Basics */ | ||
387 | input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL); | ||
388 | |||
389 | __set_bit(REL_WHEEL, input->relbit); | ||
390 | |||
391 | __set_bit(BTN_TOOL_PEN, input->keybit); | ||
392 | __set_bit(BTN_TOUCH, input->keybit); | ||
393 | __set_bit(BTN_STYLUS, input->keybit); | ||
394 | __set_bit(BTN_STYLUS2, input->keybit); | ||
395 | __set_bit(BTN_LEFT, input->keybit); | ||
396 | __set_bit(BTN_RIGHT, input->keybit); | ||
397 | __set_bit(BTN_MIDDLE, input->keybit); | ||
398 | |||
399 | /* Pad */ | ||
400 | input->evbit[0] |= BIT(EV_MSC); | ||
401 | |||
402 | __set_bit(MSC_SERIAL, input->mscbit); | ||
403 | |||
404 | __set_bit(BTN_0, input->keybit); | ||
405 | __set_bit(BTN_1, input->keybit); | ||
406 | __set_bit(BTN_TOOL_FINGER, input->keybit); | ||
407 | |||
408 | /* Distance, rubber and mouse */ | ||
409 | __set_bit(BTN_TOOL_RUBBER, input->keybit); | ||
410 | __set_bit(BTN_TOOL_MOUSE, input->keybit); | ||
411 | |||
412 | input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); | ||
413 | input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); | ||
414 | input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); | ||
415 | input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); | ||
416 | |||
417 | return 0; | 413 | return 0; |
418 | 414 | ||
415 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY | ||
416 | err_ac: | ||
417 | power_supply_unregister(&wdata->battery); | ||
418 | err_battery: | ||
419 | device_remove_file(&hdev->dev, &dev_attr_speed); | ||
420 | hid_hw_stop(hdev); | ||
421 | #endif | ||
419 | err_free: | 422 | err_free: |
420 | kfree(wdata); | 423 | kfree(wdata); |
421 | return ret; | 424 | return ret; |
@@ -426,6 +429,7 @@ static void wacom_remove(struct hid_device *hdev) | |||
426 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY | 429 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY |
427 | struct wacom_data *wdata = hid_get_drvdata(hdev); | 430 | struct wacom_data *wdata = hid_get_drvdata(hdev); |
428 | #endif | 431 | #endif |
432 | device_remove_file(&hdev->dev, &dev_attr_speed); | ||
429 | hid_hw_stop(hdev); | 433 | hid_hw_stop(hdev); |
430 | 434 | ||
431 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY | 435 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY |
@@ -448,6 +452,7 @@ static struct hid_driver wacom_driver = { | |||
448 | .probe = wacom_probe, | 452 | .probe = wacom_probe, |
449 | .remove = wacom_remove, | 453 | .remove = wacom_remove, |
450 | .raw_event = wacom_raw_event, | 454 | .raw_event = wacom_raw_event, |
455 | .input_mapped = wacom_input_mapped, | ||
451 | }; | 456 | }; |
452 | 457 | ||
453 | static int __init wacom_init(void) | 458 | static int __init wacom_init(void) |
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index a594383ce03d..76739c07fa3c 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c | |||
@@ -10,15 +10,18 @@ | |||
10 | * any later version. | 10 | * any later version. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/atomic.h> | 13 | #include <linux/completion.h> |
14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
15 | #include <linux/hid.h> | 15 | #include <linux/hid.h> |
16 | #include <linux/input.h> | 16 | #include <linux/input.h> |
17 | #include <linux/leds.h> | ||
17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/mutex.h> | ||
20 | #include <linux/power_supply.h> | ||
18 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
19 | #include "hid-ids.h" | 22 | #include "hid-ids.h" |
20 | 23 | ||
21 | #define WIIMOTE_VERSION "0.1" | 24 | #define WIIMOTE_VERSION "0.2" |
22 | #define WIIMOTE_NAME "Nintendo Wii Remote" | 25 | #define WIIMOTE_NAME "Nintendo Wii Remote" |
23 | #define WIIMOTE_BUFSIZE 32 | 26 | #define WIIMOTE_BUFSIZE 32 |
24 | 27 | ||
@@ -30,12 +33,26 @@ struct wiimote_buf { | |||
30 | struct wiimote_state { | 33 | struct wiimote_state { |
31 | spinlock_t lock; | 34 | spinlock_t lock; |
32 | __u8 flags; | 35 | __u8 flags; |
36 | __u8 accel_split[2]; | ||
37 | |||
38 | /* synchronous cmd requests */ | ||
39 | struct mutex sync; | ||
40 | struct completion ready; | ||
41 | int cmd; | ||
42 | __u32 opt; | ||
43 | |||
44 | /* results of synchronous requests */ | ||
45 | __u8 cmd_battery; | ||
46 | __u8 cmd_err; | ||
33 | }; | 47 | }; |
34 | 48 | ||
35 | struct wiimote_data { | 49 | struct wiimote_data { |
36 | atomic_t ready; | ||
37 | struct hid_device *hdev; | 50 | struct hid_device *hdev; |
38 | struct input_dev *input; | 51 | struct input_dev *input; |
52 | struct led_classdev *leds[4]; | ||
53 | struct input_dev *accel; | ||
54 | struct input_dev *ir; | ||
55 | struct power_supply battery; | ||
39 | 56 | ||
40 | spinlock_t qlock; | 57 | spinlock_t qlock; |
41 | __u8 head; | 58 | __u8 head; |
@@ -46,16 +63,47 @@ struct wiimote_data { | |||
46 | struct wiimote_state state; | 63 | struct wiimote_state state; |
47 | }; | 64 | }; |
48 | 65 | ||
49 | #define WIIPROTO_FLAG_LED1 0x01 | 66 | #define WIIPROTO_FLAG_LED1 0x01 |
50 | #define WIIPROTO_FLAG_LED2 0x02 | 67 | #define WIIPROTO_FLAG_LED2 0x02 |
51 | #define WIIPROTO_FLAG_LED3 0x04 | 68 | #define WIIPROTO_FLAG_LED3 0x04 |
52 | #define WIIPROTO_FLAG_LED4 0x08 | 69 | #define WIIPROTO_FLAG_LED4 0x08 |
70 | #define WIIPROTO_FLAG_RUMBLE 0x10 | ||
71 | #define WIIPROTO_FLAG_ACCEL 0x20 | ||
72 | #define WIIPROTO_FLAG_IR_BASIC 0x40 | ||
73 | #define WIIPROTO_FLAG_IR_EXT 0x80 | ||
74 | #define WIIPROTO_FLAG_IR_FULL 0xc0 /* IR_BASIC | IR_EXT */ | ||
53 | #define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ | 75 | #define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ |
54 | WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) | 76 | WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) |
77 | #define WIIPROTO_FLAGS_IR (WIIPROTO_FLAG_IR_BASIC | WIIPROTO_FLAG_IR_EXT | \ | ||
78 | WIIPROTO_FLAG_IR_FULL) | ||
79 | |||
80 | /* return flag for led \num */ | ||
81 | #define WIIPROTO_FLAG_LED(num) (WIIPROTO_FLAG_LED1 << (num - 1)) | ||
55 | 82 | ||
56 | enum wiiproto_reqs { | 83 | enum wiiproto_reqs { |
84 | WIIPROTO_REQ_NULL = 0x0, | ||
85 | WIIPROTO_REQ_RUMBLE = 0x10, | ||
57 | WIIPROTO_REQ_LED = 0x11, | 86 | WIIPROTO_REQ_LED = 0x11, |
87 | WIIPROTO_REQ_DRM = 0x12, | ||
88 | WIIPROTO_REQ_IR1 = 0x13, | ||
89 | WIIPROTO_REQ_SREQ = 0x15, | ||
90 | WIIPROTO_REQ_WMEM = 0x16, | ||
91 | WIIPROTO_REQ_RMEM = 0x17, | ||
92 | WIIPROTO_REQ_IR2 = 0x1a, | ||
93 | WIIPROTO_REQ_STATUS = 0x20, | ||
94 | WIIPROTO_REQ_DATA = 0x21, | ||
95 | WIIPROTO_REQ_RETURN = 0x22, | ||
58 | WIIPROTO_REQ_DRM_K = 0x30, | 96 | WIIPROTO_REQ_DRM_K = 0x30, |
97 | WIIPROTO_REQ_DRM_KA = 0x31, | ||
98 | WIIPROTO_REQ_DRM_KE = 0x32, | ||
99 | WIIPROTO_REQ_DRM_KAI = 0x33, | ||
100 | WIIPROTO_REQ_DRM_KEE = 0x34, | ||
101 | WIIPROTO_REQ_DRM_KAE = 0x35, | ||
102 | WIIPROTO_REQ_DRM_KIE = 0x36, | ||
103 | WIIPROTO_REQ_DRM_KAIE = 0x37, | ||
104 | WIIPROTO_REQ_DRM_E = 0x3d, | ||
105 | WIIPROTO_REQ_DRM_SKAI1 = 0x3e, | ||
106 | WIIPROTO_REQ_DRM_SKAI2 = 0x3f, | ||
59 | }; | 107 | }; |
60 | 108 | ||
61 | enum wiiproto_keys { | 109 | enum wiiproto_keys { |
@@ -87,8 +135,55 @@ static __u16 wiiproto_keymap[] = { | |||
87 | BTN_MODE, /* WIIPROTO_KEY_HOME */ | 135 | BTN_MODE, /* WIIPROTO_KEY_HOME */ |
88 | }; | 136 | }; |
89 | 137 | ||
90 | #define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \ | 138 | static enum power_supply_property wiimote_battery_props[] = { |
91 | dev)) | 139 | POWER_SUPPLY_PROP_CAPACITY |
140 | }; | ||
141 | |||
142 | /* requires the state.lock spinlock to be held */ | ||
143 | static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd, | ||
144 | __u32 opt) | ||
145 | { | ||
146 | return wdata->state.cmd == cmd && wdata->state.opt == opt; | ||
147 | } | ||
148 | |||
149 | /* requires the state.lock spinlock to be held */ | ||
150 | static inline void wiimote_cmd_complete(struct wiimote_data *wdata) | ||
151 | { | ||
152 | wdata->state.cmd = WIIPROTO_REQ_NULL; | ||
153 | complete(&wdata->state.ready); | ||
154 | } | ||
155 | |||
156 | static inline int wiimote_cmd_acquire(struct wiimote_data *wdata) | ||
157 | { | ||
158 | return mutex_lock_interruptible(&wdata->state.sync) ? -ERESTARTSYS : 0; | ||
159 | } | ||
160 | |||
161 | /* requires the state.lock spinlock to be held */ | ||
162 | static inline void wiimote_cmd_set(struct wiimote_data *wdata, int cmd, | ||
163 | __u32 opt) | ||
164 | { | ||
165 | INIT_COMPLETION(wdata->state.ready); | ||
166 | wdata->state.cmd = cmd; | ||
167 | wdata->state.opt = opt; | ||
168 | } | ||
169 | |||
170 | static inline void wiimote_cmd_release(struct wiimote_data *wdata) | ||
171 | { | ||
172 | mutex_unlock(&wdata->state.sync); | ||
173 | } | ||
174 | |||
175 | static inline int wiimote_cmd_wait(struct wiimote_data *wdata) | ||
176 | { | ||
177 | int ret; | ||
178 | |||
179 | ret = wait_for_completion_interruptible_timeout(&wdata->state.ready, HZ); | ||
180 | if (ret < 0) | ||
181 | return -ERESTARTSYS; | ||
182 | else if (ret == 0) | ||
183 | return -EIO; | ||
184 | else | ||
185 | return 0; | ||
186 | } | ||
92 | 187 | ||
93 | static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, | 188 | static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, |
94 | size_t count) | 189 | size_t count) |
@@ -168,6 +263,39 @@ static void wiimote_queue(struct wiimote_data *wdata, const __u8 *buffer, | |||
168 | spin_unlock_irqrestore(&wdata->qlock, flags); | 263 | spin_unlock_irqrestore(&wdata->qlock, flags); |
169 | } | 264 | } |
170 | 265 | ||
266 | /* | ||
267 | * This sets the rumble bit on the given output report if rumble is | ||
268 | * currently enabled. | ||
269 | * \cmd1 must point to the second byte in the output report => &cmd[1] | ||
270 | * This must be called on nearly every output report before passing it | ||
271 | * into the output queue! | ||
272 | */ | ||
273 | static inline void wiiproto_keep_rumble(struct wiimote_data *wdata, __u8 *cmd1) | ||
274 | { | ||
275 | if (wdata->state.flags & WIIPROTO_FLAG_RUMBLE) | ||
276 | *cmd1 |= 0x01; | ||
277 | } | ||
278 | |||
279 | static void wiiproto_req_rumble(struct wiimote_data *wdata, __u8 rumble) | ||
280 | { | ||
281 | __u8 cmd[2]; | ||
282 | |||
283 | rumble = !!rumble; | ||
284 | if (rumble == !!(wdata->state.flags & WIIPROTO_FLAG_RUMBLE)) | ||
285 | return; | ||
286 | |||
287 | if (rumble) | ||
288 | wdata->state.flags |= WIIPROTO_FLAG_RUMBLE; | ||
289 | else | ||
290 | wdata->state.flags &= ~WIIPROTO_FLAG_RUMBLE; | ||
291 | |||
292 | cmd[0] = WIIPROTO_REQ_RUMBLE; | ||
293 | cmd[1] = 0; | ||
294 | |||
295 | wiiproto_keep_rumble(wdata, &cmd[1]); | ||
296 | wiimote_queue(wdata, cmd, sizeof(cmd)); | ||
297 | } | ||
298 | |||
171 | static void wiiproto_req_leds(struct wiimote_data *wdata, int leds) | 299 | static void wiiproto_req_leds(struct wiimote_data *wdata, int leds) |
172 | { | 300 | { |
173 | __u8 cmd[2]; | 301 | __u8 cmd[2]; |
@@ -189,71 +317,439 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds) | |||
189 | if (leds & WIIPROTO_FLAG_LED4) | 317 | if (leds & WIIPROTO_FLAG_LED4) |
190 | cmd[1] |= 0x80; | 318 | cmd[1] |= 0x80; |
191 | 319 | ||
320 | wiiproto_keep_rumble(wdata, &cmd[1]); | ||
321 | wiimote_queue(wdata, cmd, sizeof(cmd)); | ||
322 | } | ||
323 | |||
324 | /* | ||
325 | * Check what peripherals of the wiimote are currently | ||
326 | * active and select a proper DRM that supports all of | ||
327 | * the requested data inputs. | ||
328 | */ | ||
329 | static __u8 select_drm(struct wiimote_data *wdata) | ||
330 | { | ||
331 | __u8 ir = wdata->state.flags & WIIPROTO_FLAGS_IR; | ||
332 | |||
333 | if (ir == WIIPROTO_FLAG_IR_BASIC) { | ||
334 | if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) | ||
335 | return WIIPROTO_REQ_DRM_KAIE; | ||
336 | else | ||
337 | return WIIPROTO_REQ_DRM_KIE; | ||
338 | } else if (ir == WIIPROTO_FLAG_IR_EXT) { | ||
339 | return WIIPROTO_REQ_DRM_KAI; | ||
340 | } else if (ir == WIIPROTO_FLAG_IR_FULL) { | ||
341 | return WIIPROTO_REQ_DRM_SKAI1; | ||
342 | } else { | ||
343 | if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) | ||
344 | return WIIPROTO_REQ_DRM_KA; | ||
345 | else | ||
346 | return WIIPROTO_REQ_DRM_K; | ||
347 | } | ||
348 | } | ||
349 | |||
350 | static void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm) | ||
351 | { | ||
352 | __u8 cmd[3]; | ||
353 | |||
354 | if (drm == WIIPROTO_REQ_NULL) | ||
355 | drm = select_drm(wdata); | ||
356 | |||
357 | cmd[0] = WIIPROTO_REQ_DRM; | ||
358 | cmd[1] = 0; | ||
359 | cmd[2] = drm; | ||
360 | |||
361 | wiiproto_keep_rumble(wdata, &cmd[1]); | ||
362 | wiimote_queue(wdata, cmd, sizeof(cmd)); | ||
363 | } | ||
364 | |||
365 | static void wiiproto_req_status(struct wiimote_data *wdata) | ||
366 | { | ||
367 | __u8 cmd[2]; | ||
368 | |||
369 | cmd[0] = WIIPROTO_REQ_SREQ; | ||
370 | cmd[1] = 0; | ||
371 | |||
372 | wiiproto_keep_rumble(wdata, &cmd[1]); | ||
373 | wiimote_queue(wdata, cmd, sizeof(cmd)); | ||
374 | } | ||
375 | |||
376 | static void wiiproto_req_accel(struct wiimote_data *wdata, __u8 accel) | ||
377 | { | ||
378 | accel = !!accel; | ||
379 | if (accel == !!(wdata->state.flags & WIIPROTO_FLAG_ACCEL)) | ||
380 | return; | ||
381 | |||
382 | if (accel) | ||
383 | wdata->state.flags |= WIIPROTO_FLAG_ACCEL; | ||
384 | else | ||
385 | wdata->state.flags &= ~WIIPROTO_FLAG_ACCEL; | ||
386 | |||
387 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | ||
388 | } | ||
389 | |||
390 | static void wiiproto_req_ir1(struct wiimote_data *wdata, __u8 flags) | ||
391 | { | ||
392 | __u8 cmd[2]; | ||
393 | |||
394 | cmd[0] = WIIPROTO_REQ_IR1; | ||
395 | cmd[1] = flags; | ||
396 | |||
397 | wiiproto_keep_rumble(wdata, &cmd[1]); | ||
398 | wiimote_queue(wdata, cmd, sizeof(cmd)); | ||
399 | } | ||
400 | |||
401 | static void wiiproto_req_ir2(struct wiimote_data *wdata, __u8 flags) | ||
402 | { | ||
403 | __u8 cmd[2]; | ||
404 | |||
405 | cmd[0] = WIIPROTO_REQ_IR2; | ||
406 | cmd[1] = flags; | ||
407 | |||
408 | wiiproto_keep_rumble(wdata, &cmd[1]); | ||
409 | wiimote_queue(wdata, cmd, sizeof(cmd)); | ||
410 | } | ||
411 | |||
412 | #define wiiproto_req_wreg(wdata, os, buf, sz) \ | ||
413 | wiiproto_req_wmem((wdata), false, (os), (buf), (sz)) | ||
414 | |||
415 | #define wiiproto_req_weeprom(wdata, os, buf, sz) \ | ||
416 | wiiproto_req_wmem((wdata), true, (os), (buf), (sz)) | ||
417 | |||
418 | static void wiiproto_req_wmem(struct wiimote_data *wdata, bool eeprom, | ||
419 | __u32 offset, const __u8 *buf, __u8 size) | ||
420 | { | ||
421 | __u8 cmd[22]; | ||
422 | |||
423 | if (size > 16 || size == 0) { | ||
424 | hid_warn(wdata->hdev, "Invalid length %d wmem request\n", size); | ||
425 | return; | ||
426 | } | ||
427 | |||
428 | memset(cmd, 0, sizeof(cmd)); | ||
429 | cmd[0] = WIIPROTO_REQ_WMEM; | ||
430 | cmd[2] = (offset >> 16) & 0xff; | ||
431 | cmd[3] = (offset >> 8) & 0xff; | ||
432 | cmd[4] = offset & 0xff; | ||
433 | cmd[5] = size; | ||
434 | memcpy(&cmd[6], buf, size); | ||
435 | |||
436 | if (!eeprom) | ||
437 | cmd[1] |= 0x04; | ||
438 | |||
439 | wiiproto_keep_rumble(wdata, &cmd[1]); | ||
192 | wiimote_queue(wdata, cmd, sizeof(cmd)); | 440 | wiimote_queue(wdata, cmd, sizeof(cmd)); |
193 | } | 441 | } |
194 | 442 | ||
195 | #define wiifs_led_show_set(num) \ | 443 | /* requries the cmd-mutex to be held */ |
196 | static ssize_t wiifs_led_show_##num(struct device *dev, \ | 444 | static int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, |
197 | struct device_attribute *attr, char *buf) \ | 445 | const __u8 *wmem, __u8 size) |
198 | { \ | 446 | { |
199 | struct wiimote_data *wdata = dev_to_wii(dev); \ | 447 | unsigned long flags; |
200 | unsigned long flags; \ | 448 | int ret; |
201 | int state; \ | 449 | |
202 | \ | 450 | spin_lock_irqsave(&wdata->state.lock, flags); |
203 | if (!atomic_read(&wdata->ready)) \ | 451 | wiimote_cmd_set(wdata, WIIPROTO_REQ_WMEM, 0); |
204 | return -EBUSY; \ | 452 | wiiproto_req_wreg(wdata, offset, wmem, size); |
205 | \ | 453 | spin_unlock_irqrestore(&wdata->state.lock, flags); |
206 | spin_lock_irqsave(&wdata->state.lock, flags); \ | 454 | |
207 | state = !!(wdata->state.flags & WIIPROTO_FLAG_LED##num); \ | 455 | ret = wiimote_cmd_wait(wdata); |
208 | spin_unlock_irqrestore(&wdata->state.lock, flags); \ | 456 | if (!ret && wdata->state.cmd_err) |
209 | \ | 457 | ret = -EIO; |
210 | return sprintf(buf, "%d\n", state); \ | 458 | |
211 | } \ | 459 | return ret; |
212 | static ssize_t wiifs_led_set_##num(struct device *dev, \ | 460 | } |
213 | struct device_attribute *attr, const char *buf, size_t count) \ | 461 | |
214 | { \ | 462 | static int wiimote_battery_get_property(struct power_supply *psy, |
215 | struct wiimote_data *wdata = dev_to_wii(dev); \ | 463 | enum power_supply_property psp, |
216 | int tmp = simple_strtoul(buf, NULL, 10); \ | 464 | union power_supply_propval *val) |
217 | unsigned long flags; \ | 465 | { |
218 | __u8 state; \ | 466 | struct wiimote_data *wdata = container_of(psy, |
219 | \ | 467 | struct wiimote_data, battery); |
220 | if (!atomic_read(&wdata->ready)) \ | 468 | int ret = 0, state; |
221 | return -EBUSY; \ | 469 | unsigned long flags; |
222 | \ | 470 | |
223 | spin_lock_irqsave(&wdata->state.lock, flags); \ | 471 | ret = wiimote_cmd_acquire(wdata); |
224 | \ | 472 | if (ret) |
225 | state = wdata->state.flags; \ | 473 | return ret; |
226 | \ | 474 | |
227 | if (tmp) \ | 475 | spin_lock_irqsave(&wdata->state.lock, flags); |
228 | wiiproto_req_leds(wdata, state | WIIPROTO_FLAG_LED##num);\ | 476 | wiimote_cmd_set(wdata, WIIPROTO_REQ_SREQ, 0); |
229 | else \ | 477 | wiiproto_req_status(wdata); |
230 | wiiproto_req_leds(wdata, state & ~WIIPROTO_FLAG_LED##num);\ | 478 | spin_unlock_irqrestore(&wdata->state.lock, flags); |
231 | \ | 479 | |
232 | spin_unlock_irqrestore(&wdata->state.lock, flags); \ | 480 | ret = wiimote_cmd_wait(wdata); |
233 | \ | 481 | state = wdata->state.cmd_battery; |
234 | return count; \ | 482 | wiimote_cmd_release(wdata); |
235 | } \ | 483 | |
236 | static DEVICE_ATTR(led##num, S_IRUGO | S_IWUSR, wiifs_led_show_##num, \ | 484 | if (ret) |
237 | wiifs_led_set_##num) | 485 | return ret; |
238 | 486 | ||
239 | wiifs_led_show_set(1); | 487 | switch (psp) { |
240 | wiifs_led_show_set(2); | 488 | case POWER_SUPPLY_PROP_CAPACITY: |
241 | wiifs_led_show_set(3); | 489 | val->intval = state * 100 / 255; |
242 | wiifs_led_show_set(4); | 490 | break; |
243 | 491 | default: | |
244 | static int wiimote_input_event(struct input_dev *dev, unsigned int type, | 492 | ret = -EINVAL; |
245 | unsigned int code, int value) | 493 | break; |
494 | } | ||
495 | |||
496 | return ret; | ||
497 | } | ||
498 | |||
499 | static int wiimote_init_ir(struct wiimote_data *wdata, __u16 mode) | ||
500 | { | ||
501 | int ret; | ||
502 | unsigned long flags; | ||
503 | __u8 format = 0; | ||
504 | static const __u8 data_enable[] = { 0x01 }; | ||
505 | static const __u8 data_sens1[] = { 0x02, 0x00, 0x00, 0x71, 0x01, | ||
506 | 0x00, 0xaa, 0x00, 0x64 }; | ||
507 | static const __u8 data_sens2[] = { 0x63, 0x03 }; | ||
508 | static const __u8 data_fin[] = { 0x08 }; | ||
509 | |||
510 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
511 | |||
512 | if (mode == (wdata->state.flags & WIIPROTO_FLAGS_IR)) { | ||
513 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | if (mode == 0) { | ||
518 | wdata->state.flags &= ~WIIPROTO_FLAGS_IR; | ||
519 | wiiproto_req_ir1(wdata, 0); | ||
520 | wiiproto_req_ir2(wdata, 0); | ||
521 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | ||
522 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
527 | |||
528 | ret = wiimote_cmd_acquire(wdata); | ||
529 | if (ret) | ||
530 | return ret; | ||
531 | |||
532 | /* send PIXEL CLOCK ENABLE cmd first */ | ||
533 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
534 | wiimote_cmd_set(wdata, WIIPROTO_REQ_IR1, 0); | ||
535 | wiiproto_req_ir1(wdata, 0x06); | ||
536 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
537 | |||
538 | ret = wiimote_cmd_wait(wdata); | ||
539 | if (ret) | ||
540 | goto unlock; | ||
541 | if (wdata->state.cmd_err) { | ||
542 | ret = -EIO; | ||
543 | goto unlock; | ||
544 | } | ||
545 | |||
546 | /* enable IR LOGIC */ | ||
547 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
548 | wiimote_cmd_set(wdata, WIIPROTO_REQ_IR2, 0); | ||
549 | wiiproto_req_ir2(wdata, 0x06); | ||
550 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
551 | |||
552 | ret = wiimote_cmd_wait(wdata); | ||
553 | if (ret) | ||
554 | goto unlock; | ||
555 | if (wdata->state.cmd_err) { | ||
556 | ret = -EIO; | ||
557 | goto unlock; | ||
558 | } | ||
559 | |||
560 | /* enable IR cam but do not make it send data, yet */ | ||
561 | ret = wiimote_cmd_write(wdata, 0xb00030, data_enable, | ||
562 | sizeof(data_enable)); | ||
563 | if (ret) | ||
564 | goto unlock; | ||
565 | |||
566 | /* write first sensitivity block */ | ||
567 | ret = wiimote_cmd_write(wdata, 0xb00000, data_sens1, | ||
568 | sizeof(data_sens1)); | ||
569 | if (ret) | ||
570 | goto unlock; | ||
571 | |||
572 | /* write second sensitivity block */ | ||
573 | ret = wiimote_cmd_write(wdata, 0xb0001a, data_sens2, | ||
574 | sizeof(data_sens2)); | ||
575 | if (ret) | ||
576 | goto unlock; | ||
577 | |||
578 | /* put IR cam into desired state */ | ||
579 | switch (mode) { | ||
580 | case WIIPROTO_FLAG_IR_FULL: | ||
581 | format = 5; | ||
582 | break; | ||
583 | case WIIPROTO_FLAG_IR_EXT: | ||
584 | format = 3; | ||
585 | break; | ||
586 | case WIIPROTO_FLAG_IR_BASIC: | ||
587 | format = 1; | ||
588 | break; | ||
589 | } | ||
590 | ret = wiimote_cmd_write(wdata, 0xb00033, &format, sizeof(format)); | ||
591 | if (ret) | ||
592 | goto unlock; | ||
593 | |||
594 | /* make IR cam send data */ | ||
595 | ret = wiimote_cmd_write(wdata, 0xb00030, data_fin, sizeof(data_fin)); | ||
596 | if (ret) | ||
597 | goto unlock; | ||
598 | |||
599 | /* request new DRM mode compatible to IR mode */ | ||
600 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
601 | wdata->state.flags &= ~WIIPROTO_FLAGS_IR; | ||
602 | wdata->state.flags |= mode & WIIPROTO_FLAGS_IR; | ||
603 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | ||
604 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
605 | |||
606 | unlock: | ||
607 | wiimote_cmd_release(wdata); | ||
608 | return ret; | ||
609 | } | ||
610 | |||
611 | static enum led_brightness wiimote_leds_get(struct led_classdev *led_dev) | ||
612 | { | ||
613 | struct wiimote_data *wdata; | ||
614 | struct device *dev = led_dev->dev->parent; | ||
615 | int i; | ||
616 | unsigned long flags; | ||
617 | bool value = false; | ||
618 | |||
619 | wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); | ||
620 | |||
621 | for (i = 0; i < 4; ++i) { | ||
622 | if (wdata->leds[i] == led_dev) { | ||
623 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
624 | value = wdata->state.flags & WIIPROTO_FLAG_LED(i + 1); | ||
625 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
626 | break; | ||
627 | } | ||
628 | } | ||
629 | |||
630 | return value ? LED_FULL : LED_OFF; | ||
631 | } | ||
632 | |||
633 | static void wiimote_leds_set(struct led_classdev *led_dev, | ||
634 | enum led_brightness value) | ||
635 | { | ||
636 | struct wiimote_data *wdata; | ||
637 | struct device *dev = led_dev->dev->parent; | ||
638 | int i; | ||
639 | unsigned long flags; | ||
640 | __u8 state, flag; | ||
641 | |||
642 | wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev)); | ||
643 | |||
644 | for (i = 0; i < 4; ++i) { | ||
645 | if (wdata->leds[i] == led_dev) { | ||
646 | flag = WIIPROTO_FLAG_LED(i + 1); | ||
647 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
648 | state = wdata->state.flags; | ||
649 | if (value == LED_OFF) | ||
650 | wiiproto_req_leds(wdata, state & ~flag); | ||
651 | else | ||
652 | wiiproto_req_leds(wdata, state | flag); | ||
653 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
654 | break; | ||
655 | } | ||
656 | } | ||
657 | } | ||
658 | |||
659 | static int wiimote_ff_play(struct input_dev *dev, void *data, | ||
660 | struct ff_effect *eff) | ||
246 | { | 661 | { |
247 | struct wiimote_data *wdata = input_get_drvdata(dev); | 662 | struct wiimote_data *wdata = input_get_drvdata(dev); |
663 | __u8 value; | ||
664 | unsigned long flags; | ||
665 | |||
666 | /* | ||
667 | * The wiimote supports only a single rumble motor so if any magnitude | ||
668 | * is set to non-zero then we start the rumble motor. If both are set to | ||
669 | * zero, we stop the rumble motor. | ||
670 | */ | ||
248 | 671 | ||
249 | if (!atomic_read(&wdata->ready)) | 672 | if (eff->u.rumble.strong_magnitude || eff->u.rumble.weak_magnitude) |
250 | return -EBUSY; | 673 | value = 1; |
251 | /* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */ | 674 | else |
252 | smp_rmb(); | 675 | value = 0; |
676 | |||
677 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
678 | wiiproto_req_rumble(wdata, value); | ||
679 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
253 | 680 | ||
254 | return 0; | 681 | return 0; |
255 | } | 682 | } |
256 | 683 | ||
684 | static int wiimote_input_open(struct input_dev *dev) | ||
685 | { | ||
686 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
687 | |||
688 | return hid_hw_open(wdata->hdev); | ||
689 | } | ||
690 | |||
691 | static void wiimote_input_close(struct input_dev *dev) | ||
692 | { | ||
693 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
694 | |||
695 | hid_hw_close(wdata->hdev); | ||
696 | } | ||
697 | |||
698 | static int wiimote_accel_open(struct input_dev *dev) | ||
699 | { | ||
700 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
701 | int ret; | ||
702 | unsigned long flags; | ||
703 | |||
704 | ret = hid_hw_open(wdata->hdev); | ||
705 | if (ret) | ||
706 | return ret; | ||
707 | |||
708 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
709 | wiiproto_req_accel(wdata, true); | ||
710 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
711 | |||
712 | return 0; | ||
713 | } | ||
714 | |||
715 | static void wiimote_accel_close(struct input_dev *dev) | ||
716 | { | ||
717 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
718 | unsigned long flags; | ||
719 | |||
720 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
721 | wiiproto_req_accel(wdata, false); | ||
722 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
723 | |||
724 | hid_hw_close(wdata->hdev); | ||
725 | } | ||
726 | |||
727 | static int wiimote_ir_open(struct input_dev *dev) | ||
728 | { | ||
729 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
730 | int ret; | ||
731 | |||
732 | ret = hid_hw_open(wdata->hdev); | ||
733 | if (ret) | ||
734 | return ret; | ||
735 | |||
736 | ret = wiimote_init_ir(wdata, WIIPROTO_FLAG_IR_BASIC); | ||
737 | if (ret) { | ||
738 | hid_hw_close(wdata->hdev); | ||
739 | return ret; | ||
740 | } | ||
741 | |||
742 | return 0; | ||
743 | } | ||
744 | |||
745 | static void wiimote_ir_close(struct input_dev *dev) | ||
746 | { | ||
747 | struct wiimote_data *wdata = input_get_drvdata(dev); | ||
748 | |||
749 | wiimote_init_ir(wdata, 0); | ||
750 | hid_hw_close(wdata->hdev); | ||
751 | } | ||
752 | |||
257 | static void handler_keys(struct wiimote_data *wdata, const __u8 *payload) | 753 | static void handler_keys(struct wiimote_data *wdata, const __u8 *payload) |
258 | { | 754 | { |
259 | input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_LEFT], | 755 | input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_LEFT], |
@@ -281,6 +777,210 @@ static void handler_keys(struct wiimote_data *wdata, const __u8 *payload) | |||
281 | input_sync(wdata->input); | 777 | input_sync(wdata->input); |
282 | } | 778 | } |
283 | 779 | ||
780 | static void handler_accel(struct wiimote_data *wdata, const __u8 *payload) | ||
781 | { | ||
782 | __u16 x, y, z; | ||
783 | |||
784 | if (!(wdata->state.flags & WIIPROTO_FLAG_ACCEL)) | ||
785 | return; | ||
786 | |||
787 | /* | ||
788 | * payload is: BB BB XX YY ZZ | ||
789 | * Accelerometer data is encoded into 3 10bit values. XX, YY and ZZ | ||
790 | * contain the upper 8 bits of each value. The lower 2 bits are | ||
791 | * contained in the buttons data BB BB. | ||
792 | * Bits 6 and 7 of the first buttons byte BB is the lower 2 bits of the | ||
793 | * X accel value. Bit 5 of the second buttons byte is the 2nd bit of Y | ||
794 | * accel value and bit 6 is the second bit of the Z value. | ||
795 | * The first bit of Y and Z values is not available and always set to 0. | ||
796 | * 0x200 is returned on no movement. | ||
797 | */ | ||
798 | |||
799 | x = payload[2] << 2; | ||
800 | y = payload[3] << 2; | ||
801 | z = payload[4] << 2; | ||
802 | |||
803 | x |= (payload[0] >> 5) & 0x3; | ||
804 | y |= (payload[1] >> 4) & 0x2; | ||
805 | z |= (payload[1] >> 5) & 0x2; | ||
806 | |||
807 | input_report_abs(wdata->accel, ABS_RX, x - 0x200); | ||
808 | input_report_abs(wdata->accel, ABS_RY, y - 0x200); | ||
809 | input_report_abs(wdata->accel, ABS_RZ, z - 0x200); | ||
810 | input_sync(wdata->accel); | ||
811 | } | ||
812 | |||
813 | #define ir_to_input0(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \ | ||
814 | ABS_HAT0X, ABS_HAT0Y) | ||
815 | #define ir_to_input1(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \ | ||
816 | ABS_HAT1X, ABS_HAT1Y) | ||
817 | #define ir_to_input2(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \ | ||
818 | ABS_HAT2X, ABS_HAT2Y) | ||
819 | #define ir_to_input3(wdata, ir, packed) __ir_to_input((wdata), (ir), (packed), \ | ||
820 | ABS_HAT3X, ABS_HAT3Y) | ||
821 | |||
822 | static void __ir_to_input(struct wiimote_data *wdata, const __u8 *ir, | ||
823 | bool packed, __u8 xid, __u8 yid) | ||
824 | { | ||
825 | __u16 x, y; | ||
826 | |||
827 | if (!(wdata->state.flags & WIIPROTO_FLAGS_IR)) | ||
828 | return; | ||
829 | |||
830 | /* | ||
831 | * Basic IR data is encoded into 3 bytes. The first two bytes are the | ||
832 | * upper 8 bit of the X/Y data, the 3rd byte contains the lower 2 bits | ||
833 | * of both. | ||
834 | * If data is packed, then the 3rd byte is put first and slightly | ||
835 | * reordered. This allows to interleave packed and non-packed data to | ||
836 | * have two IR sets in 5 bytes instead of 6. | ||
837 | * The resulting 10bit X/Y values are passed to the ABS_HATXY input dev. | ||
838 | */ | ||
839 | |||
840 | if (packed) { | ||
841 | x = ir[1] << 2; | ||
842 | y = ir[2] << 2; | ||
843 | |||
844 | x |= ir[0] & 0x3; | ||
845 | y |= (ir[0] >> 2) & 0x3; | ||
846 | } else { | ||
847 | x = ir[0] << 2; | ||
848 | y = ir[1] << 2; | ||
849 | |||
850 | x |= (ir[2] >> 4) & 0x3; | ||
851 | y |= (ir[2] >> 6) & 0x3; | ||
852 | } | ||
853 | |||
854 | input_report_abs(wdata->ir, xid, x); | ||
855 | input_report_abs(wdata->ir, yid, y); | ||
856 | } | ||
857 | |||
858 | static void handler_status(struct wiimote_data *wdata, const __u8 *payload) | ||
859 | { | ||
860 | handler_keys(wdata, payload); | ||
861 | |||
862 | /* on status reports the drm is reset so we need to resend the drm */ | ||
863 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | ||
864 | |||
865 | if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_SREQ, 0)) { | ||
866 | wdata->state.cmd_battery = payload[5]; | ||
867 | wiimote_cmd_complete(wdata); | ||
868 | } | ||
869 | } | ||
870 | |||
871 | static void handler_data(struct wiimote_data *wdata, const __u8 *payload) | ||
872 | { | ||
873 | handler_keys(wdata, payload); | ||
874 | } | ||
875 | |||
876 | static void handler_return(struct wiimote_data *wdata, const __u8 *payload) | ||
877 | { | ||
878 | __u8 err = payload[3]; | ||
879 | __u8 cmd = payload[2]; | ||
880 | |||
881 | handler_keys(wdata, payload); | ||
882 | |||
883 | if (wiimote_cmd_pending(wdata, cmd, 0)) { | ||
884 | wdata->state.cmd_err = err; | ||
885 | wiimote_cmd_complete(wdata); | ||
886 | } else if (err) { | ||
887 | hid_warn(wdata->hdev, "Remote error %hhu on req %hhu\n", err, | ||
888 | cmd); | ||
889 | } | ||
890 | } | ||
891 | |||
892 | static void handler_drm_KA(struct wiimote_data *wdata, const __u8 *payload) | ||
893 | { | ||
894 | handler_keys(wdata, payload); | ||
895 | handler_accel(wdata, payload); | ||
896 | } | ||
897 | |||
898 | static void handler_drm_KE(struct wiimote_data *wdata, const __u8 *payload) | ||
899 | { | ||
900 | handler_keys(wdata, payload); | ||
901 | } | ||
902 | |||
903 | static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload) | ||
904 | { | ||
905 | handler_keys(wdata, payload); | ||
906 | handler_accel(wdata, payload); | ||
907 | ir_to_input0(wdata, &payload[5], false); | ||
908 | ir_to_input1(wdata, &payload[8], false); | ||
909 | ir_to_input2(wdata, &payload[11], false); | ||
910 | ir_to_input3(wdata, &payload[14], false); | ||
911 | input_sync(wdata->ir); | ||
912 | } | ||
913 | |||
914 | static void handler_drm_KEE(struct wiimote_data *wdata, const __u8 *payload) | ||
915 | { | ||
916 | handler_keys(wdata, payload); | ||
917 | } | ||
918 | |||
919 | static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload) | ||
920 | { | ||
921 | handler_keys(wdata, payload); | ||
922 | ir_to_input0(wdata, &payload[2], false); | ||
923 | ir_to_input1(wdata, &payload[4], true); | ||
924 | ir_to_input2(wdata, &payload[7], false); | ||
925 | ir_to_input3(wdata, &payload[9], true); | ||
926 | input_sync(wdata->ir); | ||
927 | } | ||
928 | |||
929 | static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload) | ||
930 | { | ||
931 | handler_keys(wdata, payload); | ||
932 | handler_accel(wdata, payload); | ||
933 | } | ||
934 | |||
935 | static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload) | ||
936 | { | ||
937 | handler_keys(wdata, payload); | ||
938 | handler_accel(wdata, payload); | ||
939 | ir_to_input0(wdata, &payload[5], false); | ||
940 | ir_to_input1(wdata, &payload[7], true); | ||
941 | ir_to_input2(wdata, &payload[10], false); | ||
942 | ir_to_input3(wdata, &payload[12], true); | ||
943 | input_sync(wdata->ir); | ||
944 | } | ||
945 | |||
946 | static void handler_drm_E(struct wiimote_data *wdata, const __u8 *payload) | ||
947 | { | ||
948 | } | ||
949 | |||
950 | static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload) | ||
951 | { | ||
952 | handler_keys(wdata, payload); | ||
953 | |||
954 | wdata->state.accel_split[0] = payload[2]; | ||
955 | wdata->state.accel_split[1] = (payload[0] >> 1) & (0x10 | 0x20); | ||
956 | wdata->state.accel_split[1] |= (payload[1] << 1) & (0x40 | 0x80); | ||
957 | |||
958 | ir_to_input0(wdata, &payload[3], false); | ||
959 | ir_to_input1(wdata, &payload[12], false); | ||
960 | input_sync(wdata->ir); | ||
961 | } | ||
962 | |||
963 | static void handler_drm_SKAI2(struct wiimote_data *wdata, const __u8 *payload) | ||
964 | { | ||
965 | __u8 buf[5]; | ||
966 | |||
967 | handler_keys(wdata, payload); | ||
968 | |||
969 | wdata->state.accel_split[1] |= (payload[0] >> 5) & (0x01 | 0x02); | ||
970 | wdata->state.accel_split[1] |= (payload[1] >> 3) & (0x04 | 0x08); | ||
971 | |||
972 | buf[0] = 0; | ||
973 | buf[1] = 0; | ||
974 | buf[2] = wdata->state.accel_split[0]; | ||
975 | buf[3] = payload[2]; | ||
976 | buf[4] = wdata->state.accel_split[1]; | ||
977 | handler_accel(wdata, buf); | ||
978 | |||
979 | ir_to_input2(wdata, &payload[3], false); | ||
980 | ir_to_input3(wdata, &payload[12], false); | ||
981 | input_sync(wdata->ir); | ||
982 | } | ||
983 | |||
284 | struct wiiproto_handler { | 984 | struct wiiproto_handler { |
285 | __u8 id; | 985 | __u8 id; |
286 | size_t size; | 986 | size_t size; |
@@ -288,7 +988,20 @@ struct wiiproto_handler { | |||
288 | }; | 988 | }; |
289 | 989 | ||
290 | static struct wiiproto_handler handlers[] = { | 990 | static struct wiiproto_handler handlers[] = { |
991 | { .id = WIIPROTO_REQ_STATUS, .size = 6, .func = handler_status }, | ||
992 | { .id = WIIPROTO_REQ_DATA, .size = 21, .func = handler_data }, | ||
993 | { .id = WIIPROTO_REQ_RETURN, .size = 4, .func = handler_return }, | ||
291 | { .id = WIIPROTO_REQ_DRM_K, .size = 2, .func = handler_keys }, | 994 | { .id = WIIPROTO_REQ_DRM_K, .size = 2, .func = handler_keys }, |
995 | { .id = WIIPROTO_REQ_DRM_KA, .size = 5, .func = handler_drm_KA }, | ||
996 | { .id = WIIPROTO_REQ_DRM_KE, .size = 10, .func = handler_drm_KE }, | ||
997 | { .id = WIIPROTO_REQ_DRM_KAI, .size = 17, .func = handler_drm_KAI }, | ||
998 | { .id = WIIPROTO_REQ_DRM_KEE, .size = 21, .func = handler_drm_KEE }, | ||
999 | { .id = WIIPROTO_REQ_DRM_KAE, .size = 21, .func = handler_drm_KAE }, | ||
1000 | { .id = WIIPROTO_REQ_DRM_KIE, .size = 21, .func = handler_drm_KIE }, | ||
1001 | { .id = WIIPROTO_REQ_DRM_KAIE, .size = 21, .func = handler_drm_KAIE }, | ||
1002 | { .id = WIIPROTO_REQ_DRM_E, .size = 21, .func = handler_drm_E }, | ||
1003 | { .id = WIIPROTO_REQ_DRM_SKAI1, .size = 21, .func = handler_drm_SKAI1 }, | ||
1004 | { .id = WIIPROTO_REQ_DRM_SKAI2, .size = 21, .func = handler_drm_SKAI2 }, | ||
292 | { .id = 0 } | 1005 | { .id = 0 } |
293 | }; | 1006 | }; |
294 | 1007 | ||
@@ -299,11 +1012,7 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, | |||
299 | struct wiiproto_handler *h; | 1012 | struct wiiproto_handler *h; |
300 | int i; | 1013 | int i; |
301 | unsigned long flags; | 1014 | unsigned long flags; |
302 | 1015 | bool handled = false; | |
303 | if (!atomic_read(&wdata->ready)) | ||
304 | return -EBUSY; | ||
305 | /* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */ | ||
306 | smp_rmb(); | ||
307 | 1016 | ||
308 | if (size < 1) | 1017 | if (size < 1) |
309 | return -EINVAL; | 1018 | return -EINVAL; |
@@ -312,15 +1021,73 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, | |||
312 | 1021 | ||
313 | for (i = 0; handlers[i].id; ++i) { | 1022 | for (i = 0; handlers[i].id; ++i) { |
314 | h = &handlers[i]; | 1023 | h = &handlers[i]; |
315 | if (h->id == raw_data[0] && h->size < size) | 1024 | if (h->id == raw_data[0] && h->size < size) { |
316 | h->func(wdata, &raw_data[1]); | 1025 | h->func(wdata, &raw_data[1]); |
1026 | handled = true; | ||
1027 | } | ||
317 | } | 1028 | } |
318 | 1029 | ||
1030 | if (!handled) | ||
1031 | hid_warn(hdev, "Unhandled report %hhu size %d\n", raw_data[0], | ||
1032 | size); | ||
1033 | |||
319 | spin_unlock_irqrestore(&wdata->state.lock, flags); | 1034 | spin_unlock_irqrestore(&wdata->state.lock, flags); |
320 | 1035 | ||
321 | return 0; | 1036 | return 0; |
322 | } | 1037 | } |
323 | 1038 | ||
1039 | static void wiimote_leds_destroy(struct wiimote_data *wdata) | ||
1040 | { | ||
1041 | int i; | ||
1042 | struct led_classdev *led; | ||
1043 | |||
1044 | for (i = 0; i < 4; ++i) { | ||
1045 | if (wdata->leds[i]) { | ||
1046 | led = wdata->leds[i]; | ||
1047 | wdata->leds[i] = NULL; | ||
1048 | led_classdev_unregister(led); | ||
1049 | kfree(led); | ||
1050 | } | ||
1051 | } | ||
1052 | } | ||
1053 | |||
1054 | static int wiimote_leds_create(struct wiimote_data *wdata) | ||
1055 | { | ||
1056 | int i, ret; | ||
1057 | struct device *dev = &wdata->hdev->dev; | ||
1058 | size_t namesz = strlen(dev_name(dev)) + 9; | ||
1059 | struct led_classdev *led; | ||
1060 | char *name; | ||
1061 | |||
1062 | for (i = 0; i < 4; ++i) { | ||
1063 | led = kzalloc(sizeof(struct led_classdev) + namesz, GFP_KERNEL); | ||
1064 | if (!led) { | ||
1065 | ret = -ENOMEM; | ||
1066 | goto err; | ||
1067 | } | ||
1068 | name = (void*)&led[1]; | ||
1069 | snprintf(name, namesz, "%s:blue:p%d", dev_name(dev), i); | ||
1070 | led->name = name; | ||
1071 | led->brightness = 0; | ||
1072 | led->max_brightness = 1; | ||
1073 | led->brightness_get = wiimote_leds_get; | ||
1074 | led->brightness_set = wiimote_leds_set; | ||
1075 | |||
1076 | ret = led_classdev_register(dev, led); | ||
1077 | if (ret) { | ||
1078 | kfree(led); | ||
1079 | goto err; | ||
1080 | } | ||
1081 | wdata->leds[i] = led; | ||
1082 | } | ||
1083 | |||
1084 | return 0; | ||
1085 | |||
1086 | err: | ||
1087 | wiimote_leds_destroy(wdata); | ||
1088 | return ret; | ||
1089 | } | ||
1090 | |||
324 | static struct wiimote_data *wiimote_create(struct hid_device *hdev) | 1091 | static struct wiimote_data *wiimote_create(struct hid_device *hdev) |
325 | { | 1092 | { |
326 | struct wiimote_data *wdata; | 1093 | struct wiimote_data *wdata; |
@@ -331,16 +1098,15 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev) | |||
331 | return NULL; | 1098 | return NULL; |
332 | 1099 | ||
333 | wdata->input = input_allocate_device(); | 1100 | wdata->input = input_allocate_device(); |
334 | if (!wdata->input) { | 1101 | if (!wdata->input) |
335 | kfree(wdata); | 1102 | goto err; |
336 | return NULL; | ||
337 | } | ||
338 | 1103 | ||
339 | wdata->hdev = hdev; | 1104 | wdata->hdev = hdev; |
340 | hid_set_drvdata(hdev, wdata); | 1105 | hid_set_drvdata(hdev, wdata); |
341 | 1106 | ||
342 | input_set_drvdata(wdata->input, wdata); | 1107 | input_set_drvdata(wdata->input, wdata); |
343 | wdata->input->event = wiimote_input_event; | 1108 | wdata->input->open = wiimote_input_open; |
1109 | wdata->input->close = wiimote_input_close; | ||
344 | wdata->input->dev.parent = &wdata->hdev->dev; | 1110 | wdata->input->dev.parent = &wdata->hdev->dev; |
345 | wdata->input->id.bustype = wdata->hdev->bus; | 1111 | wdata->input->id.bustype = wdata->hdev->bus; |
346 | wdata->input->id.vendor = wdata->hdev->vendor; | 1112 | wdata->input->id.vendor = wdata->hdev->vendor; |
@@ -352,16 +1118,93 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev) | |||
352 | for (i = 0; i < WIIPROTO_KEY_COUNT; ++i) | 1118 | for (i = 0; i < WIIPROTO_KEY_COUNT; ++i) |
353 | set_bit(wiiproto_keymap[i], wdata->input->keybit); | 1119 | set_bit(wiiproto_keymap[i], wdata->input->keybit); |
354 | 1120 | ||
1121 | set_bit(FF_RUMBLE, wdata->input->ffbit); | ||
1122 | if (input_ff_create_memless(wdata->input, NULL, wiimote_ff_play)) | ||
1123 | goto err_input; | ||
1124 | |||
1125 | wdata->accel = input_allocate_device(); | ||
1126 | if (!wdata->accel) | ||
1127 | goto err_input; | ||
1128 | |||
1129 | input_set_drvdata(wdata->accel, wdata); | ||
1130 | wdata->accel->open = wiimote_accel_open; | ||
1131 | wdata->accel->close = wiimote_accel_close; | ||
1132 | wdata->accel->dev.parent = &wdata->hdev->dev; | ||
1133 | wdata->accel->id.bustype = wdata->hdev->bus; | ||
1134 | wdata->accel->id.vendor = wdata->hdev->vendor; | ||
1135 | wdata->accel->id.product = wdata->hdev->product; | ||
1136 | wdata->accel->id.version = wdata->hdev->version; | ||
1137 | wdata->accel->name = WIIMOTE_NAME " Accelerometer"; | ||
1138 | |||
1139 | set_bit(EV_ABS, wdata->accel->evbit); | ||
1140 | set_bit(ABS_RX, wdata->accel->absbit); | ||
1141 | set_bit(ABS_RY, wdata->accel->absbit); | ||
1142 | set_bit(ABS_RZ, wdata->accel->absbit); | ||
1143 | input_set_abs_params(wdata->accel, ABS_RX, -500, 500, 2, 4); | ||
1144 | input_set_abs_params(wdata->accel, ABS_RY, -500, 500, 2, 4); | ||
1145 | input_set_abs_params(wdata->accel, ABS_RZ, -500, 500, 2, 4); | ||
1146 | |||
1147 | wdata->ir = input_allocate_device(); | ||
1148 | if (!wdata->ir) | ||
1149 | goto err_ir; | ||
1150 | |||
1151 | input_set_drvdata(wdata->ir, wdata); | ||
1152 | wdata->ir->open = wiimote_ir_open; | ||
1153 | wdata->ir->close = wiimote_ir_close; | ||
1154 | wdata->ir->dev.parent = &wdata->hdev->dev; | ||
1155 | wdata->ir->id.bustype = wdata->hdev->bus; | ||
1156 | wdata->ir->id.vendor = wdata->hdev->vendor; | ||
1157 | wdata->ir->id.product = wdata->hdev->product; | ||
1158 | wdata->ir->id.version = wdata->hdev->version; | ||
1159 | wdata->ir->name = WIIMOTE_NAME " IR"; | ||
1160 | |||
1161 | set_bit(EV_ABS, wdata->ir->evbit); | ||
1162 | set_bit(ABS_HAT0X, wdata->ir->absbit); | ||
1163 | set_bit(ABS_HAT0Y, wdata->ir->absbit); | ||
1164 | set_bit(ABS_HAT1X, wdata->ir->absbit); | ||
1165 | set_bit(ABS_HAT1Y, wdata->ir->absbit); | ||
1166 | set_bit(ABS_HAT2X, wdata->ir->absbit); | ||
1167 | set_bit(ABS_HAT2Y, wdata->ir->absbit); | ||
1168 | set_bit(ABS_HAT3X, wdata->ir->absbit); | ||
1169 | set_bit(ABS_HAT3Y, wdata->ir->absbit); | ||
1170 | input_set_abs_params(wdata->ir, ABS_HAT0X, 0, 1023, 2, 4); | ||
1171 | input_set_abs_params(wdata->ir, ABS_HAT0Y, 0, 767, 2, 4); | ||
1172 | input_set_abs_params(wdata->ir, ABS_HAT1X, 0, 1023, 2, 4); | ||
1173 | input_set_abs_params(wdata->ir, ABS_HAT1Y, 0, 767, 2, 4); | ||
1174 | input_set_abs_params(wdata->ir, ABS_HAT2X, 0, 1023, 2, 4); | ||
1175 | input_set_abs_params(wdata->ir, ABS_HAT2Y, 0, 767, 2, 4); | ||
1176 | input_set_abs_params(wdata->ir, ABS_HAT3X, 0, 1023, 2, 4); | ||
1177 | input_set_abs_params(wdata->ir, ABS_HAT3Y, 0, 767, 2, 4); | ||
1178 | |||
355 | spin_lock_init(&wdata->qlock); | 1179 | spin_lock_init(&wdata->qlock); |
356 | INIT_WORK(&wdata->worker, wiimote_worker); | 1180 | INIT_WORK(&wdata->worker, wiimote_worker); |
357 | 1181 | ||
358 | spin_lock_init(&wdata->state.lock); | 1182 | spin_lock_init(&wdata->state.lock); |
1183 | init_completion(&wdata->state.ready); | ||
1184 | mutex_init(&wdata->state.sync); | ||
359 | 1185 | ||
360 | return wdata; | 1186 | return wdata; |
1187 | |||
1188 | err_ir: | ||
1189 | input_free_device(wdata->accel); | ||
1190 | err_input: | ||
1191 | input_free_device(wdata->input); | ||
1192 | err: | ||
1193 | kfree(wdata); | ||
1194 | return NULL; | ||
361 | } | 1195 | } |
362 | 1196 | ||
363 | static void wiimote_destroy(struct wiimote_data *wdata) | 1197 | static void wiimote_destroy(struct wiimote_data *wdata) |
364 | { | 1198 | { |
1199 | wiimote_leds_destroy(wdata); | ||
1200 | |||
1201 | power_supply_unregister(&wdata->battery); | ||
1202 | input_unregister_device(wdata->accel); | ||
1203 | input_unregister_device(wdata->ir); | ||
1204 | input_unregister_device(wdata->input); | ||
1205 | cancel_work_sync(&wdata->worker); | ||
1206 | hid_hw_stop(wdata->hdev); | ||
1207 | |||
365 | kfree(wdata); | 1208 | kfree(wdata); |
366 | } | 1209 | } |
367 | 1210 | ||
@@ -377,19 +1220,6 @@ static int wiimote_hid_probe(struct hid_device *hdev, | |||
377 | return -ENOMEM; | 1220 | return -ENOMEM; |
378 | } | 1221 | } |
379 | 1222 | ||
380 | ret = device_create_file(&hdev->dev, &dev_attr_led1); | ||
381 | if (ret) | ||
382 | goto err; | ||
383 | ret = device_create_file(&hdev->dev, &dev_attr_led2); | ||
384 | if (ret) | ||
385 | goto err; | ||
386 | ret = device_create_file(&hdev->dev, &dev_attr_led3); | ||
387 | if (ret) | ||
388 | goto err; | ||
389 | ret = device_create_file(&hdev->dev, &dev_attr_led4); | ||
390 | if (ret) | ||
391 | goto err; | ||
392 | |||
393 | ret = hid_parse(hdev); | 1223 | ret = hid_parse(hdev); |
394 | if (ret) { | 1224 | if (ret) { |
395 | hid_err(hdev, "HID parse failed\n"); | 1225 | hid_err(hdev, "HID parse failed\n"); |
@@ -402,15 +1232,41 @@ static int wiimote_hid_probe(struct hid_device *hdev, | |||
402 | goto err; | 1232 | goto err; |
403 | } | 1233 | } |
404 | 1234 | ||
405 | ret = input_register_device(wdata->input); | 1235 | ret = input_register_device(wdata->accel); |
406 | if (ret) { | 1236 | if (ret) { |
407 | hid_err(hdev, "Cannot register input device\n"); | 1237 | hid_err(hdev, "Cannot register input device\n"); |
408 | goto err_stop; | 1238 | goto err_stop; |
409 | } | 1239 | } |
410 | 1240 | ||
411 | /* smp_wmb: Write wdata->xy first before wdata->ready is set to 1 */ | 1241 | ret = input_register_device(wdata->ir); |
412 | smp_wmb(); | 1242 | if (ret) { |
413 | atomic_set(&wdata->ready, 1); | 1243 | hid_err(hdev, "Cannot register input device\n"); |
1244 | goto err_ir; | ||
1245 | } | ||
1246 | |||
1247 | ret = input_register_device(wdata->input); | ||
1248 | if (ret) { | ||
1249 | hid_err(hdev, "Cannot register input device\n"); | ||
1250 | goto err_input; | ||
1251 | } | ||
1252 | |||
1253 | wdata->battery.properties = wiimote_battery_props; | ||
1254 | wdata->battery.num_properties = ARRAY_SIZE(wiimote_battery_props); | ||
1255 | wdata->battery.get_property = wiimote_battery_get_property; | ||
1256 | wdata->battery.name = "wiimote_battery"; | ||
1257 | wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY; | ||
1258 | wdata->battery.use_for_apm = 0; | ||
1259 | |||
1260 | ret = power_supply_register(&wdata->hdev->dev, &wdata->battery); | ||
1261 | if (ret) { | ||
1262 | hid_err(hdev, "Cannot register battery device\n"); | ||
1263 | goto err_battery; | ||
1264 | } | ||
1265 | |||
1266 | ret = wiimote_leds_create(wdata); | ||
1267 | if (ret) | ||
1268 | goto err_free; | ||
1269 | |||
414 | hid_info(hdev, "New device registered\n"); | 1270 | hid_info(hdev, "New device registered\n"); |
415 | 1271 | ||
416 | /* by default set led1 after device initialization */ | 1272 | /* by default set led1 after device initialization */ |
@@ -420,15 +1276,26 @@ static int wiimote_hid_probe(struct hid_device *hdev, | |||
420 | 1276 | ||
421 | return 0; | 1277 | return 0; |
422 | 1278 | ||
1279 | err_free: | ||
1280 | wiimote_destroy(wdata); | ||
1281 | return ret; | ||
1282 | |||
1283 | err_battery: | ||
1284 | input_unregister_device(wdata->input); | ||
1285 | wdata->input = NULL; | ||
1286 | err_input: | ||
1287 | input_unregister_device(wdata->ir); | ||
1288 | wdata->ir = NULL; | ||
1289 | err_ir: | ||
1290 | input_unregister_device(wdata->accel); | ||
1291 | wdata->accel = NULL; | ||
423 | err_stop: | 1292 | err_stop: |
424 | hid_hw_stop(hdev); | 1293 | hid_hw_stop(hdev); |
425 | err: | 1294 | err: |
1295 | input_free_device(wdata->ir); | ||
1296 | input_free_device(wdata->accel); | ||
426 | input_free_device(wdata->input); | 1297 | input_free_device(wdata->input); |
427 | device_remove_file(&hdev->dev, &dev_attr_led1); | 1298 | kfree(wdata); |
428 | device_remove_file(&hdev->dev, &dev_attr_led2); | ||
429 | device_remove_file(&hdev->dev, &dev_attr_led3); | ||
430 | device_remove_file(&hdev->dev, &dev_attr_led4); | ||
431 | wiimote_destroy(wdata); | ||
432 | return ret; | 1299 | return ret; |
433 | } | 1300 | } |
434 | 1301 | ||
@@ -437,16 +1304,6 @@ static void wiimote_hid_remove(struct hid_device *hdev) | |||
437 | struct wiimote_data *wdata = hid_get_drvdata(hdev); | 1304 | struct wiimote_data *wdata = hid_get_drvdata(hdev); |
438 | 1305 | ||
439 | hid_info(hdev, "Device removed\n"); | 1306 | hid_info(hdev, "Device removed\n"); |
440 | |||
441 | device_remove_file(&hdev->dev, &dev_attr_led1); | ||
442 | device_remove_file(&hdev->dev, &dev_attr_led2); | ||
443 | device_remove_file(&hdev->dev, &dev_attr_led3); | ||
444 | device_remove_file(&hdev->dev, &dev_attr_led4); | ||
445 | |||
446 | hid_hw_stop(hdev); | ||
447 | input_unregister_device(wdata->input); | ||
448 | |||
449 | cancel_work_sync(&wdata->worker); | ||
450 | wiimote_destroy(wdata); | 1307 | wiimote_destroy(wdata); |
451 | } | 1308 | } |
452 | 1309 | ||
diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c index f31fab012f2f..f6ba81df71bd 100644 --- a/drivers/hid/hid-zpff.c +++ b/drivers/hid/hid-zpff.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/input.h> | 25 | #include <linux/input.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/usb.h> | 27 | #include <linux/usb.h> |
28 | #include <linux/module.h> | ||
28 | 29 | ||
29 | #include "hid-ids.h" | 30 | #include "hid-ids.h" |
30 | 31 | ||
diff --git a/drivers/hid/hid-zydacron.c b/drivers/hid/hid-zydacron.c index e90371508fd2..1ad85f2257b4 100644 --- a/drivers/hid/hid-zydacron.c +++ b/drivers/hid/hid-zydacron.c | |||
@@ -201,9 +201,7 @@ static void zc_remove(struct hid_device *hdev) | |||
201 | struct zc_device *zc = hid_get_drvdata(hdev); | 201 | struct zc_device *zc = hid_get_drvdata(hdev); |
202 | 202 | ||
203 | hid_hw_stop(hdev); | 203 | hid_hw_stop(hdev); |
204 | 204 | kfree(zc); | |
205 | if (NULL != zc) | ||
206 | kfree(zc); | ||
207 | } | 205 | } |
208 | 206 | ||
209 | static const struct hid_device_id zc_devices[] = { | 207 | static const struct hid_device_id zc_devices[] = { |
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index c79578b5a788..cf7d6d58e79f 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
@@ -259,7 +259,6 @@ static int hidraw_open(struct inode *inode, struct file *file) | |||
259 | 259 | ||
260 | mutex_lock(&minors_lock); | 260 | mutex_lock(&minors_lock); |
261 | if (!hidraw_table[minor]) { | 261 | if (!hidraw_table[minor]) { |
262 | kfree(list); | ||
263 | err = -ENODEV; | 262 | err = -ENODEV; |
264 | goto out_unlock; | 263 | goto out_unlock; |
265 | } | 264 | } |
@@ -272,8 +271,10 @@ static int hidraw_open(struct inode *inode, struct file *file) | |||
272 | dev = hidraw_table[minor]; | 271 | dev = hidraw_table[minor]; |
273 | if (!dev->open++) { | 272 | if (!dev->open++) { |
274 | err = hid_hw_power(dev->hid, PM_HINT_FULLON); | 273 | err = hid_hw_power(dev->hid, PM_HINT_FULLON); |
275 | if (err < 0) | 274 | if (err < 0) { |
275 | dev->open--; | ||
276 | goto out_unlock; | 276 | goto out_unlock; |
277 | } | ||
277 | 278 | ||
278 | err = hid_hw_open(dev->hid); | 279 | err = hid_hw_open(dev->hid); |
279 | if (err < 0) { | 280 | if (err < 0) { |
@@ -285,6 +286,8 @@ static int hidraw_open(struct inode *inode, struct file *file) | |||
285 | out_unlock: | 286 | out_unlock: |
286 | mutex_unlock(&minors_lock); | 287 | mutex_unlock(&minors_lock); |
287 | out: | 288 | out: |
289 | if (err < 0) | ||
290 | kfree(list); | ||
288 | return err; | 291 | return err; |
289 | 292 | ||
290 | } | 293 | } |
@@ -510,13 +513,12 @@ void hidraw_disconnect(struct hid_device *hid) | |||
510 | { | 513 | { |
511 | struct hidraw *hidraw = hid->hidraw; | 514 | struct hidraw *hidraw = hid->hidraw; |
512 | 515 | ||
516 | mutex_lock(&minors_lock); | ||
513 | hidraw->exist = 0; | 517 | hidraw->exist = 0; |
514 | 518 | ||
515 | device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); | 519 | device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); |
516 | 520 | ||
517 | mutex_lock(&minors_lock); | ||
518 | hidraw_table[hidraw->minor] = NULL; | 521 | hidraw_table[hidraw->minor] = NULL; |
519 | mutex_unlock(&minors_lock); | ||
520 | 522 | ||
521 | if (hidraw->open) { | 523 | if (hidraw->open) { |
522 | hid_hw_close(hid); | 524 | hid_hw_close(hid); |
@@ -524,6 +526,7 @@ void hidraw_disconnect(struct hid_device *hid) | |||
524 | } else { | 526 | } else { |
525 | kfree(hidraw); | 527 | kfree(hidraw); |
526 | } | 528 | } |
529 | mutex_unlock(&minors_lock); | ||
527 | } | 530 | } |
528 | EXPORT_SYMBOL_GPL(hidraw_disconnect); | 531 | EXPORT_SYMBOL_GPL(hidraw_disconnect); |
529 | 532 | ||
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index ad978f5748d3..b403fcef0b86 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -1270,7 +1270,7 @@ static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid) | |||
1270 | 1270 | ||
1271 | static void hid_cease_io(struct usbhid_device *usbhid) | 1271 | static void hid_cease_io(struct usbhid_device *usbhid) |
1272 | { | 1272 | { |
1273 | del_timer(&usbhid->io_retry); | 1273 | del_timer_sync(&usbhid->io_retry); |
1274 | usb_kill_urb(usbhid->urbin); | 1274 | usb_kill_urb(usbhid->urbin); |
1275 | usb_kill_urb(usbhid->urbctrl); | 1275 | usb_kill_urb(usbhid->urbctrl); |
1276 | usb_kill_urb(usbhid->urbout); | 1276 | usb_kill_urb(usbhid->urbout); |
@@ -1332,7 +1332,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
1332 | struct usbhid_device *usbhid = hid->driver_data; | 1332 | struct usbhid_device *usbhid = hid->driver_data; |
1333 | int status; | 1333 | int status; |
1334 | 1334 | ||
1335 | if (message.event & PM_EVENT_AUTO) { | 1335 | if (PMSG_IS_AUTO(message)) { |
1336 | spin_lock_irq(&usbhid->lock); /* Sync with error handler */ | 1336 | spin_lock_irq(&usbhid->lock); /* Sync with error handler */ |
1337 | if (!test_bit(HID_RESET_PENDING, &usbhid->iofl) | 1337 | if (!test_bit(HID_RESET_PENDING, &usbhid->iofl) |
1338 | && !test_bit(HID_CLEAR_HALT, &usbhid->iofl) | 1338 | && !test_bit(HID_CLEAR_HALT, &usbhid->iofl) |
@@ -1367,7 +1367,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
1367 | return -EIO; | 1367 | return -EIO; |
1368 | } | 1368 | } |
1369 | 1369 | ||
1370 | if (!ignoreled && (message.event & PM_EVENT_AUTO)) { | 1370 | if (!ignoreled && PMSG_IS_AUTO(message)) { |
1371 | spin_lock_irq(&usbhid->lock); | 1371 | spin_lock_irq(&usbhid->lock); |
1372 | if (test_bit(HID_LED_ON, &usbhid->iofl)) { | 1372 | if (test_bit(HID_LED_ON, &usbhid->iofl)) { |
1373 | spin_unlock_irq(&usbhid->lock); | 1373 | spin_unlock_irq(&usbhid->lock); |
@@ -1380,8 +1380,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
1380 | hid_cancel_delayed_stuff(usbhid); | 1380 | hid_cancel_delayed_stuff(usbhid); |
1381 | hid_cease_io(usbhid); | 1381 | hid_cease_io(usbhid); |
1382 | 1382 | ||
1383 | if ((message.event & PM_EVENT_AUTO) && | 1383 | if (PMSG_IS_AUTO(message) && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) { |
1384 | test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) { | ||
1385 | /* lost race against keypresses */ | 1384 | /* lost race against keypresses */ |
1386 | status = hid_start_in(hid); | 1385 | status = hid_start_in(hid); |
1387 | if (status < 0) | 1386 | if (status < 0) |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 621959d5cc42..5028d60a22a1 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/hid.h> | 18 | #include <linux/hid.h> |
19 | #include <linux/export.h> | ||
19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
20 | 21 | ||
21 | #include "../hid-ids.h" | 22 | #include "../hid-ids.h" |
@@ -47,6 +48,7 @@ static const struct hid_blacklist { | |||
47 | { USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL }, | 48 | { USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL }, |
48 | 49 | ||
49 | { USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH, HID_QUIRK_MULTI_INPUT }, | 50 | { USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH, HID_QUIRK_MULTI_INPUT }, |
51 | { USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD, HID_QUIRK_MULTI_INPUT }, | ||
50 | { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | 52 | { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, |
51 | { USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT }, | 53 | { USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT }, |
52 | { USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS, HID_QUIRK_MULTI_INPUT }, | 54 | { USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS, HID_QUIRK_MULTI_INPUT }, |
@@ -79,16 +81,15 @@ static const struct hid_blacklist { | |||
79 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT }, | 81 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT }, |
80 | { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT }, | 82 | { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT }, |
81 | { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH, HID_QUIRK_MULTI_INPUT }, | 83 | { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH, HID_QUIRK_MULTI_INPUT }, |
82 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | ||
83 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | 84 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, |
84 | 85 | ||
85 | { USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | ||
86 | { USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | 86 | { USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, |
87 | 87 | ||
88 | { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE }, | 88 | { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE }, |
89 | 89 | ||
90 | { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH, HID_QUIRK_MULTI_INPUT }, | 90 | { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH, HID_QUIRK_MULTI_INPUT }, |
91 | { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS, HID_QUIRK_MULTI_INPUT }, | 91 | { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS, HID_QUIRK_MULTI_INPUT }, |
92 | { USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD, HID_QUIRK_NO_INIT_REPORTS }, | ||
92 | { 0, 0 } | 93 | { 0, 0 } |
93 | }; | 94 | }; |
94 | 95 | ||
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 7c1188b53c3e..4ef02b269a71 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c | |||
@@ -641,6 +641,8 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
641 | struct usb_device *dev = hid_to_usb_dev(hid); | 641 | struct usb_device *dev = hid_to_usb_dev(hid); |
642 | struct usbhid_device *usbhid = hid->driver_data; | 642 | struct usbhid_device *usbhid = hid->driver_data; |
643 | 643 | ||
644 | memset(&dinfo, 0, sizeof(dinfo)); | ||
645 | |||
644 | dinfo.bustype = BUS_USB; | 646 | dinfo.bustype = BUS_USB; |
645 | dinfo.busnum = dev->bus->busnum; | 647 | dinfo.busnum = dev->bus->busnum; |
646 | dinfo.devnum = dev->devnum; | 648 | dinfo.devnum = dev->devnum; |