hid-speedlink.c 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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, 2013 Stefan Kriwanek <dev@stefankriwanek.de>
  7. */
  8. /*
  9. * This program is free software; you can redistribute it and/or modify it
  10. * under the terms of the GNU General Public License as published by the Free
  11. * Software Foundation; either version 2 of the License, or (at your option)
  12. * any later version.
  13. */
  14. #include <linux/device.h>
  15. #include <linux/hid.h>
  16. #include <linux/module.h>
  17. #include <linux/usb.h>
  18. #include "hid-ids.h"
  19. #include "usbhid/usbhid.h"
  20. static const struct hid_device_id speedlink_devices[] = {
  21. { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE)},
  22. { }
  23. };
  24. static int speedlink_input_mapping(struct hid_device *hdev,
  25. struct hid_input *hi,
  26. struct hid_field *field, struct hid_usage *usage,
  27. unsigned long **bit, int *max)
  28. {
  29. /*
  30. * The Cezanne mouse has a second "keyboard" USB endpoint for it is
  31. * able to map keyboard events to the button presses.
  32. * It sends a standard keyboard report descriptor, though, whose
  33. * LEDs we ignore.
  34. */
  35. switch (usage->hid & HID_USAGE_PAGE) {
  36. case HID_UP_LED:
  37. return -1;
  38. }
  39. return 0;
  40. }
  41. static int speedlink_event(struct hid_device *hdev, struct hid_field *field,
  42. struct hid_usage *usage, __s32 value)
  43. {
  44. /* No other conditions due to usage_table. */
  45. /* This fixes the "jumpy" cursor occuring due to invalid events sent
  46. * by the device. Some devices only send them with value==+256, others
  47. * don't. However, catching abs(value)>=256 is restrictive enough not
  48. * to interfere with devices that were bug-free (has been tested).
  49. */
  50. if (abs(value) >= 256)
  51. return 1;
  52. /* Drop useless distance 0 events (on button clicks etc.) as well */
  53. if (value == 0)
  54. return 1;
  55. return 0;
  56. }
  57. MODULE_DEVICE_TABLE(hid, speedlink_devices);
  58. static const struct hid_usage_id speedlink_grabbed_usages[] = {
  59. { HID_GD_X, EV_REL, 0 },
  60. { HID_GD_Y, EV_REL, 1 },
  61. { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
  62. };
  63. static struct hid_driver speedlink_driver = {
  64. .name = "speedlink",
  65. .id_table = speedlink_devices,
  66. .usage_table = speedlink_grabbed_usages,
  67. .input_mapping = speedlink_input_mapping,
  68. .event = speedlink_event,
  69. };
  70. static int __init speedlink_init(void)
  71. {
  72. return hid_register_driver(&speedlink_driver);
  73. }
  74. static void __exit speedlink_exit(void)
  75. {
  76. hid_unregister_driver(&speedlink_driver);
  77. }
  78. module_init(speedlink_init);
  79. module_exit(speedlink_exit);
  80. MODULE_LICENSE("GPL");