GoogleGit

blob: eff0b450b981e368661675d6c09b6eb1c935114d [file] [log] [blame]
  1. /*
  2. * HID driver for Google Fiber TV remote controls
  3. *
  4. * Copyright (c) 2014 Google Inc.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the Free
  8. * Software Foundation; either version 2 of the License, or (at your option)
  9. * any later version.
  10. */
  11. #include <linux/device.h>
  12. #include <linux/hid.h>
  13. #include <linux/module.h>
  14. #include <linux/slab.h>
  15. #include <linux/usb.h>
  16. #include "hid-ids.h"
  17. #define GFRM100 1 /* Google Fiber GFRM100 (Bluetooth classic) */
  18. #define GFRM200 2 /* Google Fiber GFRM200 (Bluetooth LE) */
  19. #define TIARC 3 /* Texas Instruments CC2541ARC (Bluetooth LE) */
  20. #define GFRM100_SEARCH_KEY_REPORT_ID 0xF7
  21. #define GFRM100_SEARCH_KEY_DOWN 0x0
  22. #define GFRM100_SEARCH_KEY_AUDIO_DATA 0x1
  23. #define GFRM100_SEARCH_KEY_UP 0x2
  24. static u8 search_key_dn[3] = {0x40, 0xF7, 0x00};
  25. static u8 search_key_up[3] = {0x40, 0x00, 0x00};
  26. static int gfrm_input_mapped(struct hid_device *hdev, struct hid_input *hi,
  27. struct hid_field *field, struct hid_usage *usage,
  28. unsigned long **bit, int *max)
  29. {
  30. int hdev_type = (int)hid_get_drvdata(hdev);
  31. if (hdev_type == TIARC) {
  32. if (usage->code == KEY_LEFTMETA) {
  33. hid_map_usage(hi, usage, bit, max, usage->type, KEY_MENU);
  34. } else if (usage->code == KEY_BACKSPACE) {
  35. hid_map_usage(hi, usage, bit, max, usage->type, KEY_BACK);
  36. } else if (usage->code == KEY_MUTE) {
  37. hid_map_usage(hi, usage, bit, max, usage->type, KEY_PROGRAM);
  38. }
  39. }
  40. return 0;
  41. }
  42. static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,
  43. u8 *data, int size)
  44. {
  45. int hdev_type = (int)hid_get_drvdata(hdev);
  46. int ret = 0;
  47. if (hdev_type != GFRM100)
  48. return 0;
  49. if (size < 2 || data[0] != GFRM100_SEARCH_KEY_REPORT_ID)
  50. return 0;
  51. /*
  52. * Convert GFRM100 Search key reports into Consumer.00f7 (Key.Search)
  53. * reports. Ignore audio data.
  54. */
  55. switch (data[1]) {
  56. case GFRM100_SEARCH_KEY_DOWN:
  57. ret = hid_input_report(hdev, HID_INPUT_REPORT, search_key_dn,
  58. sizeof(search_key_dn), 1);
  59. break;
  60. case GFRM100_SEARCH_KEY_AUDIO_DATA:
  61. break;
  62. case GFRM100_SEARCH_KEY_UP:
  63. ret = hid_input_report(hdev, HID_INPUT_REPORT, search_key_up,
  64. sizeof(search_key_up), 1);
  65. break;
  66. default:
  67. break;
  68. }
  69. return (ret < 0) ? ret : 1;
  70. }
  71. static int gfrm_probe(struct hid_device *hdev, const struct hid_device_id *id)
  72. {
  73. int ret;
  74. hid_set_drvdata(hdev, (void *)id->driver_data);
  75. ret = hid_parse(hdev);
  76. if (ret)
  77. goto done;
  78. if (id->driver_data == GFRM100) {
  79. /*
  80. * GFRM100 HID Report Descriptor does not describe the Search
  81. * key reports. Thus, we need to add it manually here, so that
  82. * those reports reach gfrm_raw_event() from hid_input_report().
  83. */
  84. if (!hid_register_report(hdev, HID_INPUT_REPORT,
  85. GFRM100_SEARCH_KEY_REPORT_ID)) {
  86. ret = -ENOMEM;
  87. goto done;
  88. }
  89. }
  90. ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
  91. done:
  92. return ret;
  93. }
  94. static void gfrm_remove(struct hid_device *hdev)
  95. {
  96. hid_hw_stop(hdev);
  97. hid_set_drvdata(hdev, NULL);
  98. }
  99. static const struct hid_device_id gfrm_devices[] = {
  100. { HID_BLUETOOTH_DEVICE(0x58, 0x2000),
  101. .driver_data = GFRM100 },
  102. { HID_BLUETOOTH_DEVICE(0x471, 0x2210),
  103. .driver_data = GFRM200 },
  104. { HID_BLUETOOTH_DEVICE(0xD, 0x0),
  105. .driver_data = TIARC },
  106. { }
  107. };
  108. MODULE_DEVICE_TABLE(hid, gfrm_devices);
  109. static struct hid_driver gfrm_driver = {
  110. .name = "gfrm",
  111. .id_table = gfrm_devices,
  112. .probe = gfrm_probe,
  113. .remove = gfrm_remove,
  114. .input_mapped = gfrm_input_mapped,
  115. .raw_event = gfrm_raw_event,
  116. };
  117. static int __init gfrm_init(void)
  118. {
  119. return hid_register_driver(&gfrm_driver);
  120. }
  121. static void __exit gfrm_exit(void)
  122. {
  123. hid_unregister_driver(&gfrm_driver);
  124. }
  125. module_init(gfrm_init);
  126. module_exit(gfrm_exit);
  127. MODULE_LICENSE("GPL");