Loading drivers/hid/hid-core.c +13 −6 Original line number Diff line number Diff line Loading @@ -57,7 +57,9 @@ MODULE_PARM_DESC(ignore_special_drivers, "Ignore any special drivers and handle * Register a new report for a device. */ struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id) struct hid_report *hid_register_report(struct hid_device *device, unsigned int type, unsigned int id, unsigned int application) { struct hid_report_enum *report_enum = device->report_enum + type; struct hid_report *report; Loading @@ -78,6 +80,7 @@ struct hid_report *hid_register_report(struct hid_device *device, unsigned type, report->type = type; report->size = 0; report->device = device; report->application = application; report_enum->report_id_hash[id] = report; list_add_tail(&report->list, &report_enum->report_list); Loading Loading @@ -221,11 +224,15 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign { struct hid_report *report; struct hid_field *field; unsigned usages; unsigned offset; unsigned i; unsigned int usages; unsigned int offset; unsigned int i; unsigned int application; application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); report = hid_register_report(parser->device, report_type, parser->global.report_id); report = hid_register_report(parser->device, report_type, parser->global.report_id, application); if (!report) { hid_err(parser->device, "hid_register_report failed\n"); return -1; Loading Loading @@ -259,7 +266,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL); field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL); field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); field->application = application; for (i = 0; i < usages; i++) { unsigned j = i; Loading drivers/hid/hid-generic.c +15 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,20 @@ static bool hid_generic_match(struct hid_device *hdev, return true; } static int hid_generic_probe(struct hid_device *hdev, const struct hid_device_id *id) { int ret; hdev->quirks |= HID_QUIRK_INPUT_PER_APP; ret = hid_parse(hdev); if (ret) return ret; return hid_hw_start(hdev, HID_CONNECT_DEFAULT); } static const struct hid_device_id hid_table[] = { { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, HID_ANY_ID, HID_ANY_ID) }, { } Loading @@ -66,6 +80,7 @@ static struct hid_driver hid_generic = { .name = "hid-generic", .id_table = hid_table, .match = hid_generic_match, .probe = hid_generic_probe, }; module_hid_driver(hid_generic); Loading drivers/hid/hid-gfrm.c +1 −1 Original line number Diff line number Diff line Loading @@ -116,7 +116,7 @@ static int gfrm_probe(struct hid_device *hdev, const struct hid_device_id *id) * those reports reach gfrm_raw_event() from hid_input_report(). */ if (!hid_register_report(hdev, HID_INPUT_REPORT, GFRM100_SEARCH_KEY_REPORT_ID)) { GFRM100_SEARCH_KEY_REPORT_ID, 0)) { ret = -ENOMEM; goto done; } Loading drivers/hid/hid-input.c +113 −10 Original line number Diff line number Diff line Loading @@ -1110,8 +1110,31 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel set_bit(usage->type, input->evbit); while (usage->code <= max && test_and_set_bit(usage->code, bit)) usage->code = find_next_zero_bit(bit, max + 1, usage->code); /* * This part is *really* controversial: * - HID aims at being generic so we should do our best to export * all incoming events * - HID describes what events are, so there is no reason for ABS_X * to be mapped to ABS_Y * - HID is using *_MISC+N as a default value, but nothing prevents * *_MISC+N to overwrite a legitimate even, which confuses userspace * (for instance ABS_MISC + 7 is ABS_MT_SLOT, which has a different * processing) * * If devices still want to use this (at their own risk), they will * have to use the quirk HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE, but * the default should be a reliable mapping. */ while (usage->code <= max && test_and_set_bit(usage->code, bit)) { if (device->quirks & HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE) { usage->code = find_next_zero_bit(bit, max + 1, usage->code); } else { device->status |= HID_STAT_DUP_DETECTED; goto ignore; } } if (usage->code > max) goto ignore; Loading Loading @@ -1487,15 +1510,56 @@ static void report_features(struct hid_device *hid) } } static struct hid_input *hidinput_allocate(struct hid_device *hid) static struct hid_input *hidinput_allocate(struct hid_device *hid, unsigned int application) { struct hid_input *hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL); struct input_dev *input_dev = input_allocate_device(); if (!hidinput || !input_dev) { kfree(hidinput); input_free_device(input_dev); hid_err(hid, "Out of memory during hid input probe\n"); return NULL; const char *suffix = NULL; if (!hidinput || !input_dev) goto fail; if ((hid->quirks & HID_QUIRK_INPUT_PER_APP) && hid->maxapplication > 1) { switch (application) { case HID_GD_KEYBOARD: suffix = "Keyboard"; break; case HID_GD_KEYPAD: suffix = "Keypad"; break; case HID_GD_MOUSE: suffix = "Mouse"; break; case HID_DG_STYLUS: suffix = "Pen"; break; case HID_DG_TOUCHSCREEN: suffix = "Touchscreen"; break; case HID_DG_TOUCHPAD: suffix = "Touchpad"; break; case HID_GD_SYSTEM_CONTROL: suffix = "System Control"; break; case HID_CP_CONSUMER_CONTROL: suffix = "Consumer Control"; break; case HID_GD_WIRELESS_RADIO_CTLS: suffix = "Wireless Radio Control"; break; default: break; } } if (suffix) { hidinput->name = kasprintf(GFP_KERNEL, "%s %s", hid->name, suffix); if (!hidinput->name) goto fail; } input_set_drvdata(input_dev, hid); Loading @@ -1505,7 +1569,7 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid) input_dev->setkeycode = hidinput_setkeycode; input_dev->getkeycode = hidinput_getkeycode; input_dev->name = hid->name; input_dev->name = hidinput->name ? hidinput->name : hid->name; input_dev->phys = hid->phys; input_dev->uniq = hid->uniq; input_dev->id.bustype = hid->bus; Loading @@ -1513,10 +1577,19 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid) input_dev->id.product = hid->product; input_dev->id.version = hid->version; input_dev->dev.parent = &hid->dev; hidinput->input = input_dev; list_add_tail(&hidinput->list, &hid->inputs); INIT_LIST_HEAD(&hidinput->reports); return hidinput; fail: kfree(hidinput); input_free_device(input_dev); hid_err(hid, "Out of memory during hid input probe\n"); return NULL; } static bool hidinput_has_been_populated(struct hid_input *hidinput) Loading Loading @@ -1562,6 +1635,7 @@ static void hidinput_cleanup_hidinput(struct hid_device *hid, list_del(&hidinput->list); input_free_device(hidinput->input); kfree(hidinput->name); for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { if (k == HID_OUTPUT_REPORT && Loading Loading @@ -1594,6 +1668,20 @@ static struct hid_input *hidinput_match(struct hid_report *report) return NULL; } static struct hid_input *hidinput_match_application(struct hid_report *report) { struct hid_device *hid = report->device; struct hid_input *hidinput; list_for_each_entry(hidinput, &hid->inputs, list) { if (hidinput->report && hidinput->report->application == report->application) return hidinput; } return NULL; } static inline void hidinput_configure_usages(struct hid_input *hidinput, struct hid_report *report) { Loading @@ -1616,11 +1704,14 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) struct hid_driver *drv = hid->driver; struct hid_report *report; struct hid_input *next, *hidinput = NULL; unsigned int application; int i, k; INIT_LIST_HEAD(&hid->inputs); INIT_WORK(&hid->led_work, hidinput_led_worker); hid->status &= ~HID_STAT_DUP_DETECTED; if (!force) { for (i = 0; i < hid->maxcollection; i++) { struct hid_collection *col = &hid->collection[i]; Loading @@ -1646,15 +1737,20 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) if (!report->maxfield) continue; application = report->application; /* * Find the previous hidinput report attached * to this report id. */ if (hid->quirks & HID_QUIRK_MULTI_INPUT) hidinput = hidinput_match(report); else if (hid->maxapplication > 1 && (hid->quirks & HID_QUIRK_INPUT_PER_APP)) hidinput = hidinput_match_application(report); if (!hidinput) { hidinput = hidinput_allocate(hid); hidinput = hidinput_allocate(hid, application); if (!hidinput) goto out_unwind; } Loading @@ -1663,6 +1759,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) if (hid->quirks & HID_QUIRK_MULTI_INPUT) hidinput->report = report; list_add_tail(&report->hidinput_list, &hidinput->reports); } } Loading @@ -1687,6 +1786,10 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) goto out_unwind; } if (hid->status & HID_STAT_DUP_DETECTED) hid_dbg(hid, "Some usages could not be mapped, please use HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE if this is legitimate.\n"); return 0; out_unwind: Loading drivers/hid/hid-magicmouse.c +3 −3 Original line number Diff line number Diff line Loading @@ -531,12 +531,12 @@ static int magicmouse_probe(struct hid_device *hdev, if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE) report = hid_register_report(hdev, HID_INPUT_REPORT, MOUSE_REPORT_ID); MOUSE_REPORT_ID, 0); else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ report = hid_register_report(hdev, HID_INPUT_REPORT, TRACKPAD_REPORT_ID); TRACKPAD_REPORT_ID, 0); report = hid_register_report(hdev, HID_INPUT_REPORT, DOUBLE_REPORT_ID); DOUBLE_REPORT_ID, 0); } if (!report) { Loading Loading
drivers/hid/hid-core.c +13 −6 Original line number Diff line number Diff line Loading @@ -57,7 +57,9 @@ MODULE_PARM_DESC(ignore_special_drivers, "Ignore any special drivers and handle * Register a new report for a device. */ struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id) struct hid_report *hid_register_report(struct hid_device *device, unsigned int type, unsigned int id, unsigned int application) { struct hid_report_enum *report_enum = device->report_enum + type; struct hid_report *report; Loading @@ -78,6 +80,7 @@ struct hid_report *hid_register_report(struct hid_device *device, unsigned type, report->type = type; report->size = 0; report->device = device; report->application = application; report_enum->report_id_hash[id] = report; list_add_tail(&report->list, &report_enum->report_list); Loading Loading @@ -221,11 +224,15 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign { struct hid_report *report; struct hid_field *field; unsigned usages; unsigned offset; unsigned i; unsigned int usages; unsigned int offset; unsigned int i; unsigned int application; application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); report = hid_register_report(parser->device, report_type, parser->global.report_id); report = hid_register_report(parser->device, report_type, parser->global.report_id, application); if (!report) { hid_err(parser->device, "hid_register_report failed\n"); return -1; Loading Loading @@ -259,7 +266,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL); field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL); field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); field->application = application; for (i = 0; i < usages; i++) { unsigned j = i; Loading
drivers/hid/hid-generic.c +15 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,20 @@ static bool hid_generic_match(struct hid_device *hdev, return true; } static int hid_generic_probe(struct hid_device *hdev, const struct hid_device_id *id) { int ret; hdev->quirks |= HID_QUIRK_INPUT_PER_APP; ret = hid_parse(hdev); if (ret) return ret; return hid_hw_start(hdev, HID_CONNECT_DEFAULT); } static const struct hid_device_id hid_table[] = { { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, HID_ANY_ID, HID_ANY_ID) }, { } Loading @@ -66,6 +80,7 @@ static struct hid_driver hid_generic = { .name = "hid-generic", .id_table = hid_table, .match = hid_generic_match, .probe = hid_generic_probe, }; module_hid_driver(hid_generic); Loading
drivers/hid/hid-gfrm.c +1 −1 Original line number Diff line number Diff line Loading @@ -116,7 +116,7 @@ static int gfrm_probe(struct hid_device *hdev, const struct hid_device_id *id) * those reports reach gfrm_raw_event() from hid_input_report(). */ if (!hid_register_report(hdev, HID_INPUT_REPORT, GFRM100_SEARCH_KEY_REPORT_ID)) { GFRM100_SEARCH_KEY_REPORT_ID, 0)) { ret = -ENOMEM; goto done; } Loading
drivers/hid/hid-input.c +113 −10 Original line number Diff line number Diff line Loading @@ -1110,8 +1110,31 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel set_bit(usage->type, input->evbit); while (usage->code <= max && test_and_set_bit(usage->code, bit)) usage->code = find_next_zero_bit(bit, max + 1, usage->code); /* * This part is *really* controversial: * - HID aims at being generic so we should do our best to export * all incoming events * - HID describes what events are, so there is no reason for ABS_X * to be mapped to ABS_Y * - HID is using *_MISC+N as a default value, but nothing prevents * *_MISC+N to overwrite a legitimate even, which confuses userspace * (for instance ABS_MISC + 7 is ABS_MT_SLOT, which has a different * processing) * * If devices still want to use this (at their own risk), they will * have to use the quirk HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE, but * the default should be a reliable mapping. */ while (usage->code <= max && test_and_set_bit(usage->code, bit)) { if (device->quirks & HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE) { usage->code = find_next_zero_bit(bit, max + 1, usage->code); } else { device->status |= HID_STAT_DUP_DETECTED; goto ignore; } } if (usage->code > max) goto ignore; Loading Loading @@ -1487,15 +1510,56 @@ static void report_features(struct hid_device *hid) } } static struct hid_input *hidinput_allocate(struct hid_device *hid) static struct hid_input *hidinput_allocate(struct hid_device *hid, unsigned int application) { struct hid_input *hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL); struct input_dev *input_dev = input_allocate_device(); if (!hidinput || !input_dev) { kfree(hidinput); input_free_device(input_dev); hid_err(hid, "Out of memory during hid input probe\n"); return NULL; const char *suffix = NULL; if (!hidinput || !input_dev) goto fail; if ((hid->quirks & HID_QUIRK_INPUT_PER_APP) && hid->maxapplication > 1) { switch (application) { case HID_GD_KEYBOARD: suffix = "Keyboard"; break; case HID_GD_KEYPAD: suffix = "Keypad"; break; case HID_GD_MOUSE: suffix = "Mouse"; break; case HID_DG_STYLUS: suffix = "Pen"; break; case HID_DG_TOUCHSCREEN: suffix = "Touchscreen"; break; case HID_DG_TOUCHPAD: suffix = "Touchpad"; break; case HID_GD_SYSTEM_CONTROL: suffix = "System Control"; break; case HID_CP_CONSUMER_CONTROL: suffix = "Consumer Control"; break; case HID_GD_WIRELESS_RADIO_CTLS: suffix = "Wireless Radio Control"; break; default: break; } } if (suffix) { hidinput->name = kasprintf(GFP_KERNEL, "%s %s", hid->name, suffix); if (!hidinput->name) goto fail; } input_set_drvdata(input_dev, hid); Loading @@ -1505,7 +1569,7 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid) input_dev->setkeycode = hidinput_setkeycode; input_dev->getkeycode = hidinput_getkeycode; input_dev->name = hid->name; input_dev->name = hidinput->name ? hidinput->name : hid->name; input_dev->phys = hid->phys; input_dev->uniq = hid->uniq; input_dev->id.bustype = hid->bus; Loading @@ -1513,10 +1577,19 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid) input_dev->id.product = hid->product; input_dev->id.version = hid->version; input_dev->dev.parent = &hid->dev; hidinput->input = input_dev; list_add_tail(&hidinput->list, &hid->inputs); INIT_LIST_HEAD(&hidinput->reports); return hidinput; fail: kfree(hidinput); input_free_device(input_dev); hid_err(hid, "Out of memory during hid input probe\n"); return NULL; } static bool hidinput_has_been_populated(struct hid_input *hidinput) Loading Loading @@ -1562,6 +1635,7 @@ static void hidinput_cleanup_hidinput(struct hid_device *hid, list_del(&hidinput->list); input_free_device(hidinput->input); kfree(hidinput->name); for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { if (k == HID_OUTPUT_REPORT && Loading Loading @@ -1594,6 +1668,20 @@ static struct hid_input *hidinput_match(struct hid_report *report) return NULL; } static struct hid_input *hidinput_match_application(struct hid_report *report) { struct hid_device *hid = report->device; struct hid_input *hidinput; list_for_each_entry(hidinput, &hid->inputs, list) { if (hidinput->report && hidinput->report->application == report->application) return hidinput; } return NULL; } static inline void hidinput_configure_usages(struct hid_input *hidinput, struct hid_report *report) { Loading @@ -1616,11 +1704,14 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) struct hid_driver *drv = hid->driver; struct hid_report *report; struct hid_input *next, *hidinput = NULL; unsigned int application; int i, k; INIT_LIST_HEAD(&hid->inputs); INIT_WORK(&hid->led_work, hidinput_led_worker); hid->status &= ~HID_STAT_DUP_DETECTED; if (!force) { for (i = 0; i < hid->maxcollection; i++) { struct hid_collection *col = &hid->collection[i]; Loading @@ -1646,15 +1737,20 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) if (!report->maxfield) continue; application = report->application; /* * Find the previous hidinput report attached * to this report id. */ if (hid->quirks & HID_QUIRK_MULTI_INPUT) hidinput = hidinput_match(report); else if (hid->maxapplication > 1 && (hid->quirks & HID_QUIRK_INPUT_PER_APP)) hidinput = hidinput_match_application(report); if (!hidinput) { hidinput = hidinput_allocate(hid); hidinput = hidinput_allocate(hid, application); if (!hidinput) goto out_unwind; } Loading @@ -1663,6 +1759,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) if (hid->quirks & HID_QUIRK_MULTI_INPUT) hidinput->report = report; list_add_tail(&report->hidinput_list, &hidinput->reports); } } Loading @@ -1687,6 +1786,10 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) goto out_unwind; } if (hid->status & HID_STAT_DUP_DETECTED) hid_dbg(hid, "Some usages could not be mapped, please use HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE if this is legitimate.\n"); return 0; out_unwind: Loading
drivers/hid/hid-magicmouse.c +3 −3 Original line number Diff line number Diff line Loading @@ -531,12 +531,12 @@ static int magicmouse_probe(struct hid_device *hdev, if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE) report = hid_register_report(hdev, HID_INPUT_REPORT, MOUSE_REPORT_ID); MOUSE_REPORT_ID, 0); else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ report = hid_register_report(hdev, HID_INPUT_REPORT, TRACKPAD_REPORT_ID); TRACKPAD_REPORT_ID, 0); report = hid_register_report(hdev, HID_INPUT_REPORT, DOUBLE_REPORT_ID); DOUBLE_REPORT_ID, 0); } if (!report) { Loading