Loading Documentation/hid/uhid.txt +11 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,11 @@ the request was handled successfully. event to the kernel. The payload is of type struct uhid_create_req and contains information about your device. You can start I/O now. UHID_CREATE2: Same as UHID_CREATE, but the HID report descriptor data (rd_data) is an array inside struct uhid_create2_req, instead of a pointer to a separate array. Enables use from languages that don't support pointers, e.g. Python. UHID_DESTROY: This destroys the internal HID device. No further I/O will be accepted. There may still be pending messages that you can receive with read() but no further Loading @@ -105,6 +110,12 @@ the request was handled successfully. contains a data-payload. This is the raw data that you read from your device. The kernel will parse the HID reports and react on it. UHID_INPUT2: Same as UHID_INPUT, but the data array is the last field of uhid_input2_req. Enables userspace to write only the required bytes to kernel (ev.type + ev.u.input2.size + the part of the data array that matters), instead of the entire struct uhid_input2_req. UHID_FEATURE_ANSWER: If you receive a UHID_FEATURE request you must answer with this request. You must copy the "id" field from the request into the answer. Set the "err" field Loading drivers/hid/hid-ids.h +3 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,9 @@ #define USB_VENDOR_ID_ALPS 0x0433 #define USB_DEVICE_ID_IBM_GAMEPAD 0x1101 #define USB_VENDOR_ID_ANTON 0x1130 #define USB_DEVICE_ID_ANTON_TOUCH_PAD 0x3101 #define USB_VENDOR_ID_APPLE 0x05ac #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 #define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d Loading drivers/hid/hid-multitouch.c +104 −177 Original line number Diff line number Diff line Loading @@ -68,6 +68,9 @@ MODULE_LICENSE("GPL"); #define MT_QUIRK_HOVERING (1 << 11) #define MT_QUIRK_CONTACT_CNT_ACCURATE (1 << 12) #define MT_INPUTMODE_TOUCHSCREEN 0x02 #define MT_INPUTMODE_TOUCHPAD 0x03 struct mt_slot { __s32 x, y, cx, cy, p, w, h; __s32 contactid; /* the device ContactID assigned to this slot */ Loading @@ -84,6 +87,7 @@ struct mt_class { __s32 sn_pressure; /* Signal/noise ratio for pressure events */ __u8 maxcontacts; bool is_indirect; /* true for touchpads */ bool export_all_inputs; /* do not ignore mouse, keyboards, etc... */ }; struct mt_fields { Loading @@ -100,11 +104,11 @@ struct mt_device { int cc_value_index; /* contact count value index in the field */ 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 */ __s16 inputmode; /* InputMode HID feature, -1 if non-existent */ __s16 inputmode_index; /* InputMode HID feature index in the report */ __s16 maxcontact_report_id; /* Maximum Contact Number HID feature, -1 if non-existent */ __u8 inputmode_value; /* InputMode HID feature value */ __u8 num_received; /* how many contacts we received */ __u8 num_expected; /* expected last contact index */ __u8 maxcontacts; Loading @@ -128,16 +132,17 @@ static void mt_post_parse(struct mt_device *td); #define MT_CLS_CONFIDENCE_MINUS_ONE 0x0005 #define MT_CLS_DUAL_INRANGE_CONTACTID 0x0006 #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 0x0007 #define MT_CLS_DUAL_NSMU_CONTACTID 0x0008 /* reserved 0x0008 */ #define MT_CLS_INRANGE_CONTACTNUMBER 0x0009 #define MT_CLS_NSMU 0x000a #define MT_CLS_DUAL_CONTACT_NUMBER 0x0010 #define MT_CLS_DUAL_CONTACT_ID 0x0011 /* reserved 0x0010 */ /* reserved 0x0011 */ #define MT_CLS_WIN_8 0x0012 #define MT_CLS_EXPORT_ALL_INPUTS 0x0013 /* vendor specific classes */ #define MT_CLS_3M 0x0101 #define MT_CLS_CYPRESS 0x0102 /* reserved 0x0102 */ #define MT_CLS_EGALAX 0x0103 #define MT_CLS_EGALAX_SERIAL 0x0104 #define MT_CLS_TOPSEED 0x0105 Loading Loading @@ -189,28 +194,18 @@ static struct mt_class mt_classes[] = { .quirks = MT_QUIRK_VALID_IS_INRANGE | MT_QUIRK_SLOT_IS_CONTACTNUMBER, .maxcontacts = 2 }, { .name = MT_CLS_DUAL_NSMU_CONTACTID, .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | MT_QUIRK_SLOT_IS_CONTACTID, .maxcontacts = 2 }, { .name = MT_CLS_INRANGE_CONTACTNUMBER, .quirks = MT_QUIRK_VALID_IS_INRANGE | MT_QUIRK_SLOT_IS_CONTACTNUMBER }, { .name = MT_CLS_DUAL_CONTACT_NUMBER, .quirks = MT_QUIRK_ALWAYS_VALID | MT_QUIRK_CONTACT_CNT_ACCURATE | MT_QUIRK_SLOT_IS_CONTACTNUMBER, .maxcontacts = 2 }, { .name = MT_CLS_DUAL_CONTACT_ID, .quirks = MT_QUIRK_ALWAYS_VALID | MT_QUIRK_CONTACT_CNT_ACCURATE | MT_QUIRK_SLOT_IS_CONTACTID, .maxcontacts = 2 }, { .name = MT_CLS_WIN_8, .quirks = MT_QUIRK_ALWAYS_VALID | MT_QUIRK_IGNORE_DUPLICATES | MT_QUIRK_HOVERING | MT_QUIRK_CONTACT_CNT_ACCURATE }, { .name = MT_CLS_EXPORT_ALL_INPUTS, .quirks = MT_QUIRK_ALWAYS_VALID | MT_QUIRK_CONTACT_CNT_ACCURATE, .export_all_inputs = true }, /* * vendor specific classes Loading @@ -223,10 +218,6 @@ static struct mt_class mt_classes[] = { .sn_height = 128, .maxcontacts = 60, }, { .name = MT_CLS_CYPRESS, .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | MT_QUIRK_CYPRESS, .maxcontacts = 10 }, { .name = MT_CLS_EGALAX, .quirks = MT_QUIRK_SLOT_IS_CONTACTID | MT_QUIRK_VALID_IS_INRANGE, Loading Loading @@ -360,45 +351,6 @@ static void mt_store_field(struct hid_usage *usage, struct mt_device *td, f->usages[f->length++] = usage->hid; } 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) { /* 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 @@ -415,8 +367,10 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, * Model touchscreens providing buttons as touchpads. */ if (field->application == HID_DG_TOUCHPAD || (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) { td->mt_flags |= INPUT_MT_POINTER; td->inputmode_value = MT_INPUTMODE_TOUCHPAD; } if (usage->usage_index) prev_usage = &field->usage[usage->usage_index - 1]; Loading Loading @@ -776,28 +730,52 @@ 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 && struct mt_device *td = hid_get_drvdata(hdev); /* * If mtclass.export_all_inputs is not set, 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 (!td->mtclass.export_all_inputs && field->application != HID_DG_TOUCHSCREEN && field->application != HID_DG_PEN && field->application != HID_DG_TOUCHPAD) return -1; /* * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN" * for the stylus. */ if (field->physical == HID_DG_STYLUS) return mt_pen_input_mapping(hdev, hi, field, usage, bit, max); return 0; if (field->application == HID_DG_TOUCHSCREEN || field->application == HID_DG_TOUCHPAD) return mt_touch_input_mapping(hdev, hi, field, usage, bit, max); /* let hid-core decide for the others */ return 0; } 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) { /* * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN" * for the stylus. */ if (field->physical == HID_DG_STYLUS) return mt_pen_input_mapped(hdev, hi, field, usage, bit, max); return 0; if (field->application == HID_DG_TOUCHSCREEN || field->application == HID_DG_TOUCHPAD) return mt_touch_input_mapped(hdev, hi, field, usage, bit, max); /* let hid-core decide for the others */ return 0; } static int mt_event(struct hid_device *hid, struct hid_field *field, Loading @@ -808,25 +786,22 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, 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; return 0; } static void mt_report(struct hid_device *hid, struct hid_report *report) { struct mt_device *td = hid_get_drvdata(hid); struct hid_field *field = report->field[0]; if (!(hid->claimed & HID_CLAIMED_INPUT)) return; if (report->id == td->mt_report_id) mt_touch_report(hid, report); return mt_touch_report(hid, report); if (report->id == td->pen_report_id) mt_pen_report(hid, report); if (field && field->hidinput && field->hidinput->input) input_sync(field->hidinput->input); } static void mt_set_input_mode(struct hid_device *hdev) Loading @@ -841,7 +816,7 @@ static void mt_set_input_mode(struct hid_device *hdev) re = &(hdev->report_enum[HID_FEATURE_REPORT]); r = re->report_id_hash[td->inputmode]; if (r) { r->field[0]->value[td->inputmode_index] = 0x02; r->field[0]->value[td->inputmode_index] = td->inputmode_value; hid_hw_request(hdev, r, HID_REQ_SET_REPORT); } } Loading Loading @@ -907,13 +882,49 @@ static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi) struct mt_device *td = hid_get_drvdata(hdev); char *name; const char *suffix = NULL; struct hid_field *field = hi->report->field[0]; if (hi->report->id == td->mt_report_id) mt_touch_input_configured(hdev, hi); /* * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN" * for the stylus. Check this first, and then rely on the application * field. */ if (hi->report->field[0]->physical == HID_DG_STYLUS) { suffix = "Pen"; mt_pen_input_configured(hdev, hi); /* force BTN_STYLUS to allow tablet matching in udev */ __set_bit(BTN_STYLUS, hi->input->keybit); } else { switch (field->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"; /* force BTN_STYLUS to allow tablet matching in udev */ __set_bit(BTN_STYLUS, hi->input->keybit); break; case HID_DG_TOUCHSCREEN: /* we do not set suffix = "Touchscreen" */ break; case HID_GD_SYSTEM_CONTROL: suffix = "System Control"; break; case HID_CP_CONSUMER_CONTROL: suffix = "Consumer Control"; break; default: suffix = "UNKNOWN"; break; } } if (suffix) { Loading Loading @@ -973,9 +984,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) td->mtclass = *mtclass; td->inputmode = -1; td->maxcontact_report_id = -1; td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN; td->cc_index = -1; td->mt_report_id = -1; td->pen_report_id = -1; hid_set_drvdata(hdev, td); td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields), Loading Loading @@ -1034,6 +1045,12 @@ static void mt_remove(struct hid_device *hdev) hid_hw_stop(hdev); } /* * This list contains only: * - VID/PID of products not working with the default multitouch handling * - 2 generic rules. * So there is no point in adding here any device with MT_CLS_DEFAULT. */ static const struct hid_device_id mt_devices[] = { /* 3M panels */ Loading @@ -1047,15 +1064,12 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M3266) }, /* ActionStar panels */ { .driver_data = MT_CLS_NSMU, MT_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR, USB_DEVICE_ID_ACTIONSTAR_1011) }, /* Anton devices */ { .driver_data = MT_CLS_EXPORT_ALL_INPUTS, MT_USB_DEVICE(USB_VENDOR_ID_ANTON, USB_DEVICE_ID_ANTON_TOUCH_PAD) }, /* Atmel panels */ { .driver_data = MT_CLS_SERIAL, MT_USB_DEVICE(USB_VENDOR_ID_ATMEL, USB_DEVICE_ID_ATMEL_MULTITOUCH) }, { .driver_data = MT_CLS_SERIAL, MT_USB_DEVICE(USB_VENDOR_ID_ATMEL, USB_DEVICE_ID_ATMEL_MXT_DIGITIZER) }, Loading @@ -1064,16 +1078,11 @@ static const struct hid_device_id mt_devices[] = { { .driver_data = MT_CLS_NSMU, MT_USB_DEVICE(USB_VENDOR_ID_BAANTO, USB_DEVICE_ID_BAANTO_MT_190W2) }, /* Cando panels */ { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, MT_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, { .driver_data = MT_CLS_DUAL_CONTACT_NUMBER, MT_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) }, { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, MT_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, MT_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, Loading @@ -1088,16 +1097,6 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) }, /* Cypress panel */ { .driver_data = MT_CLS_CYPRESS, HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, /* Data Modul easyMaxTouch */ { .driver_data = MT_CLS_DEFAULT, MT_USB_DEVICE(USB_VENDOR_ID_DATA_MODUL, USB_VENDOR_ID_DATA_MODUL_EASYMAXTOUCH) }, /* eGalax devices (resistive) */ { .driver_data = MT_CLS_EGALAX, MT_USB_DEVICE(USB_VENDOR_ID_DWAV, Loading Loading @@ -1156,11 +1155,6 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) }, /* Elo TouchSystems IntelliTouch Plus panel */ { .driver_data = MT_CLS_DUAL_CONTACT_ID, MT_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2515) }, /* Flatfrog Panels */ { .driver_data = MT_CLS_FLATFROG, MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG, Loading Loading @@ -1209,37 +1203,11 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT, USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) }, /* Ideacom panel */ { .driver_data = MT_CLS_SERIAL, MT_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6650) }, { .driver_data = MT_CLS_SERIAL, MT_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6651) }, /* Ilitek dual touch panel */ { .driver_data = MT_CLS_NSMU, MT_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) }, /* IRTOUCH panels */ { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, MT_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, /* LG Display panels */ { .driver_data = MT_CLS_DEFAULT, MT_USB_DEVICE(USB_VENDOR_ID_LG, USB_DEVICE_ID_LG_MULTITOUCH) }, /* Lumio panels */ { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, MT_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH) }, { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, MT_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH_DUAL) }, /* MosArt panels */ { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, MT_USB_DEVICE(USB_VENDOR_ID_ASUS, Loading @@ -1251,11 +1219,6 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, /* Nexio panels */ { .driver_data = MT_CLS_DEFAULT, MT_USB_DEVICE(USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_420)}, /* Panasonic panels */ { .driver_data = MT_CLS_PANASONIC, MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC, Loading @@ -1269,11 +1232,6 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_PCT) }, /* PenMount panels */ { .driver_data = MT_CLS_CONFIDENCE, MT_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) }, /* PixArt optical touch screen */ { .driver_data = MT_CLS_INRANGE_CONTACTNUMBER, MT_USB_DEVICE(USB_VENDOR_ID_PIXART, Loading @@ -1286,45 +1244,19 @@ static const struct hid_device_id mt_devices[] = { USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) }, /* PixCir-based panels */ { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, MT_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) }, { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, MT_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) }, /* Quanta-based panels */ { .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID, MT_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, { .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID, MT_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001) }, { .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID, MT_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008) }, /* SiS panels */ { .driver_data = MT_CLS_DEFAULT, HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH) }, { .driver_data = MT_CLS_DEFAULT, HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) }, { .driver_data = MT_CLS_DEFAULT, HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS1030_TOUCH) }, /* Stantum panels */ { .driver_data = MT_CLS_CONFIDENCE, MT_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP)}, { .driver_data = MT_CLS_CONFIDENCE, MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_MTP_STM)}, { .driver_data = MT_CLS_DEFAULT, MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, USB_DEVICE_ID_MTP_SITRONIX)}, /* TopSeed panels */ { .driver_data = MT_CLS_TOPSEED, Loading Loading @@ -1383,11 +1315,6 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR2) }, /* Zytronic panels */ { .driver_data = MT_CLS_SERIAL, MT_USB_DEVICE(USB_VENDOR_ID_ZYTRONIC, USB_DEVICE_ID_ZYTRONIC_ZXY100) }, /* Generic MT device */ { HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) }, Loading drivers/hid/hid-sony.c +11 −1 Original line number Diff line number Diff line Loading @@ -863,7 +863,7 @@ static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size) battery_capacity = sixaxis_battery_capacity[index]; battery_charging = 0; } cable_state = !((rd[31] >> 4) & 0x01); cable_state = !(rd[31] & 0x04); spin_lock_irqsave(&sc->lock, flags); sc->cable_state = cable_state; Loading Loading @@ -1632,11 +1632,21 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) sc->worker_initialized = 1; INIT_WORK(&sc->state_worker, sixaxis_state_worker); } else if (sc->quirks & SIXAXIS_CONTROLLER_BT) { /* * The Sixaxis wants output reports sent on the ctrl endpoint * when connected via Bluetooth. */ hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; ret = sixaxis_set_operational_bt(hdev); sc->worker_initialized = 1; INIT_WORK(&sc->state_worker, sixaxis_state_worker); } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { /* * The DualShock 4 wants output reports sent on the ctrl * endpoint when connected via Bluetooth. */ hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; ret = dualshock4_set_operational_bt(hdev); if (ret < 0) { hid_err(hdev, "failed to set the Dualshock 4 operational mode\n"); Loading drivers/hid/uhid.c +78 −0 Original line number Diff line number Diff line Loading @@ -428,6 +428,67 @@ err_free: return ret; } static int uhid_dev_create2(struct uhid_device *uhid, const struct uhid_event *ev) { struct hid_device *hid; int ret; if (uhid->running) return -EALREADY; uhid->rd_size = ev->u.create2.rd_size; if (uhid->rd_size <= 0 || uhid->rd_size > HID_MAX_DESCRIPTOR_SIZE) return -EINVAL; uhid->rd_data = kmalloc(uhid->rd_size, GFP_KERNEL); if (!uhid->rd_data) return -ENOMEM; memcpy(uhid->rd_data, ev->u.create2.rd_data, uhid->rd_size); hid = hid_allocate_device(); if (IS_ERR(hid)) { ret = PTR_ERR(hid); goto err_free; } strncpy(hid->name, ev->u.create2.name, 127); hid->name[127] = 0; strncpy(hid->phys, ev->u.create2.phys, 63); hid->phys[63] = 0; strncpy(hid->uniq, ev->u.create2.uniq, 63); hid->uniq[63] = 0; hid->ll_driver = &uhid_hid_driver; hid->bus = ev->u.create2.bus; hid->vendor = ev->u.create2.vendor; hid->product = ev->u.create2.product; hid->version = ev->u.create2.version; hid->country = ev->u.create2.country; hid->driver_data = uhid; hid->dev.parent = uhid_misc.this_device; uhid->hid = hid; uhid->running = true; ret = hid_add_device(hid); if (ret) { hid_err(hid, "Cannot register HID device\n"); goto err_hid; } return 0; err_hid: hid_destroy_device(hid); uhid->hid = NULL; uhid->running = false; err_free: kfree(uhid->rd_data); return ret; } static int uhid_dev_destroy(struct uhid_device *uhid) { if (!uhid->running) Loading Loading @@ -456,6 +517,17 @@ static int uhid_dev_input(struct uhid_device *uhid, struct uhid_event *ev) return 0; } static int uhid_dev_input2(struct uhid_device *uhid, struct uhid_event *ev) { if (!uhid->running) return -EINVAL; hid_input_report(uhid->hid, HID_INPUT_REPORT, ev->u.input2.data, min_t(size_t, ev->u.input2.size, UHID_DATA_MAX), 0); return 0; } static int uhid_dev_feature_answer(struct uhid_device *uhid, struct uhid_event *ev) { Loading Loading @@ -592,12 +664,18 @@ static ssize_t uhid_char_write(struct file *file, const char __user *buffer, case UHID_CREATE: ret = uhid_dev_create(uhid, &uhid->input_buf); break; case UHID_CREATE2: ret = uhid_dev_create2(uhid, &uhid->input_buf); break; case UHID_DESTROY: ret = uhid_dev_destroy(uhid); break; case UHID_INPUT: ret = uhid_dev_input(uhid, &uhid->input_buf); break; case UHID_INPUT2: ret = uhid_dev_input2(uhid, &uhid->input_buf); break; case UHID_FEATURE_ANSWER: ret = uhid_dev_feature_answer(uhid, &uhid->input_buf); break; Loading Loading
Documentation/hid/uhid.txt +11 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,11 @@ the request was handled successfully. event to the kernel. The payload is of type struct uhid_create_req and contains information about your device. You can start I/O now. UHID_CREATE2: Same as UHID_CREATE, but the HID report descriptor data (rd_data) is an array inside struct uhid_create2_req, instead of a pointer to a separate array. Enables use from languages that don't support pointers, e.g. Python. UHID_DESTROY: This destroys the internal HID device. No further I/O will be accepted. There may still be pending messages that you can receive with read() but no further Loading @@ -105,6 +110,12 @@ the request was handled successfully. contains a data-payload. This is the raw data that you read from your device. The kernel will parse the HID reports and react on it. UHID_INPUT2: Same as UHID_INPUT, but the data array is the last field of uhid_input2_req. Enables userspace to write only the required bytes to kernel (ev.type + ev.u.input2.size + the part of the data array that matters), instead of the entire struct uhid_input2_req. UHID_FEATURE_ANSWER: If you receive a UHID_FEATURE request you must answer with this request. You must copy the "id" field from the request into the answer. Set the "err" field Loading
drivers/hid/hid-ids.h +3 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,9 @@ #define USB_VENDOR_ID_ALPS 0x0433 #define USB_DEVICE_ID_IBM_GAMEPAD 0x1101 #define USB_VENDOR_ID_ANTON 0x1130 #define USB_DEVICE_ID_ANTON_TOUCH_PAD 0x3101 #define USB_VENDOR_ID_APPLE 0x05ac #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 #define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d Loading
drivers/hid/hid-multitouch.c +104 −177 Original line number Diff line number Diff line Loading @@ -68,6 +68,9 @@ MODULE_LICENSE("GPL"); #define MT_QUIRK_HOVERING (1 << 11) #define MT_QUIRK_CONTACT_CNT_ACCURATE (1 << 12) #define MT_INPUTMODE_TOUCHSCREEN 0x02 #define MT_INPUTMODE_TOUCHPAD 0x03 struct mt_slot { __s32 x, y, cx, cy, p, w, h; __s32 contactid; /* the device ContactID assigned to this slot */ Loading @@ -84,6 +87,7 @@ struct mt_class { __s32 sn_pressure; /* Signal/noise ratio for pressure events */ __u8 maxcontacts; bool is_indirect; /* true for touchpads */ bool export_all_inputs; /* do not ignore mouse, keyboards, etc... */ }; struct mt_fields { Loading @@ -100,11 +104,11 @@ struct mt_device { int cc_value_index; /* contact count value index in the field */ 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 */ __s16 inputmode; /* InputMode HID feature, -1 if non-existent */ __s16 inputmode_index; /* InputMode HID feature index in the report */ __s16 maxcontact_report_id; /* Maximum Contact Number HID feature, -1 if non-existent */ __u8 inputmode_value; /* InputMode HID feature value */ __u8 num_received; /* how many contacts we received */ __u8 num_expected; /* expected last contact index */ __u8 maxcontacts; Loading @@ -128,16 +132,17 @@ static void mt_post_parse(struct mt_device *td); #define MT_CLS_CONFIDENCE_MINUS_ONE 0x0005 #define MT_CLS_DUAL_INRANGE_CONTACTID 0x0006 #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 0x0007 #define MT_CLS_DUAL_NSMU_CONTACTID 0x0008 /* reserved 0x0008 */ #define MT_CLS_INRANGE_CONTACTNUMBER 0x0009 #define MT_CLS_NSMU 0x000a #define MT_CLS_DUAL_CONTACT_NUMBER 0x0010 #define MT_CLS_DUAL_CONTACT_ID 0x0011 /* reserved 0x0010 */ /* reserved 0x0011 */ #define MT_CLS_WIN_8 0x0012 #define MT_CLS_EXPORT_ALL_INPUTS 0x0013 /* vendor specific classes */ #define MT_CLS_3M 0x0101 #define MT_CLS_CYPRESS 0x0102 /* reserved 0x0102 */ #define MT_CLS_EGALAX 0x0103 #define MT_CLS_EGALAX_SERIAL 0x0104 #define MT_CLS_TOPSEED 0x0105 Loading Loading @@ -189,28 +194,18 @@ static struct mt_class mt_classes[] = { .quirks = MT_QUIRK_VALID_IS_INRANGE | MT_QUIRK_SLOT_IS_CONTACTNUMBER, .maxcontacts = 2 }, { .name = MT_CLS_DUAL_NSMU_CONTACTID, .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | MT_QUIRK_SLOT_IS_CONTACTID, .maxcontacts = 2 }, { .name = MT_CLS_INRANGE_CONTACTNUMBER, .quirks = MT_QUIRK_VALID_IS_INRANGE | MT_QUIRK_SLOT_IS_CONTACTNUMBER }, { .name = MT_CLS_DUAL_CONTACT_NUMBER, .quirks = MT_QUIRK_ALWAYS_VALID | MT_QUIRK_CONTACT_CNT_ACCURATE | MT_QUIRK_SLOT_IS_CONTACTNUMBER, .maxcontacts = 2 }, { .name = MT_CLS_DUAL_CONTACT_ID, .quirks = MT_QUIRK_ALWAYS_VALID | MT_QUIRK_CONTACT_CNT_ACCURATE | MT_QUIRK_SLOT_IS_CONTACTID, .maxcontacts = 2 }, { .name = MT_CLS_WIN_8, .quirks = MT_QUIRK_ALWAYS_VALID | MT_QUIRK_IGNORE_DUPLICATES | MT_QUIRK_HOVERING | MT_QUIRK_CONTACT_CNT_ACCURATE }, { .name = MT_CLS_EXPORT_ALL_INPUTS, .quirks = MT_QUIRK_ALWAYS_VALID | MT_QUIRK_CONTACT_CNT_ACCURATE, .export_all_inputs = true }, /* * vendor specific classes Loading @@ -223,10 +218,6 @@ static struct mt_class mt_classes[] = { .sn_height = 128, .maxcontacts = 60, }, { .name = MT_CLS_CYPRESS, .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | MT_QUIRK_CYPRESS, .maxcontacts = 10 }, { .name = MT_CLS_EGALAX, .quirks = MT_QUIRK_SLOT_IS_CONTACTID | MT_QUIRK_VALID_IS_INRANGE, Loading Loading @@ -360,45 +351,6 @@ static void mt_store_field(struct hid_usage *usage, struct mt_device *td, f->usages[f->length++] = usage->hid; } 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) { /* 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 @@ -415,8 +367,10 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, * Model touchscreens providing buttons as touchpads. */ if (field->application == HID_DG_TOUCHPAD || (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) { td->mt_flags |= INPUT_MT_POINTER; td->inputmode_value = MT_INPUTMODE_TOUCHPAD; } if (usage->usage_index) prev_usage = &field->usage[usage->usage_index - 1]; Loading Loading @@ -776,28 +730,52 @@ 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 && struct mt_device *td = hid_get_drvdata(hdev); /* * If mtclass.export_all_inputs is not set, 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 (!td->mtclass.export_all_inputs && field->application != HID_DG_TOUCHSCREEN && field->application != HID_DG_PEN && field->application != HID_DG_TOUCHPAD) return -1; /* * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN" * for the stylus. */ if (field->physical == HID_DG_STYLUS) return mt_pen_input_mapping(hdev, hi, field, usage, bit, max); return 0; if (field->application == HID_DG_TOUCHSCREEN || field->application == HID_DG_TOUCHPAD) return mt_touch_input_mapping(hdev, hi, field, usage, bit, max); /* let hid-core decide for the others */ return 0; } 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) { /* * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN" * for the stylus. */ if (field->physical == HID_DG_STYLUS) return mt_pen_input_mapped(hdev, hi, field, usage, bit, max); return 0; if (field->application == HID_DG_TOUCHSCREEN || field->application == HID_DG_TOUCHPAD) return mt_touch_input_mapped(hdev, hi, field, usage, bit, max); /* let hid-core decide for the others */ return 0; } static int mt_event(struct hid_device *hid, struct hid_field *field, Loading @@ -808,25 +786,22 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, 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; return 0; } static void mt_report(struct hid_device *hid, struct hid_report *report) { struct mt_device *td = hid_get_drvdata(hid); struct hid_field *field = report->field[0]; if (!(hid->claimed & HID_CLAIMED_INPUT)) return; if (report->id == td->mt_report_id) mt_touch_report(hid, report); return mt_touch_report(hid, report); if (report->id == td->pen_report_id) mt_pen_report(hid, report); if (field && field->hidinput && field->hidinput->input) input_sync(field->hidinput->input); } static void mt_set_input_mode(struct hid_device *hdev) Loading @@ -841,7 +816,7 @@ static void mt_set_input_mode(struct hid_device *hdev) re = &(hdev->report_enum[HID_FEATURE_REPORT]); r = re->report_id_hash[td->inputmode]; if (r) { r->field[0]->value[td->inputmode_index] = 0x02; r->field[0]->value[td->inputmode_index] = td->inputmode_value; hid_hw_request(hdev, r, HID_REQ_SET_REPORT); } } Loading Loading @@ -907,13 +882,49 @@ static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi) struct mt_device *td = hid_get_drvdata(hdev); char *name; const char *suffix = NULL; struct hid_field *field = hi->report->field[0]; if (hi->report->id == td->mt_report_id) mt_touch_input_configured(hdev, hi); /* * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN" * for the stylus. Check this first, and then rely on the application * field. */ if (hi->report->field[0]->physical == HID_DG_STYLUS) { suffix = "Pen"; mt_pen_input_configured(hdev, hi); /* force BTN_STYLUS to allow tablet matching in udev */ __set_bit(BTN_STYLUS, hi->input->keybit); } else { switch (field->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"; /* force BTN_STYLUS to allow tablet matching in udev */ __set_bit(BTN_STYLUS, hi->input->keybit); break; case HID_DG_TOUCHSCREEN: /* we do not set suffix = "Touchscreen" */ break; case HID_GD_SYSTEM_CONTROL: suffix = "System Control"; break; case HID_CP_CONSUMER_CONTROL: suffix = "Consumer Control"; break; default: suffix = "UNKNOWN"; break; } } if (suffix) { Loading Loading @@ -973,9 +984,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) td->mtclass = *mtclass; td->inputmode = -1; td->maxcontact_report_id = -1; td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN; td->cc_index = -1; td->mt_report_id = -1; td->pen_report_id = -1; hid_set_drvdata(hdev, td); td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields), Loading Loading @@ -1034,6 +1045,12 @@ static void mt_remove(struct hid_device *hdev) hid_hw_stop(hdev); } /* * This list contains only: * - VID/PID of products not working with the default multitouch handling * - 2 generic rules. * So there is no point in adding here any device with MT_CLS_DEFAULT. */ static const struct hid_device_id mt_devices[] = { /* 3M panels */ Loading @@ -1047,15 +1064,12 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M3266) }, /* ActionStar panels */ { .driver_data = MT_CLS_NSMU, MT_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR, USB_DEVICE_ID_ACTIONSTAR_1011) }, /* Anton devices */ { .driver_data = MT_CLS_EXPORT_ALL_INPUTS, MT_USB_DEVICE(USB_VENDOR_ID_ANTON, USB_DEVICE_ID_ANTON_TOUCH_PAD) }, /* Atmel panels */ { .driver_data = MT_CLS_SERIAL, MT_USB_DEVICE(USB_VENDOR_ID_ATMEL, USB_DEVICE_ID_ATMEL_MULTITOUCH) }, { .driver_data = MT_CLS_SERIAL, MT_USB_DEVICE(USB_VENDOR_ID_ATMEL, USB_DEVICE_ID_ATMEL_MXT_DIGITIZER) }, Loading @@ -1064,16 +1078,11 @@ static const struct hid_device_id mt_devices[] = { { .driver_data = MT_CLS_NSMU, MT_USB_DEVICE(USB_VENDOR_ID_BAANTO, USB_DEVICE_ID_BAANTO_MT_190W2) }, /* Cando panels */ { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, MT_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, { .driver_data = MT_CLS_DUAL_CONTACT_NUMBER, MT_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) }, { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, MT_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, MT_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, Loading @@ -1088,16 +1097,6 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) }, /* Cypress panel */ { .driver_data = MT_CLS_CYPRESS, HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, /* Data Modul easyMaxTouch */ { .driver_data = MT_CLS_DEFAULT, MT_USB_DEVICE(USB_VENDOR_ID_DATA_MODUL, USB_VENDOR_ID_DATA_MODUL_EASYMAXTOUCH) }, /* eGalax devices (resistive) */ { .driver_data = MT_CLS_EGALAX, MT_USB_DEVICE(USB_VENDOR_ID_DWAV, Loading Loading @@ -1156,11 +1155,6 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) }, /* Elo TouchSystems IntelliTouch Plus panel */ { .driver_data = MT_CLS_DUAL_CONTACT_ID, MT_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2515) }, /* Flatfrog Panels */ { .driver_data = MT_CLS_FLATFROG, MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG, Loading Loading @@ -1209,37 +1203,11 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT, USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) }, /* Ideacom panel */ { .driver_data = MT_CLS_SERIAL, MT_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6650) }, { .driver_data = MT_CLS_SERIAL, MT_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6651) }, /* Ilitek dual touch panel */ { .driver_data = MT_CLS_NSMU, MT_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) }, /* IRTOUCH panels */ { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, MT_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, /* LG Display panels */ { .driver_data = MT_CLS_DEFAULT, MT_USB_DEVICE(USB_VENDOR_ID_LG, USB_DEVICE_ID_LG_MULTITOUCH) }, /* Lumio panels */ { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, MT_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH) }, { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, MT_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH_DUAL) }, /* MosArt panels */ { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, MT_USB_DEVICE(USB_VENDOR_ID_ASUS, Loading @@ -1251,11 +1219,6 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, /* Nexio panels */ { .driver_data = MT_CLS_DEFAULT, MT_USB_DEVICE(USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_420)}, /* Panasonic panels */ { .driver_data = MT_CLS_PANASONIC, MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC, Loading @@ -1269,11 +1232,6 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_PCT) }, /* PenMount panels */ { .driver_data = MT_CLS_CONFIDENCE, MT_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) }, /* PixArt optical touch screen */ { .driver_data = MT_CLS_INRANGE_CONTACTNUMBER, MT_USB_DEVICE(USB_VENDOR_ID_PIXART, Loading @@ -1286,45 +1244,19 @@ static const struct hid_device_id mt_devices[] = { USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) }, /* PixCir-based panels */ { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, MT_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) }, { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, MT_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) }, /* Quanta-based panels */ { .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID, MT_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, { .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID, MT_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001) }, { .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID, MT_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008) }, /* SiS panels */ { .driver_data = MT_CLS_DEFAULT, HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH) }, { .driver_data = MT_CLS_DEFAULT, HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) }, { .driver_data = MT_CLS_DEFAULT, HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS1030_TOUCH) }, /* Stantum panels */ { .driver_data = MT_CLS_CONFIDENCE, MT_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP)}, { .driver_data = MT_CLS_CONFIDENCE, MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_MTP_STM)}, { .driver_data = MT_CLS_DEFAULT, MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, USB_DEVICE_ID_MTP_SITRONIX)}, /* TopSeed panels */ { .driver_data = MT_CLS_TOPSEED, Loading Loading @@ -1383,11 +1315,6 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR2) }, /* Zytronic panels */ { .driver_data = MT_CLS_SERIAL, MT_USB_DEVICE(USB_VENDOR_ID_ZYTRONIC, USB_DEVICE_ID_ZYTRONIC_ZXY100) }, /* Generic MT device */ { HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) }, Loading
drivers/hid/hid-sony.c +11 −1 Original line number Diff line number Diff line Loading @@ -863,7 +863,7 @@ static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size) battery_capacity = sixaxis_battery_capacity[index]; battery_charging = 0; } cable_state = !((rd[31] >> 4) & 0x01); cable_state = !(rd[31] & 0x04); spin_lock_irqsave(&sc->lock, flags); sc->cable_state = cable_state; Loading Loading @@ -1632,11 +1632,21 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) sc->worker_initialized = 1; INIT_WORK(&sc->state_worker, sixaxis_state_worker); } else if (sc->quirks & SIXAXIS_CONTROLLER_BT) { /* * The Sixaxis wants output reports sent on the ctrl endpoint * when connected via Bluetooth. */ hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; ret = sixaxis_set_operational_bt(hdev); sc->worker_initialized = 1; INIT_WORK(&sc->state_worker, sixaxis_state_worker); } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { /* * The DualShock 4 wants output reports sent on the ctrl * endpoint when connected via Bluetooth. */ hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; ret = dualshock4_set_operational_bt(hdev); if (ret < 0) { hid_err(hdev, "failed to set the Dualshock 4 operational mode\n"); Loading
drivers/hid/uhid.c +78 −0 Original line number Diff line number Diff line Loading @@ -428,6 +428,67 @@ err_free: return ret; } static int uhid_dev_create2(struct uhid_device *uhid, const struct uhid_event *ev) { struct hid_device *hid; int ret; if (uhid->running) return -EALREADY; uhid->rd_size = ev->u.create2.rd_size; if (uhid->rd_size <= 0 || uhid->rd_size > HID_MAX_DESCRIPTOR_SIZE) return -EINVAL; uhid->rd_data = kmalloc(uhid->rd_size, GFP_KERNEL); if (!uhid->rd_data) return -ENOMEM; memcpy(uhid->rd_data, ev->u.create2.rd_data, uhid->rd_size); hid = hid_allocate_device(); if (IS_ERR(hid)) { ret = PTR_ERR(hid); goto err_free; } strncpy(hid->name, ev->u.create2.name, 127); hid->name[127] = 0; strncpy(hid->phys, ev->u.create2.phys, 63); hid->phys[63] = 0; strncpy(hid->uniq, ev->u.create2.uniq, 63); hid->uniq[63] = 0; hid->ll_driver = &uhid_hid_driver; hid->bus = ev->u.create2.bus; hid->vendor = ev->u.create2.vendor; hid->product = ev->u.create2.product; hid->version = ev->u.create2.version; hid->country = ev->u.create2.country; hid->driver_data = uhid; hid->dev.parent = uhid_misc.this_device; uhid->hid = hid; uhid->running = true; ret = hid_add_device(hid); if (ret) { hid_err(hid, "Cannot register HID device\n"); goto err_hid; } return 0; err_hid: hid_destroy_device(hid); uhid->hid = NULL; uhid->running = false; err_free: kfree(uhid->rd_data); return ret; } static int uhid_dev_destroy(struct uhid_device *uhid) { if (!uhid->running) Loading Loading @@ -456,6 +517,17 @@ static int uhid_dev_input(struct uhid_device *uhid, struct uhid_event *ev) return 0; } static int uhid_dev_input2(struct uhid_device *uhid, struct uhid_event *ev) { if (!uhid->running) return -EINVAL; hid_input_report(uhid->hid, HID_INPUT_REPORT, ev->u.input2.data, min_t(size_t, ev->u.input2.size, UHID_DATA_MAX), 0); return 0; } static int uhid_dev_feature_answer(struct uhid_device *uhid, struct uhid_event *ev) { Loading Loading @@ -592,12 +664,18 @@ static ssize_t uhid_char_write(struct file *file, const char __user *buffer, case UHID_CREATE: ret = uhid_dev_create(uhid, &uhid->input_buf); break; case UHID_CREATE2: ret = uhid_dev_create2(uhid, &uhid->input_buf); break; case UHID_DESTROY: ret = uhid_dev_destroy(uhid); break; case UHID_INPUT: ret = uhid_dev_input(uhid, &uhid->input_buf); break; case UHID_INPUT2: ret = uhid_dev_input2(uhid, &uhid->input_buf); break; case UHID_FEATURE_ANSWER: ret = uhid_dev_feature_answer(uhid, &uhid->input_buf); break; Loading