From: Steve Oswald <stevepeter.oswald@xxxxxxxxx> --- drivers/hid/hid-ids.h | 3 ++ drivers/hid/hid-lofree.c | 96 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 drivers/hid/hid-lofree.c diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 33cc5820f2be..cb2704550043 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -848,6 +848,9 @@ #define USB_DEVICE_ID_PXN_V12_LITE_2 0x1211 #define USB_DEVICE_LITE_STAR_GT987_FF 0x2141 +#define USB_VENDOR_ID_LOFREE 0x248A +#define USB_VENDOR_ID_LOFREE_TOUCH 0x8266 + #define USB_VENDOR_ID_LOGITECH 0x046d #define USB_DEVICE_ID_LOGITECH_Z_10_SPK 0x0a07 #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e diff --git a/drivers/hid/hid-lofree.c b/drivers/hid/hid-lofree.c new file mode 100644 index 000000000000..89383527e519 --- /dev/null +++ b/drivers/hid/hid-lofree.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Custom HID driver for Lofree products + * Adds support for Back (BTN_SIDE) and Forward (BTN_EXTRA) buttons + * + * Copyright (c) 2025 Steve Oswald + * based on hid-cherry + */ + +#include <linux/module.h> +#include <linux/hid.h> +#include <linux/input.h> +#include "hid-ids.h" + +/* + * Remaps back/forward buttons to input events for Lofree Touch. + */ +static int lofree_touch_raw_event(struct hid_device *hdev, + struct hid_report *report, u8 *data, int size) +{ + struct hid_input *hidinput; + struct input_dev *input; + + if (report->id != 3) + return 0; + + list_for_each_entry(hidinput, &hdev->inputs, list) { + input = hidinput->input; + input_report_key(input, BTN_SIDE, !!(data[1] & 0x08)); + input_report_key(input, BTN_EXTRA, !!(data[1] & 0x10)); + input_sync(input); + } + + return 0; +} + +/* + * Apply capabilities. + */ +static int lofree_touch_input_configured(struct hid_device *hdev, + struct hid_input *hi) +{ + struct input_dev *input = hi->input; + + input_set_capability(input, EV_KEY, BTN_SIDE); + input_set_capability(input, EV_KEY, BTN_EXTRA); + + return 0; +} + +static int lofree_probe(struct hid_device *hdev, const struct hid_device_id *id) +{ + int ret; + + ret = hid_parse(hdev); + if (ret) { + hid_err(hdev, "HID parse failed\n"); + return ret; + } + + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + if (ret) { + hid_err(hdev, "HID hw start failed\n"); + return ret; + } + + hid_info(hdev, "Touch@LOFREE custom HID driver loaded\n"); + return 0; +} + +static void lofree_remove(struct hid_device *hdev) +{ + hid_hw_stop(hdev); +} + +static const struct hid_device_id lofree_touch_devices[] = { + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOFREE, + USB_VENDOR_ID_LOFREE_TOUCH) }, + {} +}; +MODULE_DEVICE_TABLE(hid, lofree_touch_devices); + +static struct hid_driver lofree_touch_driver = { + .name = "hid_lofree_touch", + .id_table = lofree_touch_devices, + .probe = lofree_probe, + .remove = lofree_remove, + .raw_event = lofree_touch_raw_event, + .input_configured = lofree_touch_input_configured, +}; + +module_hid_driver(lofree_touch_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION( + "HID driver for some special Lofree devices like Lofree Touch mouse."); -- 2.48.1