[PATCH] HID: input: HID driver for IRMP USB-HID-keyboard remote control receiver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



There are remote control receivers, which register as an USB HID keyboard and receive and decode signals from many IR remote controls with all kinds of IR protocols (for instance IRMP, the Infra Red Multi Protocol library). Most of those IR remote controls only send keys on key press, but not on key release. Because of that, the receiver sends either a release after each key press or
 after a timeout, when no key was pressed any more. The first has the
disadvantage, that each key is processed as new, even if it is a repeat. The second has the disadvantage, that the autorepeat feature of the input core
 may generate keys during the timeout, while the user actually already has
 taken his  finger of the remote control button.
 In order to solve the problem, this driver was made. It processes keys
exactly as they were sent. Autorepeat is turned off and key repeats are taken
from raw events, get translated and are passed on to input.

This is my first time on this list and I am a hobbyist only.
The patch is for 4.20-rc6.
checkpatch.pl shows many errors because of hid_keyboard[], but that is just a copy from hid-input.c.
https://github.com/j1rie/IRMP_STM32_KBD
Signed-off-by: Joerg Riechardt <J.Riechardt@xxxxxx>

diff -Nrup A/drivers/hid/Kconfig B/drivers/hid/Kconfig
--- A/drivers/hid/Kconfig	2018-12-10 00:31:00.000000000 +0100
+++ B/drivers/hid/Kconfig	2018-12-13 01:25:16.995349622 +0100
@@ -1093,6 +1093,13 @@ config HID_ALPS
 	Say Y here if you have a Alps touchpads over i2c-hid or usbhid
 	and want support for its special functionalities.

+config HID_IRMP
+	tristate "IRMP USB-HID-keyboard support"
+	depends on HID
+	---help---
+	Support for IRMP STM32 KBD remote control receivers.
+	Say Y here if you have a IRMP STM32 KBD.
+
 endmenu

 endif # HID
diff -Nrup A/drivers/hid/Makefile B/drivers/hid/Makefile
--- A/drivers/hid/Makefile	2018-12-10 00:31:00.000000000 +0100
+++ B/drivers/hid/Makefile	2018-12-13 01:25:16.995349622 +0100
@@ -121,6 +121,7 @@ obj-$(CONFIG_HID_WALTOP)	+= hid-waltop.o
 obj-$(CONFIG_HID_WIIMOTE)	+= hid-wiimote.o
 obj-$(CONFIG_HID_SENSOR_HUB)	+= hid-sensor-hub.o
 obj-$(CONFIG_HID_SENSOR_CUSTOM_SENSOR)	+= hid-sensor-custom.o
+obj-$(CONFIG_HID_IRMP)		+= hid-irmp.o

 obj-$(CONFIG_USB_HID)		+= usbhid/
 obj-$(CONFIG_USB_MOUSE)		+= usbhid/
diff -Nrup A/drivers/hid/hid-ids.h B/drivers/hid/hid-ids.h
--- A/drivers/hid/hid-ids.h	2018-12-10 00:31:00.000000000 +0100
+++ B/drivers/hid/hid-ids.h	2018-12-13 01:25:16.995349622 +0100
@@ -1227,4 +1227,7 @@
 #define USB_VENDOR_ID_UGTIZER			0x2179
 #define USB_DEVICE_ID_UGTIZER_TABLET_GP0610	0x0053

+#define USB_VENDOR_ID_IRMP		0x1209
+#define USB_DEVICE_ID_IRMP_STM32_KBD	0x4445
+
 #endif
