aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/input/usbtouchscreen.c
diff options
context:
space:
mode:
authorDaniel Ritz <daniel.ritz-ml@swissonline.ch>2006-07-31 15:43:24 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-09-27 14:58:51 -0400
commit5d8926658ce41b254fdfba7d057e6c9438c25cca (patch)
tree64bddda2a71765f807ae0599905c7bcce083f1fb /drivers/usb/input/usbtouchscreen.c
parentd388dab7b562b76525761f89702246686747ba30 (diff)
usbtouchscreen: version 0.4
changes over 0.3: - some more eGalax device IDs (from eGalax driver/spec) - return the error code in probe() - 3M/MTouch init fixes, tested by Don Alexander - eGalax fixes for bugs in multi-packet handling, spottet by Pieter Grimmerink - support for some eTurboTouch devices, mostly by Pieter Grimmerink - support for Gunze AHL61 controller (untested, but simple enough) Signed-off-by: Daniel Ritz <daniel.ritz@gmx.ch> Cc: Pieter Grimmerink <p.grimmerink@inepro.com> Cc: Don Alexander <debug@roosoft.ltd.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/input/usbtouchscreen.c')
-rw-r--r--drivers/usb/input/usbtouchscreen.c283
1 files changed, 203 insertions, 80 deletions
diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c
index a338bf4c2d78..a1be7840ea02 100644
--- a/drivers/usb/input/usbtouchscreen.c
+++ b/drivers/usb/input/usbtouchscreen.c
@@ -2,9 +2,12 @@
2 * usbtouchscreen.c 2 * usbtouchscreen.c
3 * Driver for USB Touchscreens, supporting those devices: 3 * Driver for USB Touchscreens, supporting those devices:
4 * - eGalax Touchkit 4 * - eGalax Touchkit
5 * - 3M/Microtouch 5 * includes eTurboTouch CT-410/510/700
6 * - 3M/Microtouch EX II series
6 * - ITM 7 * - ITM
7 * - PanJit TouchSet 8 * - PanJit TouchSet
9 * - eTurboTouch
10 * - Gunze AHL61
8 * 11 *
9 * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch> 12 * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
10 * Copyright (C) by Todd E. Johnson (mtouchusb.c) 13 * Copyright (C) by Todd E. Johnson (mtouchusb.c)
@@ -42,7 +45,7 @@
42#include <linux/usb/input.h> 45#include <linux/usb/input.h>
43 46
44 47
45#define DRIVER_VERSION "v0.3" 48#define DRIVER_VERSION "v0.4"
46#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" 49#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>"
47#define DRIVER_DESC "USB Touchscreen Driver" 50#define DRIVER_DESC "USB Touchscreen Driver"
48 51
@@ -60,6 +63,7 @@ struct usbtouch_device_info {
60 int flags; 63 int flags;
61 64
62 void (*process_pkt) (struct usbtouch_usb *usbtouch, struct pt_regs *regs, unsigned char *pkt, int len); 65 void (*process_pkt) (struct usbtouch_usb *usbtouch, struct pt_regs *regs, unsigned char *pkt, int len);
66 int (*get_pkt_len) (unsigned char *pkt, int len);
63 int (*read_data) (unsigned char *pkt, int *x, int *y, int *touch, int *press); 67 int (*read_data) (unsigned char *pkt, int *x, int *y, int *touch, int *press);
64 int (*init) (struct usbtouch_usb *usbtouch); 68 int (*init) (struct usbtouch_usb *usbtouch);
65}; 69};
@@ -81,8 +85,16 @@ struct usbtouch_usb {
81 char phys[64]; 85 char phys[64];
82}; 86};
83 87
84static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, 88
85 struct pt_regs *regs, unsigned char *pkt, int len); 89#if defined(CONFIG_USB_TOUCHSCREEN_EGALAX) || defined(CONFIG_USB_TOUCHSCREEN_ETURBO)
90#define MULTI_PACKET
91#endif
92
93#ifdef MULTI_PACKET
94static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
95 struct pt_regs *regs,
96 unsigned char *pkt, int len);
97#endif
86 98
87/* device types */ 99/* device types */
88enum { 100enum {
@@ -91,14 +103,19 @@ enum {
91 DEVTYPE_PANJIT, 103 DEVTYPE_PANJIT,
92 DEVTYPE_3M, 104 DEVTYPE_3M,
93 DEVTYPE_ITM, 105 DEVTYPE_ITM,
106 DEVTYPE_ETURBO,
107 DEVTYPE_GUNZE,
94}; 108};
95 109
96static struct usb_device_id usbtouch_devices[] = { 110static struct usb_device_id usbtouch_devices[] = {
97#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX 111#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
98 {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX}, 112 {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX},
113 {USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX},
99 {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX}, 114 {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX},
100 {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX}, 115 {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX},
101 {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX}, 116 {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX},
117 {USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX},
118 {USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX},
102#endif 119#endif
103 120
104#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT 121#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
@@ -116,6 +133,14 @@ static struct usb_device_id usbtouch_devices[] = {
116 {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, 133 {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM},
117#endif 134#endif
118 135
136#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
137 {USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO},
138#endif
139
140#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
141 {USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE},
142#endif
143
119 {} 144 {}
120}; 145};
121 146
@@ -140,82 +165,23 @@ static int egalax_read_data(unsigned char *pkt, int *x, int *y, int *touch, int
140 *touch = pkt[0] & 0x01; 165 *touch = pkt[0] & 0x01;
141 166
142 return 1; 167 return 1;
143
144} 168}
145 169
146static int egalax_get_pkt_len(unsigned char *buf) 170static int egalax_get_pkt_len(unsigned char *buf, int len)
147{ 171{
148 switch (buf[0] & EGALAX_PKT_TYPE_MASK) { 172 switch (buf[0] & EGALAX_PKT_TYPE_MASK) {
149 case EGALAX_PKT_TYPE_REPT: 173 case EGALAX_PKT_TYPE_REPT:
150 return 5; 174 return 5;
151 175
152 case EGALAX_PKT_TYPE_DIAG: 176 case EGALAX_PKT_TYPE_DIAG:
177 if (len < 2)
178 return -1;
179
153 return buf[1] + 2; 180 return buf[1] + 2;
154 } 181 }
155 182
156 return 0; 183 return 0;
157} 184}
158
159static void egalax_process(struct usbtouch_usb *usbtouch, struct pt_regs *regs,
160 unsigned char *pkt, int len)
161{
162 unsigned char *buffer;
163 int pkt_len, buf_len, pos;
164
165 /* if the buffer contains data, append */
166 if (unlikely(usbtouch->buf_len)) {
167 int tmp;
168
169 /* if only 1 byte in buffer, add another one to get length */
170 if (usbtouch->buf_len == 1)
171 usbtouch->buffer[1] = pkt[0];
172
173 pkt_len = egalax_get_pkt_len(usbtouch->buffer);
174
175 /* unknown packet: drop everything */
176 if (!pkt_len)
177 return;
178
179 /* append, process */
180 tmp = pkt_len - usbtouch->buf_len;
181 memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp);
182 usbtouch_process_pkt(usbtouch, regs, usbtouch->buffer, pkt_len);
183
184 buffer = pkt + tmp;
185 buf_len = len - tmp;
186 } else {
187 buffer = pkt;
188 buf_len = len;
189 }
190
191 /* only one byte left in buffer */
192 if (unlikely(buf_len == 1)) {
193 usbtouch->buffer[0] = buffer[0];
194 usbtouch->buf_len = 1;
195 return;
196 }
197
198 /* loop over the buffer */
199 pos = 0;
200 while (pos < buf_len) {
201 /* get packet len */
202 pkt_len = egalax_get_pkt_len(buffer + pos);
203
204 /* unknown packet: drop everything */
205 if (unlikely(!pkt_len))
206 return;
207
208 /* full packet: process */
209 if (likely(pkt_len <= buf_len)) {
210 usbtouch_process_pkt(usbtouch, regs, buffer + pos, pkt_len);
211 } else {
212 /* incomplete packet: save in buffer */
213 memcpy(usbtouch->buffer, buffer + pos, buf_len - pos);
214 usbtouch->buf_len = buf_len - pos;
215 }
216 pos += pkt_len;
217 }
218}
219#endif 185#endif
220 186
221 187
@@ -254,7 +220,7 @@ static int mtouch_read_data(unsigned char *pkt, int *x, int *y, int *touch, int
254 220
255static int mtouch_init(struct usbtouch_usb *usbtouch) 221static int mtouch_init(struct usbtouch_usb *usbtouch)
256{ 222{
257 int ret; 223 int ret, i;
258 224
259 ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), 225 ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
260 MTOUCHUSB_RESET, 226 MTOUCHUSB_RESET,
@@ -264,15 +230,20 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
264 __FUNCTION__, ret); 230 __FUNCTION__, ret);
265 if (ret < 0) 231 if (ret < 0)
266 return ret; 232 return ret;
267 233 msleep(150);
268 ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), 234
269 MTOUCHUSB_ASYNC_REPORT, 235 for (i = 0; i < 3; i++) {
270 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 236 ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
271 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); 237 MTOUCHUSB_ASYNC_REPORT,
272 dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", 238 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
273 __FUNCTION__, ret); 239 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
274 if (ret < 0) 240 dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
275 return ret; 241 __FUNCTION__, ret);
242 if (ret >= 0)
243 break;
244 if (ret != -EPIPE)
245 return ret;
246 }
276 247
277 return 0; 248 return 0;
278} 249}
@@ -296,6 +267,54 @@ static int itm_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *pr
296 267
297 268
298/***************************************************************************** 269/*****************************************************************************
270 * eTurboTouch part
271 */
272#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
273static int eturbo_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
274{
275 unsigned int shift;
276
277 /* packets should start with sync */
278 if (!(pkt[0] & 0x80))
279 return 0;
280
281 shift = (6 - (pkt[0] & 0x03));
282 *x = ((pkt[3] << 7) | pkt[4]) >> shift;
283 *y = ((pkt[1] << 7) | pkt[2]) >> shift;
284 *touch = (pkt[0] & 0x10) ? 1 : 0;
285
286 return 1;
287}
288
289static int eturbo_get_pkt_len(unsigned char *buf, int len)
290{
291 if (buf[0] & 0x80)
292 return 5;
293 if (buf[0] == 0x01)
294 return 3;
295 return 0;
296}
297#endif
298
299
300/*****************************************************************************
301 * Gunze part
302 */
303#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
304static int gunze_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
305{
306 if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80))
307 return 0;
308
309 *x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F);
310 *y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F);
311 *touch = pkt[0] & 0x20;
312
313 return 1;
314}
315#endif
316
317/*****************************************************************************
299 * the different device descriptors 318 * the different device descriptors
300 */ 319 */
301static struct usbtouch_device_info usbtouch_dev_info[] = { 320static struct usbtouch_device_info usbtouch_dev_info[] = {
@@ -307,7 +326,8 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
307 .max_yc = 0x07ff, 326 .max_yc = 0x07ff,
308 .rept_size = 16, 327 .rept_size = 16,
309 .flags = USBTOUCH_FLG_BUFFER, 328 .flags = USBTOUCH_FLG_BUFFER,
310 .process_pkt = egalax_process, 329 .process_pkt = usbtouch_process_multi,
330 .get_pkt_len = egalax_get_pkt_len,
311 .read_data = egalax_read_data, 331 .read_data = egalax_read_data,
312 }, 332 },
313#endif 333#endif
@@ -346,6 +366,31 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
346 .read_data = itm_read_data, 366 .read_data = itm_read_data,
347 }, 367 },
348#endif 368#endif
369
370#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
371 [DEVTYPE_ETURBO] = {
372 .min_xc = 0x0,
373 .max_xc = 0x07ff,
374 .min_yc = 0x0,
375 .max_yc = 0x07ff,
376 .rept_size = 8,
377 .flags = USBTOUCH_FLG_BUFFER,
378 .process_pkt = usbtouch_process_multi,
379 .get_pkt_len = eturbo_get_pkt_len,
380 .read_data = eturbo_read_data,
381 },
382#endif
383
384#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
385 [DEVTYPE_GUNZE] = {
386 .min_xc = 0x0,
387 .max_xc = 0x0fff,
388 .min_yc = 0x0,
389 .max_yc = 0x0fff,
390 .rept_size = 4,
391 .read_data = gunze_read_data,
392 },
393#endif
349}; 394};
350 395
351 396
@@ -377,6 +422,83 @@ static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
377} 422}
378 423
379 424
425#ifdef MULTI_PACKET
426static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
427 struct pt_regs *regs,
428 unsigned char *pkt, int len)
429{
430 unsigned char *buffer;
431 int pkt_len, pos, buf_len, tmp;
432
433 /* process buffer */
434 if (unlikely(usbtouch->buf_len)) {
435 /* try to get size */
436 pkt_len = usbtouch->type->get_pkt_len(
437 usbtouch->buffer, usbtouch->buf_len);
438
439 /* drop? */
440 if (unlikely(!pkt_len))
441 goto out_flush_buf;
442
443 /* need to append -pkt_len bytes before able to get size */
444 if (unlikely(pkt_len < 0)) {
445 int append = -pkt_len;
446 if (unlikely(append > len))
447 append = len;
448 if (usbtouch->buf_len + append >= usbtouch->type->rept_size)
449 goto out_flush_buf;
450 memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append);
451 usbtouch->buf_len += append;
452
453 pkt_len = usbtouch->type->get_pkt_len(
454 usbtouch->buffer, usbtouch->buf_len);
455 if (pkt_len < 0)
456 return;
457 }
458
459 /* append */
460 tmp = pkt_len - usbtouch->buf_len;
461 if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size)
462 goto out_flush_buf;
463 memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp);
464 usbtouch_process_pkt(usbtouch, regs, usbtouch->buffer, pkt_len);
465
466 buffer = pkt + tmp;
467 buf_len = len - tmp;
468 } else {
469 buffer = pkt;
470 buf_len = len;
471 }
472
473 /* loop over the received packet, process */
474 pos = 0;
475 while (pos < buf_len) {
476 /* get packet len */
477 pkt_len = usbtouch->type->get_pkt_len(buffer + pos, len);
478
479 /* unknown packet: drop everything */
480 if (unlikely(!pkt_len))
481 goto out_flush_buf;
482
483 /* full packet: process */
484 if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) {
485 usbtouch_process_pkt(usbtouch, regs, buffer + pos, pkt_len);
486 } else {
487 /* incomplete packet: save in buffer */
488 memcpy(usbtouch->buffer, buffer + pos, buf_len - pos);
489 usbtouch->buf_len = buf_len - pos;
490 return;
491 }
492 pos += pkt_len;
493 }
494
495out_flush_buf:
496 usbtouch->buf_len = 0;
497 return;
498}
499#endif
500
501
380static void usbtouch_irq(struct urb *urb, struct pt_regs *regs) 502static void usbtouch_irq(struct urb *urb, struct pt_regs *regs)
381{ 503{
382 struct usbtouch_usb *usbtouch = urb->context; 504 struct usbtouch_usb *usbtouch = urb->context;
@@ -452,7 +574,7 @@ static int usbtouch_probe(struct usb_interface *intf,
452 struct usb_endpoint_descriptor *endpoint; 574 struct usb_endpoint_descriptor *endpoint;
453 struct usb_device *udev = interface_to_usbdev(intf); 575 struct usb_device *udev = interface_to_usbdev(intf);
454 struct usbtouch_device_info *type; 576 struct usbtouch_device_info *type;
455 int err; 577 int err = -ENOMEM;
456 578
457 interface = intf->cur_altsetting; 579 interface = intf->cur_altsetting;
458 endpoint = &interface->endpoint[0].desc; 580 endpoint = &interface->endpoint[0].desc;
@@ -526,6 +648,7 @@ static int usbtouch_probe(struct usb_interface *intf,
526 usbtouch->data, type->rept_size, 648 usbtouch->data, type->rept_size,
527 usbtouch_irq, usbtouch, endpoint->bInterval); 649 usbtouch_irq, usbtouch, endpoint->bInterval);
528 650
651 usbtouch->irq->dev = usbtouch->udev;
529 usbtouch->irq->transfer_dma = usbtouch->data_dma; 652 usbtouch->irq->transfer_dma = usbtouch->data_dma;
530 usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 653 usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
531 654
@@ -553,7 +676,7 @@ out_free_buffers:
553out_free: 676out_free:
554 input_free_device(input_dev); 677 input_free_device(input_dev);
555 kfree(usbtouch); 678 kfree(usbtouch);
556 return -ENOMEM; 679 return err;
557} 680}
558 681
559static void usbtouch_disconnect(struct usb_interface *intf) 682static void usbtouch_disconnect(struct usb_interface *intf)