Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.16-rc5 314 lines 7.8 kB view raw
1/* 2 * HID driver for ELO usb touchscreen 4000/4500 3 * 4 * Copyright (c) 2013 Jiri Slaby 5 * 6 * Data parsing taken from elousb driver by Vojtech Pavlik. 7 * 8 * This driver is licensed under the terms of GPLv2. 9 */ 10 11#include <linux/hid.h> 12#include <linux/input.h> 13#include <linux/module.h> 14#include <linux/usb.h> 15#include <linux/workqueue.h> 16 17#include "hid-ids.h" 18 19#define ELO_PERIODIC_READ_INTERVAL HZ 20#define ELO_SMARTSET_CMD_TIMEOUT 2000 /* msec */ 21 22/* Elo SmartSet commands */ 23#define ELO_FLUSH_SMARTSET_RESPONSES 0x02 /* Flush all pending smartset responses */ 24#define ELO_SEND_SMARTSET_COMMAND 0x05 /* Send a smartset command */ 25#define ELO_GET_SMARTSET_RESPONSE 0x06 /* Get a smartset response */ 26#define ELO_DIAG 0x64 /* Diagnostics command */ 27#define ELO_SMARTSET_PACKET_SIZE 8 28 29struct elo_priv { 30 struct usb_device *usbdev; 31 struct delayed_work work; 32 unsigned char buffer[ELO_SMARTSET_PACKET_SIZE]; 33}; 34 35static struct workqueue_struct *wq; 36static bool use_fw_quirk = true; 37module_param(use_fw_quirk, bool, S_IRUGO); 38MODULE_PARM_DESC(use_fw_quirk, "Do periodic pokes for broken M firmwares (default = true)"); 39 40static int elo_input_configured(struct hid_device *hdev, 41 struct hid_input *hidinput) 42{ 43 struct input_dev *input = hidinput->input; 44 45 /* 46 * ELO devices have one Button usage in GenDesk field, which makes 47 * hid-input map it to BTN_LEFT; that confuses userspace, which then 48 * considers the device to be a mouse/touchpad instead of touchscreen. 49 */ 50 clear_bit(BTN_LEFT, input->keybit); 51 set_bit(BTN_TOUCH, input->keybit); 52 set_bit(ABS_PRESSURE, input->absbit); 53 input_set_abs_params(input, ABS_PRESSURE, 0, 256, 0, 0); 54 55 return 0; 56} 57 58static void elo_process_data(struct input_dev *input, const u8 *data, int size) 59{ 60 int press; 61 62 input_report_abs(input, ABS_X, (data[3] << 8) | data[2]); 63 input_report_abs(input, ABS_Y, (data[5] << 8) | data[4]); 64 65 press = 0; 66 if (data[1] & 0x80) 67 press = (data[7] << 8) | data[6]; 68 input_report_abs(input, ABS_PRESSURE, press); 69 70 if (data[1] & 0x03) { 71 input_report_key(input, BTN_TOUCH, 1); 72 input_sync(input); 73 } 74 75 if (data[1] & 0x04) 76 input_report_key(input, BTN_TOUCH, 0); 77 78 input_sync(input); 79} 80 81static int elo_raw_event(struct hid_device *hdev, struct hid_report *report, 82 u8 *data, int size) 83{ 84 struct hid_input *hidinput; 85 86 if (!(hdev->claimed & HID_CLAIMED_INPUT) || list_empty(&hdev->inputs)) 87 return 0; 88 89 hidinput = list_first_entry(&hdev->inputs, struct hid_input, list); 90 91 switch (report->id) { 92 case 0: 93 if (data[0] == 'T') { /* Mandatory ELO packet marker */ 94 elo_process_data(hidinput->input, data, size); 95 return 1; 96 } 97 break; 98 default: /* unknown report */ 99 /* Unknown report type; pass upstream */ 100 hid_info(hdev, "unknown report type %d\n", report->id); 101 break; 102 } 103 104 return 0; 105} 106 107static int elo_smartset_send_get(struct usb_device *dev, u8 command, 108 void *data) 109{ 110 unsigned int pipe; 111 u8 dir; 112 113 if (command == ELO_SEND_SMARTSET_COMMAND) { 114 pipe = usb_sndctrlpipe(dev, 0); 115 dir = USB_DIR_OUT; 116 } else if (command == ELO_GET_SMARTSET_RESPONSE) { 117 pipe = usb_rcvctrlpipe(dev, 0); 118 dir = USB_DIR_IN; 119 } else 120 return -EINVAL; 121 122 return usb_control_msg(dev, pipe, command, 123 dir | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 124 0, 0, data, ELO_SMARTSET_PACKET_SIZE, 125 ELO_SMARTSET_CMD_TIMEOUT); 126} 127 128static int elo_flush_smartset_responses(struct usb_device *dev) 129{ 130 return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 131 ELO_FLUSH_SMARTSET_RESPONSES, 132 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 133 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); 134} 135 136static void elo_work(struct work_struct *work) 137{ 138 struct elo_priv *priv = container_of(work, struct elo_priv, work.work); 139 struct usb_device *dev = priv->usbdev; 140 unsigned char *buffer = priv->buffer; 141 int ret; 142 143 ret = elo_flush_smartset_responses(dev); 144 if (ret < 0) { 145 dev_err(&dev->dev, "initial FLUSH_SMARTSET_RESPONSES failed, error %d\n", 146 ret); 147 goto fail; 148 } 149 150 /* send Diagnostics command */ 151 *buffer = ELO_DIAG; 152 ret = elo_smartset_send_get(dev, ELO_SEND_SMARTSET_COMMAND, buffer); 153 if (ret < 0) { 154 dev_err(&dev->dev, "send Diagnostics Command failed, error %d\n", 155 ret); 156 goto fail; 157 } 158 159 /* get the result */ 160 ret = elo_smartset_send_get(dev, ELO_GET_SMARTSET_RESPONSE, buffer); 161 if (ret < 0) { 162 dev_err(&dev->dev, "get Diagnostics Command response failed, error %d\n", 163 ret); 164 goto fail; 165 } 166 167 /* read the ack */ 168 if (*buffer != 'A') { 169 ret = elo_smartset_send_get(dev, ELO_GET_SMARTSET_RESPONSE, 170 buffer); 171 if (ret < 0) { 172 dev_err(&dev->dev, "get acknowledge response failed, error %d\n", 173 ret); 174 goto fail; 175 } 176 } 177 178fail: 179 ret = elo_flush_smartset_responses(dev); 180 if (ret < 0) 181 dev_err(&dev->dev, "final FLUSH_SMARTSET_RESPONSES failed, error %d\n", 182 ret); 183 queue_delayed_work(wq, &priv->work, ELO_PERIODIC_READ_INTERVAL); 184} 185 186/* 187 * Not all Elo devices need the periodic HID descriptor reads. 188 * Only firmware version M needs this. 189 */ 190static bool elo_broken_firmware(struct usb_device *dev) 191{ 192 struct usb_device *hub = dev->parent; 193 struct usb_device *child = NULL; 194 u16 fw_lvl = le16_to_cpu(dev->descriptor.bcdDevice); 195 u16 child_vid, child_pid; 196 int i; 197 198 if (!use_fw_quirk) 199 return false; 200 if (fw_lvl != 0x10d) 201 return false; 202 203 /* iterate sibling devices of the touch controller */ 204 usb_hub_for_each_child(hub, i, child) { 205 child_vid = le16_to_cpu(child->descriptor.idVendor); 206 child_pid = le16_to_cpu(child->descriptor.idProduct); 207 208 /* 209 * If one of the devices below is present attached as a sibling of 210 * the touch controller then this is a newer IBM 4820 monitor that 211 * does not need the IBM-requested workaround if fw level is 212 * 0x010d - aka 'M'. 213 * No other HW can have this combination. 214 */ 215 if (child_vid==0x04b3) { 216 switch (child_pid) { 217 case 0x4676: /* 4820 21x Video */ 218 case 0x4677: /* 4820 51x Video */ 219 case 0x4678: /* 4820 2Lx Video */ 220 case 0x4679: /* 4820 5Lx Video */ 221 return false; 222 } 223 } 224 } 225 return true; 226} 227 228static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id) 229{ 230 struct elo_priv *priv; 231 int ret; 232 233 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 234 if (!priv) 235 return -ENOMEM; 236 237 INIT_DELAYED_WORK(&priv->work, elo_work); 238 priv->usbdev = interface_to_usbdev(to_usb_interface(hdev->dev.parent)); 239 240 hid_set_drvdata(hdev, priv); 241 242 ret = hid_parse(hdev); 243 if (ret) { 244 hid_err(hdev, "parse failed\n"); 245 goto err_free; 246 } 247 248 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 249 if (ret) { 250 hid_err(hdev, "hw start failed\n"); 251 goto err_free; 252 } 253 254 if (elo_broken_firmware(priv->usbdev)) { 255 hid_info(hdev, "broken firmware found, installing workaround\n"); 256 queue_delayed_work(wq, &priv->work, ELO_PERIODIC_READ_INTERVAL); 257 } 258 259 return 0; 260err_free: 261 kfree(priv); 262 return ret; 263} 264 265static void elo_remove(struct hid_device *hdev) 266{ 267 struct elo_priv *priv = hid_get_drvdata(hdev); 268 269 hid_hw_stop(hdev); 270 cancel_delayed_work_sync(&priv->work); 271 kfree(priv); 272} 273 274static const struct hid_device_id elo_devices[] = { 275 { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009), }, 276 { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0030), }, 277 { } 278}; 279MODULE_DEVICE_TABLE(hid, elo_devices); 280 281static struct hid_driver elo_driver = { 282 .name = "elo", 283 .id_table = elo_devices, 284 .probe = elo_probe, 285 .remove = elo_remove, 286 .raw_event = elo_raw_event, 287 .input_configured = elo_input_configured, 288}; 289 290static int __init elo_driver_init(void) 291{ 292 int ret; 293 294 wq = create_singlethread_workqueue("elousb"); 295 if (!wq) 296 return -ENOMEM; 297 298 ret = hid_register_driver(&elo_driver); 299 if (ret) 300 destroy_workqueue(wq); 301 302 return ret; 303} 304module_init(elo_driver_init); 305 306static void __exit elo_driver_exit(void) 307{ 308 hid_unregister_driver(&elo_driver); 309 destroy_workqueue(wq); 310} 311module_exit(elo_driver_exit); 312 313MODULE_AUTHOR("Jiri Slaby <jslaby@suse.cz>"); 314MODULE_LICENSE("GPL");