diff options
author | Olivier Scherler <oscherler@ithink.ch> | 2013-07-27 19:20:02 +0200 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2013-07-29 11:49:29 +0200 |
commit | cb2c9e3f92480a292670e2cc261723ce4de8059e (patch) | |
tree | 4d10b5d17b78f124b9eeba66c3fcd1e4cc8722c9 /drivers/hid/hid-xinmo.c | |
parent | dfc450b55d6b9215da27c5dc2c5f3ca1865575a6 (diff) |
HID: Add new driver for non-compliant Xin-Mo devices.
The driver currently only supports the Dual Arcade controller.
It fixes the negative axis event values (the devices sends -2) to match the
logical axis minimum of the HID report descriptor (the report announces -1).
It is needed because hid-input discards out of bounds values.
Signed-off-by: Olivier Scherler <oscherler@ithink.ch>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-xinmo.c')
-rw-r--r-- | drivers/hid/hid-xinmo.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/drivers/hid/hid-xinmo.c b/drivers/hid/hid-xinmo.c new file mode 100644 index 000000000000..6153e50d9721 --- /dev/null +++ b/drivers/hid/hid-xinmo.c @@ -0,0 +1,72 @@ +/* + * HID driver for Xin-Mo devices, currently only the Dual Arcade controller. + * Fixes the negative axis event values (the devices sends -2) to match the + * logical axis minimum of the HID report descriptor (the report announces + * -1). It is needed because hid-input discards out of bounds values. + * (This module is based on "hid-saitek" and "hid-lg".) + * + * Copyright (c) 2013 Olivier Scherler + */ + +/* + * 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/kernel.h> + +#include "hid-ids.h" + +/* + * Fix negative events that are out of bounds. + */ +static int xinmo_event(struct hid_device *hdev, struct hid_field *field, + struct hid_usage *usage, __s32 value) +{ + switch (usage->code) { + case ABS_X: + case ABS_Y: + case ABS_Z: + case ABS_RX: + if (value < -1) { + input_event(field->hidinput->input, usage->type, + usage->code, -1); + return 1; + } + break; + } + + return 0; +} + +static const struct hid_device_id xinmo_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE) }, + { } +}; + +MODULE_DEVICE_TABLE(hid, xinmo_devices); + +static struct hid_driver xinmo_driver = { + .name = "xinmo", + .id_table = xinmo_devices, + .event = xinmo_event +}; + +static int __init xinmo_init(void) +{ + return hid_register_driver(&xinmo_driver); +} + +static void __exit xinmo_exit(void) +{ + hid_unregister_driver(&xinmo_driver); +} + +module_init(xinmo_init); +module_exit(xinmo_exit); +MODULE_LICENSE("GPL"); |