aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/touchscreen/elo.c124
1 files changed, 107 insertions, 17 deletions
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
index fe6e1a428674..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
@@ -36,9 +37,17 @@ MODULE_LICENSE("GPL");
36 37
37#define ELO_MAX_LENGTH 10 38#define ELO_MAX_LENGTH 10
38 39
40#define ELO10_PACKET_LEN 8
41#define ELO10_TOUCH 0x03
42#define ELO10_PRESSURE 0x80
43
39#define ELO10_LEAD_BYTE 'U' 44#define ELO10_LEAD_BYTE 'U'
40 45
46#define ELO10_ID_CMD 'i'
47
41#define ELO10_TOUCH_PACKET 'T' 48#define ELO10_TOUCH_PACKET 'T'
49#define ELO10_ACK_PACKET 'A'
50#define ELI10_ID_PACKET 'I'
42 51
43/* 52/*
44 * Per-touchscreen data. 53 * Per-touchscreen data.
@@ -47,10 +56,14 @@ MODULE_LICENSE("GPL");
47struct elo { 56struct elo {
48 struct input_dev *dev; 57 struct input_dev *dev;
49 struct serio *serio; 58 struct serio *serio;
59 struct mutex cmd_mutex;
60 struct completion cmd_done;
50 int id; 61 int id;
51 int idx; 62 int idx;
63 unsigned char expected_packet;
52 unsigned char csum; 64 unsigned char csum;
53 unsigned char data[ELO_MAX_LENGTH]; 65 unsigned char data[ELO_MAX_LENGTH];
66 unsigned char response[ELO10_PACKET_LEN];
54 char phys[32]; 67 char phys[32];
55}; 68};
56 69
@@ -75,16 +88,29 @@ static void elo_process_data_10(struct elo *elo, unsigned char data, struct pt_r
75 data, elo->csum); 88 data, elo->csum);
76 break; 89 break;
77 } 90 }
78 if (elo->data[1] != ELO10_TOUCH_PACKET) { 91 if (elo->data[1] != elo->expected_packet) {
79 pr_debug(elo: "unexpected packet: 0x%02x\n", elo->data[1]); 92 if (elo->data[1] != ELO10_TOUCH_PACKET)
93 pr_debug("elo: unexpected packet: 0x%02x\n",
94 elo->data[1]);
80 break; 95 break;
81 } 96 }
82 input_regs(dev, regs); 97 if (likely(elo->data[1] == ELO10_TOUCH_PACKET)) {
83 input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]); 98 input_regs(dev, regs);
84 input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]); 99 input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]);
85 input_report_abs(dev, ABS_PRESSURE, (elo->data[8] << 8) | elo->data[7]); 100 input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]);
86 input_report_key(dev, BTN_TOUCH, elo->data[8] || elo->data[7]); 101 if (elo->data[2] & ELO10_PRESSURE)
87 input_sync(dev); 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 }
88 break; 114 break;
89 } 115 }
90 elo->csum += data; 116 elo->csum += data;
@@ -184,6 +210,68 @@ static irqreturn_t elo_interrupt(struct serio *serio,
184 return IRQ_HANDLED; 210 return IRQ_HANDLED;
185} 211}
186 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
187/* 275/*
188 * elo_disconnect() is the opposite of elo_connect() 276 * elo_disconnect() is the opposite of elo_connect()
189 */ 277 */
@@ -222,6 +310,9 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
222 elo->serio = serio; 310 elo->serio = serio;
223 elo->id = serio->id.id; 311 elo->id = serio->id.id;
224 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);
225 snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys); 316 snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys);
226 317
227 input_dev->private = elo; 318 input_dev->private = elo;
@@ -236,12 +327,17 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
236 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); 327 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
237 input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); 328 input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
238 329
330 serio_set_drvdata(serio, elo);
331 err = serio_open(serio, drv);
332 if (err)
333 goto fail2;
334
239 switch (elo->id) { 335 switch (elo->id) {
240 336
241 case 0: /* 10-byte protocol */ 337 case 0: /* 10-byte protocol */
242 input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0); 338 if (elo_setup_10(elo))
243 input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0); 339 goto fail3;
244 input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0); 340
245 break; 341 break;
246 342
247 case 1: /* 6-byte protocol */ 343 case 1: /* 6-byte protocol */
@@ -258,12 +354,6 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
258 break; 354 break;
259 } 355 }
260 356
261 serio_set_drvdata(serio, elo);
262
263 err = serio_open(serio, drv);
264 if (err)
265 goto fail2;
266
267 err = input_register_device(elo->dev); 357 err = input_register_device(elo->dev);
268 if (err) 358 if (err)
269 goto fail3; 359 goto fail3;