From 0aba665489c8f16ebb96c17f619211c0f43337a1 Mon Sep 17 00:00:00 2001 From: Arne Keller Date: Mon, 13 Sep 2021 09:53:24 +0200 Subject: [PATCH] Initial commit --- Makefile | 1 + hid-microsoft-ergonomic.c | 109 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 Makefile create mode 100644 hid-microsoft-ergonomic.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4c76df6 --- /dev/null +++ b/Makefile @@ -0,0 +1 @@ +obj-m += hid-microsoft-ergonomic.o diff --git a/hid-microsoft-ergonomic.c b/hid-microsoft-ergonomic.c new file mode 100644 index 0000000..4308512 --- /dev/null +++ b/hid-microsoft-ergonomic.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * HID driver for the microsoft ergonomic keyboard + * + * Copyright (c) 2021 Arne Keller + */ + +#include +#include +#include +#include + +#define USB_VENDOR_ID_MICROSOFT 0x045e +#define USB_DEVICE_ID_MS_ERGONOMIC_KEYBOARD 0x082c +#define MS_ERGONOMY2 BIT(8) + +struct ms_data { + unsigned long quirks; + struct hid_device *hdev; + __u8 strong; + __u8 weak; + void *output_report_dmabuf; +}; + + +static int ms_raw_event(struct hid_device *hdev, struct hid_report *report, + u8 *data, int size) +{ + struct ms_data *ms = hid_get_drvdata(hdev); + unsigned long quirks = ms->quirks; + + if (!(hdev->claimed & HID_CLAIMED_INPUT)) + return 0; + + if (quirks & MS_ERGONOMY2) { + if (size == 8 && ((data[1] & 0x0f) == 0x0f)) { + hid_info(hdev, "remapped button %x :)", data[1]); + // weird Office button just simulates Left Shift + Ctrl + Alt + Super! + data[1] |= 0x80; // other combination keys might also be pressed! + data[1] &= 0xf0; // clear the 4 key mess + } + /* + hid_info(hdev, "event of size %d", size); + int size2 = size; + while (size2 > 0) { + printk(KERN_CONT " %x", *data); + size2--; + data++; + } + printk(KERN_CONT "\n"); + */ + } + return 0; +} + +static int ms_probe(struct hid_device *hdev, const struct hid_device_id *id) +{ + unsigned long quirks = id->driver_data; + struct ms_data *ms; + int ret; + + ms = devm_kzalloc(&hdev->dev, sizeof(*ms), GFP_KERNEL); + if (ms == NULL) + return -ENOMEM; + + ms->quirks = quirks; + + hid_set_drvdata(hdev, ms); + + ret = hid_parse(hdev); + if (ret) { + hid_err(hdev, "parse failed\n"); + goto err_free; + } + + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + if (ret) { + hid_err(hdev, "hw start failed\n"); + goto err_free; + } + + return 0; +err_free: + return ret; +} + +static void ms_remove(struct hid_device *hdev) +{ + hid_hw_stop(hdev); +} + +static const struct hid_device_id ms_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_ERGONOMIC_KEYBOARD), + .driver_data = MS_ERGONOMY2}, + { } +}; +MODULE_DEVICE_TABLE(hid, ms_devices); + +static struct hid_driver ms_driver = { + .name = "microsoft_ergonomic", + .id_table = ms_devices, + .raw_event = ms_raw_event, + .probe = ms_probe, + .remove = ms_remove, +}; +module_hid_driver(ms_driver); + +MODULE_LICENSE("GPL"); +