Re: [PATCH v2] HID: add ouya HID driver

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

 



Hi Lukas,

On 12.05.2018 03:49, Lukas Rusak wrote:
> This driver is a simple implementation to get the controller working
> and mapped properly.
> This driver does not include functionality for the touchpad (yet). The
> original driver
> was taken from from the ouya linux tree and has been simplified. It
> seems there may have
> been other versions of the controller present that had a broken report
> descriptor. I have
> removed that for now.

Would be nice if we have native Ouya support, also have two of those
controllers here :-)

Btw, commit text should be broken at around 70 characters or so.

> 
> V2:
>   - updated original authors email
> 
> ---
>  drivers/hid/Kconfig      |   6 ++
>  drivers/hid/Makefile     |   1 +
>  drivers/hid/hid-ids.h    |   3 +
>  drivers/hid/hid-ouya.c   | 131 +++++++++++++++++++++++++++++++++++++++
>  drivers/hid/hid-quirks.c |   3 +
>  5 files changed, 144 insertions(+)
>  create mode 100644 drivers/hid/hid-ouya.c
> 
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 60252fd796f6..6be2c454e72e 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -659,6 +659,12 @@ config HID_ORTEK
>  	   - Ortek WKB-2000
>  	   - Skycable wireless presenter
>  
> +config HID_OUYA
> +	tristate "OUYA Game Controller"
> +	depends on USB_HID
> +	---help---
> +	  Support for OUYA Game Controller.
> +
>  config HID_PANTHERLORD
>  	tristate "Pantherlord/GreenAsia game controller"
>  	depends on HID
> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> index 17a8bd97da9d..4425890934e4 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -71,6 +71,7 @@ obj-$(CONFIG_HID_MULTITOUCH)	+= hid-multitouch.o
>  obj-$(CONFIG_HID_NTI)			+= hid-nti.o
>  obj-$(CONFIG_HID_NTRIG)		+= hid-ntrig.o
>  obj-$(CONFIG_HID_ORTEK)		+= hid-ortek.o
> +obj-$(CONFIG_HID_OUYA)		+= hid-ouya.o
>  obj-$(CONFIG_HID_PRODIKEYS)	+= hid-prodikeys.o
>  obj-$(CONFIG_HID_PANTHERLORD)	+= hid-pl.o
>  obj-$(CONFIG_HID_PENMOUNT)	+= hid-penmount.o
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 0b5cc910f62e..0528efb825fa 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -859,6 +859,9 @@
>  #define USB_DEVICE_ID_ORTEK_WKB2000	0x2000
>  #define USB_DEVICE_ID_ORTEK_IHOME_IMAC_A210S	0x8003
>  
> +#define USB_VENDOR_ID_OUYA 0x2836
> +#define USB_DEVICE_ID_OUYA_CONTROLLER 0x0001
> +
>  #define USB_VENDOR_ID_PLANTRONICS	0x047f
>  
>  #define USB_VENDOR_ID_PANASONIC		0x04da
> diff --git a/drivers/hid/hid-ouya.c b/drivers/hid/hid-ouya.c
> new file mode 100644
> index 000000000000..4344a47b40af
> --- /dev/null
> +++ b/drivers/hid/hid-ouya.c
> @@ -0,0 +1,131 @@
> +/*
> + *  HID driver for OUYA Game Controller(s)
> + *
> + *  Copyright (c) 2013 OUYA
> + *  Copyright (c) 2013 Gregorios Leach <optikflux@xxxxxxxxx>
> + *  Copyright (c) 2018 Lukas Rusak <lorusak@xxxxxxxxx>
> + */
> +
> +#include <linux/device.h>
> +#include <linux/hid.h>
> +#include <linux/input.h>
> +#include <linux/module.h>
> +
> +#include "hid-ids.h"
> +
> +static const unsigned int ouya_absmap[] = {
> +	[0x30] = ABS_X,		/* left stick X */
> +	[0x31] = ABS_Y,		/* left stick Y */
> +	[0x32] = ABS_Z,		/* L2 */
> +	[0x33] = ABS_RX,	/* right stick X */
> +	[0x34] = ABS_RY,	/* right stick Y */
> +	[0x35] = ABS_RZ,	/* R2 */
> +};
> +
> +static const unsigned int ouya_keymap[] = {
> +	[0x1] = BTN_SOUTH,	/* O */
> +	[0x2] = BTN_WEST,	/* U */
> +	[0x3] = BTN_NORTH,	/* Y */
> +	[0x4] = BTN_EAST,	/* A */
> +	[0x5] = BTN_TL,		/* L1 */
> +	[0x6] = BTN_TR,		/* R1 */
> +	[0x7] = BTN_THUMBL,	/* L3 */
> +	[0x8] = BTN_THUMBR,	/* R3 */
> +	[0x9] = BTN_DPAD_UP,	/* Up */
> +	[0xa] = BTN_DPAD_DOWN,	/* Down */
> +	[0xb] = BTN_DPAD_LEFT,	/* Left */
> +	[0xc] = BTN_DPAD_RIGHT, /* Right */
> +	[0xd] = BTN_TL2,	/* L2 */
> +	[0xe] = BTN_TR2,	/* R2 */
> +	[0xf] = BTN_MODE,	/* Power */
> +};
> +
> +static int ouya_input_mapping(struct hid_device *hdev, struct hid_input *hi,
> +			       struct hid_field *field, struct hid_usage *usage,
> +			       unsigned long **bit, int *max)
> +{
> +	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
> +		unsigned int key = usage->hid & HID_USAGE;
> +
> +		if (key >= ARRAY_SIZE(ouya_keymap))
> +			return -1;
> +
> +		key = ouya_keymap[key];
> +		hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
> +
> +		return 1;
> +
> +	} else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) {
> +		unsigned int abs = usage->hid & HID_USAGE;
> +
> +		if (abs >= ARRAY_SIZE(ouya_absmap))
> +			return -1;
> +
> +		abs = ouya_absmap[abs];
> +		hid_map_usage_clear(hi, usage, bit, max, EV_ABS, abs);
> +
> +		return 1;
> +	}
> +
> +	return 0;
> +}
> +
> +static int ouya_probe(struct hid_device *hdev, const struct hid_device_id *id)
> +{
> +	int ret;
> +
> +	ret = hid_parse(hdev);
> +	if (ret) {
> +		hid_err(hdev, "parse failed\n");
> +		goto err_free;

Since you do not do anything in free, you can return here directly.

> +	}
> +
> +	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | HID_CONNECT_HIDDEV_FORCE);
> +	if (ret) {
> +		hid_err(hdev, "hw start failed\n");
> +		goto err_free;

Same here.

> +	}
> +
> +	return 0;
> +
> +err_free:

