aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-driver-hid-roccat-kone13
-rw-r--r--drivers/hid/hid-core.c2
-rw-r--r--drivers/hid/hid-ids.h4
-rw-r--r--drivers/hid/hid-input.c18
-rw-r--r--drivers/hid/hid-magicmouse.c96
-rw-r--r--drivers/hid/hid-roccat-kone.c25
-rw-r--r--drivers/hid/hid-roccat-kone.h2
-rw-r--r--drivers/hid/hid-roccat.c9
-rw-r--r--drivers/hid/hid-roccat.h2
-rw-r--r--drivers/hid/usbhid/hid-quirks.c2
-rw-r--r--include/linux/hid.h1
11 files changed, 99 insertions, 75 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone
index 88340a23ce91..063bda7fe707 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone
@@ -33,19 +33,6 @@ Description: When read, this file returns the raw integer version number of the
33 left. E.g. a returned value of 138 means 1.38 33 left. E.g. a returned value of 138 means 1.38
34 This file is readonly. 34 This file is readonly.
35 35
36What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/kone_driver_version
37Date: March 2010
38Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
39Description: When read, this file returns the driver version.
40 The format of the string is "v<major>.<minor>.<patchlevel>".
41 This attribute is used by the userland tools to find the sysfs-
42 paths of installed kone-mice and determine the capabilites of
43 the driver. Versions of this driver for old kernels replace
44 usbhid instead of generic-usb. The way to scan for this file
45 has been chosen to provide a consistent way for all supported
46 kernel versions.
47 This file is readonly.
48
49What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile[1-5] 36What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile[1-5]
50Date: March 2010 37Date: March 2010
51Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 38Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index e13d8033a84b..f4f04e4ef943 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1157,6 +1157,8 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
1157 1157
1158 if (hdev->quirks & HID_QUIRK_HIDDEV_FORCE) 1158 if (hdev->quirks & HID_QUIRK_HIDDEV_FORCE)
1159 connect_mask |= (HID_CONNECT_HIDDEV_FORCE | HID_CONNECT_HIDDEV); 1159 connect_mask |= (HID_CONNECT_HIDDEV_FORCE | HID_CONNECT_HIDDEV);
1160 if (hdev->quirks & HID_QUIRK_HIDINPUT_FORCE)
1161 connect_mask |= HID_CONNECT_HIDINPUT_FORCE;
1160 if (hdev->bus != BUS_USB) 1162 if (hdev->bus != BUS_USB)
1161 connect_mask &= ~HID_CONNECT_HIDDEV; 1163 connect_mask &= ~HID_CONNECT_HIDDEV;
1162 if (hid_hiddev(hdev)) 1164 if (hid_hiddev(hdev))
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 08b6ac6d2cc1..fa053ab4d570 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -439,6 +439,9 @@
439#define USB_VENDOR_ID_PHILIPS 0x0471 439#define USB_VENDOR_ID_PHILIPS 0x0471
440#define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617 440#define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617
441 441
442#define USB_VENDOR_ID_PI_ENGINEERING 0x05f3
443#define USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL 0xff
444
442#define USB_VENDOR_ID_PLAYDOTCOM 0x0b43 445#define USB_VENDOR_ID_PLAYDOTCOM 0x0b43
443#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003 446#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003
444 447
@@ -533,5 +536,4 @@
533#define USB_VENDOR_ID_ZYDACRON 0x13EC 536#define USB_VENDOR_ID_ZYDACRON 0x13EC
534#define USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL 0x0006 537#define USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL 0x0006
535 538
536
537#endif 539#endif
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 6b10e5afe770..d8cc79023848 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -199,11 +199,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
199 case HID_GD_MOUSE: 199 case HID_GD_MOUSE:
200 case HID_GD_POINTER: code += 0x110; break; 200 case HID_GD_POINTER: code += 0x110; break;
201 case HID_GD_JOYSTICK: 201 case HID_GD_JOYSTICK:
202 if (code <= 0xf) 202 if (code <= 0xf)
203 code += BTN_JOYSTICK; 203 code += BTN_JOYSTICK;
204 else 204 else
205 code += BTN_TRIGGER_HAPPY; 205 code += BTN_TRIGGER_HAPPY;
206 break; 206 break;
207 case HID_GD_GAMEPAD: code += 0x130; break; 207 case HID_GD_GAMEPAD: code += 0x130; break;
208 default: 208 default:
209 switch (field->physical) { 209 switch (field->physical) {
@@ -483,7 +483,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
483 483
484 case HID_UP_LOGIVENDOR: 484 case HID_UP_LOGIVENDOR:
485 goto ignore; 485 goto ignore;
486 486
487 case HID_UP_PID: 487 case HID_UP_PID:
488 switch (usage->hid & HID_USAGE) { 488 switch (usage->hid & HID_USAGE) {
489 case 0xa4: map_key_clear(BTN_DEAD); break; 489 case 0xa4: map_key_clear(BTN_DEAD); break;
@@ -589,9 +589,9 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
589 hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; 589 hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1;
590 if (hat_dir < 0 || hat_dir > 8) hat_dir = 0; 590 if (hat_dir < 0 || hat_dir > 8) hat_dir = 0;
591 input_event(input, usage->type, usage->code , hid_hat_to_axis[hat_dir].x); 591 input_event(input, usage->type, usage->code , hid_hat_to_axis[hat_dir].x);
592 input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[hat_dir].y); 592 input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[hat_dir].y);
593 return; 593 return;
594 } 594 }
595 595
596 if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */ 596 if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */
597 *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT); 597 *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT);
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index f10d56a15f21..319b0e57ee41 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -30,6 +30,21 @@ static bool emulate_scroll_wheel = true;
30module_param(emulate_scroll_wheel, bool, 0644); 30module_param(emulate_scroll_wheel, bool, 0644);
31MODULE_PARM_DESC(emulate_scroll_wheel, "Emulate a scroll wheel"); 31MODULE_PARM_DESC(emulate_scroll_wheel, "Emulate a scroll wheel");
32 32
33static unsigned int scroll_speed = 32;
34static int param_set_scroll_speed(const char *val, struct kernel_param *kp) {
35 unsigned long speed;
36 if (!val || strict_strtoul(val, 0, &speed) || speed > 63)
37 return -EINVAL;
38 scroll_speed = speed;
39 return 0;
40}
41module_param_call(scroll_speed, param_set_scroll_speed, param_get_uint, &scroll_speed, 0644);
42MODULE_PARM_DESC(scroll_speed, "Scroll speed, value from 0 (slow) to 63 (fast)");
43
44static bool scroll_acceleration = false;
45module_param(scroll_acceleration, bool, 0644);
46MODULE_PARM_DESC(scroll_acceleration, "Accelerate sequential scroll events");
47
33static bool report_touches = true; 48static bool report_touches = true;
34module_param(report_touches, bool, 0644); 49module_param(report_touches, bool, 0644);
35MODULE_PARM_DESC(report_touches, "Emit touch records (otherwise, only use them for emulation)"); 50MODULE_PARM_DESC(report_touches, "Emit touch records (otherwise, only use them for emulation)");
@@ -50,6 +65,8 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
50#define TOUCH_STATE_START 0x30 65#define TOUCH_STATE_START 0x30
51#define TOUCH_STATE_DRAG 0x40 66#define TOUCH_STATE_DRAG 0x40
52 67
68#define SCROLL_ACCEL_DEFAULT 7
69
53/** 70/**
54 * struct magicmouse_sc - Tracks Magic Mouse-specific data. 71 * struct magicmouse_sc - Tracks Magic Mouse-specific data.
55 * @input: Input device through which we report events. 72 * @input: Input device through which we report events.
@@ -78,8 +95,10 @@ struct magicmouse_sc {
78 struct { 95 struct {
79 short x; 96 short x;
80 short y; 97 short y;
98 short scroll_x;
81 short scroll_y; 99 short scroll_y;
82 u8 size; 100 u8 size;
101 u8 down;
83 } touches[16]; 102 } touches[16];
84 int tracking_ids[16]; 103 int tracking_ids[16];
85}; 104};
@@ -141,7 +160,7 @@ static void magicmouse_emit_buttons(struct magicmouse_sc *msc, int state)
141 input_report_key(msc->input, BTN_RIGHT, state & 2); 160 input_report_key(msc->input, BTN_RIGHT, state & 2);
142 161
143 if (state != last_state) 162 if (state != last_state)
144 msc->scroll_accel = 0; 163 msc->scroll_accel = SCROLL_ACCEL_DEFAULT;
145} 164}
146 165
147static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata) 166static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata)
@@ -152,6 +171,7 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
152 int id = (misc >> 6) & 15; 171 int id = (misc >> 6) & 15;
153 int x = x_y << 12 >> 20; 172 int x = x_y << 12 >> 20;
154 int y = -(x_y >> 20); 173 int y = -(x_y >> 20);
174 int down = (tdata[7] & TOUCH_STATE_MASK) != TOUCH_STATE_NONE;
155 175
156 /* Store tracking ID and other fields. */ 176 /* Store tracking ID and other fields. */
157 msc->tracking_ids[raw_id] = id; 177 msc->tracking_ids[raw_id] = id;
@@ -160,42 +180,54 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
160 msc->touches[id].size = misc & 63; 180 msc->touches[id].size = misc & 63;
161 181
162 /* If requested, emulate a scroll wheel by detecting small 182 /* If requested, emulate a scroll wheel by detecting small
163 * vertical touch motions along the middle of the mouse. 183 * vertical touch motions.
164 */ 184 */
165 if (emulate_scroll_wheel && 185 if (emulate_scroll_wheel) {
166 middle_button_start < x && x < middle_button_stop) {
167 static const int accel_profile[] = {
168 256, 228, 192, 160, 128, 96, 64, 32,
169 };
170 unsigned long now = jiffies; 186 unsigned long now = jiffies;
171 int step = msc->touches[id].scroll_y - y; 187 int step_x = msc->touches[id].scroll_x - x;
172 188 int step_y = msc->touches[id].scroll_y - y;
173 /* Reset acceleration after half a second. */
174 if (time_after(now, msc->scroll_jiffies + HZ / 2))
175 msc->scroll_accel = 0;
176 189
177 /* Calculate and apply the scroll motion. */ 190 /* Calculate and apply the scroll motion. */
178 switch (tdata[7] & TOUCH_STATE_MASK) { 191 switch (tdata[7] & TOUCH_STATE_MASK) {
179 case TOUCH_STATE_START: 192 case TOUCH_STATE_START:
193 msc->touches[id].scroll_x = x;
180 msc->touches[id].scroll_y = y; 194 msc->touches[id].scroll_y = y;
181 msc->scroll_accel = min_t(int, msc->scroll_accel + 1, 195
182 ARRAY_SIZE(accel_profile) - 1); 196 /* Reset acceleration after half a second. */
197 if (scroll_acceleration && time_before(now,
198 msc->scroll_jiffies + HZ / 2))
199 msc->scroll_accel = max_t(int,
200 msc->scroll_accel - 1, 1);
201 else
202 msc->scroll_accel = SCROLL_ACCEL_DEFAULT;
203
183 break; 204 break;
184 case TOUCH_STATE_DRAG: 205 case TOUCH_STATE_DRAG:
185 step = step / accel_profile[msc->scroll_accel]; 206 step_x /= (64 - (int)scroll_speed) * msc->scroll_accel;
186 if (step != 0) { 207 if (step_x != 0) {
187 msc->touches[id].scroll_y = y; 208 msc->touches[id].scroll_x -= step_x *
209 (64 - scroll_speed) * msc->scroll_accel;
188 msc->scroll_jiffies = now; 210 msc->scroll_jiffies = now;
189 input_report_rel(input, REL_WHEEL, step); 211 input_report_rel(input, REL_HWHEEL, -step_x);
212 }
213
214 step_y /= (64 - (int)scroll_speed) * msc->scroll_accel;
215 if (step_y != 0) {
216 msc->touches[id].scroll_y -= step_y *
217 (64 - scroll_speed) * msc->scroll_accel;
218 msc->scroll_jiffies = now;
219 input_report_rel(input, REL_WHEEL, step_y);
190 } 220 }
191 break; 221 break;
192 } 222 }
193 } 223 }
194 224
195 /* Generate the input events for this touch. */ 225 /* Generate the input events for this touch. */
196 if (report_touches) { 226 if (report_touches && down) {
197 int orientation = (misc >> 10) - 32; 227 int orientation = (misc >> 10) - 32;
198 228
229 msc->touches[id].down = 1;
230
199 input_report_abs(input, ABS_MT_TRACKING_ID, id); 231 input_report_abs(input, ABS_MT_TRACKING_ID, id);
200 input_report_abs(input, ABS_MT_TOUCH_MAJOR, tdata[3]); 232 input_report_abs(input, ABS_MT_TOUCH_MAJOR, tdata[3]);
201 input_report_abs(input, ABS_MT_TOUCH_MINOR, tdata[4]); 233 input_report_abs(input, ABS_MT_TOUCH_MINOR, tdata[4]);
@@ -215,7 +247,7 @@ static int magicmouse_raw_event(struct hid_device *hdev,
215{ 247{
216 struct magicmouse_sc *msc = hid_get_drvdata(hdev); 248 struct magicmouse_sc *msc = hid_get_drvdata(hdev);
217 struct input_dev *input = msc->input; 249 struct input_dev *input = msc->input;
218 int x, y, ts, ii, clicks; 250 int x, y, ts, ii, clicks, last_up;
219 251
220 switch (data[0]) { 252 switch (data[0]) {
221 case 0x10: 253 case 0x10:
@@ -235,12 +267,26 @@ static int magicmouse_raw_event(struct hid_device *hdev,
235 msc->ntouches = (size - 6) / 8; 267 msc->ntouches = (size - 6) / 8;
236 for (ii = 0; ii < msc->ntouches; ii++) 268 for (ii = 0; ii < msc->ntouches; ii++)
237 magicmouse_emit_touch(msc, ii, data + ii * 8 + 6); 269 magicmouse_emit_touch(msc, ii, data + ii * 8 + 6);
270
271 if (report_touches) {
272 last_up = 1;
273 for (ii = 0; ii < ARRAY_SIZE(msc->touches); ii++) {
274 if (msc->touches[ii].down) {
275 last_up = 0;
276 msc->touches[ii].down = 0;
277 }
278 }
279 if (last_up) {
280 input_mt_sync(input);
281 }
282 }
283
238 /* When emulating three-button mode, it is important 284 /* When emulating three-button mode, it is important
239 * to have the current touch information before 285 * to have the current touch information before
240 * generating a click event. 286 * generating a click event.
241 */ 287 */
242 x = (signed char)data[1]; 288 x = (int)(((data[3] & 0x0c) << 28) | (data[1] << 22)) >> 22;
243 y = (signed char)data[2]; 289 y = (int)(((data[3] & 0x30) << 26) | (data[2] << 22)) >> 22;
244 clicks = data[3]; 290 clicks = data[3];
245 break; 291 break;
246 case 0x20: /* Theoretically battery status (0-100), but I have 292 case 0x20: /* Theoretically battery status (0-100), but I have
@@ -301,8 +347,10 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h
301 __set_bit(EV_REL, input->evbit); 347 __set_bit(EV_REL, input->evbit);
302 __set_bit(REL_X, input->relbit); 348 __set_bit(REL_X, input->relbit);
303 __set_bit(REL_Y, input->relbit); 349 __set_bit(REL_Y, input->relbit);
304 if (emulate_scroll_wheel) 350 if (emulate_scroll_wheel) {
305 __set_bit(REL_WHEEL, input->relbit); 351 __set_bit(REL_WHEEL, input->relbit);
352 __set_bit(REL_HWHEEL, input->relbit);
353 }
306 354
307 if (report_touches) { 355 if (report_touches) {
308 __set_bit(EV_ABS, input->evbit); 356 __set_bit(EV_ABS, input->evbit);
@@ -345,6 +393,8 @@ static int magicmouse_probe(struct hid_device *hdev,
345 return -ENOMEM; 393 return -ENOMEM;
346 } 394 }
347 395
396 msc->scroll_accel = SCROLL_ACCEL_DEFAULT;
397
348 msc->quirks = id->driver_data; 398 msc->quirks = id->driver_data;
349 hid_set_drvdata(hdev, msc); 399 hid_set_drvdata(hdev, msc);
350 400
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c
index 17f2dc04f883..f77695762cb5 100644
--- a/drivers/hid/hid-roccat-kone.c
+++ b/drivers/hid/hid-roccat-kone.c
@@ -22,11 +22,6 @@
22 * Is it possible to remove and reinstall the urb in raw-event- or any 22 * Is it possible to remove and reinstall the urb in raw-event- or any
23 * other handler, or to defer this action to be executed somewhere else? 23 * other handler, or to defer this action to be executed somewhere else?
24 * 24 *
25 * TODO implement notification mechanism for overlong macro execution
26 * If user wants to execute an overlong macro only the names of macroset
27 * and macro are given. Should userland tap hidraw or is there an
28 * additional streaming mechanism?
29 *
30 * TODO is it possible to overwrite group for sysfs attributes via udev? 25 * TODO is it possible to overwrite group for sysfs attributes via udev?
31 */ 26 */
32 27
@@ -277,7 +272,7 @@ static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj,
277 count = sizeof(struct kone_settings) - off; 272 count = sizeof(struct kone_settings) - off;
278 273
279 mutex_lock(&kone->kone_lock); 274 mutex_lock(&kone->kone_lock);
280 memcpy(buf, &kone->settings + off, count); 275 memcpy(buf, ((char const *)&kone->settings) + off, count);
281 mutex_unlock(&kone->kone_lock); 276 mutex_unlock(&kone->kone_lock);
282 277
283 return count; 278 return count;
@@ -337,7 +332,7 @@ static ssize_t kone_sysfs_read_profilex(struct kobject *kobj,
337 count = sizeof(struct kone_profile) - off; 332 count = sizeof(struct kone_profile) - off;
338 333
339 mutex_lock(&kone->kone_lock); 334 mutex_lock(&kone->kone_lock);
340 memcpy(buf, &kone->profiles[number - 1], sizeof(struct kone_profile)); 335 memcpy(buf, ((char const *)&kone->profiles[number - 1]) + off, count);
341 mutex_unlock(&kone->kone_lock); 336 mutex_unlock(&kone->kone_lock);
342 337
343 return count; 338 return count;
@@ -623,18 +618,6 @@ static ssize_t kone_sysfs_set_startup_profile(struct device *dev,
623} 618}
624 619
625/* 620/*
626 * This file is used by userland software to find devices that are handled by
627 * this driver. This provides a consistent way for actual and older kernels
628 * where this driver replaced usbhid instead of generic-usb.
629 * Driver capabilities are determined by version number.
630 */
631static ssize_t kone_sysfs_show_driver_version(struct device *dev,
632 struct device_attribute *attr, char *buf)
633{
634 return snprintf(buf, PAGE_SIZE, ROCCAT_KONE_DRIVER_VERSION "\n");
635}
636
637/*
638 * Read actual dpi settings. 621 * Read actual dpi settings.
639 * Returns raw value for further processing. Refer to enum kone_polling_rates to 622 * Returns raw value for further processing. Refer to enum kone_polling_rates to
640 * get real value. 623 * get real value.
@@ -671,9 +654,6 @@ static DEVICE_ATTR(startup_profile, 0660,
671 kone_sysfs_show_startup_profile, 654 kone_sysfs_show_startup_profile,
672 kone_sysfs_set_startup_profile); 655 kone_sysfs_set_startup_profile);
673 656
674static DEVICE_ATTR(kone_driver_version, 0440,
675 kone_sysfs_show_driver_version, NULL);
676
677static struct attribute *kone_attributes[] = { 657static struct attribute *kone_attributes[] = {
678 &dev_attr_actual_dpi.attr, 658 &dev_attr_actual_dpi.attr,
679 &dev_attr_actual_profile.attr, 659 &dev_attr_actual_profile.attr,
@@ -681,7 +661,6 @@ static struct attribute *kone_attributes[] = {
681 &dev_attr_firmware_version.attr, 661 &dev_attr_firmware_version.attr,
682 &dev_attr_tcu.attr, 662 &dev_attr_tcu.attr,
683 &dev_attr_startup_profile.attr, 663 &dev_attr_startup_profile.attr,
684 &dev_attr_kone_driver_version.attr,
685 NULL 664 NULL
686}; 665};
687 666
diff --git a/drivers/hid/hid-roccat-kone.h b/drivers/hid/hid-roccat-kone.h
index 003e6f81c195..130d6566ea82 100644
--- a/drivers/hid/hid-roccat-kone.h
+++ b/drivers/hid/hid-roccat-kone.h
@@ -14,8 +14,6 @@
14 14
15#include <linux/types.h> 15#include <linux/types.h>
16 16
17#define ROCCAT_KONE_DRIVER_VERSION "v0.3.1"
18
19#pragma pack(push) 17#pragma pack(push)
20#pragma pack(1) 18#pragma pack(1)
21 19
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c
index e05d48edb66f..f6e80c7ca61e 100644
--- a/drivers/hid/hid-roccat.c
+++ b/drivers/hid/hid-roccat.c
@@ -168,7 +168,7 @@ static int roccat_open(struct inode *inode, struct file *file)
168 printk(KERN_EMERG "roccat device with minor %d doesn't exist\n", 168 printk(KERN_EMERG "roccat device with minor %d doesn't exist\n",
169 minor); 169 minor);
170 error = -ENODEV; 170 error = -ENODEV;
171 goto exit_unlock; 171 goto exit_err;
172 } 172 }
173 173
174 if (!device->open++) { 174 if (!device->open++) {
@@ -178,7 +178,7 @@ static int roccat_open(struct inode *inode, struct file *file)
178 PM_HINT_FULLON); 178 PM_HINT_FULLON);
179 if (error < 0) { 179 if (error < 0) {
180 --device->open; 180 --device->open;
181 goto exit_unlock; 181 goto exit_err;
182 } 182 }
183 } 183 }
184 error = device->hid->ll_driver->open(device->hid); 184 error = device->hid->ll_driver->open(device->hid);
@@ -187,7 +187,7 @@ static int roccat_open(struct inode *inode, struct file *file)
187 device->hid->ll_driver->power(device->hid, 187 device->hid->ll_driver->power(device->hid,
188 PM_HINT_NORMAL); 188 PM_HINT_NORMAL);
189 --device->open; 189 --device->open;
190 goto exit_unlock; 190 goto exit_err;
191 } 191 }
192 } 192 }
193 193
@@ -202,6 +202,9 @@ exit_unlock:
202 mutex_unlock(&device->readers_lock); 202 mutex_unlock(&device->readers_lock);
203 mutex_unlock(&devices_lock); 203 mutex_unlock(&devices_lock);
204 return error; 204 return error;
205exit_err:
206 kfree(reader);
207 goto exit_unlock;
205} 208}
206 209
207static int roccat_release(struct inode *inode, struct file *file) 210static int roccat_release(struct inode *inode, struct file *file)
diff --git a/drivers/hid/hid-roccat.h b/drivers/hid/hid-roccat.h
index d8aae0c1fa7e..09e864e9f79d 100644
--- a/drivers/hid/hid-roccat.h
+++ b/drivers/hid/hid-roccat.h
@@ -15,7 +15,7 @@
15#include <linux/hid.h> 15#include <linux/hid.h>
16#include <linux/types.h> 16#include <linux/types.h>
17 17
18#if defined(CONFIG_HID_ROCCAT) || defined (CONFIG_HID_ROCCAT_MODULE) 18#if defined(CONFIG_HID_ROCCAT) || defined(CONFIG_HID_ROCCAT_MODULE)
19int roccat_connect(struct hid_device *hid); 19int roccat_connect(struct hid_device *hid);
20void roccat_disconnect(int minor); 20void roccat_disconnect(int minor);
21int roccat_report_event(int minor, u8 const *data, int len); 21int roccat_report_event(int minor, u8 const *data, int len);
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 5f5aa39b3988..2643d3147621 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -75,6 +75,8 @@ static const struct hid_blacklist {
75 { USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, 75 { USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
76 { USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, 76 { USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
77 77
78 { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE },
79
78 { 0, 0 } 80 { 0, 0 }
79}; 81};
80 82
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 895001f7f4b2..42a0f1d11365 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -311,6 +311,7 @@ struct hid_item {
311#define HID_QUIRK_HIDDEV_FORCE 0x00000010 311#define HID_QUIRK_HIDDEV_FORCE 0x00000010
312#define HID_QUIRK_BADPAD 0x00000020 312#define HID_QUIRK_BADPAD 0x00000020
313#define HID_QUIRK_MULTI_INPUT 0x00000040 313#define HID_QUIRK_MULTI_INPUT 0x00000040
314#define HID_QUIRK_HIDINPUT_FORCE 0x00000080
314#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 315#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000
315#define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000 316#define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000
316#define HID_QUIRK_NO_INIT_REPORTS 0x20000000 317#define HID_QUIRK_NO_INIT_REPORTS 0x20000000