diff options
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/Kconfig | 13 | ||||
-rw-r--r-- | drivers/hid/hid-apple.c | 6 | ||||
-rw-r--r-- | drivers/hid/hid-core.c | 17 | ||||
-rw-r--r-- | drivers/hid/hid-debug.c | 2 | ||||
-rw-r--r-- | drivers/hid/hid-ids.h | 13 | ||||
-rw-r--r-- | drivers/hid/hid-input.c | 64 | ||||
-rw-r--r-- | drivers/hid/hid-lg.c | 2 | ||||
-rw-r--r-- | drivers/hid/hid-lgff.c | 5 | ||||
-rw-r--r-- | drivers/hid/hid-magicmouse.c | 14 | ||||
-rw-r--r-- | drivers/hid/hid-ortek.c | 16 | ||||
-rw-r--r-- | drivers/hid/hid-picolcd.c | 9 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-kone.h | 2 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-koneplus.c | 82 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-koneplus.h | 11 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-pyra.c | 3 | ||||
-rw-r--r-- | drivers/hid/hid-sony.c | 2 | ||||
-rw-r--r-- | drivers/hid/hidraw.c | 30 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-quirks.c | 3 | ||||
-rw-r--r-- | drivers/hid/usbhid/hiddev.c | 34 |
19 files changed, 217 insertions, 111 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index d588a5e28d0..67d2a758593 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -173,7 +173,7 @@ config HID_EZKEY Support for Ezkey BTC 8193 keyboard. config HID_KEYTOUCH - tristate "Keyoutch HID devices" + tristate "Keytouch HID devices" depends on USB_HID ---help--- Support for Keytouch HID devices not fully compliant with @@ -334,10 +334,17 @@ config HID_NTRIG Support for N-Trig touch screen. config HID_ORTEK - tristate "Ortek PKB-1700/WKB-2000 wireless keyboard and mouse trackpad" + tristate "Ortek PKB-1700/WKB-2000/Skycable wireless keyboard and mouse trackpad" depends on USB_HID ---help--- - Support for Ortek PKB-1700/WKB-2000 wireless keyboard + mouse trackpad. + There are certain devices which have LogicalMaximum wrong in the keyboard + usage page of their report descriptor. The most prevailing ones so far + are manufactured by Ortek, thus the name of the driver. Currently + supported devices by this driver are + + - Ortek PKB-1700 + - Ortek WKB-2000 + - Skycable wireless presenter config HID_PANTHERLORD tristate "Pantherlord/GreenAsia game controller" diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 61aa7123339..b85744fe846 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -481,6 +481,12 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS), .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI), + .driver_data = APPLE_HAS_FN }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO), + .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 9f15c9238fb..4140fd27141 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -306,7 +306,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) case HID_GLOBAL_ITEM_TAG_PUSH: if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) { - dbg_hid("global enviroment stack overflow\n"); + dbg_hid("global environment stack overflow\n"); return -1; } @@ -317,7 +317,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) case HID_GLOBAL_ITEM_TAG_POP: if (!parser->global_stack_ptr) { - dbg_hid("global enviroment stack underflow\n"); + dbg_hid("global environment stack underflow\n"); return -1; } @@ -1045,6 +1045,9 @@ void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, rsize = ((report->size - 1) >> 3) + 1; + if (rsize > HID_MAX_BUFFER_SIZE) + rsize = HID_MAX_BUFFER_SIZE; + if (csize < rsize) { dbg_hid("report %d is too short, (%d < %d)\n", report->id, csize, rsize); @@ -1334,6 +1337,9 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, @@ -1410,6 +1416,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) }, @@ -1453,9 +1460,12 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) }, @@ -1850,6 +1860,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { } diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 555382fc741..bae48745bb4 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -341,7 +341,7 @@ static const struct hid_usage_entry hid_usage_table[] = { { 0x85, 0x83, "DesignCapacity" }, { 0x85, 0x85, "ManufacturerDate" }, { 0x85, 0x89, "iDeviceChemistry" }, - { 0x85, 0x8b, "Rechargable" }, + { 0x85, 0x8b, "Rechargeable" }, { 0x85, 0x8f, "iOEMInformation" }, { 0x85, 0x8d, "CapacityGranularity1" }, { 0x85, 0xd0, "ACPresent" }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index b8299ef0f01..e715c43aa01 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -106,6 +106,9 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244 +#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 +#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 +#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b @@ -150,6 +153,7 @@ #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01 #define USB_VENDOR_ID_CH 0x068e +#define USB_DEVICE_ID_CH_PRO_THROTTLE 0x00f1 #define USB_DEVICE_ID_CH_PRO_PEDALS 0x00f2 #define USB_DEVICE_ID_CH_COMBATSTICK 0x00f4 #define USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE 0x0051 @@ -407,6 +411,7 @@ #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 #define USB_DEVICE_ID_LOGITECH_DFP_WHEEL 0xc298 #define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299 +#define USB_DEVICE_ID_LOGITECH_G27_WHEEL 0xc29b #define USB_DEVICE_ID_LOGITECH_WII_WHEEL 0xc29c #define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a #define USB_DEVICE_ID_S510_RECEIVER 0xc50c @@ -540,9 +545,13 @@ #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001 #define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE 0x0600 +#define USB_VENDOR_ID_SKYCABLE 0x1223 +#define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 + #define USB_VENDOR_ID_SONY 0x054c #define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 +#define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f #define USB_VENDOR_ID_SOUNDGRAPH 0x15c2 #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034 @@ -563,6 +572,10 @@ #define USB_VENDOR_ID_SUNPLUS 0x04fc #define USB_DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8 +#define USB_VENDOR_ID_SYMBOL 0x05e0 +#define USB_DEVICE_ID_SYMBOL_SCANNER_1 0x0800 +#define USB_DEVICE_ID_SYMBOL_SCANNER_2 0x1300 + #define USB_VENDOR_ID_THRUSTMASTER 0x044f #define USB_VENDOR_ID_TOPSEED 0x0766 diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index cd74203c817..6559e2e3364 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -44,11 +44,11 @@ static const unsigned char hid_keyboard[256] = { 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, 115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk, - 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, + 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk, unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,unk,unk,unk,unk, unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, - unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, + unk,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,unk,unk,unk,unk, 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, 150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk }; @@ -357,6 +357,18 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x1: map_key_clear(KEY_POWER); break; case 0x2: map_key_clear(KEY_SLEEP); break; case 0x3: map_key_clear(KEY_WAKEUP); break; + case 0x4: map_key_clear(KEY_CONTEXT_MENU); break; + case 0x5: map_key_clear(KEY_MENU); break; + case 0x6: map_key_clear(KEY_PROG1); break; + case 0x7: map_key_clear(KEY_HELP); break; + case 0x8: map_key_clear(KEY_EXIT); break; + case 0x9: map_key_clear(KEY_SELECT); break; + case 0xa: map_key_clear(KEY_RIGHT); break; + case 0xb: map_key_clear(KEY_LEFT); break; + case 0xc: map_key_clear(KEY_UP); break; + case 0xd: map_key_clear(KEY_DOWN); break; + case 0xe: map_key_clear(KEY_POWER2); break; + case 0xf: map_key_clear(KEY_RESTART); break; default: goto unknown; } break; @@ -466,16 +478,39 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel } break; - case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */ + case HID_UP_CONSUMER: /* USB HUT v1.12, pages 75-84 */ switch (usage->hid & HID_USAGE) { case 0x000: goto ignore; + case 0x030: map_key_clear(KEY_POWER); break; + case 0x031: map_key_clear(KEY_RESTART); break; + case 0x032: map_key_clear(KEY_SLEEP); break; case 0x034: map_key_clear(KEY_SLEEP); break; + case 0x035: map_key_clear(KEY_KBDILLUMTOGGLE); break; case 0x036: map_key_clear(BTN_MISC); break; - case 0x040: map_key_clear(KEY_MENU); break; - case 0x045: map_key_clear(KEY_RADIO); break; - + case 0x040: map_key_clear(KEY_MENU); break; /* Menu */ + case 0x041: map_key_clear(KEY_SELECT); break; /* Menu Pick */ + case 0x042: map_key_clear(KEY_UP); break; /* Menu Up */ + case 0x043: map_key_clear(KEY_DOWN); break; /* Menu Down */ + case 0x044: map_key_clear(KEY_LEFT); break; /* Menu Left */ + case 0x045: map_key_clear(KEY_RIGHT); break; /* Menu Right */ + case 0x046: map_key_clear(KEY_ESC); break; /* Menu Escape */ + case 0x047: map_key_clear(KEY_KPPLUS); break; /* Menu Value Increase */ + case 0x048: map_key_clear(KEY_KPMINUS); break; /* Menu Value Decrease */ + + case 0x060: map_key_clear(KEY_INFO); break; /* Data On Screen */ + case 0x061: map_key_clear(KEY_SUBTITLE); break; /* Closed Caption */ + case 0x063: map_key_clear(KEY_VCR); break; /* VCR/TV */ + case 0x065: map_key_clear(KEY_CAMERA); break; /* Snapshot */ + case 0x069: map_key_clear(KEY_RED); break; + case 0x06a: map_key_clear(KEY_GREEN); break; + case 0x06b: map_key_clear(KEY_BLUE); break; + case 0x06c: map_key_clear(KEY_YELLOW); break; + case 0x06d: map_key_clear(KEY_ZOOM); break; + + case 0x082: map_key_clear(KEY_VIDEO_NEXT); break; case 0x083: map_key_clear(KEY_LAST); break; + case 0x084: map_key_clear(KEY_ENTER); break; case 0x088: map_key_clear(KEY_PC); break; case 0x089: map_key_clear(KEY_TV); break; case 0x08a: map_key_clear(KEY_WWW); break; @@ -509,6 +544,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x0b7: map_key_clear(KEY_STOPCD); break; case 0x0b8: map_key_clear(KEY_EJECTCD); break; case 0x0bc: map_key_clear(KEY_MEDIA_REPEAT); break; + case 0x0b9: map_key_clear(KEY_SHUFFLE); break; + case 0x0bf: map_key_clear(KEY_SLOW); break; case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break; case 0x0e0: map_abs_clear(ABS_VOLUME); break; @@ -516,6 +553,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x0e5: map_key_clear(KEY_BASSBOOST); break; case 0x0e9: map_key_clear(KEY_VOLUMEUP); break; case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break; + case 0x0f5: map_key_clear(KEY_SLOW); break; case 0x182: map_key_clear(KEY_BOOKMARKS); break; case 0x183: map_key_clear(KEY_CONFIG); break; @@ -532,6 +570,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x18e: map_key_clear(KEY_CALENDAR); break; case 0x191: map_key_clear(KEY_FINANCE); break; case 0x192: map_key_clear(KEY_CALC); break; + case 0x193: map_key_clear(KEY_PLAYER); break; case 0x194: map_key_clear(KEY_FILE); break; case 0x196: map_key_clear(KEY_WWW); break; case 0x199: map_key_clear(KEY_CHAT); break; @@ -540,8 +579,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x1a6: map_key_clear(KEY_HELP); break; case 0x1a7: map_key_clear(KEY_DOCUMENTS); break; case 0x1ab: map_key_clear(KEY_SPELLCHECK); break; - case 0x1b6: map_key_clear(KEY_MEDIA); break; - case 0x1b7: map_key_clear(KEY_SOUND); break; + case 0x1ae: map_key_clear(KEY_KEYBOARD); break; + case 0x1b6: map_key_clear(KEY_IMAGES); break; + case 0x1b7: map_key_clear(KEY_AUDIO); break; + case 0x1b8: map_key_clear(KEY_VIDEO); break; case 0x1bc: map_key_clear(KEY_MESSENGER); break; case 0x1bd: map_key_clear(KEY_INFO); break; case 0x201: map_key_clear(KEY_NEW); break; @@ -570,7 +611,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x233: map_key_clear(KEY_SCROLLUP); break; case 0x234: map_key_clear(KEY_SCROLLDOWN); break; case 0x238: map_rel(REL_HWHEEL); break; + case 0x23d: map_key_clear(KEY_EDIT); break; case 0x25f: map_key_clear(KEY_CANCEL); break; + case 0x269: map_key_clear(KEY_INSERT); break; + case 0x26a: map_key_clear(KEY_DELETE); break; case 0x279: map_key_clear(KEY_REDO); break; case 0x289: map_key_clear(KEY_REPLY); break; @@ -900,8 +944,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) hid->ll_driver->hidinput_input_event; input_dev->open = hidinput_open; input_dev->close = hidinput_close; - input_dev->setkeycode_new = hidinput_setkeycode; - input_dev->getkeycode_new = hidinput_getkeycode; + input_dev->setkeycode = hidinput_setkeycode; + input_dev->getkeycode = hidinput_getkeycode; input_dev->name = hid->name; input_dev->phys = hid->phys; diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 3da90402ee8..21f205f0925 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -377,6 +377,8 @@ static const struct hid_device_id lg_devices[] = { .driver_data = LG_FF }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL), .driver_data = LG_FF }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL), + .driver_data = LG_FF }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL), .driver_data = LG_FF }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL), diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c index 90d0ef2c92b..088f8504929 100644 --- a/drivers/hid/hid-lgff.c +++ b/drivers/hid/hid-lgff.c @@ -72,7 +72,12 @@ static const struct dev_type devices[] = { { 0x046d, 0xc287, ff_joystick_ac }, { 0x046d, 0xc293, ff_joystick }, { 0x046d, 0xc294, ff_wheel }, + { 0x046d, 0xc298, ff_wheel }, + { 0x046d, 0xc299, ff_wheel }, + { 0x046d, 0xc29b, ff_wheel }, { 0x046d, 0xc295, ff_joystick }, + { 0x046d, 0xc298, ff_wheel }, + { 0x046d, 0xc299, ff_wheel }, { 0x046d, 0xca03, ff_wheel }, }; diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index 318cc40df92..a5eda4c8127 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -76,7 +76,7 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie * This is true when single_touch_id is equal to NO_TOUCHES. If multiple touches * are down and the touch providing for single touch emulation is lifted, * single_touch_id is equal to SINGLE_TOUCH_UP. While single touch emulation is - * occuring, single_touch_id corresponds with the tracking id of the touch used. + * occurring, single_touch_id corresponds with the tracking id of the touch used. */ #define NO_TOUCHES -1 #define SINGLE_TOUCH_UP -2 @@ -418,6 +418,8 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h input_set_abs_params(input, ABS_MT_POSITION_Y, -2456, 2565, 4, 0); } + + input_set_events_per_packet(input, 60); } if (report_undeciphered) { @@ -499,9 +501,17 @@ static int magicmouse_probe(struct hid_device *hdev, } report->size = 6; + /* + * The device reponds with 'invalid report id' when feature + * report switching it into multitouch mode is sent to it. + * + * This results in -EIO from the _raw low-level transport callback, + * but there seems to be no other way of switching the mode. + * Thus the super-ugly hacky success check below. + */ ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature), HID_FEATURE_REPORT); - if (ret != sizeof(feature)) { + if (ret != -EIO) { hid_err(hdev, "unable to request touch data (%d)\n", ret); goto err_stop_hw; } diff --git a/drivers/hid/hid-ortek.c b/drivers/hid/hid-ortek.c index f9b7dd4f607..0ffa1d2d64f 100644 --- a/drivers/hid/hid-ortek.c +++ b/drivers/hid/hid-ortek.c @@ -1,8 +1,14 @@ /* - * HID driver for Ortek PKB-1700/WKB-2000 (wireless keyboard + mouse trackpad). - * Fixes LogicalMaximum error in HID report description. + * HID driver for various devices which are apparently based on the same chipset + * from certain vendor which produces chips that contain wrong LogicalMaximum + * value in their HID report descriptor. Currently supported devices are: + * + * Ortek PKB-1700 + * Ortek WKB-2000 + * Skycable wireless presenter * * Copyright (c) 2010 Johnathon Harris <jmharris@gmail.com> + * Copyright (c) 2011 Jiri Kosina */ /* @@ -22,8 +28,11 @@ static __u8 *ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { if (*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) { - hid_info(hdev, "Fixing up Ortek WKB-2000 report descriptor\n"); + hid_info(hdev, "Fixing up logical minimum in report descriptor (Ortek)\n"); rdesc[55] = 0x92; + } else if (*rsize >= 54 && rdesc[52] == 0x25 && rdesc[53] == 0x01) { + hid_info(hdev, "Fixing up logical minimum in report descriptor (Skycable)\n"); + rdesc[53] = 0x65; } return rdesc; } @@ -31,6 +40,7 @@ static __u8 *ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc, static const struct hid_device_id ortek_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) }, { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, { } }; MODULE_DEVICE_TABLE(hid, ortek_devices); diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c index de9cf21b349..9d8710f8bc7 100644 --- a/drivers/hid/hid-picolcd.c +++ b/drivers/hid/hid-picolcd.c @@ -944,6 +944,7 @@ static int picolcd_init_backlight(struct picolcd_data *data, struct hid_report * } memset(&props, 0, sizeof(props)); + props.type = BACKLIGHT_RAW; props.max_brightness = 0xff; bdev = backlight_device_register(dev_name(dev), dev, data, &picolcd_blops, &props); @@ -1584,11 +1585,11 @@ static ssize_t picolcd_debug_eeprom_write(struct file *f, const char __user *u, memset(raw_data, 0, sizeof(raw_data)); raw_data[0] = *off & 0xff; raw_data[1] = (*off >> 8) & 0xff; - raw_data[2] = s < 20 ? s : 20; + raw_data[2] = min((size_t)20, s); if (*off + raw_data[2] > 0xff) raw_data[2] = 0x100 - *off; - if (copy_from_user(raw_data+3, u, raw_data[2])) + if (copy_from_user(raw_data+3, u, min((u8)20, raw_data[2]))) return -EFAULT; resp = picolcd_send_and_wait(data->hdev, REPORT_EE_WRITE, raw_data, sizeof(raw_data)); @@ -1805,13 +1806,13 @@ static ssize_t picolcd_debug_flash_write(struct file *f, const char __user *u, /* * Notes: * - concurrent writing is prevented by mutex and all writes must be - * n*64 bytes and 64-byte aligned, each write being preceeded by an + * n*64 bytes and 64-byte aligned, each write being preceded by an * ERASE which erases a 64byte block. * If less than requested was written or an error is returned for an * otherwise correct write request the next 64-byte block which should * have been written is in undefined state (mostly: original, erased, * (half-)written with write error) - * - reading can happend without special restriction + * - reading can happen without special restriction */ static const struct file_operations picolcd_debug_flash_fops = { .owner = THIS_MODULE, diff --git a/drivers/hid/hid-roccat-kone.h b/drivers/hid/hid-roccat-kone.h index 64abb5b8a59..4109a028e13 100644 --- a/drivers/hid/hid-roccat-kone.h +++ b/drivers/hid/hid-roccat-kone.h @@ -166,7 +166,7 @@ enum kone_mouse_events { /* osd events are thought to be display on screen */ kone_mouse_event_osd_dpi = 0xa0, kone_mouse_event_osd_profile = 0xb0, - /* TODO clarify meaning and occurence of kone_mouse_event_calibration */ + /* TODO clarify meaning and occurrence of kone_mouse_event_calibration */ kone_mouse_event_calibration = 0xc0, kone_mouse_event_call_overlong_macro = 0xe0, /* switch events notify if user changed values with mousebutton click */ diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c index 33eec74e061..5b640a7a15a 100644 --- a/drivers/hid/hid-roccat-koneplus.c +++ b/drivers/hid/hid-roccat-koneplus.c @@ -167,28 +167,28 @@ static int koneplus_set_profile_buttons(struct usb_device *usb_dev, } /* retval is 0-4 on success, < 0 on error */ -static int koneplus_get_startup_profile(struct usb_device *usb_dev) +static int koneplus_get_actual_profile(struct usb_device *usb_dev) { - struct koneplus_startup_profile buf; + struct koneplus_actual_profile buf; int retval; - retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE, - &buf, sizeof(struct koneplus_startup_profile)); + retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_ACTUAL_PROFILE, + &buf, sizeof(struct koneplus_actual_profile)); - return retval ? retval : buf.startup_profile; + return retval ? retval : buf.actual_profile; } -static int koneplus_set_startup_profile(struct usb_device *usb_dev, - int startup_profile) +static int koneplus_set_actual_profile(struct usb_device *usb_dev, + int new_profile) { - struct koneplus_startup_profile buf; + struct koneplus_actual_profile buf; - buf.command = KONEPLUS_COMMAND_STARTUP_PROFILE; - buf.size = sizeof(struct koneplus_startup_profile); - buf.startup_profile = startup_profile; + buf.command = KONEPLUS_COMMAND_ACTUAL_PROFILE; + buf.size = sizeof(struct koneplus_actual_profile); + buf.actual_profile = new_profile; - return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE, - &buf, sizeof(struct koneplus_profile_buttons)); + return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_ACTUAL_PROFILE, + &buf, sizeof(struct koneplus_actual_profile)); } static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj, @@ -398,21 +398,22 @@ static ssize_t koneplus_sysfs_write_profile_buttons(struct file *fp, return sizeof(struct koneplus_profile_buttons); } -static ssize_t koneplus_sysfs_show_startup_profile(struct device *dev, +static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev, struct device_attribute *attr, char *buf) { struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->startup_profile); + return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->actual_profile); } -static ssize_t koneplus_sysfs_set_startup_profile(struct device *dev, +static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev, struct device_attribute *attr, char const *buf, size_t size) { struct koneplus_device *koneplus; struct usb_device *usb_dev; unsigned long profile; int retval; + struct koneplus_roccat_report roccat_report; dev = dev->parent->parent; koneplus = hid_get_drvdata(dev_get_drvdata(dev)); @@ -423,20 +424,25 @@ static ssize_t koneplus_sysfs_set_startup_profile(struct device *dev, return retval; mutex_lock(&koneplus->koneplus_lock); - retval = koneplus_set_startup_profile(usb_dev, profile); - mutex_unlock(&koneplus->koneplus_lock); - if (retval) + + retval = koneplus_set_actual_profile(usb_dev, profile); + if (retval) { + mutex_unlock(&koneplus->koneplus_lock); return retval; + } - return size; -} + koneplus->actual_profile = profile; -static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct koneplus_device *koneplus = - hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); - return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->actual_profile); + roccat_report.type = KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE; + roccat_report.data1 = profile + 1; + roccat_report.data2 = 0; + roccat_report.profile = profile + 1; + roccat_report_event(koneplus->chrdev_minor, + (uint8_t const *)&roccat_report); + + mutex_unlock(&koneplus->koneplus_lock); + + return size; } static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev, @@ -448,11 +454,12 @@ static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev, } static struct device_attribute koneplus_attributes[] = { + __ATTR(actual_profile, 0660, + koneplus_sysfs_show_actual_profile, + koneplus_sysfs_set_actual_profile), __ATTR(startup_profile, 0660, - koneplus_sysfs_show_startup_profile, - koneplus_sysfs_set_startup_profile), - __ATTR(actual_profile, 0440, - koneplus_sysfs_show_actual_profile, NULL), + koneplus_sysfs_show_actual_profile, + koneplus_sysfs_set_actual_profile), __ATTR(firmware_version, 0440, koneplus_sysfs_show_firmware_version, NULL), __ATTR_NULL @@ -557,15 +564,10 @@ static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev, struct koneplus_device *koneplus) { int retval, i; - static uint wait = 100; /* device will freeze with just 60 */ + static uint wait = 200; mutex_init(&koneplus->koneplus_lock); - koneplus->startup_profile = koneplus_get_startup_profile(usb_dev); - if (koneplus->startup_profile < 0) - return koneplus->startup_profile; - - msleep(wait); retval = koneplus_get_info(usb_dev, &koneplus->info); if (retval) return retval; @@ -584,7 +586,11 @@ static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev, return retval; } - koneplus_profile_activated(koneplus, koneplus->startup_profile); + msleep(wait); + retval = koneplus_get_actual_profile(usb_dev); + if (retval < 0) + return retval; + koneplus_profile_activated(koneplus, retval); return 0; } diff --git a/drivers/hid/hid-roccat-koneplus.h b/drivers/hid/hid-roccat-koneplus.h index 57a5c1ab7b0..c57a376ab8a 100644 --- a/drivers/hid/hid-roccat-koneplus.h +++ b/drivers/hid/hid-roccat-koneplus.h @@ -40,10 +40,10 @@ enum koneplus_control_values { KONEPLUS_CONTROL_REQUEST_STATUS_WAIT = 3, }; -struct koneplus_startup_profile { - uint8_t command; /* KONEPLUS_COMMAND_STARTUP_PROFILE */ +struct koneplus_actual_profile { + uint8_t command; /* KONEPLUS_COMMAND_ACTUAL_PROFILE */ uint8_t size; /* always 3 */ - uint8_t startup_profile; /* Range 0-4! */ + uint8_t actual_profile; /* Range 0-4! */ } __attribute__ ((__packed__)); struct koneplus_profile_settings { @@ -132,7 +132,7 @@ struct koneplus_tcu_image { enum koneplus_commands { KONEPLUS_COMMAND_CONTROL = 0x4, - KONEPLUS_COMMAND_STARTUP_PROFILE = 0x5, + KONEPLUS_COMMAND_ACTUAL_PROFILE = 0x5, KONEPLUS_COMMAND_PROFILE_SETTINGS = 0x6, KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7, KONEPLUS_COMMAND_MACRO = 0x8, @@ -145,7 +145,7 @@ enum koneplus_commands { enum koneplus_usb_commands { KONEPLUS_USB_COMMAND_CONTROL = 0x304, - KONEPLUS_USB_COMMAND_STARTUP_PROFILE = 0x305, + KONEPLUS_USB_COMMAND_ACTUAL_PROFILE = 0x305, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS = 0x306, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS = 0x307, KONEPLUS_USB_COMMAND_MACRO = 0x308, @@ -215,7 +215,6 @@ struct koneplus_device { struct mutex koneplus_lock; - int startup_profile; struct koneplus_info info; struct koneplus_profile_settings profile_settings[5]; struct koneplus_profile_buttons profile_buttons[5]; diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c index 160f481344f..38280c055a1 100644 --- a/drivers/hid/hid-roccat-pyra.c +++ b/drivers/hid/hid-roccat-pyra.c @@ -652,7 +652,8 @@ static int pyra_raw_event(struct hid_device *hdev, struct hid_report *report, static const struct hid_device_id pyra_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, - /* TODO add USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS after testing */ + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, + USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) }, { } }; diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 93819a08121..936c911fdca 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -178,6 +178,8 @@ static void sony_remove(struct hid_device *hdev) static const struct hid_device_id sony_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), .driver_data = SIXAXIS_CONTROLLER_USB }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), + .driver_data = SIXAXIS_CONTROLLER_USB }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), .driver_data = SIXAXIS_CONTROLLER_BT }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 54409cba018..c79578b5a78 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -101,8 +101,8 @@ out: return ret; } -/* the first byte is expected to be a report number */ -/* This function is to be called with the minors_lock mutex held */ +/* The first byte is expected to be a report number. + * This function is to be called with the minors_lock mutex held */ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, size_t count, unsigned char report_type) { unsigned int minor = iminor(file->f_path.dentry->d_inode); @@ -166,11 +166,11 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t /* This function performs a Get_Report transfer over the control endpoint - per section 7.2.1 of the HID specification, version 1.1. The first byte - of buffer is the report number to request, or 0x0 if the defice does not - use numbered reports. The report_type parameter can be HID_FEATURE_REPORT - or HID_INPUT_REPORT. This function is to be called with the minors_lock - mutex held. */ + * per section 7.2.1 of the HID specification, version 1.1. The first byte + * of buffer is the report number to request, or 0x0 if the defice does not + * use numbered reports. The report_type parameter can be HID_FEATURE_REPORT + * or HID_INPUT_REPORT. This function is to be called with the minors_lock + * mutex held. */ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t count, unsigned char report_type) { unsigned int minor = iminor(file->f_path.dentry->d_inode); @@ -207,7 +207,7 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t } /* Read the first byte from the user. This is the report number, - which is passed to dev->hid_get_raw_report(). */ + * which is passed to dev->hid_get_raw_report(). */ if (copy_from_user(&report_number, buffer, 1)) { ret = -EFAULT; goto out_free; @@ -395,12 +395,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, } if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) { - int len; - if (!hid->name) { - ret = 0; - break; - } - len = strlen(hid->name) + 1; + int len = strlen(hid->name) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); ret = copy_to_user(user_arg, hid->name, len) ? @@ -409,12 +404,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, } if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) { - int len; - if (!hid->phys) { - ret = 0; - break; - } - len = strlen(hid->phys) + 1; + int len = strlen(hid->phys) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); ret = copy_to_user(user_arg, hid->phys, len) ? diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 9a94b643ccd..0e30b140edc 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -59,6 +59,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET }, { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE, HID_QUIRK_NOGET }, { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_THROTTLE, HID_QUIRK_NOGET }, { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK, HID_QUIRK_NOGET }, { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, @@ -67,6 +68,8 @@ static const struct hid_blacklist { { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index af0a7c1002a..ff3c644888b 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -242,6 +242,7 @@ static int hiddev_release(struct inode * inode, struct file * file) list_del(&list->node); spin_unlock_irqrestore(&list->hiddev->list_lock, flags); + mutex_lock(&list->hiddev->existancelock); if (!--list->hiddev->open) { if (list->hiddev->exist) { usbhid_close(list->hiddev->hid); @@ -252,6 +253,7 @@ static int hiddev_release(struct inode * inode, struct file * file) } kfree(list); + mutex_unlock(&list->hiddev->existancelock); return 0; } @@ -300,17 +302,21 @@ static int hiddev_open(struct inode *inode, struct file *file) list_add_tail(&list->node, &hiddev->list); spin_unlock_irq(&list->hiddev->list_lock); + mutex_lock(&hiddev->existancelock); if (!list->hiddev->open++) if (list->hiddev->exist) { struct hid_device *hid = hiddev->hid; res = usbhid_get_power(hid); if (res < 0) { res = -EIO; - goto bail; + goto bail_unlock; } usbhid_open(hid); } + mutex_unlock(&hiddev->existancelock); return 0; +bail_unlock: + mutex_unlock(&hiddev->existancelock); bail: file->private_data = NULL; kfree(list); @@ -367,8 +373,10 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun /* let O_NONBLOCK tasks run */ mutex_unlock(&list->thread_lock); schedule(); - if (mutex_lock_interruptible(&list->thread_lock)) + if (mutex_lock_interruptible(&list->thread_lock)) { + finish_wait(&list->hiddev->wait, &wait); return -EINTR; + } set_current_state(TASK_INTERRUPTIBLE); } finish_wait(&list->hiddev->wait, &wait); @@ -509,7 +517,7 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd, (uref_multi->num_values > HID_MAX_MULTI_USAGES || uref->usage_index + uref_multi->num_values > field->report_count)) goto inval; - } + } switch (cmd) { case HIDIOCGUSAGE: @@ -801,14 +809,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) { - int len; - - if (!hid->name) { - r = 0; - break; - } - - len = strlen(hid->name) + 1; + int len = strlen(hid->name) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); r = copy_to_user(user_arg, hid->name, len) ? @@ -817,14 +818,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGPHYS(0))) { - int len; - - if (!hid->phys) { - r = 0; - break; - } - - len = strlen(hid->phys) + 1; + int len = strlen(hid->phys) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); r = copy_to_user(user_arg, hid->phys, len) ? @@ -925,7 +919,6 @@ void hiddev_disconnect(struct hid_device *hid) mutex_lock(&hiddev->existancelock); hiddev->exist = 0; - mutex_unlock(&hiddev->existancelock); usb_deregister_dev(usbhid->intf, &hiddev_class); @@ -935,4 +928,5 @@ void hiddev_disconnect(struct hid_device *hid) } else { kfree(hiddev); } + mutex_unlock(&hiddev->existancelock); } |