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:
Linus Torvalds 2008-01-29 08:52:20 +11:00
commit f4798748de
10 changed files with 651 additions and 245 deletions

View File

@ -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

View File

@ -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;

View 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;
}
}

View File

@ -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,
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).
*/
/* 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,37 +720,8 @@ 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:
@ -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,8 +759,9 @@ 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))
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))
@ -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);

View File

@ -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.

View File

@ -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);
}
/**

View File

@ -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) {

View File

@ -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));

View File

@ -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));

View File

@ -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);