* [PATCH] HID: Add driver for ION iCade
@ 2012-10-30 19:55 Bastien Nocera
2012-10-30 21:46 ` Benjamin Tissoires
0 siblings, 1 reply; 9+ messages in thread
From: Bastien Nocera @ 2012-10-30 19:55 UTC (permalink / raw)
To: linux-input, Jiri Kosina, benjamin.tissoires
Add a driver for the ION iCade mini arcade cabinet [1]. The device
generates a key press and release for each joystick movement or
button press or release. For example, moving the stick to the
left will generate the "A" key being pressed and the released.
A list of all the combinations is available in the iCade
developer guide [2].
This driver hides all this and makes the device work as a generic
joystick.
[1]: http://www.ionaudio.com/products/details/icade
[2]: http://www.ionaudio.com/downloads/iCade_Dev_Resource_v1.3.pdf
---
drivers/hid/Kconfig | 6 ++
drivers/hid/Makefile | 1 +
drivers/hid/hid-core.c | 1 +
drivers/hid/hid-icade.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++
drivers/hid/hid-ids.h | 3 +
5 files changed, 205 insertions(+)
create mode 100644 drivers/hid/hid-icade.c
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 1630150..750d435 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -265,6 +265,12 @@ config HID_GYRATION
---help---
Support for Gyration remote control.
+config HID_ICADE
+ tristate "ION iCade arcade controller"
+ depends on (BT_HIDP)
+ ---help---
+ Support for the ION iCade arcade controller to work as a joystick.
+
config HID_TWINHAN
tristate "Twinhan IR remote control"
depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index cef68ca..9860d97 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -59,6 +59,7 @@ obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o
obj-$(CONFIG_HID_LENOVO_TPKBD) += hid-lenovo-tpkbd.o
obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o
+obj-$(CONFIG_HID_ICADE) += hid-icade.o
obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o
obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o
obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index bd3971b..0a6b36f 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1572,6 +1572,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, USB_DEVICE_ID_SENSOR_HUB_09FA) },
{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_1020) },
{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_09FA) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
diff --git a/drivers/hid/hid-icade.c b/drivers/hid/hid-icade.c
new file mode 100644
index 0000000..54e1cb9
--- /dev/null
+++ b/drivers/hid/hid-icade.c
@@ -0,0 +1,194 @@
+/*
+ * USB HID quirks support for Linux
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (c) 2012 Bastien Nocera <hadess@hadess.net>
+ * Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.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/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+
+struct icade_key_translation {
+ u16 from_key;
+ u16 from_usage; /* hid_keyboard[from_usage] == from_key */
+ u16 to;
+ u8 press : 1;
+};
+
+/*
+ * ↑ A C Y L
+ * ← →
+ * ↓ B X Z R
+ *
+ *
+ * UP ON,OFF = w,e
+ * RT ON,OFF = d,c
+ * DN ON,OFF = x,z
+ * LT ON,OFF = a,q
+ * A ON,OFF = y,t
+ * B ON,OFF = h,r
+ * C ON,OFF = u,f
+ * X ON,OFF = j,n
+ * Y ON,OFF = i,m
+ * Z ON,OFF = k,p
+ * L ON,OFF = o,g
+ * R ON,OFF = l,v
+ */
+static const struct icade_key_translation icade_keys[] = {
+ { KEY_W, 26, KEY_UP, 1 },
+ { KEY_E, 8, KEY_UP, 0 },
+ { KEY_D, 7, KEY_RIGHT, 1 },
+ { KEY_C, 6, KEY_RIGHT, 0 },
+ { KEY_X, 27, KEY_DOWN, 1 },
+ { KEY_Z, 29, KEY_DOWN, 0 },
+ { KEY_A, 4, KEY_LEFT, 1 },
+ { KEY_Q, 20, KEY_LEFT, 0 },
+ { KEY_Y, 28, BTN_A, 1 },
+ { KEY_T, 23, BTN_A, 0 },
+ { KEY_H, 11, BTN_B, 1 },
+ { KEY_R, 21, BTN_B, 0 },
+ { KEY_U, 24, BTN_C, 1 },
+ { KEY_F, 9, BTN_C, 0 },
+ { KEY_J, 13, BTN_X, 1 },
+ { KEY_N, 17, BTN_X, 0 },
+ { KEY_I, 12, BTN_Y, 1 },
+ { KEY_M, 16, BTN_Y, 0 },
+ { KEY_K, 14, BTN_Z, 1 },
+ { KEY_P, 19, BTN_Z, 0 },
+ { KEY_O, 18, BTN_THUMBL, 1 },
+ { KEY_G, 10, BTN_THUMBL, 0 },
+ { KEY_L, 15, BTN_THUMBR, 1 },
+ { KEY_V, 25, BTN_THUMBR, 0 },
+
+ { }
+};
+
+static const struct icade_key_translation *icade_find_translation(
+ u16 from)
+{
+ const struct icade_key_translation *trans;
+
+ /* Look for the translation */
+ for (trans = icade_keys; trans->from_key; trans++)
+ if (trans->from_usage == from)
+ return trans;
+
+ return NULL;
+}
+
+static int icade_event(struct hid_device *hdev, struct hid_field *field,
+ struct hid_usage *usage, __s32 value)
+{
+ const struct icade_key_translation *trans;
+ unsigned code;
+
+ if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
+ !usage->type)
+ return 0;
+
+ code = usage->hid & HID_USAGE;
+
+ /* We ignore the fake key up, and act only on key down */
+ if (!value)
+ return 1;
+
+ trans = icade_find_translation (code);
+
+ if (!trans)
+ return 1;
+
+ input_event(field->hidinput->input, usage->type, trans->to, trans->press);
+
+ return 1;
+}
+
+static int icade_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ const struct icade_key_translation *trans;
+ unsigned code;
+
+ if ((usage->hid & HID_USAGE_PAGE) == HID_UP_KEYBOARD) {
+ /* find out which KEY_ code is (usage->hid & HID_USAGE)
+ * and store it into code */
+ code = usage->hid & HID_USAGE;
+
+ trans = icade_find_translation (code);
+
+ if (!trans)
+ return -1;
+
+ hid_map_usage(hi, usage, bit, max, EV_KEY, trans->to);
+ set_bit(trans->to, hi->input->keybit);
+
+ return 1;
+ }
+
+ /* ignore others */
+ return -1;
+
+}
+
+static int icade_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if (usage->type == EV_KEY)
+ set_bit(usage->type, hi->input->evbit);
+
+ return -1;
+}
+
+static const struct hid_device_id icade_devices[] = {
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
+
+ { }
+};
+MODULE_DEVICE_TABLE(hid, icade_devices);
+
+static struct hid_driver icade_driver = {
+ .name = "icade",
+ .id_table = icade_devices,
+ .event = icade_event,
+ .input_mapped = icade_input_mapped,
+ .input_mapping = icade_input_mapping,
+};
+
+static int __init icade_init(void)
+{
+ int ret;
+
+ ret = hid_register_driver(&icade_driver);
+ if (ret)
+ pr_err("can't register icade driver\n");
+
+ return ret;
+}
+
+static void __exit icade_exit(void)
+{
+ hid_unregister_driver(&icade_driver);
+}
+
+module_init(icade_init);
+module_exit(icade_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 269b509..9bc8d57 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -420,6 +420,9 @@
#define USB_VENDOR_ID_ILITEK 0x222a
#define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001
+#define USB_VENDOR_ID_ION 0x15e4
+#define USB_DEVICE_ID_ICADE 0x0132
+
#define USB_VENDOR_ID_HOLTEK 0x1241
#define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP 0x5015
--
1.7.12.1
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH] HID: Add driver for ION iCade
2012-10-30 19:55 Bastien Nocera
@ 2012-10-30 21:46 ` Benjamin Tissoires
0 siblings, 0 replies; 9+ messages in thread
From: Benjamin Tissoires @ 2012-10-30 21:46 UTC (permalink / raw)
To: Bastien Nocera; +Cc: linux-input, Jiri Kosina
Hi Bastien,
a few random comments:
On Tue, Oct 30, 2012 at 8:55 PM, Bastien Nocera <hadess@hadess.net> wrote:
>
> Add a driver for the ION iCade mini arcade cabinet [1]. The device
> generates a key press and release for each joystick movement or
> button press or release. For example, moving the stick to the
> left will generate the "A" key being pressed and the released.
>
> A list of all the combinations is available in the iCade
> developer guide [2].
>
> This driver hides all this and makes the device work as a generic
> joystick.
>
> [1]: http://www.ionaudio.com/products/details/icade
> [2]: http://www.ionaudio.com/downloads/iCade_Dev_Resource_v1.3.pdf
You are missing your Signed-off-by line. Without it Jiri won't be able
to pick your driver.
> ---
> drivers/hid/Kconfig | 6 ++
> drivers/hid/Makefile | 1 +
> drivers/hid/hid-core.c | 1 +
> drivers/hid/hid-icade.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++
> drivers/hid/hid-ids.h | 3 +
> 5 files changed, 205 insertions(+)
> create mode 100644 drivers/hid/hid-icade.c
>
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 1630150..750d435 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -265,6 +265,12 @@ config HID_GYRATION
> ---help---
> Support for Gyration remote control.
>
> +config HID_ICADE
> + tristate "ION iCade arcade controller"
> + depends on (BT_HIDP)
> + ---help---
> + Support for the ION iCade arcade controller to work as a joystick.
> +
> config HID_TWINHAN
> tristate "Twinhan IR remote control"
> depends on USB_HID
> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> index cef68ca..9860d97 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -59,6 +59,7 @@ obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o
> obj-$(CONFIG_HID_LENOVO_TPKBD) += hid-lenovo-tpkbd.o
> obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
> obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o
> +obj-$(CONFIG_HID_ICADE) += hid-icade.o
mmm.... this should go above between hid-hyperv.o and hid-kensington.o... :)
> obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o
> obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o
> obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o
> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> index bd3971b..0a6b36f 100644
> --- a/drivers/hid/hid-core.c
> +++ b/drivers/hid/hid-core.c
> @@ -1572,6 +1572,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
> { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, USB_DEVICE_ID_SENSOR_HUB_09FA) },
> { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_1020) },
> { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_09FA) },
> + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
> { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
> { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
> { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
> diff --git a/drivers/hid/hid-icade.c b/drivers/hid/hid-icade.c
> new file mode 100644
> index 0000000..54e1cb9
> --- /dev/null
> +++ b/drivers/hid/hid-icade.c
> @@ -0,0 +1,194 @@
> +/*
> + * USB HID quirks support for Linux
> + *
> + * Copyright (c) 1999 Andreas Gal
> + * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
> + * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
> + * Copyright (c) 2006-2007 Jiri Kosina
> + * Copyright (c) 2007 Paul Walmsley
> + * Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com>
I'm not sure we should keep these copyrights. Actually, nearly all the
code is new except the skeleton.
> + * Copyright (c) 2012 Bastien Nocera <hadess@hadess.net>
> + * Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.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/module.h>
> +#include <linux/slab.h>
> +#include <linux/usb.h>
Not sure usb.h is required here.
> +
> +#include "hid-ids.h"
> +
> +struct icade_key_translation {
> + u16 from_key;
> + u16 from_usage; /* hid_keyboard[from_usage] == from_key */
> + u16 to;
> + u8 press : 1;
checkpatch.pl says: ERROR: spaces prohibited around that ':' (ctx:WxW)
> +};
> +
> +/*
> + * ↑ A C Y L
> + * ← →
> + * ↓ B X Z R
> + *
> + *
> + * UP ON,OFF = w,e
> + * RT ON,OFF = d,c
> + * DN ON,OFF = x,z
> + * LT ON,OFF = a,q
> + * A ON,OFF = y,t
> + * B ON,OFF = h,r
> + * C ON,OFF = u,f
> + * X ON,OFF = j,n
> + * Y ON,OFF = i,m
> + * Z ON,OFF = k,p
> + * L ON,OFF = o,g
> + * R ON,OFF = l,v
> + */
> +static const struct icade_key_translation icade_keys[] = {
> + { KEY_W, 26, KEY_UP, 1 },
> + { KEY_E, 8, KEY_UP, 0 },
> + { KEY_D, 7, KEY_RIGHT, 1 },
> + { KEY_C, 6, KEY_RIGHT, 0 },
> + { KEY_X, 27, KEY_DOWN, 1 },
> + { KEY_Z, 29, KEY_DOWN, 0 },
> + { KEY_A, 4, KEY_LEFT, 1 },
> + { KEY_Q, 20, KEY_LEFT, 0 },
> + { KEY_Y, 28, BTN_A, 1 },
> + { KEY_T, 23, BTN_A, 0 },
> + { KEY_H, 11, BTN_B, 1 },
> + { KEY_R, 21, BTN_B, 0 },
> + { KEY_U, 24, BTN_C, 1 },
> + { KEY_F, 9, BTN_C, 0 },
> + { KEY_J, 13, BTN_X, 1 },
> + { KEY_N, 17, BTN_X, 0 },
> + { KEY_I, 12, BTN_Y, 1 },
> + { KEY_M, 16, BTN_Y, 0 },
> + { KEY_K, 14, BTN_Z, 1 },
> + { KEY_P, 19, BTN_Z, 0 },
> + { KEY_O, 18, BTN_THUMBL, 1 },
> + { KEY_G, 10, BTN_THUMBL, 0 },
> + { KEY_L, 15, BTN_THUMBR, 1 },
> + { KEY_V, 25, BTN_THUMBR, 0 },
> +
> + { }
> +};
As discussed on IRC, using a table with indexes matching from_usage
will enhance the speed of icade_find_translation.
> +
> +static const struct icade_key_translation *icade_find_translation(
> + u16 from)
this can move on the previous line
> +{
> + const struct icade_key_translation *trans;
> +
> + /* Look for the translation */
> + for (trans = icade_keys; trans->from_key; trans++)
> + if (trans->from_usage == from)
> + return trans;
this can be replaced by a check on the size and an access in the table.
> +
> + return NULL;
> +}
> +
> +static int icade_event(struct hid_device *hdev, struct hid_field *field,
> + struct hid_usage *usage, __s32 value)
> +{
> + const struct icade_key_translation *trans;
> + unsigned code;
> +
> + if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
> + !usage->type)
I don't think it's required to check against field->hidinput and
usage->type. Anyway, it won't hurt to effectively do the test.
> + return 0;
> +
> + code = usage->hid & HID_USAGE;
> +
> + /* We ignore the fake key up, and act only on key down */
> + if (!value)
> + return 1;
> +
> + trans = icade_find_translation (code);
checkpatch.pl: WARNING: space prohibited between function name and
open parenthesis '('
...this must come from me, sorry. My previous job had this style rule
and I have to fight to forget it...
> +
> + if (!trans)
> + return 1;
> +
> + input_event(field->hidinput->input, usage->type, trans->to, trans->press);
line over 80 characters: 82... :)
> +
> + return 1;
> +}
> +
> +static int icade_input_mapping(struct hid_device *hdev, struct hid_input *hi,
> + struct hid_field *field, struct hid_usage *usage,
> + unsigned long **bit, int *max)
> +{
> + const struct icade_key_translation *trans;
> + unsigned code;
code is not required anymore
> +
> + if ((usage->hid & HID_USAGE_PAGE) == HID_UP_KEYBOARD) {
> + /* find out which KEY_ code is (usage->hid & HID_USAGE)
> + * and store it into code */
> + code = usage->hid & HID_USAGE;
> +
> + trans = icade_find_translation (code);
just use usage->hid & HID_USAGE instead of code
checkpatch.pl: WARNING: space prohibited between function name and
open parenthesis '('
... ditto
> +
> + if (!trans)
> + return -1;
> +
> + hid_map_usage(hi, usage, bit, max, EV_KEY, trans->to);
> + set_bit(trans->to, hi->input->keybit);
> +
> + return 1;
> + }
> +
> + /* ignore others */
> + return -1;
> +
> +}
> +
> +static int icade_input_mapped(struct hid_device *hdev, struct hid_input *hi,
> + struct hid_field *field, struct hid_usage *usage,
> + unsigned long **bit, int *max)
> +{
> + if (usage->type == EV_KEY)
> + set_bit(usage->type, hi->input->evbit);
> +
> + return -1;
> +}
> +
> +static const struct hid_device_id icade_devices[] = {
> + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
> +
> + { }
> +};
> +MODULE_DEVICE_TABLE(hid, icade_devices);
> +
> +static struct hid_driver icade_driver = {
> + .name = "icade",
> + .id_table = icade_devices,
> + .event = icade_event,
> + .input_mapped = icade_input_mapped,
> + .input_mapping = icade_input_mapping,
> +};
> +
> +static int __init icade_init(void)
> +{
> + int ret;
> +
> + ret = hid_register_driver(&icade_driver);
> + if (ret)
> + pr_err("can't register icade driver\n");
> +
> + return ret;
> +}
> +
> +static void __exit icade_exit(void)
> +{
> + hid_unregister_driver(&icade_driver);
> +}
> +
> +module_init(icade_init);
> +module_exit(icade_exit);
> +MODULE_LICENSE("GPL");
you are missing MODULE_AUTHOR and MODULE_DESCRIPTION
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 269b509..9bc8d57 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -420,6 +420,9 @@
> #define USB_VENDOR_ID_ILITEK 0x222a
> #define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001
>
> +#define USB_VENDOR_ID_ION 0x15e4
> +#define USB_DEVICE_ID_ICADE 0x0132
> +
> #define USB_VENDOR_ID_HOLTEK 0x1241
> #define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP 0x5015
>
> --
> 1.7.12.1
>
>
Thanks,
Benjamin
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH] HID: Add driver for ION iCade
@ 2012-10-31 11:10 Bastien Nocera
2012-10-31 11:17 ` Bastien Nocera
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Bastien Nocera @ 2012-10-31 11:10 UTC (permalink / raw)
To: linux-input, benjamin.tissoires, Jiri Kosina
Add a driver for the ION iCade mini arcade cabinet [1]. The device
generates a key press and release for each joystick movement or
button press or release. For example, moving the stick to the
left will generate the "A" key being pressed and the released.
A list of all the combinations is available in the iCade
developer guide [2].
This driver hides all this and makes the device work as a generic
joystick.
[1]: http://www.ionaudio.com/products/details/icade
[2]: http://www.ionaudio.com/downloads/iCade_Dev_Resource_v1.3.pdf
Signed-off-by: Bastien Nocera <hadess@hadess.net>
---
drivers/hid/Kconfig | 9 ++
drivers/hid/Makefile | 1 +
drivers/hid/hid-core.c | 1 +
drivers/hid/hid-icade.c | 259 ++++++++++++++++++++++++++++++++++++++++++++++++
drivers/hid/hid-ids.h | 3 +
5 files changed, 273 insertions(+)
create mode 100644 drivers/hid/hid-icade.c
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 1630150..813f0fe 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -265,6 +265,15 @@ config HID_GYRATION
---help---
Support for Gyration remote control.
+config HID_ICADE
+ tristate "ION iCade arcade controller"
+ depends on (BT_HIDP)
+ ---help---
+ Support for the ION iCade arcade controller to work as a joystick.
+
+ To compile this driver as a module, choose M here: the
+ module will be called hid-icade.
+
config HID_TWINHAN
tristate "Twinhan IR remote control"
depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index cef68ca..85c910c 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o
obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o
+obj-$(CONFIG_HID_ICADE) += hid-icade.o
obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o
obj-$(CONFIG_HID_KYE) += hid-kye.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index bd3971b..0a6b36f 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1572,6 +1572,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, USB_DEVICE_ID_SENSOR_HUB_09FA) },
{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_1020) },
{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_09FA) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
diff --git a/drivers/hid/hid-icade.c b/drivers/hid/hid-icade.c
new file mode 100644
index 0000000..1d6565e
--- /dev/null
+++ b/drivers/hid/hid-icade.c
@@ -0,0 +1,259 @@
+/*
+ * ION iCade input driver
+ *
+ * Copyright (c) 2012 Bastien Nocera <hadess@hadess.net>
+ * Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.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/module.h>
+
+#include "hid-ids.h"
+
+/*
+ * ↑ A C Y L
+ * ← →
+ * ↓ B X Z R
+ *
+ *
+ * UP ON,OFF = w,e
+ * RT ON,OFF = d,c
+ * DN ON,OFF = x,z
+ * LT ON,OFF = a,q
+ * A ON,OFF = y,t
+ * B ON,OFF = h,r
+ * C ON,OFF = u,f
+ * X ON,OFF = j,n
+ * Y ON,OFF = i,m
+ * Z ON,OFF = k,p
+ * L ON,OFF = o,g
+ * R ON,OFF = l,v
+ */
+
+/* The translation code uses HID usage instead of input layer
+ * keys. This code generates a lookup table that makes
+ * translation quick.
+ *
+ * #include <linux/input.h>
+ * #include <stdio.h>
+ * #include <assert.h>
+ *
+ * #define unk KEY_UNKNOWN
+ *
+ * < copy of hid_keyboard[] from hid-input.c >
+ *
+ * struct icade_key_translation {
+ * int from;
+ * const char *to;
+ * int press;
+ * };
+ *
+ * static const struct icade_key_translation icade_keys[] = {
+ * { KEY_W, "KEY_UP", 1 },
+ * { KEY_E, "KEY_UP", 0 },
+ * { KEY_D, "KEY_RIGHT", 1 },
+ * { KEY_C, "KEY_RIGHT", 0 },
+ * { KEY_X, "KEY_DOWN", 1 },
+ * { KEY_Z, "KEY_DOWN", 0 },
+ * { KEY_A, "KEY_LEFT", 1 },
+ * { KEY_Q, "KEY_LEFT", 0 },
+ * { KEY_Y, "BTN_A", 1 },
+ * { KEY_T, "BTN_A", 0 },
+ * { KEY_H, "BTN_B", 1 },
+ * { KEY_R, "BTN_B", 0 },
+ * { KEY_U, "BTN_C", 1 },
+ * { KEY_F, "BTN_C", 0 },
+ * { KEY_J, "BTN_X", 1 },
+ * { KEY_N, "BTN_X", 0 },
+ * { KEY_I, "BTN_Y", 1 },
+ * { KEY_M, "BTN_Y", 0 },
+ * { KEY_K, "BTN_Z", 1 },
+ * { KEY_P, "BTN_Z", 0 },
+ * { KEY_O, "BTN_THUMBL", 1 },
+ * { KEY_G, "BTN_THUMBL", 0 },
+ * { KEY_L, "BTN_THUMBR", 1 },
+ * { KEY_V, "BTN_THUMBR", 0 },
+ *
+ * { }
+ * };
+ *
+ * static int
+ * usage_for_key (int key)
+ * {
+ * int i;
+ * for (i = 0; i < 256; i++) {
+ * if (hid_keyboard[i] == key)
+ * return i;
+ * }
+ * assert(0);
+ * }
+ *
+ * int main (int argc, char **argv)
+ * {
+ * const struct icade_key_translation *trans;
+ * int max_usage = 0;
+ *
+ * for (trans = icade_keys; trans->from; trans++) {
+ * int usage = usage_for_key (trans->from);
+ * max_usage = usage > max_usage ? usage : max_usage;
+ * }
+ *
+ * printf ("#define ICADE_MAX_USAGE %d\n\n", max_usage);
+ * printf ("struct icade_key {\n");
+ * printf ("\tu16 to;\n");
+ * printf ("\tu8 press:1;\n");
+ * printf ("};\n\n");
+ * printf ("static const struct icade_key "
+ * "icade_usage_table[%d] = {\n", max_usage + 1);
+ * for (trans = icade_keys; trans->from; trans++) {
+ * printf ("\t[%d] = { %s, %d },\n",
+ * usage_for_key (trans->from), trans->to, trans->press);
+ * }
+ * printf ("};\n");
+ *
+ * return 0;
+ * }
+ */
+
+#define ICADE_MAX_USAGE 29
+
+struct icade_key {
+ u16 to;
+ u8 press:1;
+};
+
+static const struct icade_key icade_usage_table[30] = {
+ [26] = { KEY_UP, 1 },
+ [8] = { KEY_UP, 0 },
+ [7] = { KEY_RIGHT, 1 },
+ [6] = { KEY_RIGHT, 0 },
+ [27] = { KEY_DOWN, 1 },
+ [29] = { KEY_DOWN, 0 },
+ [4] = { KEY_LEFT, 1 },
+ [20] = { KEY_LEFT, 0 },
+ [28] = { BTN_A, 1 },
+ [23] = { BTN_A, 0 },
+ [11] = { BTN_B, 1 },
+ [21] = { BTN_B, 0 },
+ [24] = { BTN_C, 1 },
+ [9] = { BTN_C, 0 },
+ [13] = { BTN_X, 1 },
+ [17] = { BTN_X, 0 },
+ [12] = { BTN_Y, 1 },
+ [16] = { BTN_Y, 0 },
+ [14] = { BTN_Z, 1 },
+ [19] = { BTN_Z, 0 },
+ [18] = { BTN_THUMBL, 1 },
+ [10] = { BTN_THUMBL, 0 },
+ [15] = { BTN_THUMBR, 1 },
+ [25] = { BTN_THUMBR, 0 },
+};
+
+static const struct icade_key *icade_find_translation(u16 from)
+{
+ if (from < 0 || from > ICADE_MAX_USAGE)
+ return NULL;
+ return &icade_usage_table[from];
+}
+
+static int icade_event(struct hid_device *hdev, struct hid_field *field,
+ struct hid_usage *usage, __s32 value)
+{
+ const struct icade_key *trans;
+
+ if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
+ !usage->type)
+ return 0;
+
+ /* We ignore the fake key up, and act only on key down */
+ if (!value)
+ return 1;
+
+ trans = icade_find_translation(usage->hid & HID_USAGE);
+
+ if (!trans)
+ return 1;
+
+ input_event(field->hidinput->input, usage->type,
+ trans->to, trans->press);
+
+ return 1;
+}
+
+static int icade_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ const struct icade_key *trans;
+
+ if ((usage->hid & HID_USAGE_PAGE) == HID_UP_KEYBOARD) {
+ trans = icade_find_translation(usage->hid & HID_USAGE);
+
+ if (!trans)
+ return -1;
+
+ hid_map_usage(hi, usage, bit, max, EV_KEY, trans->to);
+ set_bit(trans->to, hi->input->keybit);
+
+ return 1;
+ }
+
+ /* ignore others */
+ return -1;
+
+}
+
+static int icade_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if (usage->type == EV_KEY)
+ set_bit(usage->type, hi->input->evbit);
+
+ return -1;
+}
+
+static const struct hid_device_id icade_devices[] = {
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
+
+ { }
+};
+MODULE_DEVICE_TABLE(hid, icade_devices);
+
+static struct hid_driver icade_driver = {
+ .name = "icade",
+ .id_table = icade_devices,
+ .event = icade_event,
+ .input_mapped = icade_input_mapped,
+ .input_mapping = icade_input_mapping,
+};
+
+static int __init icade_init(void)
+{
+ int ret;
+
+ ret = hid_register_driver(&icade_driver);
+ if (ret)
+ pr_err("can't register icade driver\n");
+
+ return ret;
+}
+
+static void __exit icade_exit(void)
+{
+ hid_unregister_driver(&icade_driver);
+}
+
+module_init(icade_init);
+module_exit(icade_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
+MODULE_DESCRIPTION("ION iCade input driver");
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 269b509..9bc8d57 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -420,6 +420,9 @@
#define USB_VENDOR_ID_ILITEK 0x222a
#define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001
+#define USB_VENDOR_ID_ION 0x15e4
+#define USB_DEVICE_ID_ICADE 0x0132
+
#define USB_VENDOR_ID_HOLTEK 0x1241
#define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP 0x5015
--
1.7.12.1
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH] HID: Add driver for ION iCade
2012-10-31 11:10 [PATCH] HID: Add driver for ION iCade Bastien Nocera
@ 2012-10-31 11:17 ` Bastien Nocera
2012-10-31 11:17 ` Benjamin Tissoires
2012-10-31 14:54 ` Jiri Kosina
2 siblings, 0 replies; 9+ messages in thread
From: Bastien Nocera @ 2012-10-31 11:17 UTC (permalink / raw)
To: linux-input; +Cc: benjamin.tissoires, Jiri Kosina
Em Wed, 2012-10-31 às 12:10 +0100, Bastien Nocera escreveu:
> Add a driver for the ION iCade mini arcade cabinet [1]. The device
> generates a key press and release for each joystick movement or
> button press or release. For example, moving the stick to the
> left will generate the "A" key being pressed and the released.
^^^
Should be "then".
> A list of all the combinations is available in the iCade
> developer guide [2].
>
> This driver hides all this and makes the device work as a generic
> joystick.
>
> [1]: http://www.ionaudio.com/products/details/icade
> [2]: http://www.ionaudio.com/downloads/iCade_Dev_Resource_v1.3.pdf
Latest version of the devel guide is:
http://www.ionaudio.com/downloads/ION%20Arcade%20Dev%20Resource%20v1.5.pdf
Let me know if you want a new patch for those.
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] HID: Add driver for ION iCade
2012-10-31 11:10 [PATCH] HID: Add driver for ION iCade Bastien Nocera
2012-10-31 11:17 ` Bastien Nocera
@ 2012-10-31 11:17 ` Benjamin Tissoires
2012-10-31 14:54 ` Jiri Kosina
2 siblings, 0 replies; 9+ messages in thread
From: Benjamin Tissoires @ 2012-10-31 11:17 UTC (permalink / raw)
To: Bastien Nocera; +Cc: linux-input, Jiri Kosina
Hi Bastien,
this v2 is good for me:
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Cheers,
Benjamin
On Wed, Oct 31, 2012 at 12:10 PM, Bastien Nocera <hadess@hadess.net> wrote:
>
> Add a driver for the ION iCade mini arcade cabinet [1]. The device
> generates a key press and release for each joystick movement or
> button press or release. For example, moving the stick to the
> left will generate the "A" key being pressed and the released.
>
> A list of all the combinations is available in the iCade
> developer guide [2].
>
> This driver hides all this and makes the device work as a generic
> joystick.
>
> [1]: http://www.ionaudio.com/products/details/icade
> [2]: http://www.ionaudio.com/downloads/iCade_Dev_Resource_v1.3.pdf
>
> Signed-off-by: Bastien Nocera <hadess@hadess.net>
> ---
> drivers/hid/Kconfig | 9 ++
> drivers/hid/Makefile | 1 +
> drivers/hid/hid-core.c | 1 +
> drivers/hid/hid-icade.c | 259 ++++++++++++++++++++++++++++++++++++++++++++++++
> drivers/hid/hid-ids.h | 3 +
> 5 files changed, 273 insertions(+)
> create mode 100644 drivers/hid/hid-icade.c
>
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 1630150..813f0fe 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -265,6 +265,15 @@ config HID_GYRATION
> ---help---
> Support for Gyration remote control.
>
> +config HID_ICADE
> + tristate "ION iCade arcade controller"
> + depends on (BT_HIDP)
> + ---help---
> + Support for the ION iCade arcade controller to work as a joystick.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called hid-icade.
> +
> config HID_TWINHAN
> tristate "Twinhan IR remote control"
> depends on USB_HID
> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> index cef68ca..85c910c 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -52,6 +52,7 @@ obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
> obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
> obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o
> obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o
> +obj-$(CONFIG_HID_ICADE) += hid-icade.o
> obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
> obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o
> obj-$(CONFIG_HID_KYE) += hid-kye.o
> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> index bd3971b..0a6b36f 100644
> --- a/drivers/hid/hid-core.c
> +++ b/drivers/hid/hid-core.c
> @@ -1572,6 +1572,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
> { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, USB_DEVICE_ID_SENSOR_HUB_09FA) },
> { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_1020) },
> { HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_09FA) },
> + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
> { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
> { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
> { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
> diff --git a/drivers/hid/hid-icade.c b/drivers/hid/hid-icade.c
> new file mode 100644
> index 0000000..1d6565e
> --- /dev/null
> +++ b/drivers/hid/hid-icade.c
> @@ -0,0 +1,259 @@
> +/*
> + * ION iCade input driver
> + *
> + * Copyright (c) 2012 Bastien Nocera <hadess@hadess.net>
> + * Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.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/module.h>
> +
> +#include "hid-ids.h"
> +
> +/*
> + * ↑ A C Y L
> + * ← →
> + * ↓ B X Z R
> + *
> + *
> + * UP ON,OFF = w,e
> + * RT ON,OFF = d,c
> + * DN ON,OFF = x,z
> + * LT ON,OFF = a,q
> + * A ON,OFF = y,t
> + * B ON,OFF = h,r
> + * C ON,OFF = u,f
> + * X ON,OFF = j,n
> + * Y ON,OFF = i,m
> + * Z ON,OFF = k,p
> + * L ON,OFF = o,g
> + * R ON,OFF = l,v
> + */
> +
> +/* The translation code uses HID usage instead of input layer
> + * keys. This code generates a lookup table that makes
> + * translation quick.
> + *
> + * #include <linux/input.h>
> + * #include <stdio.h>
> + * #include <assert.h>
> + *
> + * #define unk KEY_UNKNOWN
> + *
> + * < copy of hid_keyboard[] from hid-input.c >
> + *
> + * struct icade_key_translation {
> + * int from;
> + * const char *to;
> + * int press;
> + * };
> + *
> + * static const struct icade_key_translation icade_keys[] = {
> + * { KEY_W, "KEY_UP", 1 },
> + * { KEY_E, "KEY_UP", 0 },
> + * { KEY_D, "KEY_RIGHT", 1 },
> + * { KEY_C, "KEY_RIGHT", 0 },
> + * { KEY_X, "KEY_DOWN", 1 },
> + * { KEY_Z, "KEY_DOWN", 0 },
> + * { KEY_A, "KEY_LEFT", 1 },
> + * { KEY_Q, "KEY_LEFT", 0 },
> + * { KEY_Y, "BTN_A", 1 },
> + * { KEY_T, "BTN_A", 0 },
> + * { KEY_H, "BTN_B", 1 },
> + * { KEY_R, "BTN_B", 0 },
> + * { KEY_U, "BTN_C", 1 },
> + * { KEY_F, "BTN_C", 0 },
> + * { KEY_J, "BTN_X", 1 },
> + * { KEY_N, "BTN_X", 0 },
> + * { KEY_I, "BTN_Y", 1 },
> + * { KEY_M, "BTN_Y", 0 },
> + * { KEY_K, "BTN_Z", 1 },
> + * { KEY_P, "BTN_Z", 0 },
> + * { KEY_O, "BTN_THUMBL", 1 },
> + * { KEY_G, "BTN_THUMBL", 0 },
> + * { KEY_L, "BTN_THUMBR", 1 },
> + * { KEY_V, "BTN_THUMBR", 0 },
> + *
> + * { }
> + * };
> + *
> + * static int
> + * usage_for_key (int key)
> + * {
> + * int i;
> + * for (i = 0; i < 256; i++) {
> + * if (hid_keyboard[i] == key)
> + * return i;
> + * }
> + * assert(0);
> + * }
> + *
> + * int main (int argc, char **argv)
> + * {
> + * const struct icade_key_translation *trans;
> + * int max_usage = 0;
> + *
> + * for (trans = icade_keys; trans->from; trans++) {
> + * int usage = usage_for_key (trans->from);
> + * max_usage = usage > max_usage ? usage : max_usage;
> + * }
> + *
> + * printf ("#define ICADE_MAX_USAGE %d\n\n", max_usage);
> + * printf ("struct icade_key {\n");
> + * printf ("\tu16 to;\n");
> + * printf ("\tu8 press:1;\n");
> + * printf ("};\n\n");
> + * printf ("static const struct icade_key "
> + * "icade_usage_table[%d] = {\n", max_usage + 1);
> + * for (trans = icade_keys; trans->from; trans++) {
> + * printf ("\t[%d] = { %s, %d },\n",
> + * usage_for_key (trans->from), trans->to, trans->press);
> + * }
> + * printf ("};\n");
> + *
> + * return 0;
> + * }
> + */
> +
> +#define ICADE_MAX_USAGE 29
> +
> +struct icade_key {
> + u16 to;
> + u8 press:1;
> +};
> +
> +static const struct icade_key icade_usage_table[30] = {
> + [26] = { KEY_UP, 1 },
> + [8] = { KEY_UP, 0 },
> + [7] = { KEY_RIGHT, 1 },
> + [6] = { KEY_RIGHT, 0 },
> + [27] = { KEY_DOWN, 1 },
> + [29] = { KEY_DOWN, 0 },
> + [4] = { KEY_LEFT, 1 },
> + [20] = { KEY_LEFT, 0 },
> + [28] = { BTN_A, 1 },
> + [23] = { BTN_A, 0 },
> + [11] = { BTN_B, 1 },
> + [21] = { BTN_B, 0 },
> + [24] = { BTN_C, 1 },
> + [9] = { BTN_C, 0 },
> + [13] = { BTN_X, 1 },
> + [17] = { BTN_X, 0 },
> + [12] = { BTN_Y, 1 },
> + [16] = { BTN_Y, 0 },
> + [14] = { BTN_Z, 1 },
> + [19] = { BTN_Z, 0 },
> + [18] = { BTN_THUMBL, 1 },
> + [10] = { BTN_THUMBL, 0 },
> + [15] = { BTN_THUMBR, 1 },
> + [25] = { BTN_THUMBR, 0 },
> +};
> +
> +static const struct icade_key *icade_find_translation(u16 from)
> +{
> + if (from < 0 || from > ICADE_MAX_USAGE)
> + return NULL;
> + return &icade_usage_table[from];
> +}
> +
> +static int icade_event(struct hid_device *hdev, struct hid_field *field,
> + struct hid_usage *usage, __s32 value)
> +{
> + const struct icade_key *trans;
> +
> + if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
> + !usage->type)
> + return 0;
> +
> + /* We ignore the fake key up, and act only on key down */
> + if (!value)
> + return 1;
> +
> + trans = icade_find_translation(usage->hid & HID_USAGE);
> +
> + if (!trans)
> + return 1;
> +
> + input_event(field->hidinput->input, usage->type,
> + trans->to, trans->press);
> +
> + return 1;
> +}
> +
> +static int icade_input_mapping(struct hid_device *hdev, struct hid_input *hi,
> + struct hid_field *field, struct hid_usage *usage,
> + unsigned long **bit, int *max)
> +{
> + const struct icade_key *trans;
> +
> + if ((usage->hid & HID_USAGE_PAGE) == HID_UP_KEYBOARD) {
> + trans = icade_find_translation(usage->hid & HID_USAGE);
> +
> + if (!trans)
> + return -1;
> +
> + hid_map_usage(hi, usage, bit, max, EV_KEY, trans->to);
> + set_bit(trans->to, hi->input->keybit);
> +
> + return 1;
> + }
> +
> + /* ignore others */
> + return -1;
> +
> +}
> +
> +static int icade_input_mapped(struct hid_device *hdev, struct hid_input *hi,
> + struct hid_field *field, struct hid_usage *usage,
> + unsigned long **bit, int *max)
> +{
> + if (usage->type == EV_KEY)
> + set_bit(usage->type, hi->input->evbit);
> +
> + return -1;
> +}
> +
> +static const struct hid_device_id icade_devices[] = {
> + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
> +
> + { }
> +};
> +MODULE_DEVICE_TABLE(hid, icade_devices);
> +
> +static struct hid_driver icade_driver = {
> + .name = "icade",
> + .id_table = icade_devices,
> + .event = icade_event,
> + .input_mapped = icade_input_mapped,
> + .input_mapping = icade_input_mapping,
> +};
> +
> +static int __init icade_init(void)
> +{
> + int ret;
> +
> + ret = hid_register_driver(&icade_driver);
> + if (ret)
> + pr_err("can't register icade driver\n");
> +
> + return ret;
> +}
> +
> +static void __exit icade_exit(void)
> +{
> + hid_unregister_driver(&icade_driver);
> +}
> +
> +module_init(icade_init);
> +module_exit(icade_exit);
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
> +MODULE_DESCRIPTION("ION iCade input driver");
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 269b509..9bc8d57 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -420,6 +420,9 @@
> #define USB_VENDOR_ID_ILITEK 0x222a
> #define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001
>
> +#define USB_VENDOR_ID_ION 0x15e4
> +#define USB_DEVICE_ID_ICADE 0x0132
> +
> #define USB_VENDOR_ID_HOLTEK 0x1241
> #define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP 0x5015
>
> --
> 1.7.12.1
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] HID: Add driver for ION iCade
2012-10-31 11:10 [PATCH] HID: Add driver for ION iCade Bastien Nocera
2012-10-31 11:17 ` Bastien Nocera
2012-10-31 11:17 ` Benjamin Tissoires
@ 2012-10-31 14:54 ` Jiri Kosina
2012-10-31 15:49 ` Bastien Nocera
2 siblings, 1 reply; 9+ messages in thread
From: Jiri Kosina @ 2012-10-31 14:54 UTC (permalink / raw)
To: Bastien Nocera; +Cc: linux-input, benjamin.tissoires
On Wed, 31 Oct 2012, Bastien Nocera wrote:
>
> Add a driver for the ION iCade mini arcade cabinet [1]. The device
> generates a key press and release for each joystick movement or
> button press or release. For example, moving the stick to the
> left will generate the "A" key being pressed and the released.
>
> A list of all the combinations is available in the iCade
> developer guide [2].
>
> This driver hides all this and makes the device work as a generic
> joystick.
>
> [1]: http://www.ionaudio.com/products/details/icade
> [2]: http://www.ionaudio.com/downloads/iCade_Dev_Resource_v1.3.pdf
>
> Signed-off-by: Bastien Nocera <hadess@hadess.net>
> ---
> drivers/hid/Kconfig | 9 ++
> drivers/hid/Makefile | 1 +
> drivers/hid/hid-core.c | 1 +
> drivers/hid/hid-icade.c | 259 ++++++++++++++++++++++++++++++++++++++++++++++++
> drivers/hid/hid-ids.h | 3 +
> 5 files changed, 273 insertions(+)
> create mode 100644 drivers/hid/hid-icade.c
>
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 1630150..813f0fe 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -265,6 +265,15 @@ config HID_GYRATION
> ---help---
> Support for Gyration remote control.
>
> +config HID_ICADE
> + tristate "ION iCade arcade controller"
> + depends on (BT_HIDP)
Why the spurious brackets here?
Otherwise the patch looks good, thanks (and thanks Benjamin for review), I
apply and remove the brackets.
--
Jiri Kosina
SUSE Labs
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] HID: Add driver for ION iCade
2012-10-31 14:54 ` Jiri Kosina
@ 2012-10-31 15:49 ` Bastien Nocera
2012-10-31 15:52 ` Jiri Kosina
0 siblings, 1 reply; 9+ messages in thread
From: Bastien Nocera @ 2012-10-31 15:49 UTC (permalink / raw)
To: Jiri Kosina; +Cc: linux-input, benjamin.tissoires
On Wed, 2012-10-31 at 15:54 +0100, Jiri Kosina wrote:
> On Wed, 31 Oct 2012, Bastien Nocera wrote:
>
> >
> > Add a driver for the ION iCade mini arcade cabinet [1]. The device
> > generates a key press and release for each joystick movement or
> > button press or release. For example, moving the stick to the
> > left will generate the "A" key being pressed and the released.
> >
> > A list of all the combinations is available in the iCade
> > developer guide [2].
> >
> > This driver hides all this and makes the device work as a generic
> > joystick.
> >
> > [1]: http://www.ionaudio.com/products/details/icade
> > [2]: http://www.ionaudio.com/downloads/iCade_Dev_Resource_v1.3.pdf
> >
> > Signed-off-by: Bastien Nocera <hadess@hadess.net>
> > ---
> > drivers/hid/Kconfig | 9 ++
> > drivers/hid/Makefile | 1 +
> > drivers/hid/hid-core.c | 1 +
> > drivers/hid/hid-icade.c | 259 ++++++++++++++++++++++++++++++++++++++++++++++++
> > drivers/hid/hid-ids.h | 3 +
> > 5 files changed, 273 insertions(+)
> > create mode 100644 drivers/hid/hid-icade.c
> >
> > diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> > index 1630150..813f0fe 100644
> > --- a/drivers/hid/Kconfig
> > +++ b/drivers/hid/Kconfig
> > @@ -265,6 +265,15 @@ config HID_GYRATION
> > ---help---
> > Support for Gyration remote control.
> >
> > +config HID_ICADE
> > + tristate "ION iCade arcade controller"
> > + depends on (BT_HIDP)
>
> Why the spurious brackets here?
>
> Otherwise the patch looks good, thanks (and thanks Benjamin for review), I
> apply and remove the brackets.
Probably because whatever I copy/pasted it from had the brackets. Did
you make the typos changes in the commit message itself as well?
Cheers
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] HID: Add driver for ION iCade
2012-10-31 15:49 ` Bastien Nocera
@ 2012-10-31 15:52 ` Jiri Kosina
2012-10-31 15:57 ` Bastien Nocera
0 siblings, 1 reply; 9+ messages in thread
From: Jiri Kosina @ 2012-10-31 15:52 UTC (permalink / raw)
To: Bastien Nocera; +Cc: linux-input, benjamin.tissoires
On Wed, 31 Oct 2012, Bastien Nocera wrote:
> Probably because whatever I copy/pasted it from had the brackets.
I don't see any such occurence in hid/Kconfig. Anyway, not important at
all :)
> Did you make the typos changes in the commit message itself as well?
Yup. Thanks,
--
Jiri Kosina
SUSE Labs
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] HID: Add driver for ION iCade
2012-10-31 15:52 ` Jiri Kosina
@ 2012-10-31 15:57 ` Bastien Nocera
0 siblings, 0 replies; 9+ messages in thread
From: Bastien Nocera @ 2012-10-31 15:57 UTC (permalink / raw)
To: Jiri Kosina; +Cc: linux-input, benjamin.tissoires
On Wed, 2012-10-31 at 16:52 +0100, Jiri Kosina wrote:
> On Wed, 31 Oct 2012, Bastien Nocera wrote:
>
> > Probably because whatever I copy/pasted it from had the brackets.
>
> I don't see any such occurence in hid/Kconfig. Anyway, not important at
> all :)
I wrote the driver nearly a year ago, Benjamin helped me get it working
yesterday.
> > Did you make the typos changes in the commit message itself as well?
>
> Yup. Thanks,
Great stuff. Now onto the other HID drivers :)
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2012-10-31 15:57 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-31 11:10 [PATCH] HID: Add driver for ION iCade Bastien Nocera
2012-10-31 11:17 ` Bastien Nocera
2012-10-31 11:17 ` Benjamin Tissoires
2012-10-31 14:54 ` Jiri Kosina
2012-10-31 15:49 ` Bastien Nocera
2012-10-31 15:52 ` Jiri Kosina
2012-10-31 15:57 ` Bastien Nocera
-- strict thread matches above, loose matches on Subject: below --
2012-10-30 19:55 Bastien Nocera
2012-10-30 21:46 ` Benjamin Tissoires
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).