Re: [PATCH] HID: Add driver for ION iCade

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

 



Hi Bastien,

a few random comments:

On Tue, Oct 30, 2012 at 8:55 PM, Bastien Nocera <hadess@xxxxxxxxxx> 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@xxxxxxx>
> + *  Copyright (c) 2005 Michael Haboustak <mike-@xxxxxxxxxxxx> for Concept2, Inc
> + *  Copyright (c) 2006-2007 Jiri Kosina
> + *  Copyright (c) 2007 Paul Walmsley
> + *  Copyright (c) 2008 Jiri Slaby <jirislaby@xxxxxxxxx>

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@xxxxxxxxxx>
> + *  Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@xxxxxxxxx>
> + */
> +
> +/*
> + * 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@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[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