forked from Minki/linux
HID: add driver for ELO 4000/4500
This is a driver for ELO 4000/4500 devices which report themselves as HID devices, but do not really send HID events on touch. So we introduce a new HID 'quirk' driver with a raw_event handler where we take care of those events. What we need additionally is an input_configured hook, because the device does not mention anything about PRESSURE and TOUCH in its report descriptor, but it actually generate those. So we set the bits in the corresponding input_dev in that hook. Thanks to Petr Ostadal who was willing to test the driver. The rest of Cc's listed below had something to do with that driver over the years in our enterprise tree. Signed-off-by: Jiri Slaby <jslaby@suse.cz> Tested-by: Petr Ostadal <postadal@suse.cz> Cc: Oliver Neukum <oliver@neukum.org> Cc: Vojtech Pavlik <vojtech@suse.cz> Cc: Egbert Eich <eich@suse.com> Cc: Libor Pechacek <lpechacek@suse.cz> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
This commit is contained in:
parent
f755407dd1
commit
d23efc1947
@ -217,6 +217,13 @@ config HID_ELECOM
|
|||||||
---help---
|
---help---
|
||||||
Support for the ELECOM BM084 (bluetooth mouse).
|
Support for the ELECOM BM084 (bluetooth mouse).
|
||||||
|
|
||||||
|
config HID_ELO
|
||||||
|
tristate "ELO USB 4000/4500 touchscreen"
|
||||||
|
depends on USB_HID
|
||||||
|
---help---
|
||||||
|
Support for the ELO USB 4000/4500 touchscreens. Note that this is for
|
||||||
|
different devices than those handled by CONFIG_TOUCHSCREEN_USB_ELO.
|
||||||
|
|
||||||
config HID_EZKEY
|
config HID_EZKEY
|
||||||
tristate "Ezkey BTC 8193 keyboard" if EXPERT
|
tristate "Ezkey BTC 8193 keyboard" if EXPERT
|
||||||
depends on HID
|
depends on HID
|
||||||
|
@ -48,6 +48,7 @@ obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
|
|||||||
obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o
|
obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o
|
||||||
obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o
|
obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o
|
||||||
obj-$(CONFIG_HID_ELECOM) += hid-elecom.o
|
obj-$(CONFIG_HID_ELECOM) += hid-elecom.o
|
||||||
|
obj-$(CONFIG_HID_ELO) += hid-elo.o
|
||||||
obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
|
obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
|
||||||
obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
|
obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
|
||||||
obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
|
obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
|
||||||
|
@ -1573,6 +1573,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
|||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) },
|
||||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0030) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
|
||||||
{ 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_PSX_ADAPTOR) },
|
||||||
|
131
drivers/hid/hid-elo.c
Normal file
131
drivers/hid/hid-elo.c
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* HID driver for ELO usb touchscreen 4000/4500
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Jiri Slaby
|
||||||
|
*
|
||||||
|
* Data parsing taken from elousb driver by Vojtech Pavlik.
|
||||||
|
*
|
||||||
|
* This driver is licensed under the terms of GPLv2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/hid.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
|
||||||
|
#include "hid-ids.h"
|
||||||
|
|
||||||
|
static void elo_input_configured(struct hid_device *hdev,
|
||||||
|
struct hid_input *hidinput)
|
||||||
|
{
|
||||||
|
struct input_dev *input = hidinput->input;
|
||||||
|
|
||||||
|
set_bit(BTN_TOUCH, input->keybit);
|
||||||
|
set_bit(ABS_PRESSURE, input->absbit);
|
||||||
|
input_set_abs_params(input, ABS_PRESSURE, 0, 256, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void elo_process_data(struct input_dev *input, const u8 *data, int size)
|
||||||
|
{
|
||||||
|
int press;
|
||||||
|
|
||||||
|
input_report_abs(input, ABS_X, (data[3] << 8) | data[2]);
|
||||||
|
input_report_abs(input, ABS_Y, (data[5] << 8) | data[4]);
|
||||||
|
|
||||||
|
press = 0;
|
||||||
|
if (data[1] & 0x80)
|
||||||
|
press = (data[7] << 8) | data[6];
|
||||||
|
input_report_abs(input, ABS_PRESSURE, press);
|
||||||
|
|
||||||
|
if (data[1] & 0x03) {
|
||||||
|
input_report_key(input, BTN_TOUCH, 1);
|
||||||
|
input_sync(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data[1] & 0x04)
|
||||||
|
input_report_key(input, BTN_TOUCH, 0);
|
||||||
|
|
||||||
|
input_sync(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int elo_raw_event(struct hid_device *hdev, struct hid_report *report,
|
||||||
|
u8 *data, int size)
|
||||||
|
{
|
||||||
|
struct hid_input *hidinput;
|
||||||
|
|
||||||
|
if (!(hdev->claimed & HID_CLAIMED_INPUT) || list_empty(&hdev->inputs))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
hidinput = list_first_entry(&hdev->inputs, struct hid_input, list);
|
||||||
|
|
||||||
|
switch (report->id) {
|
||||||
|
case 0:
|
||||||
|
if (data[0] == 'T') { /* Mandatory ELO packet marker */
|
||||||
|
elo_process_data(hidinput->input, data, size);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: /* unknown report */
|
||||||
|
/* Unknown report type; pass upstream */
|
||||||
|
hid_info(hdev, "unknown report type %d\n", report->id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int elo_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 void elo_remove(struct hid_device *hdev)
|
||||||
|
{
|
||||||
|
hid_hw_stop(hdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct hid_device_id elo_devices[] = {
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009), },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0030), },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(hid, elo_devices);
|
||||||
|
|
||||||
|
static struct hid_driver elo_driver = {
|
||||||
|
.name = "elo",
|
||||||
|
.id_table = elo_devices,
|
||||||
|
.probe = elo_probe,
|
||||||
|
.remove = elo_remove,
|
||||||
|
.raw_event = elo_raw_event,
|
||||||
|
.input_configured = elo_input_configured,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init elo_driver_init(void)
|
||||||
|
{
|
||||||
|
return hid_register_driver(&elo_driver);
|
||||||
|
}
|
||||||
|
module_init(elo_driver_init);
|
||||||
|
|
||||||
|
static void __exit elo_driver_exit(void)
|
||||||
|
{
|
||||||
|
hid_unregister_driver(&elo_driver);
|
||||||
|
}
|
||||||
|
module_exit(elo_driver_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Jiri Slaby <jslaby@suse.cz>");
|
||||||
|
MODULE_LICENSE("GPL");
|
Loading…
Reference in New Issue
Block a user