2 * TSC-40 serial touchscreen driver. It should be compatible with
5 * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
6 * License: GPLv2 as published by the FSF.
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/slab.h>
12 #include <linux/input.h>
13 #include <linux/serio.h>
14 #include <linux/init.h>
16 #define PACKET_LENGTH 5
18 struct input_dev
*dev
;
21 unsigned char data
[PACKET_LENGTH
];
25 static void tsc_process_data(struct tsc_ser
*ptsc
)
27 struct input_dev
*dev
= ptsc
->dev
;
28 u8
*data
= ptsc
->data
;
32 x
= ((data
[1] & 0x03) << 8) | data
[2];
33 y
= ((data
[3] & 0x03) << 8) | data
[4];
35 input_report_abs(dev
, ABS_X
, x
);
36 input_report_abs(dev
, ABS_Y
, y
);
37 input_report_key(dev
, BTN_TOUCH
, 1);
42 static irqreturn_t
tsc_interrupt(struct serio
*serio
,
43 unsigned char data
, unsigned int flags
)
45 struct tsc_ser
*ptsc
= serio_get_drvdata(serio
);
46 struct input_dev
*dev
= ptsc
->dev
;
48 ptsc
->data
[ptsc
->idx
] = data
;
49 switch (ptsc
->idx
++) {
51 if (unlikely((data
& 0x3e) != 0x10)) {
53 "unsynchronized packet start (0x%02x)\n", data
);
55 } else if (!(data
& 0x01)) {
56 input_report_key(dev
, BTN_TOUCH
, 0);
64 if (unlikely(data
& 0xfc)) {
66 "unsynchronized data 0x%02x at offset %d\n",
73 tsc_process_data(ptsc
);
81 static int tsc_connect(struct serio
*serio
, struct serio_driver
*drv
)
84 struct input_dev
*input_dev
;
87 ptsc
= kzalloc(sizeof(struct tsc_ser
), GFP_KERNEL
);
88 input_dev
= input_allocate_device();
89 if (!ptsc
|| !input_dev
) {
95 ptsc
->dev
= input_dev
;
96 snprintf(ptsc
->phys
, sizeof(ptsc
->phys
), "%s/input0", serio
->phys
);
98 input_dev
->name
= "TSC-10/25/40 Serial TouchScreen";
99 input_dev
->phys
= ptsc
->phys
;
100 input_dev
->id
.bustype
= BUS_RS232
;
101 input_dev
->id
.vendor
= SERIO_TSC40
;
102 input_dev
->id
.product
= 40;
103 input_dev
->id
.version
= 0x0001;
104 input_dev
->dev
.parent
= &serio
->dev
;
106 input_dev
->evbit
[0] = BIT_MASK(EV_KEY
) | BIT_MASK(EV_ABS
);
107 __set_bit(BTN_TOUCH
, input_dev
->keybit
);
108 input_set_abs_params(ptsc
->dev
, ABS_X
, 0, 0x3ff, 0, 0);
109 input_set_abs_params(ptsc
->dev
, ABS_Y
, 0, 0x3ff, 0, 0);
110 input_set_abs_params(ptsc
->dev
, ABS_PRESSURE
, 0, 0, 0, 0);
112 serio_set_drvdata(serio
, ptsc
);
114 error
= serio_open(serio
, drv
);
118 error
= input_register_device(ptsc
->dev
);
127 serio_set_drvdata(serio
, NULL
);
129 input_free_device(input_dev
);
134 static void tsc_disconnect(struct serio
*serio
)
136 struct tsc_ser
*ptsc
= serio_get_drvdata(serio
);
140 input_unregister_device(ptsc
->dev
);
143 serio_set_drvdata(serio
, NULL
);
146 static struct serio_device_id tsc_serio_ids
[] = {
149 .proto
= SERIO_TSC40
,
155 MODULE_DEVICE_TABLE(serio
, tsc_serio_ids
);
157 #define DRIVER_DESC "TSC-10/25/40 serial touchscreen driver"
159 static struct serio_driver tsc_drv
= {
163 .description
= DRIVER_DESC
,
164 .id_table
= tsc_serio_ids
,
165 .interrupt
= tsc_interrupt
,
166 .connect
= tsc_connect
,
167 .disconnect
= tsc_disconnect
,
170 static int __init
tsc_ser_init(void)
172 return serio_register_driver(&tsc_drv
);
174 module_init(tsc_ser_init
);
176 static void __exit
tsc_exit(void)
178 serio_unregister_driver(&tsc_drv
);
180 module_exit(tsc_exit
);
182 MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
183 MODULE_DESCRIPTION(DRIVER_DESC
);
184 MODULE_LICENSE("GPL v2");