Commit | Line | Data |
---|---|---|
74ba9207 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
1d3e2023 DR |
2 | /****************************************************************************** |
3 | * usbtouchscreen.c | |
4 | * Driver for USB Touchscreens, supporting those devices: | |
5 | * - eGalax Touchkit | |
5d892665 DR |
6 | * includes eTurboTouch CT-410/510/700 |
7 | * - 3M/Microtouch EX II series | |
1d3e2023 DR |
8 | * - ITM |
9 | * - PanJit TouchSet | |
5d892665 DR |
10 | * - eTurboTouch |
11 | * - Gunze AHL61 | |
24ced062 | 12 | * - DMC TSC-10/25 |
df561fcd | 13 | * - IRTOUCHSYSTEMS/UNITOP |
a14a8401 | 14 | * - IdealTEK URTC1000 |
62aa366d | 15 | * - General Touch |
14e40206 | 16 | * - GoTop Super_Q2/GogoPen/PenPower tablets |
f7370699 | 17 | * - JASTEC USB touch controller/DigiTech DTR-02U |
2330ed18 | 18 | * - Zytronic capacitive touchscreen |
5197424c | 19 | * - NEXIO/iNexio |
d2cc817a | 20 | * - Elo TouchSystems 2700 IntelliTouch |
aa87512f | 21 | * - EasyTouch USB Dual/Multi touch controller from Data Modul |
1d3e2023 | 22 | * |
14e40206 | 23 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> |
1d3e2023 DR |
24 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) |
25 | * | |
1d3e2023 DR |
26 | * Driver is based on touchkitusb.c |
27 | * - ITM parts are from itmtouch.c | |
28 | * - 3M parts are from mtouchusb.c | |
29 | * - PanJit parts are from an unmerged driver by Lanslott Gish | |
24ced062 HS |
30 | * - DMC TSC 10/25 are from Holger Schurig, with ideas from an unmerged |
31 | * driver from Marius Vollmer | |
1d3e2023 DR |
32 | * |
33 | *****************************************************************************/ | |
34 | ||
35 | //#define DEBUG | |
36 | ||
1d3e2023 DR |
37 | #include <linux/kernel.h> |
38 | #include <linux/slab.h> | |
39 | #include <linux/input.h> | |
40 | #include <linux/module.h> | |
1d3e2023 | 41 | #include <linux/usb.h> |
ae0dadcf | 42 | #include <linux/usb/input.h> |
ec42d448 | 43 | #include <linux/hid.h> |
12e510db | 44 | #include <linux/mutex.h> |
1d3e2023 | 45 | |
90ab5ee9 | 46 | static bool swap_xy; |
1d3e2023 DR |
47 | module_param(swap_xy, bool, 0644); |
48 | MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); | |
49 | ||
90ab5ee9 | 50 | static bool hwcalib_xy; |
c9cbf3d3 DS |
51 | module_param(hwcalib_xy, bool, 0644); |
52 | MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available"); | |
53 | ||
1d3e2023 DR |
54 | /* device specifc data/functions */ |
55 | struct usbtouch_usb; | |
56 | struct usbtouch_device_info { | |
57 | int min_xc, max_xc; | |
58 | int min_yc, max_yc; | |
59 | int min_press, max_press; | |
60 | int rept_size; | |
1d3e2023 | 61 | |
2330ed18 DS |
62 | /* |
63 | * Always service the USB devices irq not just when the input device is | |
64 | * open. This is useful when devices have a watchdog which prevents us | |
65 | * from periodically polling the device. Leave this unset unless your | |
66 | * touchscreen device requires it, as it does consume more of the USB | |
67 | * bandwidth. | |
68 | */ | |
69 | bool irq_always; | |
70 | ||
62aa366d DR |
71 | /* |
72 | * used to get the packet len. possible return values: | |
73 | * > 0: packet len | |
74 | * = 0: skip one byte | |
75 | * < 0: -return value more bytes needed | |
76 | */ | |
5d892665 | 77 | int (*get_pkt_len) (unsigned char *pkt, int len); |
62aa366d | 78 | |
c9d8c2b3 | 79 | int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt); |
a8aef622 | 80 | int (*alloc) (struct usbtouch_usb *usbtouch); |
1d3e2023 | 81 | int (*init) (struct usbtouch_usb *usbtouch); |
5197424c | 82 | void (*exit) (struct usbtouch_usb *usbtouch); |
1d3e2023 DR |
83 | }; |
84 | ||
1d3e2023 DR |
85 | /* a usbtouch device */ |
86 | struct usbtouch_usb { | |
87 | unsigned char *data; | |
88 | dma_addr_t data_dma; | |
4ef38351 | 89 | int data_size; |
1d3e2023 DR |
90 | unsigned char *buffer; |
91 | int buf_len; | |
92 | struct urb *irq; | |
fea4d14b | 93 | struct usb_interface *interface; |
1d3e2023 | 94 | struct input_dev *input; |
830f06c0 | 95 | const struct usbtouch_device_info *type; |
12e510db | 96 | struct mutex pm_mutex; /* serialize access to open/suspend */ |
85f46fbf | 97 | bool is_open; |
1d3e2023 DR |
98 | char name[128]; |
99 | char phys[64]; | |
5197424c | 100 | void *priv; |
c9d8c2b3 DR |
101 | |
102 | int x, y; | |
103 | int touch, press; | |
fbb1c922 DT |
104 | |
105 | void (*process_pkt)(struct usbtouch_usb *usbtouch, unsigned char *pkt, int len); | |
1d3e2023 DR |
106 | }; |
107 | ||
5d892665 | 108 | |
9e3b2583 FE |
109 | /***************************************************************************** |
110 | * e2i Part | |
111 | */ | |
112 | ||
113 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | |
114 | static int e2i_init(struct usbtouch_usb *usbtouch) | |
115 | { | |
116 | int ret; | |
fea4d14b | 117 | struct usb_device *udev = interface_to_usbdev(usbtouch->interface); |
9e3b2583 | 118 | |
41e81022 | 119 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), |
9e3b2583 FE |
120 | 0x01, 0x02, 0x0000, 0x0081, |
121 | NULL, 0, USB_CTRL_SET_TIMEOUT); | |
122 | ||
0a5ebc88 | 123 | dev_dbg(&usbtouch->interface->dev, |
b741ab9d GKH |
124 | "%s - usb_control_msg - E2I_RESET - bytes|err: %d\n", |
125 | __func__, ret); | |
9e3b2583 FE |
126 | return ret; |
127 | } | |
128 | ||
129 | static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |
130 | { | |
131 | int tmp = (pkt[0] << 8) | pkt[1]; | |
132 | dev->x = (pkt[2] << 8) | pkt[3]; | |
133 | dev->y = (pkt[4] << 8) | pkt[5]; | |
134 | ||
135 | tmp = tmp - 0xA000; | |
136 | dev->touch = (tmp > 0); | |
137 | dev->press = (tmp > 0 ? tmp : 0); | |
138 | ||
139 | return 1; | |
140 | } | |
7f787df1 DT |
141 | |
142 | static const struct usbtouch_device_info e2i_dev_info = { | |
143 | .min_xc = 0x0, | |
144 | .max_xc = 0x7fff, | |
145 | .min_yc = 0x0, | |
146 | .max_yc = 0x7fff, | |
147 | .rept_size = 6, | |
148 | .init = e2i_init, | |
149 | .read_data = e2i_read_data, | |
150 | }; | |
9e3b2583 FE |
151 | #endif |
152 | ||
153 | ||
1d3e2023 DR |
154 | /***************************************************************************** |
155 | * eGalax part | |
156 | */ | |
157 | ||
c6f8d706 | 158 | #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX |
1d3e2023 | 159 | |
62aa366d DR |
160 | #ifndef MULTI_PACKET |
161 | #define MULTI_PACKET | |
162 | #endif | |
163 | ||
1d3e2023 DR |
164 | #define EGALAX_PKT_TYPE_MASK 0xFE |
165 | #define EGALAX_PKT_TYPE_REPT 0x80 | |
166 | #define EGALAX_PKT_TYPE_DIAG 0x0A | |
167 | ||
037a833e FB |
168 | static int egalax_init(struct usbtouch_usb *usbtouch) |
169 | { | |
037a833e | 170 | struct usb_device *udev = interface_to_usbdev(usbtouch->interface); |
d04f9393 | 171 | int ret, i; |
037a833e FB |
172 | |
173 | /* | |
174 | * An eGalax diagnostic packet kicks the device into using the right | |
175 | * protocol. We send a "check active" packet. The response will be | |
176 | * read later and ignored. | |
177 | */ | |
178 | ||
d04f9393 | 179 | u8 *buf __free(kfree) = kmalloc(3, GFP_KERNEL); |
037a833e FB |
180 | if (!buf) |
181 | return -ENOMEM; | |
182 | ||
183 | buf[0] = EGALAX_PKT_TYPE_DIAG; | |
184 | buf[1] = 1; /* length */ | |
185 | buf[2] = 'A'; /* command - check active */ | |
186 | ||
187 | for (i = 0; i < 3; i++) { | |
188 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | |
189 | 0, | |
190 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
191 | 0, 0, buf, 3, | |
192 | USB_CTRL_SET_TIMEOUT); | |
037a833e FB |
193 | if (ret != -EPIPE) |
194 | break; | |
195 | } | |
196 | ||
d04f9393 | 197 | return ret < 0 ? ret : 0; |
037a833e FB |
198 | } |
199 | ||
c9d8c2b3 | 200 | static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt) |
1d3e2023 DR |
201 | { |
202 | if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) | |
203 | return 0; | |
204 | ||
c9d8c2b3 DR |
205 | dev->x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F); |
206 | dev->y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F); | |
207 | dev->touch = pkt[0] & 0x01; | |
1d3e2023 DR |
208 | |
209 | return 1; | |
1d3e2023 DR |
210 | } |
211 | ||
5d892665 | 212 | static int egalax_get_pkt_len(unsigned char *buf, int len) |
1d3e2023 DR |
213 | { |
214 | switch (buf[0] & EGALAX_PKT_TYPE_MASK) { | |
215 | case EGALAX_PKT_TYPE_REPT: | |
216 | return 5; | |
217 | ||
218 | case EGALAX_PKT_TYPE_DIAG: | |
5d892665 DR |
219 | if (len < 2) |
220 | return -1; | |
221 | ||
1d3e2023 DR |
222 | return buf[1] + 2; |
223 | } | |
224 | ||
225 | return 0; | |
226 | } | |
7f787df1 DT |
227 | |
228 | static const struct usbtouch_device_info egalax_dev_info = { | |
229 | .min_xc = 0x0, | |
230 | .max_xc = 0x07ff, | |
231 | .min_yc = 0x0, | |
232 | .max_yc = 0x07ff, | |
233 | .rept_size = 16, | |
234 | .get_pkt_len = egalax_get_pkt_len, | |
235 | .read_data = egalax_read_data, | |
236 | .init = egalax_init, | |
237 | }; | |
1d3e2023 DR |
238 | #endif |
239 | ||
aa87512f AV |
240 | /***************************************************************************** |
241 | * EasyTouch part | |
242 | */ | |
243 | ||
244 | #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH | |
245 | ||
246 | #ifndef MULTI_PACKET | |
247 | #define MULTI_PACKET | |
248 | #endif | |
249 | ||
250 | #define ETOUCH_PKT_TYPE_MASK 0xFE | |
251 | #define ETOUCH_PKT_TYPE_REPT 0x80 | |
252 | #define ETOUCH_PKT_TYPE_REPT2 0xB0 | |
253 | #define ETOUCH_PKT_TYPE_DIAG 0x0A | |
254 | ||
255 | static int etouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |
256 | { | |
257 | if ((pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT && | |
258 | (pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT2) | |
259 | return 0; | |
260 | ||
261 | dev->x = ((pkt[1] & 0x1F) << 7) | (pkt[2] & 0x7F); | |
262 | dev->y = ((pkt[3] & 0x1F) << 7) | (pkt[4] & 0x7F); | |
263 | dev->touch = pkt[0] & 0x01; | |
264 | ||
265 | return 1; | |
266 | } | |
267 | ||
268 | static int etouch_get_pkt_len(unsigned char *buf, int len) | |
269 | { | |
270 | switch (buf[0] & ETOUCH_PKT_TYPE_MASK) { | |
271 | case ETOUCH_PKT_TYPE_REPT: | |
272 | case ETOUCH_PKT_TYPE_REPT2: | |
273 | return 5; | |
274 | ||
275 | case ETOUCH_PKT_TYPE_DIAG: | |
276 | if (len < 2) | |
277 | return -1; | |
278 | ||
279 | return buf[1] + 2; | |
280 | } | |
281 | ||
282 | return 0; | |
283 | } | |
7f787df1 DT |
284 | |
285 | static const struct usbtouch_device_info etouch_dev_info = { | |
286 | .min_xc = 0x0, | |
287 | .max_xc = 0x07ff, | |
288 | .min_yc = 0x0, | |
289 | .max_yc = 0x07ff, | |
290 | .rept_size = 16, | |
291 | .get_pkt_len = etouch_get_pkt_len, | |
292 | .read_data = etouch_read_data, | |
293 | }; | |
aa87512f | 294 | #endif |
1d3e2023 DR |
295 | |
296 | /***************************************************************************** | |
297 | * PanJit Part | |
298 | */ | |
c6f8d706 | 299 | #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT |
c9d8c2b3 | 300 | static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt) |
1d3e2023 | 301 | { |
c9d8c2b3 DR |
302 | dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; |
303 | dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; | |
304 | dev->touch = pkt[0] & 0x01; | |
1d3e2023 DR |
305 | |
306 | return 1; | |
307 | } | |
7f787df1 DT |
308 | |
309 | static const struct usbtouch_device_info panjit_dev_info = { | |
310 | .min_xc = 0x0, | |
311 | .max_xc = 0x0fff, | |
312 | .min_yc = 0x0, | |
313 | .max_yc = 0x0fff, | |
314 | .rept_size = 8, | |
315 | .read_data = panjit_read_data, | |
316 | }; | |
1d3e2023 DR |
317 | #endif |
318 | ||
319 | ||
320 | /***************************************************************************** | |
321 | * 3M/Microtouch Part | |
322 | */ | |
c6f8d706 | 323 | #ifdef CONFIG_TOUCHSCREEN_USB_3M |
1d3e2023 DR |
324 | |
325 | #define MTOUCHUSB_ASYNC_REPORT 1 | |
326 | #define MTOUCHUSB_RESET 7 | |
327 | #define MTOUCHUSB_REQ_CTRLLR_ID 10 | |
328 | ||
89f84b84 ND |
329 | #define MTOUCHUSB_REQ_CTRLLR_ID_LEN 16 |
330 | ||
c9d8c2b3 | 331 | static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) |
1d3e2023 | 332 | { |
c9cbf3d3 DS |
333 | if (hwcalib_xy) { |
334 | dev->x = (pkt[4] << 8) | pkt[3]; | |
335 | dev->y = 0xffff - ((pkt[6] << 8) | pkt[5]); | |
336 | } else { | |
337 | dev->x = (pkt[8] << 8) | pkt[7]; | |
338 | dev->y = (pkt[10] << 8) | pkt[9]; | |
339 | } | |
c9d8c2b3 | 340 | dev->touch = (pkt[2] & 0x40) ? 1 : 0; |
1d3e2023 DR |
341 | |
342 | return 1; | |
343 | } | |
344 | ||
89f84b84 ND |
345 | struct mtouch_priv { |
346 | u8 fw_rev_major; | |
347 | u8 fw_rev_minor; | |
348 | }; | |
349 | ||
89f84b84 ND |
350 | static int mtouch_get_fw_revision(struct usbtouch_usb *usbtouch) |
351 | { | |
352 | struct usb_device *udev = interface_to_usbdev(usbtouch->interface); | |
353 | struct mtouch_priv *priv = usbtouch->priv; | |
89f84b84 ND |
354 | int ret; |
355 | ||
d04f9393 | 356 | u8 *buf __free(kfree) = kzalloc(MTOUCHUSB_REQ_CTRLLR_ID_LEN, GFP_NOIO); |
89f84b84 ND |
357 | if (!buf) |
358 | return -ENOMEM; | |
359 | ||
360 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | |
361 | MTOUCHUSB_REQ_CTRLLR_ID, | |
362 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
363 | 0, 0, buf, MTOUCHUSB_REQ_CTRLLR_ID_LEN, | |
364 | USB_CTRL_SET_TIMEOUT); | |
365 | if (ret != MTOUCHUSB_REQ_CTRLLR_ID_LEN) { | |
366 | dev_warn(&usbtouch->interface->dev, | |
367 | "Failed to read FW rev: %d\n", ret); | |
d04f9393 | 368 | return ret < 0 ? ret : -EIO; |
89f84b84 ND |
369 | } |
370 | ||
371 | priv->fw_rev_major = buf[3]; | |
372 | priv->fw_rev_minor = buf[4]; | |
373 | ||
d04f9393 | 374 | return 0; |
89f84b84 ND |
375 | } |
376 | ||
377 | static int mtouch_alloc(struct usbtouch_usb *usbtouch) | |
378 | { | |
f81d03d4 | 379 | struct mtouch_priv *priv; |
89f84b84 | 380 | |
f81d03d4 EA |
381 | priv = kmalloc(sizeof(*priv), GFP_KERNEL); |
382 | if (!priv) | |
89f84b84 ND |
383 | return -ENOMEM; |
384 | ||
f81d03d4 | 385 | usbtouch->priv = priv; |
89f84b84 ND |
386 | return 0; |
387 | } | |
388 | ||
1d3e2023 DR |
389 | static int mtouch_init(struct usbtouch_usb *usbtouch) |
390 | { | |
5d892665 | 391 | int ret, i; |
fea4d14b | 392 | struct usb_device *udev = interface_to_usbdev(usbtouch->interface); |
1d3e2023 | 393 | |
89f84b84 ND |
394 | ret = mtouch_get_fw_revision(usbtouch); |
395 | if (ret) | |
396 | return ret; | |
397 | ||
41e81022 | 398 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), |
1d3e2023 DR |
399 | MTOUCHUSB_RESET, |
400 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
401 | 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); | |
0a5ebc88 | 402 | dev_dbg(&usbtouch->interface->dev, |
b741ab9d GKH |
403 | "%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d\n", |
404 | __func__, ret); | |
1d3e2023 DR |
405 | if (ret < 0) |
406 | return ret; | |
5d892665 DR |
407 | msleep(150); |
408 | ||
409 | for (i = 0; i < 3; i++) { | |
41e81022 | 410 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), |
5d892665 DR |
411 | MTOUCHUSB_ASYNC_REPORT, |
412 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
413 | 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); | |
0a5ebc88 | 414 | dev_dbg(&usbtouch->interface->dev, |
b741ab9d GKH |
415 | "%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d\n", |
416 | __func__, ret); | |
5d892665 DR |
417 | if (ret >= 0) |
418 | break; | |
419 | if (ret != -EPIPE) | |
420 | return ret; | |
421 | } | |
1d3e2023 | 422 | |
c9cbf3d3 DS |
423 | /* Default min/max xy are the raw values, override if using hw-calib */ |
424 | if (hwcalib_xy) { | |
425 | input_set_abs_params(usbtouch->input, ABS_X, 0, 0xffff, 0, 0); | |
426 | input_set_abs_params(usbtouch->input, ABS_Y, 0, 0xffff, 0, 0); | |
427 | } | |
428 | ||
1d3e2023 DR |
429 | return 0; |
430 | } | |
89f84b84 ND |
431 | |
432 | static void mtouch_exit(struct usbtouch_usb *usbtouch) | |
433 | { | |
434 | struct mtouch_priv *priv = usbtouch->priv; | |
435 | ||
89f84b84 ND |
436 | kfree(priv); |
437 | } | |
7f787df1 DT |
438 | |
439 | static struct usbtouch_device_info mtouch_dev_info = { | |
440 | .min_xc = 0x0, | |
441 | .max_xc = 0x4000, | |
442 | .min_yc = 0x0, | |
443 | .max_yc = 0x4000, | |
444 | .rept_size = 11, | |
445 | .read_data = mtouch_read_data, | |
446 | .alloc = mtouch_alloc, | |
447 | .init = mtouch_init, | |
448 | .exit = mtouch_exit, | |
449 | }; | |
450 | ||
451 | static ssize_t mtouch_firmware_rev_show(struct device *dev, | |
452 | struct device_attribute *attr, char *output) | |
453 | { | |
454 | struct usb_interface *intf = to_usb_interface(dev); | |
455 | struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); | |
456 | struct mtouch_priv *priv = usbtouch->priv; | |
457 | ||
458 | return sysfs_emit(output, "%1x.%1x\n", | |
459 | priv->fw_rev_major, priv->fw_rev_minor); | |
460 | } | |
461 | static DEVICE_ATTR(firmware_rev, 0444, mtouch_firmware_rev_show, NULL); | |
462 | ||
463 | static struct attribute *mtouch_attrs[] = { | |
464 | &dev_attr_firmware_rev.attr, | |
465 | NULL | |
466 | }; | |
467 | ||
468 | static bool mtouch_group_visible(struct kobject *kobj) | |
469 | { | |
470 | struct device *dev = kobj_to_dev(kobj); | |
471 | struct usb_interface *intf = to_usb_interface(dev); | |
472 | struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); | |
473 | ||
474 | return usbtouch->type == &mtouch_dev_info; | |
475 | } | |
476 | ||
477 | DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(mtouch); | |
478 | ||
479 | static const struct attribute_group mtouch_attr_group = { | |
480 | .is_visible = SYSFS_GROUP_VISIBLE(mtouch), | |
481 | .attrs = mtouch_attrs, | |
482 | }; | |
1d3e2023 DR |
483 | #endif |
484 | ||
485 | ||
486 | /***************************************************************************** | |
487 | * ITM Part | |
488 | */ | |
c6f8d706 | 489 | #ifdef CONFIG_TOUCHSCREEN_USB_ITM |
c9d8c2b3 | 490 | static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt) |
1d3e2023 | 491 | { |
c9d8c2b3 DR |
492 | int touch; |
493 | /* | |
494 | * ITM devices report invalid x/y data if not touched. | |
495 | * if the screen was touched before but is not touched any more | |
496 | * report touch as 0 with the last valid x/y data once. then stop | |
497 | * reporting data until touched again. | |
498 | */ | |
499 | dev->press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F); | |
500 | ||
501 | touch = ~pkt[7] & 0x20; | |
502 | if (!touch) { | |
503 | if (dev->touch) { | |
504 | dev->touch = 0; | |
505 | return 1; | |
506 | } | |
507 | ||
508 | return 0; | |
509 | } | |
510 | ||
511 | dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F); | |
512 | dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F); | |
513 | dev->touch = touch; | |
1d3e2023 | 514 | |
c9d8c2b3 | 515 | return 1; |
1d3e2023 | 516 | } |
7f787df1 DT |
517 | |
518 | static const struct usbtouch_device_info itm_dev_info = { | |
519 | .min_xc = 0x0, | |
520 | .max_xc = 0x0fff, | |
521 | .min_yc = 0x0, | |
522 | .max_yc = 0x0fff, | |
523 | .max_press = 0xff, | |
524 | .rept_size = 8, | |
525 | .read_data = itm_read_data, | |
526 | }; | |
1d3e2023 DR |
527 | #endif |
528 | ||
529 | ||
5d892665 DR |
530 | /***************************************************************************** |
531 | * eTurboTouch part | |
532 | */ | |
c6f8d706 | 533 | #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO |
62aa366d DR |
534 | #ifndef MULTI_PACKET |
535 | #define MULTI_PACKET | |
536 | #endif | |
c9d8c2b3 | 537 | static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) |
5d892665 DR |
538 | { |
539 | unsigned int shift; | |
540 | ||
541 | /* packets should start with sync */ | |
542 | if (!(pkt[0] & 0x80)) | |
543 | return 0; | |
544 | ||
545 | shift = (6 - (pkt[0] & 0x03)); | |
c9d8c2b3 DR |
546 | dev->x = ((pkt[3] << 7) | pkt[4]) >> shift; |
547 | dev->y = ((pkt[1] << 7) | pkt[2]) >> shift; | |
548 | dev->touch = (pkt[0] & 0x10) ? 1 : 0; | |
5d892665 DR |
549 | |
550 | return 1; | |
551 | } | |
552 | ||
553 | static int eturbo_get_pkt_len(unsigned char *buf, int len) | |
554 | { | |
555 | if (buf[0] & 0x80) | |
556 | return 5; | |
557 | if (buf[0] == 0x01) | |
558 | return 3; | |
559 | return 0; | |
560 | } | |
7f787df1 DT |
561 | |
562 | static const struct usbtouch_device_info eturbo_dev_info = { | |
563 | .min_xc = 0x0, | |
564 | .max_xc = 0x07ff, | |
565 | .min_yc = 0x0, | |
566 | .max_yc = 0x07ff, | |
567 | .rept_size = 8, | |
568 | .get_pkt_len = eturbo_get_pkt_len, | |
569 | .read_data = eturbo_read_data, | |
570 | }; | |
5d892665 DR |
571 | #endif |
572 | ||
573 | ||
574 | /***************************************************************************** | |
575 | * Gunze part | |
576 | */ | |
c6f8d706 | 577 | #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE |
c9d8c2b3 | 578 | static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt) |
5d892665 DR |
579 | { |
580 | if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80)) | |
581 | return 0; | |
582 | ||
c9d8c2b3 DR |
583 | dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F); |
584 | dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F); | |
585 | dev->touch = pkt[0] & 0x20; | |
5d892665 DR |
586 | |
587 | return 1; | |
588 | } | |
7f787df1 DT |
589 | |
590 | static const struct usbtouch_device_info gunze_dev_info = { | |
591 | .min_xc = 0x0, | |
592 | .max_xc = 0x0fff, | |
593 | .min_yc = 0x0, | |
594 | .max_yc = 0x0fff, | |
595 | .rept_size = 4, | |
596 | .read_data = gunze_read_data, | |
597 | }; | |
5d892665 DR |
598 | #endif |
599 | ||
24ced062 HS |
600 | /***************************************************************************** |
601 | * DMC TSC-10/25 Part | |
602 | * | |
603 | * Documentation about the controller and it's protocol can be found at | |
604 | * http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf | |
605 | * http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf | |
606 | */ | |
c6f8d706 | 607 | #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 |
24ced062 HS |
608 | |
609 | /* supported data rates. currently using 130 */ | |
610 | #define TSC10_RATE_POINT 0x50 | |
611 | #define TSC10_RATE_30 0x40 | |
612 | #define TSC10_RATE_50 0x41 | |
613 | #define TSC10_RATE_80 0x42 | |
614 | #define TSC10_RATE_100 0x43 | |
615 | #define TSC10_RATE_130 0x44 | |
616 | #define TSC10_RATE_150 0x45 | |
617 | ||
618 | /* commands */ | |
619 | #define TSC10_CMD_RESET 0x55 | |
620 | #define TSC10_CMD_RATE 0x05 | |
621 | #define TSC10_CMD_DATA1 0x01 | |
622 | ||
623 | static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) | |
624 | { | |
fea4d14b | 625 | struct usb_device *dev = interface_to_usbdev(usbtouch->interface); |
d04f9393 | 626 | int ret; |
24ced062 | 627 | |
d04f9393 | 628 | u8 *buf __free(kfree) = kmalloc(2, GFP_NOIO); |
76d057ce | 629 | if (!buf) |
d04f9393 DT |
630 | return -ENOMEM; |
631 | ||
24ced062 HS |
632 | /* reset */ |
633 | buf[0] = buf[1] = 0xFF; | |
634 | ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), | |
d04f9393 DT |
635 | TSC10_CMD_RESET, |
636 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
637 | 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT); | |
24ced062 | 638 | if (ret < 0) |
d04f9393 DT |
639 | return ret; |
640 | ||
641 | if (buf[0] != 0x06) | |
642 | return -ENODEV; | |
24ced062 | 643 | |
96849170 BB |
644 | /* TSC-25 data sheet specifies a delay after the RESET command */ |
645 | msleep(150); | |
646 | ||
24ced062 HS |
647 | /* set coordinate output rate */ |
648 | buf[0] = buf[1] = 0xFF; | |
649 | ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), | |
d04f9393 DT |
650 | TSC10_CMD_RATE, |
651 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
652 | TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); | |
24ced062 | 653 | if (ret < 0) |
d04f9393 DT |
654 | return ret; |
655 | ||
656 | if (buf[0] != 0x06 && (buf[0] != 0x15 || buf[1] != 0x01)) | |
657 | return -ENODEV; | |
24ced062 HS |
658 | |
659 | /* start sending data */ | |
d04f9393 DT |
660 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
661 | TSC10_CMD_DATA1, | |
662 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
663 | 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); | |
24ced062 HS |
664 | } |
665 | ||
c9d8c2b3 | 666 | static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt) |
24ced062 | 667 | { |
c9d8c2b3 DR |
668 | dev->x = ((pkt[2] & 0x03) << 8) | pkt[1]; |
669 | dev->y = ((pkt[4] & 0x03) << 8) | pkt[3]; | |
670 | dev->touch = pkt[0] & 0x01; | |
24ced062 HS |
671 | |
672 | return 1; | |
673 | } | |
7f787df1 DT |
674 | |
675 | static const struct usbtouch_device_info dmc_tsc10_dev_info = { | |
676 | .min_xc = 0x0, | |
677 | .max_xc = 0x03ff, | |
678 | .min_yc = 0x0, | |
679 | .max_yc = 0x03ff, | |
680 | .rept_size = 5, | |
681 | .init = dmc_tsc10_init, | |
682 | .read_data = dmc_tsc10_read_data, | |
683 | }; | |
24ced062 HS |
684 | #endif |
685 | ||
686 | ||
df561fcd OZ |
687 | /***************************************************************************** |
688 | * IRTOUCH Part | |
689 | */ | |
690 | #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH | |
691 | static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |
692 | { | |
693 | dev->x = (pkt[3] << 8) | pkt[2]; | |
694 | dev->y = (pkt[5] << 8) | pkt[4]; | |
695 | dev->touch = (pkt[1] & 0x03) ? 1 : 0; | |
696 | ||
697 | return 1; | |
698 | } | |
7f787df1 DT |
699 | |
700 | static const struct usbtouch_device_info irtouch_dev_info = { | |
701 | .min_xc = 0x0, | |
702 | .max_xc = 0x0fff, | |
703 | .min_yc = 0x0, | |
704 | .max_yc = 0x0fff, | |
705 | .rept_size = 8, | |
706 | .read_data = irtouch_read_data, | |
707 | }; | |
708 | ||
709 | static const struct usbtouch_device_info irtouch_hires_dev_info = { | |
710 | .min_xc = 0x0, | |
711 | .max_xc = 0x7fff, | |
712 | .min_yc = 0x0, | |
713 | .max_yc = 0x7fff, | |
714 | .rept_size = 8, | |
715 | .read_data = irtouch_read_data, | |
716 | }; | |
df561fcd OZ |
717 | #endif |
718 | ||
dbe1420b | 719 | /***************************************************************************** |
38771bb4 | 720 | * ET&T TC5UH/TC4UM part |
dbe1420b | 721 | */ |
38771bb4 PÅ |
722 | #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB |
723 | static int tc45usb_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |
dbe1420b PÅ |
724 | { |
725 | dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; | |
726 | dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; | |
727 | dev->touch = pkt[0] & 0x01; | |
728 | ||
729 | return 1; | |
730 | } | |
7f787df1 DT |
731 | |
732 | static const struct usbtouch_device_info tc45usb_dev_info = { | |
733 | .min_xc = 0x0, | |
734 | .max_xc = 0x0fff, | |
735 | .min_yc = 0x0, | |
736 | .max_yc = 0x0fff, | |
737 | .rept_size = 5, | |
738 | .read_data = tc45usb_read_data, | |
739 | }; | |
dbe1420b | 740 | #endif |
df561fcd | 741 | |
a14a8401 OZ |
742 | /***************************************************************************** |
743 | * IdealTEK URTC1000 Part | |
744 | */ | |
745 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK | |
62aa366d DR |
746 | #ifndef MULTI_PACKET |
747 | #define MULTI_PACKET | |
748 | #endif | |
a14a8401 OZ |
749 | static int idealtek_get_pkt_len(unsigned char *buf, int len) |
750 | { | |
751 | if (buf[0] & 0x80) | |
752 | return 5; | |
753 | if (buf[0] == 0x01) | |
754 | return len; | |
755 | return 0; | |
756 | } | |
757 | ||
758 | static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |
759 | { | |
760 | switch (pkt[0] & 0x98) { | |
761 | case 0x88: | |
762 | /* touch data in IdealTEK mode */ | |
763 | dev->x = (pkt[1] << 5) | (pkt[2] >> 2); | |
764 | dev->y = (pkt[3] << 5) | (pkt[4] >> 2); | |
765 | dev->touch = (pkt[0] & 0x40) ? 1 : 0; | |
766 | return 1; | |
767 | ||
768 | case 0x98: | |
769 | /* touch data in MT emulation mode */ | |
770 | dev->x = (pkt[2] << 5) | (pkt[1] >> 2); | |
771 | dev->y = (pkt[4] << 5) | (pkt[3] >> 2); | |
772 | dev->touch = (pkt[0] & 0x40) ? 1 : 0; | |
773 | return 1; | |
774 | ||
775 | default: | |
776 | return 0; | |
777 | } | |
778 | } | |
7f787df1 DT |
779 | |
780 | static const struct usbtouch_device_info idealtek_dev_info = { | |
781 | .min_xc = 0x0, | |
782 | .max_xc = 0x0fff, | |
783 | .min_yc = 0x0, | |
784 | .max_yc = 0x0fff, | |
785 | .rept_size = 8, | |
786 | .get_pkt_len = idealtek_get_pkt_len, | |
787 | .read_data = idealtek_read_data, | |
788 | }; | |
a14a8401 OZ |
789 | #endif |
790 | ||
9d5657db IF |
791 | /***************************************************************************** |
792 | * General Touch Part | |
793 | */ | |
794 | #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH | |
795 | static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |
796 | { | |
eb083ba2 RY |
797 | dev->x = (pkt[2] << 8) | pkt[1]; |
798 | dev->y = (pkt[4] << 8) | pkt[3]; | |
9d5657db IF |
799 | dev->press = pkt[5] & 0xff; |
800 | dev->touch = pkt[0] & 0x01; | |
801 | ||
802 | return 1; | |
803 | } | |
7f787df1 DT |
804 | |
805 | static const struct usbtouch_device_info general_touch_dev_info = { | |
806 | .min_xc = 0x0, | |
807 | .max_xc = 0x7fff, | |
808 | .min_yc = 0x0, | |
809 | .max_yc = 0x7fff, | |
810 | .rept_size = 7, | |
811 | .read_data = general_touch_read_data, | |
812 | }; | |
9d5657db | 813 | #endif |
a14a8401 | 814 | |
14e40206 JJ |
815 | /***************************************************************************** |
816 | * GoTop Part | |
817 | */ | |
818 | #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP | |
819 | static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |
820 | { | |
821 | dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; | |
822 | dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; | |
823 | dev->touch = pkt[0] & 0x01; | |
f7370699 JP |
824 | |
825 | return 1; | |
826 | } | |
7f787df1 DT |
827 | |
828 | static const struct usbtouch_device_info gotop_dev_info = { | |
829 | .min_xc = 0x0, | |
830 | .max_xc = 0x03ff, | |
831 | .min_yc = 0x0, | |
832 | .max_yc = 0x03ff, | |
833 | .rept_size = 4, | |
834 | .read_data = gotop_read_data, | |
835 | }; | |
f7370699 JP |
836 | #endif |
837 | ||
838 | /***************************************************************************** | |
839 | * JASTEC Part | |
840 | */ | |
841 | #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC | |
842 | static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |
843 | { | |
844 | dev->x = ((pkt[0] & 0x3f) << 6) | (pkt[2] & 0x3f); | |
845 | dev->y = ((pkt[1] & 0x3f) << 6) | (pkt[3] & 0x3f); | |
846 | dev->touch = (pkt[0] & 0x40) >> 6; | |
847 | ||
14e40206 JJ |
848 | return 1; |
849 | } | |
7f787df1 DT |
850 | |
851 | static const struct usbtouch_device_info jastec_dev_info = { | |
852 | .min_xc = 0x0, | |
853 | .max_xc = 0x0fff, | |
854 | .min_yc = 0x0, | |
855 | .max_yc = 0x0fff, | |
856 | .rept_size = 4, | |
857 | .read_data = jastec_read_data, | |
858 | }; | |
14e40206 JJ |
859 | #endif |
860 | ||
2330ed18 DS |
861 | /***************************************************************************** |
862 | * Zytronic Part | |
863 | */ | |
864 | #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC | |
865 | static int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |
866 | { | |
0a5ebc88 | 867 | struct usb_interface *intf = dev->interface; |
b741ab9d | 868 | |
2330ed18 DS |
869 | switch (pkt[0]) { |
870 | case 0x3A: /* command response */ | |
0a5ebc88 | 871 | dev_dbg(&intf->dev, "%s: Command response %d\n", __func__, pkt[1]); |
2330ed18 DS |
872 | break; |
873 | ||
874 | case 0xC0: /* down */ | |
875 | dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); | |
876 | dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); | |
877 | dev->touch = 1; | |
0a5ebc88 | 878 | dev_dbg(&intf->dev, "%s: down %d,%d\n", __func__, dev->x, dev->y); |
2330ed18 DS |
879 | return 1; |
880 | ||
881 | case 0x80: /* up */ | |
882 | dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); | |
883 | dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); | |
884 | dev->touch = 0; | |
0a5ebc88 | 885 | dev_dbg(&intf->dev, "%s: up %d,%d\n", __func__, dev->x, dev->y); |
2330ed18 DS |
886 | return 1; |
887 | ||
888 | default: | |
0a5ebc88 | 889 | dev_dbg(&intf->dev, "%s: Unknown return %d\n", __func__, pkt[0]); |
2330ed18 DS |
890 | break; |
891 | } | |
892 | ||
893 | return 0; | |
894 | } | |
7f787df1 DT |
895 | |
896 | static const struct usbtouch_device_info zytronic_dev_info = { | |
897 | .min_xc = 0x0, | |
898 | .max_xc = 0x03ff, | |
899 | .min_yc = 0x0, | |
900 | .max_yc = 0x03ff, | |
901 | .rept_size = 5, | |
902 | .read_data = zytronic_read_data, | |
903 | .irq_always = true, | |
904 | }; | |
2330ed18 | 905 | #endif |
14e40206 | 906 | |
5197424c OZ |
907 | /***************************************************************************** |
908 | * NEXIO Part | |
909 | */ | |
910 | #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO | |
911 | ||
912 | #define NEXIO_TIMEOUT 5000 | |
913 | #define NEXIO_BUFSIZE 1024 | |
914 | #define NEXIO_THRESHOLD 50 | |
915 | ||
916 | struct nexio_priv { | |
917 | struct urb *ack; | |
918 | unsigned char *ack_buf; | |
919 | }; | |
920 | ||
921 | struct nexio_touch_packet { | |
922 | u8 flags; /* 0xe1 = touch, 0xe1 = release */ | |
923 | __be16 data_len; /* total bytes of touch data */ | |
924 | __be16 x_len; /* bytes for X axis */ | |
925 | __be16 y_len; /* bytes for Y axis */ | |
926 | u8 data[]; | |
927 | } __attribute__ ((packed)); | |
928 | ||
929 | static unsigned char nexio_ack_pkt[2] = { 0xaa, 0x02 }; | |
930 | static unsigned char nexio_init_pkt[4] = { 0x82, 0x04, 0x0a, 0x0f }; | |
931 | ||
932 | static void nexio_ack_complete(struct urb *urb) | |
933 | { | |
934 | } | |
935 | ||
a8aef622 ON |
936 | static int nexio_alloc(struct usbtouch_usb *usbtouch) |
937 | { | |
938 | struct nexio_priv *priv; | |
939 | int ret = -ENOMEM; | |
940 | ||
f81d03d4 EA |
941 | priv = kmalloc(sizeof(*priv), GFP_KERNEL); |
942 | if (!priv) | |
a8aef622 ON |
943 | goto out_buf; |
944 | ||
f81d03d4 | 945 | usbtouch->priv = priv; |
a8aef622 ON |
946 | priv->ack_buf = kmemdup(nexio_ack_pkt, sizeof(nexio_ack_pkt), |
947 | GFP_KERNEL); | |
948 | if (!priv->ack_buf) | |
949 | goto err_priv; | |
950 | ||
951 | priv->ack = usb_alloc_urb(0, GFP_KERNEL); | |
952 | if (!priv->ack) { | |
0a5ebc88 | 953 | dev_dbg(&usbtouch->interface->dev, |
b741ab9d | 954 | "%s - usb_alloc_urb failed: usbtouch->ack\n", __func__); |
a8aef622 ON |
955 | goto err_ack_buf; |
956 | } | |
957 | ||
958 | return 0; | |
959 | ||
960 | err_ack_buf: | |
961 | kfree(priv->ack_buf); | |
962 | err_priv: | |
963 | kfree(priv); | |
964 | out_buf: | |
965 | return ret; | |
966 | } | |
967 | ||
5197424c OZ |
968 | static int nexio_init(struct usbtouch_usb *usbtouch) |
969 | { | |
970 | struct usb_device *dev = interface_to_usbdev(usbtouch->interface); | |
971 | struct usb_host_interface *interface = usbtouch->interface->cur_altsetting; | |
a8aef622 | 972 | struct nexio_priv *priv = usbtouch->priv; |
5197424c OZ |
973 | int ret = -ENOMEM; |
974 | int actual_len, i; | |
5197424c OZ |
975 | char *firmware_ver = NULL, *device_name = NULL; |
976 | int input_ep = 0, output_ep = 0; | |
977 | ||
978 | /* find first input and output endpoint */ | |
979 | for (i = 0; i < interface->desc.bNumEndpoints; i++) { | |
980 | if (!input_ep && | |
981 | usb_endpoint_dir_in(&interface->endpoint[i].desc)) | |
982 | input_ep = interface->endpoint[i].desc.bEndpointAddress; | |
983 | if (!output_ep && | |
984 | usb_endpoint_dir_out(&interface->endpoint[i].desc)) | |
985 | output_ep = interface->endpoint[i].desc.bEndpointAddress; | |
986 | } | |
987 | if (!input_ep || !output_ep) | |
988 | return -ENXIO; | |
989 | ||
d04f9393 | 990 | u8 *buf __free(kfree) = kmalloc(NEXIO_BUFSIZE, GFP_NOIO); |
5197424c | 991 | if (!buf) |
d04f9393 | 992 | return -ENOMEM; |
5197424c OZ |
993 | |
994 | /* two empty reads */ | |
995 | for (i = 0; i < 2; i++) { | |
996 | ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep), | |
997 | buf, NEXIO_BUFSIZE, &actual_len, | |
998 | NEXIO_TIMEOUT); | |
999 | if (ret < 0) | |
d04f9393 | 1000 | return ret; |
5197424c OZ |
1001 | } |
1002 | ||
1003 | /* send init command */ | |
1004 | memcpy(buf, nexio_init_pkt, sizeof(nexio_init_pkt)); | |
1005 | ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, output_ep), | |
1006 | buf, sizeof(nexio_init_pkt), &actual_len, | |
1007 | NEXIO_TIMEOUT); | |
1008 | if (ret < 0) | |
d04f9393 | 1009 | return ret; |
5197424c OZ |
1010 | |
1011 | /* read replies */ | |
1012 | for (i = 0; i < 3; i++) { | |
1013 | memset(buf, 0, NEXIO_BUFSIZE); | |
1014 | ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep), | |
1015 | buf, NEXIO_BUFSIZE, &actual_len, | |
1016 | NEXIO_TIMEOUT); | |
1017 | if (ret < 0 || actual_len < 1 || buf[1] != actual_len) | |
1018 | continue; | |
1019 | switch (buf[0]) { | |
1020 | case 0x83: /* firmware version */ | |
1021 | if (!firmware_ver) | |
a8aef622 | 1022 | firmware_ver = kstrdup(&buf[2], GFP_NOIO); |
5197424c OZ |
1023 | break; |
1024 | case 0x84: /* device name */ | |
1025 | if (!device_name) | |
a8aef622 | 1026 | device_name = kstrdup(&buf[2], GFP_NOIO); |
5197424c OZ |
1027 | break; |
1028 | } | |
1029 | } | |
1030 | ||
1031 | printk(KERN_INFO "Nexio device: %s, firmware version: %s\n", | |
1032 | device_name, firmware_ver); | |
1033 | ||
1034 | kfree(firmware_ver); | |
1035 | kfree(device_name); | |
1036 | ||
5197424c OZ |
1037 | usb_fill_bulk_urb(priv->ack, dev, usb_sndbulkpipe(dev, output_ep), |
1038 | priv->ack_buf, sizeof(nexio_ack_pkt), | |
1039 | nexio_ack_complete, usbtouch); | |
5197424c | 1040 | |
d04f9393 | 1041 | return 0; |
5197424c OZ |
1042 | } |
1043 | ||
1044 | static void nexio_exit(struct usbtouch_usb *usbtouch) | |
1045 | { | |
1046 | struct nexio_priv *priv = usbtouch->priv; | |
1047 | ||
1048 | usb_kill_urb(priv->ack); | |
1049 | usb_free_urb(priv->ack); | |
1050 | kfree(priv->ack_buf); | |
1051 | kfree(priv); | |
1052 | } | |
1053 | ||
1054 | static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) | |
1055 | { | |
33f93726 | 1056 | struct device *dev = &usbtouch->interface->dev; |
5197424c OZ |
1057 | struct nexio_touch_packet *packet = (void *) pkt; |
1058 | struct nexio_priv *priv = usbtouch->priv; | |
4aa5bbec DT |
1059 | unsigned int data_len = be16_to_cpu(packet->data_len); |
1060 | unsigned int x_len = be16_to_cpu(packet->x_len); | |
1061 | unsigned int y_len = be16_to_cpu(packet->y_len); | |
1062 | int x, y, begin_x, begin_y, end_x, end_y, w, h, ret; | |
5197424c OZ |
1063 | |
1064 | /* got touch data? */ | |
1065 | if ((pkt[0] & 0xe0) != 0xe0) | |
1066 | return 0; | |
1067 | ||
4aa5bbec DT |
1068 | if (data_len > 0xff) |
1069 | data_len -= 0x100; | |
1070 | if (x_len > 0xff) | |
1071 | x_len -= 0x80; | |
388bbcad | 1072 | |
5197424c OZ |
1073 | /* send ACK */ |
1074 | ret = usb_submit_urb(priv->ack, GFP_ATOMIC); | |
33f93726 LJ |
1075 | if (ret) |
1076 | dev_warn(dev, "Failed to submit ACK URB: %d\n", ret); | |
5197424c | 1077 | |
830f06c0 | 1078 | if (!input_abs_get_max(usbtouch->input, ABS_X)) { |
4aa5bbec | 1079 | input_set_abs_params(usbtouch->input, ABS_X, |
830f06c0 | 1080 | 0, 2 * x_len, 0, 0); |
4aa5bbec | 1081 | input_set_abs_params(usbtouch->input, ABS_Y, |
830f06c0 | 1082 | 0, 2 * y_len, 0, 0); |
5197424c OZ |
1083 | } |
1084 | /* | |
1085 | * The device reports state of IR sensors on X and Y axes. | |
1086 | * Each byte represents "darkness" percentage (0-100) of one element. | |
1087 | * 17" touchscreen reports only 64 x 52 bytes so the resolution is low. | |
1088 | * This also means that there's a limited multi-touch capability but | |
1089 | * it's disabled (and untested) here as there's no X driver for that. | |
1090 | */ | |
1091 | begin_x = end_x = begin_y = end_y = -1; | |
4aa5bbec | 1092 | for (x = 0; x < x_len; x++) { |
5197424c OZ |
1093 | if (begin_x == -1 && packet->data[x] > NEXIO_THRESHOLD) { |
1094 | begin_x = x; | |
1095 | continue; | |
1096 | } | |
1097 | if (end_x == -1 && begin_x != -1 && packet->data[x] < NEXIO_THRESHOLD) { | |
1098 | end_x = x - 1; | |
4aa5bbec | 1099 | for (y = x_len; y < data_len; y++) { |
5197424c | 1100 | if (begin_y == -1 && packet->data[y] > NEXIO_THRESHOLD) { |
4aa5bbec | 1101 | begin_y = y - x_len; |
5197424c OZ |
1102 | continue; |
1103 | } | |
1104 | if (end_y == -1 && | |
1105 | begin_y != -1 && packet->data[y] < NEXIO_THRESHOLD) { | |
4aa5bbec | 1106 | end_y = y - 1 - x_len; |
5197424c OZ |
1107 | w = end_x - begin_x; |
1108 | h = end_y - begin_y; | |
1109 | #if 0 | |
1110 | /* multi-touch */ | |
1111 | input_report_abs(usbtouch->input, | |
1112 | ABS_MT_TOUCH_MAJOR, max(w,h)); | |
1113 | input_report_abs(usbtouch->input, | |
1114 | ABS_MT_TOUCH_MINOR, min(x,h)); | |
1115 | input_report_abs(usbtouch->input, | |
1116 | ABS_MT_POSITION_X, 2*begin_x+w); | |
1117 | input_report_abs(usbtouch->input, | |
1118 | ABS_MT_POSITION_Y, 2*begin_y+h); | |
1119 | input_report_abs(usbtouch->input, | |
1120 | ABS_MT_ORIENTATION, w > h); | |
1121 | input_mt_sync(usbtouch->input); | |
1122 | #endif | |
1123 | /* single touch */ | |
1124 | usbtouch->x = 2 * begin_x + w; | |
1125 | usbtouch->y = 2 * begin_y + h; | |
1126 | usbtouch->touch = packet->flags & 0x01; | |
1127 | begin_y = end_y = -1; | |
1128 | return 1; | |
1129 | } | |
1130 | } | |
1131 | begin_x = end_x = -1; | |
1132 | } | |
1133 | ||
1134 | } | |
1135 | return 0; | |
1136 | } | |
7f787df1 DT |
1137 | |
1138 | static const struct usbtouch_device_info nexio_dev_info = { | |
1139 | .rept_size = 1024, | |
1140 | .irq_always = true, | |
1141 | .read_data = nexio_read_data, | |
1142 | .alloc = nexio_alloc, | |
1143 | .init = nexio_init, | |
1144 | .exit = nexio_exit, | |
1145 | }; | |
5197424c OZ |
1146 | #endif |
1147 | ||
1148 | ||
d2cc817a MG |
1149 | /***************************************************************************** |
1150 | * ELO part | |
1151 | */ | |
1152 | ||
1153 | #ifdef CONFIG_TOUCHSCREEN_USB_ELO | |
1154 | ||
1155 | static int elo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |
1156 | { | |
1157 | dev->x = (pkt[3] << 8) | pkt[2]; | |
1158 | dev->y = (pkt[5] << 8) | pkt[4]; | |
1159 | dev->touch = pkt[6] > 0; | |
1160 | dev->press = pkt[6]; | |
1161 | ||
1162 | return 1; | |
1163 | } | |
1d3e2023 | 1164 | |
7f787df1 DT |
1165 | static const struct usbtouch_device_info elo_dev_info = { |
1166 | .min_xc = 0x0, | |
1167 | .max_xc = 0x0fff, | |
1168 | .min_yc = 0x0, | |
1169 | .max_yc = 0x0fff, | |
1170 | .max_press = 0xff, | |
1171 | .rept_size = 8, | |
1172 | .read_data = elo_read_data, | |
1d3e2023 | 1173 | }; |
7f787df1 | 1174 | #endif |
1d3e2023 DR |
1175 | |
1176 | ||
1177 | /***************************************************************************** | |
1178 | * Generic Part | |
1179 | */ | |
1180 | static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, | |
7d12e780 | 1181 | unsigned char *pkt, int len) |
1d3e2023 | 1182 | { |
830f06c0 | 1183 | const struct usbtouch_device_info *type = usbtouch->type; |
1d3e2023 | 1184 | |
c9d8c2b3 | 1185 | if (!type->read_data(usbtouch, pkt)) |
830f06c0 | 1186 | return; |
1d3e2023 | 1187 | |
c9d8c2b3 | 1188 | input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch); |
1d3e2023 DR |
1189 | |
1190 | if (swap_xy) { | |
c9d8c2b3 DR |
1191 | input_report_abs(usbtouch->input, ABS_X, usbtouch->y); |
1192 | input_report_abs(usbtouch->input, ABS_Y, usbtouch->x); | |
1d3e2023 | 1193 | } else { |
c9d8c2b3 DR |
1194 | input_report_abs(usbtouch->input, ABS_X, usbtouch->x); |
1195 | input_report_abs(usbtouch->input, ABS_Y, usbtouch->y); | |
1d3e2023 DR |
1196 | } |
1197 | if (type->max_press) | |
c9d8c2b3 | 1198 | input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press); |
1d3e2023 DR |
1199 | input_sync(usbtouch->input); |
1200 | } | |
1201 | ||
1202 | ||
5d892665 DR |
1203 | #ifdef MULTI_PACKET |
1204 | static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, | |
5d892665 DR |
1205 | unsigned char *pkt, int len) |
1206 | { | |
1207 | unsigned char *buffer; | |
1208 | int pkt_len, pos, buf_len, tmp; | |
1209 | ||
1210 | /* process buffer */ | |
1211 | if (unlikely(usbtouch->buf_len)) { | |
1212 | /* try to get size */ | |
1213 | pkt_len = usbtouch->type->get_pkt_len( | |
1214 | usbtouch->buffer, usbtouch->buf_len); | |
1215 | ||
1216 | /* drop? */ | |
1217 | if (unlikely(!pkt_len)) | |
1218 | goto out_flush_buf; | |
1219 | ||
1220 | /* need to append -pkt_len bytes before able to get size */ | |
1221 | if (unlikely(pkt_len < 0)) { | |
1222 | int append = -pkt_len; | |
1223 | if (unlikely(append > len)) | |
1224 | append = len; | |
1225 | if (usbtouch->buf_len + append >= usbtouch->type->rept_size) | |
1226 | goto out_flush_buf; | |
1227 | memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append); | |
1228 | usbtouch->buf_len += append; | |
1229 | ||
1230 | pkt_len = usbtouch->type->get_pkt_len( | |
1231 | usbtouch->buffer, usbtouch->buf_len); | |
1232 | if (pkt_len < 0) | |
1233 | return; | |
1234 | } | |
1235 | ||
1236 | /* append */ | |
1237 | tmp = pkt_len - usbtouch->buf_len; | |
1238 | if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size) | |
1239 | goto out_flush_buf; | |
1240 | memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp); | |
7d12e780 | 1241 | usbtouch_process_pkt(usbtouch, usbtouch->buffer, pkt_len); |
5d892665 DR |
1242 | |
1243 | buffer = pkt + tmp; | |
1244 | buf_len = len - tmp; | |
1245 | } else { | |
1246 | buffer = pkt; | |
1247 | buf_len = len; | |
1248 | } | |
1249 | ||
1250 | /* loop over the received packet, process */ | |
1251 | pos = 0; | |
1252 | while (pos < buf_len) { | |
1253 | /* get packet len */ | |
62aa366d DR |
1254 | pkt_len = usbtouch->type->get_pkt_len(buffer + pos, |
1255 | buf_len - pos); | |
5d892665 | 1256 | |
62aa366d DR |
1257 | /* unknown packet: skip one byte */ |
1258 | if (unlikely(!pkt_len)) { | |
1259 | pos++; | |
1260 | continue; | |
1261 | } | |
5d892665 DR |
1262 | |
1263 | /* full packet: process */ | |
1264 | if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) { | |
7d12e780 | 1265 | usbtouch_process_pkt(usbtouch, buffer + pos, pkt_len); |
5d892665 DR |
1266 | } else { |
1267 | /* incomplete packet: save in buffer */ | |
1268 | memcpy(usbtouch->buffer, buffer + pos, buf_len - pos); | |
1269 | usbtouch->buf_len = buf_len - pos; | |
1270 | return; | |
1271 | } | |
1272 | pos += pkt_len; | |
1273 | } | |
1274 | ||
1275 | out_flush_buf: | |
1276 | usbtouch->buf_len = 0; | |
1277 | return; | |
1278 | } | |
fbb1c922 DT |
1279 | #else |
1280 | static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, | |
1281 | unsigned char *pkt, int len) | |
1282 | { | |
1283 | dev_WARN_ONCE(&usbtouch->interface->dev, 1, | |
1284 | "Protocol has ->get_pkt_len() without #define MULTI_PACKET"); | |
1285 | } | |
5d892665 DR |
1286 | #endif |
1287 | ||
7d12e780 | 1288 | static void usbtouch_irq(struct urb *urb) |
1d3e2023 DR |
1289 | { |
1290 | struct usbtouch_usb *usbtouch = urb->context; | |
0a5ebc88 | 1291 | struct device *dev = &usbtouch->interface->dev; |
1d3e2023 DR |
1292 | int retval; |
1293 | ||
1294 | switch (urb->status) { | |
1295 | case 0: | |
1296 | /* success */ | |
1297 | break; | |
38e2bfc9 | 1298 | case -ETIME: |
1d3e2023 | 1299 | /* this urb is timing out */ |
b741ab9d GKH |
1300 | dev_dbg(dev, |
1301 | "%s - urb timed out - was the device unplugged?\n", | |
1302 | __func__); | |
1d3e2023 DR |
1303 | return; |
1304 | case -ECONNRESET: | |
1305 | case -ENOENT: | |
1306 | case -ESHUTDOWN: | |
5197424c | 1307 | case -EPIPE: |
1d3e2023 | 1308 | /* this urb is terminated, clean up */ |
b741ab9d GKH |
1309 | dev_dbg(dev, "%s - urb shutting down with status: %d\n", |
1310 | __func__, urb->status); | |
1d3e2023 DR |
1311 | return; |
1312 | default: | |
b741ab9d GKH |
1313 | dev_dbg(dev, "%s - nonzero urb status received: %d\n", |
1314 | __func__, urb->status); | |
1d3e2023 DR |
1315 | goto exit; |
1316 | } | |
1317 | ||
fbb1c922 | 1318 | usbtouch->process_pkt(usbtouch, usbtouch->data, urb->actual_length); |
1d3e2023 DR |
1319 | |
1320 | exit: | |
5d9efc59 | 1321 | usb_mark_last_busy(interface_to_usbdev(usbtouch->interface)); |
1d3e2023 DR |
1322 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
1323 | if (retval) | |
0a5ebc88 | 1324 | dev_err(dev, "%s - usb_submit_urb failed with result: %d\n", |
e27ad0fe | 1325 | __func__, retval); |
1d3e2023 DR |
1326 | } |
1327 | ||
f784adb6 DT |
1328 | static int usbtouch_start_io(struct usbtouch_usb *usbtouch) |
1329 | { | |
1330 | guard(mutex)(&usbtouch->pm_mutex); | |
1331 | ||
1332 | if (!usbtouch->type->irq_always) | |
1333 | if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) | |
1334 | return -EIO; | |
1335 | ||
1336 | usbtouch->interface->needs_remote_wakeup = 1; | |
1337 | usbtouch->is_open = true; | |
1338 | ||
1339 | return 0; | |
1340 | } | |
1341 | ||
1d3e2023 DR |
1342 | static int usbtouch_open(struct input_dev *input) |
1343 | { | |
7791bdae | 1344 | struct usbtouch_usb *usbtouch = input_get_drvdata(input); |
5d9efc59 | 1345 | int r; |
1d3e2023 | 1346 | |
fea4d14b | 1347 | usbtouch->irq->dev = interface_to_usbdev(usbtouch->interface); |
1d3e2023 | 1348 | |
5d9efc59 | 1349 | r = usb_autopm_get_interface(usbtouch->interface) ? -EIO : 0; |
f784adb6 DT |
1350 | if (r) |
1351 | return r; | |
1352 | ||
1353 | r = usbtouch_start_io(usbtouch); | |
1d3e2023 | 1354 | |
5d9efc59 | 1355 | usb_autopm_put_interface(usbtouch->interface); |
5d9efc59 | 1356 | return r; |
1d3e2023 DR |
1357 | } |
1358 | ||
1359 | static void usbtouch_close(struct input_dev *input) | |
1360 | { | |
7791bdae | 1361 | struct usbtouch_usb *usbtouch = input_get_drvdata(input); |
5d9efc59 | 1362 | int r; |
1d3e2023 | 1363 | |
f784adb6 DT |
1364 | scoped_guard(mutex, &usbtouch->pm_mutex) { |
1365 | if (!usbtouch->type->irq_always) | |
1366 | usb_kill_urb(usbtouch->irq); | |
1367 | usbtouch->is_open = false; | |
1368 | } | |
12e510db | 1369 | |
5d9efc59 ON |
1370 | r = usb_autopm_get_interface(usbtouch->interface); |
1371 | usbtouch->interface->needs_remote_wakeup = 0; | |
1372 | if (!r) | |
1373 | usb_autopm_put_interface(usbtouch->interface); | |
1d3e2023 DR |
1374 | } |
1375 | ||
f784adb6 | 1376 | static int usbtouch_suspend(struct usb_interface *intf, pm_message_t message) |
ed4299e1 ON |
1377 | { |
1378 | struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); | |
1379 | ||
1380 | usb_kill_urb(usbtouch->irq); | |
1381 | ||
1382 | return 0; | |
1383 | } | |
1384 | ||
1385 | static int usbtouch_resume(struct usb_interface *intf) | |
1386 | { | |
1387 | struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); | |
ed4299e1 | 1388 | |
f784adb6 DT |
1389 | guard(mutex)(&usbtouch->pm_mutex); |
1390 | ||
85f46fbf | 1391 | if (usbtouch->is_open || usbtouch->type->irq_always) |
f784adb6 | 1392 | return usb_submit_urb(usbtouch->irq, GFP_NOIO); |
ed4299e1 | 1393 | |
f784adb6 | 1394 | return 0; |
ed4299e1 | 1395 | } |
1d3e2023 | 1396 | |
a8aef622 ON |
1397 | static int usbtouch_reset_resume(struct usb_interface *intf) |
1398 | { | |
1399 | struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); | |
f784adb6 | 1400 | int err; |
a8aef622 ON |
1401 | |
1402 | /* reinit the device */ | |
1403 | if (usbtouch->type->init) { | |
1404 | err = usbtouch->type->init(usbtouch); | |
1405 | if (err) { | |
0a5ebc88 | 1406 | dev_dbg(&intf->dev, |
b741ab9d GKH |
1407 | "%s - type->init() failed, err: %d\n", |
1408 | __func__, err); | |
a8aef622 ON |
1409 | return err; |
1410 | } | |
1411 | } | |
1412 | ||
1413 | /* restart IO if needed */ | |
f784adb6 DT |
1414 | guard(mutex)(&usbtouch->pm_mutex); |
1415 | ||
85f46fbf | 1416 | if (usbtouch->is_open) |
f784adb6 | 1417 | return usb_submit_urb(usbtouch->irq, GFP_NOIO); |
a8aef622 | 1418 | |
f784adb6 | 1419 | return 0; |
a8aef622 ON |
1420 | } |
1421 | ||
1d3e2023 DR |
1422 | static void usbtouch_free_buffers(struct usb_device *udev, |
1423 | struct usbtouch_usb *usbtouch) | |
1424 | { | |
4ef38351 | 1425 | usb_free_coherent(udev, usbtouch->data_size, |
997ea58e | 1426 | usbtouch->data, usbtouch->data_dma); |
1d3e2023 DR |
1427 | kfree(usbtouch->buffer); |
1428 | } | |
1429 | ||
f4a5e359 OZ |
1430 | static struct usb_endpoint_descriptor * |
1431 | usbtouch_get_input_endpoint(struct usb_host_interface *interface) | |
1432 | { | |
1433 | int i; | |
1434 | ||
1435 | for (i = 0; i < interface->desc.bNumEndpoints; i++) | |
1436 | if (usb_endpoint_dir_in(&interface->endpoint[i].desc)) | |
1437 | return &interface->endpoint[i].desc; | |
1438 | ||
1439 | return NULL; | |
1440 | } | |
1d3e2023 DR |
1441 | |
1442 | static int usbtouch_probe(struct usb_interface *intf, | |
1443 | const struct usb_device_id *id) | |
1444 | { | |
1445 | struct usbtouch_usb *usbtouch; | |
1446 | struct input_dev *input_dev; | |
1d3e2023 DR |
1447 | struct usb_endpoint_descriptor *endpoint; |
1448 | struct usb_device *udev = interface_to_usbdev(intf); | |
830f06c0 | 1449 | const struct usbtouch_device_info *type; |
5d892665 | 1450 | int err = -ENOMEM; |
ec42d448 DR |
1451 | |
1452 | /* some devices are ignored */ | |
7f787df1 DT |
1453 | type = (const struct usbtouch_device_info *)id->driver_info; |
1454 | if (!type) | |
039d4ed3 JH |
1455 | return -ENODEV; |
1456 | ||
f4a5e359 OZ |
1457 | endpoint = usbtouch_get_input_endpoint(intf->cur_altsetting); |
1458 | if (!endpoint) | |
1459 | return -ENXIO; | |
1d3e2023 | 1460 | |
f81d03d4 | 1461 | usbtouch = kzalloc(sizeof(*usbtouch), GFP_KERNEL); |
1d3e2023 DR |
1462 | input_dev = input_allocate_device(); |
1463 | if (!usbtouch || !input_dev) | |
1464 | goto out_free; | |
1465 | ||
b55d996f | 1466 | mutex_init(&usbtouch->pm_mutex); |
1d3e2023 | 1467 | usbtouch->type = type; |
1d3e2023 | 1468 | |
4ef38351 CE |
1469 | usbtouch->data_size = type->rept_size; |
1470 | if (type->get_pkt_len) { | |
1471 | /* | |
1472 | * When dealing with variable-length packets we should | |
1473 | * not request more than wMaxPacketSize bytes at once | |
1474 | * as we do not know if there is more data coming or | |
1475 | * we filled exactly wMaxPacketSize bytes and there is | |
1476 | * nothing else. | |
1477 | */ | |
1478 | usbtouch->data_size = min(usbtouch->data_size, | |
1479 | usb_endpoint_maxp(endpoint)); | |
1480 | } | |
1481 | ||
1482 | usbtouch->data = usb_alloc_coherent(udev, usbtouch->data_size, | |
997ea58e | 1483 | GFP_KERNEL, &usbtouch->data_dma); |
1d3e2023 DR |
1484 | if (!usbtouch->data) |
1485 | goto out_free; | |
1486 | ||
62aa366d | 1487 | if (type->get_pkt_len) { |
1d3e2023 DR |
1488 | usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL); |
1489 | if (!usbtouch->buffer) | |
1490 | goto out_free_buffers; | |
fbb1c922 DT |
1491 | usbtouch->process_pkt = usbtouch_process_multi; |
1492 | } else { | |
1493 | usbtouch->process_pkt = usbtouch_process_pkt; | |
1d3e2023 DR |
1494 | } |
1495 | ||
1496 | usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL); | |
1497 | if (!usbtouch->irq) { | |
b741ab9d GKH |
1498 | dev_dbg(&intf->dev, |
1499 | "%s - usb_alloc_urb failed: usbtouch->irq\n", __func__); | |
1d3e2023 DR |
1500 | goto out_free_buffers; |
1501 | } | |
1502 | ||
fea4d14b | 1503 | usbtouch->interface = intf; |
1d3e2023 DR |
1504 | usbtouch->input = input_dev; |
1505 | ||
1506 | if (udev->manufacturer) | |
a9f08ad7 | 1507 | strscpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name)); |
1d3e2023 DR |
1508 | |
1509 | if (udev->product) { | |
1510 | if (udev->manufacturer) | |
1511 | strlcat(usbtouch->name, " ", sizeof(usbtouch->name)); | |
1512 | strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name)); | |
1513 | } | |
1514 | ||
1515 | if (!strlen(usbtouch->name)) | |
1516 | snprintf(usbtouch->name, sizeof(usbtouch->name), | |
1517 | "USB Touchscreen %04x:%04x", | |
1518 | le16_to_cpu(udev->descriptor.idVendor), | |
1519 | le16_to_cpu(udev->descriptor.idProduct)); | |
1520 | ||
1521 | usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys)); | |
7b6dff98 | 1522 | strlcat(usbtouch->phys, "/input0", sizeof(usbtouch->phys)); |
1d3e2023 DR |
1523 | |
1524 | input_dev->name = usbtouch->name; | |
1525 | input_dev->phys = usbtouch->phys; | |
1526 | usb_to_input_id(udev, &input_dev->id); | |
c0f82d57 | 1527 | input_dev->dev.parent = &intf->dev; |
7791bdae DT |
1528 | |
1529 | input_set_drvdata(input_dev, usbtouch); | |
1530 | ||
1d3e2023 DR |
1531 | input_dev->open = usbtouch_open; |
1532 | input_dev->close = usbtouch_close; | |
1533 | ||
7b19ada2 JS |
1534 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
1535 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | |
1d3e2023 DR |
1536 | input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0); |
1537 | input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0); | |
1538 | if (type->max_press) | |
1539 | input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press, | |
1540 | type->max_press, 0, 0); | |
1541 | ||
5197424c OZ |
1542 | if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT) |
1543 | usb_fill_int_urb(usbtouch->irq, udev, | |
fea4d14b | 1544 | usb_rcvintpipe(udev, endpoint->bEndpointAddress), |
4ef38351 | 1545 | usbtouch->data, usbtouch->data_size, |
1d3e2023 | 1546 | usbtouch_irq, usbtouch, endpoint->bInterval); |
5197424c OZ |
1547 | else |
1548 | usb_fill_bulk_urb(usbtouch->irq, udev, | |
1549 | usb_rcvbulkpipe(udev, endpoint->bEndpointAddress), | |
4ef38351 | 1550 | usbtouch->data, usbtouch->data_size, |
5197424c | 1551 | usbtouch_irq, usbtouch); |
1d3e2023 | 1552 | |
fea4d14b | 1553 | usbtouch->irq->dev = udev; |
1d3e2023 DR |
1554 | usbtouch->irq->transfer_dma = usbtouch->data_dma; |
1555 | usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | |
1556 | ||
a8aef622 ON |
1557 | /* device specific allocations */ |
1558 | if (type->alloc) { | |
1559 | err = type->alloc(usbtouch); | |
1560 | if (err) { | |
b741ab9d GKH |
1561 | dev_dbg(&intf->dev, |
1562 | "%s - type->alloc() failed, err: %d\n", | |
1563 | __func__, err); | |
a8aef622 ON |
1564 | goto out_free_urb; |
1565 | } | |
1566 | } | |
1567 | ||
1568 | /* device specific initialisation*/ | |
1d3e2023 DR |
1569 | if (type->init) { |
1570 | err = type->init(usbtouch); | |
1571 | if (err) { | |
b741ab9d GKH |
1572 | dev_dbg(&intf->dev, |
1573 | "%s - type->init() failed, err: %d\n", | |
1574 | __func__, err); | |
a8aef622 | 1575 | goto out_do_exit; |
1d3e2023 DR |
1576 | } |
1577 | } | |
1578 | ||
1579 | err = input_register_device(usbtouch->input); | |
1580 | if (err) { | |
b741ab9d GKH |
1581 | dev_dbg(&intf->dev, |
1582 | "%s - input_register_device failed, err: %d\n", | |
1583 | __func__, err); | |
5197424c | 1584 | goto out_do_exit; |
1d3e2023 DR |
1585 | } |
1586 | ||
1587 | usb_set_intfdata(intf, usbtouch); | |
1588 | ||
1e87a430 | 1589 | if (usbtouch->type->irq_always) { |
5d9efc59 ON |
1590 | /* this can't fail */ |
1591 | usb_autopm_get_interface(intf); | |
1e87a430 OZ |
1592 | err = usb_submit_urb(usbtouch->irq, GFP_KERNEL); |
1593 | if (err) { | |
5d9efc59 | 1594 | usb_autopm_put_interface(intf); |
0a5ebc88 | 1595 | dev_err(&intf->dev, |
e27ad0fe GKH |
1596 | "%s - usb_submit_urb failed with result: %d\n", |
1597 | __func__, err); | |
1e87a430 OZ |
1598 | goto out_unregister_input; |
1599 | } | |
1600 | } | |
2330ed18 | 1601 | |
1d3e2023 DR |
1602 | return 0; |
1603 | ||
1e87a430 OZ |
1604 | out_unregister_input: |
1605 | input_unregister_device(input_dev); | |
1606 | input_dev = NULL; | |
5197424c OZ |
1607 | out_do_exit: |
1608 | if (type->exit) | |
1609 | type->exit(usbtouch); | |
1e87a430 OZ |
1610 | out_free_urb: |
1611 | usb_free_urb(usbtouch->irq); | |
1d3e2023 DR |
1612 | out_free_buffers: |
1613 | usbtouch_free_buffers(udev, usbtouch); | |
1614 | out_free: | |
1615 | input_free_device(input_dev); | |
1616 | kfree(usbtouch); | |
5d892665 | 1617 | return err; |
1d3e2023 DR |
1618 | } |
1619 | ||
1620 | static void usbtouch_disconnect(struct usb_interface *intf) | |
1621 | { | |
1622 | struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); | |
1623 | ||
1d3e2023 DR |
1624 | if (!usbtouch) |
1625 | return; | |
1626 | ||
0a5ebc88 | 1627 | dev_dbg(&intf->dev, |
b741ab9d GKH |
1628 | "%s - usbtouch is initialized, cleaning up\n", __func__); |
1629 | ||
1d3e2023 | 1630 | usb_set_intfdata(intf, NULL); |
722232bc | 1631 | /* this will stop IO via close */ |
1d3e2023 DR |
1632 | input_unregister_device(usbtouch->input); |
1633 | usb_free_urb(usbtouch->irq); | |
5197424c OZ |
1634 | if (usbtouch->type->exit) |
1635 | usbtouch->type->exit(usbtouch); | |
1d3e2023 DR |
1636 | usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); |
1637 | kfree(usbtouch); | |
1638 | } | |
1639 | ||
6797e19d DT |
1640 | static const struct attribute_group *usbtouch_groups[] = { |
1641 | #ifdef CONFIG_TOUCHSCREEN_USB_3M | |
1642 | &mtouch_attr_group, | |
1643 | #endif | |
1644 | NULL | |
1645 | }; | |
1646 | ||
ca95a47e DT |
1647 | static const struct usb_device_id usbtouch_devices[] = { |
1648 | #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX | |
1649 | /* ignore the HID capable devices, handled by usbhid */ | |
7f787df1 DT |
1650 | { USB_DEVICE_INTERFACE_CLASS(0x0eef, 0x0001, USB_INTERFACE_CLASS_HID), |
1651 | .driver_info = 0 }, | |
1652 | { USB_DEVICE_INTERFACE_CLASS(0x0eef, 0x0002, USB_INTERFACE_CLASS_HID), | |
1653 | .driver_info = 0 }, | |
ca95a47e DT |
1654 | |
1655 | /* normal device IDs */ | |
7f787df1 DT |
1656 | { USB_DEVICE(0x3823, 0x0001), |
1657 | .driver_info = (kernel_ulong_t)&egalax_dev_info }, | |
1658 | { USB_DEVICE(0x3823, 0x0002), | |
1659 | .driver_info = (kernel_ulong_t)&egalax_dev_info }, | |
1660 | { USB_DEVICE(0x0123, 0x0001), | |
1661 | .driver_info = (kernel_ulong_t)&egalax_dev_info }, | |
1662 | { USB_DEVICE(0x0eef, 0x0001), | |
1663 | .driver_info = (kernel_ulong_t)&egalax_dev_info }, | |
1664 | { USB_DEVICE(0x0eef, 0x0002), | |
1665 | .driver_info = (kernel_ulong_t)&egalax_dev_info }, | |
1666 | { USB_DEVICE(0x1234, 0x0001), | |
1667 | .driver_info = (kernel_ulong_t)&egalax_dev_info }, | |
1668 | { USB_DEVICE(0x1234, 0x0002), | |
1669 | .driver_info = (kernel_ulong_t)&egalax_dev_info }, | |
ca95a47e DT |
1670 | #endif |
1671 | ||
1672 | #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT | |
7f787df1 DT |
1673 | { USB_DEVICE(0x134c, 0x0001), |
1674 | .driver_info = (kernel_ulong_t)&panjit_dev_info }, | |
1675 | { USB_DEVICE(0x134c, 0x0002), | |
1676 | .driver_info = (kernel_ulong_t)&panjit_dev_info }, | |
1677 | { USB_DEVICE(0x134c, 0x0003), | |
1678 | .driver_info = (kernel_ulong_t)&panjit_dev_info }, | |
1679 | { USB_DEVICE(0x134c, 0x0004), | |
1680 | .driver_info = (kernel_ulong_t)&panjit_dev_info }, | |
ca95a47e DT |
1681 | #endif |
1682 | ||
1683 | #ifdef CONFIG_TOUCHSCREEN_USB_3M | |
7f787df1 DT |
1684 | { USB_DEVICE(0x0596, 0x0001), |
1685 | .driver_info = (kernel_ulong_t)&mtouch_dev_info }, | |
ca95a47e DT |
1686 | #endif |
1687 | ||
1688 | #ifdef CONFIG_TOUCHSCREEN_USB_ITM | |
7f787df1 DT |
1689 | { USB_DEVICE(0x0403, 0xf9e9), |
1690 | .driver_info = (kernel_ulong_t)&itm_dev_info }, | |
1691 | { USB_DEVICE(0x16e3, 0xf9e9), | |
1692 | .driver_info = (kernel_ulong_t)&itm_dev_info }, | |
ca95a47e DT |
1693 | #endif |
1694 | ||
1695 | #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO | |
7f787df1 DT |
1696 | { USB_DEVICE(0x1234, 0x5678), |
1697 | .driver_info = (kernel_ulong_t)&eturbo_dev_info }, | |
ca95a47e DT |
1698 | #endif |
1699 | ||
1700 | #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE | |
7f787df1 DT |
1701 | { USB_DEVICE(0x0637, 0x0001), |
1702 | .driver_info = (kernel_ulong_t)&gunze_dev_info }, | |
ca95a47e DT |
1703 | #endif |
1704 | ||
1705 | #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 | |
7f787df1 DT |
1706 | { USB_DEVICE(0x0afa, 0x03e8), |
1707 | .driver_info = (kernel_ulong_t)&dmc_tsc10_dev_info }, | |
ca95a47e DT |
1708 | #endif |
1709 | ||
1710 | #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH | |
7f787df1 DT |
1711 | { USB_DEVICE(0x255e, 0x0001), |
1712 | .driver_info = (kernel_ulong_t)&irtouch_dev_info }, | |
1713 | { USB_DEVICE(0x595a, 0x0001), | |
1714 | .driver_info = (kernel_ulong_t)&irtouch_dev_info }, | |
1715 | { USB_DEVICE(0x6615, 0x0001), | |
1716 | .driver_info = (kernel_ulong_t)&irtouch_dev_info }, | |
1717 | { USB_DEVICE(0x6615, 0x0012), | |
1718 | .driver_info = (kernel_ulong_t)&irtouch_hires_dev_info }, | |
ca95a47e DT |
1719 | #endif |
1720 | ||
1721 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK | |
7f787df1 DT |
1722 | { USB_DEVICE(0x1391, 0x1000), |
1723 | .driver_info = (kernel_ulong_t)&idealtek_dev_info }, | |
ca95a47e DT |
1724 | #endif |
1725 | ||
1726 | #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH | |
7f787df1 DT |
1727 | { USB_DEVICE(0x0dfc, 0x0001), |
1728 | .driver_info = (kernel_ulong_t)&general_touch_dev_info }, | |
ca95a47e DT |
1729 | #endif |
1730 | ||
1731 | #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP | |
7f787df1 DT |
1732 | { USB_DEVICE(0x08f2, 0x007f), |
1733 | .driver_info = (kernel_ulong_t)&gotop_dev_info }, | |
1734 | { USB_DEVICE(0x08f2, 0x00ce), | |
1735 | .driver_info = (kernel_ulong_t)&gotop_dev_info }, | |
1736 | { USB_DEVICE(0x08f2, 0x00f4), | |
1737 | .driver_info = (kernel_ulong_t)&gotop_dev_info }, | |
ca95a47e DT |
1738 | #endif |
1739 | ||
1740 | #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC | |
7f787df1 DT |
1741 | { USB_DEVICE(0x0f92, 0x0001), |
1742 | .driver_info = (kernel_ulong_t)&jastec_dev_info }, | |
ca95a47e DT |
1743 | #endif |
1744 | ||
1745 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | |
7f787df1 DT |
1746 | { USB_DEVICE(0x1ac7, 0x0001), |
1747 | .driver_info = (kernel_ulong_t)&e2i_dev_info }, | |
ca95a47e DT |
1748 | #endif |
1749 | ||
1750 | #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC | |
7f787df1 DT |
1751 | { USB_DEVICE(0x14c8, 0x0003), |
1752 | .driver_info = (kernel_ulong_t)&zytronic_dev_info }, | |
ca95a47e DT |
1753 | #endif |
1754 | ||
1755 | #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB | |
1756 | /* TC5UH */ | |
7f787df1 DT |
1757 | { USB_DEVICE(0x0664, 0x0309), |
1758 | .driver_info = (kernel_ulong_t)&tc45usb_dev_info }, | |
ca95a47e | 1759 | /* TC4UM */ |
7f787df1 DT |
1760 | { USB_DEVICE(0x0664, 0x0306), |
1761 | .driver_info = (kernel_ulong_t)&tc45usb_dev_info }, | |
ca95a47e DT |
1762 | #endif |
1763 | ||
1764 | #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO | |
1765 | /* data interface only */ | |
7f787df1 DT |
1766 | { USB_DEVICE_AND_INTERFACE_INFO(0x10f0, 0x2002, 0x0a, 0x00, 0x00), |
1767 | .driver_info = (kernel_ulong_t)&nexio_dev_info }, | |
1768 | { USB_DEVICE_AND_INTERFACE_INFO(0x1870, 0x0001, 0x0a, 0x00, 0x00), | |
1769 | .driver_info = (kernel_ulong_t)&nexio_dev_info }, | |
ca95a47e DT |
1770 | #endif |
1771 | ||
1772 | #ifdef CONFIG_TOUCHSCREEN_USB_ELO | |
7f787df1 DT |
1773 | { USB_DEVICE(0x04e7, 0x0020), |
1774 | .driver_info = (kernel_ulong_t)&elo_dev_info }, | |
ca95a47e DT |
1775 | #endif |
1776 | ||
1777 | #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH | |
7f787df1 DT |
1778 | { USB_DEVICE(0x7374, 0x0001), |
1779 | .driver_info = (kernel_ulong_t)&etouch_dev_info }, | |
ca95a47e DT |
1780 | #endif |
1781 | ||
7f787df1 | 1782 | { } |
ca95a47e | 1783 | }; |
1d3e2023 DR |
1784 | MODULE_DEVICE_TABLE(usb, usbtouch_devices); |
1785 | ||
1786 | static struct usb_driver usbtouch_driver = { | |
1787 | .name = "usbtouchscreen", | |
1788 | .probe = usbtouch_probe, | |
1789 | .disconnect = usbtouch_disconnect, | |
ed4299e1 ON |
1790 | .suspend = usbtouch_suspend, |
1791 | .resume = usbtouch_resume, | |
a8aef622 | 1792 | .reset_resume = usbtouch_reset_resume, |
1d3e2023 | 1793 | .id_table = usbtouch_devices, |
6797e19d | 1794 | .dev_groups = usbtouch_groups, |
5d9efc59 | 1795 | .supports_autosuspend = 1, |
1d3e2023 DR |
1796 | }; |
1797 | ||
08642e7c | 1798 | module_usb_driver(usbtouch_driver); |
1d3e2023 | 1799 | |
698c03b4 JL |
1800 | MODULE_AUTHOR("Daniel Ritz <daniel.ritz@gmx.ch>"); |
1801 | MODULE_DESCRIPTION("USB Touchscreen Driver"); | |
1d3e2023 DR |
1802 | MODULE_LICENSE("GPL"); |
1803 | ||
1804 | MODULE_ALIAS("touchkitusb"); | |
1805 | MODULE_ALIAS("itmtouch"); | |
1806 | MODULE_ALIAS("mtouchusb"); |