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 77dc2db6d1d2703ee4e83d4b3dbecf4e06a910e6 413 lines 9.3 kB view raw
1/* 2 * Elo serial touchscreen driver 3 * 4 * Copyright (c) 2004 Vojtech Pavlik 5 */ 6 7/* 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License version 2 as published by 10 * the Free Software Foundation. 11 */ 12 13/* 14 * This driver can handle serial Elo touchscreens using either the Elo standard 15 * 'E271-2210' 10-byte protocol, Elo legacy 'E281A-4002' 6-byte protocol, Elo 16 * legacy 'E271-140' 4-byte protocol and Elo legacy 'E261-280' 3-byte protocol. 17 */ 18 19#include <linux/errno.h> 20#include <linux/kernel.h> 21#include <linux/module.h> 22#include <linux/slab.h> 23#include <linux/input.h> 24#include <linux/serio.h> 25#include <linux/init.h> 26#include <linux/ctype.h> 27 28#define DRIVER_DESC "Elo serial touchscreen driver" 29 30MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 31MODULE_DESCRIPTION(DRIVER_DESC); 32MODULE_LICENSE("GPL"); 33 34/* 35 * Definitions & global arrays. 36 */ 37 38#define ELO_MAX_LENGTH 10 39 40#define ELO10_PACKET_LEN 8 41#define ELO10_TOUCH 0x03 42#define ELO10_PRESSURE 0x80 43 44#define ELO10_LEAD_BYTE 'U' 45 46#define ELO10_ID_CMD 'i' 47 48#define ELO10_TOUCH_PACKET 'T' 49#define ELO10_ACK_PACKET 'A' 50#define ELI10_ID_PACKET 'I' 51 52/* 53 * Per-touchscreen data. 54 */ 55 56struct elo { 57 struct input_dev *dev; 58 struct serio *serio; 59 struct mutex cmd_mutex; 60 struct completion cmd_done; 61 int id; 62 int idx; 63 unsigned char expected_packet; 64 unsigned char csum; 65 unsigned char data[ELO_MAX_LENGTH]; 66 unsigned char response[ELO10_PACKET_LEN]; 67 char phys[32]; 68}; 69 70static void elo_process_data_10(struct elo *elo, unsigned char data, struct pt_regs *regs) 71{ 72 struct input_dev *dev = elo->dev; 73 74 elo->data[elo->idx] = data; 75 switch (elo->idx++) { 76 case 0: 77 elo->csum = 0xaa; 78 if (data != ELO10_LEAD_BYTE) { 79 pr_debug("elo: unsynchronized data: 0x%02x\n", data); 80 elo->idx = 0; 81 } 82 break; 83 84 case 9: 85 elo->idx = 0; 86 if (data != elo->csum) { 87 pr_debug("elo: bad checksum: 0x%02x, expected 0x%02x\n", 88 data, elo->csum); 89 break; 90 } 91 if (elo->data[1] != elo->expected_packet) { 92 if (elo->data[1] != ELO10_TOUCH_PACKET) 93 pr_debug("elo: unexpected packet: 0x%02x\n", 94 elo->data[1]); 95 break; 96 } 97 if (likely(elo->data[1] == ELO10_TOUCH_PACKET)) { 98 input_regs(dev, regs); 99 input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]); 100 input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]); 101 if (elo->data[2] & ELO10_PRESSURE) 102 input_report_abs(dev, ABS_PRESSURE, 103 (elo->data[8] << 8) | elo->data[7]); 104 input_report_key(dev, BTN_TOUCH, elo->data[2] & ELO10_TOUCH); 105 input_sync(dev); 106 } else if (elo->data[1] == ELO10_ACK_PACKET) { 107 if (elo->data[2] == '0') 108 elo->expected_packet = ELO10_TOUCH_PACKET; 109 complete(&elo->cmd_done); 110 } else { 111 memcpy(elo->response, &elo->data[1], ELO10_PACKET_LEN); 112 elo->expected_packet = ELO10_ACK_PACKET; 113 } 114 break; 115 } 116 elo->csum += data; 117} 118 119static void elo_process_data_6(struct elo *elo, unsigned char data, struct pt_regs *regs) 120{ 121 struct input_dev *dev = elo->dev; 122 123 elo->data[elo->idx] = data; 124 125 switch (elo->idx++) { 126 127 case 0: if ((data & 0xc0) != 0xc0) elo->idx = 0; break; 128 case 1: if ((data & 0xc0) != 0x80) elo->idx = 0; break; 129 case 2: if ((data & 0xc0) != 0x40) elo->idx = 0; break; 130 131 case 3: 132 if (data & 0xc0) { 133 elo->idx = 0; 134 break; 135 } 136 137 input_regs(dev, regs); 138 input_report_abs(dev, ABS_X, ((elo->data[0] & 0x3f) << 6) | (elo->data[1] & 0x3f)); 139 input_report_abs(dev, ABS_Y, ((elo->data[2] & 0x3f) << 6) | (elo->data[3] & 0x3f)); 140 141 if (elo->id == 2) { 142 input_report_key(dev, BTN_TOUCH, 1); 143 input_sync(dev); 144 elo->idx = 0; 145 } 146 147 break; 148 149 case 4: 150 if (data) { 151 input_sync(dev); 152 elo->idx = 0; 153 } 154 break; 155 156 case 5: 157 if ((data & 0xf0) == 0) { 158 input_report_abs(dev, ABS_PRESSURE, elo->data[5]); 159 input_report_key(dev, BTN_TOUCH, !!elo->data[5]); 160 } 161 input_sync(dev); 162 elo->idx = 0; 163 break; 164 } 165} 166 167static void elo_process_data_3(struct elo *elo, unsigned char data, struct pt_regs *regs) 168{ 169 struct input_dev *dev = elo->dev; 170 171 elo->data[elo->idx] = data; 172 173 switch (elo->idx++) { 174 175 case 0: 176 if ((data & 0x7f) != 0x01) 177 elo->idx = 0; 178 break; 179 case 2: 180 input_regs(dev, regs); 181 input_report_key(dev, BTN_TOUCH, !(elo->data[1] & 0x80)); 182 input_report_abs(dev, ABS_X, elo->data[1]); 183 input_report_abs(dev, ABS_Y, elo->data[2]); 184 input_sync(dev); 185 elo->idx = 0; 186 break; 187 } 188} 189 190static irqreturn_t elo_interrupt(struct serio *serio, 191 unsigned char data, unsigned int flags, struct pt_regs *regs) 192{ 193 struct elo *elo = serio_get_drvdata(serio); 194 195 switch(elo->id) { 196 case 0: 197 elo_process_data_10(elo, data, regs); 198 break; 199 200 case 1: 201 case 2: 202 elo_process_data_6(elo, data, regs); 203 break; 204 205 case 3: 206 elo_process_data_3(elo, data, regs); 207 break; 208 } 209 210 return IRQ_HANDLED; 211} 212 213static int elo_command_10(struct elo *elo, unsigned char *packet) 214{ 215 int rc = -1; 216 int i; 217 unsigned char csum = 0xaa + ELO10_LEAD_BYTE; 218 219 mutex_lock(&elo->cmd_mutex); 220 221 serio_pause_rx(elo->serio); 222 elo->expected_packet = toupper(packet[0]); 223 init_completion(&elo->cmd_done); 224 serio_continue_rx(elo->serio); 225 226 if (serio_write(elo->serio, ELO10_LEAD_BYTE)) 227 goto out; 228 229 for (i = 0; i < ELO10_PACKET_LEN; i++) { 230 csum += packet[i]; 231 if (serio_write(elo->serio, packet[i])) 232 goto out; 233 } 234 235 if (serio_write(elo->serio, csum)) 236 goto out; 237 238 wait_for_completion_timeout(&elo->cmd_done, HZ); 239 240 if (elo->expected_packet == ELO10_TOUCH_PACKET) { 241 /* We are back in reporting mode, the command was ACKed */ 242 memcpy(packet, elo->response, ELO10_PACKET_LEN); 243 rc = 0; 244 } 245 246 out: 247 mutex_unlock(&elo->cmd_mutex); 248 return rc; 249} 250 251static int elo_setup_10(struct elo *elo) 252{ 253 static const char *elo_types[] = { "Accu", "Dura", "Intelli", "Carroll" }; 254 struct input_dev *dev = elo->dev; 255 unsigned char packet[ELO10_PACKET_LEN] = { ELO10_ID_CMD }; 256 257 if (elo_command_10(elo, packet)) 258 return -1; 259 260 dev->id.version = (packet[5] << 8) | packet[4]; 261 262 input_set_abs_params(dev, ABS_X, 96, 4000, 0, 0); 263 input_set_abs_params(dev, ABS_Y, 96, 4000, 0, 0); 264 if (packet[3] & ELO10_PRESSURE) 265 input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); 266 267 printk(KERN_INFO "elo: %sTouch touchscreen, fw: %02x.%02x, " 268 "features: %x02x, controller: 0x%02x\n", 269 elo_types[(packet[1] -'0') & 0x03], 270 packet[5], packet[4], packet[3], packet[7]); 271 272 return 0; 273} 274 275/* 276 * elo_disconnect() is the opposite of elo_connect() 277 */ 278 279static void elo_disconnect(struct serio *serio) 280{ 281 struct elo *elo = serio_get_drvdata(serio); 282 283 input_get_device(elo->dev); 284 input_unregister_device(elo->dev); 285 serio_close(serio); 286 serio_set_drvdata(serio, NULL); 287 input_put_device(elo->dev); 288 kfree(elo); 289} 290 291/* 292 * elo_connect() is the routine that is called when someone adds a 293 * new serio device that supports Gunze protocol and registers it as 294 * an input device. 295 */ 296 297static int elo_connect(struct serio *serio, struct serio_driver *drv) 298{ 299 struct elo *elo; 300 struct input_dev *input_dev; 301 int err; 302 303 elo = kzalloc(sizeof(struct elo), GFP_KERNEL); 304 input_dev = input_allocate_device(); 305 if (!elo || !input_dev) { 306 err = -ENOMEM; 307 goto fail1; 308 } 309 310 elo->serio = serio; 311 elo->id = serio->id.id; 312 elo->dev = input_dev; 313 elo->expected_packet = ELO10_TOUCH_PACKET; 314 mutex_init(&elo->cmd_mutex); 315 init_completion(&elo->cmd_done); 316 snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys); 317 318 input_dev->private = elo; 319 input_dev->name = "Elo Serial TouchScreen"; 320 input_dev->phys = elo->phys; 321 input_dev->id.bustype = BUS_RS232; 322 input_dev->id.vendor = SERIO_ELO; 323 input_dev->id.product = elo->id; 324 input_dev->id.version = 0x0100; 325 input_dev->cdev.dev = &serio->dev; 326 327 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); 328 input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); 329 330 serio_set_drvdata(serio, elo); 331 err = serio_open(serio, drv); 332 if (err) 333 goto fail2; 334 335 switch (elo->id) { 336 337 case 0: /* 10-byte protocol */ 338 if (elo_setup_10(elo)) 339 goto fail3; 340 341 break; 342 343 case 1: /* 6-byte protocol */ 344 input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0); 345 346 case 2: /* 4-byte protocol */ 347 input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0); 348 input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0); 349 break; 350 351 case 3: /* 3-byte protocol */ 352 input_set_abs_params(input_dev, ABS_X, 0, 255, 0, 0); 353 input_set_abs_params(input_dev, ABS_Y, 0, 255, 0, 0); 354 break; 355 } 356 357 err = input_register_device(elo->dev); 358 if (err) 359 goto fail3; 360 361 return 0; 362 363 fail3: serio_close(serio); 364 fail2: serio_set_drvdata(serio, NULL); 365 fail1: input_free_device(input_dev); 366 kfree(elo); 367 return err; 368} 369 370/* 371 * The serio driver structure. 372 */ 373 374static struct serio_device_id elo_serio_ids[] = { 375 { 376 .type = SERIO_RS232, 377 .proto = SERIO_ELO, 378 .id = SERIO_ANY, 379 .extra = SERIO_ANY, 380 }, 381 { 0 } 382}; 383 384MODULE_DEVICE_TABLE(serio, elo_serio_ids); 385 386static struct serio_driver elo_drv = { 387 .driver = { 388 .name = "elo", 389 }, 390 .description = DRIVER_DESC, 391 .id_table = elo_serio_ids, 392 .interrupt = elo_interrupt, 393 .connect = elo_connect, 394 .disconnect = elo_disconnect, 395}; 396 397/* 398 * The functions for inserting/removing us as a module. 399 */ 400 401static int __init elo_init(void) 402{ 403 serio_register_driver(&elo_drv); 404 return 0; 405} 406 407static void __exit elo_exit(void) 408{ 409 serio_unregister_driver(&elo_drv); 410} 411 412module_init(elo_init); 413module_exit(elo_exit);