diff options
author | Daniel Ritz <daniel.ritz-ml@swissonline.ch> | 2006-07-31 15:43:24 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-09-27 14:58:51 -0400 |
commit | 5d8926658ce41b254fdfba7d057e6c9438c25cca (patch) | |
tree | 64bddda2a71765f807ae0599905c7bcce083f1fb /drivers/usb/input | |
parent | d388dab7b562b76525761f89702246686747ba30 (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')
-rw-r--r-- | drivers/usb/input/Kconfig | 20 | ||||
-rw-r--r-- | drivers/usb/input/usbtouchscreen.c | 283 |
2 files changed, 219 insertions, 84 deletions
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index 650103bc9618..8a708520547b 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig | |||
@@ -205,10 +205,12 @@ config USB_TOUCHSCREEN | |||
205 | depends on USB && INPUT | 205 | depends on USB && INPUT |
206 | ---help--- | 206 | ---help--- |
207 | USB Touchscreen driver for: | 207 | USB Touchscreen driver for: |
208 | - eGalax Touchkit USB | 208 | - eGalax Touchkit USB (also includes eTurboTouch CT-410/510/700) |
209 | - PanJit TouchSet USB | 209 | - PanJit TouchSet USB |
210 | - 3M MicroTouch USB | 210 | - 3M MicroTouch USB (EX II series) |
211 | - ITM | 211 | - ITM |
212 | - some other eTurboTouch | ||
213 | - Gunze AHL61 | ||
212 | 214 | ||
213 | Have a look at <http://linux.chapter7.ch/touchkit/> for | 215 | Have a look at <http://linux.chapter7.ch/touchkit/> for |
214 | a usage description and the required user-space stuff. | 216 | a usage description and the required user-space stuff. |
@@ -218,7 +220,7 @@ config USB_TOUCHSCREEN | |||
218 | 220 | ||
219 | config USB_TOUCHSCREEN_EGALAX | 221 | config USB_TOUCHSCREEN_EGALAX |
220 | default y | 222 | default y |
221 | bool "eGalax device support" if EMBEDDED | 223 | bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED |
222 | depends on USB_TOUCHSCREEN | 224 | depends on USB_TOUCHSCREEN |
223 | 225 | ||
224 | config USB_TOUCHSCREEN_PANJIT | 226 | config USB_TOUCHSCREEN_PANJIT |
@@ -228,7 +230,7 @@ config USB_TOUCHSCREEN_PANJIT | |||
228 | 230 | ||
229 | config USB_TOUCHSCREEN_3M | 231 | config USB_TOUCHSCREEN_3M |
230 | default y | 232 | default y |
231 | bool "3M/Microtouch device support" if EMBEDDED | 233 | bool "3M/Microtouch EX II series device support" if EMBEDDED |
232 | depends on USB_TOUCHSCREEN | 234 | depends on USB_TOUCHSCREEN |
233 | 235 | ||
234 | config USB_TOUCHSCREEN_ITM | 236 | config USB_TOUCHSCREEN_ITM |
@@ -236,6 +238,16 @@ config USB_TOUCHSCREEN_ITM | |||
236 | bool "ITM device support" if EMBEDDED | 238 | bool "ITM device support" if EMBEDDED |
237 | depends on USB_TOUCHSCREEN | 239 | depends on USB_TOUCHSCREEN |
238 | 240 | ||
241 | config USB_TOUCHSCREEN_ETURBO | ||
242 | default y | ||
243 | bool "eTurboTouch (non-eGalax compatible) device support" if EMBEDDED | ||
244 | depends on USB_TOUCHSCREEN | ||
245 | |||
246 | config USB_TOUCHSCREEN_GUNZE | ||
247 | default y | ||
248 | bool "Gunze AHL61 device support" if EMBEDDED | ||
249 | depends on USB_TOUCHSCREEN | ||
250 | |||
239 | config USB_YEALINK | 251 | config USB_YEALINK |
240 | tristate "Yealink usb-p1k voip phone" | 252 | tristate "Yealink usb-p1k voip phone" |
241 | depends on USB && INPUT && EXPERIMENTAL | 253 | depends on USB && INPUT && EXPERIMENTAL |
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 | ||
84 | static 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 | ||
94 | static 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 */ |
88 | enum { | 100 | enum { |
@@ -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 | ||
96 | static struct usb_device_id usbtouch_devices[] = { | 110 | static 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 | ||
146 | static int egalax_get_pkt_len(unsigned char *buf) | 170 | static 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 | |||
159 | static 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 | ||
255 | static int mtouch_init(struct usbtouch_usb *usbtouch) | 221 | static 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 | ||
273 | static 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 | |||
289 | static 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 | ||
304 | static 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 | */ |
301 | static struct usbtouch_device_info usbtouch_dev_info[] = { | 320 | static 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 | ||
426 | static 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 | |||
495 | out_flush_buf: | ||
496 | usbtouch->buf_len = 0; | ||
497 | return; | ||
498 | } | ||
499 | #endif | ||
500 | |||
501 | |||
380 | static void usbtouch_irq(struct urb *urb, struct pt_regs *regs) | 502 | static 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: | |||
553 | out_free: | 676 | out_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 | ||
559 | static void usbtouch_disconnect(struct usb_interface *intf) | 682 | static void usbtouch_disconnect(struct usb_interface *intf) |