Loading drivers/hid/hid-input.c +77 −0 Original line number Diff line number Diff line Loading @@ -1198,6 +1198,67 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid) return hidinput; } static bool hidinput_has_been_populated(struct hid_input *hidinput) { int i; unsigned long r = 0; for (i = 0; i < BITS_TO_LONGS(EV_CNT); i++) r |= hidinput->input->evbit[i]; for (i = 0; i < BITS_TO_LONGS(KEY_CNT); i++) r |= hidinput->input->keybit[i]; for (i = 0; i < BITS_TO_LONGS(REL_CNT); i++) r |= hidinput->input->relbit[i]; for (i = 0; i < BITS_TO_LONGS(ABS_CNT); i++) r |= hidinput->input->absbit[i]; for (i = 0; i < BITS_TO_LONGS(MSC_CNT); i++) r |= hidinput->input->mscbit[i]; for (i = 0; i < BITS_TO_LONGS(LED_CNT); i++) r |= hidinput->input->ledbit[i]; for (i = 0; i < BITS_TO_LONGS(SND_CNT); i++) r |= hidinput->input->sndbit[i]; for (i = 0; i < BITS_TO_LONGS(FF_CNT); i++) r |= hidinput->input->ffbit[i]; for (i = 0; i < BITS_TO_LONGS(SW_CNT); i++) r |= hidinput->input->swbit[i]; return !!r; } static void hidinput_cleanup_hidinput(struct hid_device *hid, struct hid_input *hidinput) { struct hid_report *report; int i, k; list_del(&hidinput->list); input_free_device(hidinput->input); for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { if (k == HID_OUTPUT_REPORT && hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS) continue; list_for_each_entry(report, &hid->report_enum[k].report_list, list) { for (i = 0; i < report->maxfield; i++) if (report->field[i]->hidinput == hidinput) report->field[i]->hidinput = NULL; } } kfree(hidinput); } /* * Register the input device; print a message. * Configure the input layer interface Loading Loading @@ -1249,6 +1310,10 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) hidinput_configure_usage(hidinput, report->field[i], report->field[i]->usage + j); if ((hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) && !hidinput_has_been_populated(hidinput)) continue; if (hid->quirks & HID_QUIRK_MULTI_INPUT) { /* This will leave hidinput NULL, so that it * allocates another one if we have more inputs on Loading @@ -1265,6 +1330,18 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) } } if (hidinput && (hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) && !hidinput_has_been_populated(hidinput)) { /* no need to register an input device not populated */ hidinput_cleanup_hidinput(hid, hidinput); hidinput = NULL; } if (list_empty(&hid->inputs)) { hid_err(hid, "No inputs registered, leaving\n"); goto out_unwind; } if (hidinput) { if (drv->input_configured) drv->input_configured(hid, hidinput); Loading drivers/hid/hid-multitouch.c +177 −60 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ #include <linux/slab.h> #include <linux/usb.h> #include <linux/input/mt.h> #include <linux/string.h> MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); Loading Loading @@ -97,9 +98,9 @@ struct mt_device { multitouch fields */ int cc_index; /* contact count field index in the report */ int cc_value_index; /* contact count value index in the field */ unsigned last_field_index; /* last field index of the report */ unsigned last_slot_field; /* the last field of a slot */ unsigned mt_report_id; /* the report ID of the multitouch device */ unsigned pen_report_id; /* the report ID of the pen device */ __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ __s8 inputmode_index; /* InputMode HID feature index in the report */ __s8 maxcontact_report_id; /* Maximum Contact Number HID feature, Loading @@ -115,6 +116,9 @@ struct mt_device { unsigned mt_flags; /* flags to pass to input-mt */ }; static void mt_post_parse_default_settings(struct mt_device *td); static void mt_post_parse(struct mt_device *td); /* classes of device behavior */ #define MT_CLS_DEFAULT 0x0001 Loading Loading @@ -257,6 +261,14 @@ static struct mt_class mt_classes[] = { { } }; static void mt_free_input_name(struct hid_input *hi) { struct hid_device *hdev = hi->report->device; if (hi->input->name != hdev->name) kfree(hi->input->name); } static ssize_t mt_show_quirks(struct device *dev, struct device_attribute *attr, char *buf) Loading Loading @@ -365,7 +377,53 @@ static void mt_store_field(struct hid_usage *usage, struct mt_device *td, f->usages[f->length++] = usage->hid; } static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, static int mt_pen_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { struct mt_device *td = hid_get_drvdata(hdev); td->pen_report_id = field->report->id; return 0; } static int mt_pen_input_mapped(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { return 0; } static int mt_pen_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { /* let hid-input handle it */ return 0; } static void mt_pen_report(struct hid_device *hid, struct hid_report *report) { struct hid_field *field = report->field[0]; input_sync(field->hidinput->input); } static void mt_pen_input_configured(struct hid_device *hdev, struct hid_input *hi) { char *name = kzalloc(strlen(hi->input->name) + 5, GFP_KERNEL); if (name) { sprintf(name, "%s Pen", hi->input->name); mt_free_input_name(hi); hi->input->name = name; } /* force BTN_STYLUS to allow tablet matching in udev */ __set_bit(BTN_STYLUS, hi->input->keybit); } static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { Loading @@ -374,13 +432,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, int code; struct hid_usage *prev_usage = NULL; /* Only map fields from TouchScreen or TouchPad collections. * We need to ignore fields that belong to other collections * such as Mouse that might have the same GenericDesktop usages. */ if (field->application == HID_DG_TOUCHSCREEN) td->mt_flags |= INPUT_MT_DIRECT; else if (field->application != HID_DG_TOUCHPAD) return 0; /* * Model touchscreens providing buttons as touchpads. Loading @@ -389,12 +442,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) td->mt_flags |= INPUT_MT_POINTER; /* eGalax devices provide a Digitizer.Stylus input which overrides * the correct Digitizers.Finger X/Y ranges. * Let's just ignore this input. */ if (field->physical == HID_DG_STYLUS) return -1; if (usage->usage_index) prev_usage = &field->usage[usage->usage_index - 1]; Loading @@ -416,7 +463,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, } mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_GD_Y: if (prev_usage && (prev_usage->hid == usage->hid)) { Loading @@ -432,7 +478,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, } mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; } return 0; Loading @@ -447,21 +492,17 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, ABS_MT_DISTANCE, 0, 1, 0, 0); } mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_CONFIDENCE: mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_TIPSWITCH: hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); input_set_capability(hi->input, EV_KEY, BTN_TOUCH); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_CONTACTID: mt_store_field(usage, td, hi); td->last_field_index = field->index; td->touches_by_report++; td->mt_report_id = field->report->id; return 1; Loading @@ -472,7 +513,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, cls->sn_width); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_HEIGHT: hid_map_usage(hi, usage, bit, max, Loading @@ -484,7 +524,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, ABS_MT_ORIENTATION, 0, 1, 0, 0); } mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_TIPPRESSURE: hid_map_usage(hi, usage, bit, max, Loading @@ -492,17 +531,14 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, set_abs(hi->input, ABS_MT_PRESSURE, field, cls->sn_pressure); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_CONTACTCOUNT: td->cc_index = field->index; td->cc_value_index = usage->usage_index; td->last_field_index = field->index; return 1; case HID_DG_CONTACTMAX: /* we don't set td->last_slot_field as contactcount and * contact max are global to the report */ td->last_field_index = field->index; return -1; case HID_DG_TOUCH: /* Legacy devices use TIPSWITCH and not TOUCH. Loading @@ -526,7 +562,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, return 0; } static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, static int mt_touch_input_mapped(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { Loading Loading @@ -617,7 +653,7 @@ static void mt_sync_frame(struct mt_device *td, struct input_dev *input) td->num_received = 0; } static int mt_event(struct hid_device *hid, struct hid_field *field, static int mt_touch_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { /* we will handle the hidinput part later, now remains hiddev */ Loading Loading @@ -691,29 +727,19 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field, if (usage->usage_index + 1 == field->report_count) { /* we only take into account the last report. */ if (usage->hid == td->last_slot_field) mt_complete_slot(td, input); if (field->index == td->last_field_index && td->num_received >= td->num_expected) mt_sync_frame(td, field->hidinput->input); mt_complete_slot(td, field->hidinput->input); } } } static void mt_report(struct hid_device *hid, struct hid_report *report) static void mt_touch_report(struct hid_device *hid, struct hid_report *report) { struct mt_device *td = hid_get_drvdata(hid); struct hid_field *field; unsigned count; int r, n; if (report->id != td->mt_report_id) return; if (!(hid->claimed & HID_CLAIMED_INPUT)) return; /* * Includes multi-packet support where subsequent * packets are sent with zero contactcount. Loading @@ -736,6 +762,91 @@ static void mt_report(struct hid_device *hid, struct hid_report *report) mt_process_mt_event(hid, field, &field->usage[n], field->value[n]); } if (td->num_received >= td->num_expected) mt_sync_frame(td, report->field[0]->hidinput->input); } static void mt_touch_input_configured(struct hid_device *hdev, struct hid_input *hi) { struct mt_device *td = hid_get_drvdata(hdev); struct mt_class *cls = &td->mtclass; struct input_dev *input = hi->input; if (!td->maxcontacts) td->maxcontacts = MT_DEFAULT_MAXCONTACT; mt_post_parse(td); if (td->serial_maybe) mt_post_parse_default_settings(td); if (cls->is_indirect) td->mt_flags |= INPUT_MT_POINTER; if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) td->mt_flags |= INPUT_MT_DROP_UNUSED; input_mt_init_slots(input, td->maxcontacts, td->mt_flags); td->mt_flags = 0; } static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { /* Only map fields from TouchScreen or TouchPad collections. * We need to ignore fields that belong to other collections * such as Mouse that might have the same GenericDesktop usages. */ if (field->application != HID_DG_TOUCHSCREEN && field->application != HID_DG_PEN && field->application != HID_DG_TOUCHPAD) return -1; if (field->physical == HID_DG_STYLUS) return mt_pen_input_mapping(hdev, hi, field, usage, bit, max); return mt_touch_input_mapping(hdev, hi, field, usage, bit, max); } static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { if (field->physical == HID_DG_STYLUS) return mt_pen_input_mapped(hdev, hi, field, usage, bit, max); return mt_touch_input_mapped(hdev, hi, field, usage, bit, max); } static int mt_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { struct mt_device *td = hid_get_drvdata(hid); if (field->report->id == td->mt_report_id) return mt_touch_event(hid, field, usage, value); if (field->report->id == td->pen_report_id) return mt_pen_event(hid, field, usage, value); /* ignore other reports */ return 1; } static void mt_report(struct hid_device *hid, struct hid_report *report) { struct mt_device *td = hid_get_drvdata(hid); if (!(hid->claimed & HID_CLAIMED_INPUT)) return; if (report->id == td->mt_report_id) mt_touch_report(hid, report); if (report->id == td->pen_report_id) mt_pen_report(hid, report); } static void mt_set_input_mode(struct hid_device *hdev) Loading Loading @@ -812,32 +923,18 @@ static void mt_post_parse(struct mt_device *td) } static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi) { struct mt_device *td = hid_get_drvdata(hdev); struct mt_class *cls = &td->mtclass; struct input_dev *input = hi->input; /* Only initialize slots for MT input devices */ if (!test_bit(ABS_MT_POSITION_X, input->absbit)) return; if (!td->maxcontacts) td->maxcontacts = MT_DEFAULT_MAXCONTACT; char *name = kstrdup(hdev->name, GFP_KERNEL); mt_post_parse(td); if (td->serial_maybe) mt_post_parse_default_settings(td); if (cls->is_indirect) td->mt_flags |= INPUT_MT_POINTER; if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) td->mt_flags |= INPUT_MT_DROP_UNUSED; if (name) hi->input->name = name; input_mt_init_slots(input, td->maxcontacts, td->mt_flags); if (hi->report->id == td->mt_report_id) mt_touch_input_configured(hdev, hi); td->mt_flags = 0; if (hi->report->id == td->pen_report_id) mt_pen_input_configured(hdev, hi); } static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) Loading @@ -845,6 +942,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) int ret, i; struct mt_device *td; struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */ struct hid_input *hi; for (i = 0; mt_classes[i].name ; i++) { if (id->driver_data == mt_classes[i].name) { Loading @@ -858,6 +956,14 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) */ hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; /* * This allows the driver to handle different input sensors * that emits events through different reports on the same HID * device. */ hdev->quirks |= HID_QUIRK_MULTI_INPUT; hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT; td = kzalloc(sizeof(struct mt_device), GFP_KERNEL); if (!td) { dev_err(&hdev->dev, "cannot allocate multitouch data\n"); Loading @@ -867,6 +973,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) td->inputmode = -1; td->maxcontact_report_id = -1; td->cc_index = -1; td->mt_report_id = -1; td->pen_report_id = -1; hid_set_drvdata(hdev, td); td->fields = kzalloc(sizeof(struct mt_fields), GFP_KERNEL); Loading @@ -885,7 +993,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); if (ret) goto fail; goto hid_fail; ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group); Loading @@ -897,6 +1005,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) return 0; hid_fail: list_for_each_entry(hi, &hdev->inputs, list) mt_free_input_name(hi); fail: kfree(td->fields); kfree(td); Loading Loading @@ -926,8 +1037,14 @@ static int mt_resume(struct hid_device *hdev) static void mt_remove(struct hid_device *hdev) { struct mt_device *td = hid_get_drvdata(hdev); struct hid_input *hi; sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group); hid_hw_stop(hdev); list_for_each_entry(hi, &hdev->inputs, list) mt_free_input_name(hi); kfree(td); hid_set_drvdata(hdev, NULL); } Loading include/linux/hid.h +1 −0 Original line number Diff line number Diff line Loading @@ -282,6 +282,7 @@ struct hid_item { #define HID_QUIRK_BADPAD 0x00000020 #define HID_QUIRK_MULTI_INPUT 0x00000040 #define HID_QUIRK_HIDINPUT_FORCE 0x00000080 #define HID_QUIRK_NO_EMPTY_INPUT 0x00000100 #define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 #define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000 #define HID_QUIRK_NO_INIT_REPORTS 0x20000000 Loading Loading
drivers/hid/hid-input.c +77 −0 Original line number Diff line number Diff line Loading @@ -1198,6 +1198,67 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid) return hidinput; } static bool hidinput_has_been_populated(struct hid_input *hidinput) { int i; unsigned long r = 0; for (i = 0; i < BITS_TO_LONGS(EV_CNT); i++) r |= hidinput->input->evbit[i]; for (i = 0; i < BITS_TO_LONGS(KEY_CNT); i++) r |= hidinput->input->keybit[i]; for (i = 0; i < BITS_TO_LONGS(REL_CNT); i++) r |= hidinput->input->relbit[i]; for (i = 0; i < BITS_TO_LONGS(ABS_CNT); i++) r |= hidinput->input->absbit[i]; for (i = 0; i < BITS_TO_LONGS(MSC_CNT); i++) r |= hidinput->input->mscbit[i]; for (i = 0; i < BITS_TO_LONGS(LED_CNT); i++) r |= hidinput->input->ledbit[i]; for (i = 0; i < BITS_TO_LONGS(SND_CNT); i++) r |= hidinput->input->sndbit[i]; for (i = 0; i < BITS_TO_LONGS(FF_CNT); i++) r |= hidinput->input->ffbit[i]; for (i = 0; i < BITS_TO_LONGS(SW_CNT); i++) r |= hidinput->input->swbit[i]; return !!r; } static void hidinput_cleanup_hidinput(struct hid_device *hid, struct hid_input *hidinput) { struct hid_report *report; int i, k; list_del(&hidinput->list); input_free_device(hidinput->input); for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { if (k == HID_OUTPUT_REPORT && hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS) continue; list_for_each_entry(report, &hid->report_enum[k].report_list, list) { for (i = 0; i < report->maxfield; i++) if (report->field[i]->hidinput == hidinput) report->field[i]->hidinput = NULL; } } kfree(hidinput); } /* * Register the input device; print a message. * Configure the input layer interface Loading Loading @@ -1249,6 +1310,10 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) hidinput_configure_usage(hidinput, report->field[i], report->field[i]->usage + j); if ((hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) && !hidinput_has_been_populated(hidinput)) continue; if (hid->quirks & HID_QUIRK_MULTI_INPUT) { /* This will leave hidinput NULL, so that it * allocates another one if we have more inputs on Loading @@ -1265,6 +1330,18 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) } } if (hidinput && (hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) && !hidinput_has_been_populated(hidinput)) { /* no need to register an input device not populated */ hidinput_cleanup_hidinput(hid, hidinput); hidinput = NULL; } if (list_empty(&hid->inputs)) { hid_err(hid, "No inputs registered, leaving\n"); goto out_unwind; } if (hidinput) { if (drv->input_configured) drv->input_configured(hid, hidinput); Loading
drivers/hid/hid-multitouch.c +177 −60 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ #include <linux/slab.h> #include <linux/usb.h> #include <linux/input/mt.h> #include <linux/string.h> MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); Loading Loading @@ -97,9 +98,9 @@ struct mt_device { multitouch fields */ int cc_index; /* contact count field index in the report */ int cc_value_index; /* contact count value index in the field */ unsigned last_field_index; /* last field index of the report */ unsigned last_slot_field; /* the last field of a slot */ unsigned mt_report_id; /* the report ID of the multitouch device */ unsigned pen_report_id; /* the report ID of the pen device */ __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ __s8 inputmode_index; /* InputMode HID feature index in the report */ __s8 maxcontact_report_id; /* Maximum Contact Number HID feature, Loading @@ -115,6 +116,9 @@ struct mt_device { unsigned mt_flags; /* flags to pass to input-mt */ }; static void mt_post_parse_default_settings(struct mt_device *td); static void mt_post_parse(struct mt_device *td); /* classes of device behavior */ #define MT_CLS_DEFAULT 0x0001 Loading Loading @@ -257,6 +261,14 @@ static struct mt_class mt_classes[] = { { } }; static void mt_free_input_name(struct hid_input *hi) { struct hid_device *hdev = hi->report->device; if (hi->input->name != hdev->name) kfree(hi->input->name); } static ssize_t mt_show_quirks(struct device *dev, struct device_attribute *attr, char *buf) Loading Loading @@ -365,7 +377,53 @@ static void mt_store_field(struct hid_usage *usage, struct mt_device *td, f->usages[f->length++] = usage->hid; } static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, static int mt_pen_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { struct mt_device *td = hid_get_drvdata(hdev); td->pen_report_id = field->report->id; return 0; } static int mt_pen_input_mapped(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { return 0; } static int mt_pen_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { /* let hid-input handle it */ return 0; } static void mt_pen_report(struct hid_device *hid, struct hid_report *report) { struct hid_field *field = report->field[0]; input_sync(field->hidinput->input); } static void mt_pen_input_configured(struct hid_device *hdev, struct hid_input *hi) { char *name = kzalloc(strlen(hi->input->name) + 5, GFP_KERNEL); if (name) { sprintf(name, "%s Pen", hi->input->name); mt_free_input_name(hi); hi->input->name = name; } /* force BTN_STYLUS to allow tablet matching in udev */ __set_bit(BTN_STYLUS, hi->input->keybit); } static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { Loading @@ -374,13 +432,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, int code; struct hid_usage *prev_usage = NULL; /* Only map fields from TouchScreen or TouchPad collections. * We need to ignore fields that belong to other collections * such as Mouse that might have the same GenericDesktop usages. */ if (field->application == HID_DG_TOUCHSCREEN) td->mt_flags |= INPUT_MT_DIRECT; else if (field->application != HID_DG_TOUCHPAD) return 0; /* * Model touchscreens providing buttons as touchpads. Loading @@ -389,12 +442,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) td->mt_flags |= INPUT_MT_POINTER; /* eGalax devices provide a Digitizer.Stylus input which overrides * the correct Digitizers.Finger X/Y ranges. * Let's just ignore this input. */ if (field->physical == HID_DG_STYLUS) return -1; if (usage->usage_index) prev_usage = &field->usage[usage->usage_index - 1]; Loading @@ -416,7 +463,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, } mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_GD_Y: if (prev_usage && (prev_usage->hid == usage->hid)) { Loading @@ -432,7 +478,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, } mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; } return 0; Loading @@ -447,21 +492,17 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, ABS_MT_DISTANCE, 0, 1, 0, 0); } mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_CONFIDENCE: mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_TIPSWITCH: hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); input_set_capability(hi->input, EV_KEY, BTN_TOUCH); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_CONTACTID: mt_store_field(usage, td, hi); td->last_field_index = field->index; td->touches_by_report++; td->mt_report_id = field->report->id; return 1; Loading @@ -472,7 +513,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, cls->sn_width); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_HEIGHT: hid_map_usage(hi, usage, bit, max, Loading @@ -484,7 +524,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, ABS_MT_ORIENTATION, 0, 1, 0, 0); } mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_TIPPRESSURE: hid_map_usage(hi, usage, bit, max, Loading @@ -492,17 +531,14 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, set_abs(hi->input, ABS_MT_PRESSURE, field, cls->sn_pressure); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_CONTACTCOUNT: td->cc_index = field->index; td->cc_value_index = usage->usage_index; td->last_field_index = field->index; return 1; case HID_DG_CONTACTMAX: /* we don't set td->last_slot_field as contactcount and * contact max are global to the report */ td->last_field_index = field->index; return -1; case HID_DG_TOUCH: /* Legacy devices use TIPSWITCH and not TOUCH. Loading @@ -526,7 +562,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, return 0; } static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, static int mt_touch_input_mapped(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { Loading Loading @@ -617,7 +653,7 @@ static void mt_sync_frame(struct mt_device *td, struct input_dev *input) td->num_received = 0; } static int mt_event(struct hid_device *hid, struct hid_field *field, static int mt_touch_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { /* we will handle the hidinput part later, now remains hiddev */ Loading Loading @@ -691,29 +727,19 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field, if (usage->usage_index + 1 == field->report_count) { /* we only take into account the last report. */ if (usage->hid == td->last_slot_field) mt_complete_slot(td, input); if (field->index == td->last_field_index && td->num_received >= td->num_expected) mt_sync_frame(td, field->hidinput->input); mt_complete_slot(td, field->hidinput->input); } } } static void mt_report(struct hid_device *hid, struct hid_report *report) static void mt_touch_report(struct hid_device *hid, struct hid_report *report) { struct mt_device *td = hid_get_drvdata(hid); struct hid_field *field; unsigned count; int r, n; if (report->id != td->mt_report_id) return; if (!(hid->claimed & HID_CLAIMED_INPUT)) return; /* * Includes multi-packet support where subsequent * packets are sent with zero contactcount. Loading @@ -736,6 +762,91 @@ static void mt_report(struct hid_device *hid, struct hid_report *report) mt_process_mt_event(hid, field, &field->usage[n], field->value[n]); } if (td->num_received >= td->num_expected) mt_sync_frame(td, report->field[0]->hidinput->input); } static void mt_touch_input_configured(struct hid_device *hdev, struct hid_input *hi) { struct mt_device *td = hid_get_drvdata(hdev); struct mt_class *cls = &td->mtclass; struct input_dev *input = hi->input; if (!td->maxcontacts) td->maxcontacts = MT_DEFAULT_MAXCONTACT; mt_post_parse(td); if (td->serial_maybe) mt_post_parse_default_settings(td); if (cls->is_indirect) td->mt_flags |= INPUT_MT_POINTER; if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) td->mt_flags |= INPUT_MT_DROP_UNUSED; input_mt_init_slots(input, td->maxcontacts, td->mt_flags); td->mt_flags = 0; } static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { /* Only map fields from TouchScreen or TouchPad collections. * We need to ignore fields that belong to other collections * such as Mouse that might have the same GenericDesktop usages. */ if (field->application != HID_DG_TOUCHSCREEN && field->application != HID_DG_PEN && field->application != HID_DG_TOUCHPAD) return -1; if (field->physical == HID_DG_STYLUS) return mt_pen_input_mapping(hdev, hi, field, usage, bit, max); return mt_touch_input_mapping(hdev, hi, field, usage, bit, max); } static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { if (field->physical == HID_DG_STYLUS) return mt_pen_input_mapped(hdev, hi, field, usage, bit, max); return mt_touch_input_mapped(hdev, hi, field, usage, bit, max); } static int mt_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { struct mt_device *td = hid_get_drvdata(hid); if (field->report->id == td->mt_report_id) return mt_touch_event(hid, field, usage, value); if (field->report->id == td->pen_report_id) return mt_pen_event(hid, field, usage, value); /* ignore other reports */ return 1; } static void mt_report(struct hid_device *hid, struct hid_report *report) { struct mt_device *td = hid_get_drvdata(hid); if (!(hid->claimed & HID_CLAIMED_INPUT)) return; if (report->id == td->mt_report_id) mt_touch_report(hid, report); if (report->id == td->pen_report_id) mt_pen_report(hid, report); } static void mt_set_input_mode(struct hid_device *hdev) Loading Loading @@ -812,32 +923,18 @@ static void mt_post_parse(struct mt_device *td) } static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi) { struct mt_device *td = hid_get_drvdata(hdev); struct mt_class *cls = &td->mtclass; struct input_dev *input = hi->input; /* Only initialize slots for MT input devices */ if (!test_bit(ABS_MT_POSITION_X, input->absbit)) return; if (!td->maxcontacts) td->maxcontacts = MT_DEFAULT_MAXCONTACT; char *name = kstrdup(hdev->name, GFP_KERNEL); mt_post_parse(td); if (td->serial_maybe) mt_post_parse_default_settings(td); if (cls->is_indirect) td->mt_flags |= INPUT_MT_POINTER; if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) td->mt_flags |= INPUT_MT_DROP_UNUSED; if (name) hi->input->name = name; input_mt_init_slots(input, td->maxcontacts, td->mt_flags); if (hi->report->id == td->mt_report_id) mt_touch_input_configured(hdev, hi); td->mt_flags = 0; if (hi->report->id == td->pen_report_id) mt_pen_input_configured(hdev, hi); } static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) Loading @@ -845,6 +942,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) int ret, i; struct mt_device *td; struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */ struct hid_input *hi; for (i = 0; mt_classes[i].name ; i++) { if (id->driver_data == mt_classes[i].name) { Loading @@ -858,6 +956,14 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) */ hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; /* * This allows the driver to handle different input sensors * that emits events through different reports on the same HID * device. */ hdev->quirks |= HID_QUIRK_MULTI_INPUT; hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT; td = kzalloc(sizeof(struct mt_device), GFP_KERNEL); if (!td) { dev_err(&hdev->dev, "cannot allocate multitouch data\n"); Loading @@ -867,6 +973,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) td->inputmode = -1; td->maxcontact_report_id = -1; td->cc_index = -1; td->mt_report_id = -1; td->pen_report_id = -1; hid_set_drvdata(hdev, td); td->fields = kzalloc(sizeof(struct mt_fields), GFP_KERNEL); Loading @@ -885,7 +993,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); if (ret) goto fail; goto hid_fail; ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group); Loading @@ -897,6 +1005,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) return 0; hid_fail: list_for_each_entry(hi, &hdev->inputs, list) mt_free_input_name(hi); fail: kfree(td->fields); kfree(td); Loading Loading @@ -926,8 +1037,14 @@ static int mt_resume(struct hid_device *hdev) static void mt_remove(struct hid_device *hdev) { struct mt_device *td = hid_get_drvdata(hdev); struct hid_input *hi; sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group); hid_hw_stop(hdev); list_for_each_entry(hi, &hdev->inputs, list) mt_free_input_name(hi); kfree(td); hid_set_drvdata(hdev, NULL); } Loading
include/linux/hid.h +1 −0 Original line number Diff line number Diff line Loading @@ -282,6 +282,7 @@ struct hid_item { #define HID_QUIRK_BADPAD 0x00000020 #define HID_QUIRK_MULTI_INPUT 0x00000040 #define HID_QUIRK_HIDINPUT_FORCE 0x00000080 #define HID_QUIRK_NO_EMPTY_INPUT 0x00000100 #define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 #define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000 #define HID_QUIRK_NO_INIT_REPORTS 0x20000000 Loading