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