Skip to content

Commit fd84831

Browse files
committed
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
2 parents 4f97c9b + f50f9aa commit fd84831

13 files changed

+63
-27
lines changed

drivers/hid/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ config HID_HOLTEK
241241
- Sharkoon Drakonia / Perixx MX-2000 gaming mice
242242
- Tracer Sniper TRM-503 / NOVA Gaming Slider X200 /
243243
Zalman ZM-GM1
244+
- SHARKOON DarkGlider Gaming mouse
244245

245246
config HOLTEK_FF
246247
bool "Holtek On Line Grip force feedback support"

drivers/hid/hid-core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1715,6 +1715,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
17151715
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) },
17161716
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) },
17171717
{ 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) },
17181719
{ HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) },
17191720
{ HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) },
17201721
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },

drivers/hid/hid-holtek-mouse.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
* - USB ID 04d9:a067, sold as Sharkoon Drakonia and Perixx MX-2000
2828
* - USB ID 04d9:a04a, sold as Tracer Sniper TRM-503, NOVA Gaming Slider X200
2929
* and Zalman ZM-GM1
30+
* - USB ID 04d9:a081, sold as SHARKOON DarkGlider Gaming mouse
3031
*/
3132

3233
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,
4647
}
4748
break;
4849
case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A:
50+
case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081:
4951
if (*rsize >= 113 && rdesc[106] == 0xff && rdesc[107] == 0x7f
5052
&& rdesc[111] == 0xff && rdesc[112] == 0x7f) {
5153
hid_info(hdev, "Fixing up report descriptor\n");
@@ -63,6 +65,8 @@ static const struct hid_device_id holtek_mouse_devices[] = {
6365
USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) },
6466
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
6567
USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) },
68+
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
69+
USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) },
6670
{ }
6771
};
6872
MODULE_DEVICE_TABLE(hid, holtek_mouse_devices);

drivers/hid/hid-ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@
450450
#define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD 0xa055
451451
#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067 0xa067
452452
#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A 0xa04a
453+
#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081 0xa081
453454

454455
#define USB_VENDOR_ID_IMATION 0x0718
455456
#define USB_DEVICE_ID_DISC_STAKKA 0xd000

drivers/hid/hid-roccat-kone.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ static ssize_t kone_sysfs_write_profilex(struct file *fp,
382382
}
383383
#define PROFILE_ATTR(number) \
384384
static struct bin_attribute bin_attr_profile##number = { \
385-
.attr = { .name = "profile##number", .mode = 0660 }, \
385+
.attr = { .name = "profile" #number, .mode = 0660 }, \
386386
.size = sizeof(struct kone_profile), \
387387
.read = kone_sysfs_read_profilex, \
388388
.write = kone_sysfs_write_profilex, \

drivers/hid/hid-roccat-koneplus.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,13 +229,13 @@ static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp,
229229

230230
#define PROFILE_ATTR(number) \
231231
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 }, \
233233
.size = KONEPLUS_SIZE_PROFILE_SETTINGS, \
234234
.read = koneplus_sysfs_read_profilex_settings, \
235235
.private = &profile_numbers[number-1], \
236236
}; \
237237
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 }, \
239239
.size = KONEPLUS_SIZE_PROFILE_BUTTONS, \
240240
.read = koneplus_sysfs_read_profilex_buttons, \
241241
.private = &profile_numbers[number-1], \

drivers/hid/hid-roccat-kovaplus.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,13 +257,13 @@ static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp,
257257

258258
#define PROFILE_ATTR(number) \
259259
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 }, \
261261
.size = KOVAPLUS_SIZE_PROFILE_SETTINGS, \
262262
.read = kovaplus_sysfs_read_profilex_settings, \
263263
.private = &profile_numbers[number-1], \
264264
}; \
265265
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 }, \
267267
.size = KOVAPLUS_SIZE_PROFILE_BUTTONS, \
268268
.read = kovaplus_sysfs_read_profilex_buttons, \
269269
.private = &profile_numbers[number-1], \

drivers/hid/hid-roccat-pyra.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,13 +225,13 @@ static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp,
225225

226226
#define PROFILE_ATTR(number) \
227227
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 }, \
229229
.size = PYRA_SIZE_PROFILE_SETTINGS, \
230230
.read = pyra_sysfs_read_profilex_settings, \
231231
.private = &profile_numbers[number-1], \
232232
}; \
233233
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 }, \
235235
.size = PYRA_SIZE_PROFILE_BUTTONS, \
236236
.read = pyra_sysfs_read_profilex_buttons, \
237237
.private = &profile_numbers[number-1], \

