diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/hid/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/hid/hid-core.c | 1 | ||||
| -rw-r--r-- | drivers/hid/hid-holtek-mouse.c | 4 | ||||
| -rw-r--r-- | drivers/hid/hid-ids.h | 1 | ||||
| -rw-r--r-- | drivers/hid/hid-roccat-kone.c | 2 | ||||
| -rw-r--r-- | drivers/hid/hid-roccat-koneplus.c | 4 | ||||
| -rw-r--r-- | drivers/hid/hid-roccat-kovaplus.c | 4 | ||||
| -rw-r--r-- | drivers/hid/hid-roccat-pyra.c | 4 | ||||
| -rw-r--r-- | drivers/hid/hid-wiimote-modules.c | 40 | ||||
| -rw-r--r-- | drivers/hid/hid-wiimote.h | 4 | ||||
| -rw-r--r-- | drivers/hid/hidraw.c | 21 | ||||
| -rw-r--r-- | drivers/hid/uhid.c | 3 |
12 files changed, 62 insertions, 27 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 71b70e3a7a71..c91d547191dd 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
| @@ -241,6 +241,7 @@ config HID_HOLTEK | |||
| 241 | - Sharkoon Drakonia / Perixx MX-2000 gaming mice | 241 | - Sharkoon Drakonia / Perixx MX-2000 gaming mice |
| 242 | - Tracer Sniper TRM-503 / NOVA Gaming Slider X200 / | 242 | - Tracer Sniper TRM-503 / NOVA Gaming Slider X200 / |
| 243 | Zalman ZM-GM1 | 243 | Zalman ZM-GM1 |
| 244 | - SHARKOON DarkGlider Gaming mouse | ||
| 244 | 245 | ||
| 245 | config HOLTEK_FF | 246 | config HOLTEK_FF |
| 246 | bool "Holtek On Line Grip force feedback support" | 247 | bool "Holtek On Line Grip force feedback support" |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index b8470b1a10fe..5a8c01112a23 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -1715,6 +1715,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1715 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) }, | 1715 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) }, |
| 1716 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) }, | 1716 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) }, |
| 1717 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) }, | 1717 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) }, |
| 1718 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) }, | ||
| 1718 | { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) }, | 1719 | { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) }, |
| 1719 | { HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) }, | 1720 | { HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) }, |
| 1720 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) }, | 1721 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) }, |
diff --git a/drivers/hid/hid-holtek-mouse.c b/drivers/hid/hid-holtek-mouse.c index 7e6db3cf46f9..e696566cde46 100644 --- a/drivers/hid/hid-holtek-mouse.c +++ b/drivers/hid/hid-holtek-mouse.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | * - USB ID 04d9:a067, sold as Sharkoon Drakonia and Perixx MX-2000 | 27 | * - USB ID 04d9:a067, sold as Sharkoon Drakonia and Perixx MX-2000 |
| 28 | * - USB ID 04d9:a04a, sold as Tracer Sniper TRM-503, NOVA Gaming Slider X200 | 28 | * - USB ID 04d9:a04a, sold as Tracer Sniper TRM-503, NOVA Gaming Slider X200 |
| 29 | * and Zalman ZM-GM1 | 29 | * and Zalman ZM-GM1 |
| 30 | * - USB ID 04d9:a081, sold as SHARKOON DarkGlider Gaming mouse | ||
| 30 | */ | 31 | */ |
| 31 | 32 | ||
| 32 | static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 33 | static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| @@ -46,6 +47,7 @@ static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
| 46 | } | 47 | } |
| 47 | break; | 48 | break; |
| 48 | case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A: | 49 | case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A: |
| 50 | case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081: | ||
| 49 | if (*rsize >= 113 && rdesc[106] == 0xff && rdesc[107] == 0x7f | 51 | if (*rsize >= 113 && rdesc[106] == 0xff && rdesc[107] == 0x7f |
| 50 | && rdesc[111] == 0xff && rdesc[112] == 0x7f) { | 52 | && rdesc[111] == 0xff && rdesc[112] == 0x7f) { |
| 51 | hid_info(hdev, "Fixing up report descriptor\n"); | 53 | hid_info(hdev, "Fixing up report descriptor\n"); |
| @@ -63,6 +65,8 @@ static const struct hid_device_id holtek_mouse_devices[] = { | |||
| 63 | USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) }, | 65 | USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) }, |
| 64 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, | 66 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, |
| 65 | USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) }, | 67 | USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) }, |
| 68 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, | ||
| 69 | USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) }, | ||
| 66 | { } | 70 | { } |
| 67 | }; | 71 | }; |
| 68 | MODULE_DEVICE_TABLE(hid, holtek_mouse_devices); | 72 | MODULE_DEVICE_TABLE(hid, holtek_mouse_devices); |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index e60e8d530697..9cbc7ab07dfa 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
| @@ -450,6 +450,7 @@ | |||
| 450 | #define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD 0xa055 | 450 | #define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD 0xa055 |
| 451 | #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067 0xa067 | 451 | #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067 0xa067 |
| 452 | #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A 0xa04a | 452 | #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A 0xa04a |
| 453 | #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081 0xa081 | ||
| 453 | 454 | ||
| 454 | #define USB_VENDOR_ID_IMATION 0x0718 | 455 | #define USB_VENDOR_ID_IMATION 0x0718 |
| 455 | #define USB_DEVICE_ID_DISC_STAKKA 0xd000 | 456 | #define USB_DEVICE_ID_DISC_STAKKA 0xd000 |
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index 602c188e9d86..6101816a7ddd 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c | |||
| @@ -382,7 +382,7 @@ static ssize_t kone_sysfs_write_profilex(struct file *fp, | |||
| 382 | } | 382 | } |
| 383 | #define PROFILE_ATTR(number) \ | 383 | #define PROFILE_ATTR(number) \ |
| 384 | static struct bin_attribute bin_attr_profile##number = { \ | 384 | static struct bin_attribute bin_attr_profile##number = { \ |
| 385 | .attr = { .name = "profile##number", .mode = 0660 }, \ | 385 | .attr = { .name = "profile" #number, .mode = 0660 }, \ |
| 386 | .size = sizeof(struct kone_profile), \ | 386 | .size = sizeof(struct kone_profile), \ |
| 387 | .read = kone_sysfs_read_profilex, \ | 387 | .read = kone_sysfs_read_profilex, \ |
| 388 | .write = kone_sysfs_write_profilex, \ | 388 | .write = kone_sysfs_write_profilex, \ |
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c index 5ddf605b6b89..5e99fcdc71b9 100644 --- a/drivers/hid/hid-roccat-koneplus.c +++ b/drivers/hid/hid-roccat-koneplus.c | |||
| @@ -229,13 +229,13 @@ static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp, | |||
| 229 | 229 | ||
| 230 | #define PROFILE_ATTR(number) \ | 230 | #define PROFILE_ATTR(number) \ |
| 231 | static struct bin_attribute bin_attr_profile##number##_settings = { \ | 231 | static struct bin_attribute bin_attr_profile##number##_settings = { \ |
| 232 | .attr = { .name = "profile##number##_settings", .mode = 0440 }, \ | 232 | .attr = { .name = "profile" #number "_settings", .mode = 0440 }, \ |
| 233 | .size = KONEPLUS_SIZE_PROFILE_SETTINGS, \ | 233 | .size = KONEPLUS_SIZE_PROFILE_SETTINGS, \ |
| 234 | .read = koneplus_sysfs_read_profilex_settings, \ | 234 | .read = koneplus_sysfs_read_profilex_settings, \ |
| 235 | .private = &profile_numbers[number-1], \ | 235 | .private = &profile_numbers[number-1], \ |
| 236 | }; \ | 236 | }; \ |
| 237 | static struct bin_attribute bin_attr_profile##number##_buttons = { \ | 237 | static struct bin_attribute bin_attr_profile##number##_buttons = { \ |
| 238 | .attr = { .name = "profile##number##_buttons", .mode = 0440 }, \ | 238 | .attr = { .name = "profile" #number "_buttons", .mode = 0440 }, \ |
| 239 | .size = KONEPLUS_SIZE_PROFILE_BUTTONS, \ | 239 | .size = KONEPLUS_SIZE_PROFILE_BUTTONS, \ |
| 240 | .read = koneplus_sysfs_read_profilex_buttons, \ | 240 | .read = koneplus_sysfs_read_profilex_buttons, \ |
| 241 | .private = &profile_numbers[number-1], \ | 241 | .private = &profile_numbers[number-1], \ |
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c index 515bc03136c0..0c8e1ef0b67d 100644 --- a/drivers/hid/hid-roccat-kovaplus.c +++ b/drivers/hid/hid-roccat-kovaplus.c | |||
| @@ -257,13 +257,13 @@ static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp, | |||
| 257 | 257 | ||
| 258 | #define PROFILE_ATTR(number) \ | 258 | #define PROFILE_ATTR(number) \ |
| 259 | static struct bin_attribute bin_attr_profile##number##_settings = { \ | 259 | static struct bin_attribute bin_attr_profile##number##_settings = { \ |
| 260 | .attr = { .name = "profile##number##_settings", .mode = 0440 }, \ | 260 | .attr = { .name = "profile" #number "_settings", .mode = 0440 }, \ |
| 261 | .size = KOVAPLUS_SIZE_PROFILE_SETTINGS, \ | 261 | .size = KOVAPLUS_SIZE_PROFILE_SETTINGS, \ |
| 262 | .read = kovaplus_sysfs_read_profilex_settings, \ | 262 | .read = kovaplus_sysfs_read_profilex_settings, \ |
| 263 | .private = &profile_numbers[number-1], \ | 263 | .private = &profile_numbers[number-1], \ |
| 264 | }; \ | 264 | }; \ |
| 265 | static struct bin_attribute bin_attr_profile##number##_buttons = { \ | 265 | static struct bin_attribute bin_attr_profile##number##_buttons = { \ |
| 266 | .attr = { .name = "profile##number##_buttons", .mode = 0440 }, \ | 266 | .attr = { .name = "profile" #number "_buttons", .mode = 0440 }, \ |
| 267 | .size = KOVAPLUS_SIZE_PROFILE_BUTTONS, \ | 267 | .size = KOVAPLUS_SIZE_PROFILE_BUTTONS, \ |
| 268 | .read = kovaplus_sysfs_read_profilex_buttons, \ | 268 | .read = kovaplus_sysfs_read_profilex_buttons, \ |
| 269 | .private = &profile_numbers[number-1], \ | 269 | .private = &profile_numbers[number-1], \ |
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c index 5a6dbbeee790..1a07e07d99a0 100644 --- a/drivers/hid/hid-roccat-pyra.c +++ b/drivers/hid/hid-roccat-pyra.c | |||
| @@ -225,13 +225,13 @@ static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp, | |||
| 225 | 225 | ||
| 226 | #define PROFILE_ATTR(number) \ | 226 | #define PROFILE_ATTR(number) \ |
| 227 | static struct bin_attribute bin_attr_profile##number##_settings = { \ | 227 | static struct bin_attribute bin_attr_profile##number##_settings = { \ |
| 228 | .attr = { .name = "profile##number##_settings", .mode = 0440 }, \ | 228 | .attr = { .name = "profile" #number "_settings", .mode = 0440 }, \ |
| 229 | .size = PYRA_SIZE_PROFILE_SETTINGS, \ | 229 | .size = PYRA_SIZE_PROFILE_SETTINGS, \ |
| 230 | .read = pyra_sysfs_read_profilex_settings, \ | 230 | .read = pyra_sysfs_read_profilex_settings, \ |
| 231 | .private = &profile_numbers[number-1], \ | 231 | .private = &profile_numbers[number-1], \ |
| 232 | }; \ | 232 | }; \ |
| 233 | static struct bin_attribute bin_attr_profile##number##_buttons = { \ | 233 | static struct bin_attribute bin_attr_profile##number##_buttons = { \ |
| 234 | .attr = { .name = "profile##number##_buttons", .mode = 0440 }, \ | 234 | .attr = { .name = "profile" #number "_buttons", .mode = 0440 }, \ |
| 235 | .size = PYRA_SIZE_PROFILE_BUTTONS, \ | 235 | .size = PYRA_SIZE_PROFILE_BUTTONS, \ |
| 236 | .read = pyra_sysfs_read_profilex_buttons, \ | 236 | .read = pyra_sysfs_read_profilex_buttons, \ |
| 237 | .private = &profile_numbers[number-1], \ | 237 | .private = &profile_numbers[number-1], \ |
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c index 2e7d644dba18..71adf9e60b13 100644 --- a/drivers/hid/hid-wiimote-modules.c +++ b/drivers/hid/hid-wiimote-modules.c | |||
| @@ -119,12 +119,22 @@ static const struct wiimod_ops wiimod_keys = { | |||
| 119 | * the rumble motor, this flag shouldn't be set. | 119 | * the rumble motor, this flag shouldn't be set. |
| 120 | */ | 120 | */ |
| 121 | 121 | ||
| 122 | /* used by wiimod_rumble and wiipro_rumble */ | ||
| 123 | static void wiimod_rumble_worker(struct work_struct *work) | ||
| 124 | { | ||
| 125 | struct wiimote_data *wdata = container_of(work, struct wiimote_data, | ||
| 126 | rumble_worker); | ||
| 127 | |||
| 128 | spin_lock_irq(&wdata->state.lock); | ||
| 129 | wiiproto_req_rumble(wdata, wdata->state.cache_rumble); | ||
| 130 | spin_unlock_irq(&wdata->state.lock); | ||
| 131 | } | ||
| 132 | |||
| 122 | static int wiimod_rumble_play(struct input_dev *dev, void *data, | 133 | static int wiimod_rumble_play(struct input_dev *dev, void *data, |
| 123 | struct ff_effect *eff) | 134 | struct ff_effect *eff) |
| 124 | { | 135 | { |
| 125 | struct wiimote_data *wdata = input_get_drvdata(dev); | 136 | struct wiimote_data *wdata = input_get_drvdata(dev); |
| 126 | __u8 value; | 137 | __u8 value; |
| 127 | unsigned long flags; | ||
| 128 | 138 | ||
| 129 | /* | 139 | /* |
| 130 | * The wiimote supports only a single rumble motor so if any magnitude | 140 | * The wiimote supports only a single rumble motor so if any magnitude |
| @@ -137,9 +147,10 @@ static int wiimod_rumble_play(struct input_dev *dev, void *data, | |||
| 137 | else | 147 | else |
| 138 | value = 0; | 148 | value = 0; |
| 139 | 149 | ||
| 140 | spin_lock_irqsave(&wdata->state.lock, flags); | 150 | /* Locking state.lock here might deadlock with input_event() calls. |
| 141 | wiiproto_req_rumble(wdata, value); | 151 | * schedule_work acts as barrier. Merging multiple changes is fine. */ |
| 142 | spin_unlock_irqrestore(&wdata->state.lock, flags); | 152 | wdata->state.cache_rumble = value; |
| 153 | schedule_work(&wdata->rumble_worker); | ||
| 143 | 154 | ||
| 144 | return 0; | 155 | return 0; |
| 145 | } | 156 | } |
| @@ -147,6 +158,8 @@ static int wiimod_rumble_play(struct input_dev *dev, void *data, | |||
| 147 | static int wiimod_rumble_probe(const struct wiimod_ops *ops, | 158 | static int wiimod_rumble_probe(const struct wiimod_ops *ops, |
| 148 | struct wiimote_data *wdata) | 159 | struct wiimote_data *wdata) |
| 149 | { | 160 | { |
| 161 | INIT_WORK(&wdata->rumble_worker, wiimod_rumble_worker); | ||
| 162 | |||
| 150 | set_bit(FF_RUMBLE, wdata->input->ffbit); | 163 | set_bit(FF_RUMBLE, wdata->input->ffbit); |
| 151 | if (input_ff_create_memless(wdata->input, NULL, wiimod_rumble_play)) | 164 | if (input_ff_create_memless(wdata->input, NULL, wiimod_rumble_play)) |
| 152 | return -ENOMEM; | 165 | return -ENOMEM; |
| @@ -159,6 +172,8 @@ static void wiimod_rumble_remove(const struct wiimod_ops *ops, | |||
| 159 | { | 172 | { |
| 160 | unsigned long flags; | 173 | unsigned long flags; |
| 161 | 174 | ||
| 175 | cancel_work_sync(&wdata->rumble_worker); | ||
| 176 | |||
| 162 | spin_lock_irqsave(&wdata->state.lock, flags); | 177 | spin_lock_irqsave(&wdata->state.lock, flags); |
| 163 | wiiproto_req_rumble(wdata, 0); | 178 | wiiproto_req_rumble(wdata, 0); |
| 164 | spin_unlock_irqrestore(&wdata->state.lock, flags); | 179 | spin_unlock_irqrestore(&wdata->state.lock, flags); |
| @@ -1731,7 +1746,6 @@ static int wiimod_pro_play(struct input_dev *dev, void *data, | |||
| 1731 | { | 1746 | { |
| 1732 | struct wiimote_data *wdata = input_get_drvdata(dev); | 1747 | struct wiimote_data *wdata = input_get_drvdata(dev); |
| 1733 | __u8 value; | 1748 | __u8 value; |
| 1734 | unsigned long flags; | ||
| 1735 | 1749 | ||
| 1736 | /* | 1750 | /* |
| 1737 | * The wiimote supports only a single rumble motor so if any magnitude | 1751 | * The wiimote supports only a single rumble motor so if any magnitude |
| @@ -1744,9 +1758,10 @@ static int wiimod_pro_play(struct input_dev *dev, void *data, | |||
| 1744 | else | 1758 | else |
| 1745 | value = 0; | 1759 | value = 0; |
| 1746 | 1760 | ||
| 1747 | spin_lock_irqsave(&wdata->state.lock, flags); | 1761 | /* Locking state.lock here might deadlock with input_event() calls. |
| 1748 | wiiproto_req_rumble(wdata, value); | 1762 | * schedule_work acts as barrier. Merging multiple changes is fine. */ |
| 1749 | spin_unlock_irqrestore(&wdata->state.lock, flags); | 1763 | wdata->state.cache_rumble = value; |
| 1764 | schedule_work(&wdata->rumble_worker); | ||
| 1750 | 1765 | ||
| 1751 | return 0; | 1766 | return 0; |
| 1752 | } | 1767 | } |
| @@ -1756,6 +1771,8 @@ static int wiimod_pro_probe(const struct wiimod_ops *ops, | |||
| 1756 | { | 1771 | { |
| 1757 | int ret, i; | 1772 | int ret, i; |
| 1758 | 1773 | ||
| 1774 | INIT_WORK(&wdata->rumble_worker, wiimod_rumble_worker); | ||
| 1775 | |||
| 1759 | wdata->extension.input = input_allocate_device(); | 1776 | wdata->extension.input = input_allocate_device(); |
| 1760 | if (!wdata->extension.input) | 1777 | if (!wdata->extension.input) |
| 1761 | return -ENOMEM; | 1778 | return -ENOMEM; |
| @@ -1817,12 +1834,13 @@ static void wiimod_pro_remove(const struct wiimod_ops *ops, | |||
| 1817 | if (!wdata->extension.input) | 1834 | if (!wdata->extension.input) |
| 1818 | return; | 1835 | return; |
| 1819 | 1836 | ||
| 1837 | input_unregister_device(wdata->extension.input); | ||
| 1838 | wdata->extension.input = NULL; | ||
| 1839 | cancel_work_sync(&wdata->rumble_worker); | ||
| 1840 | |||
| 1820 | spin_lock_irqsave(&wdata->state.lock, flags); | 1841 | spin_lock_irqsave(&wdata->state.lock, flags); |
| 1821 | wiiproto_req_rumble(wdata, 0); | 1842 | wiiproto_req_rumble(wdata, 0); |
| 1822 | spin_unlock_irqrestore(&wdata->state.lock, flags); | 1843 | spin_unlock_irqrestore(&wdata->state.lock, flags); |
| 1823 | |||
| 1824 | input_unregister_device(wdata->extension.input); | ||
| 1825 | wdata->extension.input = NULL; | ||
| 1826 | } | 1844 | } |
| 1827 | 1845 | ||
| 1828 | static const struct wiimod_ops wiimod_pro = { | 1846 | static const struct wiimod_ops wiimod_pro = { |
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h index f1474f372c0b..75db0c400037 100644 --- a/drivers/hid/hid-wiimote.h +++ b/drivers/hid/hid-wiimote.h | |||
| @@ -133,13 +133,15 @@ struct wiimote_state { | |||
| 133 | __u8 *cmd_read_buf; | 133 | __u8 *cmd_read_buf; |
| 134 | __u8 cmd_read_size; | 134 | __u8 cmd_read_size; |
| 135 | 135 | ||
| 136 | /* calibration data */ | 136 | /* calibration/cache data */ |
| 137 | __u16 calib_bboard[4][3]; | 137 | __u16 calib_bboard[4][3]; |
| 138 | __u8 cache_rumble; | ||
| 138 | }; | 139 | }; |
| 139 | 140 | ||
| 140 | struct wiimote_data { | 141 | struct wiimote_data { |
| 141 | struct hid_device *hdev; | 142 | struct hid_device *hdev; |
| 142 | struct input_dev *input; | 143 | struct input_dev *input; |
| 144 | struct work_struct rumble_worker; | ||
| 143 | struct led_classdev *leds[4]; | 145 | struct led_classdev *leds[4]; |
| 144 | struct input_dev *accel; | 146 | struct input_dev *accel; |
| 145 | struct input_dev *ir; | 147 | struct input_dev *ir; |
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 8918dd12bb69..6a6dd5cd7833 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
| @@ -308,18 +308,25 @@ static int hidraw_fasync(int fd, struct file *file, int on) | |||
| 308 | static void drop_ref(struct hidraw *hidraw, int exists_bit) | 308 | static void drop_ref(struct hidraw *hidraw, int exists_bit) |
| 309 | { | 309 | { |
| 310 | if (exists_bit) { | 310 | if (exists_bit) { |
| 311 | hid_hw_close(hidraw->hid); | ||
| 312 | hidraw->exist = 0; | 311 | hidraw->exist = 0; |
| 313 | if (hidraw->open) | 312 | if (hidraw->open) { |
| 313 | hid_hw_close(hidraw->hid); | ||
| 314 | wake_up_interruptible(&hidraw->wait); | 314 | wake_up_interruptible(&hidraw->wait); |
| 315 | } | ||
| 315 | } else { | 316 | } else { |
| 316 | --hidraw->open; | 317 | --hidraw->open; |
| 317 | } | 318 | } |
| 318 | 319 | if (!hidraw->open) { | |
| 319 | if (!hidraw->open && !hidraw->exist) { | 320 | if (!hidraw->exist) { |
| 320 | device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); | 321 | device_destroy(hidraw_class, |
| 321 | hidraw_table[hidraw->minor] = NULL; | 322 | MKDEV(hidraw_major, hidraw->minor)); |
| 322 | kfree(hidraw); | 323 | hidraw_table[hidraw->minor] = NULL; |
| 324 | kfree(hidraw); | ||
| 325 | } else { | ||
| 326 | /* close device for last reader */ | ||
| 327 | hid_hw_power(hidraw->hid, PM_HINT_NORMAL); | ||
| 328 | hid_hw_close(hidraw->hid); | ||
| 329 | } | ||
| 323 | } | 330 | } |
| 324 | } | 331 | } |
| 325 | 332 | ||
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c index 5bf2fb785844..93b00d76374c 100644 --- a/drivers/hid/uhid.c +++ b/drivers/hid/uhid.c | |||
| @@ -615,7 +615,7 @@ static const struct file_operations uhid_fops = { | |||
| 615 | 615 | ||
| 616 | static struct miscdevice uhid_misc = { | 616 | static struct miscdevice uhid_misc = { |
| 617 | .fops = &uhid_fops, | 617 | .fops = &uhid_fops, |
| 618 | .minor = MISC_DYNAMIC_MINOR, | 618 | .minor = UHID_MINOR, |
| 619 | .name = UHID_NAME, | 619 | .name = UHID_NAME, |
| 620 | }; | 620 | }; |
| 621 | 621 | ||
| @@ -634,4 +634,5 @@ module_exit(uhid_exit); | |||
| 634 | MODULE_LICENSE("GPL"); | 634 | MODULE_LICENSE("GPL"); |
| 635 | MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>"); | 635 | MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>"); |
| 636 | MODULE_DESCRIPTION("User-space I/O driver support for HID subsystem"); | 636 | MODULE_DESCRIPTION("User-space I/O driver support for HID subsystem"); |
| 637 | MODULE_ALIAS_MISCDEV(UHID_MINOR); | ||
| 637 | MODULE_ALIAS("devname:" UHID_NAME); | 638 | MODULE_ALIAS("devname:" UHID_NAME); |
