📄 hid-input.c
字号:
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; case HID_UP_PID: switch(usage->hid & HID_USAGE) { case 0xa4: map_key_clear(BTN_DEAD); break; default: goto ignore; } break; default: unknown: if (field->report_size == 1) { if (field->report->type == HID_OUTPUT_REPORT) { map_led(LED_MISC); break; } map_key(BTN_MISC); break; } if (field->flags & HID_MAIN_ITEM_RELATIVE) { map_rel(REL_MISC); break; } map_abs(ABS_MISC); break; } if (device->quirks & HID_QUIRK_MIGHTYMOUSE) { if (usage->hid == HID_GD_Z) map_rel(REL_HWHEEL); else if (usage->code == BTN_1) map_key(BTN_2); else if (usage->code == BTN_2) map_key(BTN_1); } if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) && (usage->type == EV_REL) && (usage->code == REL_WHEEL)) set_bit(REL_HWHEEL, bit); if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005)) || ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) goto ignore; if ((device->quirks & HID_QUIRK_BAD_RELATIVE_KEYS) && usage->type == EV_KEY && (field->flags & HID_MAIN_ITEM_RELATIVE)) field->flags &= ~HID_MAIN_ITEM_RELATIVE; set_bit(usage->type, input->evbit); if (device->quirks & HID_QUIRK_DUPLICATE_USAGES && (usage->type == EV_KEY || usage->type == EV_REL || usage->type == EV_ABS)) clear_bit(usage->code, bit); while (usage->code <= max && test_and_set_bit(usage->code, bit)) usage->code = find_next_zero_bit(bit, max + 1, usage->code); if (usage->code > max) goto ignore; if (usage->type == EV_ABS) { int a = field->logical_minimum; int b = field->logical_maximum; if ((device->quirks & HID_QUIRK_BADPAD) && (usage->code == ABS_X || usage->code == ABS_Y)) { a = field->logical_minimum = 0; b = field->logical_maximum = 255; } if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK) input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4); else input_set_abs_params(input, usage->code, a, b, 0, 0); } if (usage->type == EV_ABS && (usage->hat_min < usage->hat_max || usage->hat_dir)) { int i; for (i = usage->code; i < usage->code + 2 && i <= max; i++) { input_set_abs_params(input, i, -1, 1, 0, 0); set_bit(i, input->absbit); } if (usage->hat_dir && !field->dpad) 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); } if (usage->type == EV_KEY) { set_bit(EV_MSC, input->evbit); set_bit(MSC_SCAN, input->mscbit); } hid_resolv_event(usage->type, usage->code); dbg_hid_line("\n"); return;ignore: dbg_hid_line("IGNORED\n"); return;}void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value){ struct input_dev *input; unsigned *quirks = &hid->quirks; if (!field->hidinput) return; input = field->hidinput->input; 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; if (usage->hat_min < usage->hat_max || usage->hat_dir) { int hat_dir = usage->hat_dir; if (!hat_dir) hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; if (hat_dir < 0 || hat_dir > 8) hat_dir = 0; input_event(input, usage->type, usage->code , hid_hat_to_axis[hat_dir].x); input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[hat_dir].y); return; } if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */ *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT); return; } if (usage->hid == (HID_UP_DIGITIZER | 0x0032)) { /* InRange */ if (value) { input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1); return; } input_event(input, usage->type, usage->code, 0); input_event(input, usage->type, BTN_TOOL_RUBBER, 0); return; } if (usage->hid == (HID_UP_DIGITIZER | 0x0030) && (*quirks & HID_QUIRK_NOTOUCH)) { /* Pressure */ int a = field->logical_minimum; int b = field->logical_maximum; input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3)); } if (usage->hid == (HID_UP_PID | 0x83UL)) { /* Simultaneous Effects Max */ dbg_hid("Maximum Effects - %d\n",value); return; } if (usage->hid == (HID_UP_PID | 0x7fUL)) { 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; } /* 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); input_event(input, usage->type, usage->code, value); if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY)) input_event(input, usage->type, usage->code, 0);}void hidinput_report_event(struct hid_device *hid, struct hid_report *report){ struct hid_input *hidinput; list_for_each_entry(hidinput, &hid->inputs, list) input_sync(hidinput->input);}EXPORT_SYMBOL_GPL(hidinput_report_event);int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field){ struct hid_report *report; int i, j; list_for_each_entry(report, &hid->report_enum[HID_OUTPUT_REPORT].report_list, list) { for (i = 0; i < report->maxfield; i++) { *field = report->field[i]; for (j = 0; j < (*field)->maxusage; j++) if ((*field)->usage[j].type == type && (*field)->usage[j].code == code) return j; } } return -1;}EXPORT_SYMBOL_GPL(hidinput_find_field);static int hidinput_open(struct input_dev *dev){ struct hid_device *hid = input_get_drvdata(dev); return hid->hid_open(hid);}static void hidinput_close(struct input_dev *dev){ struct hid_device *hid = input_get_drvdata(dev); hid->hid_close(hid);}/* * Register the input device; print a message. * Configure the input layer interface * Read all reports and initialize the absolute field values. */int hidinput_connect(struct hid_device *hid){ struct hid_report *report; struct hid_input *hidinput = NULL; struct input_dev *input_dev; int i, j, k; int max_report_type = HID_OUTPUT_REPORT; if (hid->quirks & HID_QUIRK_IGNORE_HIDINPUT) return -1; INIT_LIST_HEAD(&hid->inputs); for (i = 0; i < hid->maxcollection; i++) if (hid->collection[i].type == HID_COLLECTION_APPLICATION || hid->collection[i].type == HID_COLLECTION_PHYSICAL) if (IS_INPUT_APPLICATION(hid->collection[i].usage)) break; if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDINPUT) == 0) return -1; if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS) max_report_type = HID_INPUT_REPORT; for (k = HID_INPUT_REPORT; k <= max_report_type; k++) list_for_each_entry(report, &hid->report_enum[k].report_list, list) { if (!report->maxfield) continue; if (!hidinput) { hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL); input_dev = input_allocate_device(); if (!hidinput || !input_dev) { kfree(hidinput); input_free_device(input_dev); err_hid("Out of memory during hid input probe"); goto out_unwind; } input_set_drvdata(input_dev, hid); input_dev->event = hid->hidinput_input_event; input_dev->open = hidinput_open; input_dev->close = hidinput_close; input_dev->setkeycode = hidinput_setkeycode; input_dev->getkeycode = hidinput_getkeycode; input_dev->name = hid->name; input_dev->phys = hid->phys; input_dev->uniq = hid->uniq; input_dev->id.bustype = hid->bus; input_dev->id.vendor = hid->vendor; 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); } for (i = 0; i < report->maxfield; i++) for (j = 0; j < report->field[i]->maxusage; j++) hidinput_configure_usage(hidinput, report->field[i], report->field[i]->usage + j); if (hid->quirks & HID_QUIRK_MULTI_INPUT) { /* This will leave hidinput NULL, so that it * allocates another one if we have more inputs on * the same interface. Some devices (e.g. Happ's * UGCI) cram a lot of unrelated inputs into the * same interface. */ hidinput->report = report; if (input_register_device(hidinput->input)) goto out_cleanup; hidinput = NULL; } } if (hidinput && input_register_device(hidinput->input)) goto out_cleanup; return 0;out_cleanup: input_free_device(hidinput->input); kfree(hidinput);out_unwind: /* unwind the ones we already registered */ hidinput_disconnect(hid); return -1;}EXPORT_SYMBOL_GPL(hidinput_connect);void hidinput_disconnect(struct hid_device *hid){ struct hid_input *hidinput, *next; list_for_each_entry_safe(hidinput, next, &hid->inputs, list) { list_del(&hidinput->list); input_unregister_device(hidinput->input); kfree(hidinput); }}EXPORT_SYMBOL_GPL(hidinput_disconnect);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -