From b7ee3d77291460b21437280b9838aaf680046073 Mon Sep 17 00:00:00 2001 From: Dmitry Mastykin Date: Tue, 25 Aug 2020 10:29:03 +0300 Subject: pen support no buttons diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 128d8f4319b9..280d85e0eac5 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -48,6 +48,9 @@ MODULE_LICENSE("GPL"); #include "hid-ids.h" +// #define MY(fmt,arg...) printk(KERN_INFO "%s: " fmt "\n", __func__, ##arg) +#define MY(fmt,arg...) + /* quirks to control the device */ #define MT_QUIRK_NOT_SEEN_MEANS_UP BIT(0) #define MT_QUIRK_SLOT_IS_CONTACTID BIT(1) @@ -70,6 +73,7 @@ MODULE_LICENSE("GPL"); #define MT_QUIRK_WIN8_PTP_BUTTONS BIT(18) #define MT_QUIRK_SEPARATE_APP_REPORT BIT(19) #define MT_QUIRK_FORCE_MULTI_INPUT BIT(20) +#define MT_QUIRK_NON_MT_PEN BIT(21) #define MT_INPUTMODE_TOUCHSCREEN 0x02 #define MT_INPUTMODE_TOUCHPAD 0x03 @@ -100,6 +104,9 @@ struct mt_usages { bool *tip_state; /* is the touch valid? */ bool *inrange_state; /* is the finger in proximity of the sensor? */ bool *confidence_state; /* is the touch made by a finger? */ + bool *barrel_state; + bool *invert_state; + bool *eraser_state; }; struct mt_application { @@ -153,6 +160,7 @@ struct mt_report_data { struct hid_report *report; struct mt_application *application; bool is_mt_collection; + bool non_mt_pen; }; struct mt_device { @@ -208,6 +216,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app); #define MT_CLS_GOOGLE 0x0111 #define MT_CLS_RAZER_BLADE_STEALTH 0x0112 #define MT_CLS_SMART_TECH 0x0113 +#define MT_CLS_NON_MT_PEN 0x0114 #define MT_DEFAULT_MAXCONTACT 10 #define MT_MAX_MAXCONTACT 250 @@ -374,6 +383,9 @@ static const struct mt_class mt_classes[] = { MT_QUIRK_CONTACT_CNT_ACCURATE | MT_QUIRK_SEPARATE_APP_REPORT, }, + { .name = MT_CLS_NON_MT_PEN, + .quirks = MT_QUIRK_NON_MT_PEN, + }, { } }; @@ -523,6 +535,9 @@ static struct mt_usages *mt_allocate_usage(struct hid_device *hdev, usage->tip_state = DEFAULT_FALSE; usage->inrange_state = DEFAULT_FALSE; usage->confidence_state = DEFAULT_TRUE; + usage->barrel_state = DEFAULT_FALSE; + usage->invert_state = DEFAULT_FALSE; + usage->eraser_state = DEFAULT_FALSE; list_add_tail(&usage->list, &application->mt_usages); @@ -877,6 +892,67 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, return 0; } +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_application *app) +{ + struct mt_device *td = hid_get_drvdata(hdev); + struct mt_class *cls = &td->mtclass; + + MY("application:%s:%x:%x", hdev->name, field->application, usage->hid); + + switch (usage->hid & HID_USAGE_PAGE) { + case HID_UP_GENDESK: + switch (usage->hid) { + case HID_GD_X: + __set_bit(INPUT_PROP_DIRECT, hi->input->propbit); + set_abs(hi->input, ABS_X, field, cls->sn_move); + MT_STORE_FIELD(x); + return 1; + case HID_GD_Y: + set_abs(hi->input, ABS_Y, field, cls->sn_move); + MT_STORE_FIELD(y); + return 1; + } + return -1; + + case HID_UP_DIGITIZER: + switch (usage->hid) { + case HID_DG_INRANGE: + input_set_capability(hi->input, + EV_KEY, BTN_TOOL_PEN); + input_set_abs_params(hi->input, + ABS_DISTANCE, 0, 1, 0, 0); + MT_STORE_FIELD(inrange_state); + return 1; + case HID_DG_TIPSWITCH: + input_set_capability(hi->input, + EV_KEY, BTN_TOUCH); + MT_STORE_FIELD(tip_state); + return 1; + case HID_DG_BARRELSWITCH: + input_set_capability(hi->input, + EV_KEY, BTN_STYLUS2); + MT_STORE_FIELD(barrel_state); + return 1; + case HID_DG_INVERT: + MT_STORE_FIELD(invert_state); + return 1; + case HID_DG_ERASER: + MT_STORE_FIELD(eraser_state); + return 1; + case HID_DG_TIPPRESSURE: + set_abs(hi->input, ABS_PRESSURE, field, + cls->sn_pressure); + MT_STORE_FIELD(p); + return 1; + } + return -1; + } + + return 0; +} + static int mt_compute_slot(struct mt_device *td, struct mt_application *app, struct mt_usages *slot, struct input_dev *input) @@ -1242,6 +1318,34 @@ static void mt_touch_report(struct hid_device *hid, clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags); } +static void mt_pen_report(struct hid_device *hid, + struct mt_report_data *rdata) +{ + struct mt_application *app = rdata->application; + struct mt_usages *usage; + struct input_dev *input = rdata->report->field[0]->hidinput->input; + + if (!(usage = list_first_entry_or_null(&app->mt_usages, + struct mt_usages, list))) + return; + + + MY("inr:tip:bar:inv:era %d:%d:%d:%d:%d", + *usage->inrange_state, + *usage->tip_state, + *usage->barrel_state, + *usage->invert_state, + *usage->eraser_state + ); + input_report_key(input, BTN_TOOL_PEN, *usage->inrange_state); + input_report_key(input, BTN_TOUCH, *usage->tip_state); + // input_report_key(input, BTN_STYLUS2, *usage->barrel_state); + input_event(input, EV_ABS, ABS_X, *usage->x); + input_event(input, EV_ABS, ABS_Y, *usage->y); + input_event(input, EV_ABS, ABS_PRESSURE, *usage->p); + input_event(input, EV_ABS, ABS_DISTANCE, !*usage->tip_state); +} + static int mt_touch_input_configured(struct hid_device *hdev, struct hid_input *hi, struct mt_application *app) @@ -1347,6 +1451,14 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, return 1; } + if (field->application == HID_DG_PEN && + application->quirks & MT_QUIRK_NON_MT_PEN) { + rdata->is_mt_collection = false; + rdata->non_mt_pen = true; + return mt_pen_input_mapping(hdev, hi, field, usage, bit, max, + application); + } + if (rdata->is_mt_collection) return mt_touch_input_mapping(hdev, hi, field, usage, bit, max, application); @@ -1370,7 +1482,7 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, struct mt_report_data *rdata; rdata = mt_find_report_data(td, field->report); - if (rdata && rdata->is_mt_collection) { + if (rdata && (rdata->is_mt_collection || rdata->non_mt_pen)) { /* We own these mappings, tell hid-input to ignore them */ return -1; } @@ -1404,6 +1516,8 @@ static void mt_report(struct hid_device *hid, struct hid_report *report) rdata = mt_find_report_data(td, report); if (rdata && rdata->is_mt_collection) return mt_touch_report(hid, rdata); + if (rdata && rdata->non_mt_pen) + mt_pen_report(hid, rdata); if (field && field->hidinput && field->hidinput->input) input_sync(field->hidinput->input); @@ -2151,6 +2265,11 @@ static const struct hid_device_id mt_devices[] = { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_TOUCH_ROSE) }, + { .driver_data = MT_CLS_NON_MT_PEN, + HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, + I2C_VENDOR_ID_GOODIX, + I2C_DEVICE_ID_GOODIX_0113) }, + /* Generic MT device */ { HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) },