Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (24 commits) HID: ADS/Tech Radio si470x needs blacklist entry HID: Logitech Extreme 3D needs NOGET quirk HID: Refactor MS Presenter 8K key mapping HID: MS Presenter mapping for PID 0x0701 HID: Support Samsung IR remote HID: fix compilation of hidbp drivers without usbhid HID: Blacklist the Gretag-Macbeth Huey display colorimeter HID: the `bit' in hidinput_mapping_quirks() is an out parameter HID: remove redundant WARN_ON()s in order not to scare users HID: force hiddev creation for SONY PS3 controller HID: Use hid blacklist in usbmouse/usbkbd HID: proper handling of MS 4k and 6k devices HID: remove unused variable in quirk event handler HID: hid-input quirk for BTC 8193 HID: separate hid-input event quirks from generic code HID: refactor mapping to input subsystem for quirky devices HID: Microsoft Wireless Optical Desktop 3.0 quirk HID: Add support for Logitech Elite keyboards HID: add full support for Genius KB-29E HID: fix a potential bug in pointer casting ...
This commit is contained in:
commit
f4798748de
10 changed files with 651 additions and 245 deletions
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
# Makefile for the HID driver
|
||||
#
|
||||
hid-objs := hid-core.o hid-input.o
|
||||
hid-objs := hid-core.o hid-input.o hid-input-quirks.o
|
||||
|
||||
obj-$(CONFIG_HID) += hid.o
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/input.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <linux/hid.h>
|
||||
#include <linux/hiddev.h>
|
||||
|
@ -758,7 +759,9 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
|
|||
{
|
||||
u64 x;
|
||||
|
||||
WARN_ON(n > 32);
|
||||
if (n > 32)
|
||||
printk(KERN_WARNING "HID: extract() called with n (%d) > 32! (%s)\n",
|
||||
n, current->comm);
|
||||
|
||||
report += offset >> 3; /* adjust byte index */
|
||||
offset &= 7; /* now only need bit offset into one byte */
|
||||
|
@ -780,8 +783,13 @@ static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u3
|
|||
__le64 x;
|
||||
u64 m = (1ULL << n) - 1;
|
||||
|
||||
WARN_ON(n > 32);
|
||||
if (n > 32)
|
||||
printk(KERN_WARNING "HID: implement() called with n (%d) > 32! (%s)\n",
|
||||
n, current->comm);
|
||||
|
||||
if (value > m)
|
||||
printk(KERN_WARNING "HID: implement() called with too large value %d! (%s)\n",
|
||||
value, current->comm);
|
||||
WARN_ON(value > m);
|
||||
value &= m;
|
||||
|
||||
|
|
423
drivers/hid/hid-input-quirks.c
Normal file
423
drivers/hid/hid-input-quirks.c
Normal file
|
@ -0,0 +1,423 @@
|
|||
/*
|
||||
* HID-input usage mapping quirks
|
||||
*
|
||||
* This is used to handle HID-input mappings for devices violating
|
||||
* HUT 1.12 specification.
|
||||
*
|
||||
* Copyright (c) 2007-2008 Jiri Kosina
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License
|
||||
*/
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/hid.h>
|
||||
|
||||
#define map_abs(c) do { usage->code = c; usage->type = EV_ABS; *bit = input->absbit; *max = ABS_MAX; } while (0)
|
||||
#define map_rel(c) do { usage->code = c; usage->type = EV_REL; *bit = input->relbit; *max = REL_MAX; } while (0)
|
||||
#define map_key(c) do { usage->code = c; usage->type = EV_KEY; *bit = input->keybit; *max = KEY_MAX; } while (0)
|
||||
#define map_led(c) do { usage->code = c; usage->type = EV_LED; *bit = input->ledbit; *max = LED_MAX; } while (0)
|
||||
|
||||
#define map_abs_clear(c) do { map_abs(c); clear_bit(c, *bit); } while (0)
|
||||
#define map_key_clear(c) do { map_key(c); clear_bit(c, *bit); } while (0)
|
||||
|
||||
static int quirk_belkin_wkbd(struct hid_usage *usage, struct input_dev *input,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
|
||||
return 0;
|
||||
|
||||
switch (usage->hid & HID_USAGE) {
|
||||
case 0x03a: map_key_clear(KEY_SOUND); break;
|
||||
case 0x03b: map_key_clear(KEY_CAMERA); break;
|
||||
case 0x03c: map_key_clear(KEY_DOCUMENTS); break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int quirk_cherry_cymotion(struct hid_usage *usage, struct input_dev *input,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
|
||||
return 0;
|
||||
|
||||
switch (usage->hid & HID_USAGE) {
|
||||
case 0x301: map_key_clear(KEY_PROG1); break;
|
||||
case 0x302: map_key_clear(KEY_PROG2); break;
|
||||
case 0x303: map_key_clear(KEY_PROG3); break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int quirk_logitech_ultrax_remote(struct hid_usage *usage, struct input_dev *input,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
|
||||
return 0;
|
||||
|
||||
set_bit(EV_REP, input->evbit);
|
||||
switch(usage->hid & HID_USAGE) {
|
||||
/* Reported on Logitech Ultra X Media Remote */
|
||||
case 0x004: map_key_clear(KEY_AGAIN); break;
|
||||
case 0x00d: map_key_clear(KEY_HOME); break;
|
||||
case 0x024: map_key_clear(KEY_SHUFFLE); break;
|
||||
case 0x025: map_key_clear(KEY_TV); break;
|
||||
case 0x026: map_key_clear(KEY_MENU); break;
|
||||
case 0x031: map_key_clear(KEY_AUDIO); break;
|
||||
case 0x032: map_key_clear(KEY_TEXT); break;
|
||||
case 0x033: map_key_clear(KEY_LAST); break;
|
||||
case 0x047: map_key_clear(KEY_MP3); break;
|
||||
case 0x048: map_key_clear(KEY_DVD); break;
|
||||
case 0x049: map_key_clear(KEY_MEDIA); break;
|
||||
case 0x04a: map_key_clear(KEY_VIDEO); break;
|
||||
case 0x04b: map_key_clear(KEY_ANGLE); break;
|
||||
case 0x04c: map_key_clear(KEY_LANGUAGE); break;
|
||||
case 0x04d: map_key_clear(KEY_SUBTITLE); break;
|
||||
case 0x051: map_key_clear(KEY_RED); break;
|
||||
case 0x052: map_key_clear(KEY_CLOSE); break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int quirk_chicony_tactical_pad(struct hid_usage *usage, struct input_dev *input,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
|
||||
return 0;
|
||||
|
||||
set_bit(EV_REP, input->evbit);
|
||||
switch (usage->hid & HID_USAGE) {
|
||||
case 0xff01: map_key_clear(BTN_1); break;
|
||||
case 0xff02: map_key_clear(BTN_2); break;
|
||||
case 0xff03: map_key_clear(BTN_3); break;
|
||||
case 0xff04: map_key_clear(BTN_4); break;
|
||||
case 0xff05: map_key_clear(BTN_5); break;
|
||||
case 0xff06: map_key_clear(BTN_6); break;
|
||||
case 0xff07: map_key_clear(BTN_7); break;
|
||||
case 0xff08: map_key_clear(BTN_8); break;
|
||||
case 0xff09: map_key_clear(BTN_9); break;
|
||||
case 0xff0a: map_key_clear(BTN_A); break;
|
||||
case 0xff0b: map_key_clear(BTN_B); break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int quirk_microsoft_ergonomy_kb(struct hid_usage *usage, struct input_dev *input,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
|
||||
return 0;
|
||||
|
||||
switch(usage->hid & HID_USAGE) {
|
||||
case 0xfd06: map_key_clear(KEY_CHAT); break;
|
||||
case 0xfd07: map_key_clear(KEY_PHONE); break;
|
||||
case 0xff05:
|
||||
set_bit(EV_REP, input->evbit);
|
||||
map_key_clear(KEY_F13);
|
||||
set_bit(KEY_F14, input->keybit);
|
||||
set_bit(KEY_F15, input->keybit);
|
||||
set_bit(KEY_F16, input->keybit);
|
||||
set_bit(KEY_F17, input->keybit);
|
||||
set_bit(KEY_F18, input->keybit);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int quirk_microsoft_presenter_8k(struct hid_usage *usage, struct input_dev *input,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
|
||||
return 0;
|
||||
|
||||
set_bit(EV_REP, input->evbit);
|
||||
switch(usage->hid & HID_USAGE) {
|
||||
case 0xfd08: map_key_clear(KEY_FORWARD); break;
|
||||
case 0xfd09: map_key_clear(KEY_BACK); break;
|
||||
case 0xfd0b: map_key_clear(KEY_PLAYPAUSE); break;
|
||||
case 0xfd0e: map_key_clear(KEY_CLOSE); break;
|
||||
case 0xfd0f: map_key_clear(KEY_PLAY); break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int quirk_petalynx_remote(struct hid_usage *usage, struct input_dev *input,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if (((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) &&
|
||||
((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER))
|
||||
return 0;
|
||||
|
||||
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_LOGIVENDOR)
|
||||
switch(usage->hid & HID_USAGE) {
|
||||
case 0x05a: map_key_clear(KEY_TEXT); break;
|
||||
case 0x05b: map_key_clear(KEY_RED); break;
|
||||
case 0x05c: map_key_clear(KEY_GREEN); break;
|
||||
case 0x05d: map_key_clear(KEY_YELLOW); break;
|
||||
case 0x05e: map_key_clear(KEY_BLUE); break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER)
|
||||
switch(usage->hid & HID_USAGE) {
|
||||
case 0x0f6: map_key_clear(KEY_NEXT); break;
|
||||
case 0x0fa: map_key_clear(KEY_BACK); break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int quirk_logitech_wireless(struct hid_usage *usage, struct input_dev *input,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
|
||||
return 0;
|
||||
|
||||
switch (usage->hid & HID_USAGE) {
|
||||
case 0x1001: map_key_clear(KEY_MESSENGER); break;
|
||||
case 0x1003: map_key_clear(KEY_SOUND); break;
|
||||
case 0x1004: map_key_clear(KEY_VIDEO); break;
|
||||
case 0x1005: map_key_clear(KEY_AUDIO); break;
|
||||
case 0x100a: map_key_clear(KEY_DOCUMENTS); break;
|
||||
case 0x1011: map_key_clear(KEY_PREVIOUSSONG); break;
|
||||
case 0x1012: map_key_clear(KEY_NEXTSONG); break;
|
||||
case 0x1013: map_key_clear(KEY_CAMERA); break;
|
||||
case 0x1014: map_key_clear(KEY_MESSENGER); break;
|
||||
case 0x1015: map_key_clear(KEY_RECORD); break;
|
||||
case 0x1016: map_key_clear(KEY_PLAYER); break;
|
||||
case 0x1017: map_key_clear(KEY_EJECTCD); break;
|
||||
case 0x1018: map_key_clear(KEY_MEDIA); break;
|
||||
case 0x1019: map_key_clear(KEY_PROG1); break;
|
||||
case 0x101a: map_key_clear(KEY_PROG2); break;
|
||||
case 0x101b: map_key_clear(KEY_PROG3); break;
|
||||
case 0x101f: map_key_clear(KEY_ZOOMIN); break;
|
||||
case 0x1020: map_key_clear(KEY_ZOOMOUT); break;
|
||||
case 0x1021: map_key_clear(KEY_ZOOMRESET); break;
|
||||
case 0x1023: map_key_clear(KEY_CLOSE); break;
|
||||
case 0x1027: map_key_clear(KEY_MENU); break;
|
||||
/* this one is marked as 'Rotate' */
|
||||
case 0x1028: map_key_clear(KEY_ANGLE); break;
|
||||
case 0x1029: map_key_clear(KEY_SHUFFLE); break;
|
||||
case 0x102a: map_key_clear(KEY_BACK); break;
|
||||
case 0x102b: map_key_clear(KEY_CYCLEWINDOWS); break;
|
||||
case 0x1041: map_key_clear(KEY_BATTERY); break;
|
||||
case 0x1042: map_key_clear(KEY_WORDPROCESSOR); break;
|
||||
case 0x1043: map_key_clear(KEY_SPREADSHEET); break;
|
||||
case 0x1044: map_key_clear(KEY_PRESENTATION); break;
|
||||
case 0x1045: map_key_clear(KEY_UNDO); break;
|
||||
case 0x1046: map_key_clear(KEY_REDO); break;
|
||||
case 0x1047: map_key_clear(KEY_PRINT); break;
|
||||
case 0x1048: map_key_clear(KEY_SAVE); break;
|
||||
case 0x1049: map_key_clear(KEY_PROG1); break;
|
||||
case 0x104a: map_key_clear(KEY_PROG2); break;
|
||||
case 0x104b: map_key_clear(KEY_PROG3); break;
|
||||
case 0x104c: map_key_clear(KEY_PROG4); break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int quirk_cherry_genius_29e(struct hid_usage *usage, struct input_dev *input,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
|
||||
return 0;
|
||||
|
||||
switch (usage->hid & HID_USAGE) {
|
||||
case 0x156: map_key_clear(KEY_WORDPROCESSOR); break;
|
||||
case 0x157: map_key_clear(KEY_SPREADSHEET); break;
|
||||
case 0x158: map_key_clear(KEY_PRESENTATION); break;
|
||||
case 0x15c: map_key_clear(KEY_STOP); break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
|
||||
return 0;
|
||||
|
||||
switch (usage->hid & HID_USAGE) {
|
||||
case 0x230: map_key(BTN_MOUSE); break;
|
||||
case 0x231: map_rel(REL_WHEEL); break;
|
||||
/*
|
||||
* this keyboard has a scrollwheel implemented in
|
||||
* totally broken way. We map this usage temporarily
|
||||
* to HWHEEL and handle it in the event quirk handler
|
||||
*/
|
||||
case 0x232: map_rel(REL_HWHEEL); break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define VENDOR_ID_BELKIN 0x1020
|
||||
#define DEVICE_ID_BELKIN_WIRELESS_KEYBOARD 0x0006
|
||||
|
||||
#define VENDOR_ID_CHERRY 0x046a
|
||||
#define DEVICE_ID_CHERRY_CYMOTION 0x0023
|
||||
|
||||
#define VENDOR_ID_CHICONY 0x04f2
|
||||
#define DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418
|
||||
|
||||
#define VENDOR_ID_EZKEY 0x0518
|
||||
#define DEVICE_ID_BTC_8193 0x0002
|
||||
|
||||
#define VENDOR_ID_LOGITECH 0x046d
|
||||
#define DEVICE_ID_LOGITECH_RECEIVER 0xc101
|
||||
#define DEVICE_ID_S510_RECEIVER 0xc50c
|
||||
#define DEVICE_ID_S510_RECEIVER_2 0xc517
|
||||
#define DEVICE_ID_MX3000_RECEIVER 0xc513
|
||||
|
||||
#define VENDOR_ID_MICROSOFT 0x045e
|
||||
#define DEVICE_ID_MS4K 0x00db
|
||||
#define DEVICE_ID_MS6K 0x00f9
|
||||
#define DEVICE_IS_MS_PRESENTER_8K_BT 0x0701
|
||||
#define DEVICE_ID_MS_PRESENTER_8K_USB 0x0713
|
||||
|
||||
#define VENDOR_ID_MONTEREY 0x0566
|
||||
#define DEVICE_ID_GENIUS_KB29E 0x3004
|
||||
|
||||
#define VENDOR_ID_PETALYNX 0x18b1
|
||||
#define DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
|
||||
|
||||
static const struct hid_input_blacklist {
|
||||
__u16 idVendor;
|
||||
__u16 idProduct;
|
||||
int (*quirk)(struct hid_usage *, struct input_dev *, unsigned long **, int *);
|
||||
} hid_input_blacklist[] = {
|
||||
{ VENDOR_ID_BELKIN, DEVICE_ID_BELKIN_WIRELESS_KEYBOARD, quirk_belkin_wkbd },
|
||||
|
||||
{ VENDOR_ID_CHERRY, DEVICE_ID_CHERRY_CYMOTION, quirk_cherry_cymotion },
|
||||
|
||||
{ VENDOR_ID_CHICONY, DEVICE_ID_CHICONY_TACTICAL_PAD, quirk_chicony_tactical_pad },
|
||||
|
||||
{ VENDOR_ID_EZKEY, DEVICE_ID_BTC_8193, quirk_btc_8193 },
|
||||
|
||||
{ VENDOR_ID_LOGITECH, DEVICE_ID_LOGITECH_RECEIVER, quirk_logitech_ultrax_remote },
|
||||
{ VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER, quirk_logitech_wireless },
|
||||
{ VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER_2, quirk_logitech_wireless },
|
||||
{ VENDOR_ID_LOGITECH, DEVICE_ID_MX3000_RECEIVER, quirk_logitech_wireless },
|
||||
|
||||
{ VENDOR_ID_MICROSOFT, DEVICE_ID_MS4K, quirk_microsoft_ergonomy_kb },
|
||||
{ VENDOR_ID_MICROSOFT, DEVICE_ID_MS6K, quirk_microsoft_ergonomy_kb },
|
||||
{ VENDOR_ID_MICROSOFT, DEVICE_IS_MS_PRESENTER_8K_BT, quirk_microsoft_presenter_8k },
|
||||
{ VENDOR_ID_MICROSOFT, DEVICE_ID_MS_PRESENTER_8K_USB, quirk_microsoft_presenter_8k },
|
||||
|
||||
{ VENDOR_ID_MONTEREY, DEVICE_ID_GENIUS_KB29E, quirk_cherry_genius_29e },
|
||||
|
||||
{ VENDOR_ID_PETALYNX, DEVICE_ID_PETALYNX_MAXTER_REMOTE, quirk_petalynx_remote },
|
||||
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
int hidinput_mapping_quirks(struct hid_usage *usage,
|
||||
struct input_dev *input,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
struct hid_device *device = input_get_drvdata(input);
|
||||
int i = 0;
|
||||
|
||||
while (hid_input_blacklist[i].quirk) {
|
||||
if (hid_input_blacklist[i].idVendor == device->vendor &&
|
||||
hid_input_blacklist[i].idProduct == device->product)
|
||||
return hid_input_blacklist[i].quirk(usage, input, bit, max);
|
||||
i++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
|
||||
{
|
||||
struct input_dev *input;
|
||||
|
||||
input = field->hidinput->input;
|
||||
|
||||
if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005))
|
||||
|| ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) {
|
||||
if (value) hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
|
||||
else hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) &&
|
||||
(usage->type == EV_REL) &&
|
||||
(usage->code == REL_WHEEL)) {
|
||||
hid->delayed_value = value;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) &&
|
||||
(usage->hid == 0x000100b8)) {
|
||||
input_event(input, EV_REL, value ? REL_HWHEEL : REL_WHEEL, hid->delayed_value);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) {
|
||||
input_event(input, usage->type, usage->code, -value);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) {
|
||||
input_event(input, usage->type, REL_HWHEEL, value);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((hid->quirks & HID_QUIRK_APPLE_HAS_FN) && hidinput_apple_event(hid, input, usage, value))
|
||||
return;
|
||||
|
||||
/* Handling MS keyboards special buttons */
|
||||
if (hid->quirks & HID_QUIRK_MICROSOFT_KEYS &&
|
||||
usage->hid == (HID_UP_MSVENDOR | 0xff05)) {
|
||||
int key = 0;
|
||||
static int last_key = 0;
|
||||
switch (value) {
|
||||
case 0x01: key = KEY_F14; break;
|
||||
case 0x02: key = KEY_F15; break;
|
||||
case 0x04: key = KEY_F16; break;
|
||||
case 0x08: key = KEY_F17; break;
|
||||
case 0x10: key = KEY_F18; break;
|
||||
default: break;
|
||||
}
|
||||
if (key) {
|
||||
input_event(input, usage->type, key, 1);
|
||||
last_key = key;
|
||||
} else {
|
||||
input_event(input, usage->type, last_key, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* handle the temporary quirky mapping to HWHEEL */
|
||||
if (hid->quirks & HID_QUIRK_HWHEEL_WHEEL_INVERT &&
|
||||
usage->type == EV_REL && usage->code == REL_HWHEEL) {
|
||||
input_event(input, usage->type, REL_WHEEL, -value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -34,10 +34,10 @@
|
|||
#include <linux/hid.h>
|
||||
#include <linux/hid-debug.h>
|
||||
|
||||
static int hid_pb_fnmode = 1;
|
||||
module_param_named(pb_fnmode, hid_pb_fnmode, int, 0644);
|
||||
static int hid_apple_fnmode = 1;
|
||||
module_param_named(pb_fnmode, hid_apple_fnmode, int, 0644);
|
||||
MODULE_PARM_DESC(pb_fnmode,
|
||||
"Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
|
||||
"Mode of fn key on Apple keyboards (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
|
||||
|
||||
#define unk KEY_UNKNOWN
|
||||
|
||||
|
@ -86,10 +86,6 @@ static const struct {
|
|||
#define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0)
|
||||
#define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0)
|
||||
|
||||
/* hardware needing special handling due to colliding MSVENDOR page usages */
|
||||
#define IS_CHICONY_TACTICAL_PAD(x) (x->vendor == 0x04f2 && device->product == 0x0418)
|
||||
#define IS_MS_KB(x) (x->vendor == 0x045e && (x->product == 0x00db || x->product == 0x00f9))
|
||||
|
||||
#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
|
||||
|
||||
struct hidinput_key_translation {
|
||||
|
@ -98,20 +94,36 @@ struct hidinput_key_translation {
|
|||
u8 flags;
|
||||
};
|
||||
|
||||
#define POWERBOOK_FLAG_FKEY 0x01
|
||||
#define APPLE_FLAG_FKEY 0x01
|
||||
|
||||
static struct hidinput_key_translation apple_fn_keys[] = {
|
||||
{ KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
|
||||
{ KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
|
||||
{ KEY_F3, KEY_CYCLEWINDOWS, APPLE_FLAG_FKEY }, /* Exposé */
|
||||
{ KEY_F4, KEY_FN_F4, APPLE_FLAG_FKEY }, /* Dashboard */
|
||||
{ KEY_F5, KEY_FN_F5 },
|
||||
{ KEY_F6, KEY_FN_F6 },
|
||||
{ KEY_F7, KEY_BACK, APPLE_FLAG_FKEY },
|
||||
{ KEY_F8, KEY_PLAYPAUSE, APPLE_FLAG_FKEY },
|
||||
{ KEY_F9, KEY_FORWARD, APPLE_FLAG_FKEY },
|
||||
{ KEY_F10, KEY_MUTE, APPLE_FLAG_FKEY },
|
||||
{ KEY_F11, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY },
|
||||
{ KEY_F12, KEY_VOLUMEUP, APPLE_FLAG_FKEY },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct hidinput_key_translation powerbook_fn_keys[] = {
|
||||
{ KEY_BACKSPACE, KEY_DELETE },
|
||||
{ KEY_F1, KEY_BRIGHTNESSDOWN, POWERBOOK_FLAG_FKEY },
|
||||
{ KEY_F2, KEY_BRIGHTNESSUP, POWERBOOK_FLAG_FKEY },
|
||||
{ KEY_F3, KEY_MUTE, POWERBOOK_FLAG_FKEY },
|
||||
{ KEY_F4, KEY_VOLUMEDOWN, POWERBOOK_FLAG_FKEY },
|
||||
{ KEY_F5, KEY_VOLUMEUP, POWERBOOK_FLAG_FKEY },
|
||||
{ KEY_F6, KEY_NUMLOCK, POWERBOOK_FLAG_FKEY },
|
||||
{ KEY_F7, KEY_SWITCHVIDEOMODE, POWERBOOK_FLAG_FKEY },
|
||||
{ KEY_F8, KEY_KBDILLUMTOGGLE, POWERBOOK_FLAG_FKEY },
|
||||
{ KEY_F9, KEY_KBDILLUMDOWN, POWERBOOK_FLAG_FKEY },
|
||||
{ KEY_F10, KEY_KBDILLUMUP, POWERBOOK_FLAG_FKEY },
|
||||
{ KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
|
||||
{ KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
|
||||
{ KEY_F3, KEY_MUTE, APPLE_FLAG_FKEY },
|
||||
{ KEY_F4, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY },
|
||||
{ KEY_F5, KEY_VOLUMEUP, APPLE_FLAG_FKEY },
|
||||
{ KEY_F6, KEY_NUMLOCK, APPLE_FLAG_FKEY },
|
||||
{ KEY_F7, KEY_SWITCHVIDEOMODE, APPLE_FLAG_FKEY },
|
||||
{ KEY_F8, KEY_KBDILLUMTOGGLE, APPLE_FLAG_FKEY },
|
||||
{ KEY_F9, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY },
|
||||
{ KEY_F10, KEY_KBDILLUMUP, APPLE_FLAG_FKEY },
|
||||
{ KEY_UP, KEY_PAGEUP },
|
||||
{ KEY_DOWN, KEY_PAGEDOWN },
|
||||
{ KEY_LEFT, KEY_HOME },
|
||||
|
@ -142,7 +154,7 @@ static struct hidinput_key_translation powerbook_numlock_keys[] = {
|
|||
{ }
|
||||
};
|
||||
|
||||
static struct hidinput_key_translation powerbook_iso_keyboard[] = {
|
||||
static struct hidinput_key_translation apple_iso_keyboard[] = {
|
||||
{ KEY_GRAVE, KEY_102ND },
|
||||
{ KEY_102ND, KEY_GRAVE },
|
||||
{ }
|
||||
|
@ -160,39 +172,42 @@ static struct hidinput_key_translation *find_translation(struct hidinput_key_tra
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
|
||||
int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
|
||||
struct hid_usage *usage, __s32 value)
|
||||
{
|
||||
struct hidinput_key_translation *trans;
|
||||
|
||||
if (usage->code == KEY_FN) {
|
||||
if (value) hid->quirks |= HID_QUIRK_POWERBOOK_FN_ON;
|
||||
else hid->quirks &= ~HID_QUIRK_POWERBOOK_FN_ON;
|
||||
if (value) hid->quirks |= HID_QUIRK_APPLE_FN_ON;
|
||||
else hid->quirks &= ~HID_QUIRK_APPLE_FN_ON;
|
||||
|
||||
input_event(input, usage->type, usage->code, value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (hid_pb_fnmode) {
|
||||
if (hid_apple_fnmode) {
|
||||
int do_translate;
|
||||
|
||||
trans = find_translation(powerbook_fn_keys, usage->code);
|
||||
trans = find_translation((hid->product < 0x220 ||
|
||||
hid->product >= 0x300) ?
|
||||
powerbook_fn_keys : apple_fn_keys,
|
||||
usage->code);
|
||||
if (trans) {
|
||||
if (test_bit(usage->code, hid->pb_pressed_fn))
|
||||
if (test_bit(usage->code, hid->apple_pressed_fn))
|
||||
do_translate = 1;
|
||||
else if (trans->flags & POWERBOOK_FLAG_FKEY)
|
||||
else if (trans->flags & APPLE_FLAG_FKEY)
|
||||
do_translate =
|
||||
(hid_pb_fnmode == 2 && (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) ||
|
||||
(hid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON));
|
||||
(hid_apple_fnmode == 2 && (hid->quirks & HID_QUIRK_APPLE_FN_ON)) ||
|
||||
(hid_apple_fnmode == 1 && !(hid->quirks & HID_QUIRK_APPLE_FN_ON));
|
||||
else
|
||||
do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON);
|
||||
do_translate = (hid->quirks & HID_QUIRK_APPLE_FN_ON);
|
||||
|
||||
if (do_translate) {
|
||||
if (value)
|
||||
set_bit(usage->code, hid->pb_pressed_fn);
|
||||
set_bit(usage->code, hid->apple_pressed_fn);
|
||||
else
|
||||
clear_bit(usage->code, hid->pb_pressed_fn);
|
||||
clear_bit(usage->code, hid->apple_pressed_fn);
|
||||
|
||||
input_event(input, usage->type, trans->to, value);
|
||||
|
||||
|
@ -217,8 +232,8 @@ static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
|
|||
}
|
||||
}
|
||||
|
||||
if (hid->quirks & HID_QUIRK_POWERBOOK_ISO_KEYBOARD) {
|
||||
trans = find_translation(powerbook_iso_keyboard, usage->code);
|
||||
if (hid->quirks & HID_QUIRK_APPLE_ISO_KEYBOARD) {
|
||||
trans = find_translation(apple_iso_keyboard, usage->code);
|
||||
if (trans) {
|
||||
input_event(input, usage->type, trans->to, value);
|
||||
return 1;
|
||||
|
@ -228,31 +243,35 @@ static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void hidinput_pb_setup(struct input_dev *input)
|
||||
static void hidinput_apple_setup(struct input_dev *input)
|
||||
{
|
||||
struct hidinput_key_translation *trans;
|
||||
|
||||
set_bit(KEY_NUMLOCK, input->keybit);
|
||||
|
||||
/* Enable all needed keys */
|
||||
for (trans = apple_fn_keys; trans->from; trans++)
|
||||
set_bit(trans->to, input->keybit);
|
||||
|
||||
for (trans = powerbook_fn_keys; trans->from; trans++)
|
||||
set_bit(trans->to, input->keybit);
|
||||
|
||||
for (trans = powerbook_numlock_keys; trans->from; trans++)
|
||||
set_bit(trans->to, input->keybit);
|
||||
|
||||
for (trans = powerbook_iso_keyboard; trans->from; trans++)
|
||||
for (trans = apple_iso_keyboard; trans->from; trans++)
|
||||
set_bit(trans->to, input->keybit);
|
||||
|
||||
}
|
||||
#else
|
||||
static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
|
||||
struct hid_usage *usage, __s32 value)
|
||||
inline int hidinput_apple_event(struct hid_device *hid,
|
||||
struct input_dev *input,
|
||||
struct hid_usage *usage, __s32 value)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void hidinput_pb_setup(struct input_dev *input)
|
||||
static inline void hidinput_apple_setup(struct input_dev *input)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
@ -343,7 +362,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||
{
|
||||
struct input_dev *input = hidinput->input;
|
||||
struct hid_device *device = input_get_drvdata(input);
|
||||
int max = 0, code;
|
||||
int max = 0, code, ret;
|
||||
unsigned long *bit = NULL;
|
||||
|
||||
field->hidinput = hidinput;
|
||||
|
@ -362,6 +381,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||
goto ignore;
|
||||
}
|
||||
|
||||
/* handle input mappings for quirky devices */
|
||||
ret = hidinput_mapping_quirks(usage, input, &bit, &max);
|
||||
if (ret)
|
||||
goto mapped;
|
||||
|
||||
switch (usage->hid & HID_USAGE_PAGE) {
|
||||
|
||||
case HID_UP_UNDEFINED:
|
||||
|
@ -549,14 +573,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||
case 0x000: goto ignore;
|
||||
case 0x034: map_key_clear(KEY_SLEEP); break;
|
||||
case 0x036: map_key_clear(BTN_MISC); break;
|
||||
/*
|
||||
* The next three are reported by Belkin wireless
|
||||
* keyboard (1020:0006). These values are "reserved"
|
||||
* in HUT 1.12.
|
||||
*/
|
||||
case 0x03a: map_key_clear(KEY_SOUND); break;
|
||||
case 0x03b: map_key_clear(KEY_CAMERA); break;
|
||||
case 0x03c: map_key_clear(KEY_DOCUMENTS); break;
|
||||
|
||||
case 0x040: map_key_clear(KEY_MENU); break;
|
||||
case 0x045: map_key_clear(KEY_RADIO); break;
|
||||
|
@ -602,10 +618,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||
case 0x0e9: map_key_clear(KEY_VOLUMEUP); break;
|
||||
case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break;
|
||||
|
||||
/* reserved in HUT 1.12. Reported on Petalynx remote */
|
||||
case 0x0f6: map_key_clear(KEY_NEXT); break;
|
||||
case 0x0fa: map_key_clear(KEY_BACK); break;
|
||||
|
||||
case 0x182: map_key_clear(KEY_BOOKMARKS); break;
|
||||
case 0x183: map_key_clear(KEY_CONFIG); break;
|
||||
case 0x184: map_key_clear(KEY_WORDPROCESSOR); break;
|
||||
|
@ -665,51 +677,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||
case 0x28b: map_key_clear(KEY_FORWARDMAIL); break;
|
||||
case 0x28c: map_key_clear(KEY_SEND); break;
|
||||
|
||||
/* Reported on a Cherry Cymotion keyboard */
|
||||
case 0x301: map_key_clear(KEY_PROG1); break;
|
||||
case 0x302: map_key_clear(KEY_PROG2); break;
|
||||
case 0x303: map_key_clear(KEY_PROG3); break;
|
||||
|
||||
/* Reported on certain Logitech wireless keyboards */
|
||||
case 0x1001: map_key_clear(KEY_MESSENGER); break;
|
||||
case 0x1003: map_key_clear(KEY_SOUND); break;
|
||||
case 0x1004: map_key_clear(KEY_VIDEO); break;
|
||||
case 0x1005: map_key_clear(KEY_AUDIO); break;
|
||||
case 0x100a: map_key_clear(KEY_DOCUMENTS); break;
|
||||
case 0x1011: map_key_clear(KEY_PREVIOUSSONG); break;
|
||||
case 0x1012: map_key_clear(KEY_NEXTSONG); break;
|
||||
case 0x1013: map_key_clear(KEY_CAMERA); break;
|
||||
case 0x1014: map_key_clear(KEY_MESSENGER); break;
|
||||
case 0x1015: map_key_clear(KEY_RECORD); break;
|
||||
case 0x1016: map_key_clear(KEY_PLAYER); break;
|
||||
case 0x1017: map_key_clear(KEY_EJECTCD); break;
|
||||
case 0x1018: map_key_clear(KEY_MEDIA); break;
|
||||
case 0x1019: map_key_clear(KEY_PROG1); break;
|
||||
case 0x101a: map_key_clear(KEY_PROG2); break;
|
||||
case 0x101b: map_key_clear(KEY_PROG3); break;
|
||||
case 0x101f: map_key_clear(KEY_ZOOMIN); break;
|
||||
case 0x1020: map_key_clear(KEY_ZOOMOUT); break;
|
||||
case 0x1021: map_key_clear(KEY_ZOOMRESET); break;
|
||||
case 0x1023: map_key_clear(KEY_CLOSE); break;
|
||||
case 0x1027: map_key_clear(KEY_MENU); break;
|
||||
/* this one is marked as 'Rotate' */
|
||||
case 0x1028: map_key_clear(KEY_ANGLE); break;
|
||||
case 0x1029: map_key_clear(KEY_SHUFFLE); break;
|
||||
case 0x102a: map_key_clear(KEY_BACK); break;
|
||||
case 0x102b: map_key_clear(KEY_CYCLEWINDOWS); break;
|
||||
case 0x1041: map_key_clear(KEY_BATTERY); break;
|
||||
case 0x1042: map_key_clear(KEY_WORDPROCESSOR); break;
|
||||
case 0x1043: map_key_clear(KEY_SPREADSHEET); break;
|
||||
case 0x1044: map_key_clear(KEY_PRESENTATION); break;
|
||||
case 0x1045: map_key_clear(KEY_UNDO); break;
|
||||
case 0x1046: map_key_clear(KEY_REDO); break;
|
||||
case 0x1047: map_key_clear(KEY_PRINT); break;
|
||||
case 0x1048: map_key_clear(KEY_SAVE); break;
|
||||
case 0x1049: map_key_clear(KEY_PROG1); break;
|
||||
case 0x104a: map_key_clear(KEY_PROG2); break;
|
||||
case 0x104b: map_key_clear(KEY_PROG3); break;
|
||||
case 0x104c: map_key_clear(KEY_PROG4); break;
|
||||
|
||||
default: goto ignore;
|
||||
}
|
||||
break;
|
||||
|
@ -736,63 +703,16 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||
|
||||
case HID_UP_MSVENDOR:
|
||||
|
||||
/* Unfortunately, there are multiple devices which
|
||||
* emit usages from MSVENDOR page that require different
|
||||
* handling. If this list grows too much in the future,
|
||||
* more general handling will have to be introduced here
|
||||
* (i.e. another blacklist).
|
||||
*/
|
||||
goto ignore;
|
||||
|
||||
/* Chicony Chicony KU-0418 tactical pad */
|
||||
if (IS_CHICONY_TACTICAL_PAD(device)) {
|
||||
set_bit(EV_REP, input->evbit);
|
||||
switch(usage->hid & HID_USAGE) {
|
||||
case 0xff01: map_key_clear(BTN_1); break;
|
||||
case 0xff02: map_key_clear(BTN_2); break;
|
||||
case 0xff03: map_key_clear(BTN_3); break;
|
||||
case 0xff04: map_key_clear(BTN_4); break;
|
||||
case 0xff05: map_key_clear(BTN_5); break;
|
||||
case 0xff06: map_key_clear(BTN_6); break;
|
||||
case 0xff07: map_key_clear(BTN_7); break;
|
||||
case 0xff08: map_key_clear(BTN_8); break;
|
||||
case 0xff09: map_key_clear(BTN_9); break;
|
||||
case 0xff0a: map_key_clear(BTN_A); break;
|
||||
case 0xff0b: map_key_clear(BTN_B); break;
|
||||
default: goto ignore;
|
||||
}
|
||||
|
||||
/* Microsoft Natural Ergonomic Keyboard 4000 */
|
||||
} else if (IS_MS_KB(device)) {
|
||||
switch(usage->hid & HID_USAGE) {
|
||||
case 0xfd06:
|
||||
map_key_clear(KEY_CHAT);
|
||||
break;
|
||||
case 0xfd07:
|
||||
map_key_clear(KEY_PHONE);
|
||||
break;
|
||||
case 0xff05:
|
||||
set_bit(EV_REP, input->evbit);
|
||||
map_key_clear(KEY_F13);
|
||||
set_bit(KEY_F14, input->keybit);
|
||||
set_bit(KEY_F15, input->keybit);
|
||||
set_bit(KEY_F16, input->keybit);
|
||||
set_bit(KEY_F17, input->keybit);
|
||||
set_bit(KEY_F18, input->keybit);
|
||||
default: goto ignore;
|
||||
}
|
||||
} else {
|
||||
goto ignore;
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB keyboards */
|
||||
case HID_UP_CUSTOM: /* Reported on Logitech and Apple USB keyboards */
|
||||
|
||||
set_bit(EV_REP, input->evbit);
|
||||
switch(usage->hid & HID_USAGE) {
|
||||
case 0x003:
|
||||
/* The fn key on Apple PowerBooks */
|
||||
/* The fn key on Apple USB keyboards */
|
||||
map_key_clear(KEY_FN);
|
||||
hidinput_pb_setup(input);
|
||||
hidinput_apple_setup(input);
|
||||
break;
|
||||
|
||||
default: goto ignore;
|
||||
|
@ -800,38 +720,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||
break;
|
||||
|
||||
case HID_UP_LOGIVENDOR:
|
||||
set_bit(EV_REP, input->evbit);
|
||||
switch(usage->hid & HID_USAGE) {
|
||||
/* Reported on Logitech Ultra X Media Remote */
|
||||
case 0x004: map_key_clear(KEY_AGAIN); break;
|
||||
case 0x00d: map_key_clear(KEY_HOME); break;
|
||||
case 0x024: map_key_clear(KEY_SHUFFLE); break;
|
||||
case 0x025: map_key_clear(KEY_TV); break;
|
||||
case 0x026: map_key_clear(KEY_MENU); break;
|
||||
case 0x031: map_key_clear(KEY_AUDIO); break;
|
||||
case 0x032: map_key_clear(KEY_TEXT); break;
|
||||
case 0x033: map_key_clear(KEY_LAST); break;
|
||||
case 0x047: map_key_clear(KEY_MP3); break;
|
||||
case 0x048: map_key_clear(KEY_DVD); break;
|
||||
case 0x049: map_key_clear(KEY_MEDIA); break;
|
||||
case 0x04a: map_key_clear(KEY_VIDEO); break;
|
||||
case 0x04b: map_key_clear(KEY_ANGLE); break;
|
||||
case 0x04c: map_key_clear(KEY_LANGUAGE); break;
|
||||
case 0x04d: map_key_clear(KEY_SUBTITLE); break;
|
||||
case 0x051: map_key_clear(KEY_RED); break;
|
||||
case 0x052: map_key_clear(KEY_CLOSE); break;
|
||||
|
||||
/* Reported on Petalynx Maxter remote */
|
||||
case 0x05a: map_key_clear(KEY_TEXT); break;
|
||||
case 0x05b: map_key_clear(KEY_RED); break;
|
||||
case 0x05c: map_key_clear(KEY_GREEN); break;
|
||||
case 0x05d: map_key_clear(KEY_YELLOW); break;
|
||||
case 0x05e: map_key_clear(KEY_BLUE); break;
|
||||
|
||||
default: goto ignore;
|
||||
}
|
||||
break;
|
||||
|
||||
goto ignore;
|
||||
|
||||
case HID_UP_PID:
|
||||
|
||||
switch(usage->hid & HID_USAGE) {
|
||||
|
@ -858,6 +749,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||
break;
|
||||
}
|
||||
|
||||
mapped:
|
||||
if (device->quirks & HID_QUIRK_MIGHTYMOUSE) {
|
||||
if (usage->hid == HID_GD_Z)
|
||||
map_rel(REL_HWHEEL);
|
||||
|
@ -867,9 +759,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||
map_key(BTN_1);
|
||||
}
|
||||
|
||||
if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) &&
|
||||
(usage->type == EV_REL) && (usage->code == REL_WHEEL))
|
||||
set_bit(REL_HWHEEL, bit);
|
||||
if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5 |
|
||||
HID_QUIRK_2WHEEL_MOUSE_HACK_B8)) && (usage->type == EV_REL) &&
|
||||
(usage->code == REL_WHEEL))
|
||||
set_bit(REL_HWHEEL, bit);
|
||||
|
||||
if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005))
|
||||
|| ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007)))
|
||||
|
@ -960,25 +853,8 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
|
|||
if (!usage->type)
|
||||
return;
|
||||
|
||||
if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005))
|
||||
|| ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) {
|
||||
if (value) hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
|
||||
else hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) {
|
||||
input_event(input, usage->type, usage->code, -value);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) {
|
||||
input_event(input, usage->type, REL_HWHEEL, value);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((hid->quirks & HID_QUIRK_POWERBOOK_HAS_FN) && hidinput_pb_event(hid, input, usage, value))
|
||||
return;
|
||||
/* handle input events for quirky devices */
|
||||
hidinput_event_quirks(hid, field, usage, value);
|
||||
|
||||
if (usage->hat_min < usage->hat_max || usage->hat_dir) {
|
||||
int hat_dir = usage->hat_dir;
|
||||
|
@ -1039,25 +915,6 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
|
|||
return;
|
||||
}
|
||||
|
||||
/* Handling MS keyboards special buttons */
|
||||
if (IS_MS_KB(hid) && usage->hid == (HID_UP_MSVENDOR | 0xff05)) {
|
||||
int key = 0;
|
||||
static int last_key = 0;
|
||||
switch (value) {
|
||||
case 0x01: key = KEY_F14; break;
|
||||
case 0x02: key = KEY_F15; break;
|
||||
case 0x04: key = KEY_F16; break;
|
||||
case 0x08: key = KEY_F17; break;
|
||||
case 0x10: key = KEY_F18; break;
|
||||
default: break;
|
||||
}
|
||||
if (key) {
|
||||
input_event(input, usage->type, key, 1);
|
||||
last_key = key;
|
||||
} else {
|
||||
input_event(input, usage->type, last_key, 0);
|
||||
}
|
||||
}
|
||||
/* report the usage code as scancode if the key status has changed */
|
||||
if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value)
|
||||
input_event(input, EV_MSC, MSC_SCAN, usage->hid);
|
||||
|
|
|
@ -25,12 +25,13 @@ comment "Input core support is needed for USB HID input layer or HIDBP support"
|
|||
depends on USB_HID && INPUT=n
|
||||
|
||||
config USB_HIDINPUT_POWERBOOK
|
||||
bool "Enable support for iBook/PowerBook/MacBook/MacBookPro special keys"
|
||||
bool "Enable support for Apple laptop/aluminum USB special keys"
|
||||
default n
|
||||
depends on USB_HID
|
||||
help
|
||||
Say Y here if you want support for the special keys (Fn, Numlock) on
|
||||
Apple iBooks, PowerBooks, MacBooks and MacBook Pros.
|
||||
Apple iBooks, PowerBooks, MacBooks, MacBook Pros and aluminum USB
|
||||
keyboards.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#define USB_VENDOR_ID_A4TECH 0x09da
|
||||
#define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006
|
||||
#define USB_DEVICE_ID_A4TECH_X5_005D 0x000a
|
||||
|
||||
#define USB_VENDOR_ID_AASHIMA 0x06d6
|
||||
#define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025
|
||||
|
@ -28,6 +29,9 @@
|
|||
#define USB_DEVICE_ID_ACECAD_FLAIR 0x0004
|
||||
#define USB_DEVICE_ID_ACECAD_302 0x0008
|
||||
|
||||
#define USB_VENDOR_ID_ADS_TECH 0x06e1
|
||||
#define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X 0xa155
|
||||
|
||||
#define USB_VENDOR_ID_AIPTEK 0x08ca
|
||||
#define USB_DEVICE_ID_AIPTEK_01 0x0001
|
||||
#define USB_DEVICE_ID_AIPTEK_10 0x0010
|
||||
|
@ -59,6 +63,9 @@
|
|||
#define USB_DEVICE_ID_APPLE_GEYSER4_ANSI 0x021a
|
||||
#define USB_DEVICE_ID_APPLE_GEYSER4_ISO 0x021b
|
||||
#define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c
|
||||
#define USB_DEVICE_ID_APPLE_ALU_ANSI 0x0220
|
||||
#define USB_DEVICE_ID_APPLE_ALU_ISO 0x0221
|
||||
#define USB_DEVICE_ID_APPLE_ALU_JIS 0x0222
|
||||
#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a
|
||||
#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
|
||||
#define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242
|
||||
|
@ -94,6 +101,9 @@
|
|||
#define USB_DEVICE_ID_CODEMERCS_IOW_FIRST 0x1500
|
||||
#define USB_DEVICE_ID_CODEMERCS_IOW_LAST 0x15ff
|
||||
|
||||
#define USB_VENDOR_ID_CYGNAL 0x10c4
|
||||
#define USB_DEVICE_ID_CYGNAL_RADIO_SI470X 0x818a
|
||||
|
||||
#define USB_VENDOR_ID_CYPRESS 0x04b4
|
||||
#define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001
|
||||
#define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500
|
||||
|
@ -114,6 +124,9 @@
|
|||
#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
|
||||
#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
|
||||
|
||||
#define USB_VENDOR_ID_EZKEY 0x0518
|
||||
#define USB_DEVICE_ID_BTC_8193 0x0002
|
||||
|
||||
#define USB_VENDOR_ID_GAMERON 0x0810
|
||||
#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
|
||||
|
||||
|
@ -134,6 +147,9 @@
|
|||
#define USB_DEVICE_ID_GOGOPEN 0x00ce
|
||||
#define USB_DEVICE_ID_PENPOWER 0x00f4
|
||||
|
||||
#define USB_VENDOR_ID_GRETAGMACBETH 0x0971
|
||||
#define USB_DEVICE_ID_GRETAGMACBETH_HUEY 0x2005
|
||||
|
||||
#define USB_VENDOR_ID_GRIFFIN 0x077d
|
||||
#define USB_DEVICE_ID_POWERMATE 0x0410
|
||||
#define USB_DEVICE_ID_SOUNDKNOB 0x04AA
|
||||
|
@ -278,7 +294,9 @@
|
|||
#define USB_DEVICE_ID_LOGITECH_HARMONY_62 0xc14d
|
||||
#define USB_DEVICE_ID_LOGITECH_HARMONY_63 0xc14e
|
||||
#define USB_DEVICE_ID_LOGITECH_HARMONY_64 0xc14f
|
||||
#define USB_DEVICE_ID_LOGITECH_EXTREME_3D 0xc215
|
||||
#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
|
||||
#define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a
|
||||
#define USB_DEVICE_ID_LOGITECH_KBD 0xc311
|
||||
#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
|
||||
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
|
||||
|
@ -296,6 +314,12 @@
|
|||
|
||||
#define USB_VENDOR_ID_MICROSOFT 0x045e
|
||||
#define USB_DEVICE_ID_SIDEWINDER_GV 0x003b
|
||||
#define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
|
||||
#define USB_DEVICE_ID_MS_NE4K 0x00db
|
||||
#define USB_DEVICE_ID_MS_LK6K 0x00f9
|
||||
|
||||
#define USB_VENDOR_ID_MONTEREY 0x0566
|
||||
#define USB_DEVICE_ID_GENIUS_KB29E 0x3004
|
||||
|
||||
#define USB_VENDOR_ID_NCR 0x0404
|
||||
#define USB_DEVICE_ID_NCR_FIRST 0x0300
|
||||
|
@ -324,6 +348,9 @@
|
|||
#define USB_VENDOR_ID_SAITEK 0x06a3
|
||||
#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17
|
||||
|
||||
#define USB_VENDOR_ID_SAMSUNG 0x0419
|
||||
#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001
|
||||
|
||||
#define USB_VENDOR_ID_SONY 0x054c
|
||||
#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268
|
||||
|
||||
|
@ -368,6 +395,7 @@ static const struct hid_blacklist {
|
|||
} hid_blacklist[] = {
|
||||
|
||||
{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
|
||||
{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D, HID_QUIRK_2WHEEL_MOUSE_HACK_B8 },
|
||||
{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 },
|
||||
|
||||
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS },
|
||||
|
@ -390,6 +418,9 @@ static const struct hid_blacklist {
|
|||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4, HID_QUIRK_HIDDEV | HID_QUIRK_IGNORE_HIDINPUT },
|
||||
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT },
|
||||
|
||||
{ USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193, HID_QUIRK_HWHEEL_WHEEL_INVERT },
|
||||
|
||||
{ USB_VENDOR_ID_ADS_TECH, USB_DEVICE_ID_ADS_TECH_RADIO_SI470X, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE },
|
||||
|
@ -402,6 +433,7 @@ static const struct hid_blacklist {
|
|||
{ USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM, HID_QUIRK_IGNORE},
|
||||
{ USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_CIDC, 0x0103, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE },
|
||||
|
@ -423,6 +455,7 @@ static const struct hid_blacklist {
|
|||
{ USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_GRETAGMACBETH, USB_DEVICE_ID_GRETAGMACBETH_HUEY, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE },
|
||||
|
@ -516,14 +549,18 @@ static const struct hid_blacklist {
|
|||
{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
|
||||
|
||||
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
|
||||
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
|
||||
|
||||
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K, HID_QUIRK_MICROSOFT_KEYS },
|
||||
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K, HID_QUIRK_MICROSOFT_KEYS },
|
||||
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
|
||||
|
||||
{ USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
|
||||
{ USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT },
|
||||
|
||||
{ USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER },
|
||||
{ USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER | HID_QUIRK_HIDDEV },
|
||||
|
||||
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
|
||||
|
@ -531,7 +568,9 @@ static const struct hid_blacklist {
|
|||
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
|
||||
|
@ -540,19 +579,22 @@ static const struct hid_blacklist {
|
|||
|
||||
{ USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
|
||||
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI, HID_QUIRK_APPLE_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS, HID_QUIRK_APPLE_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
|
||||
{ USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
|
||||
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD, HID_QUIRK_RESET_LEDS },
|
||||
|
@ -638,10 +680,14 @@ static const struct hid_rdesc_blacklist {
|
|||
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
|
||||
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH },
|
||||
|
||||
{ USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E, HID_QUIRK_RDESC_BUTTON_CONSUMER },
|
||||
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_RDESC_MACBOOK_JIS },
|
||||
|
||||
{ USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_RDESC_PETALYNX },
|
||||
|
||||
{ USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE, HID_QUIRK_RDESC_SAMSUNG_REMOTE },
|
||||
|
||||
{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
|
||||
{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
|
||||
|
||||
|
@ -884,6 +930,8 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
|
|||
return quirks;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(usbhid_lookup_quirk);
|
||||
|
||||
/*
|
||||
* Cherry Cymotion keyboard have an invalid HID report descriptor,
|
||||
* that needs fixing before we can parse it.
|
||||
|
@ -914,6 +962,33 @@ static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Samsung IrDA remote controller (reports as Cypress USB Mouse).
|
||||
*
|
||||
* Vendor specific report #4 has a size of 48 bit,
|
||||
* and therefore is not accepted when inspecting the descriptors.
|
||||
* As a workaround we reinterpret the report as:
|
||||
* Variable type, count 6, size 8 bit, log. maximum 255
|
||||
* The burden to reconstruct the data is moved into user space.
|
||||
*/
|
||||
static void usbhid_fixup_samsung_irda_descriptor(unsigned char *rdesc,
|
||||
int rsize)
|
||||
{
|
||||
if (rsize >= 182 && rdesc[175] == 0x25
|
||||
&& rdesc[176] == 0x40
|
||||
&& rdesc[177] == 0x75
|
||||
&& rdesc[178] == 0x30
|
||||
&& rdesc[179] == 0x95
|
||||
&& rdesc[180] == 0x01
|
||||
&& rdesc[182] == 0x40) {
|
||||
printk(KERN_INFO "Fixing up Samsung IrDA report descriptor\n");
|
||||
rdesc[176] = 0xff;
|
||||
rdesc[178] = 0x08;
|
||||
rdesc[180] = 0x06;
|
||||
rdesc[182] = 0x42;
|
||||
}
|
||||
}
|
||||
|
||||
/* Petalynx Maxter Remote has maximum for consumer page set too low */
|
||||
static void usbhid_fixup_petalynx_descriptor(unsigned char *rdesc, int rsize)
|
||||
{
|
||||
|
@ -965,6 +1040,14 @@ static void usbhid_fixup_macbook_descriptor(unsigned char *rdesc, int rsize)
|
|||
}
|
||||
}
|
||||
|
||||
static void usbhid_fixup_button_consumer_descriptor(unsigned char *rdesc, int rsize)
|
||||
{
|
||||
if (rsize >= 30 && rdesc[29] == 0x05
|
||||
&& rdesc[30] == 0x09) {
|
||||
printk(KERN_INFO "Fixing up button/consumer in HID report descriptor\n");
|
||||
rdesc[30] = 0x0c;
|
||||
}
|
||||
}
|
||||
|
||||
static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize)
|
||||
{
|
||||
|
@ -982,6 +1065,13 @@ static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned
|
|||
|
||||
if (quirks & HID_QUIRK_RDESC_MACBOOK_JIS)
|
||||
usbhid_fixup_macbook_descriptor(rdesc, rsize);
|
||||
|
||||
if (quirks & HID_QUIRK_RDESC_BUTTON_CONSUMER)
|
||||
usbhid_fixup_button_consumer_descriptor(rdesc, rsize);
|
||||
|
||||
if (quirks & HID_QUIRK_RDESC_SAMSUNG_REMOTE)
|
||||
usbhid_fixup_samsung_irda_descriptor(rdesc, rsize);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -137,7 +137,8 @@ static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *ef
|
|||
int hid_tmff_init(struct hid_device *hid)
|
||||
{
|
||||
struct tmff_device *tmff;
|
||||
struct list_head *pos;
|
||||
struct hid_report *report;
|
||||
struct list_head *report_list;
|
||||
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
|
||||
struct input_dev *input_dev = hidinput->input;
|
||||
const signed short *ff_bits = ff_joystick;
|
||||
|
@ -149,8 +150,8 @@ int hid_tmff_init(struct hid_device *hid)
|
|||
return -ENOMEM;
|
||||
|
||||
/* Find the report to use */
|
||||
list_for_each(pos, &hid->report_enum[HID_OUTPUT_REPORT].report_list) {
|
||||
struct hid_report *report = (struct hid_report *)pos;
|
||||
report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
|
||||
list_for_each_entry(report, report_list, list) {
|
||||
int fieldnum;
|
||||
|
||||
for (fieldnum = 0; fieldnum < report->maxfield; ++fieldnum) {
|
||||
|
|
|
@ -235,6 +235,14 @@ static int usb_kbd_probe(struct usb_interface *iface,
|
|||
if (!usb_endpoint_is_int_in(endpoint))
|
||||
return -ENODEV;
|
||||
|
||||
#ifdef CONFIG_USB_HID
|
||||
if (usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
|
||||
le16_to_cpu(dev->descriptor.idProduct))
|
||||
& HID_QUIRK_IGNORE) {
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
|
||||
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
|
||||
|
||||
|
|
|
@ -131,6 +131,14 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
|
|||
if (!usb_endpoint_is_int_in(endpoint))
|
||||
return -ENODEV;
|
||||
|
||||
#ifdef CONFIG_USB_HID
|
||||
if (usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
|
||||
le16_to_cpu(dev->descriptor.idProduct))
|
||||
& (HID_QUIRK_IGNORE|HID_QUIRK_IGNORE_MOUSE)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
|
||||
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
|
||||
|
||||
|
|
|
@ -267,10 +267,10 @@ struct hid_item {
|
|||
#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100
|
||||
#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200
|
||||
#define HID_QUIRK_MIGHTYMOUSE 0x00000400
|
||||
#define HID_QUIRK_POWERBOOK_HAS_FN 0x00000800
|
||||
#define HID_QUIRK_POWERBOOK_FN_ON 0x00001000
|
||||
#define HID_QUIRK_APPLE_HAS_FN 0x00000800
|
||||
#define HID_QUIRK_APPLE_FN_ON 0x00001000
|
||||
#define HID_QUIRK_INVERT_HWHEEL 0x00002000
|
||||
#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00004000
|
||||
#define HID_QUIRK_APPLE_ISO_KEYBOARD 0x00004000
|
||||
#define HID_QUIRK_BAD_RELATIVE_KEYS 0x00008000
|
||||
#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000
|
||||
#define HID_QUIRK_IGNORE_MOUSE 0x00020000
|
||||
|
@ -281,6 +281,9 @@ struct hid_item {
|
|||
#define HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL 0x00400000
|
||||
#define HID_QUIRK_LOGITECH_EXPANDED_KEYMAP 0x00800000
|
||||
#define HID_QUIRK_IGNORE_HIDINPUT 0x01000000
|
||||
#define HID_QUIRK_2WHEEL_MOUSE_HACK_B8 0x02000000
|
||||
#define HID_QUIRK_HWHEEL_WHEEL_INVERT 0x04000000
|
||||
#define HID_QUIRK_MICROSOFT_KEYS 0x08000000
|
||||
|
||||
/*
|
||||
* Separate quirks for runtime report descriptor fixup
|
||||
|
@ -291,6 +294,8 @@ struct hid_item {
|
|||
#define HID_QUIRK_RDESC_SWAPPED_MIN_MAX 0x00000004
|
||||
#define HID_QUIRK_RDESC_PETALYNX 0x00000008
|
||||
#define HID_QUIRK_RDESC_MACBOOK_JIS 0x00000010
|
||||
#define HID_QUIRK_RDESC_BUTTON_CONSUMER 0x00000020
|
||||
#define HID_QUIRK_RDESC_SAMSUNG_REMOTE 0x00000040
|
||||
|
||||
/*
|
||||
* This is the global environment of the parser. This information is
|
||||
|
@ -456,6 +461,8 @@ struct hid_device { /* device report descriptor */
|
|||
|
||||
void *driver_data;
|
||||
|
||||
__s32 delayed_value; /* For A4 Tech mice hwheel quirk */
|
||||
|
||||
/* device-specific function pointers */
|
||||
int (*hidinput_input_event) (struct input_dev *, unsigned int, unsigned int, int);
|
||||
int (*hid_open) (struct hid_device *);
|
||||
|
@ -469,7 +476,7 @@ struct hid_device { /* device report descriptor */
|
|||
/* handler for raw output data, used by hidraw */
|
||||
int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t);
|
||||
#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
|
||||
unsigned long pb_pressed_fn[BITS_TO_LONGS(KEY_CNT)];
|
||||
unsigned long apple_pressed_fn[BITS_TO_LONGS(KEY_CNT)];
|
||||
unsigned long pb_pressed_numlock[BITS_TO_LONGS(KEY_CNT)];
|
||||
#endif
|
||||
};
|
||||
|
@ -520,6 +527,9 @@ extern void hidinput_disconnect(struct hid_device *);
|
|||
int hid_set_field(struct hid_field *, unsigned, __s32);
|
||||
int hid_input_report(struct hid_device *, int type, u8 *, int, int);
|
||||
int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field);
|
||||
int hidinput_mapping_quirks(struct hid_usage *, struct input_dev *, unsigned long **, int *);
|
||||
void hidinput_event_quirks(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
|
||||
int hidinput_apple_event(struct hid_device *, struct input_dev *, struct hid_usage *, __s32);
|
||||
void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt);
|
||||
void hid_output_report(struct hid_report *report, __u8 *data);
|
||||
void hid_free_device(struct hid_device *device);
|
||||
|
|
Loading…
Reference in a new issue