2 * HID driver for Google Fiber TV Box remote controls
4 * Copyright (c) 2014-2015 Google Inc.
6 * Author: Petri Gynther <pgynther@google.com>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
13 #include <linux/device.h>
14 #include <linux/hid.h>
15 #include <linux/input.h>
16 #include <linux/module.h>
20 #define GFRM100 1 /* Google Fiber GFRM100 (Bluetooth classic) */
21 #define GFRM200 2 /* Google Fiber GFRM200 (Bluetooth LE) */
23 #define GFRM100_SEARCH_KEY_REPORT_ID 0xF7
24 #define GFRM100_SEARCH_KEY_DOWN 0x0
25 #define GFRM100_SEARCH_KEY_AUDIO_DATA 0x1
26 #define GFRM100_SEARCH_KEY_UP 0x2
28 static u8 search_key_dn
[3] = {0x40, 0x21, 0x02};
29 static u8 search_key_up
[3] = {0x40, 0x00, 0x00};
31 static int gfrm_input_mapping(struct hid_device
*hdev
, struct hid_input
*hi
,
32 struct hid_field
*field
, struct hid_usage
*usage
,
33 unsigned long **bit
, int *max
)
35 unsigned long hdev_type
= (unsigned long) hid_get_drvdata(hdev
);
37 if (hdev_type
== GFRM100
) {
38 if (usage
->hid
== (HID_UP_CONSUMER
| 0x4)) {
39 /* Consumer.0004 -> KEY_INFO */
40 hid_map_usage_clear(hi
, usage
, bit
, max
, EV_KEY
, KEY_INFO
);
44 if (usage
->hid
== (HID_UP_CONSUMER
| 0x41)) {
45 /* Consumer.0041 -> KEY_OK */
46 hid_map_usage_clear(hi
, usage
, bit
, max
, EV_KEY
, KEY_OK
);
54 static int gfrm_raw_event(struct hid_device
*hdev
, struct hid_report
*report
,
57 unsigned long hdev_type
= (unsigned long) hid_get_drvdata(hdev
);
60 if (hdev_type
!= GFRM100
)
63 if (size
< 2 || data
[0] != GFRM100_SEARCH_KEY_REPORT_ID
)
67 * Convert GFRM100 Search key reports into Consumer.0221 (Key.Search)
68 * reports. Ignore audio data.
71 case GFRM100_SEARCH_KEY_DOWN
:
72 ret
= hid_report_raw_event(hdev
, HID_INPUT_REPORT
, search_key_dn
,
73 sizeof(search_key_dn
), 1);
76 case GFRM100_SEARCH_KEY_AUDIO_DATA
:
79 case GFRM100_SEARCH_KEY_UP
:
80 ret
= hid_report_raw_event(hdev
, HID_INPUT_REPORT
, search_key_up
,
81 sizeof(search_key_up
), 1);
88 return (ret
< 0) ? ret
: -1;
91 static int gfrm_input_configured(struct hid_device
*hid
, struct hid_input
*hidinput
)
94 * Enable software autorepeat with:
95 * - repeat delay: 400 msec
96 * - repeat period: 100 msec
98 input_enable_softrepeat(hidinput
->input
, 400, 100);
102 static int gfrm_probe(struct hid_device
*hdev
, const struct hid_device_id
*id
)
106 hid_set_drvdata(hdev
, (void *) id
->driver_data
);
108 ret
= hid_parse(hdev
);
112 if (id
->driver_data
== GFRM100
) {
114 * GFRM100 HID Report Descriptor does not describe the Search
115 * key reports. Thus, we need to add it manually here, so that
116 * those reports reach gfrm_raw_event() from hid_input_report().
118 if (!hid_register_report(hdev
, HID_INPUT_REPORT
,
119 GFRM100_SEARCH_KEY_REPORT_ID
)) {
125 ret
= hid_hw_start(hdev
, HID_CONNECT_DEFAULT
);
130 static void gfrm_remove(struct hid_device
*hdev
)
133 hid_set_drvdata(hdev
, NULL
);
136 static const struct hid_device_id gfrm_devices
[] = {
137 { HID_BLUETOOTH_DEVICE(0x58, 0x2000),
138 .driver_data
= GFRM100
},
139 { HID_BLUETOOTH_DEVICE(0x471, 0x2210),
140 .driver_data
= GFRM200
},
143 MODULE_DEVICE_TABLE(hid
, gfrm_devices
);
145 static struct hid_driver gfrm_driver
= {
147 .id_table
= gfrm_devices
,
149 .remove
= gfrm_remove
,
150 .input_mapping
= gfrm_input_mapping
,
151 .raw_event
= gfrm_raw_event
,
152 .input_configured
= gfrm_input_configured
,
155 module_hid_driver(gfrm_driver
);
157 MODULE_AUTHOR("Petri Gynther <pgynther@google.com>");
158 MODULE_DESCRIPTION("Google Fiber TV Box remote control driver");
159 MODULE_LICENSE("GPL");