📄 hid-input.c
字号:
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: goto ignore; } break; case HID_UP_PID: set_bit(EV_FF, input->evbit); switch(usage->hid & HID_USAGE) { case 0x26: map_ff_effect(FF_CONSTANT); goto ignore; case 0x27: map_ff_effect(FF_RAMP); goto ignore; case 0x28: map_ff_effect(FF_CUSTOM); goto ignore; case 0x30: map_ff_effect(FF_SQUARE); map_ff_effect(FF_PERIODIC); goto ignore; case 0x31: map_ff_effect(FF_SINE); map_ff_effect(FF_PERIODIC); goto ignore; case 0x32: map_ff_effect(FF_TRIANGLE); map_ff_effect(FF_PERIODIC); goto ignore; case 0x33: map_ff_effect(FF_SAW_UP); map_ff_effect(FF_PERIODIC); goto ignore; case 0x34: map_ff_effect(FF_SAW_DOWN); map_ff_effect(FF_PERIODIC); goto ignore; case 0x40: map_ff_effect(FF_SPRING); goto ignore; case 0x41: map_ff_effect(FF_DAMPER); goto ignore; case 0x42: map_ff_effect(FF_INERTIA); goto ignore; case 0x43: map_ff_effect(FF_FRICTION); goto ignore; case 0x7e: map_ff(FF_GAIN); break; case 0x83: input->ff_effects_max = field->value[0]; goto ignore; case 0x98: map_ff(FF_AUTOCENTER); break; 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; } 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); if (usage->code > max) goto ignore; if (((device->quirks & (HID_QUIRK_2WHEEL_POWERMOUSE)) && (usage->hid == 0x00010032))) map_rel(REL_HWHEEL); 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 (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->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; }#ifdef DEBUG resolv_event(usage->type, usage->code); printk("\n");#endif return;ignore:#ifdef DEBUG printk("IGNORED\n");#endif return;}void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, struct pt_regs *regs){ struct input_dev *input; int *quirks = &hid->quirks; if (!field->hidinput) return; input = field->hidinput->input; input_regs(input, regs); 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_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) { input_event(input, usage->type, REL_HWHEEL, 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 */ input->ff_effects_max = value; dbg("Maximum Effects - %d",input->ff_effects_max); return; } if (usage->hid == (HID_UP_PID | 0x7fUL)) { dbg("PID Pool Report\n"); return; } if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */ return; 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);}static 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;}static int hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value){ struct hid_device *hid = dev->private; struct hid_field *field; int offset; if (type == EV_FF) return hid_ff_event(hid, dev, type, code, value); if (type != EV_LED) return -1; if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) { warn("event field not found"); return -1; } hid_set_field(field, offset, value); hid_submit_report(hid, field->report, USB_DIR_OUT); return 0;}static int hidinput_open(struct input_dev *dev){ struct hid_device *hid = dev->private; return hid_open(hid);}static void hidinput_close(struct input_dev *dev){ struct hid_device *hid = dev->private; 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 usb_device *dev = hid->dev; struct hid_report *report; struct hid_input *hidinput = NULL; struct input_dev *input_dev; int i, j, k; 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) return -1; for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; 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("Out of memory during hid input probe"); return -1; } input_dev->private = hid; input_dev->event = hidinput_input_event; input_dev->open = hidinput_open; input_dev->close = hidinput_close; input_dev->name = hid->name; input_dev->phys = hid->phys; input_dev->uniq = hid->uniq; usb_to_input_id(dev, &input_dev->id); input_dev->cdev.dev = &hid->intf->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; input_register_device(hidinput->input); hidinput = NULL; } } /* This only gets called when we are a single-input (most of the * time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is * only useful in this case, and not for multi-input quirks. */ if (hidinput) { hid_ff_init(hid); input_register_device(hidinput->input); } return 0;}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); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -