xref: /linux/drivers/input/touchscreen/usbtouchscreen.c (revision 968491709e5b1aaf429428814fff3d932fa90b60)
1d05e84e6SDmitry Torokhov /******************************************************************************
2d05e84e6SDmitry Torokhov  * usbtouchscreen.c
3d05e84e6SDmitry Torokhov  * Driver for USB Touchscreens, supporting those devices:
4d05e84e6SDmitry Torokhov  *  - eGalax Touchkit
5d05e84e6SDmitry Torokhov  *    includes eTurboTouch CT-410/510/700
6d05e84e6SDmitry Torokhov  *  - 3M/Microtouch  EX II series
7d05e84e6SDmitry Torokhov  *  - ITM
8d05e84e6SDmitry Torokhov  *  - PanJit TouchSet
9d05e84e6SDmitry Torokhov  *  - eTurboTouch
10d05e84e6SDmitry Torokhov  *  - Gunze AHL61
11d05e84e6SDmitry Torokhov  *  - DMC TSC-10/25
12df561fcdSOndrej Zary  *  - IRTOUCHSYSTEMS/UNITOP
13a14a8401SOndrej Zary  *  - IdealTEK URTC1000
1462aa366dSDaniel Ritz  *  - General Touch
1514e40206SJerrold Jones  *  - GoTop Super_Q2/GogoPen/PenPower tablets
16f7370699SJim Persson  *  - JASTEC USB touch controller/DigiTech DTR-02U
172330ed18SDaniel Silverstone  *  - Zytronic capacitive touchscreen
185197424cSOndrej Zary  *  - NEXIO/iNexio
19d2cc817aSMichael Gebetsroither  *  - Elo TouchSystems 2700 IntelliTouch
20aa87512fSArmando Visconti  *  - EasyTouch USB Dual/Multi touch controller from Data Modul
21d05e84e6SDmitry Torokhov  *
2214e40206SJerrold Jones  * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch>
23d05e84e6SDmitry Torokhov  * Copyright (C) by Todd E. Johnson (mtouchusb.c)
24d05e84e6SDmitry Torokhov  *
25d05e84e6SDmitry Torokhov  * This program is free software; you can redistribute it and/or
26d05e84e6SDmitry Torokhov  * modify it under the terms of the GNU General Public License as
27d05e84e6SDmitry Torokhov  * published by the Free Software Foundation; either version 2 of the
28d05e84e6SDmitry Torokhov  * License, or (at your option) any later version.
29d05e84e6SDmitry Torokhov  *
30d05e84e6SDmitry Torokhov  * This program is distributed in the hope that it will be useful, but
31d05e84e6SDmitry Torokhov  * WITHOUT ANY WARRANTY; without even the implied warranty of
32d05e84e6SDmitry Torokhov  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
33d05e84e6SDmitry Torokhov  * General Public License for more details.
34d05e84e6SDmitry Torokhov  *
35d05e84e6SDmitry Torokhov  * You should have received a copy of the GNU General Public License
36d05e84e6SDmitry Torokhov  * along with this program; if not, write to the Free Software
37d05e84e6SDmitry Torokhov  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
38d05e84e6SDmitry Torokhov  *
39d05e84e6SDmitry Torokhov  * Driver is based on touchkitusb.c
40d05e84e6SDmitry Torokhov  * - ITM parts are from itmtouch.c
41d05e84e6SDmitry Torokhov  * - 3M parts are from mtouchusb.c
42d05e84e6SDmitry Torokhov  * - PanJit parts are from an unmerged driver by Lanslott Gish
43d05e84e6SDmitry Torokhov  * - DMC TSC 10/25 are from Holger Schurig, with ideas from an unmerged
44d05e84e6SDmitry Torokhov  *   driver from Marius Vollmer
45d05e84e6SDmitry Torokhov  *
46d05e84e6SDmitry Torokhov  *****************************************************************************/
47d05e84e6SDmitry Torokhov 
48d05e84e6SDmitry Torokhov //#define DEBUG
49d05e84e6SDmitry Torokhov 
50d05e84e6SDmitry Torokhov #include <linux/kernel.h>
51d05e84e6SDmitry Torokhov #include <linux/slab.h>
52d05e84e6SDmitry Torokhov #include <linux/input.h>
53d05e84e6SDmitry Torokhov #include <linux/module.h>
54d05e84e6SDmitry Torokhov #include <linux/usb.h>
55d05e84e6SDmitry Torokhov #include <linux/usb/input.h>
56ec42d448SDaniel Ritz #include <linux/hid.h>
57d05e84e6SDmitry Torokhov 
58d05e84e6SDmitry Torokhov 
5962aa366dSDaniel Ritz #define DRIVER_VERSION		"v0.6"
60d05e84e6SDmitry Torokhov #define DRIVER_AUTHOR		"Daniel Ritz <daniel.ritz@gmx.ch>"
61d05e84e6SDmitry Torokhov #define DRIVER_DESC		"USB Touchscreen Driver"
62d05e84e6SDmitry Torokhov 
6390ab5ee9SRusty Russell static bool swap_xy;
64d05e84e6SDmitry Torokhov module_param(swap_xy, bool, 0644);
65d05e84e6SDmitry Torokhov MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped.");
66d05e84e6SDmitry Torokhov 
6790ab5ee9SRusty Russell static bool hwcalib_xy;
68c9cbf3d3SDan Streetman module_param(hwcalib_xy, bool, 0644);
69c9cbf3d3SDan Streetman MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available");
70c9cbf3d3SDan Streetman 
71d05e84e6SDmitry Torokhov /* device specifc data/functions */
72d05e84e6SDmitry Torokhov struct usbtouch_usb;
73d05e84e6SDmitry Torokhov struct usbtouch_device_info {
74d05e84e6SDmitry Torokhov 	int min_xc, max_xc;
75d05e84e6SDmitry Torokhov 	int min_yc, max_yc;
76d05e84e6SDmitry Torokhov 	int min_press, max_press;
77d05e84e6SDmitry Torokhov 	int rept_size;
78d05e84e6SDmitry Torokhov 
792330ed18SDaniel Silverstone 	/*
802330ed18SDaniel Silverstone 	 * Always service the USB devices irq not just when the input device is
812330ed18SDaniel Silverstone 	 * open. This is useful when devices have a watchdog which prevents us
822330ed18SDaniel Silverstone 	 * from periodically polling the device. Leave this unset unless your
832330ed18SDaniel Silverstone 	 * touchscreen device requires it, as it does consume more of the USB
842330ed18SDaniel Silverstone 	 * bandwidth.
852330ed18SDaniel Silverstone 	 */
862330ed18SDaniel Silverstone 	bool irq_always;
872330ed18SDaniel Silverstone 
88d05e84e6SDmitry Torokhov 	void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len);
8962aa366dSDaniel Ritz 
9062aa366dSDaniel Ritz 	/*
9162aa366dSDaniel Ritz 	 * used to get the packet len. possible return values:
9262aa366dSDaniel Ritz 	 * > 0: packet len
9362aa366dSDaniel Ritz 	 * = 0: skip one byte
9462aa366dSDaniel Ritz 	 * < 0: -return value more bytes needed
9562aa366dSDaniel Ritz 	 */
96d05e84e6SDmitry Torokhov 	int  (*get_pkt_len) (unsigned char *pkt, int len);
9762aa366dSDaniel Ritz 
98d05e84e6SDmitry Torokhov 	int  (*read_data)   (struct usbtouch_usb *usbtouch, unsigned char *pkt);
99a8aef622SOliver Neukum 	int  (*alloc)       (struct usbtouch_usb *usbtouch);
100d05e84e6SDmitry Torokhov 	int  (*init)        (struct usbtouch_usb *usbtouch);
1015197424cSOndrej Zary 	void (*exit)	    (struct usbtouch_usb *usbtouch);
102d05e84e6SDmitry Torokhov };
103d05e84e6SDmitry Torokhov 
104d05e84e6SDmitry Torokhov /* a usbtouch device */
105d05e84e6SDmitry Torokhov struct usbtouch_usb {
106d05e84e6SDmitry Torokhov 	unsigned char *data;
107d05e84e6SDmitry Torokhov 	dma_addr_t data_dma;
1084ef38351SChristian Engelmayer 	int data_size;
109d05e84e6SDmitry Torokhov 	unsigned char *buffer;
110d05e84e6SDmitry Torokhov 	int buf_len;
111d05e84e6SDmitry Torokhov 	struct urb *irq;
112fea4d14bSOndrej Zary 	struct usb_interface *interface;
113d05e84e6SDmitry Torokhov 	struct input_dev *input;
114d05e84e6SDmitry Torokhov 	struct usbtouch_device_info *type;
115d05e84e6SDmitry Torokhov 	char name[128];
116d05e84e6SDmitry Torokhov 	char phys[64];
1175197424cSOndrej Zary 	void *priv;
118d05e84e6SDmitry Torokhov 
119d05e84e6SDmitry Torokhov 	int x, y;
120d05e84e6SDmitry Torokhov 	int touch, press;
121d05e84e6SDmitry Torokhov };
122d05e84e6SDmitry Torokhov 
123d05e84e6SDmitry Torokhov 
124d05e84e6SDmitry Torokhov /* device types */
125d05e84e6SDmitry Torokhov enum {
126ec42d448SDaniel Ritz 	DEVTYPE_IGNORE = -1,
127d05e84e6SDmitry Torokhov 	DEVTYPE_EGALAX,
128d05e84e6SDmitry Torokhov 	DEVTYPE_PANJIT,
129d05e84e6SDmitry Torokhov 	DEVTYPE_3M,
130d05e84e6SDmitry Torokhov 	DEVTYPE_ITM,
131d05e84e6SDmitry Torokhov 	DEVTYPE_ETURBO,
132d05e84e6SDmitry Torokhov 	DEVTYPE_GUNZE,
133d05e84e6SDmitry Torokhov 	DEVTYPE_DMC_TSC10,
134df561fcdSOndrej Zary 	DEVTYPE_IRTOUCH,
135dbea4032SLars Poeschel 	DEVTYPE_IRTOUCH_HIRES,
136a14a8401SOndrej Zary 	DEVTYPE_IDEALTEK,
1379d5657dbSIlya Frolov 	DEVTYPE_GENERAL_TOUCH,
13814e40206SJerrold Jones 	DEVTYPE_GOTOP,
139f7370699SJim Persson 	DEVTYPE_JASTEC,
1409e3b2583SFlorian Echtler 	DEVTYPE_E2I,
1412330ed18SDaniel Silverstone 	DEVTYPE_ZYTRONIC,
14238771bb4SPetr Štetiar 	DEVTYPE_TC45USB,
1435197424cSOndrej Zary 	DEVTYPE_NEXIO,
144d2cc817aSMichael Gebetsroither 	DEVTYPE_ELO,
145aa87512fSArmando Visconti 	DEVTYPE_ETOUCH,
146d05e84e6SDmitry Torokhov };
147d05e84e6SDmitry Torokhov 
148ec42d448SDaniel Ritz #define USB_DEVICE_HID_CLASS(vend, prod) \
149ec42d448SDaniel Ritz 	.match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \
150ec42d448SDaniel Ritz 		| USB_DEVICE_ID_MATCH_DEVICE, \
151ec42d448SDaniel Ritz 	.idVendor = (vend), \
152ec42d448SDaniel Ritz 	.idProduct = (prod), \
153ae2aa3a5SForest Bond 	.bInterfaceClass = USB_INTERFACE_CLASS_HID
154ec42d448SDaniel Ritz 
1559cb3ce52SMárton Németh static const struct usb_device_id usbtouch_devices[] = {
156c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
157ec42d448SDaniel Ritz 	/* ignore the HID capable devices, handled by usbhid */
158ec42d448SDaniel Ritz 	{USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE},
159ec42d448SDaniel Ritz 	{USB_DEVICE_HID_CLASS(0x0eef, 0x0002), .driver_info = DEVTYPE_IGNORE},
160ec42d448SDaniel Ritz 
161ec42d448SDaniel Ritz 	/* normal device IDs */
162d05e84e6SDmitry Torokhov 	{USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX},
163d05e84e6SDmitry Torokhov 	{USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX},
164d05e84e6SDmitry Torokhov 	{USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX},
165d05e84e6SDmitry Torokhov 	{USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX},
166d05e84e6SDmitry Torokhov 	{USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX},
167d05e84e6SDmitry Torokhov 	{USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX},
168d05e84e6SDmitry Torokhov 	{USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX},
169d05e84e6SDmitry Torokhov #endif
170d05e84e6SDmitry Torokhov 
171c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT
172d05e84e6SDmitry Torokhov 	{USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT},
173d05e84e6SDmitry Torokhov 	{USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT},
174d05e84e6SDmitry Torokhov 	{USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT},
175d05e84e6SDmitry Torokhov 	{USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT},
176d05e84e6SDmitry Torokhov #endif
177d05e84e6SDmitry Torokhov 
178c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_3M
179d05e84e6SDmitry Torokhov 	{USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M},
180d05e84e6SDmitry Torokhov #endif
181d05e84e6SDmitry Torokhov 
182c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ITM
183d05e84e6SDmitry Torokhov 	{USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM},
18409910509SGlenn Sommer 	{USB_DEVICE(0x16e3, 0xf9e9), .driver_info = DEVTYPE_ITM},
185d05e84e6SDmitry Torokhov #endif
186d05e84e6SDmitry Torokhov 
187c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO
188d05e84e6SDmitry Torokhov 	{USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO},
189d05e84e6SDmitry Torokhov #endif
190d05e84e6SDmitry Torokhov 
191c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE
192d05e84e6SDmitry Torokhov 	{USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE},
193d05e84e6SDmitry Torokhov #endif
194d05e84e6SDmitry Torokhov 
195c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10
196d05e84e6SDmitry Torokhov 	{USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10},
197d05e84e6SDmitry Torokhov #endif
198d05e84e6SDmitry Torokhov 
199df561fcdSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
200df561fcdSOndrej Zary 	{USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
201df561fcdSOndrej Zary 	{USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
202dbea4032SLars Poeschel 	{USB_DEVICE(0x6615, 0x0012), .driver_info = DEVTYPE_IRTOUCH_HIRES},
203df561fcdSOndrej Zary #endif
204df561fcdSOndrej Zary 
205a14a8401SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK
206a14a8401SOndrej Zary 	{USB_DEVICE(0x1391, 0x1000), .driver_info = DEVTYPE_IDEALTEK},
207a14a8401SOndrej Zary #endif
208a14a8401SOndrej Zary 
2099d5657dbSIlya Frolov #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH
2109d5657dbSIlya Frolov 	{USB_DEVICE(0x0dfc, 0x0001), .driver_info = DEVTYPE_GENERAL_TOUCH},
2119d5657dbSIlya Frolov #endif
2129d5657dbSIlya Frolov 
21314e40206SJerrold Jones #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP
21414e40206SJerrold Jones 	{USB_DEVICE(0x08f2, 0x007f), .driver_info = DEVTYPE_GOTOP},
21514e40206SJerrold Jones 	{USB_DEVICE(0x08f2, 0x00ce), .driver_info = DEVTYPE_GOTOP},
21614e40206SJerrold Jones 	{USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP},
21714e40206SJerrold Jones #endif
21814e40206SJerrold Jones 
219f7370699SJim Persson #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC
220f7370699SJim Persson 	{USB_DEVICE(0x0f92, 0x0001), .driver_info = DEVTYPE_JASTEC},
221f7370699SJim Persson #endif
222f7370699SJim Persson 
2239e3b2583SFlorian Echtler #ifdef CONFIG_TOUCHSCREEN_USB_E2I
2249e3b2583SFlorian Echtler 	{USB_DEVICE(0x1ac7, 0x0001), .driver_info = DEVTYPE_E2I},
2259e3b2583SFlorian Echtler #endif
2262330ed18SDaniel Silverstone 
2272330ed18SDaniel Silverstone #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC
2282330ed18SDaniel Silverstone 	{USB_DEVICE(0x14c8, 0x0003), .driver_info = DEVTYPE_ZYTRONIC},
2292330ed18SDaniel Silverstone #endif
2302330ed18SDaniel Silverstone 
23138771bb4SPetr Štetiar #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB
23238771bb4SPetr Štetiar 	/* TC5UH */
23338771bb4SPetr Štetiar 	{USB_DEVICE(0x0664, 0x0309), .driver_info = DEVTYPE_TC45USB},
23438771bb4SPetr Štetiar 	/* TC4UM */
23538771bb4SPetr Štetiar 	{USB_DEVICE(0x0664, 0x0306), .driver_info = DEVTYPE_TC45USB},
236dbe1420bSPetr Štetiar #endif
237dbe1420bSPetr Štetiar 
2385197424cSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
2395197424cSOndrej Zary 	/* data interface only */
2405197424cSOndrej Zary 	{USB_DEVICE_AND_INTERFACE_INFO(0x10f0, 0x2002, 0x0a, 0x00, 0x00),
2415197424cSOndrej Zary 		.driver_info = DEVTYPE_NEXIO},
2425197424cSOndrej Zary 	{USB_DEVICE_AND_INTERFACE_INFO(0x1870, 0x0001, 0x0a, 0x00, 0x00),
2435197424cSOndrej Zary 		.driver_info = DEVTYPE_NEXIO},
2445197424cSOndrej Zary #endif
2455197424cSOndrej Zary 
246d2cc817aSMichael Gebetsroither #ifdef CONFIG_TOUCHSCREEN_USB_ELO
247d2cc817aSMichael Gebetsroither 	{USB_DEVICE(0x04e7, 0x0020), .driver_info = DEVTYPE_ELO},
248d2cc817aSMichael Gebetsroither #endif
249d2cc817aSMichael Gebetsroither 
250aa87512fSArmando Visconti #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH
251aa87512fSArmando Visconti 	{USB_DEVICE(0x7374, 0x0001), .driver_info = DEVTYPE_ETOUCH},
252aa87512fSArmando Visconti #endif
253aa87512fSArmando Visconti 
254d05e84e6SDmitry Torokhov 	{}
255d05e84e6SDmitry Torokhov };
256d05e84e6SDmitry Torokhov 
257d05e84e6SDmitry Torokhov 
258d05e84e6SDmitry Torokhov /*****************************************************************************
2599e3b2583SFlorian Echtler  * e2i Part
2609e3b2583SFlorian Echtler  */
2619e3b2583SFlorian Echtler 
2629e3b2583SFlorian Echtler #ifdef CONFIG_TOUCHSCREEN_USB_E2I
2639e3b2583SFlorian Echtler static int e2i_init(struct usbtouch_usb *usbtouch)
2649e3b2583SFlorian Echtler {
2659e3b2583SFlorian Echtler 	int ret;
266fea4d14bSOndrej Zary 	struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
2679e3b2583SFlorian Echtler 
268fea4d14bSOndrej Zary 	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
2699e3b2583SFlorian Echtler 	                      0x01, 0x02, 0x0000, 0x0081,
2709e3b2583SFlorian Echtler 	                      NULL, 0, USB_CTRL_SET_TIMEOUT);
2719e3b2583SFlorian Echtler 
2720a5ebc88SGreg Kroah-Hartman 	dev_dbg(&usbtouch->interface->dev,
273b741ab9dSGreg Kroah-Hartman 		"%s - usb_control_msg - E2I_RESET - bytes|err: %d\n",
2749e3b2583SFlorian Echtler 		__func__, ret);
2759e3b2583SFlorian Echtler 	return ret;
2769e3b2583SFlorian Echtler }
2779e3b2583SFlorian Echtler 
2789e3b2583SFlorian Echtler static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
2799e3b2583SFlorian Echtler {
2809e3b2583SFlorian Echtler 	int tmp = (pkt[0] << 8) | pkt[1];
2819e3b2583SFlorian Echtler 	dev->x  = (pkt[2] << 8) | pkt[3];
2829e3b2583SFlorian Echtler 	dev->y  = (pkt[4] << 8) | pkt[5];
2839e3b2583SFlorian Echtler 
2849e3b2583SFlorian Echtler 	tmp = tmp - 0xA000;
2859e3b2583SFlorian Echtler 	dev->touch = (tmp > 0);
2869e3b2583SFlorian Echtler 	dev->press = (tmp > 0 ? tmp : 0);
2879e3b2583SFlorian Echtler 
2889e3b2583SFlorian Echtler 	return 1;
2899e3b2583SFlorian Echtler }
2909e3b2583SFlorian Echtler #endif
2919e3b2583SFlorian Echtler 
2929e3b2583SFlorian Echtler 
2939e3b2583SFlorian Echtler /*****************************************************************************
294d05e84e6SDmitry Torokhov  * eGalax part
295d05e84e6SDmitry Torokhov  */
296d05e84e6SDmitry Torokhov 
297c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
298d05e84e6SDmitry Torokhov 
29962aa366dSDaniel Ritz #ifndef MULTI_PACKET
30062aa366dSDaniel Ritz #define MULTI_PACKET
30162aa366dSDaniel Ritz #endif
30262aa366dSDaniel Ritz 
303d05e84e6SDmitry Torokhov #define EGALAX_PKT_TYPE_MASK		0xFE
304d05e84e6SDmitry Torokhov #define EGALAX_PKT_TYPE_REPT		0x80
305d05e84e6SDmitry Torokhov #define EGALAX_PKT_TYPE_DIAG		0x0A
306d05e84e6SDmitry Torokhov 
307037a833eSForest Bond static int egalax_init(struct usbtouch_usb *usbtouch)
308037a833eSForest Bond {
309037a833eSForest Bond 	int ret, i;
310037a833eSForest Bond 	unsigned char *buf;
311037a833eSForest Bond 	struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
312037a833eSForest Bond 
313037a833eSForest Bond 	/*
314037a833eSForest Bond 	 * An eGalax diagnostic packet kicks the device into using the right
315037a833eSForest Bond 	 * protocol.  We send a "check active" packet.  The response will be
316037a833eSForest Bond 	 * read later and ignored.
317037a833eSForest Bond 	 */
318037a833eSForest Bond 
319037a833eSForest Bond 	buf = kmalloc(3, GFP_KERNEL);
320037a833eSForest Bond 	if (!buf)
321037a833eSForest Bond 		return -ENOMEM;
322037a833eSForest Bond 
323037a833eSForest Bond 	buf[0] = EGALAX_PKT_TYPE_DIAG;
324037a833eSForest Bond 	buf[1] = 1;	/* length */
325037a833eSForest Bond 	buf[2] = 'A';	/* command - check active */
326037a833eSForest Bond 
327037a833eSForest Bond 	for (i = 0; i < 3; i++) {
328037a833eSForest Bond 		ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
329037a833eSForest Bond 				      0,
330037a833eSForest Bond 				      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
331037a833eSForest Bond 				      0, 0, buf, 3,
332037a833eSForest Bond 				      USB_CTRL_SET_TIMEOUT);
333037a833eSForest Bond 		if (ret >= 0) {
334037a833eSForest Bond 			ret = 0;
335037a833eSForest Bond 			break;
336037a833eSForest Bond 		}
337037a833eSForest Bond 		if (ret != -EPIPE)
338037a833eSForest Bond 			break;
339037a833eSForest Bond 	}
340037a833eSForest Bond 
341037a833eSForest Bond 	kfree(buf);
342037a833eSForest Bond 
343037a833eSForest Bond 	return ret;
344037a833eSForest Bond }
345037a833eSForest Bond 
346d05e84e6SDmitry Torokhov static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
347d05e84e6SDmitry Torokhov {
348d05e84e6SDmitry Torokhov 	if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT)
349d05e84e6SDmitry Torokhov 		return 0;
350d05e84e6SDmitry Torokhov 
351d05e84e6SDmitry Torokhov 	dev->x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F);
352d05e84e6SDmitry Torokhov 	dev->y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F);
353d05e84e6SDmitry Torokhov 	dev->touch = pkt[0] & 0x01;
354d05e84e6SDmitry Torokhov 
355d05e84e6SDmitry Torokhov 	return 1;
356d05e84e6SDmitry Torokhov }
357d05e84e6SDmitry Torokhov 
358d05e84e6SDmitry Torokhov static int egalax_get_pkt_len(unsigned char *buf, int len)
359d05e84e6SDmitry Torokhov {
360d05e84e6SDmitry Torokhov 	switch (buf[0] & EGALAX_PKT_TYPE_MASK) {
361d05e84e6SDmitry Torokhov 	case EGALAX_PKT_TYPE_REPT:
362d05e84e6SDmitry Torokhov 		return 5;
363d05e84e6SDmitry Torokhov 
364d05e84e6SDmitry Torokhov 	case EGALAX_PKT_TYPE_DIAG:
365d05e84e6SDmitry Torokhov 		if (len < 2)
366d05e84e6SDmitry Torokhov 			return -1;
367d05e84e6SDmitry Torokhov 
368d05e84e6SDmitry Torokhov 		return buf[1] + 2;
369d05e84e6SDmitry Torokhov 	}
370d05e84e6SDmitry Torokhov 
371d05e84e6SDmitry Torokhov 	return 0;
372d05e84e6SDmitry Torokhov }
373d05e84e6SDmitry Torokhov #endif
374d05e84e6SDmitry Torokhov 
375aa87512fSArmando Visconti /*****************************************************************************
376aa87512fSArmando Visconti  * EasyTouch part
377aa87512fSArmando Visconti  */
378aa87512fSArmando Visconti 
379aa87512fSArmando Visconti #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH
380aa87512fSArmando Visconti 
381aa87512fSArmando Visconti #ifndef MULTI_PACKET
382aa87512fSArmando Visconti #define MULTI_PACKET
383aa87512fSArmando Visconti #endif
384aa87512fSArmando Visconti 
385aa87512fSArmando Visconti #define ETOUCH_PKT_TYPE_MASK		0xFE
386aa87512fSArmando Visconti #define ETOUCH_PKT_TYPE_REPT		0x80
387aa87512fSArmando Visconti #define ETOUCH_PKT_TYPE_REPT2		0xB0
388aa87512fSArmando Visconti #define ETOUCH_PKT_TYPE_DIAG		0x0A
389aa87512fSArmando Visconti 
390aa87512fSArmando Visconti static int etouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
391aa87512fSArmando Visconti {
392aa87512fSArmando Visconti 	if ((pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT &&
393aa87512fSArmando Visconti 		(pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT2)
394aa87512fSArmando Visconti 		return 0;
395aa87512fSArmando Visconti 
396aa87512fSArmando Visconti 	dev->x = ((pkt[1] & 0x1F) << 7) | (pkt[2] & 0x7F);
397aa87512fSArmando Visconti 	dev->y = ((pkt[3] & 0x1F) << 7) | (pkt[4] & 0x7F);
398aa87512fSArmando Visconti 	dev->touch = pkt[0] & 0x01;
399aa87512fSArmando Visconti 
400aa87512fSArmando Visconti 	return 1;
401aa87512fSArmando Visconti }
402aa87512fSArmando Visconti 
403aa87512fSArmando Visconti static int etouch_get_pkt_len(unsigned char *buf, int len)
404aa87512fSArmando Visconti {
405aa87512fSArmando Visconti 	switch (buf[0] & ETOUCH_PKT_TYPE_MASK) {
406aa87512fSArmando Visconti 	case ETOUCH_PKT_TYPE_REPT:
407aa87512fSArmando Visconti 	case ETOUCH_PKT_TYPE_REPT2:
408aa87512fSArmando Visconti 		return 5;
409aa87512fSArmando Visconti 
410aa87512fSArmando Visconti 	case ETOUCH_PKT_TYPE_DIAG:
411aa87512fSArmando Visconti 		if (len < 2)
412aa87512fSArmando Visconti 			return -1;
413aa87512fSArmando Visconti 
414aa87512fSArmando Visconti 		return buf[1] + 2;
415aa87512fSArmando Visconti 	}
416aa87512fSArmando Visconti 
417aa87512fSArmando Visconti 	return 0;
418aa87512fSArmando Visconti }
419aa87512fSArmando Visconti #endif
420d05e84e6SDmitry Torokhov 
421d05e84e6SDmitry Torokhov /*****************************************************************************
422d05e84e6SDmitry Torokhov  * PanJit Part
423d05e84e6SDmitry Torokhov  */
424c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT
425d05e84e6SDmitry Torokhov static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
426d05e84e6SDmitry Torokhov {
427d05e84e6SDmitry Torokhov 	dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1];
428d05e84e6SDmitry Torokhov 	dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3];
429d05e84e6SDmitry Torokhov 	dev->touch = pkt[0] & 0x01;
430d05e84e6SDmitry Torokhov 
431d05e84e6SDmitry Torokhov 	return 1;
432d05e84e6SDmitry Torokhov }
433d05e84e6SDmitry Torokhov #endif
434d05e84e6SDmitry Torokhov 
435d05e84e6SDmitry Torokhov 
436d05e84e6SDmitry Torokhov /*****************************************************************************
437d05e84e6SDmitry Torokhov  * 3M/Microtouch Part
438d05e84e6SDmitry Torokhov  */
439c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_3M
440d05e84e6SDmitry Torokhov 
441d05e84e6SDmitry Torokhov #define MTOUCHUSB_ASYNC_REPORT          1
442d05e84e6SDmitry Torokhov #define MTOUCHUSB_RESET                 7
443d05e84e6SDmitry Torokhov #define MTOUCHUSB_REQ_CTRLLR_ID         10
444d05e84e6SDmitry Torokhov 
445d05e84e6SDmitry Torokhov static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
446d05e84e6SDmitry Torokhov {
447c9cbf3d3SDan Streetman 	if (hwcalib_xy) {
448c9cbf3d3SDan Streetman 		dev->x = (pkt[4] << 8) | pkt[3];
449c9cbf3d3SDan Streetman 		dev->y = 0xffff - ((pkt[6] << 8) | pkt[5]);
450c9cbf3d3SDan Streetman 	} else {
451d05e84e6SDmitry Torokhov 		dev->x = (pkt[8] << 8) | pkt[7];
452d05e84e6SDmitry Torokhov 		dev->y = (pkt[10] << 8) | pkt[9];
453c9cbf3d3SDan Streetman 	}
454d05e84e6SDmitry Torokhov 	dev->touch = (pkt[2] & 0x40) ? 1 : 0;
455d05e84e6SDmitry Torokhov 
456d05e84e6SDmitry Torokhov 	return 1;
457d05e84e6SDmitry Torokhov }
458d05e84e6SDmitry Torokhov 
459d05e84e6SDmitry Torokhov static int mtouch_init(struct usbtouch_usb *usbtouch)
460d05e84e6SDmitry Torokhov {
461d05e84e6SDmitry Torokhov 	int ret, i;
462fea4d14bSOndrej Zary 	struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
463d05e84e6SDmitry Torokhov 
464fea4d14bSOndrej Zary 	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
465d05e84e6SDmitry Torokhov 	                      MTOUCHUSB_RESET,
466d05e84e6SDmitry Torokhov 	                      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
467d05e84e6SDmitry Torokhov 	                      1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
4680a5ebc88SGreg Kroah-Hartman 	dev_dbg(&usbtouch->interface->dev,
469b741ab9dSGreg Kroah-Hartman 		"%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d\n",
470ea3e6c59SHarvey Harrison 		__func__, ret);
471d05e84e6SDmitry Torokhov 	if (ret < 0)
472d05e84e6SDmitry Torokhov 		return ret;
473d05e84e6SDmitry Torokhov 	msleep(150);
474d05e84e6SDmitry Torokhov 
475d05e84e6SDmitry Torokhov 	for (i = 0; i < 3; i++) {
476fea4d14bSOndrej Zary 		ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
477d05e84e6SDmitry Torokhov 				      MTOUCHUSB_ASYNC_REPORT,
478d05e84e6SDmitry Torokhov 				      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
479d05e84e6SDmitry Torokhov 				      1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
4800a5ebc88SGreg Kroah-Hartman 		dev_dbg(&usbtouch->interface->dev,
481b741ab9dSGreg Kroah-Hartman 			"%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d\n",
482ea3e6c59SHarvey Harrison 			__func__, ret);
483d05e84e6SDmitry Torokhov 		if (ret >= 0)
484d05e84e6SDmitry Torokhov 			break;
485d05e84e6SDmitry Torokhov 		if (ret != -EPIPE)
486d05e84e6SDmitry Torokhov 			return ret;
487d05e84e6SDmitry Torokhov 	}
488d05e84e6SDmitry Torokhov 
489c9cbf3d3SDan Streetman 	/* Default min/max xy are the raw values, override if using hw-calib */
490c9cbf3d3SDan Streetman 	if (hwcalib_xy) {
491c9cbf3d3SDan Streetman 		input_set_abs_params(usbtouch->input, ABS_X, 0, 0xffff, 0, 0);
492c9cbf3d3SDan Streetman 		input_set_abs_params(usbtouch->input, ABS_Y, 0, 0xffff, 0, 0);
493c9cbf3d3SDan Streetman 	}
494c9cbf3d3SDan Streetman 
495d05e84e6SDmitry Torokhov 	return 0;
496d05e84e6SDmitry Torokhov }
497d05e84e6SDmitry Torokhov #endif
498d05e84e6SDmitry Torokhov 
499d05e84e6SDmitry Torokhov 
500d05e84e6SDmitry Torokhov /*****************************************************************************
501d05e84e6SDmitry Torokhov  * ITM Part
502d05e84e6SDmitry Torokhov  */
503c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ITM
504d05e84e6SDmitry Torokhov static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
505d05e84e6SDmitry Torokhov {
506d05e84e6SDmitry Torokhov 	int touch;
507d05e84e6SDmitry Torokhov 	/*
508d05e84e6SDmitry Torokhov 	 * ITM devices report invalid x/y data if not touched.
509d05e84e6SDmitry Torokhov 	 * if the screen was touched before but is not touched any more
510d05e84e6SDmitry Torokhov 	 * report touch as 0 with the last valid x/y data once. then stop
511d05e84e6SDmitry Torokhov 	 * reporting data until touched again.
512d05e84e6SDmitry Torokhov 	 */
513d05e84e6SDmitry Torokhov 	dev->press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F);
514d05e84e6SDmitry Torokhov 
515d05e84e6SDmitry Torokhov 	touch = ~pkt[7] & 0x20;
516d05e84e6SDmitry Torokhov 	if (!touch) {
517d05e84e6SDmitry Torokhov 		if (dev->touch) {
518d05e84e6SDmitry Torokhov 			dev->touch = 0;
519d05e84e6SDmitry Torokhov 			return 1;
520d05e84e6SDmitry Torokhov 		}
521d05e84e6SDmitry Torokhov 
522d05e84e6SDmitry Torokhov 		return 0;
523d05e84e6SDmitry Torokhov 	}
524d05e84e6SDmitry Torokhov 
525d05e84e6SDmitry Torokhov 	dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F);
526d05e84e6SDmitry Torokhov 	dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F);
527d05e84e6SDmitry Torokhov 	dev->touch = touch;
528d05e84e6SDmitry Torokhov 
529d05e84e6SDmitry Torokhov 	return 1;
530d05e84e6SDmitry Torokhov }
531d05e84e6SDmitry Torokhov #endif
532d05e84e6SDmitry Torokhov 
533d05e84e6SDmitry Torokhov 
534d05e84e6SDmitry Torokhov /*****************************************************************************
535d05e84e6SDmitry Torokhov  * eTurboTouch part
536d05e84e6SDmitry Torokhov  */
537c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO
53862aa366dSDaniel Ritz #ifndef MULTI_PACKET
53962aa366dSDaniel Ritz #define MULTI_PACKET
54062aa366dSDaniel Ritz #endif
541d05e84e6SDmitry Torokhov static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
542d05e84e6SDmitry Torokhov {
543d05e84e6SDmitry Torokhov 	unsigned int shift;
544d05e84e6SDmitry Torokhov 
545d05e84e6SDmitry Torokhov 	/* packets should start with sync */
546d05e84e6SDmitry Torokhov 	if (!(pkt[0] & 0x80))
547d05e84e6SDmitry Torokhov 		return 0;
548d05e84e6SDmitry Torokhov 
549d05e84e6SDmitry Torokhov 	shift = (6 - (pkt[0] & 0x03));
550d05e84e6SDmitry Torokhov 	dev->x = ((pkt[3] << 7) | pkt[4]) >> shift;
551d05e84e6SDmitry Torokhov 	dev->y = ((pkt[1] << 7) | pkt[2]) >> shift;
552d05e84e6SDmitry Torokhov 	dev->touch = (pkt[0] & 0x10) ? 1 : 0;
553d05e84e6SDmitry Torokhov 
554d05e84e6SDmitry Torokhov 	return 1;
555d05e84e6SDmitry Torokhov }
556d05e84e6SDmitry Torokhov 
557d05e84e6SDmitry Torokhov static int eturbo_get_pkt_len(unsigned char *buf, int len)
558d05e84e6SDmitry Torokhov {
559d05e84e6SDmitry Torokhov 	if (buf[0] & 0x80)
560d05e84e6SDmitry Torokhov 		return 5;
561d05e84e6SDmitry Torokhov 	if (buf[0] == 0x01)
562d05e84e6SDmitry Torokhov 		return 3;
563d05e84e6SDmitry Torokhov 	return 0;
564d05e84e6SDmitry Torokhov }
565d05e84e6SDmitry Torokhov #endif
566d05e84e6SDmitry Torokhov 
567d05e84e6SDmitry Torokhov 
568d05e84e6SDmitry Torokhov /*****************************************************************************
569d05e84e6SDmitry Torokhov  * Gunze part
570d05e84e6SDmitry Torokhov  */
571c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE
572d05e84e6SDmitry Torokhov static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
573d05e84e6SDmitry Torokhov {
574d05e84e6SDmitry Torokhov 	if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80))
575d05e84e6SDmitry Torokhov 		return 0;
576d05e84e6SDmitry Torokhov 
577d05e84e6SDmitry Torokhov 	dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F);
578d05e84e6SDmitry Torokhov 	dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F);
579d05e84e6SDmitry Torokhov 	dev->touch = pkt[0] & 0x20;
580d05e84e6SDmitry Torokhov 
581d05e84e6SDmitry Torokhov 	return 1;
582d05e84e6SDmitry Torokhov }
583d05e84e6SDmitry Torokhov #endif
584d05e84e6SDmitry Torokhov 
585d05e84e6SDmitry Torokhov /*****************************************************************************
586d05e84e6SDmitry Torokhov  * DMC TSC-10/25 Part
587d05e84e6SDmitry Torokhov  *
588d05e84e6SDmitry Torokhov  * Documentation about the controller and it's protocol can be found at
589d05e84e6SDmitry Torokhov  *   http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf
590d05e84e6SDmitry Torokhov  *   http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf
591d05e84e6SDmitry Torokhov  */
592c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10
593d05e84e6SDmitry Torokhov 
594d05e84e6SDmitry Torokhov /* supported data rates. currently using 130 */
595d05e84e6SDmitry Torokhov #define TSC10_RATE_POINT	0x50
596d05e84e6SDmitry Torokhov #define TSC10_RATE_30		0x40
597d05e84e6SDmitry Torokhov #define TSC10_RATE_50		0x41
598d05e84e6SDmitry Torokhov #define TSC10_RATE_80		0x42
599d05e84e6SDmitry Torokhov #define TSC10_RATE_100		0x43
600d05e84e6SDmitry Torokhov #define TSC10_RATE_130		0x44
601d05e84e6SDmitry Torokhov #define TSC10_RATE_150		0x45
602d05e84e6SDmitry Torokhov 
603d05e84e6SDmitry Torokhov /* commands */
604d05e84e6SDmitry Torokhov #define TSC10_CMD_RESET		0x55
605d05e84e6SDmitry Torokhov #define TSC10_CMD_RATE		0x05
606d05e84e6SDmitry Torokhov #define TSC10_CMD_DATA1		0x01
607d05e84e6SDmitry Torokhov 
608d05e84e6SDmitry Torokhov static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
609d05e84e6SDmitry Torokhov {
610fea4d14bSOndrej Zary 	struct usb_device *dev = interface_to_usbdev(usbtouch->interface);
61176d057ceSOliver Neukum 	int ret = -ENOMEM;
61276d057ceSOliver Neukum 	unsigned char *buf;
613d05e84e6SDmitry Torokhov 
614a8aef622SOliver Neukum 	buf = kmalloc(2, GFP_NOIO);
61576d057ceSOliver Neukum 	if (!buf)
61676d057ceSOliver Neukum 		goto err_nobuf;
617d05e84e6SDmitry Torokhov 	/* reset */
618d05e84e6SDmitry Torokhov 	buf[0] = buf[1] = 0xFF;
619d05e84e6SDmitry Torokhov 	ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
620d05e84e6SDmitry Torokhov 	                      TSC10_CMD_RESET,
621d05e84e6SDmitry Torokhov 	                      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
622d05e84e6SDmitry Torokhov 	                      0, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
623d05e84e6SDmitry Torokhov 	if (ret < 0)
62476d057ceSOliver Neukum 		goto err_out;
6252ec6f246SNuno Lucas 	if (buf[0] != 0x06) {
62676d057ceSOliver Neukum 		ret = -ENODEV;
62776d057ceSOliver Neukum 		goto err_out;
62876d057ceSOliver Neukum 	}
629d05e84e6SDmitry Torokhov 
630*96849170SBernhard Bender 	/* TSC-25 data sheet specifies a delay after the RESET command */
631*96849170SBernhard Bender 	msleep(150);
632*96849170SBernhard Bender 
633d05e84e6SDmitry Torokhov 	/* set coordinate output rate */
634d05e84e6SDmitry Torokhov 	buf[0] = buf[1] = 0xFF;
635d05e84e6SDmitry Torokhov 	ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
636d05e84e6SDmitry Torokhov 	                      TSC10_CMD_RATE,
637d05e84e6SDmitry Torokhov 	                      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
638d05e84e6SDmitry Torokhov 	                      TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
639d05e84e6SDmitry Torokhov 	if (ret < 0)
64076d057ceSOliver Neukum 		goto err_out;
6412ec6f246SNuno Lucas 	if ((buf[0] != 0x06) && (buf[0] != 0x15 || buf[1] != 0x01)) {
64276d057ceSOliver Neukum 		ret = -ENODEV;
64376d057ceSOliver Neukum 		goto err_out;
64476d057ceSOliver Neukum 	}
645d05e84e6SDmitry Torokhov 
646d05e84e6SDmitry Torokhov 	/* start sending data */
647d05e84e6SDmitry Torokhov 	ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
648d05e84e6SDmitry Torokhov 	                      TSC10_CMD_DATA1,
649d05e84e6SDmitry Torokhov 	                      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
650d05e84e6SDmitry Torokhov 	                      0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
65176d057ceSOliver Neukum err_out:
65276d057ceSOliver Neukum 	kfree(buf);
65376d057ceSOliver Neukum err_nobuf:
654d05e84e6SDmitry Torokhov 	return ret;
655d05e84e6SDmitry Torokhov }
656d05e84e6SDmitry Torokhov 
657d05e84e6SDmitry Torokhov 
658d05e84e6SDmitry Torokhov static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
659d05e84e6SDmitry Torokhov {
660d05e84e6SDmitry Torokhov 	dev->x = ((pkt[2] & 0x03) << 8) | pkt[1];
661d05e84e6SDmitry Torokhov 	dev->y = ((pkt[4] & 0x03) << 8) | pkt[3];
662d05e84e6SDmitry Torokhov 	dev->touch = pkt[0] & 0x01;
663d05e84e6SDmitry Torokhov 
664d05e84e6SDmitry Torokhov 	return 1;
665d05e84e6SDmitry Torokhov }
666d05e84e6SDmitry Torokhov #endif
667d05e84e6SDmitry Torokhov 
668d05e84e6SDmitry Torokhov 
669d05e84e6SDmitry Torokhov /*****************************************************************************
670df561fcdSOndrej Zary  * IRTOUCH Part
671df561fcdSOndrej Zary  */
672df561fcdSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
673df561fcdSOndrej Zary static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
674df561fcdSOndrej Zary {
675df561fcdSOndrej Zary 	dev->x = (pkt[3] << 8) | pkt[2];
676df561fcdSOndrej Zary 	dev->y = (pkt[5] << 8) | pkt[4];
677df561fcdSOndrej Zary 	dev->touch = (pkt[1] & 0x03) ? 1 : 0;
678df561fcdSOndrej Zary 
679df561fcdSOndrej Zary 	return 1;
680df561fcdSOndrej Zary }
681df561fcdSOndrej Zary #endif
682df561fcdSOndrej Zary 
683dbe1420bSPetr Štetiar /*****************************************************************************
68438771bb4SPetr Štetiar  * ET&T TC5UH/TC4UM part
685dbe1420bSPetr Štetiar  */
68638771bb4SPetr Štetiar #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB
68738771bb4SPetr Štetiar static int tc45usb_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
688dbe1420bSPetr Štetiar {
689dbe1420bSPetr Štetiar 	dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1];
690dbe1420bSPetr Štetiar 	dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3];
691dbe1420bSPetr Štetiar 	dev->touch = pkt[0] & 0x01;
692dbe1420bSPetr Štetiar 
693dbe1420bSPetr Štetiar 	return 1;
694dbe1420bSPetr Štetiar }
695dbe1420bSPetr Štetiar #endif
696df561fcdSOndrej Zary 
697df561fcdSOndrej Zary /*****************************************************************************
698a14a8401SOndrej Zary  * IdealTEK URTC1000 Part
699a14a8401SOndrej Zary  */
700a14a8401SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK
70162aa366dSDaniel Ritz #ifndef MULTI_PACKET
70262aa366dSDaniel Ritz #define MULTI_PACKET
70362aa366dSDaniel Ritz #endif
704a14a8401SOndrej Zary static int idealtek_get_pkt_len(unsigned char *buf, int len)
705a14a8401SOndrej Zary {
706a14a8401SOndrej Zary 	if (buf[0] & 0x80)
707a14a8401SOndrej Zary 		return 5;
708a14a8401SOndrej Zary 	if (buf[0] == 0x01)
709a14a8401SOndrej Zary 		return len;
710a14a8401SOndrej Zary 	return 0;
711a14a8401SOndrej Zary }
712a14a8401SOndrej Zary 
713a14a8401SOndrej Zary static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
714a14a8401SOndrej Zary {
715a14a8401SOndrej Zary 	switch (pkt[0] & 0x98) {
716a14a8401SOndrej Zary 	case 0x88:
717a14a8401SOndrej Zary 		/* touch data in IdealTEK mode */
718a14a8401SOndrej Zary 		dev->x = (pkt[1] << 5) | (pkt[2] >> 2);
719a14a8401SOndrej Zary 		dev->y = (pkt[3] << 5) | (pkt[4] >> 2);
720a14a8401SOndrej Zary 		dev->touch = (pkt[0] & 0x40) ? 1 : 0;
721a14a8401SOndrej Zary 		return 1;
722a14a8401SOndrej Zary 
723a14a8401SOndrej Zary 	case 0x98:
724a14a8401SOndrej Zary 		/* touch data in MT emulation mode */
725a14a8401SOndrej Zary 		dev->x = (pkt[2] << 5) | (pkt[1] >> 2);
726a14a8401SOndrej Zary 		dev->y = (pkt[4] << 5) | (pkt[3] >> 2);
727a14a8401SOndrej Zary 		dev->touch = (pkt[0] & 0x40) ? 1 : 0;
728a14a8401SOndrej Zary 		return 1;
729a14a8401SOndrej Zary 
730a14a8401SOndrej Zary 	default:
731a14a8401SOndrej Zary 		return 0;
732a14a8401SOndrej Zary 	}
733a14a8401SOndrej Zary }
734a14a8401SOndrej Zary #endif
735a14a8401SOndrej Zary 
7369d5657dbSIlya Frolov /*****************************************************************************
7379d5657dbSIlya Frolov  * General Touch Part
7389d5657dbSIlya Frolov  */
7399d5657dbSIlya Frolov #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH
7409d5657dbSIlya Frolov static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
7419d5657dbSIlya Frolov {
742eb083ba2SRoy Yin 	dev->x = (pkt[2] << 8) | pkt[1];
743eb083ba2SRoy Yin 	dev->y = (pkt[4] << 8) | pkt[3];
7449d5657dbSIlya Frolov 	dev->press = pkt[5] & 0xff;
7459d5657dbSIlya Frolov 	dev->touch = pkt[0] & 0x01;
7469d5657dbSIlya Frolov 
7479d5657dbSIlya Frolov 	return 1;
7489d5657dbSIlya Frolov }
7499d5657dbSIlya Frolov #endif
750a14a8401SOndrej Zary 
751a14a8401SOndrej Zary /*****************************************************************************
75214e40206SJerrold Jones  * GoTop Part
75314e40206SJerrold Jones  */
75414e40206SJerrold Jones #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP
75514e40206SJerrold Jones static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
75614e40206SJerrold Jones {
75714e40206SJerrold Jones 	dev->x = ((pkt[1] & 0x38) << 4) | pkt[2];
75814e40206SJerrold Jones 	dev->y = ((pkt[1] & 0x07) << 7) | pkt[3];
75914e40206SJerrold Jones 	dev->touch = pkt[0] & 0x01;
760f7370699SJim Persson 
761f7370699SJim Persson 	return 1;
762f7370699SJim Persson }
763f7370699SJim Persson #endif
764f7370699SJim Persson 
765f7370699SJim Persson /*****************************************************************************
766f7370699SJim Persson  * JASTEC Part
767f7370699SJim Persson  */
768f7370699SJim Persson #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC
769f7370699SJim Persson static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
770f7370699SJim Persson {
771f7370699SJim Persson 	dev->x = ((pkt[0] & 0x3f) << 6) | (pkt[2] & 0x3f);
772f7370699SJim Persson 	dev->y = ((pkt[1] & 0x3f) << 6) | (pkt[3] & 0x3f);
773f7370699SJim Persson 	dev->touch = (pkt[0] & 0x40) >> 6;
774f7370699SJim Persson 
77514e40206SJerrold Jones 	return 1;
77614e40206SJerrold Jones }
77714e40206SJerrold Jones #endif
77814e40206SJerrold Jones 
7792330ed18SDaniel Silverstone /*****************************************************************************
7802330ed18SDaniel Silverstone  * Zytronic Part
7812330ed18SDaniel Silverstone  */
7822330ed18SDaniel Silverstone #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC
7832330ed18SDaniel Silverstone static int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
7842330ed18SDaniel Silverstone {
7850a5ebc88SGreg Kroah-Hartman 	struct usb_interface *intf = dev->interface;
786b741ab9dSGreg Kroah-Hartman 
7872330ed18SDaniel Silverstone 	switch (pkt[0]) {
7882330ed18SDaniel Silverstone 	case 0x3A: /* command response */
7890a5ebc88SGreg Kroah-Hartman 		dev_dbg(&intf->dev, "%s: Command response %d\n", __func__, pkt[1]);
7902330ed18SDaniel Silverstone 		break;
7912330ed18SDaniel Silverstone 
7922330ed18SDaniel Silverstone 	case 0xC0: /* down */
7932330ed18SDaniel Silverstone 		dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7);
7942330ed18SDaniel Silverstone 		dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7);
7952330ed18SDaniel Silverstone 		dev->touch = 1;
7960a5ebc88SGreg Kroah-Hartman 		dev_dbg(&intf->dev, "%s: down %d,%d\n", __func__, dev->x, dev->y);
7972330ed18SDaniel Silverstone 		return 1;
7982330ed18SDaniel Silverstone 
7992330ed18SDaniel Silverstone 	case 0x80: /* up */
8002330ed18SDaniel Silverstone 		dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7);
8012330ed18SDaniel Silverstone 		dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7);
8022330ed18SDaniel Silverstone 		dev->touch = 0;
8030a5ebc88SGreg Kroah-Hartman 		dev_dbg(&intf->dev, "%s: up %d,%d\n", __func__, dev->x, dev->y);
8042330ed18SDaniel Silverstone 		return 1;
8052330ed18SDaniel Silverstone 
8062330ed18SDaniel Silverstone 	default:
8070a5ebc88SGreg Kroah-Hartman 		dev_dbg(&intf->dev, "%s: Unknown return %d\n", __func__, pkt[0]);
8082330ed18SDaniel Silverstone 		break;
8092330ed18SDaniel Silverstone 	}
8102330ed18SDaniel Silverstone 
8112330ed18SDaniel Silverstone 	return 0;
8122330ed18SDaniel Silverstone }
8132330ed18SDaniel Silverstone #endif
81414e40206SJerrold Jones 
81514e40206SJerrold Jones /*****************************************************************************
8165197424cSOndrej Zary  * NEXIO Part
8175197424cSOndrej Zary  */
8185197424cSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
8195197424cSOndrej Zary 
8205197424cSOndrej Zary #define NEXIO_TIMEOUT	5000
8215197424cSOndrej Zary #define NEXIO_BUFSIZE	1024
8225197424cSOndrej Zary #define NEXIO_THRESHOLD	50
8235197424cSOndrej Zary 
8245197424cSOndrej Zary struct nexio_priv {
8255197424cSOndrej Zary 	struct urb *ack;
8265197424cSOndrej Zary 	unsigned char *ack_buf;
8275197424cSOndrej Zary };
8285197424cSOndrej Zary 
8295197424cSOndrej Zary struct nexio_touch_packet {
8305197424cSOndrej Zary 	u8	flags;		/* 0xe1 = touch, 0xe1 = release */
8315197424cSOndrej Zary 	__be16	data_len;	/* total bytes of touch data */
8325197424cSOndrej Zary 	__be16	x_len;		/* bytes for X axis */
8335197424cSOndrej Zary 	__be16	y_len;		/* bytes for Y axis */
8345197424cSOndrej Zary 	u8	data[];
8355197424cSOndrej Zary } __attribute__ ((packed));
8365197424cSOndrej Zary 
8375197424cSOndrej Zary static unsigned char nexio_ack_pkt[2] = { 0xaa, 0x02 };
8385197424cSOndrej Zary static unsigned char nexio_init_pkt[4] = { 0x82, 0x04, 0x0a, 0x0f };
8395197424cSOndrej Zary 
8405197424cSOndrej Zary static void nexio_ack_complete(struct urb *urb)
8415197424cSOndrej Zary {
8425197424cSOndrej Zary }
8435197424cSOndrej Zary 
844a8aef622SOliver Neukum static int nexio_alloc(struct usbtouch_usb *usbtouch)
845a8aef622SOliver Neukum {
846a8aef622SOliver Neukum 	struct nexio_priv *priv;
847a8aef622SOliver Neukum 	int ret = -ENOMEM;
848a8aef622SOliver Neukum 
849a8aef622SOliver Neukum 	usbtouch->priv = kmalloc(sizeof(struct nexio_priv), GFP_KERNEL);
850a8aef622SOliver Neukum 	if (!usbtouch->priv)
851a8aef622SOliver Neukum 		goto out_buf;
852a8aef622SOliver Neukum 
853a8aef622SOliver Neukum 	priv = usbtouch->priv;
854a8aef622SOliver Neukum 
855a8aef622SOliver Neukum 	priv->ack_buf = kmemdup(nexio_ack_pkt, sizeof(nexio_ack_pkt),
856a8aef622SOliver Neukum 				GFP_KERNEL);
857a8aef622SOliver Neukum 	if (!priv->ack_buf)
858a8aef622SOliver Neukum 		goto err_priv;
859a8aef622SOliver Neukum 
860a8aef622SOliver Neukum 	priv->ack = usb_alloc_urb(0, GFP_KERNEL);
861a8aef622SOliver Neukum 	if (!priv->ack) {
8620a5ebc88SGreg Kroah-Hartman 		dev_dbg(&usbtouch->interface->dev,
863b741ab9dSGreg Kroah-Hartman 			"%s - usb_alloc_urb failed: usbtouch->ack\n", __func__);
864a8aef622SOliver Neukum 		goto err_ack_buf;
865a8aef622SOliver Neukum 	}
866a8aef622SOliver Neukum 
867a8aef622SOliver Neukum 	return 0;
868a8aef622SOliver Neukum 
869a8aef622SOliver Neukum err_ack_buf:
870a8aef622SOliver Neukum 	kfree(priv->ack_buf);
871a8aef622SOliver Neukum err_priv:
872a8aef622SOliver Neukum 	kfree(priv);
873a8aef622SOliver Neukum out_buf:
874a8aef622SOliver Neukum 	return ret;
875a8aef622SOliver Neukum }
876a8aef622SOliver Neukum 
8775197424cSOndrej Zary static int nexio_init(struct usbtouch_usb *usbtouch)
8785197424cSOndrej Zary {
8795197424cSOndrej Zary 	struct usb_device *dev = interface_to_usbdev(usbtouch->interface);
8805197424cSOndrej Zary 	struct usb_host_interface *interface = usbtouch->interface->cur_altsetting;
881a8aef622SOliver Neukum 	struct nexio_priv *priv = usbtouch->priv;
8825197424cSOndrej Zary 	int ret = -ENOMEM;
8835197424cSOndrej Zary 	int actual_len, i;
8845197424cSOndrej Zary 	unsigned char *buf;
8855197424cSOndrej Zary 	char *firmware_ver = NULL, *device_name = NULL;
8865197424cSOndrej Zary 	int input_ep = 0, output_ep = 0;
8875197424cSOndrej Zary 
8885197424cSOndrej Zary 	/* find first input and output endpoint */
8895197424cSOndrej Zary 	for (i = 0; i < interface->desc.bNumEndpoints; i++) {
8905197424cSOndrej Zary 		if (!input_ep &&
8915197424cSOndrej Zary 		    usb_endpoint_dir_in(&interface->endpoint[i].desc))
8925197424cSOndrej Zary 			input_ep = interface->endpoint[i].desc.bEndpointAddress;
8935197424cSOndrej Zary 		if (!output_ep &&
8945197424cSOndrej Zary 		    usb_endpoint_dir_out(&interface->endpoint[i].desc))
8955197424cSOndrej Zary 			output_ep = interface->endpoint[i].desc.bEndpointAddress;
8965197424cSOndrej Zary 	}
8975197424cSOndrej Zary 	if (!input_ep || !output_ep)
8985197424cSOndrej Zary 		return -ENXIO;
8995197424cSOndrej Zary 
900a8aef622SOliver Neukum 	buf = kmalloc(NEXIO_BUFSIZE, GFP_NOIO);
9015197424cSOndrej Zary 	if (!buf)
9025197424cSOndrej Zary 		goto out_buf;
9035197424cSOndrej Zary 
9045197424cSOndrej Zary 	/* two empty reads */
9055197424cSOndrej Zary 	for (i = 0; i < 2; i++) {
9065197424cSOndrej Zary 		ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep),
9075197424cSOndrej Zary 				   buf, NEXIO_BUFSIZE, &actual_len,
9085197424cSOndrej Zary 				   NEXIO_TIMEOUT);
9095197424cSOndrej Zary 		if (ret < 0)
9105197424cSOndrej Zary 			goto out_buf;
9115197424cSOndrej Zary 	}
9125197424cSOndrej Zary 
9135197424cSOndrej Zary 	/* send init command */
9145197424cSOndrej Zary 	memcpy(buf, nexio_init_pkt, sizeof(nexio_init_pkt));
9155197424cSOndrej Zary 	ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, output_ep),
9165197424cSOndrej Zary 			   buf, sizeof(nexio_init_pkt), &actual_len,
9175197424cSOndrej Zary 			   NEXIO_TIMEOUT);
9185197424cSOndrej Zary 	if (ret < 0)
9195197424cSOndrej Zary 		goto out_buf;
9205197424cSOndrej Zary 
9215197424cSOndrej Zary 	/* read replies */
9225197424cSOndrej Zary 	for (i = 0; i < 3; i++) {
9235197424cSOndrej Zary 		memset(buf, 0, NEXIO_BUFSIZE);
9245197424cSOndrej Zary 		ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep),
9255197424cSOndrej Zary 				   buf, NEXIO_BUFSIZE, &actual_len,
9265197424cSOndrej Zary 				   NEXIO_TIMEOUT);
9275197424cSOndrej Zary 		if (ret < 0 || actual_len < 1 || buf[1] != actual_len)
9285197424cSOndrej Zary 			continue;
9295197424cSOndrej Zary 		switch (buf[0]) {
9305197424cSOndrej Zary 		case 0x83:	/* firmware version */
9315197424cSOndrej Zary 			if (!firmware_ver)
932a8aef622SOliver Neukum 				firmware_ver = kstrdup(&buf[2], GFP_NOIO);
9335197424cSOndrej Zary 			break;
9345197424cSOndrej Zary 		case 0x84:	/* device name */
9355197424cSOndrej Zary 			if (!device_name)
936a8aef622SOliver Neukum 				device_name = kstrdup(&buf[2], GFP_NOIO);
9375197424cSOndrej Zary 			break;
9385197424cSOndrej Zary 		}
9395197424cSOndrej Zary 	}
9405197424cSOndrej Zary 
9415197424cSOndrej Zary 	printk(KERN_INFO "Nexio device: %s, firmware version: %s\n",
9425197424cSOndrej Zary 	       device_name, firmware_ver);
9435197424cSOndrej Zary 
9445197424cSOndrej Zary 	kfree(firmware_ver);
9455197424cSOndrej Zary 	kfree(device_name);
9465197424cSOndrej Zary 
9475197424cSOndrej Zary 	usb_fill_bulk_urb(priv->ack, dev, usb_sndbulkpipe(dev, output_ep),
9485197424cSOndrej Zary 			  priv->ack_buf, sizeof(nexio_ack_pkt),
9495197424cSOndrej Zary 			  nexio_ack_complete, usbtouch);
9505197424cSOndrej Zary 	ret = 0;
9515197424cSOndrej Zary 
9525197424cSOndrej Zary out_buf:
9535197424cSOndrej Zary 	kfree(buf);
9545197424cSOndrej Zary 	return ret;
9555197424cSOndrej Zary }
9565197424cSOndrej Zary 
9575197424cSOndrej Zary static void nexio_exit(struct usbtouch_usb *usbtouch)
9585197424cSOndrej Zary {
9595197424cSOndrej Zary 	struct nexio_priv *priv = usbtouch->priv;
9605197424cSOndrej Zary 
9615197424cSOndrej Zary 	usb_kill_urb(priv->ack);
9625197424cSOndrej Zary 	usb_free_urb(priv->ack);
9635197424cSOndrej Zary 	kfree(priv->ack_buf);
9645197424cSOndrej Zary 	kfree(priv);
9655197424cSOndrej Zary }
9665197424cSOndrej Zary 
9675197424cSOndrej Zary static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt)
9685197424cSOndrej Zary {
9695197424cSOndrej Zary 	struct nexio_touch_packet *packet = (void *) pkt;
9705197424cSOndrej Zary 	struct nexio_priv *priv = usbtouch->priv;
9714aa5bbecSDmitry Torokhov 	unsigned int data_len = be16_to_cpu(packet->data_len);
9724aa5bbecSDmitry Torokhov 	unsigned int x_len = be16_to_cpu(packet->x_len);
9734aa5bbecSDmitry Torokhov 	unsigned int y_len = be16_to_cpu(packet->y_len);
9744aa5bbecSDmitry Torokhov 	int x, y, begin_x, begin_y, end_x, end_y, w, h, ret;
9755197424cSOndrej Zary 
9765197424cSOndrej Zary 	/* got touch data? */
9775197424cSOndrej Zary 	if ((pkt[0] & 0xe0) != 0xe0)
9785197424cSOndrej Zary 		return 0;
9795197424cSOndrej Zary 
9804aa5bbecSDmitry Torokhov 	if (data_len > 0xff)
9814aa5bbecSDmitry Torokhov 		data_len -= 0x100;
9824aa5bbecSDmitry Torokhov 	if (x_len > 0xff)
9834aa5bbecSDmitry Torokhov 		x_len -= 0x80;
984388bbcadSOndrej Zary 
9855197424cSOndrej Zary 	/* send ACK */
9865197424cSOndrej Zary 	ret = usb_submit_urb(priv->ack, GFP_ATOMIC);
9875197424cSOndrej Zary 
9885197424cSOndrej Zary 	if (!usbtouch->type->max_xc) {
9894aa5bbecSDmitry Torokhov 		usbtouch->type->max_xc = 2 * x_len;
9904aa5bbecSDmitry Torokhov 		input_set_abs_params(usbtouch->input, ABS_X,
9914aa5bbecSDmitry Torokhov 				     0, usbtouch->type->max_xc, 0, 0);
9924aa5bbecSDmitry Torokhov 		usbtouch->type->max_yc = 2 * y_len;
9934aa5bbecSDmitry Torokhov 		input_set_abs_params(usbtouch->input, ABS_Y,
9944aa5bbecSDmitry Torokhov 				     0, usbtouch->type->max_yc, 0, 0);
9955197424cSOndrej Zary 	}
9965197424cSOndrej Zary 	/*
9975197424cSOndrej Zary 	 * The device reports state of IR sensors on X and Y axes.
9985197424cSOndrej Zary 	 * Each byte represents "darkness" percentage (0-100) of one element.
9995197424cSOndrej Zary 	 * 17" touchscreen reports only 64 x 52 bytes so the resolution is low.
10005197424cSOndrej Zary 	 * This also means that there's a limited multi-touch capability but
10015197424cSOndrej Zary 	 * it's disabled (and untested) here as there's no X driver for that.
10025197424cSOndrej Zary 	 */
10035197424cSOndrej Zary 	begin_x = end_x = begin_y = end_y = -1;
10044aa5bbecSDmitry Torokhov 	for (x = 0; x < x_len; x++) {
10055197424cSOndrej Zary 		if (begin_x == -1 && packet->data[x] > NEXIO_THRESHOLD) {
10065197424cSOndrej Zary 			begin_x = x;
10075197424cSOndrej Zary 			continue;
10085197424cSOndrej Zary 		}
10095197424cSOndrej Zary 		if (end_x == -1 && begin_x != -1 && packet->data[x] < NEXIO_THRESHOLD) {
10105197424cSOndrej Zary 			end_x = x - 1;
10114aa5bbecSDmitry Torokhov 			for (y = x_len; y < data_len; y++) {
10125197424cSOndrej Zary 				if (begin_y == -1 && packet->data[y] > NEXIO_THRESHOLD) {
10134aa5bbecSDmitry Torokhov 					begin_y = y - x_len;
10145197424cSOndrej Zary 					continue;
10155197424cSOndrej Zary 				}
10165197424cSOndrej Zary 				if (end_y == -1 &&
10175197424cSOndrej Zary 				    begin_y != -1 && packet->data[y] < NEXIO_THRESHOLD) {
10184aa5bbecSDmitry Torokhov 					end_y = y - 1 - x_len;
10195197424cSOndrej Zary 					w = end_x - begin_x;
10205197424cSOndrej Zary 					h = end_y - begin_y;
10215197424cSOndrej Zary #if 0
10225197424cSOndrej Zary 					/* multi-touch */
10235197424cSOndrej Zary 					input_report_abs(usbtouch->input,
10245197424cSOndrej Zary 						    ABS_MT_TOUCH_MAJOR, max(w,h));
10255197424cSOndrej Zary 					input_report_abs(usbtouch->input,
10265197424cSOndrej Zary 						    ABS_MT_TOUCH_MINOR, min(x,h));
10275197424cSOndrej Zary 					input_report_abs(usbtouch->input,
10285197424cSOndrej Zary 						    ABS_MT_POSITION_X, 2*begin_x+w);
10295197424cSOndrej Zary 					input_report_abs(usbtouch->input,
10305197424cSOndrej Zary 						    ABS_MT_POSITION_Y, 2*begin_y+h);
10315197424cSOndrej Zary 					input_report_abs(usbtouch->input,
10325197424cSOndrej Zary 						    ABS_MT_ORIENTATION, w > h);
10335197424cSOndrej Zary 					input_mt_sync(usbtouch->input);
10345197424cSOndrej Zary #endif
10355197424cSOndrej Zary 					/* single touch */
10365197424cSOndrej Zary 					usbtouch->x = 2 * begin_x + w;
10375197424cSOndrej Zary 					usbtouch->y = 2 * begin_y + h;
10385197424cSOndrej Zary 					usbtouch->touch = packet->flags & 0x01;
10395197424cSOndrej Zary 					begin_y = end_y = -1;
10405197424cSOndrej Zary 					return 1;
10415197424cSOndrej Zary 				}
10425197424cSOndrej Zary 			}
10435197424cSOndrej Zary 			begin_x = end_x = -1;
10445197424cSOndrej Zary 		}
10455197424cSOndrej Zary 
10465197424cSOndrej Zary 	}
10475197424cSOndrej Zary 	return 0;
10485197424cSOndrej Zary }
10495197424cSOndrej Zary #endif
10505197424cSOndrej Zary 
10515197424cSOndrej Zary 
10525197424cSOndrej Zary /*****************************************************************************
1053d2cc817aSMichael Gebetsroither  * ELO part
1054d2cc817aSMichael Gebetsroither  */
1055d2cc817aSMichael Gebetsroither 
1056d2cc817aSMichael Gebetsroither #ifdef CONFIG_TOUCHSCREEN_USB_ELO
1057d2cc817aSMichael Gebetsroither 
1058d2cc817aSMichael Gebetsroither static int elo_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
1059d2cc817aSMichael Gebetsroither {
1060d2cc817aSMichael Gebetsroither 	dev->x = (pkt[3] << 8) | pkt[2];
1061d2cc817aSMichael Gebetsroither 	dev->y = (pkt[5] << 8) | pkt[4];
1062d2cc817aSMichael Gebetsroither 	dev->touch = pkt[6] > 0;
1063d2cc817aSMichael Gebetsroither 	dev->press = pkt[6];
1064d2cc817aSMichael Gebetsroither 
1065d2cc817aSMichael Gebetsroither 	return 1;
1066d2cc817aSMichael Gebetsroither }
1067d2cc817aSMichael Gebetsroither #endif
1068d2cc817aSMichael Gebetsroither 
1069d2cc817aSMichael Gebetsroither 
1070d2cc817aSMichael Gebetsroither /*****************************************************************************
1071d05e84e6SDmitry Torokhov  * the different device descriptors
1072d05e84e6SDmitry Torokhov  */
107362aa366dSDaniel Ritz #ifdef MULTI_PACKET
107462aa366dSDaniel Ritz static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
107562aa366dSDaniel Ritz 				   unsigned char *pkt, int len);
107662aa366dSDaniel Ritz #endif
107762aa366dSDaniel Ritz 
1078d05e84e6SDmitry Torokhov static struct usbtouch_device_info usbtouch_dev_info[] = {
1079d2cc817aSMichael Gebetsroither #ifdef CONFIG_TOUCHSCREEN_USB_ELO
1080d2cc817aSMichael Gebetsroither 	[DEVTYPE_ELO] = {
1081d2cc817aSMichael Gebetsroither 		.min_xc		= 0x0,
1082d2cc817aSMichael Gebetsroither 		.max_xc		= 0x0fff,
1083d2cc817aSMichael Gebetsroither 		.min_yc		= 0x0,
1084d2cc817aSMichael Gebetsroither 		.max_yc		= 0x0fff,
1085d2cc817aSMichael Gebetsroither 		.max_press	= 0xff,
1086d2cc817aSMichael Gebetsroither 		.rept_size	= 8,
1087d2cc817aSMichael Gebetsroither 		.read_data	= elo_read_data,
1088d2cc817aSMichael Gebetsroither 	},
1089d2cc817aSMichael Gebetsroither #endif
1090d2cc817aSMichael Gebetsroither 
1091c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
1092d05e84e6SDmitry Torokhov 	[DEVTYPE_EGALAX] = {
1093d05e84e6SDmitry Torokhov 		.min_xc		= 0x0,
1094d05e84e6SDmitry Torokhov 		.max_xc		= 0x07ff,
1095d05e84e6SDmitry Torokhov 		.min_yc		= 0x0,
1096d05e84e6SDmitry Torokhov 		.max_yc		= 0x07ff,
1097d05e84e6SDmitry Torokhov 		.rept_size	= 16,
1098d05e84e6SDmitry Torokhov 		.process_pkt	= usbtouch_process_multi,
1099d05e84e6SDmitry Torokhov 		.get_pkt_len	= egalax_get_pkt_len,
1100d05e84e6SDmitry Torokhov 		.read_data	= egalax_read_data,
1101037a833eSForest Bond 		.init		= egalax_init,
1102d05e84e6SDmitry Torokhov 	},
1103d05e84e6SDmitry Torokhov #endif
1104d05e84e6SDmitry Torokhov 
1105c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT
1106d05e84e6SDmitry Torokhov 	[DEVTYPE_PANJIT] = {
1107d05e84e6SDmitry Torokhov 		.min_xc		= 0x0,
1108d05e84e6SDmitry Torokhov 		.max_xc		= 0x0fff,
1109d05e84e6SDmitry Torokhov 		.min_yc		= 0x0,
1110d05e84e6SDmitry Torokhov 		.max_yc		= 0x0fff,
1111d05e84e6SDmitry Torokhov 		.rept_size	= 8,
1112d05e84e6SDmitry Torokhov 		.read_data	= panjit_read_data,
1113d05e84e6SDmitry Torokhov 	},
1114d05e84e6SDmitry Torokhov #endif
1115d05e84e6SDmitry Torokhov 
1116c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_3M
1117d05e84e6SDmitry Torokhov 	[DEVTYPE_3M] = {
1118d05e84e6SDmitry Torokhov 		.min_xc		= 0x0,
1119d05e84e6SDmitry Torokhov 		.max_xc		= 0x4000,
1120d05e84e6SDmitry Torokhov 		.min_yc		= 0x0,
1121d05e84e6SDmitry Torokhov 		.max_yc		= 0x4000,
1122d05e84e6SDmitry Torokhov 		.rept_size	= 11,
1123d05e84e6SDmitry Torokhov 		.read_data	= mtouch_read_data,
1124d05e84e6SDmitry Torokhov 		.init		= mtouch_init,
1125d05e84e6SDmitry Torokhov 	},
1126d05e84e6SDmitry Torokhov #endif
1127d05e84e6SDmitry Torokhov 
1128c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ITM
1129d05e84e6SDmitry Torokhov 	[DEVTYPE_ITM] = {
1130d05e84e6SDmitry Torokhov 		.min_xc		= 0x0,
1131d05e84e6SDmitry Torokhov 		.max_xc		= 0x0fff,
1132d05e84e6SDmitry Torokhov 		.min_yc		= 0x0,
1133d05e84e6SDmitry Torokhov 		.max_yc		= 0x0fff,
1134d05e84e6SDmitry Torokhov 		.max_press	= 0xff,
1135d05e84e6SDmitry Torokhov 		.rept_size	= 8,
1136d05e84e6SDmitry Torokhov 		.read_data	= itm_read_data,
1137d05e84e6SDmitry Torokhov 	},
1138d05e84e6SDmitry Torokhov #endif
1139d05e84e6SDmitry Torokhov 
1140c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO
1141d05e84e6SDmitry Torokhov 	[DEVTYPE_ETURBO] = {
1142d05e84e6SDmitry Torokhov 		.min_xc		= 0x0,
1143d05e84e6SDmitry Torokhov 		.max_xc		= 0x07ff,
1144d05e84e6SDmitry Torokhov 		.min_yc		= 0x0,
1145d05e84e6SDmitry Torokhov 		.max_yc		= 0x07ff,
1146d05e84e6SDmitry Torokhov 		.rept_size	= 8,
1147d05e84e6SDmitry Torokhov 		.process_pkt	= usbtouch_process_multi,
1148d05e84e6SDmitry Torokhov 		.get_pkt_len	= eturbo_get_pkt_len,
1149d05e84e6SDmitry Torokhov 		.read_data	= eturbo_read_data,
1150d05e84e6SDmitry Torokhov 	},
1151d05e84e6SDmitry Torokhov #endif
1152d05e84e6SDmitry Torokhov 
1153c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE
1154d05e84e6SDmitry Torokhov 	[DEVTYPE_GUNZE] = {
1155d05e84e6SDmitry Torokhov 		.min_xc		= 0x0,
1156d05e84e6SDmitry Torokhov 		.max_xc		= 0x0fff,
1157d05e84e6SDmitry Torokhov 		.min_yc		= 0x0,
1158d05e84e6SDmitry Torokhov 		.max_yc		= 0x0fff,
1159d05e84e6SDmitry Torokhov 		.rept_size	= 4,
1160d05e84e6SDmitry Torokhov 		.read_data	= gunze_read_data,
1161d05e84e6SDmitry Torokhov 	},
1162d05e84e6SDmitry Torokhov #endif
1163d05e84e6SDmitry Torokhov 
1164c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10
1165d05e84e6SDmitry Torokhov 	[DEVTYPE_DMC_TSC10] = {
1166d05e84e6SDmitry Torokhov 		.min_xc		= 0x0,
1167d05e84e6SDmitry Torokhov 		.max_xc		= 0x03ff,
1168d05e84e6SDmitry Torokhov 		.min_yc		= 0x0,
1169d05e84e6SDmitry Torokhov 		.max_yc		= 0x03ff,
1170d05e84e6SDmitry Torokhov 		.rept_size	= 5,
1171d05e84e6SDmitry Torokhov 		.init		= dmc_tsc10_init,
1172d05e84e6SDmitry Torokhov 		.read_data	= dmc_tsc10_read_data,
1173d05e84e6SDmitry Torokhov 	},
1174d05e84e6SDmitry Torokhov #endif
1175df561fcdSOndrej Zary 
1176df561fcdSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
1177df561fcdSOndrej Zary 	[DEVTYPE_IRTOUCH] = {
1178df561fcdSOndrej Zary 		.min_xc		= 0x0,
1179df561fcdSOndrej Zary 		.max_xc		= 0x0fff,
1180df561fcdSOndrej Zary 		.min_yc		= 0x0,
1181df561fcdSOndrej Zary 		.max_yc		= 0x0fff,
1182df561fcdSOndrej Zary 		.rept_size	= 8,
1183df561fcdSOndrej Zary 		.read_data	= irtouch_read_data,
1184df561fcdSOndrej Zary 	},
1185dbea4032SLars Poeschel 
1186dbea4032SLars Poeschel 	[DEVTYPE_IRTOUCH_HIRES] = {
1187dbea4032SLars Poeschel 		.min_xc		= 0x0,
1188dbea4032SLars Poeschel 		.max_xc		= 0x7fff,
1189dbea4032SLars Poeschel 		.min_yc		= 0x0,
1190dbea4032SLars Poeschel 		.max_yc		= 0x7fff,
1191dbea4032SLars Poeschel 		.rept_size	= 8,
1192dbea4032SLars Poeschel 		.read_data	= irtouch_read_data,
1193dbea4032SLars Poeschel 	},
1194df561fcdSOndrej Zary #endif
1195a14a8401SOndrej Zary 
1196a14a8401SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK
1197a14a8401SOndrej Zary 	[DEVTYPE_IDEALTEK] = {
1198a14a8401SOndrej Zary 		.min_xc		= 0x0,
1199a14a8401SOndrej Zary 		.max_xc		= 0x0fff,
1200a14a8401SOndrej Zary 		.min_yc		= 0x0,
1201a14a8401SOndrej Zary 		.max_yc		= 0x0fff,
1202a14a8401SOndrej Zary 		.rept_size	= 8,
1203a14a8401SOndrej Zary 		.process_pkt	= usbtouch_process_multi,
1204a14a8401SOndrej Zary 		.get_pkt_len	= idealtek_get_pkt_len,
1205a14a8401SOndrej Zary 		.read_data	= idealtek_read_data,
1206a14a8401SOndrej Zary 	},
1207a14a8401SOndrej Zary #endif
12089d5657dbSIlya Frolov 
12099d5657dbSIlya Frolov #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH
12109d5657dbSIlya Frolov 	[DEVTYPE_GENERAL_TOUCH] = {
12119d5657dbSIlya Frolov 		.min_xc		= 0x0,
1212eb083ba2SRoy Yin 		.max_xc		= 0x7fff,
12139d5657dbSIlya Frolov 		.min_yc		= 0x0,
1214eb083ba2SRoy Yin 		.max_yc		= 0x7fff,
12159d5657dbSIlya Frolov 		.rept_size	= 7,
12169d5657dbSIlya Frolov 		.read_data	= general_touch_read_data,
121714e40206SJerrold Jones 	},
12189d5657dbSIlya Frolov #endif
12199d5657dbSIlya Frolov 
122014e40206SJerrold Jones #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP
122114e40206SJerrold Jones 	[DEVTYPE_GOTOP] = {
122214e40206SJerrold Jones 		.min_xc		= 0x0,
122314e40206SJerrold Jones 		.max_xc		= 0x03ff,
122414e40206SJerrold Jones 		.min_yc		= 0x0,
122514e40206SJerrold Jones 		.max_yc		= 0x03ff,
122614e40206SJerrold Jones 		.rept_size	= 4,
122714e40206SJerrold Jones 		.read_data	= gotop_read_data,
122814e40206SJerrold Jones 	},
122914e40206SJerrold Jones #endif
1230f7370699SJim Persson 
1231f7370699SJim Persson #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC
1232f7370699SJim Persson 	[DEVTYPE_JASTEC] = {
1233f7370699SJim Persson 		.min_xc		= 0x0,
1234f7370699SJim Persson 		.max_xc		= 0x0fff,
1235f7370699SJim Persson 		.min_yc		= 0x0,
1236f7370699SJim Persson 		.max_yc		= 0x0fff,
1237f7370699SJim Persson 		.rept_size	= 4,
1238f7370699SJim Persson 		.read_data	= jastec_read_data,
1239f7370699SJim Persson 	},
1240f7370699SJim Persson #endif
12419e3b2583SFlorian Echtler 
12429e3b2583SFlorian Echtler #ifdef CONFIG_TOUCHSCREEN_USB_E2I
12439e3b2583SFlorian Echtler 	[DEVTYPE_E2I] = {
12449e3b2583SFlorian Echtler 		.min_xc		= 0x0,
12459e3b2583SFlorian Echtler 		.max_xc		= 0x7fff,
12469e3b2583SFlorian Echtler 		.min_yc		= 0x0,
12479e3b2583SFlorian Echtler 		.max_yc		= 0x7fff,
12489e3b2583SFlorian Echtler 		.rept_size	= 6,
12499e3b2583SFlorian Echtler 		.init		= e2i_init,
12509e3b2583SFlorian Echtler 		.read_data	= e2i_read_data,
12519e3b2583SFlorian Echtler 	},
12529e3b2583SFlorian Echtler #endif
12532330ed18SDaniel Silverstone 
12542330ed18SDaniel Silverstone #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC
12552330ed18SDaniel Silverstone 	[DEVTYPE_ZYTRONIC] = {
12562330ed18SDaniel Silverstone 		.min_xc		= 0x0,
12572330ed18SDaniel Silverstone 		.max_xc		= 0x03ff,
12582330ed18SDaniel Silverstone 		.min_yc		= 0x0,
12592330ed18SDaniel Silverstone 		.max_yc		= 0x03ff,
12602330ed18SDaniel Silverstone 		.rept_size	= 5,
12612330ed18SDaniel Silverstone 		.read_data	= zytronic_read_data,
12622330ed18SDaniel Silverstone 		.irq_always     = true,
12632330ed18SDaniel Silverstone 	},
12642330ed18SDaniel Silverstone #endif
1265dbe1420bSPetr Štetiar 
126638771bb4SPetr Štetiar #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB
126738771bb4SPetr Štetiar 	[DEVTYPE_TC45USB] = {
1268dbe1420bSPetr Štetiar 		.min_xc		= 0x0,
1269dbe1420bSPetr Štetiar 		.max_xc		= 0x0fff,
1270dbe1420bSPetr Štetiar 		.min_yc		= 0x0,
1271dbe1420bSPetr Štetiar 		.max_yc		= 0x0fff,
1272dbe1420bSPetr Štetiar 		.rept_size	= 5,
127338771bb4SPetr Štetiar 		.read_data	= tc45usb_read_data,
1274dbe1420bSPetr Štetiar 	},
1275dbe1420bSPetr Štetiar #endif
12765197424cSOndrej Zary 
12775197424cSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
12785197424cSOndrej Zary 	[DEVTYPE_NEXIO] = {
1279388bbcadSOndrej Zary 		.rept_size	= 1024,
12805197424cSOndrej Zary 		.irq_always	= true,
12815197424cSOndrej Zary 		.read_data	= nexio_read_data,
1282a8aef622SOliver Neukum 		.alloc		= nexio_alloc,
12835197424cSOndrej Zary 		.init		= nexio_init,
12845197424cSOndrej Zary 		.exit		= nexio_exit,
12855197424cSOndrej Zary 	},
12865197424cSOndrej Zary #endif
1287aa87512fSArmando Visconti #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH
1288aa87512fSArmando Visconti 	[DEVTYPE_ETOUCH] = {
1289aa87512fSArmando Visconti 		.min_xc		= 0x0,
1290aa87512fSArmando Visconti 		.max_xc		= 0x07ff,
1291aa87512fSArmando Visconti 		.min_yc		= 0x0,
1292aa87512fSArmando Visconti 		.max_yc		= 0x07ff,
1293aa87512fSArmando Visconti 		.rept_size	= 16,
1294aa87512fSArmando Visconti 		.process_pkt	= usbtouch_process_multi,
1295aa87512fSArmando Visconti 		.get_pkt_len	= etouch_get_pkt_len,
1296aa87512fSArmando Visconti 		.read_data	= etouch_read_data,
1297aa87512fSArmando Visconti 	},
1298aa87512fSArmando Visconti #endif
1299d05e84e6SDmitry Torokhov };
1300d05e84e6SDmitry Torokhov 
1301d05e84e6SDmitry Torokhov 
1302d05e84e6SDmitry Torokhov /*****************************************************************************
1303d05e84e6SDmitry Torokhov  * Generic Part
1304d05e84e6SDmitry Torokhov  */
1305d05e84e6SDmitry Torokhov static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
1306d05e84e6SDmitry Torokhov                                  unsigned char *pkt, int len)
1307d05e84e6SDmitry Torokhov {
1308d05e84e6SDmitry Torokhov 	struct usbtouch_device_info *type = usbtouch->type;
1309d05e84e6SDmitry Torokhov 
1310d05e84e6SDmitry Torokhov 	if (!type->read_data(usbtouch, pkt))
1311d05e84e6SDmitry Torokhov 			return;
1312d05e84e6SDmitry Torokhov 
1313d05e84e6SDmitry Torokhov 	input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch);
1314d05e84e6SDmitry Torokhov 
1315d05e84e6SDmitry Torokhov 	if (swap_xy) {
1316d05e84e6SDmitry Torokhov 		input_report_abs(usbtouch->input, ABS_X, usbtouch->y);
1317d05e84e6SDmitry Torokhov 		input_report_abs(usbtouch->input, ABS_Y, usbtouch->x);
1318d05e84e6SDmitry Torokhov 	} else {
1319d05e84e6SDmitry Torokhov 		input_report_abs(usbtouch->input, ABS_X, usbtouch->x);
1320d05e84e6SDmitry Torokhov 		input_report_abs(usbtouch->input, ABS_Y, usbtouch->y);
1321d05e84e6SDmitry Torokhov 	}
1322d05e84e6SDmitry Torokhov 	if (type->max_press)
1323d05e84e6SDmitry Torokhov 		input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press);
1324d05e84e6SDmitry Torokhov 	input_sync(usbtouch->input);
1325d05e84e6SDmitry Torokhov }
1326d05e84e6SDmitry Torokhov 
1327d05e84e6SDmitry Torokhov 
1328d05e84e6SDmitry Torokhov #ifdef MULTI_PACKET
1329d05e84e6SDmitry Torokhov static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
1330d05e84e6SDmitry Torokhov                                    unsigned char *pkt, int len)
1331d05e84e6SDmitry Torokhov {
1332d05e84e6SDmitry Torokhov 	unsigned char *buffer;
1333d05e84e6SDmitry Torokhov 	int pkt_len, pos, buf_len, tmp;
1334d05e84e6SDmitry Torokhov 
1335d05e84e6SDmitry Torokhov 	/* process buffer */
1336d05e84e6SDmitry Torokhov 	if (unlikely(usbtouch->buf_len)) {
1337d05e84e6SDmitry Torokhov 		/* try to get size */
1338d05e84e6SDmitry Torokhov 		pkt_len = usbtouch->type->get_pkt_len(
1339d05e84e6SDmitry Torokhov 				usbtouch->buffer, usbtouch->buf_len);
1340d05e84e6SDmitry Torokhov 
1341d05e84e6SDmitry Torokhov 		/* drop? */
1342d05e84e6SDmitry Torokhov 		if (unlikely(!pkt_len))
1343d05e84e6SDmitry Torokhov 			goto out_flush_buf;
1344d05e84e6SDmitry Torokhov 
1345d05e84e6SDmitry Torokhov 		/* need to append -pkt_len bytes before able to get size */
1346d05e84e6SDmitry Torokhov 		if (unlikely(pkt_len < 0)) {
1347d05e84e6SDmitry Torokhov 			int append = -pkt_len;
1348d05e84e6SDmitry Torokhov 			if (unlikely(append > len))
1349d05e84e6SDmitry Torokhov 			       append = len;
1350d05e84e6SDmitry Torokhov 			if (usbtouch->buf_len + append >= usbtouch->type->rept_size)
1351d05e84e6SDmitry Torokhov 				goto out_flush_buf;
1352d05e84e6SDmitry Torokhov 			memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append);
1353d05e84e6SDmitry Torokhov 			usbtouch->buf_len += append;
1354d05e84e6SDmitry Torokhov 
1355d05e84e6SDmitry Torokhov 			pkt_len = usbtouch->type->get_pkt_len(
1356d05e84e6SDmitry Torokhov 					usbtouch->buffer, usbtouch->buf_len);
1357d05e84e6SDmitry Torokhov 			if (pkt_len < 0)
1358d05e84e6SDmitry Torokhov 				return;
1359d05e84e6SDmitry Torokhov 		}
1360d05e84e6SDmitry Torokhov 
1361d05e84e6SDmitry Torokhov 		/* append */
1362d05e84e6SDmitry Torokhov 		tmp = pkt_len - usbtouch->buf_len;
1363d05e84e6SDmitry Torokhov 		if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size)
1364d05e84e6SDmitry Torokhov 			goto out_flush_buf;
1365d05e84e6SDmitry Torokhov 		memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp);
1366d05e84e6SDmitry Torokhov 		usbtouch_process_pkt(usbtouch, usbtouch->buffer, pkt_len);
1367d05e84e6SDmitry Torokhov 
1368d05e84e6SDmitry Torokhov 		buffer = pkt + tmp;
1369d05e84e6SDmitry Torokhov 		buf_len = len - tmp;
1370d05e84e6SDmitry Torokhov 	} else {
1371d05e84e6SDmitry Torokhov 		buffer = pkt;
1372d05e84e6SDmitry Torokhov 		buf_len = len;
1373d05e84e6SDmitry Torokhov 	}
1374d05e84e6SDmitry Torokhov 
1375d05e84e6SDmitry Torokhov 	/* loop over the received packet, process */
1376d05e84e6SDmitry Torokhov 	pos = 0;
1377d05e84e6SDmitry Torokhov 	while (pos < buf_len) {
1378d05e84e6SDmitry Torokhov 		/* get packet len */
137962aa366dSDaniel Ritz 		pkt_len = usbtouch->type->get_pkt_len(buffer + pos,
138062aa366dSDaniel Ritz 							buf_len - pos);
1381d05e84e6SDmitry Torokhov 
138262aa366dSDaniel Ritz 		/* unknown packet: skip one byte */
138362aa366dSDaniel Ritz 		if (unlikely(!pkt_len)) {
138462aa366dSDaniel Ritz 			pos++;
138562aa366dSDaniel Ritz 			continue;
138662aa366dSDaniel Ritz 		}
1387d05e84e6SDmitry Torokhov 
1388d05e84e6SDmitry Torokhov 		/* full packet: process */
1389d05e84e6SDmitry Torokhov 		if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) {
1390d05e84e6SDmitry Torokhov 			usbtouch_process_pkt(usbtouch, buffer + pos, pkt_len);
1391d05e84e6SDmitry Torokhov 		} else {
1392d05e84e6SDmitry Torokhov 			/* incomplete packet: save in buffer */
1393d05e84e6SDmitry Torokhov 			memcpy(usbtouch->buffer, buffer + pos, buf_len - pos);
1394d05e84e6SDmitry Torokhov 			usbtouch->buf_len = buf_len - pos;
1395d05e84e6SDmitry Torokhov 			return;
1396d05e84e6SDmitry Torokhov 		}
1397d05e84e6SDmitry Torokhov 		pos += pkt_len;
1398d05e84e6SDmitry Torokhov 	}
1399d05e84e6SDmitry Torokhov 
1400d05e84e6SDmitry Torokhov out_flush_buf:
1401d05e84e6SDmitry Torokhov 	usbtouch->buf_len = 0;
1402d05e84e6SDmitry Torokhov 	return;
1403d05e84e6SDmitry Torokhov }
1404d05e84e6SDmitry Torokhov #endif
1405d05e84e6SDmitry Torokhov 
1406d05e84e6SDmitry Torokhov 
1407d05e84e6SDmitry Torokhov static void usbtouch_irq(struct urb *urb)
1408d05e84e6SDmitry Torokhov {
1409d05e84e6SDmitry Torokhov 	struct usbtouch_usb *usbtouch = urb->context;
14100a5ebc88SGreg Kroah-Hartman 	struct device *dev = &usbtouch->interface->dev;
1411d05e84e6SDmitry Torokhov 	int retval;
1412d05e84e6SDmitry Torokhov 
1413d05e84e6SDmitry Torokhov 	switch (urb->status) {
1414d05e84e6SDmitry Torokhov 	case 0:
1415d05e84e6SDmitry Torokhov 		/* success */
1416d05e84e6SDmitry Torokhov 		break;
1417d05e84e6SDmitry Torokhov 	case -ETIME:
1418d05e84e6SDmitry Torokhov 		/* this urb is timing out */
1419b741ab9dSGreg Kroah-Hartman 		dev_dbg(dev,
1420b741ab9dSGreg Kroah-Hartman 			"%s - urb timed out - was the device unplugged?\n",
1421ea3e6c59SHarvey Harrison 			__func__);
1422d05e84e6SDmitry Torokhov 		return;
1423d05e84e6SDmitry Torokhov 	case -ECONNRESET:
1424d05e84e6SDmitry Torokhov 	case -ENOENT:
1425d05e84e6SDmitry Torokhov 	case -ESHUTDOWN:
14265197424cSOndrej Zary 	case -EPIPE:
1427d05e84e6SDmitry Torokhov 		/* this urb is terminated, clean up */
1428b741ab9dSGreg Kroah-Hartman 		dev_dbg(dev, "%s - urb shutting down with status: %d\n",
1429ea3e6c59SHarvey Harrison 			__func__, urb->status);
1430d05e84e6SDmitry Torokhov 		return;
1431d05e84e6SDmitry Torokhov 	default:
1432b741ab9dSGreg Kroah-Hartman 		dev_dbg(dev, "%s - nonzero urb status received: %d\n",
1433ea3e6c59SHarvey Harrison 			__func__, urb->status);
1434d05e84e6SDmitry Torokhov 		goto exit;
1435d05e84e6SDmitry Torokhov 	}
1436d05e84e6SDmitry Torokhov 
1437d05e84e6SDmitry Torokhov 	usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length);
1438d05e84e6SDmitry Torokhov 
1439d05e84e6SDmitry Torokhov exit:
14405d9efc59SOliver Neukum 	usb_mark_last_busy(interface_to_usbdev(usbtouch->interface));
1441d05e84e6SDmitry Torokhov 	retval = usb_submit_urb(urb, GFP_ATOMIC);
1442d05e84e6SDmitry Torokhov 	if (retval)
14430a5ebc88SGreg Kroah-Hartman 		dev_err(dev, "%s - usb_submit_urb failed with result: %d\n",
1444ea3e6c59SHarvey Harrison 			__func__, retval);
1445d05e84e6SDmitry Torokhov }
1446d05e84e6SDmitry Torokhov 
1447d05e84e6SDmitry Torokhov static int usbtouch_open(struct input_dev *input)
1448d05e84e6SDmitry Torokhov {
1449d05e84e6SDmitry Torokhov 	struct usbtouch_usb *usbtouch = input_get_drvdata(input);
14505d9efc59SOliver Neukum 	int r;
1451d05e84e6SDmitry Torokhov 
1452fea4d14bSOndrej Zary 	usbtouch->irq->dev = interface_to_usbdev(usbtouch->interface);
1453d05e84e6SDmitry Torokhov 
14545d9efc59SOliver Neukum 	r = usb_autopm_get_interface(usbtouch->interface) ? -EIO : 0;
14555d9efc59SOliver Neukum 	if (r < 0)
14565d9efc59SOliver Neukum 		goto out;
14575d9efc59SOliver Neukum 
14582330ed18SDaniel Silverstone 	if (!usbtouch->type->irq_always) {
14595d9efc59SOliver Neukum 		if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) {
14605d9efc59SOliver Neukum 			r = -EIO;
14615d9efc59SOliver Neukum 			goto out_put;
14625d9efc59SOliver Neukum 		}
14632330ed18SDaniel Silverstone 	}
1464d05e84e6SDmitry Torokhov 
14655d9efc59SOliver Neukum 	usbtouch->interface->needs_remote_wakeup = 1;
14665d9efc59SOliver Neukum out_put:
14675d9efc59SOliver Neukum 	usb_autopm_put_interface(usbtouch->interface);
14685d9efc59SOliver Neukum out:
14695d9efc59SOliver Neukum 	return r;
1470d05e84e6SDmitry Torokhov }
1471d05e84e6SDmitry Torokhov 
1472d05e84e6SDmitry Torokhov static void usbtouch_close(struct input_dev *input)
1473d05e84e6SDmitry Torokhov {
1474d05e84e6SDmitry Torokhov 	struct usbtouch_usb *usbtouch = input_get_drvdata(input);
14755d9efc59SOliver Neukum 	int r;
1476d05e84e6SDmitry Torokhov 
14772330ed18SDaniel Silverstone 	if (!usbtouch->type->irq_always)
1478d05e84e6SDmitry Torokhov 		usb_kill_urb(usbtouch->irq);
14795d9efc59SOliver Neukum 	r = usb_autopm_get_interface(usbtouch->interface);
14805d9efc59SOliver Neukum 	usbtouch->interface->needs_remote_wakeup = 0;
14815d9efc59SOliver Neukum 	if (!r)
14825d9efc59SOliver Neukum 		usb_autopm_put_interface(usbtouch->interface);
1483d05e84e6SDmitry Torokhov }
1484d05e84e6SDmitry Torokhov 
1485ed4299e1SOliver Neukum static int usbtouch_suspend
1486ed4299e1SOliver Neukum (struct usb_interface *intf, pm_message_t message)
1487ed4299e1SOliver Neukum {
1488ed4299e1SOliver Neukum 	struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
1489ed4299e1SOliver Neukum 
1490ed4299e1SOliver Neukum 	usb_kill_urb(usbtouch->irq);
1491ed4299e1SOliver Neukum 
1492ed4299e1SOliver Neukum 	return 0;
1493ed4299e1SOliver Neukum }
1494ed4299e1SOliver Neukum 
1495ed4299e1SOliver Neukum static int usbtouch_resume(struct usb_interface *intf)
1496ed4299e1SOliver Neukum {
1497ed4299e1SOliver Neukum 	struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
1498ed4299e1SOliver Neukum 	struct input_dev *input = usbtouch->input;
1499ed4299e1SOliver Neukum 	int result = 0;
1500ed4299e1SOliver Neukum 
1501ed4299e1SOliver Neukum 	mutex_lock(&input->mutex);
1502ed4299e1SOliver Neukum 	if (input->users || usbtouch->type->irq_always)
1503ed4299e1SOliver Neukum 		result = usb_submit_urb(usbtouch->irq, GFP_NOIO);
1504ed4299e1SOliver Neukum 	mutex_unlock(&input->mutex);
1505ed4299e1SOliver Neukum 
1506ed4299e1SOliver Neukum 	return result;
1507ed4299e1SOliver Neukum }
1508d05e84e6SDmitry Torokhov 
1509a8aef622SOliver Neukum static int usbtouch_reset_resume(struct usb_interface *intf)
1510a8aef622SOliver Neukum {
1511a8aef622SOliver Neukum 	struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
1512a8aef622SOliver Neukum 	struct input_dev *input = usbtouch->input;
1513a8aef622SOliver Neukum 	int err = 0;
1514a8aef622SOliver Neukum 
1515a8aef622SOliver Neukum 	/* reinit the device */
1516a8aef622SOliver Neukum 	if (usbtouch->type->init) {
1517a8aef622SOliver Neukum 		err = usbtouch->type->init(usbtouch);
1518a8aef622SOliver Neukum 		if (err) {
15190a5ebc88SGreg Kroah-Hartman 			dev_dbg(&intf->dev,
1520b741ab9dSGreg Kroah-Hartman 				"%s - type->init() failed, err: %d\n",
1521a8aef622SOliver Neukum 				__func__, err);
1522a8aef622SOliver Neukum 			return err;
1523a8aef622SOliver Neukum 		}
1524a8aef622SOliver Neukum 	}
1525a8aef622SOliver Neukum 
1526a8aef622SOliver Neukum 	/* restart IO if needed */
1527a8aef622SOliver Neukum 	mutex_lock(&input->mutex);
1528a8aef622SOliver Neukum 	if (input->users)
1529a8aef622SOliver Neukum 		err = usb_submit_urb(usbtouch->irq, GFP_NOIO);
1530a8aef622SOliver Neukum 	mutex_unlock(&input->mutex);
1531a8aef622SOliver Neukum 
1532a8aef622SOliver Neukum 	return err;
1533a8aef622SOliver Neukum }
1534a8aef622SOliver Neukum 
1535d05e84e6SDmitry Torokhov static void usbtouch_free_buffers(struct usb_device *udev,
1536d05e84e6SDmitry Torokhov 				  struct usbtouch_usb *usbtouch)
1537d05e84e6SDmitry Torokhov {
15384ef38351SChristian Engelmayer 	usb_free_coherent(udev, usbtouch->data_size,
1539d05e84e6SDmitry Torokhov 			  usbtouch->data, usbtouch->data_dma);
1540d05e84e6SDmitry Torokhov 	kfree(usbtouch->buffer);
1541d05e84e6SDmitry Torokhov }
1542d05e84e6SDmitry Torokhov 
1543f4a5e359SOndrej Zary static struct usb_endpoint_descriptor *
1544f4a5e359SOndrej Zary usbtouch_get_input_endpoint(struct usb_host_interface *interface)
1545f4a5e359SOndrej Zary {
1546f4a5e359SOndrej Zary 	int i;
1547f4a5e359SOndrej Zary 
1548f4a5e359SOndrej Zary 	for (i = 0; i < interface->desc.bNumEndpoints; i++)
1549f4a5e359SOndrej Zary 		if (usb_endpoint_dir_in(&interface->endpoint[i].desc))
1550f4a5e359SOndrej Zary 			return &interface->endpoint[i].desc;
1551f4a5e359SOndrej Zary 
1552f4a5e359SOndrej Zary 	return NULL;
1553f4a5e359SOndrej Zary }
1554d05e84e6SDmitry Torokhov 
1555d05e84e6SDmitry Torokhov static int usbtouch_probe(struct usb_interface *intf,
1556d05e84e6SDmitry Torokhov 			  const struct usb_device_id *id)
1557d05e84e6SDmitry Torokhov {
1558d05e84e6SDmitry Torokhov 	struct usbtouch_usb *usbtouch;
1559d05e84e6SDmitry Torokhov 	struct input_dev *input_dev;
1560d05e84e6SDmitry Torokhov 	struct usb_endpoint_descriptor *endpoint;
1561d05e84e6SDmitry Torokhov 	struct usb_device *udev = interface_to_usbdev(intf);
1562d05e84e6SDmitry Torokhov 	struct usbtouch_device_info *type;
1563d05e84e6SDmitry Torokhov 	int err = -ENOMEM;
1564d05e84e6SDmitry Torokhov 
1565ec42d448SDaniel Ritz 	/* some devices are ignored */
1566ec42d448SDaniel Ritz 	if (id->driver_info == DEVTYPE_IGNORE)
1567ec42d448SDaniel Ritz 		return -ENODEV;
1568ec42d448SDaniel Ritz 
1569f4a5e359SOndrej Zary 	endpoint = usbtouch_get_input_endpoint(intf->cur_altsetting);
1570f4a5e359SOndrej Zary 	if (!endpoint)
1571f4a5e359SOndrej Zary 		return -ENXIO;
1572d05e84e6SDmitry Torokhov 
1573d05e84e6SDmitry Torokhov 	usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL);
1574d05e84e6SDmitry Torokhov 	input_dev = input_allocate_device();
1575d05e84e6SDmitry Torokhov 	if (!usbtouch || !input_dev)
1576d05e84e6SDmitry Torokhov 		goto out_free;
1577d05e84e6SDmitry Torokhov 
1578d05e84e6SDmitry Torokhov 	type = &usbtouch_dev_info[id->driver_info];
1579d05e84e6SDmitry Torokhov 	usbtouch->type = type;
1580d05e84e6SDmitry Torokhov 	if (!type->process_pkt)
1581d05e84e6SDmitry Torokhov 		type->process_pkt = usbtouch_process_pkt;
1582d05e84e6SDmitry Torokhov 
15834ef38351SChristian Engelmayer 	usbtouch->data_size = type->rept_size;
15844ef38351SChristian Engelmayer 	if (type->get_pkt_len) {
15854ef38351SChristian Engelmayer 		/*
15864ef38351SChristian Engelmayer 		 * When dealing with variable-length packets we should
15874ef38351SChristian Engelmayer 		 * not request more than wMaxPacketSize bytes at once
15884ef38351SChristian Engelmayer 		 * as we do not know if there is more data coming or
15894ef38351SChristian Engelmayer 		 * we filled exactly wMaxPacketSize bytes and there is
15904ef38351SChristian Engelmayer 		 * nothing else.
15914ef38351SChristian Engelmayer 		 */
15924ef38351SChristian Engelmayer 		usbtouch->data_size = min(usbtouch->data_size,
15934ef38351SChristian Engelmayer 					  usb_endpoint_maxp(endpoint));
15944ef38351SChristian Engelmayer 	}
15954ef38351SChristian Engelmayer 
15964ef38351SChristian Engelmayer 	usbtouch->data = usb_alloc_coherent(udev, usbtouch->data_size,
1597d05e84e6SDmitry Torokhov 					    GFP_KERNEL, &usbtouch->data_dma);
1598d05e84e6SDmitry Torokhov 	if (!usbtouch->data)
1599d05e84e6SDmitry Torokhov 		goto out_free;
1600d05e84e6SDmitry Torokhov 
160162aa366dSDaniel Ritz 	if (type->get_pkt_len) {
1602d05e84e6SDmitry Torokhov 		usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL);
1603d05e84e6SDmitry Torokhov 		if (!usbtouch->buffer)
1604d05e84e6SDmitry Torokhov 			goto out_free_buffers;
1605d05e84e6SDmitry Torokhov 	}
1606d05e84e6SDmitry Torokhov 
1607d05e84e6SDmitry Torokhov 	usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
1608d05e84e6SDmitry Torokhov 	if (!usbtouch->irq) {
1609b741ab9dSGreg Kroah-Hartman 		dev_dbg(&intf->dev,
1610b741ab9dSGreg Kroah-Hartman 			"%s - usb_alloc_urb failed: usbtouch->irq\n", __func__);
1611d05e84e6SDmitry Torokhov 		goto out_free_buffers;
1612d05e84e6SDmitry Torokhov 	}
1613d05e84e6SDmitry Torokhov 
1614fea4d14bSOndrej Zary 	usbtouch->interface = intf;
1615d05e84e6SDmitry Torokhov 	usbtouch->input = input_dev;
1616d05e84e6SDmitry Torokhov 
1617d05e84e6SDmitry Torokhov 	if (udev->manufacturer)
1618d05e84e6SDmitry Torokhov 		strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name));
1619d05e84e6SDmitry Torokhov 
1620d05e84e6SDmitry Torokhov 	if (udev->product) {
1621d05e84e6SDmitry Torokhov 		if (udev->manufacturer)
1622d05e84e6SDmitry Torokhov 			strlcat(usbtouch->name, " ", sizeof(usbtouch->name));
1623d05e84e6SDmitry Torokhov 		strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name));
1624d05e84e6SDmitry Torokhov 	}
1625d05e84e6SDmitry Torokhov 
1626d05e84e6SDmitry Torokhov 	if (!strlen(usbtouch->name))
1627d05e84e6SDmitry Torokhov 		snprintf(usbtouch->name, sizeof(usbtouch->name),
1628d05e84e6SDmitry Torokhov 			"USB Touchscreen %04x:%04x",
1629d05e84e6SDmitry Torokhov 			 le16_to_cpu(udev->descriptor.idVendor),
1630d05e84e6SDmitry Torokhov 			 le16_to_cpu(udev->descriptor.idProduct));
1631d05e84e6SDmitry Torokhov 
1632d05e84e6SDmitry Torokhov 	usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys));
16337b6dff98SVladimir Shebordaev 	strlcat(usbtouch->phys, "/input0", sizeof(usbtouch->phys));
1634d05e84e6SDmitry Torokhov 
1635d05e84e6SDmitry Torokhov 	input_dev->name = usbtouch->name;
1636d05e84e6SDmitry Torokhov 	input_dev->phys = usbtouch->phys;
1637d05e84e6SDmitry Torokhov 	usb_to_input_id(udev, &input_dev->id);
1638d05e84e6SDmitry Torokhov 	input_dev->dev.parent = &intf->dev;
1639d05e84e6SDmitry Torokhov 
1640d05e84e6SDmitry Torokhov 	input_set_drvdata(input_dev, usbtouch);
1641d05e84e6SDmitry Torokhov 
1642d05e84e6SDmitry Torokhov 	input_dev->open = usbtouch_open;
1643d05e84e6SDmitry Torokhov 	input_dev->close = usbtouch_close;
1644d05e84e6SDmitry Torokhov 
16457b19ada2SJiri Slaby 	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
16467b19ada2SJiri Slaby 	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
1647d05e84e6SDmitry Torokhov 	input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0);
1648d05e84e6SDmitry Torokhov 	input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0);
1649d05e84e6SDmitry Torokhov 	if (type->max_press)
1650d05e84e6SDmitry Torokhov 		input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press,
1651d05e84e6SDmitry Torokhov 		                     type->max_press, 0, 0);
1652d05e84e6SDmitry Torokhov 
16535197424cSOndrej Zary 	if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT)
1654fea4d14bSOndrej Zary 		usb_fill_int_urb(usbtouch->irq, udev,
1655fea4d14bSOndrej Zary 			 usb_rcvintpipe(udev, endpoint->bEndpointAddress),
16564ef38351SChristian Engelmayer 			 usbtouch->data, usbtouch->data_size,
1657d05e84e6SDmitry Torokhov 			 usbtouch_irq, usbtouch, endpoint->bInterval);
16585197424cSOndrej Zary 	else
16595197424cSOndrej Zary 		usb_fill_bulk_urb(usbtouch->irq, udev,
16605197424cSOndrej Zary 			 usb_rcvbulkpipe(udev, endpoint->bEndpointAddress),
16614ef38351SChristian Engelmayer 			 usbtouch->data, usbtouch->data_size,
16625197424cSOndrej Zary 			 usbtouch_irq, usbtouch);
1663d05e84e6SDmitry Torokhov 
1664fea4d14bSOndrej Zary 	usbtouch->irq->dev = udev;
1665d05e84e6SDmitry Torokhov 	usbtouch->irq->transfer_dma = usbtouch->data_dma;
1666d05e84e6SDmitry Torokhov 	usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
1667d05e84e6SDmitry Torokhov 
1668a8aef622SOliver Neukum 	/* device specific allocations */
1669a8aef622SOliver Neukum 	if (type->alloc) {
1670a8aef622SOliver Neukum 		err = type->alloc(usbtouch);
1671a8aef622SOliver Neukum 		if (err) {
1672b741ab9dSGreg Kroah-Hartman 			dev_dbg(&intf->dev,
1673b741ab9dSGreg Kroah-Hartman 				"%s - type->alloc() failed, err: %d\n",
1674b741ab9dSGreg Kroah-Hartman 				__func__, err);
1675a8aef622SOliver Neukum 			goto out_free_urb;
1676a8aef622SOliver Neukum 		}
1677a8aef622SOliver Neukum 	}
1678a8aef622SOliver Neukum 
1679a8aef622SOliver Neukum 	/* device specific initialisation*/
1680d05e84e6SDmitry Torokhov 	if (type->init) {
1681d05e84e6SDmitry Torokhov 		err = type->init(usbtouch);
1682d05e84e6SDmitry Torokhov 		if (err) {
1683b741ab9dSGreg Kroah-Hartman 			dev_dbg(&intf->dev,
1684b741ab9dSGreg Kroah-Hartman 				"%s - type->init() failed, err: %d\n",
1685b741ab9dSGreg Kroah-Hartman 				__func__, err);
1686a8aef622SOliver Neukum 			goto out_do_exit;
1687d05e84e6SDmitry Torokhov 		}
1688d05e84e6SDmitry Torokhov 	}
1689d05e84e6SDmitry Torokhov 
1690d05e84e6SDmitry Torokhov 	err = input_register_device(usbtouch->input);
1691d05e84e6SDmitry Torokhov 	if (err) {
1692b741ab9dSGreg Kroah-Hartman 		dev_dbg(&intf->dev,
1693b741ab9dSGreg Kroah-Hartman 			"%s - input_register_device failed, err: %d\n",
1694b741ab9dSGreg Kroah-Hartman 			__func__, err);
16955197424cSOndrej Zary 		goto out_do_exit;
1696d05e84e6SDmitry Torokhov 	}
1697d05e84e6SDmitry Torokhov 
1698d05e84e6SDmitry Torokhov 	usb_set_intfdata(intf, usbtouch);
1699d05e84e6SDmitry Torokhov 
17001e87a430SOndrej Zary 	if (usbtouch->type->irq_always) {
17015d9efc59SOliver Neukum 		/* this can't fail */
17025d9efc59SOliver Neukum 		usb_autopm_get_interface(intf);
17031e87a430SOndrej Zary 		err = usb_submit_urb(usbtouch->irq, GFP_KERNEL);
17041e87a430SOndrej Zary 		if (err) {
17055d9efc59SOliver Neukum 			usb_autopm_put_interface(intf);
17060a5ebc88SGreg Kroah-Hartman 			dev_err(&intf->dev,
1707e27ad0feSGreg Kroah-Hartman 				"%s - usb_submit_urb failed with result: %d\n",
17081e87a430SOndrej Zary 				__func__, err);
17091e87a430SOndrej Zary 			goto out_unregister_input;
17101e87a430SOndrej Zary 		}
17111e87a430SOndrej Zary 	}
17122330ed18SDaniel Silverstone 
1713d05e84e6SDmitry Torokhov 	return 0;
1714d05e84e6SDmitry Torokhov 
17151e87a430SOndrej Zary out_unregister_input:
17161e87a430SOndrej Zary 	input_unregister_device(input_dev);
17171e87a430SOndrej Zary 	input_dev = NULL;
17185197424cSOndrej Zary out_do_exit:
17195197424cSOndrej Zary 	if (type->exit)
17205197424cSOndrej Zary 		type->exit(usbtouch);
17211e87a430SOndrej Zary out_free_urb:
17221e87a430SOndrej Zary 	usb_free_urb(usbtouch->irq);
1723d05e84e6SDmitry Torokhov out_free_buffers:
1724d05e84e6SDmitry Torokhov 	usbtouch_free_buffers(udev, usbtouch);
1725d05e84e6SDmitry Torokhov out_free:
1726d05e84e6SDmitry Torokhov 	input_free_device(input_dev);
1727d05e84e6SDmitry Torokhov 	kfree(usbtouch);
1728d05e84e6SDmitry Torokhov 	return err;
1729d05e84e6SDmitry Torokhov }
1730d05e84e6SDmitry Torokhov 
1731d05e84e6SDmitry Torokhov static void usbtouch_disconnect(struct usb_interface *intf)
1732d05e84e6SDmitry Torokhov {
1733d05e84e6SDmitry Torokhov 	struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
1734d05e84e6SDmitry Torokhov 
1735d05e84e6SDmitry Torokhov 	if (!usbtouch)
1736d05e84e6SDmitry Torokhov 		return;
1737d05e84e6SDmitry Torokhov 
17380a5ebc88SGreg Kroah-Hartman 	dev_dbg(&intf->dev,
1739b741ab9dSGreg Kroah-Hartman 		"%s - usbtouch is initialized, cleaning up\n", __func__);
1740b741ab9dSGreg Kroah-Hartman 
1741d05e84e6SDmitry Torokhov 	usb_set_intfdata(intf, NULL);
1742722232bcSOliver Neukum 	/* this will stop IO via close */
1743d05e84e6SDmitry Torokhov 	input_unregister_device(usbtouch->input);
1744d05e84e6SDmitry Torokhov 	usb_free_urb(usbtouch->irq);
17455197424cSOndrej Zary 	if (usbtouch->type->exit)
17465197424cSOndrej Zary 		usbtouch->type->exit(usbtouch);
1747d05e84e6SDmitry Torokhov 	usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch);
1748d05e84e6SDmitry Torokhov 	kfree(usbtouch);
1749d05e84e6SDmitry Torokhov }
1750d05e84e6SDmitry Torokhov 
1751d05e84e6SDmitry Torokhov MODULE_DEVICE_TABLE(usb, usbtouch_devices);
1752d05e84e6SDmitry Torokhov 
1753d05e84e6SDmitry Torokhov static struct usb_driver usbtouch_driver = {
1754d05e84e6SDmitry Torokhov 	.name		= "usbtouchscreen",
1755d05e84e6SDmitry Torokhov 	.probe		= usbtouch_probe,
1756d05e84e6SDmitry Torokhov 	.disconnect	= usbtouch_disconnect,
1757ed4299e1SOliver Neukum 	.suspend	= usbtouch_suspend,
1758ed4299e1SOliver Neukum 	.resume		= usbtouch_resume,
1759a8aef622SOliver Neukum 	.reset_resume	= usbtouch_reset_resume,
1760d05e84e6SDmitry Torokhov 	.id_table	= usbtouch_devices,
17615d9efc59SOliver Neukum 	.supports_autosuspend = 1,
1762d05e84e6SDmitry Torokhov };
1763d05e84e6SDmitry Torokhov 
176408642e7cSGreg Kroah-Hartman module_usb_driver(usbtouch_driver);
1765d05e84e6SDmitry Torokhov 
1766d05e84e6SDmitry Torokhov MODULE_AUTHOR(DRIVER_AUTHOR);
1767d05e84e6SDmitry Torokhov MODULE_DESCRIPTION(DRIVER_DESC);
1768d05e84e6SDmitry Torokhov MODULE_LICENSE("GPL");
1769d05e84e6SDmitry Torokhov 
1770d05e84e6SDmitry Torokhov MODULE_ALIAS("touchkitusb");
1771d05e84e6SDmitry Torokhov MODULE_ALIAS("itmtouch");
1772d05e84e6SDmitry Torokhov MODULE_ALIAS("mtouchusb");
1773