@@ -224,6 +224,16 @@ config HID_LCPOWER
---help---
Support for LC-Power RC1000MCE RF remote control.
+config HID_LENOVO_TPKBD
+ tristate "Lenovo ThinkPad USB Keyboard with TrackPoint"
+ depends on USB_HID
+ ---help---
+ Support for the Lenovo ThinkPad USB Keyboard with TrackPoint.
+
+ Say Y here if you have a Lenovo ThinkPad USB Keyboard with TrackPoint
+ and would like to change the sensitivity of the trackpoint using a
+ sysfs attribute.
+
config HID_LOGITECH
tristate "Logitech devices" if EXPERT
depends on USB_HID
@@ -41,6 +41,7 @@ obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o
obj-$(CONFIG_HID_KYE) += hid-kye.o
obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o
+obj-$(CONFIG_HID_LENOVO_TPKBD) += hid-lenovo-tpkbd.o
obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o
obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o
@@ -1394,6 +1394,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
@@ -413,6 +413,9 @@
#define USB_DEVICE_ID_LD_HYBRID 0x2090
#define USB_DEVICE_ID_LD_HEATCONTROL 0x20A0
+#define USB_VENDOR_ID_LENOVO 0x17ef
+#define USB_DEVICE_ID_LENOVO_TPKBD 0x6009
+
#define USB_VENDOR_ID_LOGITECH 0x046d
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
#define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110
new file mode 100644
@@ -0,0 +1,166 @@
+/*
+ * HID driver for Lenovo ThinkPad USB Keyboard with TrackPoint
+ *
+ * Copyright (c) 2011 Bernhard Seibold
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/sysfs.h>
+#include <linux/device.h>
+#include <linux/usb.h>
+#include <linux/hid.h>
+#include <linux/input.h>
+#include "usbhid/usbhid.h"
+
+#include "hid-ids.h"
+
+static int lenovo_tpkbd_input_mapping(struct hid_device *hdev,
+ struct hid_input *hi, struct hid_field *field,
+ struct hid_usage *usage, unsigned long **bit, int *max)
+{
+ return 0;
+}
+
+static ssize_t pointer_sensitivity_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct hid_device *hdev;
+ struct hid_report *report;
+ hdev = container_of(dev, struct hid_device, dev);
+
+ if (hdev == NULL)
+ return -ENODEV;
+
+ report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4];
+ usbhid_submit_report(hdev, report, USB_DIR_IN);
+ usbhid_wait_io(hdev);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ report->field[2]->value[0]);
+}
+
+static ssize_t pointer_sensitivity_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct hid_device *hdev;
+ struct hid_report *report;
+ int value;
+
+ if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
+ return -EINVAL;
+
+ hdev = container_of(dev, struct hid_device, dev);
+ if (hdev == NULL)
+ return -ENODEV;
+
+ report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4];
+ usbhid_submit_report(hdev, report, USB_DIR_IN);
+ usbhid_wait_io(hdev);
+ report->field[0]->value[0] = 0x6a;
+ report->field[1]->value[0] = 0x03;
+ report->field[2]->value[0] = value;
+ report->field[3]->value[0] = 0x38;
+ usbhid_submit_report(hdev, report, USB_DIR_OUT);
+ return count;
+}
+
+static struct device_attribute dev_attr_pointer_sensitivity =
+ __ATTR(sensitivity, S_IWUSR | S_IRUGO,
+ pointer_sensitivity_show,
+ pointer_sensitivity_store);
+
+static struct attribute *lenovo_tpkbd_attributes_pointer[] = {
+ &dev_attr_pointer_sensitivity.attr,
+ NULL
+};
+
+static const struct attribute_group lenovo_tpkbd_attr_group_pointer = {
+ .attrs = lenovo_tpkbd_attributes_pointer,
+};
+
+static int lenovo_tpkbd_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
+{
+ int ret;
+ struct usbhid_device *uhdev;
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ hid_err(hdev, "hid_parse failed\n");
+ goto err_free;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ if (ret) {
+ hid_err(hdev, "hid_hw_start failed\n");
+ goto err_free;
+ }
+
+ uhdev = (struct usbhid_device *) hdev->driver_data;
+
+ if (uhdev->ifnum == 1) {
+ if (sysfs_create_group(&hdev->dev.kobj,
+ &lenovo_tpkbd_attr_group_pointer)) {
+ printk(KERN_WARNING "hid-lenovo-tpkbd: Could not "
+ "create sysfs group\n");
+ }
+
+ }
+
+ return 0;
+err_free:
+ return ret;
+}
+
+static void lenovo_tpkbd_remove(struct hid_device *hdev)
+{
+ struct usbhid_device *uhdev;
+
+ uhdev = (struct usbhid_device *) hdev->driver_data;
+
+ if (uhdev->ifnum == 1)
+ sysfs_remove_group(&hdev->dev.kobj,
+ &lenovo_tpkbd_attr_group_pointer);
+
+ hid_hw_stop(hdev);
+}
+
+static const struct hid_device_id lenovo_tpkbd_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
+ { }
+};
+
+MODULE_DEVICE_TABLE(hid, lenovo_tpkbd_devices);
+
+static struct hid_driver lenovo_tpkbd_driver = {
+ .name = "lenovo_tpkbd",
+ .id_table = lenovo_tpkbd_devices,
+ .input_mapping = lenovo_tpkbd_input_mapping,
+ .probe = lenovo_tpkbd_probe,
+ .remove = lenovo_tpkbd_remove,
+};
+
+static int __init lenovo_tpkbd_init(void)
+{
+ return hid_register_driver(&lenovo_tpkbd_driver);
+}
+
+static void __exit lenovo_tpkbd_exit(void)
+{
+ hid_unregister_driver(&lenovo_tpkbd_driver);
+}
+
+module_init(lenovo_tpkbd_init);
+module_exit(lenovo_tpkbd_exit);
+
+MODULE_LICENSE("GPL");
This patch adds support for setting the trackpoint sensitivity of the "Lenovo ThinkPad USB Keyboard with Trackpoint". Signed-off-by: Bernhard Seibold <mail@bernhard-seibold.de> --- drivers/hid/Kconfig | 10 +++ drivers/hid/Makefile | 1 + drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 3 + drivers/hid/hid-lenovo-tpkbd.c | 166 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 181 insertions(+), 0 deletions(-) create mode 100644 drivers/hid/hid-lenovo-tpkbd.c