And remove that label.

> +	return ret;
> +}
> +
> +static void ouya_remove(struct hid_device *hdev)
> +{
> +	hid_hw_stop(hdev);
> +	kfree(hid_get_drvdata(hdev));

You don't allocate/set drvdata, so this is probably not required.

> +}
> +
> +static const struct hid_device_id ouya_devices[] = {
> +	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_OUYA, USB_DEVICE_ID_OUYA_CONTROLLER) },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(hid, ouya_devices);
> +
> +static struct hid_driver ouya_driver = {
> +	.name = "ouya",
> +	.id_table = ouya_devices,
> +	.input_mapping = ouya_input_mapping,
> +	.probe = ouya_probe,
> +	.remove = ouya_remove,
> +};
> +
> +static int __init ouya_init(void)
> +{
> +	return hid_register_driver(&ouya_driver);
> +}
> +
> +static void __exit ouya_exit(void)
> +{
> +	hid_unregister_driver(&ouya_driver);
> +}
> +
> +module_init(ouya_init);
> +module_exit(ouya_exit);

There is module_hid_driver which should make that part a bit simpler.

--
Stefan

> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Lukas Rusak <lorusak@xxxxxxxxx>");
> +MODULE_AUTHOR("Gregorios Leach <optikflux@xxxxxxxxx>");
> +MODULE_DESCRIPTION("Ouya Controller Driver");
> diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
> index 587e2681a53f..b5adc13e0df1 100644
> --- a/drivers/hid/hid-quirks.c
> +++ b/drivers/hid/hid-quirks.c
> @@ -538,6 +538,9 @@ static const struct hid_device_id
> hid_have_special_driver[] = {
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_IHOME_IMAC_A210S) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE,
> USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
>  #endif
> +#if IS_ENABLED(CONFIG_HID_OUYA)
> +	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_OUYA, USB_DEVICE_ID_OUYA_CONTROLLER) },
> +#endif
>  #if IS_ENABLED(CONFIG_HID_PANTHERLORD)
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON,
> USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON,
> USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },



[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