Loading drivers/hid/hid-multitouch.c +35 −4 Original line number Diff line number Diff line Loading @@ -71,6 +71,7 @@ MODULE_LICENSE("GPL"); #define MT_QUIRK_SEPARATE_APP_REPORT BIT(19) #define MT_QUIRK_FORCE_MULTI_INPUT BIT(20) #define MT_QUIRK_DISABLE_WAKEUP BIT(21) #define MT_QUIRK_ORIENTATION_INVERT BIT(22) #define MT_INPUTMODE_TOUCHSCREEN 0x02 #define MT_INPUTMODE_TOUCHPAD 0x03 Loading Loading @@ -1009,6 +1010,7 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input, struct mt_usages *slot) { struct input_mt *mt = input->mt; struct hid_device *hdev = td->hdev; __s32 quirks = app->quirks; bool valid = true; bool confidence_state = true; Loading Loading @@ -1086,6 +1088,10 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input, int orientation = wide; int max_azimuth; int azimuth; int x; int y; int cx; int cy; if (slot->a != DEFAULT_ZERO) { /* Loading @@ -1104,6 +1110,9 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input, if (azimuth > max_azimuth * 2) azimuth -= max_azimuth * 4; orientation = -azimuth; if (quirks & MT_QUIRK_ORIENTATION_INVERT) orientation = -orientation; } if (quirks & MT_QUIRK_TOUCH_SIZE_SCALING) { Loading @@ -1115,10 +1124,23 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input, minor = minor >> 1; } input_event(input, EV_ABS, ABS_MT_POSITION_X, *slot->x); input_event(input, EV_ABS, ABS_MT_POSITION_Y, *slot->y); input_event(input, EV_ABS, ABS_MT_TOOL_X, *slot->cx); input_event(input, EV_ABS, ABS_MT_TOOL_Y, *slot->cy); x = hdev->quirks & HID_QUIRK_X_INVERT ? input_abs_get_max(input, ABS_MT_POSITION_X) - *slot->x : *slot->x; y = hdev->quirks & HID_QUIRK_Y_INVERT ? input_abs_get_max(input, ABS_MT_POSITION_Y) - *slot->y : *slot->y; cx = hdev->quirks & HID_QUIRK_X_INVERT ? input_abs_get_max(input, ABS_MT_POSITION_X) - *slot->cx : *slot->cx; cy = hdev->quirks & HID_QUIRK_Y_INVERT ? input_abs_get_max(input, ABS_MT_POSITION_Y) - *slot->cy : *slot->cy; input_event(input, EV_ABS, ABS_MT_POSITION_X, x); input_event(input, EV_ABS, ABS_MT_POSITION_Y, y); input_event(input, EV_ABS, ABS_MT_TOOL_X, cx); input_event(input, EV_ABS, ABS_MT_TOOL_Y, cy); input_event(input, EV_ABS, ABS_MT_DISTANCE, !*slot->tip_state); input_event(input, EV_ABS, ABS_MT_ORIENTATION, orientation); input_event(input, EV_ABS, ABS_MT_PRESSURE, *slot->p); Loading Loading @@ -1735,6 +1757,15 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID) td->serial_maybe = true; /* Orientation is inverted if the X or Y axes are * flipped, but normalized if both are inverted. */ if (hdev->quirks & (HID_QUIRK_X_INVERT | HID_QUIRK_Y_INVERT) && !((hdev->quirks & HID_QUIRK_X_INVERT) && (hdev->quirks & HID_QUIRK_Y_INVERT))) td->mtclass.quirks = MT_QUIRK_ORIENTATION_INVERT; /* This allows the driver to correctly support devices * that emit events over several HID messages. */ Loading drivers/hid/hid-quirks.c +1 −1 Original line number Diff line number Diff line Loading @@ -1237,7 +1237,7 @@ EXPORT_SYMBOL_GPL(hid_quirks_exit); static unsigned long hid_gets_squirk(const struct hid_device *hdev) { const struct hid_device_id *bl_entry; unsigned long quirks = 0; unsigned long quirks = hdev->initial_quirks; if (hid_match_id(hdev, hid_ignore_list)) quirks |= HID_QUIRK_IGNORE; Loading drivers/hid/i2c-hid/i2c-hid-core.c +4 −2 Original line number Diff line number Diff line Loading @@ -1025,6 +1025,10 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID); hid->product = le16_to_cpu(ihid->hdesc.wProductID); hid->initial_quirks = quirks; hid->initial_quirks |= i2c_hid_get_dmi_quirks(hid->vendor, hid->product); snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", client->name, (u16)hid->vendor, (u16)hid->product); strscpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys)); Loading @@ -1038,8 +1042,6 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, goto err_mem_free; } hid->quirks |= quirks; return 0; err_mem_free: Loading drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c +42 −0 Original line number Diff line number Diff line Loading @@ -10,8 +10,10 @@ #include <linux/types.h> #include <linux/dmi.h> #include <linux/mod_devicetable.h> #include <linux/hid.h> #include "i2c-hid.h" #include "../hid-ids.h" struct i2c_hid_desc_override { Loading Loading @@ -416,6 +418,28 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = { { } /* Terminate list */ }; static const struct hid_device_id i2c_hid_elan_flipped_quirks = { HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, USB_VENDOR_ID_ELAN, 0x2dcd), HID_QUIRK_X_INVERT | HID_QUIRK_Y_INVERT }; /* * This list contains devices which have specific issues based on the system * they're on and not just the device itself. The driver_data will have a * specific hid device to match against. */ static const struct dmi_system_id i2c_hid_dmi_quirk_table[] = { { .ident = "DynaBook K50/FR", .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dynabook Inc."), DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "dynabook K50/FR"), }, .driver_data = (void *)&i2c_hid_elan_flipped_quirks, }, { } /* Terminate list */ }; struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name) { Loading Loading @@ -450,3 +474,21 @@ char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name, *size = override->hid_report_desc_size; return override->hid_report_desc; } u32 i2c_hid_get_dmi_quirks(const u16 vendor, const u16 product) { u32 quirks = 0; const struct dmi_system_id *system_id = dmi_first_match(i2c_hid_dmi_quirk_table); if (system_id) { const struct hid_device_id *device_id = (struct hid_device_id *)(system_id->driver_data); if (device_id && device_id->vendor == vendor && device_id->product == product) quirks = device_id->driver_data; } return quirks; } drivers/hid/i2c-hid/i2c-hid.h +3 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name); char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name, unsigned int *size); u32 i2c_hid_get_dmi_quirks(const u16 vendor, const u16 product); #else static inline struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name) Loading @@ -16,6 +17,8 @@ static inline struct i2c_hid_desc static inline char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name, unsigned int *size) { return NULL; } static inline u32 i2c_hid_get_dmi_quirks(const u16 vendor, const u16 product) { return 0; } #endif /** Loading Loading
drivers/hid/hid-multitouch.c +35 −4 Original line number Diff line number Diff line Loading @@ -71,6 +71,7 @@ MODULE_LICENSE("GPL"); #define MT_QUIRK_SEPARATE_APP_REPORT BIT(19) #define MT_QUIRK_FORCE_MULTI_INPUT BIT(20) #define MT_QUIRK_DISABLE_WAKEUP BIT(21) #define MT_QUIRK_ORIENTATION_INVERT BIT(22) #define MT_INPUTMODE_TOUCHSCREEN 0x02 #define MT_INPUTMODE_TOUCHPAD 0x03 Loading Loading @@ -1009,6 +1010,7 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input, struct mt_usages *slot) { struct input_mt *mt = input->mt; struct hid_device *hdev = td->hdev; __s32 quirks = app->quirks; bool valid = true; bool confidence_state = true; Loading Loading @@ -1086,6 +1088,10 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input, int orientation = wide; int max_azimuth; int azimuth; int x; int y; int cx; int cy; if (slot->a != DEFAULT_ZERO) { /* Loading @@ -1104,6 +1110,9 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input, if (azimuth > max_azimuth * 2) azimuth -= max_azimuth * 4; orientation = -azimuth; if (quirks & MT_QUIRK_ORIENTATION_INVERT) orientation = -orientation; } if (quirks & MT_QUIRK_TOUCH_SIZE_SCALING) { Loading @@ -1115,10 +1124,23 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input, minor = minor >> 1; } input_event(input, EV_ABS, ABS_MT_POSITION_X, *slot->x); input_event(input, EV_ABS, ABS_MT_POSITION_Y, *slot->y); input_event(input, EV_ABS, ABS_MT_TOOL_X, *slot->cx); input_event(input, EV_ABS, ABS_MT_TOOL_Y, *slot->cy); x = hdev->quirks & HID_QUIRK_X_INVERT ? input_abs_get_max(input, ABS_MT_POSITION_X) - *slot->x : *slot->x; y = hdev->quirks & HID_QUIRK_Y_INVERT ? input_abs_get_max(input, ABS_MT_POSITION_Y) - *slot->y : *slot->y; cx = hdev->quirks & HID_QUIRK_X_INVERT ? input_abs_get_max(input, ABS_MT_POSITION_X) - *slot->cx : *slot->cx; cy = hdev->quirks & HID_QUIRK_Y_INVERT ? input_abs_get_max(input, ABS_MT_POSITION_Y) - *slot->cy : *slot->cy; input_event(input, EV_ABS, ABS_MT_POSITION_X, x); input_event(input, EV_ABS, ABS_MT_POSITION_Y, y); input_event(input, EV_ABS, ABS_MT_TOOL_X, cx); input_event(input, EV_ABS, ABS_MT_TOOL_Y, cy); input_event(input, EV_ABS, ABS_MT_DISTANCE, !*slot->tip_state); input_event(input, EV_ABS, ABS_MT_ORIENTATION, orientation); input_event(input, EV_ABS, ABS_MT_PRESSURE, *slot->p); Loading Loading @@ -1735,6 +1757,15 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID) td->serial_maybe = true; /* Orientation is inverted if the X or Y axes are * flipped, but normalized if both are inverted. */ if (hdev->quirks & (HID_QUIRK_X_INVERT | HID_QUIRK_Y_INVERT) && !((hdev->quirks & HID_QUIRK_X_INVERT) && (hdev->quirks & HID_QUIRK_Y_INVERT))) td->mtclass.quirks = MT_QUIRK_ORIENTATION_INVERT; /* This allows the driver to correctly support devices * that emit events over several HID messages. */ Loading
drivers/hid/hid-quirks.c +1 −1 Original line number Diff line number Diff line Loading @@ -1237,7 +1237,7 @@ EXPORT_SYMBOL_GPL(hid_quirks_exit); static unsigned long hid_gets_squirk(const struct hid_device *hdev) { const struct hid_device_id *bl_entry; unsigned long quirks = 0; unsigned long quirks = hdev->initial_quirks; if (hid_match_id(hdev, hid_ignore_list)) quirks |= HID_QUIRK_IGNORE; Loading
drivers/hid/i2c-hid/i2c-hid-core.c +4 −2 Original line number Diff line number Diff line Loading @@ -1025,6 +1025,10 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID); hid->product = le16_to_cpu(ihid->hdesc.wProductID); hid->initial_quirks = quirks; hid->initial_quirks |= i2c_hid_get_dmi_quirks(hid->vendor, hid->product); snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", client->name, (u16)hid->vendor, (u16)hid->product); strscpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys)); Loading @@ -1038,8 +1042,6 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, goto err_mem_free; } hid->quirks |= quirks; return 0; err_mem_free: Loading
drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c +42 −0 Original line number Diff line number Diff line Loading @@ -10,8 +10,10 @@ #include <linux/types.h> #include <linux/dmi.h> #include <linux/mod_devicetable.h> #include <linux/hid.h> #include "i2c-hid.h" #include "../hid-ids.h" struct i2c_hid_desc_override { Loading Loading @@ -416,6 +418,28 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = { { } /* Terminate list */ }; static const struct hid_device_id i2c_hid_elan_flipped_quirks = { HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, USB_VENDOR_ID_ELAN, 0x2dcd), HID_QUIRK_X_INVERT | HID_QUIRK_Y_INVERT }; /* * This list contains devices which have specific issues based on the system * they're on and not just the device itself. The driver_data will have a * specific hid device to match against. */ static const struct dmi_system_id i2c_hid_dmi_quirk_table[] = { { .ident = "DynaBook K50/FR", .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dynabook Inc."), DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "dynabook K50/FR"), }, .driver_data = (void *)&i2c_hid_elan_flipped_quirks, }, { } /* Terminate list */ }; struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name) { Loading Loading @@ -450,3 +474,21 @@ char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name, *size = override->hid_report_desc_size; return override->hid_report_desc; } u32 i2c_hid_get_dmi_quirks(const u16 vendor, const u16 product) { u32 quirks = 0; const struct dmi_system_id *system_id = dmi_first_match(i2c_hid_dmi_quirk_table); if (system_id) { const struct hid_device_id *device_id = (struct hid_device_id *)(system_id->driver_data); if (device_id && device_id->vendor == vendor && device_id->product == product) quirks = device_id->driver_data; } return quirks; }
drivers/hid/i2c-hid/i2c-hid.h +3 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name); char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name, unsigned int *size); u32 i2c_hid_get_dmi_quirks(const u16 vendor, const u16 product); #else static inline struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name) Loading @@ -16,6 +17,8 @@ static inline struct i2c_hid_desc static inline char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name, unsigned int *size) { return NULL; } static inline u32 i2c_hid_get_dmi_quirks(const u16 vendor, const u16 product) { return 0; } #endif /** Loading