Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * HID driver for Google Fiber TV Box remote controls
0004  *
0005  * Copyright (c) 2014-2015 Google Inc.
0006  *
0007  * Author: Petri Gynther <pgynther@google.com>
0008  */
0009 #include <linux/device.h>
0010 #include <linux/hid.h>
0011 #include <linux/input.h>
0012 #include <linux/module.h>
0013 
0014 #include "hid-ids.h"
0015 
0016 #define GFRM100  1  /* Google Fiber GFRM100 (Bluetooth classic) */
0017 #define GFRM200  2  /* Google Fiber GFRM200 (Bluetooth LE) */
0018 
0019 #define GFRM100_SEARCH_KEY_REPORT_ID   0xF7
0020 #define GFRM100_SEARCH_KEY_DOWN        0x0
0021 #define GFRM100_SEARCH_KEY_AUDIO_DATA  0x1
0022 #define GFRM100_SEARCH_KEY_UP          0x2
0023 
0024 static u8 search_key_dn[3] = {0x40, 0x21, 0x02};
0025 static u8 search_key_up[3] = {0x40, 0x00, 0x00};
0026 
0027 static int gfrm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
0028         struct hid_field *field, struct hid_usage *usage,
0029         unsigned long **bit, int *max)
0030 {
0031     unsigned long hdev_type = (unsigned long) hid_get_drvdata(hdev);
0032 
0033     if (hdev_type == GFRM100) {
0034         if (usage->hid == (HID_UP_CONSUMER | 0x4)) {
0035             /* Consumer.0004 -> KEY_INFO */
0036             hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_INFO);
0037             return 1;
0038         }
0039 
0040         if (usage->hid == (HID_UP_CONSUMER | 0x41)) {
0041             /* Consumer.0041 -> KEY_OK */
0042             hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_OK);
0043             return 1;
0044         }
0045     }
0046 
0047     return 0;
0048 }
0049 
0050 static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,
0051         u8 *data, int size)
0052 {
0053     unsigned long hdev_type = (unsigned long) hid_get_drvdata(hdev);
0054     int ret = 0;
0055 
0056     if (hdev_type != GFRM100)
0057         return 0;
0058 
0059     if (size < 2 || data[0] != GFRM100_SEARCH_KEY_REPORT_ID)
0060         return 0;
0061 
0062     /*
0063      * Convert GFRM100 Search key reports into Consumer.0221 (Key.Search)
0064      * reports. Ignore audio data.
0065      */
0066     switch (data[1]) {
0067     case GFRM100_SEARCH_KEY_DOWN:
0068         ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_dn,
0069                        sizeof(search_key_dn), 1);
0070         break;
0071 
0072     case GFRM100_SEARCH_KEY_AUDIO_DATA:
0073         break;
0074 
0075     case GFRM100_SEARCH_KEY_UP:
0076         ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_up,
0077                        sizeof(search_key_up), 1);
0078         break;
0079 
0080     default:
0081         break;
0082     }
0083 
0084     return (ret < 0) ? ret : -1;
0085 }
0086 
0087 static int gfrm_input_configured(struct hid_device *hid, struct hid_input *hidinput)
0088 {
0089     /*
0090      * Enable software autorepeat with:
0091      * - repeat delay: 400 msec
0092      * - repeat period: 100 msec
0093      */
0094     input_enable_softrepeat(hidinput->input, 400, 100);
0095     return 0;
0096 }
0097 
0098 static int gfrm_probe(struct hid_device *hdev, const struct hid_device_id *id)
0099 {
0100     int ret;
0101 
0102     hid_set_drvdata(hdev, (void *) id->driver_data);
0103 
0104     ret = hid_parse(hdev);
0105     if (ret)
0106         goto done;
0107 
0108     if (id->driver_data == GFRM100) {
0109         /*
0110          * GFRM100 HID Report Descriptor does not describe the Search
0111          * key reports. Thus, we need to add it manually here, so that
0112          * those reports reach gfrm_raw_event() from hid_input_report().
0113          */
0114         if (!hid_register_report(hdev, HID_INPUT_REPORT,
0115                      GFRM100_SEARCH_KEY_REPORT_ID, 0)) {
0116             ret = -ENOMEM;
0117             goto done;
0118         }
0119     }
0120 
0121     ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
0122 done:
0123     return ret;
0124 }
0125 
0126 static const struct hid_device_id gfrm_devices[] = {
0127     { HID_BLUETOOTH_DEVICE(0x58, 0x2000),
0128         .driver_data = GFRM100 },
0129     { HID_BLUETOOTH_DEVICE(0x471, 0x2210),
0130         .driver_data = GFRM200 },
0131     { }
0132 };
0133 MODULE_DEVICE_TABLE(hid, gfrm_devices);
0134 
0135 static struct hid_driver gfrm_driver = {
0136     .name = "gfrm",
0137     .id_table = gfrm_devices,
0138     .probe = gfrm_probe,
0139     .input_mapping = gfrm_input_mapping,
0140     .raw_event = gfrm_raw_event,
0141     .input_configured = gfrm_input_configured,
0142 };
0143 
0144 module_hid_driver(gfrm_driver);
0145 
0146 MODULE_AUTHOR("Petri Gynther <pgynther@google.com>");
0147 MODULE_DESCRIPTION("Google Fiber TV Box remote control driver");
0148 MODULE_LICENSE("GPL");