]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/input/touchscreen/wacom_w8001.c
Extra omap code in linux-omap tree
[linux-2.6-omap-h63xx.git] / drivers / input / touchscreen / wacom_w8001.c
1 /*
2  * Wacom W8001 penabled serial touchscreen driver
3  *
4  * Copyright (c) 2008 Jaya Kumar
5  *
6  * This file is subject to the terms and conditions of the GNU General Public
7  * License. See the file COPYING in the main directory of this archive for
8  * more details.
9  *
10  * Layout based on Elo serial touchscreen driver by Vojtech Pavlik
11  */
12
13 #include <linux/errno.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/slab.h>
17 #include <linux/input.h>
18 #include <linux/serio.h>
19 #include <linux/init.h>
20 #include <linux/ctype.h>
21
22 #define DRIVER_DESC     "Wacom W8001 serial touchscreen driver"
23
24 MODULE_AUTHOR("Jaya Kumar <jayakumar.lkml@gmail.com>");
25 MODULE_DESCRIPTION(DRIVER_DESC);
26 MODULE_LICENSE("GPL");
27
28 /*
29  * Definitions & global arrays.
30  */
31
32 #define W8001_MAX_LENGTH        11
33 #define W8001_PACKET_LEN        11
34 #define W8001_LEAD_MASK 0x80
35 #define W8001_LEAD_BYTE 0x80
36 #define W8001_TAB_MASK 0x40
37 #define W8001_TAB_BYTE 0x40
38
39 #define W8001_QUERY_PACKET 0x20
40
41 struct w8001_coord {
42         u8 rdy;
43         u8 tsw;
44         u8 f1;
45         u8 f2;
46         u16 x;
47         u16 y;
48         u16 pen_pressure;
49         u8 tilt_x;
50         u8 tilt_y;
51 };
52
53 /*
54  * Per-touchscreen data.
55  */
56
57 struct w8001 {
58         struct input_dev *dev;
59         struct serio *serio;
60         struct mutex cmd_mutex;
61         struct completion cmd_done;
62         int id;
63         int idx;
64         unsigned char expected_packet;
65         unsigned char data[W8001_MAX_LENGTH];
66         unsigned char response[W8001_PACKET_LEN];
67         char phys[32];
68 };
69
70 static int parse_data(u8 *data, struct w8001_coord *coord)
71 {
72         coord->rdy = data[0] & 0x20;
73         coord->tsw = data[0] & 0x01;
74         coord->f1 = data[0] & 0x02;
75         coord->f2 = data[0] & 0x04;
76
77         coord->x = (data[1] & 0x7F) << 9;
78         coord->x |= (data[2] & 0x7F) << 2;
79         coord->x |= (data[6] & 0x60) >> 5;
80
81         coord->y = (data[3] & 0x7F) << 9;
82         coord->y |= (data[4] & 0x7F) << 2;
83         coord->y |= (data[6] & 0x18) >> 3;
84
85         coord->pen_pressure = data[5] & 0x7F;
86         coord->pen_pressure |= (data[6] & 0x07) << 7 ;
87
88         coord->tilt_x = data[7] & 0x7F;
89         coord->tilt_y = data[8] & 0x7F;
90
91         return 0;
92 }
93
94 static void w8001_process_data(struct w8001 *w8001, unsigned char data)
95 {
96         struct input_dev *dev = w8001->dev;
97         u8 tmp;
98         struct w8001_coord coord;
99
100         w8001->data[w8001->idx] = data;
101         switch (w8001->idx++) {
102         case 0:
103                 if ((data & W8001_LEAD_MASK) != W8001_LEAD_BYTE) {
104                         pr_debug("w8001: unsynchronized data: 0x%02x\n", data);
105                         w8001->idx = 0;
106                 }
107                 break;
108         case 8:
109                 tmp = w8001->data[0] & W8001_TAB_MASK;
110                 if (unlikely(tmp == W8001_TAB_BYTE))
111                         break;
112                 w8001->idx = 0;
113                 memset(&coord, 0, sizeof(coord));
114                 parse_data(w8001->data, &coord);
115                 input_report_abs(dev, ABS_X, coord.x);
116                 input_report_abs(dev, ABS_Y, coord.y);
117                 input_report_abs(dev, ABS_PRESSURE, coord.pen_pressure);
118                 input_report_key(dev, BTN_TOUCH, coord.tsw);
119                 input_sync(dev);
120                 break;
121         case 10:
122                 w8001->idx = 0;
123                 memcpy(w8001->response, &w8001->data, W8001_PACKET_LEN);
124                 w8001->expected_packet = W8001_QUERY_PACKET;
125                 complete(&w8001->cmd_done);
126                 break;
127         }
128 }
129
130
131 static irqreturn_t w8001_interrupt(struct serio *serio,
132                 unsigned char data, unsigned int flags)
133 {
134         struct w8001 *w8001 = serio_get_drvdata(serio);
135
136         w8001_process_data(w8001, data);
137
138         return IRQ_HANDLED;
139 }
140
141 static int w8001_async_command(struct w8001 *w8001, unsigned char *packet,
142                                         int len)
143 {
144         int rc = -1;
145         int i;
146
147         mutex_lock(&w8001->cmd_mutex);
148
149         for (i = 0; i < len; i++) {
150                 if (serio_write(w8001->serio, packet[i]))
151                         goto out;
152         }
153         rc = 0;
154
155 out:
156         mutex_unlock(&w8001->cmd_mutex);
157         return rc;
158 }
159
160 static int w8001_command(struct w8001 *w8001, unsigned char *packet, int len)
161 {
162         int rc = -1;
163         int i;
164
165         mutex_lock(&w8001->cmd_mutex);
166
167         serio_pause_rx(w8001->serio);
168         init_completion(&w8001->cmd_done);
169         serio_continue_rx(w8001->serio);
170
171         for (i = 0; i < len; i++) {
172                 if (serio_write(w8001->serio, packet[i]))
173                         goto out;
174         }
175
176         wait_for_completion_timeout(&w8001->cmd_done, HZ);
177
178         if (w8001->expected_packet == W8001_QUERY_PACKET) {
179                 /* We are back in reporting mode, the query was ACKed */
180                 memcpy(packet, w8001->response, W8001_PACKET_LEN);
181                 rc = 0;
182         }
183
184 out:
185         mutex_unlock(&w8001->cmd_mutex);
186         return rc;
187 }
188
189 static int w8001_setup(struct w8001 *w8001)
190 {
191         struct w8001_coord coord;
192         struct input_dev *dev = w8001->dev;
193         unsigned char start[1] = { '1' };
194         unsigned char query[11] = { '*' };
195
196         if (w8001_command(w8001, query, 1))
197                 return -1;
198
199         memset(&coord, 0, sizeof(coord));
200         parse_data(query, &coord);
201
202         input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0);
203         input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0);
204         input_set_abs_params(dev, ABS_PRESSURE, 0, coord.pen_pressure, 0, 0);
205         input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0);
206         input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0);
207
208         if (w8001_async_command(w8001, start, 1))
209                 return -1;
210
211         return 0;
212 }
213
214 /*
215  * w8001_disconnect() is the opposite of w8001_connect()
216  */
217
218 static void w8001_disconnect(struct serio *serio)
219 {
220         struct w8001 *w8001 = serio_get_drvdata(serio);
221
222         input_get_device(w8001->dev);
223         input_unregister_device(w8001->dev);
224         serio_close(serio);
225         serio_set_drvdata(serio, NULL);
226         input_put_device(w8001->dev);
227         kfree(w8001);
228 }
229
230 /*
231  * w8001_connect() is the routine that is called when someone adds a
232  * new serio device that supports the w8001 protocol and registers it as
233  * an input device.
234  */
235
236 static int w8001_connect(struct serio *serio, struct serio_driver *drv)
237 {
238         struct w8001 *w8001;
239         struct input_dev *input_dev;
240         int err;
241
242         w8001 = kzalloc(sizeof(struct w8001), GFP_KERNEL);
243         input_dev = input_allocate_device();
244         if (!w8001 || !input_dev) {
245                 err = -ENOMEM;
246                 goto fail1;
247         }
248
249         w8001->serio = serio;
250         w8001->id = serio->id.id;
251         w8001->dev = input_dev;
252         mutex_init(&w8001->cmd_mutex);
253         init_completion(&w8001->cmd_done);
254         snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys);
255
256         input_dev->name = "Wacom W8001 Penabled Serial TouchScreen";
257         input_dev->phys = w8001->phys;
258         input_dev->id.bustype = BUS_RS232;
259         input_dev->id.vendor = SERIO_W8001;
260         input_dev->id.product = w8001->id;
261         input_dev->id.version = 0x0100;
262         input_dev->dev.parent = &serio->dev;
263
264         input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
265         input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
266
267         serio_set_drvdata(serio, w8001);
268         err = serio_open(serio, drv);
269         if (err)
270                 goto fail2;
271
272         if (w8001_setup(w8001))
273                 goto fail3;
274
275         err = input_register_device(w8001->dev);
276         if (err)
277                 goto fail3;
278
279         return 0;
280
281 fail3:
282         serio_close(serio);
283 fail2:
284         serio_set_drvdata(serio, NULL);
285 fail1:
286         input_free_device(input_dev);
287         kfree(w8001);
288         return err;
289 }
290
291 static struct serio_device_id w8001_serio_ids[] = {
292         {
293                 .type   = SERIO_RS232,
294                 .proto  = SERIO_W8001,
295                 .id     = SERIO_ANY,
296                 .extra  = SERIO_ANY,
297         },
298         { 0 }
299 };
300
301 MODULE_DEVICE_TABLE(serio, w8001_serio_ids);
302
303 static struct serio_driver w8001_drv = {
304         .driver         = {
305                 .name   = "w8001",
306         },
307         .description    = DRIVER_DESC,
308         .id_table       = w8001_serio_ids,
309         .interrupt      = w8001_interrupt,
310         .connect        = w8001_connect,
311         .disconnect     = w8001_disconnect,
312 };
313
314 static int __init w8001_init(void)
315 {
316         return serio_register_driver(&w8001_drv);
317 }
318
319 static void __exit w8001_exit(void)
320 {
321         serio_unregister_driver(&w8001_drv);
322 }
323
324 module_init(w8001_init);
325 module_exit(w8001_exit);