drivers/hid/hid-wiimote-modules.c

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,22 @@ static const struct wiimod_ops wiimod_keys = {
119119
* the rumble motor, this flag shouldn't be set.
120120
*/
121121

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+
122133
static int wiimod_rumble_play(struct input_dev *dev, void *data,
123134
struct ff_effect *eff)
124135
{
125136
struct wiimote_data *wdata = input_get_drvdata(dev);
126137
__u8 value;
127-
unsigned long flags;
128138

129139
/*
130140
* The wiimote supports only a single rumble motor so if any magnitude
@@ -137,16 +147,19 @@ static int wiimod_rumble_play(struct input_dev *dev, void *data,
137147
else
138148
value = 0;
139149

140-
spin_lock_irqsave(&wdata->state.lock, flags);
141-
wiiproto_req_rumble(wdata, value);
142-
spin_unlock_irqrestore(&wdata->state.lock, flags);
150+
/* Locking state.lock here might deadlock with input_event() calls.
151+
* schedule_work acts as barrier. Merging multiple changes is fine. */
152+
wdata->state.cache_rumble = value;
153+
schedule_work(&wdata->rumble_worker);
143154

144155
return 0;
145156
}
146157

147158
static int wiimod_rumble_probe(const struct wiimod_ops *ops,
148159
struct wiimote_data *wdata)
149160
{
161+
INIT_WORK(&wdata->rumble_worker, wiimod_rumble_worker);
162+
150163
set_bit(FF_RUMBLE, wdata->input->ffbit);
151164
if (input_ff_create_memless(wdata->input, NULL, wiimod_rumble_play))
152165
return -ENOMEM;
@@ -159,6 +172,8 @@ static void wiimod_rumble_remove(const struct wiimod_ops *ops,
159172
{
160173
unsigned long flags;
161174

175+
cancel_work_sync(&wdata->rumble_worker);
176+
162177
spin_lock_irqsave(&wdata->state.lock, flags);
163178
wiiproto_req_rumble(wdata, 0);
164179
spin_unlock_irqrestore(&wdata->state.lock, flags);
@@ -1731,7 +1746,6 @@ static int wiimod_pro_play(struct input_dev *dev, void *data,
17311746
{
17321747
struct wiimote_data *wdata = input_get_drvdata(dev);
17331748
__u8 value;
1734-
unsigned long flags;
17351749

17361750
/*
17371751
* 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,
17441758
else
17451759
value = 0;
17461760

1747-
spin_lock_irqsave(&wdata->state.lock, flags);
1748-
wiiproto_req_rumble(wdata, value);
1749-
spin_unlock_irqrestore(&wdata->state.lock, flags);
1761+
/* Locking state.lock here might deadlock with input_event() calls.
1762+
* schedule_work acts as barrier. Merging multiple changes is fine. */
1763+
wdata->state.cache_rumble = value;
1764+
schedule_work(&wdata->rumble_worker);
17501765

17511766
return 0;
17521767
}
@@ -1756,6 +1771,8 @@ static int wiimod_pro_probe(const struct wiimod_ops *ops,
17561771
{
17571772
int ret, i;
17581773

1774+
INIT_WORK(&wdata->rumble_worker, wiimod_rumble_worker);
1775+
17591776
wdata->extension.input = input_allocate_device();
17601777
if (!wdata->extension.input)
17611778
return -ENOMEM;
@@ -1817,12 +1834,13 @@ static void wiimod_pro_remove(const struct wiimod_ops *ops,
18171834
if (!wdata->extension.input)
18181835
return;
18191836

1837+
input_unregister_device(wdata->extension.input);
1838+
wdata->extension.input = NULL;
1839+
cancel_work_sync(&wdata->rumble_worker);
1840+
18201841
spin_lock_irqsave(&wdata->state.lock, flags);
18211842
wiiproto_req_rumble(wdata, 0);
18221843
spin_unlock_irqrestore(&wdata->state.lock, flags);
1823-
1824-
input_unregister_device(wdata->extension.input);
1825-
wdata->extension.input = NULL;
18261844
}
18271845

18281846
static const struct wiimod_ops wiimod_pro = {

drivers/hid/hid-wiimote.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,15 @@ struct wiimote_state {
133133
__u8 *cmd_read_buf;
134134
__u8 cmd_read_size;
135135

136-
/* calibration data */
136+
/* calibration/cache data */
137137
__u16 calib_bboard[4][3];
138+
__u8 cache_rumble;
138139
};
139140

140141
struct wiimote_data {
141142
struct hid_device *hdev;
142143
struct input_dev *input;
144+
struct work_struct rumble_worker;
143145
struct led_classdev *leds[4];
144146
struct input_dev *accel;
145147
struct input_dev *ir;

drivers/hid/hidraw.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -308,18 +308,25 @@ static int hidraw_fasync(int fd, struct file *file, int on)
308308
static void drop_ref(struct hidraw *hidraw, int exists_bit)
309309
{
310310
if (exists_bit) {
311-
hid_hw_close(hidraw->hid);
312311
hidraw->exist = 0;
313-
if (hidraw->open)
312+
if (hidraw->open) {
313+
hid_hw_close(hidraw->hid);
314314
wake_up_interruptible(&hidraw->wait);
315+
}
315316
} else {
316317
--hidraw->open;
317318
}
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+
}
323330
}
324331
}
325332

drivers/hid/uhid.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ static const struct file_operations uhid_fops = {
615615

616616
static struct miscdevice uhid_misc = {
617617
.fops = &uhid_fops,
618-
.minor = MISC_DYNAMIC_MINOR,
618+
.minor = UHID_MINOR,
619619
.name = UHID_NAME,
620620
};
621621

@@ -634,4 +634,5 @@ module_exit(uhid_exit);
634634
MODULE_LICENSE("GPL");
635635
MODULE_AUTHOR("David Herrmann <[email protected]>");
636636
MODULE_DESCRIPTION("User-space I/O driver support for HID subsystem");
637+
MODULE_ALIAS_MISCDEV(UHID_MINOR);
637638
MODULE_ALIAS("devname:" UHID_NAME);

include/linux/miscdevice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#define MAPPER_CTRL_MINOR 236
4646
#define LOOP_CTRL_MINOR 237
4747
#define VHOST_NET_MINOR 238
48+
#define UHID_MINOR 239
4849
#define MISC_DYNAMIC_MINOR 255
4950

5051
struct device;

0 commit comments

Comments
 (0)