diff -Nrup A/drivers/hid/hid-irmp.c B/drivers/hid/hid-irmp.c
--- A/drivers/hid/hid-irmp.c	1970-01-01 01:00:00.000000000 +0100
+++ B/drivers/hid/hid-irmp.c	2018-12-13 16:39:11.297811930 +0100
@@ -0,0 +1,149 @@
+/*
+ *  HID driver for IRMP STM32 KBD remote control receiver
+ *
+ *  Copyright (c) 2018 Joerg Riechardt
+ *
+ * There are remote control receivers, which register as an USB HID keyboard and + * receive and decode signals from many IR remote controls with all kinds of IR + * protocols (for instance IRMP, the Infra Red Multi Protocol library). Most of + * those IR remote controls only send keys on key press, but not on key release. + * Because of that, the receiver sends either a release after each key press or
+ * after a timeout, when no key was pressed any more. The first has the
+ * disadvantage, that each key is processed as new, even if it is a repeat. The + * second has the disadvantage, that the autorepeat feature of the input core + * may generate keys during the timeout, while the user actually already has
+ * taken his  finger of the remote control button.
+ * In order to solve the problem, this driver was made. It processes keys
+ * exactly as they were sent. Autorepeat is turned off and key repeats are taken
+ * from raw events, get translated and are passed on to input.
+ */
+
+/*
+ * 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/module.h>
+
+#include "hid-ids.h"
+
+struct irmp_data {
+	struct hid_device *hdev;
+	struct input_dev *input;
+};
+
+/* copy of hid_keyboard[] from hid-input.c */
+#define unk	KEY_UNKNOWN
+
+static const unsigned char hid_keyboard[256] = {
+	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
+	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
+	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
+	 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
+	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
+	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
+	 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
+	191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
+	115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk,
+	122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,
+	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
+	unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,unk,unk,unk,unk,
+	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
+	unk,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,unk,unk,unk,unk,
+	 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
+	150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
+};
+
+static int irmp_raw_event(struct hid_device *hdev, struct hid_report *report,
+							u8 *raw_data, int size)
+{
+	struct irmp_data *hdata = hid_get_drvdata(hdev);
+	struct input_dev *input = hdata->input;
+	static unsigned int last_key;
+	unsigned int key;
+
+	key = (raw_data[1] << 8) + raw_data[3];
+	if (key) {
+		if (key == last_key) {
+			/* modifier */
+			if (raw_data[1]) {
+				input_event(input, EV_KEY, hid_keyboard[raw_data[1]], 2);
+				input_sync(input);
+			}
+			/* key */
+			if (raw_data[3]) {
+				input_event(input, EV_KEY, hid_keyboard[raw_data[3]], 2);
+				input_sync(input);
+			}
+		} else {
+			last_key = key;
+		}
+	} else {
+		last_key = 0;
+	}
+
+	return 1;
+}
+
+static int irmp_input_configured(struct hid_device *hdev, struct hid_input *hidinput)
+{
+	struct irmp_data *irmp_data = hid_get_drvdata(hdev);
+	struct input_dev *input = hidinput->input;
+
+	irmp_data->input = input;
+	/* turn off repeat */
+	__clear_bit(EV_REP, input->evbit);
+	hid_set_drvdata(hdev, irmp_data);
+	printk(KERN_INFO "irmp configured\n");
+
+	return 0;
+}
+
+static int irmp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret;
+	struct irmp_data *irmp_data;
+
+ irmp_data = devm_kzalloc(&hdev->dev, sizeof(struct irmp_data), GFP_KERNEL);
+	if (irmp_data == NULL) {
+		hid_err(hdev, "can't alloc irmp descriptor\n");
+		return -ENOMEM;
+	}
+	irmp_data->hdev = hdev;
+	hid_set_drvdata(hdev, irmp_data);
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "parse failed\n");
+		goto err_free;
+	}
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (ret) {
+		hid_err(hdev, "hw start failed\n");
+		goto err_free;
+	}
+	return 0;
+err_free:
+	return ret;
+}
+
+static const struct hid_device_id irmp_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_IRMP, USB_DEVICE_ID_IRMP_STM32_KBD) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, irmp_devices);
+
+static struct hid_driver irmp_driver = {
+	.name = "irmp",
+	.id_table = irmp_devices,
+	.probe = irmp_probe,
+	.raw_event = irmp_raw_event,
+	.input_configured = irmp_input_configured,
+};
+module_hid_driver(irmp_driver);
+
+MODULE_LICENSE("GPL v2");
diff -Nrup A/drivers/hid/hid-quirks.c B/drivers/hid/hid-quirks.c
--- A/drivers/hid/hid-quirks.c	2018-12-10 00:31:00.000000000 +0100
+++ B/drivers/hid/hid-quirks.c	2018-12-13 01:25:16.996349568 +0100
@@ -395,6 +395,9 @@ static const struct hid_device_id hid_ha
 #if IS_ENABLED(CONFIG_HID_ICADE)
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
 #endif
+#if IS_ENABLED(CONFIG_HID_IRMP)
+	{ HID_USB_DEVICE(USB_VENDOR_ID_IRMP, USB_DEVICE_ID_IRMP_STM32_KBD) },
+#endif
 #if IS_ENABLED(CONFIG_HID_JABRA)
 	{ HID_USB_DEVICE(USB_VENDOR_ID_JABRA, HID_ANY_ID) },
 #endif



[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux