diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-05-24 15:21:15 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-05-24 15:21:15 -0700 |
commit | aa051d36ce4ae23b488489f6b15abad68b59ca23 (patch) | |
tree | 24056e248d202ae3d7bbf413ecfb3d4ec5490a9c /drivers/hid/hid-uclogic-core.c | |
parent | d8e0f976f104a0258c0426b3805b057411cd0bd2 (diff) | |
parent | 07d17217c668d5b9974572b2d69c6736f60b9925 (diff) |
Merge tag 'for-linus-2022052401' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID updates from Jiri Kosina:
- support for pens with 3 buttons with Wacom driver (Joshua Dickens)
- support for HID_DG_SCANTIME to report the timestamp for pen and touch
events in Wacom driver (Joshua Dickens)
- support for sensor discovery in amd-sfh driver (Basavaraj Natikar)
- support for wider variety of Huion tablets ported from DIGImend
project (José Expósito, Nikolai Kondrashov)
- new device IDs and other assorted small code cleanups
* tag 'for-linus-2022052401' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (44 commits)
HID: apple: Properly handle function keys on Keychron keyboards
HID: uclogic: Switch to Digitizer usage for styluses
HID: uclogic: Add pen support for XP-PEN Star 06
HID: uclogic: Differentiate touch ring and touch strip
HID: uclogic: Always shift touch reports to zero
HID: uclogic: Do not focus on touch ring only
HID: uclogic: Return raw parameters from v2 pen init
HID: uclogic: Move param printing to a function
HID: core: Display "SENSOR HUB" for sensor hub bus string in hid_info
HID: amd_sfh: Move bus declaration outside of amd-sfh
HID: amd_sfh: Add physical location to HID device
HID: amd_sfh: Modify the hid name
HID: amd_sfh: Modify the bus name
HID: amd_sfh: Add sensor name by index for debug info
HID: amd_sfh: Add support for sensor discovery
HID: bigben: fix slab-out-of-bounds Write in bigben_probe
Hid: wacom: Fix kernel test robot warning
HID: uclogic: Disable pen usage for Huion keyboard interfaces
HID: uclogic: Support disabling pen usage
HID: uclogic: Pass keyboard reports as is
...
Diffstat (limited to 'drivers/hid/hid-uclogic-core.c')
-rw-r--r-- | drivers/hid/hid-uclogic-core.c | 113 |
1 files changed, 90 insertions, 23 deletions
diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index 05147f2d7564..c0fe66e50c58 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -81,6 +81,24 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, return rdesc; } +static int uclogic_input_mapping(struct hid_device *hdev, + struct hid_input *hi, + struct hid_field *field, + struct hid_usage *usage, + unsigned long **bit, + int *max) +{ + struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); + struct uclogic_params *params = &drvdata->params; + + /* Discard invalid pen usages */ + if (params->pen.usage_invalid && (field->application == HID_DG_PEN)) + return -1; + + /* Let hid-core decide what to do */ + return 0; +} + static int uclogic_input_configured(struct hid_device *hdev, struct hid_input *hi) { @@ -90,6 +108,8 @@ static int uclogic_input_configured(struct hid_device *hdev, const char *suffix = NULL; struct hid_field *field; size_t len; + size_t i; + const struct uclogic_params_frame *frame; /* no report associated (HID_QUIRK_MULTI_INPUT not set) */ if (!hi->report) @@ -104,27 +124,44 @@ static int uclogic_input_configured(struct hid_device *hdev, drvdata->pen_input = hi->input; } - field = hi->report->field[0]; + /* If it's one of the frame devices */ + for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) { + frame = ¶ms->frame_list[i]; + if (hi->report->id == frame->id) { + /* Assign custom suffix, if any */ + suffix = frame->suffix; + /* + * Disable EV_MSC reports for touch ring interfaces to + * make the Wacom driver pickup touch ring extents + */ + if (frame->touch_byte > 0) + __clear_bit(EV_MSC, hi->input->evbit); + } + } - switch (field->application) { - case HID_GD_KEYBOARD: - suffix = "Keyboard"; - break; - case HID_GD_MOUSE: - suffix = "Mouse"; - break; - case HID_GD_KEYPAD: - suffix = "Pad"; - break; - case HID_DG_PEN: - suffix = "Pen"; - break; - case HID_CP_CONSUMER_CONTROL: - suffix = "Consumer Control"; - break; - case HID_GD_SYSTEM_CONTROL: - suffix = "System Control"; - break; + if (!suffix) { + field = hi->report->field[0]; + + switch (field->application) { + case HID_GD_KEYBOARD: + suffix = "Keyboard"; + break; + case HID_GD_MOUSE: + suffix = "Mouse"; + break; + case HID_GD_KEYPAD: + suffix = "Pad"; + break; + case HID_DG_PEN: + suffix = "Pen"; + break; + case HID_CP_CONSUMER_CONTROL: + suffix = "Consumer Control"; + break; + case HID_GD_SYSTEM_CONTROL: + suffix = "System Control"; + break; + } } if (suffix) { @@ -172,8 +209,8 @@ static int uclogic_probe(struct hid_device *hdev, goto failure; } params_initialized = true; - hid_dbg(hdev, "parameters:\n" UCLOGIC_PARAMS_FMT_STR, - UCLOGIC_PARAMS_FMT_ARGS(&drvdata->params)); + hid_dbg(hdev, "parameters:\n"); + uclogic_params_hid_dbg(hdev, &drvdata->params); if (drvdata->params.invalid) { hid_info(hdev, "interface is invalid, ignoring\n"); rc = -ENODEV; @@ -313,8 +350,15 @@ static int uclogic_raw_event_frame( /* If need to, and can, set pad device ID for Wacom drivers */ if (frame->dev_id_byte > 0 && frame->dev_id_byte < size) { - data[frame->dev_id_byte] = 0xf; + /* If we also have a touch ring and the finger left it */ + if (frame->touch_byte > 0 && frame->touch_byte < size && + data[frame->touch_byte] == 0) { + data[frame->dev_id_byte] = 0; + } else { + data[frame->dev_id_byte] = 0xf; + } } + /* If need to, and can, read rotary encoder state change */ if (frame->re_lsb > 0 && frame->re_lsb / 8 < size) { unsigned int byte = frame->re_lsb / 8; @@ -341,6 +385,26 @@ static int uclogic_raw_event_frame( drvdata->re_state = state; } + /* If need to, and can, transform the touch ring reports */ + if (frame->touch_byte > 0 && frame->touch_byte < size) { + __s8 value = data[frame->touch_byte]; + + if (value != 0) { + if (frame->touch_flip_at != 0) { + value = frame->touch_flip_at - value; + if (value <= 0) + value = frame->touch_max + value; + } + data[frame->touch_byte] = value - 1; + } + } + + /* If need to, and can, transform the bitmap dial reports */ + if (frame->bitmap_dial_byte > 0 && frame->bitmap_dial_byte < size) { + if (data[frame->bitmap_dial_byte] == 2) + data[frame->bitmap_dial_byte] = -1; + } + return 0; } @@ -457,6 +521,8 @@ static const struct hid_device_id uclogic_devices[] = { USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640) }, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, + USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06) }, { } }; MODULE_DEVICE_TABLE(hid, uclogic_devices); @@ -468,6 +534,7 @@ static struct hid_driver uclogic_driver = { .remove = uclogic_remove, .report_fixup = uclogic_report_fixup, .raw_event = uclogic_raw_event, + .input_mapping = uclogic_input_mapping, .input_configured = uclogic_input_configured, #ifdef CONFIG_PM .resume = uclogic_resume, |