Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid

Pull HID fixes from Jiri Kosina:
- fix for hidraw reference counting regression, by Manoj Chourasia
- fix for minor number allocation for uhid, by David Herrmann
- other small unsorted fixes / device ID additions

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid:
HID: wiimote: fix FF deadlock
HID: add Holtek USB ID 04d9:a081 SHARKOON DarkGlider
HID: hidraw: close underlying device at removal of last reader
HID: roccat: Fix "cannot create duplicate filename" problems
HID: uhid: allocate static minor

+63 -27
+1
drivers/hid/Kconfig
··· 241 241 - Sharkoon Drakonia / Perixx MX-2000 gaming mice 242 242 - Tracer Sniper TRM-503 / NOVA Gaming Slider X200 / 243 243 Zalman ZM-GM1 244 + - SHARKOON DarkGlider Gaming mouse 244 245 245 246 config HOLTEK_FF 246 247 bool "Holtek On Line Grip force feedback support"
+1
drivers/hid/hid-core.c
··· 1715 1715 { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) }, 1716 1716 { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) }, 1717 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 1719 { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) }, 1719 1720 { HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) }, 1720 1721 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
+4
drivers/hid/hid-holtek-mouse.c
··· 27 27 * - USB ID 04d9:a067, sold as Sharkoon Drakonia and Perixx MX-2000 28 28 * - USB ID 04d9:a04a, sold as Tracer Sniper TRM-503, NOVA Gaming Slider X200 29 29 * and Zalman ZM-GM1 30 + * - USB ID 04d9:a081, sold as SHARKOON DarkGlider Gaming mouse 30 31 */ 31 32 32 33 static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, ··· 47 46 } 48 47 break; 49 48 case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A: 49 + case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081: 50 50 if (*rsize >= 113 && rdesc[106] == 0xff && rdesc[107] == 0x7f 51 51 && rdesc[111] == 0xff && rdesc[112] == 0x7f) { 52 52 hid_info(hdev, "Fixing up report descriptor\n"); ··· 65 63 USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) }, 66 64 { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, 67 65 USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) }, 66 + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, 67 + USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) }, 68 68 { } 69 69 }; 70 70 MODULE_DEVICE_TABLE(hid, holtek_mouse_devices);
+1
drivers/hid/hid-ids.h
··· 450 450 #define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD 0xa055 451 451 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067 0xa067 452 452 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A 0xa04a 453 + #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081 0xa081 453 454 454 455 #define USB_VENDOR_ID_IMATION 0x0718 455 456 #define USB_DEVICE_ID_DISC_STAKKA 0xd000
+1 -1
drivers/hid/hid-roccat-kone.c
··· 382 382 } 383 383 #define PROFILE_ATTR(number) \ 384 384 static struct bin_attribute bin_attr_profile##number = { \ 385 - .attr = { .name = "profile##number", .mode = 0660 }, \ 385 + .attr = { .name = "profile" #number, .mode = 0660 }, \ 386 386 .size = sizeof(struct kone_profile), \ 387 387 .read = kone_sysfs_read_profilex, \ 388 388 .write = kone_sysfs_write_profilex, \
+2 -2
drivers/hid/hid-roccat-koneplus.c
··· 229 229 230 230 #define PROFILE_ATTR(number) \ 231 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 233 .size = KONEPLUS_SIZE_PROFILE_SETTINGS, \ 234 234 .read = koneplus_sysfs_read_profilex_settings, \ 235 235 .private = &profile_numbers[number-1], \ 236 236 }; \ 237 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 239 .size = KONEPLUS_SIZE_PROFILE_BUTTONS, \ 240 240 .read = koneplus_sysfs_read_profilex_buttons, \ 241 241 .private = &profile_numbers[number-1], \
+2 -2
drivers/hid/hid-roccat-kovaplus.c
··· 257 257 258 258 #define PROFILE_ATTR(number) \ 259 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 261 .size = KOVAPLUS_SIZE_PROFILE_SETTINGS, \ 262 262 .read = kovaplus_sysfs_read_profilex_settings, \ 263 263 .private = &profile_numbers[number-1], \ 264 264 }; \ 265 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 267 .size = KOVAPLUS_SIZE_PROFILE_BUTTONS, \ 268 268 .read = kovaplus_sysfs_read_profilex_buttons, \ 269 269 .private = &profile_numbers[number-1], \
+2 -2
drivers/hid/hid-roccat-pyra.c
··· 225 225 226 226 #define PROFILE_ATTR(number) \ 227 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 229 .size = PYRA_SIZE_PROFILE_SETTINGS, \ 230 230 .read = pyra_sysfs_read_profilex_settings, \ 231 231 .private = &profile_numbers[number-1], \ 232 232 }; \ 233 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 235 .size = PYRA_SIZE_PROFILE_BUTTONS, \ 236 236 .read = pyra_sysfs_read_profilex_buttons, \ 237 237 .private = &profile_numbers[number-1], \
+29 -11
drivers/hid/hid-wiimote-modules.c
··· 119 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 133 static int wiimod_rumble_play(struct input_dev *dev, void *data, 123 134 struct ff_effect *eff) 124 135 { 125 136 struct wiimote_data *wdata = input_get_drvdata(dev); 126 137 __u8 value; 127 - unsigned long flags; 128 138 129 139 /* 130 140 * The wiimote supports only a single rumble motor so if any magnitude ··· 147 137 else 148 138 value = 0; 149 139 150 - spin_lock_irqsave(&wdata->state.lock, flags); 151 - wiiproto_req_rumble(wdata, value); 152 - spin_unlock_irqrestore(&wdata->state.lock, flags); 140 + /* Locking state.lock here might deadlock with input_event() calls. 141 + * schedule_work acts as barrier. Merging multiple changes is fine. */ 142 + wdata->state.cache_rumble = value; 143 + schedule_work(&wdata->rumble_worker); 153 144 154 145 return 0; 155 146 } ··· 158 147 static int wiimod_rumble_probe(const struct wiimod_ops *ops, 159 148 struct wiimote_data *wdata) 160 149 { 150 + INIT_WORK(&wdata->rumble_worker, wiimod_rumble_worker); 151 + 161 152 set_bit(FF_RUMBLE, wdata->input->ffbit); 162 153 if (input_ff_create_memless(wdata->input, NULL, wiimod_rumble_play)) 163 154 return -ENOMEM; ··· 171 158 struct wiimote_data *wdata) 172 159 { 173 160 unsigned long flags; 161 + 162 + cancel_work_sync(&wdata->rumble_worker); 174 163 175 164 spin_lock_irqsave(&wdata->state.lock, flags); 176 165 wiiproto_req_rumble(wdata, 0); ··· 1746 1731 { 1747 1732 struct wiimote_data *wdata = input_get_drvdata(dev); 1748 1733 __u8 value; 1749 - unsigned long flags; 1750 1734 1751 1735 /* 1752 1736 * The wiimote supports only a single rumble motor so if any magnitude ··· 1758 1744 else 1759 1745 value = 0; 1760 1746 1761 - spin_lock_irqsave(&wdata->state.lock, flags); 1762 - wiiproto_req_rumble(wdata, value); 1763 - spin_unlock_irqrestore(&wdata->state.lock, flags); 1747 + /* Locking state.lock here might deadlock with input_event() calls. 1748 + * schedule_work acts as barrier. Merging multiple changes is fine. */ 1749 + wdata->state.cache_rumble = value; 1750 + schedule_work(&wdata->rumble_worker); 1764 1751 1765 1752 return 0; 1766 1753 } ··· 1770 1755 struct wiimote_data *wdata) 1771 1756 { 1772 1757 int ret, i; 1758 + 1759 + INIT_WORK(&wdata->rumble_worker, wiimod_rumble_worker); 1773 1760 1774 1761 wdata->extension.input = input_allocate_device(); 1775 1762 if (!wdata->extension.input) ··· 1834 1817 if (!wdata->extension.input) 1835 1818 return; 1836 1819 1820 + input_unregister_device(wdata->extension.input); 1821 + wdata->extension.input = NULL; 1822 + cancel_work_sync(&wdata->rumble_worker); 1823 + 1837 1824 spin_lock_irqsave(&wdata->state.lock, flags); 1838 1825 wiiproto_req_rumble(wdata, 0); 1839 1826 spin_unlock_irqrestore(&wdata->state.lock, flags); 1840 - 1841 - input_unregister_device(wdata->extension.input); 1842 - wdata->extension.input = NULL; 1843 1827 } 1844 1828 1845 1829 static const struct wiimod_ops wiimod_pro = {
+3 -1
drivers/hid/hid-wiimote.h
··· 133 133 __u8 *cmd_read_buf; 134 134 __u8 cmd_read_size; 135 135 136 - /* calibration data */ 136 + /* calibration/cache data */ 137 137 __u16 calib_bboard[4][3]; 138 + __u8 cache_rumble; 138 139 }; 139 140 140 141 struct wiimote_data { 141 142 struct hid_device *hdev; 142 143 struct input_dev *input; 144 + struct work_struct rumble_worker; 143 145 struct led_classdev *leds[4]; 144 146 struct input_dev *accel; 145 147 struct input_dev *ir;
+14 -7
drivers/hid/hidraw.c
··· 308 308 static void drop_ref(struct hidraw *hidraw, int exists_bit) 309 309 { 310 310 if (exists_bit) { 311 - hid_hw_close(hidraw->hid); 312 311 hidraw->exist = 0; 313 - if (hidraw->open) 312 + if (hidraw->open) { 313 + hid_hw_close(hidraw->hid); 314 314 wake_up_interruptible(&hidraw->wait); 315 + } 315 316 } else { 316 317 --hidraw->open; 317 318 } 318 - 319 - if (!hidraw->open && !hidraw->exist) { 320 - device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); 321 - hidraw_table[hidraw->minor] = NULL; 322 - kfree(hidraw); 319 + if (!hidraw->open) { 320 + if (!hidraw->exist) { 321 + device_destroy(hidraw_class, 322 + MKDEV(hidraw_major, hidraw->minor)); 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
+2 -1
drivers/hid/uhid.c
··· 615 615 616 616 static struct miscdevice uhid_misc = { 617 617 .fops = &uhid_fops, 618 - .minor = MISC_DYNAMIC_MINOR, 618 + .minor = UHID_MINOR, 619 619 .name = UHID_NAME, 620 620 }; 621 621 ··· 634 634 MODULE_LICENSE("GPL"); 635 635 MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>"); 636 636 MODULE_DESCRIPTION("User-space I/O driver support for HID subsystem"); 637 + MODULE_ALIAS_MISCDEV(UHID_MINOR); 637 638 MODULE_ALIAS("devname:" UHID_NAME);
+1
include/linux/miscdevice.h
··· 45 45 #define MAPPER_CTRL_MINOR 236 46 46 #define LOOP_CTRL_MINOR 237 47 47 #define VHOST_NET_MINOR 238 48 + #define UHID_MINOR 239 48 49 #define MISC_DYNAMIC_MINOR 255 49 50 50 51 struct device;