1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * Elo serial touchscreen driver 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Copyright (c) 2004 Vojtech Pavlik 61da177e4SLinus Torvalds */ 71da177e4SLinus Torvalds 81da177e4SLinus Torvalds 91da177e4SLinus Torvalds /* 101da177e4SLinus Torvalds * This driver can handle serial Elo touchscreens using either the Elo standard 111da177e4SLinus Torvalds * 'E271-2210' 10-byte protocol, Elo legacy 'E281A-4002' 6-byte protocol, Elo 121da177e4SLinus Torvalds * legacy 'E271-140' 4-byte protocol and Elo legacy 'E261-280' 3-byte protocol. 131da177e4SLinus Torvalds */ 141da177e4SLinus Torvalds 151da177e4SLinus Torvalds #include <linux/errno.h> 161da177e4SLinus Torvalds #include <linux/kernel.h> 171da177e4SLinus Torvalds #include <linux/module.h> 181da177e4SLinus Torvalds #include <linux/slab.h> 191da177e4SLinus Torvalds #include <linux/input.h> 201da177e4SLinus Torvalds #include <linux/serio.h> 21fae3006eSShaun Jackman #include <linux/ctype.h> 221da177e4SLinus Torvalds 231da177e4SLinus Torvalds #define DRIVER_DESC "Elo serial touchscreen driver" 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 261da177e4SLinus Torvalds MODULE_DESCRIPTION(DRIVER_DESC); 271da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds /* 301da177e4SLinus Torvalds * Definitions & global arrays. 311da177e4SLinus Torvalds */ 321da177e4SLinus Torvalds 331da177e4SLinus Torvalds #define ELO_MAX_LENGTH 10 341da177e4SLinus Torvalds 35fae3006eSShaun Jackman #define ELO10_PACKET_LEN 8 36fae3006eSShaun Jackman #define ELO10_TOUCH 0x03 37fae3006eSShaun Jackman #define ELO10_PRESSURE 0x80 38fae3006eSShaun Jackman 391ce316efSShaun Jackman #define ELO10_LEAD_BYTE 'U' 401ce316efSShaun Jackman 41fae3006eSShaun Jackman #define ELO10_ID_CMD 'i' 42fae3006eSShaun Jackman 431ce316efSShaun Jackman #define ELO10_TOUCH_PACKET 'T' 44fae3006eSShaun Jackman #define ELO10_ACK_PACKET 'A' 45fae3006eSShaun Jackman #define ELI10_ID_PACKET 'I' 461ce316efSShaun Jackman 471da177e4SLinus Torvalds /* 481da177e4SLinus Torvalds * Per-touchscreen data. 491da177e4SLinus Torvalds */ 501da177e4SLinus Torvalds 511da177e4SLinus Torvalds struct elo { 52eca1ed19SDmitry Torokhov struct input_dev *dev; 531da177e4SLinus Torvalds struct serio *serio; 54fae3006eSShaun Jackman struct mutex cmd_mutex; 55fae3006eSShaun Jackman struct completion cmd_done; 561da177e4SLinus Torvalds int id; 571da177e4SLinus Torvalds int idx; 58fae3006eSShaun Jackman unsigned char expected_packet; 591da177e4SLinus Torvalds unsigned char csum; 601da177e4SLinus Torvalds unsigned char data[ELO_MAX_LENGTH]; 61fae3006eSShaun Jackman unsigned char response[ELO10_PACKET_LEN]; 621da177e4SLinus Torvalds char phys[32]; 631da177e4SLinus Torvalds }; 641da177e4SLinus Torvalds 657d12e780SDavid Howells static void elo_process_data_10(struct elo *elo, unsigned char data) 661da177e4SLinus Torvalds { 67eca1ed19SDmitry Torokhov struct input_dev *dev = elo->dev; 681da177e4SLinus Torvalds 691ce316efSShaun Jackman elo->data[elo->idx] = data; 708cab9ba1SDmitry Torokhov 711da177e4SLinus Torvalds switch (elo->idx++) { 721da177e4SLinus Torvalds case 0: 731ce316efSShaun Jackman elo->csum = 0xaa; 741ce316efSShaun Jackman if (data != ELO10_LEAD_BYTE) { 758cab9ba1SDmitry Torokhov dev_dbg(&elo->serio->dev, 768cab9ba1SDmitry Torokhov "unsynchronized data: 0x%02x\n", data); 771da177e4SLinus Torvalds elo->idx = 0; 781da177e4SLinus Torvalds } 791da177e4SLinus Torvalds break; 801da177e4SLinus Torvalds 811da177e4SLinus Torvalds case 9: 821ce316efSShaun Jackman elo->idx = 0; 831ce316efSShaun Jackman if (data != elo->csum) { 848cab9ba1SDmitry Torokhov dev_dbg(&elo->serio->dev, 858cab9ba1SDmitry Torokhov "bad checksum: 0x%02x, expected 0x%02x\n", 861ce316efSShaun Jackman data, elo->csum); 871ce316efSShaun Jackman break; 881ce316efSShaun Jackman } 89fae3006eSShaun Jackman if (elo->data[1] != elo->expected_packet) { 90fae3006eSShaun Jackman if (elo->data[1] != ELO10_TOUCH_PACKET) 918cab9ba1SDmitry Torokhov dev_dbg(&elo->serio->dev, 928cab9ba1SDmitry Torokhov "unexpected packet: 0x%02x\n", 93fae3006eSShaun Jackman elo->data[1]); 941ce316efSShaun Jackman break; 951ce316efSShaun Jackman } 96fae3006eSShaun Jackman if (likely(elo->data[1] == ELO10_TOUCH_PACKET)) { 971da177e4SLinus Torvalds input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]); 981da177e4SLinus Torvalds input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]); 99fae3006eSShaun Jackman if (elo->data[2] & ELO10_PRESSURE) 100fae3006eSShaun Jackman input_report_abs(dev, ABS_PRESSURE, 101fae3006eSShaun Jackman (elo->data[8] << 8) | elo->data[7]); 102fae3006eSShaun Jackman input_report_key(dev, BTN_TOUCH, elo->data[2] & ELO10_TOUCH); 1031da177e4SLinus Torvalds input_sync(dev); 104fae3006eSShaun Jackman } else if (elo->data[1] == ELO10_ACK_PACKET) { 105fae3006eSShaun Jackman if (elo->data[2] == '0') 106fae3006eSShaun Jackman elo->expected_packet = ELO10_TOUCH_PACKET; 107fae3006eSShaun Jackman complete(&elo->cmd_done); 108fae3006eSShaun Jackman } else { 109fae3006eSShaun Jackman memcpy(elo->response, &elo->data[1], ELO10_PACKET_LEN); 110fae3006eSShaun Jackman elo->expected_packet = ELO10_ACK_PACKET; 111fae3006eSShaun Jackman } 1121da177e4SLinus Torvalds break; 1131da177e4SLinus Torvalds } 1141ce316efSShaun Jackman elo->csum += data; 1151da177e4SLinus Torvalds } 1161da177e4SLinus Torvalds 1177d12e780SDavid Howells static void elo_process_data_6(struct elo *elo, unsigned char data) 1181da177e4SLinus Torvalds { 119eca1ed19SDmitry Torokhov struct input_dev *dev = elo->dev; 1201da177e4SLinus Torvalds 1211da177e4SLinus Torvalds elo->data[elo->idx] = data; 1221da177e4SLinus Torvalds 1231da177e4SLinus Torvalds switch (elo->idx++) { 1241da177e4SLinus Torvalds 1258cab9ba1SDmitry Torokhov case 0: 1268cab9ba1SDmitry Torokhov if ((data & 0xc0) != 0xc0) 1278cab9ba1SDmitry Torokhov elo->idx = 0; 1288cab9ba1SDmitry Torokhov break; 1298cab9ba1SDmitry Torokhov 1308cab9ba1SDmitry Torokhov case 1: 1318cab9ba1SDmitry Torokhov if ((data & 0xc0) != 0x80) 1328cab9ba1SDmitry Torokhov elo->idx = 0; 1338cab9ba1SDmitry Torokhov break; 1348cab9ba1SDmitry Torokhov 1358cab9ba1SDmitry Torokhov case 2: 1368cab9ba1SDmitry Torokhov if ((data & 0xc0) != 0x40) 1378cab9ba1SDmitry Torokhov elo->idx = 0; 1388cab9ba1SDmitry Torokhov break; 1391da177e4SLinus Torvalds 1401da177e4SLinus Torvalds case 3: 1411da177e4SLinus Torvalds if (data & 0xc0) { 1421da177e4SLinus Torvalds elo->idx = 0; 1431da177e4SLinus Torvalds break; 1441da177e4SLinus Torvalds } 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvalds input_report_abs(dev, ABS_X, ((elo->data[0] & 0x3f) << 6) | (elo->data[1] & 0x3f)); 1471da177e4SLinus Torvalds input_report_abs(dev, ABS_Y, ((elo->data[2] & 0x3f) << 6) | (elo->data[3] & 0x3f)); 1481da177e4SLinus Torvalds 1491da177e4SLinus Torvalds if (elo->id == 2) { 1501da177e4SLinus Torvalds input_report_key(dev, BTN_TOUCH, 1); 1511da177e4SLinus Torvalds input_sync(dev); 1521da177e4SLinus Torvalds elo->idx = 0; 1531da177e4SLinus Torvalds } 1541da177e4SLinus Torvalds 1551da177e4SLinus Torvalds break; 1561da177e4SLinus Torvalds 1571da177e4SLinus Torvalds case 4: 1581da177e4SLinus Torvalds if (data) { 1591da177e4SLinus Torvalds input_sync(dev); 1601da177e4SLinus Torvalds elo->idx = 0; 1611da177e4SLinus Torvalds } 1621da177e4SLinus Torvalds break; 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds case 5: 1651da177e4SLinus Torvalds if ((data & 0xf0) == 0) { 1661da177e4SLinus Torvalds input_report_abs(dev, ABS_PRESSURE, elo->data[5]); 167eca1ed19SDmitry Torokhov input_report_key(dev, BTN_TOUCH, !!elo->data[5]); 1681da177e4SLinus Torvalds } 1691da177e4SLinus Torvalds input_sync(dev); 1701da177e4SLinus Torvalds elo->idx = 0; 1711da177e4SLinus Torvalds break; 1721da177e4SLinus Torvalds } 1731da177e4SLinus Torvalds } 1741da177e4SLinus Torvalds 1757d12e780SDavid Howells static void elo_process_data_3(struct elo *elo, unsigned char data) 1761da177e4SLinus Torvalds { 177eca1ed19SDmitry Torokhov struct input_dev *dev = elo->dev; 1781da177e4SLinus Torvalds 1791da177e4SLinus Torvalds elo->data[elo->idx] = data; 1801da177e4SLinus Torvalds 1811da177e4SLinus Torvalds switch (elo->idx++) { 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds case 0: 1841da177e4SLinus Torvalds if ((data & 0x7f) != 0x01) 1851da177e4SLinus Torvalds elo->idx = 0; 1861da177e4SLinus Torvalds break; 1871da177e4SLinus Torvalds case 2: 1881da177e4SLinus Torvalds input_report_key(dev, BTN_TOUCH, !(elo->data[1] & 0x80)); 1891da177e4SLinus Torvalds input_report_abs(dev, ABS_X, elo->data[1]); 1901da177e4SLinus Torvalds input_report_abs(dev, ABS_Y, elo->data[2]); 1911da177e4SLinus Torvalds input_sync(dev); 1921da177e4SLinus Torvalds elo->idx = 0; 1931da177e4SLinus Torvalds break; 1941da177e4SLinus Torvalds } 1951da177e4SLinus Torvalds } 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds static irqreturn_t elo_interrupt(struct serio *serio, 1987d12e780SDavid Howells unsigned char data, unsigned int flags) 1991da177e4SLinus Torvalds { 2001da177e4SLinus Torvalds struct elo *elo = serio_get_drvdata(serio); 2011da177e4SLinus Torvalds 2021da177e4SLinus Torvalds switch (elo->id) { 2031da177e4SLinus Torvalds case 0: 2047d12e780SDavid Howells elo_process_data_10(elo, data); 2051da177e4SLinus Torvalds break; 2061da177e4SLinus Torvalds 2071da177e4SLinus Torvalds case 1: 2081da177e4SLinus Torvalds case 2: 2097d12e780SDavid Howells elo_process_data_6(elo, data); 2101da177e4SLinus Torvalds break; 2111da177e4SLinus Torvalds 2121da177e4SLinus Torvalds case 3: 2137d12e780SDavid Howells elo_process_data_3(elo, data); 2141da177e4SLinus Torvalds break; 2151da177e4SLinus Torvalds } 2161da177e4SLinus Torvalds 2171da177e4SLinus Torvalds return IRQ_HANDLED; 2181da177e4SLinus Torvalds } 2191da177e4SLinus Torvalds 220fae3006eSShaun Jackman static int elo_command_10(struct elo *elo, unsigned char *packet) 221fae3006eSShaun Jackman { 222fae3006eSShaun Jackman int rc = -1; 223fae3006eSShaun Jackman int i; 224fae3006eSShaun Jackman unsigned char csum = 0xaa + ELO10_LEAD_BYTE; 225fae3006eSShaun Jackman 226fae3006eSShaun Jackman mutex_lock(&elo->cmd_mutex); 227fae3006eSShaun Jackman 228fae3006eSShaun Jackman serio_pause_rx(elo->serio); 229fae3006eSShaun Jackman elo->expected_packet = toupper(packet[0]); 230fae3006eSShaun Jackman init_completion(&elo->cmd_done); 231fae3006eSShaun Jackman serio_continue_rx(elo->serio); 232fae3006eSShaun Jackman 233fae3006eSShaun Jackman if (serio_write(elo->serio, ELO10_LEAD_BYTE)) 234fae3006eSShaun Jackman goto out; 235fae3006eSShaun Jackman 236fae3006eSShaun Jackman for (i = 0; i < ELO10_PACKET_LEN; i++) { 237fae3006eSShaun Jackman csum += packet[i]; 238fae3006eSShaun Jackman if (serio_write(elo->serio, packet[i])) 239fae3006eSShaun Jackman goto out; 240fae3006eSShaun Jackman } 241fae3006eSShaun Jackman 242fae3006eSShaun Jackman if (serio_write(elo->serio, csum)) 243fae3006eSShaun Jackman goto out; 244fae3006eSShaun Jackman 245fae3006eSShaun Jackman wait_for_completion_timeout(&elo->cmd_done, HZ); 246fae3006eSShaun Jackman 247fae3006eSShaun Jackman if (elo->expected_packet == ELO10_TOUCH_PACKET) { 248fae3006eSShaun Jackman /* We are back in reporting mode, the command was ACKed */ 249fae3006eSShaun Jackman memcpy(packet, elo->response, ELO10_PACKET_LEN); 250fae3006eSShaun Jackman rc = 0; 251fae3006eSShaun Jackman } 252fae3006eSShaun Jackman 253fae3006eSShaun Jackman out: 254fae3006eSShaun Jackman mutex_unlock(&elo->cmd_mutex); 255fae3006eSShaun Jackman return rc; 256fae3006eSShaun Jackman } 257fae3006eSShaun Jackman 258fae3006eSShaun Jackman static int elo_setup_10(struct elo *elo) 259fae3006eSShaun Jackman { 260fae3006eSShaun Jackman static const char *elo_types[] = { "Accu", "Dura", "Intelli", "Carroll" }; 261fae3006eSShaun Jackman struct input_dev *dev = elo->dev; 262fae3006eSShaun Jackman unsigned char packet[ELO10_PACKET_LEN] = { ELO10_ID_CMD }; 263fae3006eSShaun Jackman 264fae3006eSShaun Jackman if (elo_command_10(elo, packet)) 265fae3006eSShaun Jackman return -1; 266fae3006eSShaun Jackman 267fae3006eSShaun Jackman dev->id.version = (packet[5] << 8) | packet[4]; 268fae3006eSShaun Jackman 269fae3006eSShaun Jackman input_set_abs_params(dev, ABS_X, 96, 4000, 0, 0); 270fae3006eSShaun Jackman input_set_abs_params(dev, ABS_Y, 96, 4000, 0, 0); 271fae3006eSShaun Jackman if (packet[3] & ELO10_PRESSURE) 272fae3006eSShaun Jackman input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); 273fae3006eSShaun Jackman 2748cab9ba1SDmitry Torokhov dev_info(&elo->serio->dev, 2758cab9ba1SDmitry Torokhov "%sTouch touchscreen, fw: %02x.%02x, features: 0x%02x, controller: 0x%02x\n", 276fae3006eSShaun Jackman elo_types[(packet[1] -'0') & 0x03], 277fae3006eSShaun Jackman packet[5], packet[4], packet[3], packet[7]); 278fae3006eSShaun Jackman 279fae3006eSShaun Jackman return 0; 280fae3006eSShaun Jackman } 281fae3006eSShaun Jackman 2821da177e4SLinus Torvalds /* 2831da177e4SLinus Torvalds * elo_disconnect() is the opposite of elo_connect() 2841da177e4SLinus Torvalds */ 2851da177e4SLinus Torvalds 2861da177e4SLinus Torvalds static void elo_disconnect(struct serio *serio) 2871da177e4SLinus Torvalds { 2881da177e4SLinus Torvalds struct elo *elo = serio_get_drvdata(serio); 2891da177e4SLinus Torvalds 2906b50d8b8SDmitry Torokhov input_get_device(elo->dev); 291eca1ed19SDmitry Torokhov input_unregister_device(elo->dev); 2921da177e4SLinus Torvalds serio_close(serio); 2931da177e4SLinus Torvalds serio_set_drvdata(serio, NULL); 2946b50d8b8SDmitry Torokhov input_put_device(elo->dev); 2951da177e4SLinus Torvalds kfree(elo); 2961da177e4SLinus Torvalds } 2971da177e4SLinus Torvalds 2981da177e4SLinus Torvalds /* 2991da177e4SLinus Torvalds * elo_connect() is the routine that is called when someone adds a 3001da177e4SLinus Torvalds * new serio device that supports Gunze protocol and registers it as 3011da177e4SLinus Torvalds * an input device. 3021da177e4SLinus Torvalds */ 3031da177e4SLinus Torvalds 3041da177e4SLinus Torvalds static int elo_connect(struct serio *serio, struct serio_driver *drv) 3051da177e4SLinus Torvalds { 3061da177e4SLinus Torvalds struct elo *elo; 307eca1ed19SDmitry Torokhov struct input_dev *input_dev; 3081da177e4SLinus Torvalds int err; 3091da177e4SLinus Torvalds 310eca1ed19SDmitry Torokhov elo = kzalloc(sizeof(struct elo), GFP_KERNEL); 311eca1ed19SDmitry Torokhov input_dev = input_allocate_device(); 312eca1ed19SDmitry Torokhov if (!elo || !input_dev) { 313eca1ed19SDmitry Torokhov err = -ENOMEM; 3146b50d8b8SDmitry Torokhov goto fail1; 315eca1ed19SDmitry Torokhov } 3161da177e4SLinus Torvalds 317eca1ed19SDmitry Torokhov elo->serio = serio; 3181da177e4SLinus Torvalds elo->id = serio->id.id; 319eca1ed19SDmitry Torokhov elo->dev = input_dev; 320fae3006eSShaun Jackman elo->expected_packet = ELO10_TOUCH_PACKET; 321fae3006eSShaun Jackman mutex_init(&elo->cmd_mutex); 322fae3006eSShaun Jackman init_completion(&elo->cmd_done); 323eca1ed19SDmitry Torokhov snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys); 324eca1ed19SDmitry Torokhov 325eca1ed19SDmitry Torokhov input_dev->name = "Elo Serial TouchScreen"; 326eca1ed19SDmitry Torokhov input_dev->phys = elo->phys; 327eca1ed19SDmitry Torokhov input_dev->id.bustype = BUS_RS232; 328eca1ed19SDmitry Torokhov input_dev->id.vendor = SERIO_ELO; 329eca1ed19SDmitry Torokhov input_dev->id.product = elo->id; 330eca1ed19SDmitry Torokhov input_dev->id.version = 0x0100; 331a5394fb0SDmitry Torokhov input_dev->dev.parent = &serio->dev; 332eca1ed19SDmitry Torokhov 3337b19ada2SJiri Slaby input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 3347b19ada2SJiri Slaby input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 3351da177e4SLinus Torvalds 336fae3006eSShaun Jackman serio_set_drvdata(serio, elo); 337fae3006eSShaun Jackman err = serio_open(serio, drv); 338fae3006eSShaun Jackman if (err) 339fae3006eSShaun Jackman goto fail2; 340fae3006eSShaun Jackman 3411da177e4SLinus Torvalds switch (elo->id) { 3421da177e4SLinus Torvalds 3431da177e4SLinus Torvalds case 0: /* 10-byte protocol */ 344*0958351eSDan Carpenter if (elo_setup_10(elo)) { 345*0958351eSDan Carpenter err = -EIO; 346fae3006eSShaun Jackman goto fail3; 347*0958351eSDan Carpenter } 348fae3006eSShaun Jackman 3491da177e4SLinus Torvalds break; 3501da177e4SLinus Torvalds 3511da177e4SLinus Torvalds case 1: /* 6-byte protocol */ 352eca1ed19SDmitry Torokhov input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0); 3536f49c4f5SGustavo A. R. Silva fallthrough; 3541da177e4SLinus Torvalds 3551da177e4SLinus Torvalds case 2: /* 4-byte protocol */ 356eca1ed19SDmitry Torokhov input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0); 357eca1ed19SDmitry Torokhov input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0); 3581da177e4SLinus Torvalds break; 3591da177e4SLinus Torvalds 3601da177e4SLinus Torvalds case 3: /* 3-byte protocol */ 361eca1ed19SDmitry Torokhov input_set_abs_params(input_dev, ABS_X, 0, 255, 0, 0); 362eca1ed19SDmitry Torokhov input_set_abs_params(input_dev, ABS_Y, 0, 255, 0, 0); 3631da177e4SLinus Torvalds break; 3641da177e4SLinus Torvalds } 3651da177e4SLinus Torvalds 3666b50d8b8SDmitry Torokhov err = input_register_device(elo->dev); 3676b50d8b8SDmitry Torokhov if (err) 3686b50d8b8SDmitry Torokhov goto fail3; 3696b50d8b8SDmitry Torokhov 370eca1ed19SDmitry Torokhov return 0; 371eca1ed19SDmitry Torokhov 3726b50d8b8SDmitry Torokhov fail3: serio_close(serio); 3736b50d8b8SDmitry Torokhov fail2: serio_set_drvdata(serio, NULL); 3746b50d8b8SDmitry Torokhov fail1: input_free_device(input_dev); 3751da177e4SLinus Torvalds kfree(elo); 3761da177e4SLinus Torvalds return err; 3771da177e4SLinus Torvalds } 3781da177e4SLinus Torvalds 3791da177e4SLinus Torvalds /* 3801da177e4SLinus Torvalds * The serio driver structure. 3811da177e4SLinus Torvalds */ 3821da177e4SLinus Torvalds 3834f8d5241SArvind Yadav static const struct serio_device_id elo_serio_ids[] = { 3841da177e4SLinus Torvalds { 3851da177e4SLinus Torvalds .type = SERIO_RS232, 3861da177e4SLinus Torvalds .proto = SERIO_ELO, 3871da177e4SLinus Torvalds .id = SERIO_ANY, 3881da177e4SLinus Torvalds .extra = SERIO_ANY, 3891da177e4SLinus Torvalds }, 3901da177e4SLinus Torvalds { 0 } 3911da177e4SLinus Torvalds }; 3921da177e4SLinus Torvalds 3931da177e4SLinus Torvalds MODULE_DEVICE_TABLE(serio, elo_serio_ids); 3941da177e4SLinus Torvalds 3951da177e4SLinus Torvalds static struct serio_driver elo_drv = { 3961da177e4SLinus Torvalds .driver = { 3971da177e4SLinus Torvalds .name = "elo", 3981da177e4SLinus Torvalds }, 3991da177e4SLinus Torvalds .description = DRIVER_DESC, 4001da177e4SLinus Torvalds .id_table = elo_serio_ids, 4011da177e4SLinus Torvalds .interrupt = elo_interrupt, 4021da177e4SLinus Torvalds .connect = elo_connect, 4031da177e4SLinus Torvalds .disconnect = elo_disconnect, 4041da177e4SLinus Torvalds }; 4051da177e4SLinus Torvalds 40665ac9f7aSAxel Lin module_serio_driver(elo_drv); 407