aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/elo.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/elo.c')
-rw-r--r--drivers/input/touchscreen/elo.c167
1 files changed, 133 insertions, 34 deletions
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
index c86a2eb310fd..ab565335ee44 100644
--- a/drivers/input/touchscreen/elo.c
+++ b/drivers/input/touchscreen/elo.c
@@ -23,6 +23,7 @@
23#include <linux/input.h> 23#include <linux/input.h>
24#include <linux/serio.h> 24#include <linux/serio.h>
25#include <linux/init.h> 25#include <linux/init.h>
26#include <linux/ctype.h>
26 27
27#define DRIVER_DESC "Elo serial touchscreen driver" 28#define DRIVER_DESC "Elo serial touchscreen driver"
28 29
@@ -34,7 +35,19 @@ MODULE_LICENSE("GPL");
34 * Definitions & global arrays. 35 * Definitions & global arrays.
35 */ 36 */
36 37
37#define ELO_MAX_LENGTH 10 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'
38 51
39/* 52/*
40 * Per-touchscreen data. 53 * Per-touchscreen data.
@@ -43,51 +56,67 @@ MODULE_LICENSE("GPL");
43struct elo { 56struct elo {
44 struct input_dev *dev; 57 struct input_dev *dev;
45 struct serio *serio; 58 struct serio *serio;
59 struct mutex cmd_mutex;
60 struct completion cmd_done;
46 int id; 61 int id;
47 int idx; 62 int idx;
63 unsigned char expected_packet;
48 unsigned char csum; 64 unsigned char csum;
49 unsigned char data[ELO_MAX_LENGTH]; 65 unsigned char data[ELO_MAX_LENGTH];
66 unsigned char response[ELO10_PACKET_LEN];
50 char phys[32]; 67 char phys[32];
51}; 68};
52 69
53static void elo_process_data_10(struct elo* elo, unsigned char data, struct pt_regs *regs) 70static void elo_process_data_10(struct elo *elo, unsigned char data, struct pt_regs *regs)
54{ 71{
55 struct input_dev *dev = elo->dev; 72 struct input_dev *dev = elo->dev;
56 73
57 elo->csum += elo->data[elo->idx] = data; 74 elo->data[elo->idx] = data;
58
59 switch (elo->idx++) { 75 switch (elo->idx++) {
60
61 case 0: 76 case 0:
62 if (data != 'U') { 77 elo->csum = 0xaa;
78 if (data != ELO10_LEAD_BYTE) {
79 pr_debug("elo: unsynchronized data: 0x%02x\n", data);
63 elo->idx = 0; 80 elo->idx = 0;
64 elo->csum = 0;
65 }
66 break;
67
68 case 1:
69 if (data != 'T') {
70 elo->idx = 0;
71 elo->csum = 0;
72 } 81 }
73 break; 82 break;
74 83
75 case 9: 84 case 9:
76 if (elo->csum) { 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)) {
77 input_regs(dev, regs); 98 input_regs(dev, regs);
78 input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]); 99 input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]);
79 input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]); 100 input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]);
80 input_report_abs(dev, ABS_PRESSURE, (elo->data[8] << 8) | elo->data[7]); 101 if (elo->data[2] & ELO10_PRESSURE)
81 input_report_key(dev, BTN_TOUCH, elo->data[8] || elo->data[7]); 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);
82 input_sync(dev); 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;
83 } 113 }
84 elo->idx = 0;
85 elo->csum = 0;
86 break; 114 break;
87 } 115 }
116 elo->csum += data;
88} 117}
89 118
90static void elo_process_data_6(struct elo* elo, unsigned char data, struct pt_regs *regs) 119static void elo_process_data_6(struct elo *elo, unsigned char data, struct pt_regs *regs)
91{ 120{
92 struct input_dev *dev = elo->dev; 121 struct input_dev *dev = elo->dev;
93 122
@@ -135,7 +164,7 @@ static void elo_process_data_6(struct elo* elo, unsigned char data, struct pt_re
135 } 164 }
136} 165}
137 166
138static void elo_process_data_3(struct elo* elo, unsigned char data, struct pt_regs *regs) 167static void elo_process_data_3(struct elo *elo, unsigned char data, struct pt_regs *regs)
139{ 168{
140 struct input_dev *dev = elo->dev; 169 struct input_dev *dev = elo->dev;
141 170
@@ -161,7 +190,7 @@ static void elo_process_data_3(struct elo* elo, unsigned char data, struct pt_re
161static irqreturn_t elo_interrupt(struct serio *serio, 190static irqreturn_t elo_interrupt(struct serio *serio,
162 unsigned char data, unsigned int flags, struct pt_regs *regs) 191 unsigned char data, unsigned int flags, struct pt_regs *regs)
163{ 192{
164 struct elo* elo = serio_get_drvdata(serio); 193 struct elo *elo = serio_get_drvdata(serio);
165 194
166 switch(elo->id) { 195 switch(elo->id) {
167 case 0: 196 case 0:
@@ -181,17 +210,81 @@ static irqreturn_t elo_interrupt(struct serio *serio,
181 return IRQ_HANDLED; 210 return IRQ_HANDLED;
182} 211}
183 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
184/* 275/*
185 * elo_disconnect() is the opposite of elo_connect() 276 * elo_disconnect() is the opposite of elo_connect()
186 */ 277 */
187 278
188static void elo_disconnect(struct serio *serio) 279static void elo_disconnect(struct serio *serio)
189{ 280{
190 struct elo* elo = serio_get_drvdata(serio); 281 struct elo *elo = serio_get_drvdata(serio);
191 282
283 input_get_device(elo->dev);
192 input_unregister_device(elo->dev); 284 input_unregister_device(elo->dev);
193 serio_close(serio); 285 serio_close(serio);
194 serio_set_drvdata(serio, NULL); 286 serio_set_drvdata(serio, NULL);
287 input_put_device(elo->dev);
195 kfree(elo); 288 kfree(elo);
196} 289}
197 290
@@ -211,12 +304,15 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
211 input_dev = input_allocate_device(); 304 input_dev = input_allocate_device();
212 if (!elo || !input_dev) { 305 if (!elo || !input_dev) {
213 err = -ENOMEM; 306 err = -ENOMEM;
214 goto fail; 307 goto fail1;
215 } 308 }
216 309
217 elo->serio = serio; 310 elo->serio = serio;
218 elo->id = serio->id.id; 311 elo->id = serio->id.id;
219 elo->dev = input_dev; 312 elo->dev = input_dev;
313 elo->expected_packet = ELO10_TOUCH_PACKET;
314 mutex_init(&elo->cmd_mutex);
315 init_completion(&elo->cmd_done);
220 snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys); 316 snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys);
221 317
222 input_dev->private = elo; 318 input_dev->private = elo;
@@ -231,12 +327,17 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
231 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); 327 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
232 input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); 328 input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
233 329
330 serio_set_drvdata(serio, elo);
331 err = serio_open(serio, drv);
332 if (err)
333 goto fail2;
334
234 switch (elo->id) { 335 switch (elo->id) {
235 336
236 case 0: /* 10-byte protocol */ 337 case 0: /* 10-byte protocol */
237 input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0); 338 if (elo_setup_10(elo))
238 input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0); 339 goto fail3;
239 input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0); 340
240 break; 341 break;
241 342
242 case 1: /* 6-byte protocol */ 343 case 1: /* 6-byte protocol */
@@ -253,17 +354,15 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
253 break; 354 break;
254 } 355 }
255 356
256 serio_set_drvdata(serio, elo); 357 err = input_register_device(elo->dev);
257
258 err = serio_open(serio, drv);
259 if (err) 358 if (err)
260 goto fail; 359 goto fail3;
261 360
262 input_register_device(elo->dev);
263 return 0; 361 return 0;
264 362
265 fail: serio_set_drvdata(serio, NULL); 363 fail3: serio_close(serio);
266 input_free_device(input_dev); 364 fail2: serio_set_drvdata(serio, NULL);
365 fail1: input_free_device(input_dev);
267 kfree(elo); 366 kfree(elo);
268 return err; 367 return err;
269} 368}