Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

HID: Add driver to fix Speedlink VAD Cezanne support

Speedlink VAD Cezanne have a hardware bug that makes the cursor "jump" from one
place to another every now and then. The issue are relative motion events
erroneously reported by the device, each having a distance value of +256. This
256 can in fact never occur due to real motion, therefore those events can
safely be ignored. The driver also drops useless EV_REL events with a value of
0, that the device sends every time it sends an "real" EV_REL or EV_KEY event.

Signed-off-by: Stefan Kriwanek <mail@stefankriwanek.de>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>

authored by

Stefan Kriwanek and committed by
Jiri Kosina
74bc6953 dc0a4f0c

+100
+6
drivers/hid/Kconfig
··· 494 494 ---help--- 495 495 Support for Sony PS3 controller. 496 496 497 + config HID_SPEEDLINK 498 + tristate "Speedlink VAD Cezanne mouse support" 499 + depends on USB_HID 500 + ---help--- 501 + Support for Speedlink Vicious and Divine Cezanne mouse. 502 + 497 503 config HID_SUNPLUS 498 504 tristate "Sunplus wireless desktop" 499 505 depends on USB_HID
+1
drivers/hid/Makefile
··· 63 63 obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o 64 64 obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o 65 65 obj-$(CONFIG_HID_SONY) += hid-sony.o 66 + obj-$(CONFIG_HID_SPEEDLINK) += hid-speedlink.o 66 67 obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o 67 68 obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o 68 69 obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o
+1
drivers/hid/hid-core.c
··· 1497 1497 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, 1498 1498 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, 1499 1499 { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, 1500 + { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) }, 1500 1501 { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, 1501 1502 { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, 1502 1503 { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) },
+3
drivers/hid/hid-ids.h
··· 658 658 #define USB_VENDOR_ID_WISEGROUP_LTD2 0x6677 659 659 #define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802 660 660 661 + #define USB_VENDOR_ID_X_TENSIONS 0x1ae7 662 + #define USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE 0x9001 663 + 661 664 #define USB_VENDOR_ID_YEALINK 0x6993 662 665 #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001 663 666
+89
drivers/hid/hid-speedlink.c
··· 1 + /* 2 + * HID driver for Speedlink Vicious and Divine Cezanne (USB mouse). 3 + * Fixes "jumpy" cursor and removes nonexistent keyboard LEDS from 4 + * the HID descriptor. 5 + * 6 + * Copyright (c) 2011 Stefan Kriwanek <mail@stefankriwanek.de> 7 + */ 8 + 9 + /* 10 + * This program is free software; you can redistribute it and/or modify it 11 + * under the terms of the GNU General Public License as published by the Free 12 + * Software Foundation; either version 2 of the License, or (at your option) 13 + * any later version. 14 + */ 15 + 16 + #include <linux/device.h> 17 + #include <linux/hid.h> 18 + #include <linux/module.h> 19 + #include <linux/usb.h> 20 + 21 + #include "hid-ids.h" 22 + #include "usbhid/usbhid.h" 23 + 24 + static const struct hid_device_id speedlink_devices[] = { 25 + { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE)}, 26 + { } 27 + }; 28 + 29 + static int speedlink_input_mapping(struct hid_device *hdev, 30 + struct hid_input *hi, 31 + struct hid_field *field, struct hid_usage *usage, 32 + unsigned long **bit, int *max) 33 + { 34 + /* 35 + * The Cezanne mouse has a second "keyboard" USB endpoint for it is 36 + * able to map keyboard events to the button presses. 37 + * It sends a standard keyboard report descriptor, though, whose 38 + * LEDs we ignore. 39 + */ 40 + switch (usage->hid & HID_USAGE_PAGE) { 41 + case HID_UP_LED: 42 + return -1; 43 + } 44 + return 0; 45 + } 46 + 47 + static int speedlink_event(struct hid_device *hdev, struct hid_field *field, 48 + struct hid_usage *usage, __s32 value) 49 + { 50 + /* No other conditions due to usage_table. */ 51 + /* Fix "jumpy" cursor (invalid events sent by device). */ 52 + if (value == 256) 53 + return 1; 54 + /* Drop useless distance 0 events (on button clicks etc.) as well */ 55 + if (value == 0) 56 + return 1; 57 + 58 + return 0; 59 + } 60 + 61 + MODULE_DEVICE_TABLE(hid, speedlink_devices); 62 + 63 + static const struct hid_usage_id speedlink_grabbed_usages[] = { 64 + { HID_GD_X, EV_REL, 0 }, 65 + { HID_GD_Y, EV_REL, 1 }, 66 + { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} 67 + }; 68 + 69 + static struct hid_driver speedlink_driver = { 70 + .name = "speedlink", 71 + .id_table = speedlink_devices, 72 + .usage_table = speedlink_grabbed_usages, 73 + .input_mapping = speedlink_input_mapping, 74 + .event = speedlink_event, 75 + }; 76 + 77 + static int __init speedlink_init(void) 78 + { 79 + return hid_register_driver(&speedlink_driver); 80 + } 81 + 82 + static void __exit speedlink_exit(void) 83 + { 84 + hid_unregister_driver(&speedlink_driver); 85 + } 86 + 87 + module_init(speedlink_init); 88 + module_exit(speedlink_exit); 89 + MODULE_LICENSE("GPL");