* [PATCH] hid-gfrm: Google Fiber TV Box remote controls
@ 2015-10-21 19:04 Petri Gynther
2015-10-21 19:15 ` Petri Gynther
2015-10-22 9:00 ` Jiri Kosina
0 siblings, 2 replies; 5+ messages in thread
From: Petri Gynther @ 2015-10-21 19:04 UTC (permalink / raw)
To: linux-input; +Cc: jikos, dmitry.torokhov, Petri Gynther
Add HID driver for Google Fiber TV Box remote controls
Signed-off-by: Petri Gynther <pgynther@google.com>
---
drivers/hid/Kconfig | 6 ++
drivers/hid/Makefile | 1 +
drivers/hid/hid-gfrm.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 165 insertions(+)
create mode 100644 drivers/hid/hid-gfrm.c
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 6ab51ae..7245b7f 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -257,6 +257,12 @@ config HID_GEMBIRD
---help---
Support for Gembird JPD-DualForce 2.
+config HID_GFRM
+ tristate "Google Fiber TV Box remote control support"
+ depends on HID
+ ---help---
+ Support for Google Fiber TV Box remote controls
+
config HID_HOLTEK
tristate "Holtek HID devices"
depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index e6441bc..571d176 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_HID_ELECOM) += hid-elecom.o
obj-$(CONFIG_HID_ELO) += hid-elo.o
obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
obj-$(CONFIG_HID_GEMBIRD) += hid-gembird.o
+obj-$(CONFIG_HID_GFRM) += hid-gfrm.o
obj-$(CONFIG_HID_GT683R) += hid-gt683r.o
obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
diff --git a/drivers/hid/hid-gfrm.c b/drivers/hid/hid-gfrm.c
new file mode 100644
index 0000000..4d7b7e7
--- /dev/null
+++ b/drivers/hid/hid-gfrm.c
@@ -0,0 +1,158 @@
+/*
+ * HID driver for Google Fiber TV Box remote controls
+ *
+ * Copyright (c) 2014-2015 Google Inc.
+ *
+ * Author: Petri Gynther <pgynther@google.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/input.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define GFRM100 1 /* Google Fiber GFRM100 (Bluetooth classic) */
+#define GFRM200 2 /* Google Fiber GFRM200 (Bluetooth LE) */
+
+#define GFRM100_SEARCH_KEY_REPORT_ID 0xF7
+#define GFRM100_SEARCH_KEY_DOWN 0x0
+#define GFRM100_SEARCH_KEY_AUDIO_DATA 0x1
+#define GFRM100_SEARCH_KEY_UP 0x2
+
+static u8 search_key_dn[3] = {0x40, 0x21, 0x02};
+static u8 search_key_up[3] = {0x40, 0x00, 0x00};
+
+static int gfrm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ unsigned long hdev_type = (unsigned long) hid_get_drvdata(hdev);
+
+ if (hdev_type == GFRM100) {
+ if (usage->hid == (HID_UP_CONSUMER | 0x4)) {
+ /* Consumer.0004 -> KEY_INFO */
+ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_INFO);
+ return 1;
+ }
+
+ if (usage->hid == (HID_UP_CONSUMER | 0x41)) {
+ /* Consumer.0041 -> KEY_OK */
+ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_OK);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,
+ u8 *data, int size)
+{
+ unsigned long hdev_type = (unsigned long) hid_get_drvdata(hdev);
+ int ret = 0;
+
+ if (hdev_type != GFRM100)
+ return 0;
+
+ if (size < 2 || data[0] != GFRM100_SEARCH_KEY_REPORT_ID)
+ return 0;
+
+ /*
+ * Convert GFRM100 Search key reports into Consumer.0221 (Key.Search)
+ * reports. Ignore audio data.
+ */
+ switch (data[1]) {
+ case GFRM100_SEARCH_KEY_DOWN:
+ ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_dn,
+ sizeof(search_key_dn), 1);
+ break;
+
+ case GFRM100_SEARCH_KEY_AUDIO_DATA:
+ break;
+
+ case GFRM100_SEARCH_KEY_UP:
+ ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_up,
+ sizeof(search_key_up), 1);
+ break;
+
+ default:
+ break;
+ }
+
+ return (ret < 0) ? ret : -1;
+}
+
+static void gfrm_input_configured(struct hid_device *hid, struct hid_input *hidinput)
+{
+ /*
+ * Enable software autorepeat with:
+ * - repeat delay: 400 msec
+ * - repeat period: 100 msec
+ */
+ input_enable_softrepeat(hidinput->input, 400, 100);
+}
+
+static int gfrm_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int ret;
+
+ hid_set_drvdata(hdev, (void *) id->driver_data);
+
+ ret = hid_parse(hdev);
+ if (ret)
+ goto done;
+
+ if (id->driver_data == GFRM100) {
+ /*
+ * GFRM100 HID Report Descriptor does not describe the Search
+ * key reports. Thus, we need to add it manually here, so that
+ * those reports reach gfrm_raw_event() from hid_input_report().
+ */
+ if (!hid_register_report(hdev, HID_INPUT_REPORT,
+ GFRM100_SEARCH_KEY_REPORT_ID)) {
+ ret = -ENOMEM;
+ goto done;
+ }
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+done:
+ return ret;
+}
+
+static void gfrm_remove(struct hid_device *hdev)
+{
+ hid_hw_stop(hdev);
+ hid_set_drvdata(hdev, NULL);
+}
+
+static const struct hid_device_id gfrm_devices[] = {
+ { HID_BLUETOOTH_DEVICE(0x58, 0x2000),
+ .driver_data = GFRM100 },
+ { HID_BLUETOOTH_DEVICE(0x471, 0x2210),
+ .driver_data = GFRM200 },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, gfrm_devices);
+
+static struct hid_driver gfrm_driver = {
+ .name = "gfrm",
+ .id_table = gfrm_devices,
+ .probe = gfrm_probe,
+ .remove = gfrm_remove,
+ .input_mapping = gfrm_input_mapping,
+ .raw_event = gfrm_raw_event,
+ .input_configured = gfrm_input_configured,
+};
+
+module_hid_driver(gfrm_driver);
+
+MODULE_AUTHOR("Petri Gynther <pgynther@google.com>");
+MODULE_DESCRIPTION("Google Fiber TV Box remote control driver");
+MODULE_LICENSE("GPL");
--
2.6.0.rc2.230.g3dd15c0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] hid-gfrm: Google Fiber TV Box remote controls
2015-10-21 19:04 [PATCH] hid-gfrm: Google Fiber TV Box remote controls Petri Gynther
@ 2015-10-21 19:15 ` Petri Gynther
2015-10-22 9:00 ` Jiri Kosina
1 sibling, 0 replies; 5+ messages in thread
From: Petri Gynther @ 2015-10-21 19:15 UTC (permalink / raw)
To: open list:HID CORE LAYER; +Cc: Jiri Kosina, Dmitry Torokhov, Petri Gynther
On Wed, Oct 21, 2015 at 12:04 PM, Petri Gynther <pgynther@google.com> wrote:
>
> Add HID driver for Google Fiber TV Box remote controls
>
> Signed-off-by: Petri Gynther <pgynther@google.com>
> ---
> drivers/hid/Kconfig | 6 ++
> drivers/hid/Makefile | 1 +
> drivers/hid/hid-gfrm.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 165 insertions(+)
> create mode 100644 drivers/hid/hid-gfrm.c
>
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 6ab51ae..7245b7f 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -257,6 +257,12 @@ config HID_GEMBIRD
> ---help---
> Support for Gembird JPD-DualForce 2.
>
> +config HID_GFRM
> + tristate "Google Fiber TV Box remote control support"
> + depends on HID
> + ---help---
> + Support for Google Fiber TV Box remote controls
> +
> config HID_HOLTEK
> tristate "Holtek HID devices"
> depends on USB_HID
> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> index e6441bc..571d176 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -37,6 +37,7 @@ obj-$(CONFIG_HID_ELECOM) += hid-elecom.o
> obj-$(CONFIG_HID_ELO) += hid-elo.o
> obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
> obj-$(CONFIG_HID_GEMBIRD) += hid-gembird.o
> +obj-$(CONFIG_HID_GFRM) += hid-gfrm.o
> obj-$(CONFIG_HID_GT683R) += hid-gt683r.o
> obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
> obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
> diff --git a/drivers/hid/hid-gfrm.c b/drivers/hid/hid-gfrm.c
> new file mode 100644
> index 0000000..4d7b7e7
> --- /dev/null
> +++ b/drivers/hid/hid-gfrm.c
> @@ -0,0 +1,158 @@
> +/*
> + * HID driver for Google Fiber TV Box remote controls
> + *
> + * Copyright (c) 2014-2015 Google Inc.
> + *
> + * Author: Petri Gynther <pgynther@google.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the Free
> + * Software Foundation; either version 2 of the License, or (at your option)
> + * any later version.
> + */
> +#include <linux/device.h>
> +#include <linux/hid.h>
> +#include <linux/input.h>
> +#include <linux/module.h>
> +
> +#include "hid-ids.h"
> +
> +#define GFRM100 1 /* Google Fiber GFRM100 (Bluetooth classic) */
> +#define GFRM200 2 /* Google Fiber GFRM200 (Bluetooth LE) */
> +
> +#define GFRM100_SEARCH_KEY_REPORT_ID 0xF7
> +#define GFRM100_SEARCH_KEY_DOWN 0x0
> +#define GFRM100_SEARCH_KEY_AUDIO_DATA 0x1
> +#define GFRM100_SEARCH_KEY_UP 0x2
> +
> +static u8 search_key_dn[3] = {0x40, 0x21, 0x02};
> +static u8 search_key_up[3] = {0x40, 0x00, 0x00};
> +
> +static int gfrm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
> + struct hid_field *field, struct hid_usage *usage,
> + unsigned long **bit, int *max)
> +{
> + unsigned long hdev_type = (unsigned long) hid_get_drvdata(hdev);
> +
> + if (hdev_type == GFRM100) {
> + if (usage->hid == (HID_UP_CONSUMER | 0x4)) {
> + /* Consumer.0004 -> KEY_INFO */
> + hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_INFO);
> + return 1;
> + }
> +
> + if (usage->hid == (HID_UP_CONSUMER | 0x41)) {
> + /* Consumer.0041 -> KEY_OK */
> + hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_OK);
> + return 1;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,
> + u8 *data, int size)
> +{
> + unsigned long hdev_type = (unsigned long) hid_get_drvdata(hdev);
> + int ret = 0;
> +
> + if (hdev_type != GFRM100)
> + return 0;
> +
> + if (size < 2 || data[0] != GFRM100_SEARCH_KEY_REPORT_ID)
> + return 0;
> +
> + /*
> + * Convert GFRM100 Search key reports into Consumer.0221 (Key.Search)
> + * reports. Ignore audio data.
> + */
> + switch (data[1]) {
> + case GFRM100_SEARCH_KEY_DOWN:
> + ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_dn,
> + sizeof(search_key_dn), 1);
> + break;
> +
> + case GFRM100_SEARCH_KEY_AUDIO_DATA:
> + break;
> +
> + case GFRM100_SEARCH_KEY_UP:
> + ret = hid_report_raw_event(hdev, HID_INPUT_REPORT, search_key_up,
> + sizeof(search_key_up), 1);
> + break;
> +
> + default:
> + break;
> + }
> +
> + return (ret < 0) ? ret : -1;
> +}
> +
> +static void gfrm_input_configured(struct hid_device *hid, struct hid_input *hidinput)
> +{
> + /*
> + * Enable software autorepeat with:
> + * - repeat delay: 400 msec
> + * - repeat period: 100 msec
> + */
> + input_enable_softrepeat(hidinput->input, 400, 100);
Depends on input tree commit:
commit 027c71bbae3a6eeff00c11d1b708593a5c790314
Author: Petri Gynther <pgynther@google.com>
Date: Tue Oct 13 23:13:55 2015 -0700
Input: improve autorepeat initialization
>
> +}
> +
> +static int gfrm_probe(struct hid_device *hdev, const struct hid_device_id *id)
> +{
> + int ret;
> +
> + hid_set_drvdata(hdev, (void *) id->driver_data);
> +
> + ret = hid_parse(hdev);
> + if (ret)
> + goto done;
> +
> + if (id->driver_data == GFRM100) {
> + /*
> + * GFRM100 HID Report Descriptor does not describe the Search
> + * key reports. Thus, we need to add it manually here, so that
> + * those reports reach gfrm_raw_event() from hid_input_report().
> + */
> + if (!hid_register_report(hdev, HID_INPUT_REPORT,
> + GFRM100_SEARCH_KEY_REPORT_ID)) {
> + ret = -ENOMEM;
> + goto done;
> + }
> + }
> +
> + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
> +done:
> + return ret;
> +}
> +
> +static void gfrm_remove(struct hid_device *hdev)
> +{
> + hid_hw_stop(hdev);
> + hid_set_drvdata(hdev, NULL);
> +}
> +
> +static const struct hid_device_id gfrm_devices[] = {
> + { HID_BLUETOOTH_DEVICE(0x58, 0x2000),
> + .driver_data = GFRM100 },
> + { HID_BLUETOOTH_DEVICE(0x471, 0x2210),
> + .driver_data = GFRM200 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(hid, gfrm_devices);
> +
> +static struct hid_driver gfrm_driver = {
> + .name = "gfrm",
> + .id_table = gfrm_devices,
> + .probe = gfrm_probe,
> + .remove = gfrm_remove,
> + .input_mapping = gfrm_input_mapping,
> + .raw_event = gfrm_raw_event,
> + .input_configured = gfrm_input_configured,
> +};
> +
> +module_hid_driver(gfrm_driver);
> +
> +MODULE_AUTHOR("Petri Gynther <pgynther@google.com>");
> +MODULE_DESCRIPTION("Google Fiber TV Box remote control driver");
> +MODULE_LICENSE("GPL");
> --
> 2.6.0.rc2.230.g3dd15c0
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] hid-gfrm: Google Fiber TV Box remote controls
2015-10-21 19:04 [PATCH] hid-gfrm: Google Fiber TV Box remote controls Petri Gynther
2015-10-21 19:15 ` Petri Gynther
@ 2015-10-22 9:00 ` Jiri Kosina
2015-10-26 7:01 ` Jiri Kosina
1 sibling, 1 reply; 5+ messages in thread
From: Jiri Kosina @ 2015-10-22 9:00 UTC (permalink / raw)
To: Petri Gynther; +Cc: linux-input, dmitry.torokhov
On Wed, 21 Oct 2015, Petri Gynther wrote:
> Add HID driver for Google Fiber TV Box remote controls
I am not particularly happy with drvdata not being actually used "the
usual way", i.e. to store a pointer, but apart from being unusual, I don't
see a real issue with it.
Dmitry, as this depends on a patch queued in your tree, would you be okay
with taking the patch with my signoff?
Thanks.
--
Jiri Kosina
SUSE Labs
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] hid-gfrm: Google Fiber TV Box remote controls
2015-10-22 9:00 ` Jiri Kosina
@ 2015-10-26 7:01 ` Jiri Kosina
2015-10-26 8:41 ` Dmitry Torokhov
0 siblings, 1 reply; 5+ messages in thread
From: Jiri Kosina @ 2015-10-26 7:01 UTC (permalink / raw)
To: Petri Gynther; +Cc: linux-input, dmitry.torokhov
On Thu, 22 Oct 2015, Jiri Kosina wrote:
> > Add HID driver for Google Fiber TV Box remote controls
>
> I am not particularly happy with drvdata not being actually used "the
> usual way", i.e. to store a pointer, but apart from being unusual, I don't
> see a real issue with it.
>
> Dmitry, as this depends on a patch queued in your tree, would you be okay
> with taking the patch with my signoff?
I discussed this Dmitry in person on Kernel Summit earlier today, and
he'll be taking the driver through his tree.
For that purpose:
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Thanks,
--
Jiri Kosina
SUSE Labs
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] hid-gfrm: Google Fiber TV Box remote controls
2015-10-26 7:01 ` Jiri Kosina
@ 2015-10-26 8:41 ` Dmitry Torokhov
0 siblings, 0 replies; 5+ messages in thread
From: Dmitry Torokhov @ 2015-10-26 8:41 UTC (permalink / raw)
To: Jiri Kosina; +Cc: Petri Gynther, linux-input
On Mon, Oct 26, 2015 at 04:01:25PM +0900, Jiri Kosina wrote:
> On Thu, 22 Oct 2015, Jiri Kosina wrote:
>
> > > Add HID driver for Google Fiber TV Box remote controls
> >
> > I am not particularly happy with drvdata not being actually used "the
> > usual way", i.e. to store a pointer, but apart from being unusual, I don't
> > see a real issue with it.
> >
> > Dmitry, as this depends on a patch queued in your tree, would you be okay
> > with taking the patch with my signoff?
>
> I discussed this Dmitry in person on Kernel Summit earlier today, and
> he'll be taking the driver through his tree.
>
> For that purpose:
>
> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Applied, thank you.
--
Dmitry
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2015-10-26 8:41 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-21 19:04 [PATCH] hid-gfrm: Google Fiber TV Box remote controls Petri Gynther
2015-10-21 19:15 ` Petri Gynther
2015-10-22 9:00 ` Jiri Kosina
2015-10-26 7:01 ` Jiri Kosina
2015-10-26 8:41 ` Dmitry Torokhov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.