hid-xiaomi.c 4.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * HID driver for Xiaomi Mi Dual Mode Wireless Mouse Silent Edition
  4. *
  5. * Copyright (c) 2021 Ilya Skriblovsky
  6. */
  7. #include <linux/init.h>
  8. #include <linux/module.h>
  9. #include <linux/hid.h>
  10. #include "hid-ids.h"
  11. /* Fixed Mi Silent Mouse report descriptor */
  12. /* Button's Usage Maximum changed from 3 to 5 to make side buttons work */
  13. #define MI_SILENT_MOUSE_ORIG_RDESC_LENGTH 87
  14. static __u8 mi_silent_mouse_rdesc_fixed[] = {
  15. 0x05, 0x01, /* Usage Page (Desktop), */
  16. 0x09, 0x02, /* Usage (Mouse), */
  17. 0xA1, 0x01, /* Collection (Application), */
  18. 0x85, 0x03, /* Report ID (3), */
  19. 0x09, 0x01, /* Usage (Pointer), */
  20. 0xA1, 0x00, /* Collection (Physical), */
  21. 0x05, 0x09, /* Usage Page (Button), */
  22. 0x19, 0x01, /* Usage Minimum (01h), */
  23. 0x29, 0x05, /* X */ /* Usage Maximum (05h), */
  24. 0x15, 0x00, /* Logical Minimum (0), */
  25. 0x25, 0x01, /* Logical Maximum (1), */
  26. 0x75, 0x01, /* Report Size (1), */
  27. 0x95, 0x05, /* Report Count (5), */
  28. 0x81, 0x02, /* Input (Variable), */
  29. 0x75, 0x03, /* Report Size (3), */
  30. 0x95, 0x01, /* Report Count (1), */
  31. 0x81, 0x01, /* Input (Constant), */
  32. 0x05, 0x01, /* Usage Page (Desktop), */
  33. 0x09, 0x30, /* Usage (X), */
  34. 0x09, 0x31, /* Usage (Y), */
  35. 0x15, 0x81, /* Logical Minimum (-127), */
  36. 0x25, 0x7F, /* Logical Maximum (127), */
  37. 0x75, 0x08, /* Report Size (8), */
  38. 0x95, 0x02, /* Report Count (2), */
  39. 0x81, 0x06, /* Input (Variable, Relative), */
  40. 0x09, 0x38, /* Usage (Wheel), */
  41. 0x15, 0x81, /* Logical Minimum (-127), */
  42. 0x25, 0x7F, /* Logical Maximum (127), */
  43. 0x75, 0x08, /* Report Size (8), */
  44. 0x95, 0x01, /* Report Count (1), */
  45. 0x81, 0x06, /* Input (Variable, Relative), */
  46. 0xC0, /* End Collection, */
  47. 0xC0, /* End Collection, */
  48. 0x06, 0x01, 0xFF, /* Usage Page (FF01h), */
  49. 0x09, 0x01, /* Usage (01h), */
  50. 0xA1, 0x01, /* Collection (Application), */
  51. 0x85, 0x05, /* Report ID (5), */
  52. 0x09, 0x05, /* Usage (05h), */
  53. 0x15, 0x00, /* Logical Minimum (0), */
  54. 0x26, 0xFF, 0x00, /* Logical Maximum (255), */
  55. 0x75, 0x08, /* Report Size (8), */
  56. 0x95, 0x04, /* Report Count (4), */
  57. 0xB1, 0x02, /* Feature (Variable), */
  58. 0xC0 /* End Collection */
  59. };
  60. static __u8 *xiaomi_report_fixup(struct hid_device *hdev, __u8 *rdesc,
  61. unsigned int *rsize)
  62. {
  63. switch (hdev->product) {
  64. case USB_DEVICE_ID_MI_SILENT_MOUSE:
  65. if (*rsize == MI_SILENT_MOUSE_ORIG_RDESC_LENGTH) {
  66. hid_info(hdev, "fixing up Mi Silent Mouse report descriptor\n");
  67. rdesc = mi_silent_mouse_rdesc_fixed;
  68. *rsize = sizeof(mi_silent_mouse_rdesc_fixed);
  69. }
  70. break;
  71. }
  72. return rdesc;
  73. }
  74. static const struct hid_device_id xiaomi_devices[] = {
  75. { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_XIAOMI, USB_DEVICE_ID_MI_SILENT_MOUSE) },
  76. { }
  77. };
  78. MODULE_DEVICE_TABLE(hid, xiaomi_devices);
  79. static struct hid_driver xiaomi_driver = {
  80. .name = "xiaomi",
  81. .id_table = xiaomi_devices,
  82. .report_fixup = xiaomi_report_fixup,
  83. };
  84. module_hid_driver(xiaomi_driver);
  85. MODULE_LICENSE("GPL");
  86. MODULE_AUTHOR("Ilya Skriblovsky <[email protected]>");
  87. MODULE_DESCRIPTION("Fixing side buttons of Xiaomi Mi Silent Mouse");