mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
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: HID: handle cases of volume knobs generating relative values HID: Logitech keyboard 0xc311 needs reset leds quirk HID: support for logitech cordless desktop LX500 special mapping HID: fix autocentering of PID devices HID: separate quirks for report descriptor fixup HID: Add NOGET quirk for all NCR devices HID: support for Petalynx Maxter remote control HID: fix mismatch between hid-input HUT find/search mapping and the HUT HID: support for Gameron dual psx adaptor USB HID: avoid flush_scheduled_work() HID: Use menuconfig objects HID: force hid-input for Microsoft SideWinder GameVoice device HID: input mapping for Chicony KU-0418 tactical pad HID: make debugging output runtime-configurable
This commit is contained in:
commit
36b774102e
@ -1,8 +1,12 @@
|
||||
#
|
||||
# HID driver configuration
|
||||
#
|
||||
menu "HID Devices"
|
||||
menuconfig HID_SUPPORT
|
||||
bool "HID Devices"
|
||||
depends on INPUT
|
||||
default y
|
||||
|
||||
if HID_SUPPORT
|
||||
|
||||
config HID
|
||||
tristate "Generic HID support"
|
||||
@ -24,6 +28,7 @@ config HID
|
||||
|
||||
config HID_DEBUG
|
||||
bool "HID debugging support"
|
||||
default y if !EMBEDDED
|
||||
depends on HID
|
||||
---help---
|
||||
This option lets the HID layer output diagnostics about its internal
|
||||
@ -38,5 +43,4 @@ config HID_DEBUG
|
||||
|
||||
source "drivers/hid/usbhid/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
endif # HID_SUPPORT
|
||||
|
@ -40,6 +40,13 @@
|
||||
#define DRIVER_DESC "HID core driver"
|
||||
#define DRIVER_LICENSE "GPL"
|
||||
|
||||
#ifdef CONFIG_HID_DEBUG
|
||||
int hid_debug = 0;
|
||||
module_param_named(debug, hid_debug, bool, 0600);
|
||||
MODULE_PARM_DESC(debug, "Turn HID debugging mode on and off");
|
||||
EXPORT_SYMBOL_GPL(hid_debug);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Register a new report for a device.
|
||||
*/
|
||||
@ -78,7 +85,7 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
|
||||
struct hid_field *field;
|
||||
|
||||
if (report->maxfield == HID_MAX_FIELDS) {
|
||||
dbg("too many fields in report");
|
||||
dbg_hid("too many fields in report\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -106,7 +113,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
|
||||
usage = parser->local.usage[0];
|
||||
|
||||
if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
|
||||
dbg("collection stack overflow");
|
||||
dbg_hid("collection stack overflow\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -114,7 +121,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
|
||||
collection = kmalloc(sizeof(struct hid_collection) *
|
||||
parser->device->collection_size * 2, GFP_KERNEL);
|
||||
if (collection == NULL) {
|
||||
dbg("failed to reallocate collection array");
|
||||
dbg_hid("failed to reallocate collection array\n");
|
||||
return -1;
|
||||
}
|
||||
memcpy(collection, parser->device->collection,
|
||||
@ -150,7 +157,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
|
||||
static int close_collection(struct hid_parser *parser)
|
||||
{
|
||||
if (!parser->collection_stack_ptr) {
|
||||
dbg("collection stack underflow");
|
||||
dbg_hid("collection stack underflow\n");
|
||||
return -1;
|
||||
}
|
||||
parser->collection_stack_ptr--;
|
||||
@ -178,7 +185,7 @@ static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type)
|
||||
static int hid_add_usage(struct hid_parser *parser, unsigned usage)
|
||||
{
|
||||
if (parser->local.usage_index >= HID_MAX_USAGES) {
|
||||
dbg("usage index exceeded");
|
||||
dbg_hid("usage index exceeded\n");
|
||||
return -1;
|
||||
}
|
||||
parser->local.usage[parser->local.usage_index] = usage;
|
||||
@ -202,12 +209,12 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
|
||||
int i;
|
||||
|
||||
if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
|
||||
dbg("hid_register_report failed");
|
||||
dbg_hid("hid_register_report failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (parser->global.logical_maximum < parser->global.logical_minimum) {
|
||||
dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
|
||||
dbg_hid("logical range invalid %d %d\n", parser->global.logical_minimum, parser->global.logical_maximum);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -287,7 +294,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
|
||||
case HID_GLOBAL_ITEM_TAG_PUSH:
|
||||
|
||||
if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
|
||||
dbg("global enviroment stack overflow");
|
||||
dbg_hid("global enviroment stack overflow\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -298,7 +305,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
|
||||
case HID_GLOBAL_ITEM_TAG_POP:
|
||||
|
||||
if (!parser->global_stack_ptr) {
|
||||
dbg("global enviroment stack underflow");
|
||||
dbg_hid("global enviroment stack underflow\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -342,27 +349,27 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
|
||||
|
||||
case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
|
||||
if ((parser->global.report_size = item_udata(item)) > 32) {
|
||||
dbg("invalid report_size %d", parser->global.report_size);
|
||||
dbg_hid("invalid report_size %d\n", parser->global.report_size);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
|
||||
if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
|
||||
dbg("invalid report_count %d", parser->global.report_count);
|
||||
dbg_hid("invalid report_count %d\n", parser->global.report_count);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case HID_GLOBAL_ITEM_TAG_REPORT_ID:
|
||||
if ((parser->global.report_id = item_udata(item)) == 0) {
|
||||
dbg("report_id 0 is invalid");
|
||||
dbg_hid("report_id 0 is invalid\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
default:
|
||||
dbg("unknown global tag 0x%x", item->tag);
|
||||
dbg_hid("unknown global tag 0x%x\n", item->tag);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -377,7 +384,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
|
||||
unsigned n;
|
||||
|
||||
if (item->size == 0) {
|
||||
dbg("item data expected for local item");
|
||||
dbg_hid("item data expected for local item\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -395,14 +402,14 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
|
||||
* items and the first delimiter set.
|
||||
*/
|
||||
if (parser->local.delimiter_depth != 0) {
|
||||
dbg("nested delimiters");
|
||||
dbg_hid("nested delimiters\n");
|
||||
return -1;
|
||||
}
|
||||
parser->local.delimiter_depth++;
|
||||
parser->local.delimiter_branch++;
|
||||
} else {
|
||||
if (parser->local.delimiter_depth < 1) {
|
||||
dbg("bogus close delimiter");
|
||||
dbg_hid("bogus close delimiter\n");
|
||||
return -1;
|
||||
}
|
||||
parser->local.delimiter_depth--;
|
||||
@ -412,7 +419,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
|
||||
case HID_LOCAL_ITEM_TAG_USAGE:
|
||||
|
||||
if (parser->local.delimiter_branch > 1) {
|
||||
dbg("alternative usage ignored");
|
||||
dbg_hid("alternative usage ignored\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -424,7 +431,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
|
||||
case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
|
||||
|
||||
if (parser->local.delimiter_branch > 1) {
|
||||
dbg("alternative usage ignored");
|
||||
dbg_hid("alternative usage ignored\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -437,7 +444,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
|
||||
case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
|
||||
|
||||
if (parser->local.delimiter_branch > 1) {
|
||||
dbg("alternative usage ignored");
|
||||
dbg_hid("alternative usage ignored\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -446,14 +453,14 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
|
||||
|
||||
for (n = parser->local.usage_minimum; n <= data; n++)
|
||||
if (hid_add_usage(parser, n)) {
|
||||
dbg("hid_add_usage failed\n");
|
||||
dbg_hid("hid_add_usage failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
default:
|
||||
|
||||
dbg("unknown local item tag 0x%x", item->tag);
|
||||
dbg_hid("unknown local item tag 0x%x\n", item->tag);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
@ -487,7 +494,7 @@ static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
|
||||
ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
|
||||
break;
|
||||
default:
|
||||
dbg("unknown main item tag 0x%x", item->tag);
|
||||
dbg_hid("unknown main item tag 0x%x\n", item->tag);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
@ -502,7 +509,7 @@ static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
|
||||
|
||||
static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item)
|
||||
{
|
||||
dbg("reserved item type, tag 0x%x", item->tag);
|
||||
dbg_hid("reserved item type, tag 0x%x\n", item->tag);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -667,14 +674,14 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
|
||||
while ((start = fetch_item(start, end, &item)) != NULL) {
|
||||
|
||||
if (item.format != HID_ITEM_FORMAT_SHORT) {
|
||||
dbg("unexpected long global item");
|
||||
dbg_hid("unexpected long global item\n");
|
||||
hid_free_device(device);
|
||||
vfree(parser);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dispatch_type[item.type](parser, &item)) {
|
||||
dbg("item %u %u %u %u parsing failed\n",
|
||||
dbg_hid("item %u %u %u %u parsing failed\n",
|
||||
item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
|
||||
hid_free_device(device);
|
||||
vfree(parser);
|
||||
@ -683,13 +690,13 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
|
||||
|
||||
if (start == end) {
|
||||
if (parser->collection_stack_ptr) {
|
||||
dbg("unbalanced collection at end of report description");
|
||||
dbg_hid("unbalanced collection at end of report description\n");
|
||||
hid_free_device(device);
|
||||
vfree(parser);
|
||||
return NULL;
|
||||
}
|
||||
if (parser->local.delimiter_depth) {
|
||||
dbg("unbalanced delimiter at end of report description");
|
||||
dbg_hid("unbalanced delimiter at end of report description\n");
|
||||
hid_free_device(device);
|
||||
vfree(parser);
|
||||
return NULL;
|
||||
@ -699,7 +706,7 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
|
||||
}
|
||||
}
|
||||
|
||||
dbg("item fetching failed at offset %d\n", (int)(end - start));
|
||||
dbg_hid("item fetching failed at offset %d\n", (int)(end - start));
|
||||
hid_free_device(device);
|
||||
vfree(parser);
|
||||
return NULL;
|
||||
@ -915,13 +922,13 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
|
||||
hid_dump_input(field->usage + offset, value);
|
||||
|
||||
if (offset >= field->report_count) {
|
||||
dbg("offset (%d) exceeds report_count (%d)", offset, field->report_count);
|
||||
dbg_hid("offset (%d) exceeds report_count (%d)\n", offset, field->report_count);
|
||||
hid_dump_field(field, 8);
|
||||
return -1;
|
||||
}
|
||||
if (field->logical_minimum < 0) {
|
||||
if (value != snto32(s32ton(value, size), size)) {
|
||||
dbg("value %d is out of range", value);
|
||||
dbg_hid("value %d is out of range\n", value);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -934,19 +941,17 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
|
||||
{
|
||||
struct hid_report_enum *report_enum = hid->report_enum + type;
|
||||
struct hid_report *report;
|
||||
int n, rsize;
|
||||
int n, rsize, i;
|
||||
|
||||
if (!hid)
|
||||
return -ENODEV;
|
||||
|
||||
if (!size) {
|
||||
dbg("empty report");
|
||||
dbg_hid("empty report\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HID_DEBUG
|
||||
printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
|
||||
#endif
|
||||
dbg_hid("report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
|
||||
|
||||
n = 0; /* Normally report number is 0 */
|
||||
if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */
|
||||
@ -954,25 +959,21 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
|
||||
size--;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HID_DEBUG
|
||||
{
|
||||
int i;
|
||||
printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, size);
|
||||
for (i = 0; i < size; i++)
|
||||
printk(" %02x", data[i]);
|
||||
printk("\n");
|
||||
}
|
||||
#endif
|
||||
/* dump the report descriptor */
|
||||
dbg_hid("report %d (size %u) = ", n, size);
|
||||
for (i = 0; i < size; i++)
|
||||
dbg_hid_line(" %02x", data[i]);
|
||||
dbg_hid_line("\n");
|
||||
|
||||
if (!(report = report_enum->report_id_hash[n])) {
|
||||
dbg("undefined report_id %d received", n);
|
||||
dbg_hid("undefined report_id %d received\n", n);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rsize = ((report->size - 1) >> 3) + 1;
|
||||
|
||||
if (size < rsize) {
|
||||
dbg("report %d is too short, (%d < %d)", report->id, size, rsize);
|
||||
dbg_hid("report %d is too short, (%d < %d)\n", report->id, size, rsize);
|
||||
memset(data + size, 0, rsize - size);
|
||||
}
|
||||
|
||||
|
@ -347,6 +347,9 @@ static void resolv_usage_page(unsigned page) {
|
||||
void hid_resolv_usage(unsigned usage) {
|
||||
const struct hid_usage_entry *p;
|
||||
|
||||
if (!hid_debug)
|
||||
return;
|
||||
|
||||
resolv_usage_page(usage >> 16);
|
||||
printk(".");
|
||||
for (p = hid_usage_table; p->description; p++)
|
||||
@ -369,6 +372,9 @@ __inline__ static void tab(int n) {
|
||||
void hid_dump_field(struct hid_field *field, int n) {
|
||||
int j;
|
||||
|
||||
if (!hid_debug)
|
||||
return;
|
||||
|
||||
if (field->physical) {
|
||||
tab(n);
|
||||
printk("Physical(");
|
||||
@ -466,6 +472,9 @@ void hid_dump_device(struct hid_device *device) {
|
||||
unsigned i,k;
|
||||
static char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
|
||||
|
||||
if (!hid_debug)
|
||||
return;
|
||||
|
||||
for (i = 0; i < HID_REPORT_TYPES; i++) {
|
||||
report_enum = device->report_enum + i;
|
||||
list = report_enum->report_list.next;
|
||||
@ -489,6 +498,9 @@ void hid_dump_device(struct hid_device *device) {
|
||||
EXPORT_SYMBOL_GPL(hid_dump_device);
|
||||
|
||||
void hid_dump_input(struct hid_usage *usage, __s32 value) {
|
||||
if (!hid_debug)
|
||||
return;
|
||||
|
||||
printk("hid-debug: input ");
|
||||
hid_resolv_usage(usage->hid);
|
||||
printk(" = %d\n", value);
|
||||
@ -758,6 +770,9 @@ static char **names[EV_MAX + 1] = {
|
||||
|
||||
void hid_resolv_event(__u8 type, __u16 code) {
|
||||
|
||||
if (!hid_debug)
|
||||
return;
|
||||
|
||||
printk("%s.%s", events[type] ? events[type] : "?",
|
||||
names[type] ? (names[type][code] ? names[type][code] : "?") : "?");
|
||||
}
|
||||
|
@ -60,6 +60,19 @@ static const unsigned char hid_keyboard[256] = {
|
||||
150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
|
||||
};
|
||||
|
||||
/* extended mapping for certain Logitech hardware (Logitech cordless desktop LX500) */
|
||||
#define LOGITECH_EXPANDED_KEYMAP_SIZE 80
|
||||
static int logitech_expanded_keymap[LOGITECH_EXPANDED_KEYMAP_SIZE] = {
|
||||
0,216, 0,213,175,156, 0, 0, 0, 0,
|
||||
144, 0, 0, 0, 0, 0, 0, 0, 0,212,
|
||||
174,167,152,161,112, 0, 0, 0,154, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,183,184,185,186,187,
|
||||
188,189,190,191,192,193,194, 0, 0, 0
|
||||
};
|
||||
|
||||
static const struct {
|
||||
__s32 x;
|
||||
__s32 y;
|
||||
@ -308,9 +321,7 @@ static int hidinput_setkeycode(struct input_dev *dev, int scancode,
|
||||
|
||||
clear_bit(old_keycode, dev->keybit);
|
||||
set_bit(usage->code, dev->keybit);
|
||||
#ifdef CONFIG_HID_DEBUG
|
||||
printk (KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
|
||||
#endif
|
||||
dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
|
||||
/* Set the keybit for the old keycode if the old keycode is used
|
||||
* by another key */
|
||||
if (hidinput_find_key (hid, 0, old_keycode))
|
||||
@ -333,11 +344,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
|
||||
field->hidinput = hidinput;
|
||||
|
||||
#ifdef CONFIG_HID_DEBUG
|
||||
printk(KERN_DEBUG "Mapping: ");
|
||||
dbg_hid("Mapping: ");
|
||||
hid_resolv_usage(usage->hid);
|
||||
printk(" ---> ");
|
||||
#endif
|
||||
dbg_hid_line(" ---> ");
|
||||
|
||||
if (field->flags & HID_MAIN_ITEM_CONSTANT)
|
||||
goto ignore;
|
||||
@ -378,6 +387,21 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
}
|
||||
}
|
||||
|
||||
/* Special handling for Logitech Cordless Desktop */
|
||||
if (field->application != HID_GD_MOUSE) {
|
||||
if (device->quirks & HID_QUIRK_LOGITECH_EXPANDED_KEYMAP) {
|
||||
int hid = usage->hid & HID_USAGE;
|
||||
if (hid < LOGITECH_EXPANDED_KEYMAP_SIZE && logitech_expanded_keymap[hid] != 0)
|
||||
code = logitech_expanded_keymap[hid];
|
||||
}
|
||||
} else {
|
||||
if (device->quirks & HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL) {
|
||||
int hid = usage->hid & HID_USAGE;
|
||||
if (hid == 7 || hid == 8)
|
||||
goto ignore;
|
||||
}
|
||||
}
|
||||
|
||||
map_key(code);
|
||||
break;
|
||||
|
||||
@ -566,6 +590,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
case 0x0e5: map_key_clear(KEY_BASSBOOST); break;
|
||||
case 0x0e9: map_key_clear(KEY_VOLUMEUP); break;
|
||||
case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break;
|
||||
|
||||
/* 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 0x183: map_key_clear(KEY_CONFIG); break;
|
||||
case 0x184: map_key_clear(KEY_WORDPROCESSOR); break;
|
||||
case 0x185: map_key_clear(KEY_EDITOR); break;
|
||||
@ -598,7 +627,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
case 0x21b: map_key_clear(KEY_COPY); break;
|
||||
case 0x21c: map_key_clear(KEY_CUT); break;
|
||||
case 0x21d: map_key_clear(KEY_PASTE); break;
|
||||
case 0x221: map_key_clear(KEY_FIND); break;
|
||||
case 0x21f: map_key_clear(KEY_FIND); break;
|
||||
case 0x221: map_key_clear(KEY_SEARCH); break;
|
||||
case 0x222: map_key_clear(KEY_GOTO); break;
|
||||
case 0x223: map_key_clear(KEY_HOMEPAGE); break;
|
||||
case 0x224: map_key_clear(KEY_BACK); break;
|
||||
case 0x225: map_key_clear(KEY_FORWARD); break;
|
||||
@ -688,7 +719,28 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
break;
|
||||
|
||||
case HID_UP_MSVENDOR:
|
||||
goto ignore;
|
||||
|
||||
/* special case - Chicony Chicony KU-0418 tactical pad */
|
||||
if (device->vendor == 0x04f2 && device->product == 0x0418) {
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
goto ignore;
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB keyboards */
|
||||
|
||||
@ -704,10 +756,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_UP_LOGIVENDOR: /* Reported on Logitech Ultra X Media Remote */
|
||||
|
||||
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;
|
||||
@ -725,6 +777,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
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;
|
||||
@ -818,16 +878,24 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
field->dpad = usage->code;
|
||||
}
|
||||
|
||||
/* for those devices which produce Consumer volume usage as relative,
|
||||
* we emulate pressing volumeup/volumedown appropriate number of times
|
||||
* in hidinput_hid_event()
|
||||
*/
|
||||
if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) &&
|
||||
(usage->code == ABS_VOLUME)) {
|
||||
set_bit(KEY_VOLUMEUP, input->keybit);
|
||||
set_bit(KEY_VOLUMEDOWN, input->keybit);
|
||||
}
|
||||
|
||||
hid_resolv_event(usage->type, usage->code);
|
||||
#ifdef CONFIG_HID_DEBUG
|
||||
printk("\n");
|
||||
#endif
|
||||
|
||||
dbg_hid_line("\n");
|
||||
|
||||
return;
|
||||
|
||||
ignore:
|
||||
#ifdef CONFIG_HID_DEBUG
|
||||
printk("IGNORED\n");
|
||||
#endif
|
||||
dbg_hid_line("IGNORED\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -896,18 +964,33 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
|
||||
}
|
||||
|
||||
if (usage->hid == (HID_UP_PID | 0x83UL)) { /* Simultaneous Effects Max */
|
||||
dbg("Maximum Effects - %d",value);
|
||||
dbg_hid("Maximum Effects - %d\n",value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (usage->hid == (HID_UP_PID | 0x7fUL)) {
|
||||
dbg("PID Pool Report\n");
|
||||
dbg_hid("PID Pool Report\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
|
||||
return;
|
||||
|
||||
if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) &&
|
||||
(usage->code == ABS_VOLUME)) {
|
||||
int count = abs(value);
|
||||
int direction = value > 0 ? KEY_VOLUMEUP : KEY_VOLUMEDOWN;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
input_event(input, EV_KEY, direction, 1);
|
||||
input_sync(input);
|
||||
input_event(input, EV_KEY, direction, 0);
|
||||
input_sync(input);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
input_event(input, usage->type, usage->code, value);
|
||||
|
||||
if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
|
||||
@ -976,7 +1059,7 @@ int hidinput_connect(struct hid_device *hid)
|
||||
if (IS_INPUT_APPLICATION(hid->collection[i].usage))
|
||||
break;
|
||||
|
||||
if (i == hid->maxcollection)
|
||||
if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDINPUT) == 0)
|
||||
return -1;
|
||||
|
||||
if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
|
||||
@ -994,7 +1077,7 @@ int hidinput_connect(struct hid_device *hid)
|
||||
if (!hidinput || !input_dev) {
|
||||
kfree(hidinput);
|
||||
input_free_device(input_dev);
|
||||
err("Out of memory during hid input probe");
|
||||
err_hid("Out of memory during hid input probe");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,12 @@ MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying "
|
||||
" quirks=vendorID:productID:quirks"
|
||||
" where vendorID, productID, and quirks are all in"
|
||||
" 0x-prefixed hex");
|
||||
static char *rdesc_quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL };
|
||||
module_param_array_named(rdesc_quirks, rdesc_quirks_param, charp, NULL, 0444);
|
||||
MODULE_PARM_DESC(rdesc_quirks, "Add/modify report descriptor quirks by specifying "
|
||||
" rdesc_quirks=vendorID:productID:rdesc_quirks"
|
||||
" where vendorID, productID, and rdesc_quirks are all in"
|
||||
" 0x-prefixed hex");
|
||||
/*
|
||||
* Input submission and I/O error handler.
|
||||
*/
|
||||
@ -127,7 +133,7 @@ static void hid_reset(struct work_struct *work)
|
||||
hid_io_error(hid);
|
||||
break;
|
||||
default:
|
||||
err("can't reset device, %s-%s/input%d, status %d",
|
||||
err_hid("can't reset device, %s-%s/input%d, status %d",
|
||||
hid_to_usb_dev(hid)->bus->bus_name,
|
||||
hid_to_usb_dev(hid)->devpath,
|
||||
usbhid->ifnum, rc);
|
||||
@ -220,7 +226,7 @@ static void hid_irq_in(struct urb *urb)
|
||||
if (status) {
|
||||
clear_bit(HID_IN_RUNNING, &usbhid->iofl);
|
||||
if (status != -EPERM) {
|
||||
err("can't resubmit intr, %s-%s/input%d, status %d",
|
||||
err_hid("can't resubmit intr, %s-%s/input%d, status %d",
|
||||
hid_to_usb_dev(hid)->bus->bus_name,
|
||||
hid_to_usb_dev(hid)->devpath,
|
||||
usbhid->ifnum, status);
|
||||
@ -240,10 +246,10 @@ static int hid_submit_out(struct hid_device *hid)
|
||||
usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
|
||||
usbhid->urbout->dev = hid_to_usb_dev(hid);
|
||||
|
||||
dbg("submitting out urb");
|
||||
dbg_hid("submitting out urb\n");
|
||||
|
||||
if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) {
|
||||
err("usb_submit_urb(out) failed");
|
||||
err_hid("usb_submit_urb(out) failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -287,12 +293,12 @@ static int hid_submit_ctrl(struct hid_device *hid)
|
||||
usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum);
|
||||
usbhid->cr->wLength = cpu_to_le16(len);
|
||||
|
||||
dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u",
|
||||
dbg_hid("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u\n",
|
||||
usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
|
||||
usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength);
|
||||
|
||||
if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) {
|
||||
err("usb_submit_urb(ctrl) failed");
|
||||
err_hid("usb_submit_urb(ctrl) failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -474,7 +480,7 @@ int usbhid_wait_io(struct hid_device *hid)
|
||||
if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) &&
|
||||
!test_bit(HID_OUT_RUNNING, &usbhid->iofl)),
|
||||
10*HZ)) {
|
||||
dbg("timeout waiting for ctrl or out queue to clear");
|
||||
dbg_hid("timeout waiting for ctrl or out queue to clear\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -632,20 +638,6 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
|
||||
usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cherry Cymotion keyboard have an invalid HID report descriptor,
|
||||
* that needs fixing before we can parse it.
|
||||
*/
|
||||
|
||||
static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize)
|
||||
{
|
||||
if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
|
||||
info("Fixing up Cherry Cymotion report descriptor");
|
||||
rdesc[11] = rdesc[16] = 0xff;
|
||||
rdesc[12] = rdesc[17] = 0x03;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
|
||||
* to "operational". Without this, the ps3 controller will not report any
|
||||
@ -667,51 +659,11 @@ static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum)
|
||||
USB_CTRL_GET_TIMEOUT);
|
||||
|
||||
if (result < 0)
|
||||
err("%s failed: %d\n", __func__, result);
|
||||
err_hid("%s failed: %d\n", __func__, result);
|
||||
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Certain Logitech keyboards send in report #3 keys which are far
|
||||
* above the logical maximum described in descriptor. This extends
|
||||
* the original value of 0x28c of logical maximum to 0x104d
|
||||
*/
|
||||
static void hid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
|
||||
{
|
||||
if (rsize >= 90 && rdesc[83] == 0x26
|
||||
&& rdesc[84] == 0x8c
|
||||
&& rdesc[85] == 0x02) {
|
||||
info("Fixing up Logitech keyboard report descriptor");
|
||||
rdesc[84] = rdesc[89] = 0x4d;
|
||||
rdesc[85] = rdesc[90] = 0x10;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some USB barcode readers from cypress have usage min and usage max in
|
||||
* the wrong order
|
||||
*/
|
||||
static void hid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
|
||||
{
|
||||
short fixed = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < rsize - 4; i++) {
|
||||
if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
|
||||
unsigned char tmp;
|
||||
|
||||
rdesc[i] = 0x19; rdesc[i+2] = 0x29;
|
||||
tmp = rdesc[i+3];
|
||||
rdesc[i+3] = rdesc[i+1];
|
||||
rdesc[i+1] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (fixed)
|
||||
info("Fixing up Cypress report descriptor");
|
||||
}
|
||||
|
||||
static struct hid_device *usb_hid_configure(struct usb_interface *intf)
|
||||
{
|
||||
struct usb_host_interface *interface = intf->cur_altsetting;
|
||||
@ -746,7 +698,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
|
||||
if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
|
||||
(!interface->desc.bNumEndpoints ||
|
||||
usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
|
||||
dbg("class descriptor not present\n");
|
||||
dbg_hid("class descriptor not present\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -755,41 +707,34 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
|
||||
rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
|
||||
|
||||
if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
|
||||
dbg("weird size of report descriptor (%u)", rsize);
|
||||
dbg_hid("weird size of report descriptor (%u)\n", rsize);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) {
|
||||
dbg("couldn't allocate rdesc memory");
|
||||
dbg_hid("couldn't allocate rdesc memory\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0);
|
||||
|
||||
if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {
|
||||
dbg("reading report descriptor failed");
|
||||
dbg_hid("reading report descriptor failed\n");
|
||||
kfree(rdesc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((quirks & HID_QUIRK_CYMOTION))
|
||||
hid_fixup_cymotion_descriptor(rdesc, rsize);
|
||||
usbhid_fixup_report_descriptor(le16_to_cpu(dev->descriptor.idVendor),
|
||||
le16_to_cpu(dev->descriptor.idProduct), rdesc,
|
||||
rsize, rdesc_quirks_param);
|
||||
|
||||
if (quirks & HID_QUIRK_LOGITECH_DESCRIPTOR)
|
||||
hid_fixup_logitech_descriptor(rdesc, rsize);
|
||||
|
||||
if (quirks & HID_QUIRK_SWAPPED_MIN_MAX)
|
||||
hid_fixup_cypress_descriptor(rdesc, rsize);
|
||||
|
||||
#ifdef CONFIG_HID_DEBUG
|
||||
printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
|
||||
dbg_hid("report descriptor (size %u, read %d) = ", rsize, n);
|
||||
for (n = 0; n < rsize; n++)
|
||||
printk(" %02x", (unsigned char) rdesc[n]);
|
||||
printk("\n");
|
||||
#endif
|
||||
dbg_hid_line(" %02x", (unsigned char) rdesc[n]);
|
||||
dbg_hid_line("\n");
|
||||
|
||||
if (!(hid = hid_parse_report(rdesc, n))) {
|
||||
dbg("parsing report descriptor failed");
|
||||
dbg_hid("parsing report descriptor failed\n");
|
||||
kfree(rdesc);
|
||||
return NULL;
|
||||
}
|
||||
@ -861,7 +806,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
|
||||
}
|
||||
|
||||
if (!usbhid->urbin) {
|
||||
err("couldn't find an input interrupt endpoint");
|
||||
err_hid("couldn't find an input interrupt endpoint");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -956,7 +901,7 @@ static void hid_disconnect(struct usb_interface *intf)
|
||||
usb_kill_urb(usbhid->urbctrl);
|
||||
|
||||
del_timer_sync(&usbhid->io_retry);
|
||||
flush_scheduled_work();
|
||||
cancel_work_sync(&usbhid->reset_work);
|
||||
|
||||
if (hid->claimed & HID_CLAIMED_INPUT)
|
||||
hidinput_disconnect(hid);
|
||||
@ -978,7 +923,7 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
int i;
|
||||
char *c;
|
||||
|
||||
dbg("HID probe called for ifnum %d",
|
||||
dbg_hid("HID probe called for ifnum %d\n",
|
||||
intf->altsetting->desc.bInterfaceNumber);
|
||||
|
||||
if (!(hid = usb_hid_configure(intf)))
|
||||
|
@ -78,7 +78,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
|
||||
report->field[0]->value[1] = 0x08;
|
||||
report->field[0]->value[2] = x;
|
||||
report->field[0]->value[3] = y;
|
||||
dbg("(x, y)=(%04x, %04x)", x, y);
|
||||
dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
|
||||
usbhid_submit_report(hid, report, USB_DIR_OUT);
|
||||
break;
|
||||
|
||||
@ -93,7 +93,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
|
||||
report->field[0]->value[1] = 0x00;
|
||||
report->field[0]->value[2] = left;
|
||||
report->field[0]->value[3] = right;
|
||||
dbg("(left, right)=(%04x, %04x)", left, right);
|
||||
dbg_hid("(left, right)=(%04x, %04x)\n", left, right);
|
||||
usbhid_submit_report(hid, report, USB_DIR_OUT);
|
||||
break;
|
||||
}
|
||||
@ -113,20 +113,20 @@ int hid_lgff_init(struct hid_device* hid)
|
||||
|
||||
/* Find the report to use */
|
||||
if (list_empty(report_list)) {
|
||||
err("No output report found");
|
||||
err_hid("No output report found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check that the report looks ok */
|
||||
report = list_entry(report_list->next, struct hid_report, list);
|
||||
if (!report) {
|
||||
err("NULL output report");
|
||||
err_hid("NULL output report");
|
||||
return -1;
|
||||
}
|
||||
|
||||
field = report->field[0];
|
||||
if (!field) {
|
||||
err("NULL field");
|
||||
err_hid("NULL field");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -738,6 +738,7 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
|
||||
pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0;
|
||||
pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0;
|
||||
pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
|
||||
pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
|
||||
pidff->set_effect[PID_START_DELAY].value[0] = 0;
|
||||
|
||||
usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
|
||||
|
@ -105,6 +105,9 @@
|
||||
#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
|
||||
#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
|
||||
|
||||
#define USB_VENDOR_ID_GAMERON 0x0810
|
||||
#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
|
||||
|
||||
#define USB_VENDOR_ID_GLAB 0x06c2
|
||||
#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038
|
||||
#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039
|
||||
@ -196,8 +199,10 @@
|
||||
#define USB_VENDOR_ID_LOGITECH 0x046d
|
||||
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
|
||||
#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
|
||||
#define USB_DEVICE_ID_LOGITECH_KBD 0xc311
|
||||
#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
|
||||
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
|
||||
#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
|
||||
#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
|
||||
#define USB_DEVICE_ID_DINOVO_EDGE 0xc714
|
||||
|
||||
@ -209,6 +214,13 @@
|
||||
#define USB_DEVICE_ID_MGE_UPS 0xffff
|
||||
#define USB_DEVICE_ID_MGE_UPS1 0x0001
|
||||
|
||||
#define USB_VENDOR_ID_MICROSOFT 0x045e
|
||||
#define USB_DEVICE_ID_SIDEWINDER_GV 0x003b
|
||||
|
||||
#define USB_VENDOR_ID_NCR 0x0404
|
||||
#define USB_DEVICE_ID_NCR_FIRST 0x0300
|
||||
#define USB_DEVICE_ID_NCR_LAST 0x03ff
|
||||
|
||||
#define USB_VENDOR_ID_NEC 0x073e
|
||||
#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301
|
||||
|
||||
@ -220,6 +232,9 @@
|
||||
#define USB_VENDOR_ID_PANTHERLORD 0x0810
|
||||
#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001
|
||||
|
||||
#define USB_VENDOR_ID_PETALYNX 0x18b1
|
||||
#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
|
||||
|
||||
#define USB_VENDOR_ID_PLAYDOTCOM 0x0b43
|
||||
#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003
|
||||
|
||||
@ -278,6 +293,7 @@ static const struct hid_blacklist {
|
||||
{ USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
|
||||
{ USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
|
||||
{ USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
|
||||
{ USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR, HID_QUIRK_MULTI_INPUT },
|
||||
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
|
||||
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
|
||||
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
|
||||
@ -285,11 +301,10 @@ static const struct hid_blacklist {
|
||||
{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
|
||||
{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
|
||||
|
||||
{ USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
|
||||
|
||||
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
|
||||
|
||||
{ USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV },
|
||||
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT },
|
||||
|
||||
{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
|
||||
@ -409,9 +424,7 @@ 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_MX3000_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR },
|
||||
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR },
|
||||
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_LOGITECH_DESCRIPTOR },
|
||||
{ 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_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
|
||||
|
||||
@ -426,6 +439,7 @@ 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_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, 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 },
|
||||
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
|
||||
@ -448,9 +462,28 @@ static const struct hid_blacklist {
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_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 },
|
||||
|
||||
{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_SWAPPED_MIN_MAX },
|
||||
{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_SWAPPED_MIN_MAX },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
/* Quirks for devices which require report descriptor fixup go here */
|
||||
static const struct hid_rdesc_blacklist {
|
||||
__u16 idVendor;
|
||||
__u16 idProduct;
|
||||
__u32 quirks;
|
||||
} hid_rdesc_blacklist[] = {
|
||||
|
||||
{ USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_RDESC_CYMOTION },
|
||||
|
||||
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
|
||||
{ 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_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_RDESC_PETALYNX },
|
||||
|
||||
{ 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 },
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
@ -493,7 +526,7 @@ static struct hid_blacklist *usbhid_exists_dquirk(const u16 idVendor,
|
||||
}
|
||||
|
||||
if (bl_entry != NULL)
|
||||
dbg("Found dynamic quirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
|
||||
dbg_hid("Found dynamic quirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
|
||||
bl_entry->quirks, bl_entry->idVendor,
|
||||
bl_entry->idProduct);
|
||||
|
||||
@ -521,13 +554,13 @@ int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct,
|
||||
int list_edited = 0;
|
||||
|
||||
if (!idVendor) {
|
||||
dbg("Cannot add a quirk with idVendor = 0");
|
||||
dbg_hid("Cannot add a quirk with idVendor = 0\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
q_new = kmalloc(sizeof(struct quirks_list_struct), GFP_KERNEL);
|
||||
if (!q_new) {
|
||||
dbg("Could not allocate quirks_list_struct");
|
||||
dbg_hid("Could not allocate quirks_list_struct\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -559,7 +592,6 @@ int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* usbhid_remove_all_dquirks: remove all runtime HID quirks from memory
|
||||
*
|
||||
@ -643,7 +675,7 @@ static const struct hid_blacklist *usbhid_exists_squirk(const u16 idVendor,
|
||||
bl_entry = &hid_blacklist[n];
|
||||
|
||||
if (bl_entry != NULL)
|
||||
dbg("Found squirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
|
||||
dbg_hid("Found squirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
|
||||
bl_entry->quirks, bl_entry->idVendor,
|
||||
bl_entry->idProduct);
|
||||
return bl_entry;
|
||||
@ -675,6 +707,12 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
|
||||
idProduct <= USB_DEVICE_ID_CODEMERCS_IOW_LAST)
|
||||
return HID_QUIRK_IGNORE;
|
||||
|
||||
/* NCR devices must not be queried for reports */
|
||||
if (idVendor == USB_VENDOR_ID_NCR &&
|
||||
idProduct >= USB_DEVICE_ID_NCR_FIRST &&
|
||||
idProduct <= USB_DEVICE_ID_NCR_LAST)
|
||||
return HID_QUIRK_NOGET;
|
||||
|
||||
down_read(&dquirks_rwsem);
|
||||
bl_entry = usbhid_exists_dquirk(idVendor, idProduct);
|
||||
if (!bl_entry)
|
||||
@ -686,3 +724,126 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
|
||||
return quirks;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cherry Cymotion keyboard have an invalid HID report descriptor,
|
||||
* that needs fixing before we can parse it.
|
||||
*/
|
||||
static void usbhid_fixup_cymotion_descriptor(char *rdesc, int rsize)
|
||||
{
|
||||
if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
|
||||
printk(KERN_INFO "Fixing up Cherry Cymotion report descriptor\n");
|
||||
rdesc[11] = rdesc[16] = 0xff;
|
||||
rdesc[12] = rdesc[17] = 0x03;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Certain Logitech keyboards send in report #3 keys which are far
|
||||
* above the logical maximum described in descriptor. This extends
|
||||
* the original value of 0x28c of logical maximum to 0x104d
|
||||
*/
|
||||
static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
|
||||
{
|
||||
if (rsize >= 90 && rdesc[83] == 0x26
|
||||
&& rdesc[84] == 0x8c
|
||||
&& rdesc[85] == 0x02) {
|
||||
printk(KERN_INFO "Fixing up Logitech keyboard report descriptor\n");
|
||||
rdesc[84] = rdesc[89] = 0x4d;
|
||||
rdesc[85] = rdesc[90] = 0x10;
|
||||
}
|
||||
}
|
||||
|
||||
/* Petalynx Maxter Remote has maximum for consumer page set too low */
|
||||
static void usbhid_fixup_petalynx_descriptor(unsigned char *rdesc, int rsize)
|
||||
{
|
||||
if (rsize >= 60 && rdesc[39] == 0x2a
|
||||
&& rdesc[40] == 0xf5
|
||||
&& rdesc[41] == 0x00
|
||||
&& rdesc[59] == 0x26
|
||||
&& rdesc[60] == 0xf9
|
||||
&& rdesc[61] == 0x00) {
|
||||
printk(KERN_INFO "Fixing up Petalynx Maxter Remote report descriptor\n");
|
||||
rdesc[60] = 0xfa;
|
||||
rdesc[40] = 0xfa;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some USB barcode readers from cypress have usage min and usage max in
|
||||
* the wrong order
|
||||
*/
|
||||
static void usbhid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
|
||||
{
|
||||
short fixed = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < rsize - 4; i++) {
|
||||
if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
|
||||
unsigned char tmp;
|
||||
|
||||
rdesc[i] = 0x19; rdesc[i+2] = 0x29;
|
||||
tmp = rdesc[i+3];
|
||||
rdesc[i+3] = rdesc[i+1];
|
||||
rdesc[i+1] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (fixed)
|
||||
printk(KERN_INFO "Fixing up Cypress report descriptor\n");
|
||||
}
|
||||
|
||||
|
||||
static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize)
|
||||
{
|
||||
if ((quirks & HID_QUIRK_RDESC_CYMOTION))
|
||||
usbhid_fixup_cymotion_descriptor(rdesc, rsize);
|
||||
|
||||
if (quirks & HID_QUIRK_RDESC_LOGITECH)
|
||||
usbhid_fixup_logitech_descriptor(rdesc, rsize);
|
||||
|
||||
if (quirks & HID_QUIRK_RDESC_SWAPPED_MIN_MAX)
|
||||
usbhid_fixup_cypress_descriptor(rdesc, rsize);
|
||||
|
||||
if (quirks & HID_QUIRK_RDESC_PETALYNX)
|
||||
usbhid_fixup_petalynx_descriptor(rdesc, rsize);
|
||||
}
|
||||
|
||||
/**
|
||||
* usbhid_fixup_report_descriptor: check if report descriptor needs fixup
|
||||
*
|
||||
* Description:
|
||||
* Walks the hid_rdesc_blacklist[] array and checks whether the device
|
||||
* is known to have broken report descriptor that needs to be fixed up
|
||||
* prior to entering the HID parser
|
||||
*
|
||||
* Returns: nothing
|
||||
*/
|
||||
void usbhid_fixup_report_descriptor(const u16 idVendor, const u16 idProduct,
|
||||
char *rdesc, unsigned rsize, char **quirks_param)
|
||||
{
|
||||
int n, m;
|
||||
u16 paramVendor, paramProduct;
|
||||
u32 quirks;
|
||||
|
||||
/* static rdesc quirk entries */
|
||||
for (n = 0; hid_rdesc_blacklist[n].idVendor; n++)
|
||||
if (hid_rdesc_blacklist[n].idVendor == idVendor &&
|
||||
hid_rdesc_blacklist[n].idProduct == idProduct)
|
||||
__usbhid_fixup_report_descriptor(hid_rdesc_blacklist[n].quirks,
|
||||
rdesc, rsize);
|
||||
|
||||
/* runtime rdesc quirk entries handling */
|
||||
for (n = 0; quirks_param[n] && n < MAX_USBHID_BOOT_QUIRKS; n++) {
|
||||
m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x",
|
||||
¶mVendor, ¶mProduct, &quirks);
|
||||
|
||||
if (m != 3)
|
||||
printk(KERN_WARNING
|
||||
"Could not parse HID quirk module param %s\n",
|
||||
quirks_param[n]);
|
||||
else if (paramVendor == idVendor && paramProduct == idProduct)
|
||||
__usbhid_fixup_report_descriptor(quirks, rdesc, rsize);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *ef
|
||||
|
||||
tmff->rumble->value[0] = left;
|
||||
tmff->rumble->value[1] = right;
|
||||
dbg("(left,right)=(%08x, %08x)", left, right);
|
||||
dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
|
||||
usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
|
||||
|
||||
return 0;
|
||||
|
@ -21,10 +21,6 @@
|
||||
*/
|
||||
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
#define debug(format, arg...) pr_debug("hid-zpff: " format "\n" , ## arg)
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/hid.h>
|
||||
@ -49,14 +45,14 @@ static int hid_zpff_play(struct input_dev *dev, void *data,
|
||||
|
||||
left = effect->u.rumble.strong_magnitude;
|
||||
right = effect->u.rumble.weak_magnitude;
|
||||
debug("called with 0x%04x 0x%04x", left, right);
|
||||
dbg_hid("called with 0x%04x 0x%04x\n", left, right);
|
||||
|
||||
left = left * 0x7f / 0xffff;
|
||||
right = right * 0x7f / 0xffff;
|
||||
|
||||
zpff->report->field[2]->value[0] = left;
|
||||
zpff->report->field[3]->value[0] = right;
|
||||
debug("running with 0x%02x 0x%02x", left, right);
|
||||
dbg_hid("running with 0x%02x 0x%02x\n", left, right);
|
||||
usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
|
||||
|
||||
return 0;
|
||||
|
@ -779,7 +779,7 @@ int hiddev_connect(struct hid_device *hid)
|
||||
|
||||
retval = usb_register_dev(usbhid->intf, &hiddev_class);
|
||||
if (retval) {
|
||||
err("Not able to get a minor for this device.");
|
||||
err_hid("Not able to get a minor for this device.");
|
||||
kfree(hiddev);
|
||||
return -1;
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ static void usb_kbd_irq(struct urb *urb)
|
||||
resubmit:
|
||||
i = usb_submit_urb (urb, GFP_ATOMIC);
|
||||
if (i)
|
||||
err ("can't resubmit intr, %s-%s/input0, status %d",
|
||||
err_hid ("can't resubmit intr, %s-%s/input0, status %d",
|
||||
kbd->usbdev->bus->bus_name,
|
||||
kbd->usbdev->devpath, i);
|
||||
}
|
||||
@ -151,7 +151,7 @@ static int usb_kbd_event(struct input_dev *dev, unsigned int type,
|
||||
*(kbd->leds) = kbd->newleds;
|
||||
kbd->led->dev = kbd->usbdev;
|
||||
if (usb_submit_urb(kbd->led, GFP_ATOMIC))
|
||||
err("usb_submit_urb(leds) failed");
|
||||
err_hid("usb_submit_urb(leds) failed");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -169,7 +169,7 @@ static void usb_kbd_led(struct urb *urb)
|
||||
*(kbd->leds) = kbd->newleds;
|
||||
kbd->led->dev = kbd->usbdev;
|
||||
if (usb_submit_urb(kbd->led, GFP_ATOMIC))
|
||||
err("usb_submit_urb(leds) failed");
|
||||
err_hid("usb_submit_urb(leds) failed");
|
||||
}
|
||||
|
||||
static int usb_kbd_open(struct input_dev *dev)
|
||||
|
@ -263,19 +263,28 @@ 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_CYMOTION 0x00000800
|
||||
#define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000
|
||||
#define HID_QUIRK_POWERBOOK_FN_ON 0x00002000
|
||||
#define HID_QUIRK_INVERT_HWHEEL 0x00004000
|
||||
#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00008000
|
||||
#define HID_QUIRK_BAD_RELATIVE_KEYS 0x00010000
|
||||
#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00020000
|
||||
#define HID_QUIRK_IGNORE_MOUSE 0x00040000
|
||||
#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00080000
|
||||
#define HID_QUIRK_LOGITECH_DESCRIPTOR 0x00100000
|
||||
#define HID_QUIRK_DUPLICATE_USAGES 0x00200000
|
||||
#define HID_QUIRK_RESET_LEDS 0x00400000
|
||||
#define HID_QUIRK_SWAPPED_MIN_MAX 0x00800000
|
||||
#define HID_QUIRK_POWERBOOK_HAS_FN 0x00000800
|
||||
#define HID_QUIRK_POWERBOOK_FN_ON 0x00001000
|
||||
#define HID_QUIRK_INVERT_HWHEEL 0x00002000
|
||||
#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00004000
|
||||
#define HID_QUIRK_BAD_RELATIVE_KEYS 0x00008000
|
||||
#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000
|
||||
#define HID_QUIRK_IGNORE_MOUSE 0x00020000
|
||||
#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00040000
|
||||
#define HID_QUIRK_DUPLICATE_USAGES 0x00080000
|
||||
#define HID_QUIRK_RESET_LEDS 0x00100000
|
||||
#define HID_QUIRK_HIDINPUT 0x00200000
|
||||
#define HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL 0x00400000
|
||||
#define HID_QUIRK_LOGITECH_EXPANDED_KEYMAP 0x00800000
|
||||
|
||||
/*
|
||||
* Separate quirks for runtime report descriptor fixup
|
||||
*/
|
||||
|
||||
#define HID_QUIRK_RDESC_CYMOTION 0x00000001
|
||||
#define HID_QUIRK_RDESC_LOGITECH 0x00000002
|
||||
#define HID_QUIRK_RDESC_SWAPPED_MIN_MAX 0x00000004
|
||||
#define HID_QUIRK_RDESC_PETALYNX 0x00000008
|
||||
|
||||
/*
|
||||
* This is the global environment of the parser. This information is
|
||||
@ -488,6 +497,11 @@ struct hid_descriptor {
|
||||
#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001))
|
||||
|
||||
/* HID core API */
|
||||
|
||||
#ifdef CONFIG_HID_DEBUG
|
||||
extern int hid_debug;
|
||||
#endif
|
||||
|
||||
extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
|
||||
extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report);
|
||||
extern int hidinput_connect(struct hid_device *);
|
||||
@ -506,6 +520,7 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct);
|
||||
int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct, const u32 quirks);
|
||||
int usbhid_quirks_init(char **quirks_param);
|
||||
void usbhid_quirks_exit(void);
|
||||
void usbhid_fixup_report_descriptor(const u16, const u16, char *, unsigned, char **);
|
||||
|
||||
#ifdef CONFIG_HID_FF
|
||||
int hid_ff_init(struct hid_device *hid);
|
||||
@ -523,14 +538,19 @@ static inline int hid_pidff_init(struct hid_device *hid) { return -ENODEV; }
|
||||
#else
|
||||
static inline int hid_ff_init(struct hid_device *hid) { return -1; }
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , \
|
||||
__FILE__ , ## arg)
|
||||
|
||||
#ifdef CONFIG_HID_DEBUG
|
||||
#define dbg_hid(format, arg...) if (hid_debug) \
|
||||
printk(KERN_DEBUG "%s: " format ,\
|
||||
__FILE__ , ## arg)
|
||||
#define dbg_hid_line(format, arg...) if (hid_debug) \
|
||||
printk(format, ## arg)
|
||||
#else
|
||||
#define dbg(format, arg...) do {} while (0)
|
||||
#define dbg_hid(format, arg...) do {} while (0)
|
||||
#define dbg_hid_line dbg_hid
|
||||
#endif
|
||||
|
||||
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
|
||||
#define err_hid(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
|
||||
__FILE__ , ## arg)
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user