| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1 | /****************************************************************************** | 
|  | 2 | * usbtouchscreen.c | 
|  | 3 | * Driver for USB Touchscreens, supporting those devices: | 
|  | 4 | *  - eGalax Touchkit | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 5 | *    includes eTurboTouch CT-410/510/700 | 
|  | 6 | *  - 3M/Microtouch  EX II series | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 7 | *  - ITM | 
|  | 8 | *  - PanJit TouchSet | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 9 | *  - eTurboTouch | 
|  | 10 | *  - Gunze AHL61 | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 11 | *  - DMC TSC-10/25 | 
| Ondrej Zary | df561fc | 2007-07-03 01:55:03 -0400 | [diff] [blame] | 12 | *  - IRTOUCHSYSTEMS/UNITOP | 
| Ondrej Zary | a14a840 | 2007-09-04 23:45:01 -0400 | [diff] [blame] | 13 | *  - IdealTEK URTC1000 | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 14 | *  - General Touch | 
| Jerrold Jones | 14e4020 | 2007-10-22 00:59:47 -0400 | [diff] [blame] | 15 | *  - GoTop Super_Q2/GogoPen/PenPower tablets | 
| Jim Persson | f737069 | 2009-07-07 22:07:59 -0700 | [diff] [blame] | 16 | *  - JASTEC USB touch controller/DigiTech DTR-02U | 
| Daniel Silverstone | 2330ed1 | 2009-11-23 08:38:16 -0800 | [diff] [blame] | 17 | *  - Zytronic capacitive touchscreen | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 18 | *  - NEXIO/iNexio | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 19 | * | 
| Jerrold Jones | 14e4020 | 2007-10-22 00:59:47 -0400 | [diff] [blame] | 20 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 21 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) | 
|  | 22 | * | 
|  | 23 | * This program is free software; you can redistribute it and/or | 
|  | 24 | * modify it under the terms of the GNU General Public License as | 
|  | 25 | * published by the Free Software Foundation; either version 2 of the | 
|  | 26 | * License, or (at your option) any later version. | 
|  | 27 | * | 
|  | 28 | * This program is distributed in the hope that it will be useful, but | 
|  | 29 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 30 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | 31 | * General Public License for more details. | 
|  | 32 | * | 
|  | 33 | * You should have received a copy of the GNU General Public License | 
|  | 34 | * along with this program; if not, write to the Free Software | 
|  | 35 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 
|  | 36 | * | 
|  | 37 | * Driver is based on touchkitusb.c | 
|  | 38 | * - ITM parts are from itmtouch.c | 
|  | 39 | * - 3M parts are from mtouchusb.c | 
|  | 40 | * - PanJit parts are from an unmerged driver by Lanslott Gish | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 41 | * - DMC TSC 10/25 are from Holger Schurig, with ideas from an unmerged | 
|  | 42 | *   driver from Marius Vollmer | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 43 | * | 
|  | 44 | *****************************************************************************/ | 
|  | 45 |  | 
|  | 46 | //#define DEBUG | 
|  | 47 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 48 | #include <linux/kernel.h> | 
|  | 49 | #include <linux/slab.h> | 
|  | 50 | #include <linux/input.h> | 
|  | 51 | #include <linux/module.h> | 
|  | 52 | #include <linux/init.h> | 
|  | 53 | #include <linux/usb.h> | 
| David Brownell | ae0dadc | 2006-06-13 10:04:34 -0700 | [diff] [blame] | 54 | #include <linux/usb/input.h> | 
| Daniel Ritz | ec42d44 | 2008-07-03 10:45:37 -0400 | [diff] [blame] | 55 | #include <linux/hid.h> | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 56 |  | 
|  | 57 |  | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 58 | #define DRIVER_VERSION		"v0.6" | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 59 | #define DRIVER_AUTHOR		"Daniel Ritz <daniel.ritz@gmx.ch>" | 
|  | 60 | #define DRIVER_DESC		"USB Touchscreen Driver" | 
|  | 61 |  | 
|  | 62 | static int swap_xy; | 
|  | 63 | module_param(swap_xy, bool, 0644); | 
|  | 64 | MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); | 
|  | 65 |  | 
| Dan Streetman | c9cbf3d | 2009-01-10 23:44:22 -0800 | [diff] [blame] | 66 | static int hwcalib_xy; | 
|  | 67 | module_param(hwcalib_xy, bool, 0644); | 
|  | 68 | MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available"); | 
|  | 69 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 70 | /* device specifc data/functions */ | 
|  | 71 | struct usbtouch_usb; | 
|  | 72 | struct usbtouch_device_info { | 
|  | 73 | int min_xc, max_xc; | 
|  | 74 | int min_yc, max_yc; | 
|  | 75 | int min_press, max_press; | 
|  | 76 | int rept_size; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 77 |  | 
| Daniel Silverstone | 2330ed1 | 2009-11-23 08:38:16 -0800 | [diff] [blame] | 78 | /* | 
|  | 79 | * Always service the USB devices irq not just when the input device is | 
|  | 80 | * open. This is useful when devices have a watchdog which prevents us | 
|  | 81 | * from periodically polling the device. Leave this unset unless your | 
|  | 82 | * touchscreen device requires it, as it does consume more of the USB | 
|  | 83 | * bandwidth. | 
|  | 84 | */ | 
|  | 85 | bool irq_always; | 
|  | 86 |  | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 87 | void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len); | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 88 |  | 
|  | 89 | /* | 
|  | 90 | * used to get the packet len. possible return values: | 
|  | 91 | * > 0: packet len | 
|  | 92 | * = 0: skip one byte | 
|  | 93 | * < 0: -return value more bytes needed | 
|  | 94 | */ | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 95 | int  (*get_pkt_len) (unsigned char *pkt, int len); | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 96 |  | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 97 | int  (*read_data)   (struct usbtouch_usb *usbtouch, unsigned char *pkt); | 
| Oliver Neukum | a8aef62 | 2010-07-15 09:21:40 -0700 | [diff] [blame] | 98 | int  (*alloc)       (struct usbtouch_usb *usbtouch); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 99 | int  (*init)        (struct usbtouch_usb *usbtouch); | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 100 | void (*exit)	    (struct usbtouch_usb *usbtouch); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 101 | }; | 
|  | 102 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 103 | /* a usbtouch device */ | 
|  | 104 | struct usbtouch_usb { | 
|  | 105 | unsigned char *data; | 
|  | 106 | dma_addr_t data_dma; | 
|  | 107 | unsigned char *buffer; | 
|  | 108 | int buf_len; | 
|  | 109 | struct urb *irq; | 
| Ondrej Zary | fea4d14 | 2010-02-03 23:46:48 -0800 | [diff] [blame] | 110 | struct usb_interface *interface; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 111 | struct input_dev *input; | 
|  | 112 | struct usbtouch_device_info *type; | 
|  | 113 | char name[128]; | 
|  | 114 | char phys[64]; | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 115 | void *priv; | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 116 |  | 
|  | 117 | int x, y; | 
|  | 118 | int touch, press; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 119 | }; | 
|  | 120 |  | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 121 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 122 | /* device types */ | 
|  | 123 | enum { | 
| Daniel Ritz | ec42d44 | 2008-07-03 10:45:37 -0400 | [diff] [blame] | 124 | DEVTYPE_IGNORE = -1, | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 125 | DEVTYPE_EGALAX, | 
|  | 126 | DEVTYPE_PANJIT, | 
|  | 127 | DEVTYPE_3M, | 
|  | 128 | DEVTYPE_ITM, | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 129 | DEVTYPE_ETURBO, | 
|  | 130 | DEVTYPE_GUNZE, | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 131 | DEVTYPE_DMC_TSC10, | 
| Ondrej Zary | df561fc | 2007-07-03 01:55:03 -0400 | [diff] [blame] | 132 | DEVTYPE_IRTOUCH, | 
| Ondrej Zary | a14a840 | 2007-09-04 23:45:01 -0400 | [diff] [blame] | 133 | DEVTYPE_IDEALTEK, | 
| Ilya Frolov | 9d5657d | 2007-10-12 14:19:40 -0400 | [diff] [blame] | 134 | DEVTYPE_GENERAL_TOUCH, | 
| Jerrold Jones | 14e4020 | 2007-10-22 00:59:47 -0400 | [diff] [blame] | 135 | DEVTYPE_GOTOP, | 
| Jim Persson | f737069 | 2009-07-07 22:07:59 -0700 | [diff] [blame] | 136 | DEVTYPE_JASTEC, | 
| Florian Echtler | 9e3b258 | 2009-07-27 17:35:39 -0700 | [diff] [blame] | 137 | DEVTYPE_E2I, | 
| Daniel Silverstone | 2330ed1 | 2009-11-23 08:38:16 -0800 | [diff] [blame] | 138 | DEVTYPE_ZYTRONIC, | 
| Petr Å tetiar | 38771bb | 2010-06-28 09:38:48 -0700 | [diff] [blame] | 139 | DEVTYPE_TC45USB, | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 140 | DEVTYPE_NEXIO, | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 141 | }; | 
|  | 142 |  | 
| Daniel Ritz | ec42d44 | 2008-07-03 10:45:37 -0400 | [diff] [blame] | 143 | #define USB_DEVICE_HID_CLASS(vend, prod) \ | 
|  | 144 | .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \ | 
| Daniel Ritz | 139ebe8 | 2009-02-28 12:50:54 -0800 | [diff] [blame] | 145 | | USB_DEVICE_ID_MATCH_INT_PROTOCOL \ | 
| Daniel Ritz | ec42d44 | 2008-07-03 10:45:37 -0400 | [diff] [blame] | 146 | | USB_DEVICE_ID_MATCH_DEVICE, \ | 
|  | 147 | .idVendor = (vend), \ | 
|  | 148 | .idProduct = (prod), \ | 
|  | 149 | .bInterfaceClass = USB_INTERFACE_CLASS_HID, \ | 
|  | 150 | .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE | 
|  | 151 |  | 
| Márton Németh | 9cb3ce5 | 2010-01-10 23:59:05 -0800 | [diff] [blame] | 152 | static const struct usb_device_id usbtouch_devices[] = { | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 153 | #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX | 
| Daniel Ritz | ec42d44 | 2008-07-03 10:45:37 -0400 | [diff] [blame] | 154 | /* ignore the HID capable devices, handled by usbhid */ | 
|  | 155 | {USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE}, | 
|  | 156 | {USB_DEVICE_HID_CLASS(0x0eef, 0x0002), .driver_info = DEVTYPE_IGNORE}, | 
|  | 157 |  | 
|  | 158 | /* normal device IDs */ | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 159 | {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX}, | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 160 | {USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX}, | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 161 | {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX}, | 
|  | 162 | {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX}, | 
|  | 163 | {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX}, | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 164 | {USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX}, | 
|  | 165 | {USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX}, | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 166 | #endif | 
|  | 167 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 168 | #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 169 | {USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT}, | 
|  | 170 | {USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT}, | 
|  | 171 | {USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT}, | 
|  | 172 | {USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT}, | 
|  | 173 | #endif | 
|  | 174 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 175 | #ifdef CONFIG_TOUCHSCREEN_USB_3M | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 176 | {USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M}, | 
|  | 177 | #endif | 
|  | 178 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 179 | #ifdef CONFIG_TOUCHSCREEN_USB_ITM | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 180 | {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, | 
| Glenn Sommer | 0991050 | 2010-11-22 12:00:05 -0800 | [diff] [blame] | 181 | {USB_DEVICE(0x16e3, 0xf9e9), .driver_info = DEVTYPE_ITM}, | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 182 | #endif | 
|  | 183 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 184 | #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 185 | {USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO}, | 
|  | 186 | #endif | 
|  | 187 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 188 | #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 189 | {USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE}, | 
|  | 190 | #endif | 
|  | 191 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 192 | #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 193 | {USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10}, | 
|  | 194 | #endif | 
|  | 195 |  | 
| Ondrej Zary | df561fc | 2007-07-03 01:55:03 -0400 | [diff] [blame] | 196 | #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH | 
|  | 197 | {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, | 
|  | 198 | {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, | 
|  | 199 | #endif | 
|  | 200 |  | 
| Ondrej Zary | a14a840 | 2007-09-04 23:45:01 -0400 | [diff] [blame] | 201 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK | 
|  | 202 | {USB_DEVICE(0x1391, 0x1000), .driver_info = DEVTYPE_IDEALTEK}, | 
|  | 203 | #endif | 
|  | 204 |  | 
| Ilya Frolov | 9d5657d | 2007-10-12 14:19:40 -0400 | [diff] [blame] | 205 | #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH | 
|  | 206 | {USB_DEVICE(0x0dfc, 0x0001), .driver_info = DEVTYPE_GENERAL_TOUCH}, | 
|  | 207 | #endif | 
|  | 208 |  | 
| Jerrold Jones | 14e4020 | 2007-10-22 00:59:47 -0400 | [diff] [blame] | 209 | #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP | 
|  | 210 | {USB_DEVICE(0x08f2, 0x007f), .driver_info = DEVTYPE_GOTOP}, | 
|  | 211 | {USB_DEVICE(0x08f2, 0x00ce), .driver_info = DEVTYPE_GOTOP}, | 
|  | 212 | {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP}, | 
|  | 213 | #endif | 
|  | 214 |  | 
| Jim Persson | f737069 | 2009-07-07 22:07:59 -0700 | [diff] [blame] | 215 | #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC | 
|  | 216 | {USB_DEVICE(0x0f92, 0x0001), .driver_info = DEVTYPE_JASTEC}, | 
|  | 217 | #endif | 
|  | 218 |  | 
| Florian Echtler | 9e3b258 | 2009-07-27 17:35:39 -0700 | [diff] [blame] | 219 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | 
|  | 220 | {USB_DEVICE(0x1ac7, 0x0001), .driver_info = DEVTYPE_E2I}, | 
|  | 221 | #endif | 
| Daniel Silverstone | 2330ed1 | 2009-11-23 08:38:16 -0800 | [diff] [blame] | 222 |  | 
|  | 223 | #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC | 
|  | 224 | {USB_DEVICE(0x14c8, 0x0003), .driver_info = DEVTYPE_ZYTRONIC}, | 
|  | 225 | #endif | 
|  | 226 |  | 
| Petr Å tetiar | 38771bb | 2010-06-28 09:38:48 -0700 | [diff] [blame] | 227 | #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB | 
|  | 228 | /* TC5UH */ | 
|  | 229 | {USB_DEVICE(0x0664, 0x0309), .driver_info = DEVTYPE_TC45USB}, | 
|  | 230 | /* TC4UM */ | 
|  | 231 | {USB_DEVICE(0x0664, 0x0306), .driver_info = DEVTYPE_TC45USB}, | 
| Petr Å tetiar | dbe1420 | 2009-11-29 23:37:07 -0800 | [diff] [blame] | 232 | #endif | 
|  | 233 |  | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 234 | #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO | 
|  | 235 | /* data interface only */ | 
|  | 236 | {USB_DEVICE_AND_INTERFACE_INFO(0x10f0, 0x2002, 0x0a, 0x00, 0x00), | 
|  | 237 | .driver_info = DEVTYPE_NEXIO}, | 
|  | 238 | {USB_DEVICE_AND_INTERFACE_INFO(0x1870, 0x0001, 0x0a, 0x00, 0x00), | 
|  | 239 | .driver_info = DEVTYPE_NEXIO}, | 
|  | 240 | #endif | 
|  | 241 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 242 | {} | 
|  | 243 | }; | 
|  | 244 |  | 
|  | 245 |  | 
|  | 246 | /***************************************************************************** | 
| Florian Echtler | 9e3b258 | 2009-07-27 17:35:39 -0700 | [diff] [blame] | 247 | * e2i Part | 
|  | 248 | */ | 
|  | 249 |  | 
|  | 250 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | 
|  | 251 | static int e2i_init(struct usbtouch_usb *usbtouch) | 
|  | 252 | { | 
|  | 253 | int ret; | 
| Ondrej Zary | fea4d14 | 2010-02-03 23:46:48 -0800 | [diff] [blame] | 254 | struct usb_device *udev = interface_to_usbdev(usbtouch->interface); | 
| Florian Echtler | 9e3b258 | 2009-07-27 17:35:39 -0700 | [diff] [blame] | 255 |  | 
| Ondrej Zary | fea4d14 | 2010-02-03 23:46:48 -0800 | [diff] [blame] | 256 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | 
| Florian Echtler | 9e3b258 | 2009-07-27 17:35:39 -0700 | [diff] [blame] | 257 | 0x01, 0x02, 0x0000, 0x0081, | 
|  | 258 | NULL, 0, USB_CTRL_SET_TIMEOUT); | 
|  | 259 |  | 
|  | 260 | dbg("%s - usb_control_msg - E2I_RESET - bytes|err: %d", | 
|  | 261 | __func__, ret); | 
|  | 262 | return ret; | 
|  | 263 | } | 
|  | 264 |  | 
|  | 265 | static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
|  | 266 | { | 
|  | 267 | int tmp = (pkt[0] << 8) | pkt[1]; | 
|  | 268 | dev->x  = (pkt[2] << 8) | pkt[3]; | 
|  | 269 | dev->y  = (pkt[4] << 8) | pkt[5]; | 
|  | 270 |  | 
|  | 271 | tmp = tmp - 0xA000; | 
|  | 272 | dev->touch = (tmp > 0); | 
|  | 273 | dev->press = (tmp > 0 ? tmp : 0); | 
|  | 274 |  | 
|  | 275 | return 1; | 
|  | 276 | } | 
|  | 277 | #endif | 
|  | 278 |  | 
|  | 279 |  | 
|  | 280 | /***************************************************************************** | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 281 | * eGalax part | 
|  | 282 | */ | 
|  | 283 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 284 | #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 285 |  | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 286 | #ifndef MULTI_PACKET | 
|  | 287 | #define MULTI_PACKET | 
|  | 288 | #endif | 
|  | 289 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 290 | #define EGALAX_PKT_TYPE_MASK		0xFE | 
|  | 291 | #define EGALAX_PKT_TYPE_REPT		0x80 | 
|  | 292 | #define EGALAX_PKT_TYPE_DIAG		0x0A | 
|  | 293 |  | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 294 | static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 295 | { | 
|  | 296 | if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) | 
|  | 297 | return 0; | 
|  | 298 |  | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 299 | dev->x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F); | 
|  | 300 | dev->y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F); | 
|  | 301 | dev->touch = pkt[0] & 0x01; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 302 |  | 
|  | 303 | return 1; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 304 | } | 
|  | 305 |  | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 306 | static int egalax_get_pkt_len(unsigned char *buf, int len) | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 307 | { | 
|  | 308 | switch (buf[0] & EGALAX_PKT_TYPE_MASK) { | 
|  | 309 | case EGALAX_PKT_TYPE_REPT: | 
|  | 310 | return 5; | 
|  | 311 |  | 
|  | 312 | case EGALAX_PKT_TYPE_DIAG: | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 313 | if (len < 2) | 
|  | 314 | return -1; | 
|  | 315 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 316 | return buf[1] + 2; | 
|  | 317 | } | 
|  | 318 |  | 
|  | 319 | return 0; | 
|  | 320 | } | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 321 | #endif | 
|  | 322 |  | 
|  | 323 |  | 
|  | 324 | /***************************************************************************** | 
|  | 325 | * PanJit Part | 
|  | 326 | */ | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 327 | #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 328 | static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 329 | { | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 330 | dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; | 
|  | 331 | dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; | 
|  | 332 | dev->touch = pkt[0] & 0x01; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 333 |  | 
|  | 334 | return 1; | 
|  | 335 | } | 
|  | 336 | #endif | 
|  | 337 |  | 
|  | 338 |  | 
|  | 339 | /***************************************************************************** | 
|  | 340 | * 3M/Microtouch Part | 
|  | 341 | */ | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 342 | #ifdef CONFIG_TOUCHSCREEN_USB_3M | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 343 |  | 
|  | 344 | #define MTOUCHUSB_ASYNC_REPORT          1 | 
|  | 345 | #define MTOUCHUSB_RESET                 7 | 
|  | 346 | #define MTOUCHUSB_REQ_CTRLLR_ID         10 | 
|  | 347 |  | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 348 | static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 349 | { | 
| Dan Streetman | c9cbf3d | 2009-01-10 23:44:22 -0800 | [diff] [blame] | 350 | if (hwcalib_xy) { | 
|  | 351 | dev->x = (pkt[4] << 8) | pkt[3]; | 
|  | 352 | dev->y = 0xffff - ((pkt[6] << 8) | pkt[5]); | 
|  | 353 | } else { | 
|  | 354 | dev->x = (pkt[8] << 8) | pkt[7]; | 
|  | 355 | dev->y = (pkt[10] << 8) | pkt[9]; | 
|  | 356 | } | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 357 | dev->touch = (pkt[2] & 0x40) ? 1 : 0; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 358 |  | 
|  | 359 | return 1; | 
|  | 360 | } | 
|  | 361 |  | 
|  | 362 | static int mtouch_init(struct usbtouch_usb *usbtouch) | 
|  | 363 | { | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 364 | int ret, i; | 
| Ondrej Zary | fea4d14 | 2010-02-03 23:46:48 -0800 | [diff] [blame] | 365 | struct usb_device *udev = interface_to_usbdev(usbtouch->interface); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 366 |  | 
| Ondrej Zary | fea4d14 | 2010-02-03 23:46:48 -0800 | [diff] [blame] | 367 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 368 | MTOUCHUSB_RESET, | 
|  | 369 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 
|  | 370 | 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); | 
|  | 371 | dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", | 
| Harvey Harrison | ea3e6c5 | 2008-05-05 11:36:18 -0400 | [diff] [blame] | 372 | __func__, ret); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 373 | if (ret < 0) | 
|  | 374 | return ret; | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 375 | msleep(150); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 376 |  | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 377 | for (i = 0; i < 3; i++) { | 
| Ondrej Zary | fea4d14 | 2010-02-03 23:46:48 -0800 | [diff] [blame] | 378 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 379 | MTOUCHUSB_ASYNC_REPORT, | 
|  | 380 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 
|  | 381 | 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); | 
|  | 382 | dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", | 
| Harvey Harrison | ea3e6c5 | 2008-05-05 11:36:18 -0400 | [diff] [blame] | 383 | __func__, ret); | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 384 | if (ret >= 0) | 
|  | 385 | break; | 
|  | 386 | if (ret != -EPIPE) | 
|  | 387 | return ret; | 
|  | 388 | } | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 389 |  | 
| Dan Streetman | c9cbf3d | 2009-01-10 23:44:22 -0800 | [diff] [blame] | 390 | /* Default min/max xy are the raw values, override if using hw-calib */ | 
|  | 391 | if (hwcalib_xy) { | 
|  | 392 | input_set_abs_params(usbtouch->input, ABS_X, 0, 0xffff, 0, 0); | 
|  | 393 | input_set_abs_params(usbtouch->input, ABS_Y, 0, 0xffff, 0, 0); | 
|  | 394 | } | 
|  | 395 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 396 | return 0; | 
|  | 397 | } | 
|  | 398 | #endif | 
|  | 399 |  | 
|  | 400 |  | 
|  | 401 | /***************************************************************************** | 
|  | 402 | * ITM Part | 
|  | 403 | */ | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 404 | #ifdef CONFIG_TOUCHSCREEN_USB_ITM | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 405 | static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 406 | { | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 407 | int touch; | 
|  | 408 | /* | 
|  | 409 | * ITM devices report invalid x/y data if not touched. | 
|  | 410 | * if the screen was touched before but is not touched any more | 
|  | 411 | * report touch as 0 with the last valid x/y data once. then stop | 
|  | 412 | * reporting data until touched again. | 
|  | 413 | */ | 
|  | 414 | dev->press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 415 |  | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 416 | touch = ~pkt[7] & 0x20; | 
|  | 417 | if (!touch) { | 
|  | 418 | if (dev->touch) { | 
|  | 419 | dev->touch = 0; | 
|  | 420 | return 1; | 
|  | 421 | } | 
|  | 422 |  | 
|  | 423 | return 0; | 
|  | 424 | } | 
|  | 425 |  | 
|  | 426 | dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F); | 
|  | 427 | dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F); | 
|  | 428 | dev->touch = touch; | 
|  | 429 |  | 
|  | 430 | return 1; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 431 | } | 
|  | 432 | #endif | 
|  | 433 |  | 
|  | 434 |  | 
|  | 435 | /***************************************************************************** | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 436 | * eTurboTouch part | 
|  | 437 | */ | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 438 | #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 439 | #ifndef MULTI_PACKET | 
|  | 440 | #define MULTI_PACKET | 
|  | 441 | #endif | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 442 | static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 443 | { | 
|  | 444 | unsigned int shift; | 
|  | 445 |  | 
|  | 446 | /* packets should start with sync */ | 
|  | 447 | if (!(pkt[0] & 0x80)) | 
|  | 448 | return 0; | 
|  | 449 |  | 
|  | 450 | shift = (6 - (pkt[0] & 0x03)); | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 451 | dev->x = ((pkt[3] << 7) | pkt[4]) >> shift; | 
|  | 452 | dev->y = ((pkt[1] << 7) | pkt[2]) >> shift; | 
|  | 453 | dev->touch = (pkt[0] & 0x10) ? 1 : 0; | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 454 |  | 
|  | 455 | return 1; | 
|  | 456 | } | 
|  | 457 |  | 
|  | 458 | static int eturbo_get_pkt_len(unsigned char *buf, int len) | 
|  | 459 | { | 
|  | 460 | if (buf[0] & 0x80) | 
|  | 461 | return 5; | 
|  | 462 | if (buf[0] == 0x01) | 
|  | 463 | return 3; | 
|  | 464 | return 0; | 
|  | 465 | } | 
|  | 466 | #endif | 
|  | 467 |  | 
|  | 468 |  | 
|  | 469 | /***************************************************************************** | 
|  | 470 | * Gunze part | 
|  | 471 | */ | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 472 | #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 473 | static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 474 | { | 
|  | 475 | if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80)) | 
|  | 476 | return 0; | 
|  | 477 |  | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 478 | dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F); | 
|  | 479 | dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F); | 
|  | 480 | dev->touch = pkt[0] & 0x20; | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 481 |  | 
|  | 482 | return 1; | 
|  | 483 | } | 
|  | 484 | #endif | 
|  | 485 |  | 
|  | 486 | /***************************************************************************** | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 487 | * DMC TSC-10/25 Part | 
|  | 488 | * | 
|  | 489 | * Documentation about the controller and it's protocol can be found at | 
|  | 490 | *   http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf | 
|  | 491 | *   http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf | 
|  | 492 | */ | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 493 | #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 494 |  | 
|  | 495 | /* supported data rates. currently using 130 */ | 
|  | 496 | #define TSC10_RATE_POINT	0x50 | 
|  | 497 | #define TSC10_RATE_30		0x40 | 
|  | 498 | #define TSC10_RATE_50		0x41 | 
|  | 499 | #define TSC10_RATE_80		0x42 | 
|  | 500 | #define TSC10_RATE_100		0x43 | 
|  | 501 | #define TSC10_RATE_130		0x44 | 
|  | 502 | #define TSC10_RATE_150		0x45 | 
|  | 503 |  | 
|  | 504 | /* commands */ | 
|  | 505 | #define TSC10_CMD_RESET		0x55 | 
|  | 506 | #define TSC10_CMD_RATE		0x05 | 
|  | 507 | #define TSC10_CMD_DATA1		0x01 | 
|  | 508 |  | 
|  | 509 | static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) | 
|  | 510 | { | 
| Ondrej Zary | fea4d14 | 2010-02-03 23:46:48 -0800 | [diff] [blame] | 511 | struct usb_device *dev = interface_to_usbdev(usbtouch->interface); | 
| Oliver Neukum | 76d057c | 2008-04-04 15:31:47 -0400 | [diff] [blame] | 512 | int ret = -ENOMEM; | 
|  | 513 | unsigned char *buf; | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 514 |  | 
| Oliver Neukum | a8aef62 | 2010-07-15 09:21:40 -0700 | [diff] [blame] | 515 | buf = kmalloc(2, GFP_NOIO); | 
| Oliver Neukum | 76d057c | 2008-04-04 15:31:47 -0400 | [diff] [blame] | 516 | if (!buf) | 
|  | 517 | goto err_nobuf; | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 518 | /* reset */ | 
|  | 519 | buf[0] = buf[1] = 0xFF; | 
|  | 520 | ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), | 
|  | 521 | TSC10_CMD_RESET, | 
|  | 522 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 
|  | 523 | 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT); | 
|  | 524 | if (ret < 0) | 
| Oliver Neukum | 76d057c | 2008-04-04 15:31:47 -0400 | [diff] [blame] | 525 | goto err_out; | 
| Nuno Lucas | 2ec6f24 | 2008-11-11 16:48:04 -0500 | [diff] [blame] | 526 | if (buf[0] != 0x06) { | 
| Oliver Neukum | 76d057c | 2008-04-04 15:31:47 -0400 | [diff] [blame] | 527 | ret = -ENODEV; | 
|  | 528 | goto err_out; | 
|  | 529 | } | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 530 |  | 
|  | 531 | /* set coordinate output rate */ | 
|  | 532 | buf[0] = buf[1] = 0xFF; | 
|  | 533 | ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), | 
|  | 534 | TSC10_CMD_RATE, | 
|  | 535 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 
|  | 536 | TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); | 
|  | 537 | if (ret < 0) | 
| Oliver Neukum | 76d057c | 2008-04-04 15:31:47 -0400 | [diff] [blame] | 538 | goto err_out; | 
| Nuno Lucas | 2ec6f24 | 2008-11-11 16:48:04 -0500 | [diff] [blame] | 539 | if ((buf[0] != 0x06) && (buf[0] != 0x15 || buf[1] != 0x01)) { | 
| Oliver Neukum | 76d057c | 2008-04-04 15:31:47 -0400 | [diff] [blame] | 540 | ret = -ENODEV; | 
|  | 541 | goto err_out; | 
|  | 542 | } | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 543 |  | 
|  | 544 | /* start sending data */ | 
|  | 545 | ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), | 
|  | 546 | TSC10_CMD_DATA1, | 
|  | 547 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 
|  | 548 | 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); | 
| Oliver Neukum | 76d057c | 2008-04-04 15:31:47 -0400 | [diff] [blame] | 549 | err_out: | 
|  | 550 | kfree(buf); | 
|  | 551 | err_nobuf: | 
|  | 552 | return ret; | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 553 | } | 
|  | 554 |  | 
|  | 555 |  | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 556 | static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 557 | { | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 558 | dev->x = ((pkt[2] & 0x03) << 8) | pkt[1]; | 
|  | 559 | dev->y = ((pkt[4] & 0x03) << 8) | pkt[3]; | 
|  | 560 | dev->touch = pkt[0] & 0x01; | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 561 |  | 
|  | 562 | return 1; | 
|  | 563 | } | 
|  | 564 | #endif | 
|  | 565 |  | 
|  | 566 |  | 
|  | 567 | /***************************************************************************** | 
| Ondrej Zary | df561fc | 2007-07-03 01:55:03 -0400 | [diff] [blame] | 568 | * IRTOUCH Part | 
|  | 569 | */ | 
|  | 570 | #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH | 
|  | 571 | static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
|  | 572 | { | 
|  | 573 | dev->x = (pkt[3] << 8) | pkt[2]; | 
|  | 574 | dev->y = (pkt[5] << 8) | pkt[4]; | 
|  | 575 | dev->touch = (pkt[1] & 0x03) ? 1 : 0; | 
|  | 576 |  | 
|  | 577 | return 1; | 
|  | 578 | } | 
|  | 579 | #endif | 
|  | 580 |  | 
| Petr Å tetiar | dbe1420 | 2009-11-29 23:37:07 -0800 | [diff] [blame] | 581 | /***************************************************************************** | 
| Petr Å tetiar | 38771bb | 2010-06-28 09:38:48 -0700 | [diff] [blame] | 582 | * ET&T TC5UH/TC4UM part | 
| Petr Å tetiar | dbe1420 | 2009-11-29 23:37:07 -0800 | [diff] [blame] | 583 | */ | 
| Petr Å tetiar | 38771bb | 2010-06-28 09:38:48 -0700 | [diff] [blame] | 584 | #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB | 
|  | 585 | static int tc45usb_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
| Petr Å tetiar | dbe1420 | 2009-11-29 23:37:07 -0800 | [diff] [blame] | 586 | { | 
|  | 587 | dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; | 
|  | 588 | dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; | 
|  | 589 | dev->touch = pkt[0] & 0x01; | 
|  | 590 |  | 
|  | 591 | return 1; | 
|  | 592 | } | 
|  | 593 | #endif | 
| Ondrej Zary | df561fc | 2007-07-03 01:55:03 -0400 | [diff] [blame] | 594 |  | 
|  | 595 | /***************************************************************************** | 
| Ondrej Zary | a14a840 | 2007-09-04 23:45:01 -0400 | [diff] [blame] | 596 | * IdealTEK URTC1000 Part | 
|  | 597 | */ | 
|  | 598 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 599 | #ifndef MULTI_PACKET | 
|  | 600 | #define MULTI_PACKET | 
|  | 601 | #endif | 
| Ondrej Zary | a14a840 | 2007-09-04 23:45:01 -0400 | [diff] [blame] | 602 | static int idealtek_get_pkt_len(unsigned char *buf, int len) | 
|  | 603 | { | 
|  | 604 | if (buf[0] & 0x80) | 
|  | 605 | return 5; | 
|  | 606 | if (buf[0] == 0x01) | 
|  | 607 | return len; | 
|  | 608 | return 0; | 
|  | 609 | } | 
|  | 610 |  | 
|  | 611 | static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
|  | 612 | { | 
|  | 613 | switch (pkt[0] & 0x98) { | 
|  | 614 | case 0x88: | 
|  | 615 | /* touch data in IdealTEK mode */ | 
|  | 616 | dev->x = (pkt[1] << 5) | (pkt[2] >> 2); | 
|  | 617 | dev->y = (pkt[3] << 5) | (pkt[4] >> 2); | 
|  | 618 | dev->touch = (pkt[0] & 0x40) ? 1 : 0; | 
|  | 619 | return 1; | 
|  | 620 |  | 
|  | 621 | case 0x98: | 
|  | 622 | /* touch data in MT emulation mode */ | 
|  | 623 | dev->x = (pkt[2] << 5) | (pkt[1] >> 2); | 
|  | 624 | dev->y = (pkt[4] << 5) | (pkt[3] >> 2); | 
|  | 625 | dev->touch = (pkt[0] & 0x40) ? 1 : 0; | 
|  | 626 | return 1; | 
|  | 627 |  | 
|  | 628 | default: | 
|  | 629 | return 0; | 
|  | 630 | } | 
|  | 631 | } | 
|  | 632 | #endif | 
|  | 633 |  | 
| Ilya Frolov | 9d5657d | 2007-10-12 14:19:40 -0400 | [diff] [blame] | 634 | /***************************************************************************** | 
|  | 635 | * General Touch Part | 
|  | 636 | */ | 
|  | 637 | #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH | 
|  | 638 | static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
|  | 639 | { | 
| Roy Yin | eb083ba | 2010-02-21 22:52:49 -0800 | [diff] [blame] | 640 | dev->x = (pkt[2] << 8) | pkt[1]; | 
|  | 641 | dev->y = (pkt[4] << 8) | pkt[3]; | 
| Ilya Frolov | 9d5657d | 2007-10-12 14:19:40 -0400 | [diff] [blame] | 642 | dev->press = pkt[5] & 0xff; | 
|  | 643 | dev->touch = pkt[0] & 0x01; | 
|  | 644 |  | 
|  | 645 | return 1; | 
|  | 646 | } | 
|  | 647 | #endif | 
| Ondrej Zary | a14a840 | 2007-09-04 23:45:01 -0400 | [diff] [blame] | 648 |  | 
|  | 649 | /***************************************************************************** | 
| Jerrold Jones | 14e4020 | 2007-10-22 00:59:47 -0400 | [diff] [blame] | 650 | * GoTop Part | 
|  | 651 | */ | 
|  | 652 | #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP | 
|  | 653 | static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
|  | 654 | { | 
|  | 655 | dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; | 
|  | 656 | dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; | 
|  | 657 | dev->touch = pkt[0] & 0x01; | 
| Jim Persson | f737069 | 2009-07-07 22:07:59 -0700 | [diff] [blame] | 658 |  | 
|  | 659 | return 1; | 
|  | 660 | } | 
|  | 661 | #endif | 
|  | 662 |  | 
|  | 663 | /***************************************************************************** | 
|  | 664 | * JASTEC Part | 
|  | 665 | */ | 
|  | 666 | #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC | 
|  | 667 | static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
|  | 668 | { | 
|  | 669 | dev->x = ((pkt[0] & 0x3f) << 6) | (pkt[2] & 0x3f); | 
|  | 670 | dev->y = ((pkt[1] & 0x3f) << 6) | (pkt[3] & 0x3f); | 
|  | 671 | dev->touch = (pkt[0] & 0x40) >> 6; | 
|  | 672 |  | 
| Jerrold Jones | 14e4020 | 2007-10-22 00:59:47 -0400 | [diff] [blame] | 673 | return 1; | 
|  | 674 | } | 
|  | 675 | #endif | 
|  | 676 |  | 
| Daniel Silverstone | 2330ed1 | 2009-11-23 08:38:16 -0800 | [diff] [blame] | 677 | /***************************************************************************** | 
|  | 678 | * Zytronic Part | 
|  | 679 | */ | 
|  | 680 | #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC | 
|  | 681 | static int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 
|  | 682 | { | 
|  | 683 | switch (pkt[0]) { | 
|  | 684 | case 0x3A: /* command response */ | 
|  | 685 | dbg("%s: Command response %d", __func__, pkt[1]); | 
|  | 686 | break; | 
|  | 687 |  | 
|  | 688 | case 0xC0: /* down */ | 
|  | 689 | dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); | 
|  | 690 | dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); | 
|  | 691 | dev->touch = 1; | 
|  | 692 | dbg("%s: down %d,%d", __func__, dev->x, dev->y); | 
|  | 693 | return 1; | 
|  | 694 |  | 
|  | 695 | case 0x80: /* up */ | 
|  | 696 | dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); | 
|  | 697 | dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); | 
|  | 698 | dev->touch = 0; | 
|  | 699 | dbg("%s: up %d,%d", __func__, dev->x, dev->y); | 
|  | 700 | return 1; | 
|  | 701 |  | 
|  | 702 | default: | 
|  | 703 | dbg("%s: Unknown return %d", __func__, pkt[0]); | 
|  | 704 | break; | 
|  | 705 | } | 
|  | 706 |  | 
|  | 707 | return 0; | 
|  | 708 | } | 
|  | 709 | #endif | 
| Jerrold Jones | 14e4020 | 2007-10-22 00:59:47 -0400 | [diff] [blame] | 710 |  | 
|  | 711 | /***************************************************************************** | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 712 | * NEXIO Part | 
|  | 713 | */ | 
|  | 714 | #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO | 
|  | 715 |  | 
|  | 716 | #define NEXIO_TIMEOUT	5000 | 
|  | 717 | #define NEXIO_BUFSIZE	1024 | 
|  | 718 | #define NEXIO_THRESHOLD	50 | 
|  | 719 |  | 
|  | 720 | struct nexio_priv { | 
|  | 721 | struct urb *ack; | 
|  | 722 | unsigned char *ack_buf; | 
|  | 723 | }; | 
|  | 724 |  | 
|  | 725 | struct nexio_touch_packet { | 
|  | 726 | u8	flags;		/* 0xe1 = touch, 0xe1 = release */ | 
|  | 727 | __be16	data_len;	/* total bytes of touch data */ | 
|  | 728 | __be16	x_len;		/* bytes for X axis */ | 
|  | 729 | __be16	y_len;		/* bytes for Y axis */ | 
|  | 730 | u8	data[]; | 
|  | 731 | } __attribute__ ((packed)); | 
|  | 732 |  | 
|  | 733 | static unsigned char nexio_ack_pkt[2] = { 0xaa, 0x02 }; | 
|  | 734 | static unsigned char nexio_init_pkt[4] = { 0x82, 0x04, 0x0a, 0x0f }; | 
|  | 735 |  | 
|  | 736 | static void nexio_ack_complete(struct urb *urb) | 
|  | 737 | { | 
|  | 738 | } | 
|  | 739 |  | 
| Oliver Neukum | a8aef62 | 2010-07-15 09:21:40 -0700 | [diff] [blame] | 740 | static int nexio_alloc(struct usbtouch_usb *usbtouch) | 
|  | 741 | { | 
|  | 742 | struct nexio_priv *priv; | 
|  | 743 | int ret = -ENOMEM; | 
|  | 744 |  | 
|  | 745 | usbtouch->priv = kmalloc(sizeof(struct nexio_priv), GFP_KERNEL); | 
|  | 746 | if (!usbtouch->priv) | 
|  | 747 | goto out_buf; | 
|  | 748 |  | 
|  | 749 | priv = usbtouch->priv; | 
|  | 750 |  | 
|  | 751 | priv->ack_buf = kmemdup(nexio_ack_pkt, sizeof(nexio_ack_pkt), | 
|  | 752 | GFP_KERNEL); | 
|  | 753 | if (!priv->ack_buf) | 
|  | 754 | goto err_priv; | 
|  | 755 |  | 
|  | 756 | priv->ack = usb_alloc_urb(0, GFP_KERNEL); | 
|  | 757 | if (!priv->ack) { | 
|  | 758 | dbg("%s - usb_alloc_urb failed: usbtouch->ack", __func__); | 
|  | 759 | goto err_ack_buf; | 
|  | 760 | } | 
|  | 761 |  | 
|  | 762 | return 0; | 
|  | 763 |  | 
|  | 764 | err_ack_buf: | 
|  | 765 | kfree(priv->ack_buf); | 
|  | 766 | err_priv: | 
|  | 767 | kfree(priv); | 
|  | 768 | out_buf: | 
|  | 769 | return ret; | 
|  | 770 | } | 
|  | 771 |  | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 772 | static int nexio_init(struct usbtouch_usb *usbtouch) | 
|  | 773 | { | 
|  | 774 | struct usb_device *dev = interface_to_usbdev(usbtouch->interface); | 
|  | 775 | struct usb_host_interface *interface = usbtouch->interface->cur_altsetting; | 
| Oliver Neukum | a8aef62 | 2010-07-15 09:21:40 -0700 | [diff] [blame] | 776 | struct nexio_priv *priv = usbtouch->priv; | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 777 | int ret = -ENOMEM; | 
|  | 778 | int actual_len, i; | 
|  | 779 | unsigned char *buf; | 
|  | 780 | char *firmware_ver = NULL, *device_name = NULL; | 
|  | 781 | int input_ep = 0, output_ep = 0; | 
|  | 782 |  | 
|  | 783 | /* find first input and output endpoint */ | 
|  | 784 | for (i = 0; i < interface->desc.bNumEndpoints; i++) { | 
|  | 785 | if (!input_ep && | 
|  | 786 | usb_endpoint_dir_in(&interface->endpoint[i].desc)) | 
|  | 787 | input_ep = interface->endpoint[i].desc.bEndpointAddress; | 
|  | 788 | if (!output_ep && | 
|  | 789 | usb_endpoint_dir_out(&interface->endpoint[i].desc)) | 
|  | 790 | output_ep = interface->endpoint[i].desc.bEndpointAddress; | 
|  | 791 | } | 
|  | 792 | if (!input_ep || !output_ep) | 
|  | 793 | return -ENXIO; | 
|  | 794 |  | 
| Oliver Neukum | a8aef62 | 2010-07-15 09:21:40 -0700 | [diff] [blame] | 795 | buf = kmalloc(NEXIO_BUFSIZE, GFP_NOIO); | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 796 | if (!buf) | 
|  | 797 | goto out_buf; | 
|  | 798 |  | 
|  | 799 | /* two empty reads */ | 
|  | 800 | for (i = 0; i < 2; i++) { | 
|  | 801 | ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep), | 
|  | 802 | buf, NEXIO_BUFSIZE, &actual_len, | 
|  | 803 | NEXIO_TIMEOUT); | 
|  | 804 | if (ret < 0) | 
|  | 805 | goto out_buf; | 
|  | 806 | } | 
|  | 807 |  | 
|  | 808 | /* send init command */ | 
|  | 809 | memcpy(buf, nexio_init_pkt, sizeof(nexio_init_pkt)); | 
|  | 810 | ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, output_ep), | 
|  | 811 | buf, sizeof(nexio_init_pkt), &actual_len, | 
|  | 812 | NEXIO_TIMEOUT); | 
|  | 813 | if (ret < 0) | 
|  | 814 | goto out_buf; | 
|  | 815 |  | 
|  | 816 | /* read replies */ | 
|  | 817 | for (i = 0; i < 3; i++) { | 
|  | 818 | memset(buf, 0, NEXIO_BUFSIZE); | 
|  | 819 | ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep), | 
|  | 820 | buf, NEXIO_BUFSIZE, &actual_len, | 
|  | 821 | NEXIO_TIMEOUT); | 
|  | 822 | if (ret < 0 || actual_len < 1 || buf[1] != actual_len) | 
|  | 823 | continue; | 
|  | 824 | switch (buf[0]) { | 
|  | 825 | case 0x83:	/* firmware version */ | 
|  | 826 | if (!firmware_ver) | 
| Oliver Neukum | a8aef62 | 2010-07-15 09:21:40 -0700 | [diff] [blame] | 827 | firmware_ver = kstrdup(&buf[2], GFP_NOIO); | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 828 | break; | 
|  | 829 | case 0x84:	/* device name */ | 
|  | 830 | if (!device_name) | 
| Oliver Neukum | a8aef62 | 2010-07-15 09:21:40 -0700 | [diff] [blame] | 831 | device_name = kstrdup(&buf[2], GFP_NOIO); | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 832 | break; | 
|  | 833 | } | 
|  | 834 | } | 
|  | 835 |  | 
|  | 836 | printk(KERN_INFO "Nexio device: %s, firmware version: %s\n", | 
|  | 837 | device_name, firmware_ver); | 
|  | 838 |  | 
|  | 839 | kfree(firmware_ver); | 
|  | 840 | kfree(device_name); | 
|  | 841 |  | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 842 | usb_fill_bulk_urb(priv->ack, dev, usb_sndbulkpipe(dev, output_ep), | 
|  | 843 | priv->ack_buf, sizeof(nexio_ack_pkt), | 
|  | 844 | nexio_ack_complete, usbtouch); | 
|  | 845 | ret = 0; | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 846 |  | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 847 | out_buf: | 
|  | 848 | kfree(buf); | 
|  | 849 | return ret; | 
|  | 850 | } | 
|  | 851 |  | 
|  | 852 | static void nexio_exit(struct usbtouch_usb *usbtouch) | 
|  | 853 | { | 
|  | 854 | struct nexio_priv *priv = usbtouch->priv; | 
|  | 855 |  | 
|  | 856 | usb_kill_urb(priv->ack); | 
|  | 857 | usb_free_urb(priv->ack); | 
|  | 858 | kfree(priv->ack_buf); | 
|  | 859 | kfree(priv); | 
|  | 860 | } | 
|  | 861 |  | 
|  | 862 | static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) | 
|  | 863 | { | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 864 | struct nexio_touch_packet *packet = (void *) pkt; | 
|  | 865 | struct nexio_priv *priv = usbtouch->priv; | 
| Dmitry Torokhov | 4aa5bbe | 2010-06-08 01:01:46 -0700 | [diff] [blame] | 866 | unsigned int data_len = be16_to_cpu(packet->data_len); | 
|  | 867 | unsigned int x_len = be16_to_cpu(packet->x_len); | 
|  | 868 | unsigned int y_len = be16_to_cpu(packet->y_len); | 
|  | 869 | int x, y, begin_x, begin_y, end_x, end_y, w, h, ret; | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 870 |  | 
|  | 871 | /* got touch data? */ | 
|  | 872 | if ((pkt[0] & 0xe0) != 0xe0) | 
|  | 873 | return 0; | 
|  | 874 |  | 
| Dmitry Torokhov | 4aa5bbe | 2010-06-08 01:01:46 -0700 | [diff] [blame] | 875 | if (data_len > 0xff) | 
|  | 876 | data_len -= 0x100; | 
|  | 877 | if (x_len > 0xff) | 
|  | 878 | x_len -= 0x80; | 
| Ondrej Zary | 388bbca | 2010-05-26 23:30:54 -0700 | [diff] [blame] | 879 |  | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 880 | /* send ACK */ | 
|  | 881 | ret = usb_submit_urb(priv->ack, GFP_ATOMIC); | 
|  | 882 |  | 
|  | 883 | if (!usbtouch->type->max_xc) { | 
| Dmitry Torokhov | 4aa5bbe | 2010-06-08 01:01:46 -0700 | [diff] [blame] | 884 | usbtouch->type->max_xc = 2 * x_len; | 
|  | 885 | input_set_abs_params(usbtouch->input, ABS_X, | 
|  | 886 | 0, usbtouch->type->max_xc, 0, 0); | 
|  | 887 | usbtouch->type->max_yc = 2 * y_len; | 
|  | 888 | input_set_abs_params(usbtouch->input, ABS_Y, | 
|  | 889 | 0, usbtouch->type->max_yc, 0, 0); | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 890 | } | 
|  | 891 | /* | 
|  | 892 | * The device reports state of IR sensors on X and Y axes. | 
|  | 893 | * Each byte represents "darkness" percentage (0-100) of one element. | 
|  | 894 | * 17" touchscreen reports only 64 x 52 bytes so the resolution is low. | 
|  | 895 | * This also means that there's a limited multi-touch capability but | 
|  | 896 | * it's disabled (and untested) here as there's no X driver for that. | 
|  | 897 | */ | 
|  | 898 | begin_x = end_x = begin_y = end_y = -1; | 
| Dmitry Torokhov | 4aa5bbe | 2010-06-08 01:01:46 -0700 | [diff] [blame] | 899 | for (x = 0; x < x_len; x++) { | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 900 | if (begin_x == -1 && packet->data[x] > NEXIO_THRESHOLD) { | 
|  | 901 | begin_x = x; | 
|  | 902 | continue; | 
|  | 903 | } | 
|  | 904 | if (end_x == -1 && begin_x != -1 && packet->data[x] < NEXIO_THRESHOLD) { | 
|  | 905 | end_x = x - 1; | 
| Dmitry Torokhov | 4aa5bbe | 2010-06-08 01:01:46 -0700 | [diff] [blame] | 906 | for (y = x_len; y < data_len; y++) { | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 907 | if (begin_y == -1 && packet->data[y] > NEXIO_THRESHOLD) { | 
| Dmitry Torokhov | 4aa5bbe | 2010-06-08 01:01:46 -0700 | [diff] [blame] | 908 | begin_y = y - x_len; | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 909 | continue; | 
|  | 910 | } | 
|  | 911 | if (end_y == -1 && | 
|  | 912 | begin_y != -1 && packet->data[y] < NEXIO_THRESHOLD) { | 
| Dmitry Torokhov | 4aa5bbe | 2010-06-08 01:01:46 -0700 | [diff] [blame] | 913 | end_y = y - 1 - x_len; | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 914 | w = end_x - begin_x; | 
|  | 915 | h = end_y - begin_y; | 
|  | 916 | #if 0 | 
|  | 917 | /* multi-touch */ | 
|  | 918 | input_report_abs(usbtouch->input, | 
|  | 919 | ABS_MT_TOUCH_MAJOR, max(w,h)); | 
|  | 920 | input_report_abs(usbtouch->input, | 
|  | 921 | ABS_MT_TOUCH_MINOR, min(x,h)); | 
|  | 922 | input_report_abs(usbtouch->input, | 
|  | 923 | ABS_MT_POSITION_X, 2*begin_x+w); | 
|  | 924 | input_report_abs(usbtouch->input, | 
|  | 925 | ABS_MT_POSITION_Y, 2*begin_y+h); | 
|  | 926 | input_report_abs(usbtouch->input, | 
|  | 927 | ABS_MT_ORIENTATION, w > h); | 
|  | 928 | input_mt_sync(usbtouch->input); | 
|  | 929 | #endif | 
|  | 930 | /* single touch */ | 
|  | 931 | usbtouch->x = 2 * begin_x + w; | 
|  | 932 | usbtouch->y = 2 * begin_y + h; | 
|  | 933 | usbtouch->touch = packet->flags & 0x01; | 
|  | 934 | begin_y = end_y = -1; | 
|  | 935 | return 1; | 
|  | 936 | } | 
|  | 937 | } | 
|  | 938 | begin_x = end_x = -1; | 
|  | 939 | } | 
|  | 940 |  | 
|  | 941 | } | 
|  | 942 | return 0; | 
|  | 943 | } | 
|  | 944 | #endif | 
|  | 945 |  | 
|  | 946 |  | 
|  | 947 | /***************************************************************************** | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 948 | * the different device descriptors | 
|  | 949 | */ | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 950 | #ifdef MULTI_PACKET | 
|  | 951 | static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, | 
|  | 952 | unsigned char *pkt, int len); | 
|  | 953 | #endif | 
|  | 954 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 955 | static struct usbtouch_device_info usbtouch_dev_info[] = { | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 956 | #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 957 | [DEVTYPE_EGALAX] = { | 
|  | 958 | .min_xc		= 0x0, | 
|  | 959 | .max_xc		= 0x07ff, | 
|  | 960 | .min_yc		= 0x0, | 
|  | 961 | .max_yc		= 0x07ff, | 
|  | 962 | .rept_size	= 16, | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 963 | .process_pkt	= usbtouch_process_multi, | 
|  | 964 | .get_pkt_len	= egalax_get_pkt_len, | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 965 | .read_data	= egalax_read_data, | 
|  | 966 | }, | 
|  | 967 | #endif | 
|  | 968 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 969 | #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 970 | [DEVTYPE_PANJIT] = { | 
|  | 971 | .min_xc		= 0x0, | 
|  | 972 | .max_xc		= 0x0fff, | 
|  | 973 | .min_yc		= 0x0, | 
|  | 974 | .max_yc		= 0x0fff, | 
|  | 975 | .rept_size	= 8, | 
|  | 976 | .read_data	= panjit_read_data, | 
|  | 977 | }, | 
|  | 978 | #endif | 
|  | 979 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 980 | #ifdef CONFIG_TOUCHSCREEN_USB_3M | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 981 | [DEVTYPE_3M] = { | 
|  | 982 | .min_xc		= 0x0, | 
|  | 983 | .max_xc		= 0x4000, | 
|  | 984 | .min_yc		= 0x0, | 
|  | 985 | .max_yc		= 0x4000, | 
|  | 986 | .rept_size	= 11, | 
|  | 987 | .read_data	= mtouch_read_data, | 
|  | 988 | .init		= mtouch_init, | 
|  | 989 | }, | 
|  | 990 | #endif | 
|  | 991 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 992 | #ifdef CONFIG_TOUCHSCREEN_USB_ITM | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 993 | [DEVTYPE_ITM] = { | 
|  | 994 | .min_xc		= 0x0, | 
|  | 995 | .max_xc		= 0x0fff, | 
|  | 996 | .min_yc		= 0x0, | 
|  | 997 | .max_yc		= 0x0fff, | 
|  | 998 | .max_press	= 0xff, | 
|  | 999 | .rept_size	= 8, | 
|  | 1000 | .read_data	= itm_read_data, | 
|  | 1001 | }, | 
|  | 1002 | #endif | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 1003 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 1004 | #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 1005 | [DEVTYPE_ETURBO] = { | 
|  | 1006 | .min_xc		= 0x0, | 
|  | 1007 | .max_xc		= 0x07ff, | 
|  | 1008 | .min_yc		= 0x0, | 
|  | 1009 | .max_yc		= 0x07ff, | 
|  | 1010 | .rept_size	= 8, | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 1011 | .process_pkt	= usbtouch_process_multi, | 
|  | 1012 | .get_pkt_len	= eturbo_get_pkt_len, | 
|  | 1013 | .read_data	= eturbo_read_data, | 
|  | 1014 | }, | 
|  | 1015 | #endif | 
|  | 1016 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 1017 | #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 1018 | [DEVTYPE_GUNZE] = { | 
|  | 1019 | .min_xc		= 0x0, | 
|  | 1020 | .max_xc		= 0x0fff, | 
|  | 1021 | .min_yc		= 0x0, | 
|  | 1022 | .max_yc		= 0x0fff, | 
|  | 1023 | .rept_size	= 4, | 
|  | 1024 | .read_data	= gunze_read_data, | 
|  | 1025 | }, | 
|  | 1026 | #endif | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 1027 |  | 
| Ondrej Zary | c6f8d70 | 2007-06-12 00:33:13 -0400 | [diff] [blame] | 1028 | #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 | 
| Holger Schurig | 24ced06 | 2006-11-17 22:50:15 +0100 | [diff] [blame] | 1029 | [DEVTYPE_DMC_TSC10] = { | 
|  | 1030 | .min_xc		= 0x0, | 
|  | 1031 | .max_xc		= 0x03ff, | 
|  | 1032 | .min_yc		= 0x0, | 
|  | 1033 | .max_yc		= 0x03ff, | 
|  | 1034 | .rept_size	= 5, | 
|  | 1035 | .init		= dmc_tsc10_init, | 
|  | 1036 | .read_data	= dmc_tsc10_read_data, | 
|  | 1037 | }, | 
|  | 1038 | #endif | 
| Ondrej Zary | df561fc | 2007-07-03 01:55:03 -0400 | [diff] [blame] | 1039 |  | 
|  | 1040 | #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH | 
|  | 1041 | [DEVTYPE_IRTOUCH] = { | 
|  | 1042 | .min_xc		= 0x0, | 
|  | 1043 | .max_xc		= 0x0fff, | 
|  | 1044 | .min_yc		= 0x0, | 
|  | 1045 | .max_yc		= 0x0fff, | 
|  | 1046 | .rept_size	= 8, | 
|  | 1047 | .read_data	= irtouch_read_data, | 
|  | 1048 | }, | 
|  | 1049 | #endif | 
| Ondrej Zary | a14a840 | 2007-09-04 23:45:01 -0400 | [diff] [blame] | 1050 |  | 
|  | 1051 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK | 
|  | 1052 | [DEVTYPE_IDEALTEK] = { | 
|  | 1053 | .min_xc		= 0x0, | 
|  | 1054 | .max_xc		= 0x0fff, | 
|  | 1055 | .min_yc		= 0x0, | 
|  | 1056 | .max_yc		= 0x0fff, | 
|  | 1057 | .rept_size	= 8, | 
| Ondrej Zary | a14a840 | 2007-09-04 23:45:01 -0400 | [diff] [blame] | 1058 | .process_pkt	= usbtouch_process_multi, | 
|  | 1059 | .get_pkt_len	= idealtek_get_pkt_len, | 
|  | 1060 | .read_data	= idealtek_read_data, | 
|  | 1061 | }, | 
|  | 1062 | #endif | 
| Ilya Frolov | 9d5657d | 2007-10-12 14:19:40 -0400 | [diff] [blame] | 1063 |  | 
|  | 1064 | #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH | 
|  | 1065 | [DEVTYPE_GENERAL_TOUCH] = { | 
|  | 1066 | .min_xc		= 0x0, | 
| Roy Yin | eb083ba | 2010-02-21 22:52:49 -0800 | [diff] [blame] | 1067 | .max_xc		= 0x7fff, | 
| Ilya Frolov | 9d5657d | 2007-10-12 14:19:40 -0400 | [diff] [blame] | 1068 | .min_yc		= 0x0, | 
| Roy Yin | eb083ba | 2010-02-21 22:52:49 -0800 | [diff] [blame] | 1069 | .max_yc		= 0x7fff, | 
| Ilya Frolov | 9d5657d | 2007-10-12 14:19:40 -0400 | [diff] [blame] | 1070 | .rept_size	= 7, | 
|  | 1071 | .read_data	= general_touch_read_data, | 
| Jerrold Jones | 14e4020 | 2007-10-22 00:59:47 -0400 | [diff] [blame] | 1072 | }, | 
| Ilya Frolov | 9d5657d | 2007-10-12 14:19:40 -0400 | [diff] [blame] | 1073 | #endif | 
|  | 1074 |  | 
| Jerrold Jones | 14e4020 | 2007-10-22 00:59:47 -0400 | [diff] [blame] | 1075 | #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP | 
|  | 1076 | [DEVTYPE_GOTOP] = { | 
|  | 1077 | .min_xc		= 0x0, | 
|  | 1078 | .max_xc		= 0x03ff, | 
|  | 1079 | .min_yc		= 0x0, | 
|  | 1080 | .max_yc		= 0x03ff, | 
|  | 1081 | .rept_size	= 4, | 
|  | 1082 | .read_data	= gotop_read_data, | 
|  | 1083 | }, | 
|  | 1084 | #endif | 
| Jim Persson | f737069 | 2009-07-07 22:07:59 -0700 | [diff] [blame] | 1085 |  | 
|  | 1086 | #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC | 
|  | 1087 | [DEVTYPE_JASTEC] = { | 
|  | 1088 | .min_xc		= 0x0, | 
|  | 1089 | .max_xc		= 0x0fff, | 
|  | 1090 | .min_yc		= 0x0, | 
|  | 1091 | .max_yc		= 0x0fff, | 
|  | 1092 | .rept_size	= 4, | 
|  | 1093 | .read_data	= jastec_read_data, | 
|  | 1094 | }, | 
|  | 1095 | #endif | 
| Florian Echtler | 9e3b258 | 2009-07-27 17:35:39 -0700 | [diff] [blame] | 1096 |  | 
|  | 1097 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | 
|  | 1098 | [DEVTYPE_E2I] = { | 
|  | 1099 | .min_xc		= 0x0, | 
|  | 1100 | .max_xc		= 0x7fff, | 
|  | 1101 | .min_yc		= 0x0, | 
|  | 1102 | .max_yc		= 0x7fff, | 
|  | 1103 | .rept_size	= 6, | 
|  | 1104 | .init		= e2i_init, | 
|  | 1105 | .read_data	= e2i_read_data, | 
|  | 1106 | }, | 
|  | 1107 | #endif | 
| Daniel Silverstone | 2330ed1 | 2009-11-23 08:38:16 -0800 | [diff] [blame] | 1108 |  | 
|  | 1109 | #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC | 
|  | 1110 | [DEVTYPE_ZYTRONIC] = { | 
|  | 1111 | .min_xc		= 0x0, | 
|  | 1112 | .max_xc		= 0x03ff, | 
|  | 1113 | .min_yc		= 0x0, | 
|  | 1114 | .max_yc		= 0x03ff, | 
|  | 1115 | .rept_size	= 5, | 
|  | 1116 | .read_data	= zytronic_read_data, | 
|  | 1117 | .irq_always     = true, | 
|  | 1118 | }, | 
|  | 1119 | #endif | 
| Petr Å tetiar | dbe1420 | 2009-11-29 23:37:07 -0800 | [diff] [blame] | 1120 |  | 
| Petr Å tetiar | 38771bb | 2010-06-28 09:38:48 -0700 | [diff] [blame] | 1121 | #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB | 
|  | 1122 | [DEVTYPE_TC45USB] = { | 
| Petr Å tetiar | dbe1420 | 2009-11-29 23:37:07 -0800 | [diff] [blame] | 1123 | .min_xc		= 0x0, | 
|  | 1124 | .max_xc		= 0x0fff, | 
|  | 1125 | .min_yc		= 0x0, | 
|  | 1126 | .max_yc		= 0x0fff, | 
|  | 1127 | .rept_size	= 5, | 
| Petr Å tetiar | 38771bb | 2010-06-28 09:38:48 -0700 | [diff] [blame] | 1128 | .read_data	= tc45usb_read_data, | 
| Petr Å tetiar | dbe1420 | 2009-11-29 23:37:07 -0800 | [diff] [blame] | 1129 | }, | 
|  | 1130 | #endif | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 1131 |  | 
|  | 1132 | #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO | 
|  | 1133 | [DEVTYPE_NEXIO] = { | 
| Ondrej Zary | 388bbca | 2010-05-26 23:30:54 -0700 | [diff] [blame] | 1134 | .rept_size	= 1024, | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 1135 | .irq_always	= true, | 
|  | 1136 | .read_data	= nexio_read_data, | 
| Oliver Neukum | a8aef62 | 2010-07-15 09:21:40 -0700 | [diff] [blame] | 1137 | .alloc		= nexio_alloc, | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 1138 | .init		= nexio_init, | 
|  | 1139 | .exit		= nexio_exit, | 
|  | 1140 | }, | 
|  | 1141 | #endif | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1142 | }; | 
|  | 1143 |  | 
|  | 1144 |  | 
|  | 1145 | /***************************************************************************** | 
|  | 1146 | * Generic Part | 
|  | 1147 | */ | 
|  | 1148 | static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 1149 | unsigned char *pkt, int len) | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1150 | { | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1151 | struct usbtouch_device_info *type = usbtouch->type; | 
|  | 1152 |  | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 1153 | if (!type->read_data(usbtouch, pkt)) | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1154 | return; | 
|  | 1155 |  | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 1156 | input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1157 |  | 
|  | 1158 | if (swap_xy) { | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 1159 | input_report_abs(usbtouch->input, ABS_X, usbtouch->y); | 
|  | 1160 | input_report_abs(usbtouch->input, ABS_Y, usbtouch->x); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1161 | } else { | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 1162 | input_report_abs(usbtouch->input, ABS_X, usbtouch->x); | 
|  | 1163 | input_report_abs(usbtouch->input, ABS_Y, usbtouch->y); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1164 | } | 
|  | 1165 | if (type->max_press) | 
| Daniel Ritz | c9d8c2b | 2006-12-11 18:17:45 +0100 | [diff] [blame] | 1166 | input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1167 | input_sync(usbtouch->input); | 
|  | 1168 | } | 
|  | 1169 |  | 
|  | 1170 |  | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 1171 | #ifdef MULTI_PACKET | 
|  | 1172 | static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 1173 | unsigned char *pkt, int len) | 
|  | 1174 | { | 
|  | 1175 | unsigned char *buffer; | 
|  | 1176 | int pkt_len, pos, buf_len, tmp; | 
|  | 1177 |  | 
|  | 1178 | /* process buffer */ | 
|  | 1179 | if (unlikely(usbtouch->buf_len)) { | 
|  | 1180 | /* try to get size */ | 
|  | 1181 | pkt_len = usbtouch->type->get_pkt_len( | 
|  | 1182 | usbtouch->buffer, usbtouch->buf_len); | 
|  | 1183 |  | 
|  | 1184 | /* drop? */ | 
|  | 1185 | if (unlikely(!pkt_len)) | 
|  | 1186 | goto out_flush_buf; | 
|  | 1187 |  | 
|  | 1188 | /* need to append -pkt_len bytes before able to get size */ | 
|  | 1189 | if (unlikely(pkt_len < 0)) { | 
|  | 1190 | int append = -pkt_len; | 
|  | 1191 | if (unlikely(append > len)) | 
|  | 1192 | append = len; | 
|  | 1193 | if (usbtouch->buf_len + append >= usbtouch->type->rept_size) | 
|  | 1194 | goto out_flush_buf; | 
|  | 1195 | memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append); | 
|  | 1196 | usbtouch->buf_len += append; | 
|  | 1197 |  | 
|  | 1198 | pkt_len = usbtouch->type->get_pkt_len( | 
|  | 1199 | usbtouch->buffer, usbtouch->buf_len); | 
|  | 1200 | if (pkt_len < 0) | 
|  | 1201 | return; | 
|  | 1202 | } | 
|  | 1203 |  | 
|  | 1204 | /* append */ | 
|  | 1205 | tmp = pkt_len - usbtouch->buf_len; | 
|  | 1206 | if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size) | 
|  | 1207 | goto out_flush_buf; | 
|  | 1208 | memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp); | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 1209 | usbtouch_process_pkt(usbtouch, usbtouch->buffer, pkt_len); | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 1210 |  | 
|  | 1211 | buffer = pkt + tmp; | 
|  | 1212 | buf_len = len - tmp; | 
|  | 1213 | } else { | 
|  | 1214 | buffer = pkt; | 
|  | 1215 | buf_len = len; | 
|  | 1216 | } | 
|  | 1217 |  | 
|  | 1218 | /* loop over the received packet, process */ | 
|  | 1219 | pos = 0; | 
|  | 1220 | while (pos < buf_len) { | 
|  | 1221 | /* get packet len */ | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 1222 | pkt_len = usbtouch->type->get_pkt_len(buffer + pos, | 
|  | 1223 | buf_len - pos); | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 1224 |  | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 1225 | /* unknown packet: skip one byte */ | 
|  | 1226 | if (unlikely(!pkt_len)) { | 
|  | 1227 | pos++; | 
|  | 1228 | continue; | 
|  | 1229 | } | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 1230 |  | 
|  | 1231 | /* full packet: process */ | 
|  | 1232 | if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) { | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 1233 | usbtouch_process_pkt(usbtouch, buffer + pos, pkt_len); | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 1234 | } else { | 
|  | 1235 | /* incomplete packet: save in buffer */ | 
|  | 1236 | memcpy(usbtouch->buffer, buffer + pos, buf_len - pos); | 
|  | 1237 | usbtouch->buf_len = buf_len - pos; | 
|  | 1238 | return; | 
|  | 1239 | } | 
|  | 1240 | pos += pkt_len; | 
|  | 1241 | } | 
|  | 1242 |  | 
|  | 1243 | out_flush_buf: | 
|  | 1244 | usbtouch->buf_len = 0; | 
|  | 1245 | return; | 
|  | 1246 | } | 
|  | 1247 | #endif | 
|  | 1248 |  | 
|  | 1249 |  | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 1250 | static void usbtouch_irq(struct urb *urb) | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1251 | { | 
|  | 1252 | struct usbtouch_usb *usbtouch = urb->context; | 
|  | 1253 | int retval; | 
|  | 1254 |  | 
|  | 1255 | switch (urb->status) { | 
|  | 1256 | case 0: | 
|  | 1257 | /* success */ | 
|  | 1258 | break; | 
| Pete Zaitcev | 38e2bfc | 2006-09-18 22:49:02 -0700 | [diff] [blame] | 1259 | case -ETIME: | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1260 | /* this urb is timing out */ | 
|  | 1261 | dbg("%s - urb timed out - was the device unplugged?", | 
| Harvey Harrison | ea3e6c5 | 2008-05-05 11:36:18 -0400 | [diff] [blame] | 1262 | __func__); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1263 | return; | 
|  | 1264 | case -ECONNRESET: | 
|  | 1265 | case -ENOENT: | 
|  | 1266 | case -ESHUTDOWN: | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 1267 | case -EPIPE: | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1268 | /* this urb is terminated, clean up */ | 
|  | 1269 | dbg("%s - urb shutting down with status: %d", | 
| Harvey Harrison | ea3e6c5 | 2008-05-05 11:36:18 -0400 | [diff] [blame] | 1270 | __func__, urb->status); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1271 | return; | 
|  | 1272 | default: | 
|  | 1273 | dbg("%s - nonzero urb status received: %d", | 
| Harvey Harrison | ea3e6c5 | 2008-05-05 11:36:18 -0400 | [diff] [blame] | 1274 | __func__, urb->status); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1275 | goto exit; | 
|  | 1276 | } | 
|  | 1277 |  | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 1278 | usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1279 |  | 
|  | 1280 | exit: | 
| Oliver Neukum | 5d9efc5 | 2010-07-15 09:19:51 -0700 | [diff] [blame] | 1281 | usb_mark_last_busy(interface_to_usbdev(usbtouch->interface)); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1282 | retval = usb_submit_urb(urb, GFP_ATOMIC); | 
|  | 1283 | if (retval) | 
|  | 1284 | err("%s - usb_submit_urb failed with result: %d", | 
| Harvey Harrison | ea3e6c5 | 2008-05-05 11:36:18 -0400 | [diff] [blame] | 1285 | __func__, retval); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1286 | } | 
|  | 1287 |  | 
|  | 1288 | static int usbtouch_open(struct input_dev *input) | 
|  | 1289 | { | 
| Dmitry Torokhov | 7791bda | 2007-04-12 01:34:39 -0400 | [diff] [blame] | 1290 | struct usbtouch_usb *usbtouch = input_get_drvdata(input); | 
| Oliver Neukum | 5d9efc5 | 2010-07-15 09:19:51 -0700 | [diff] [blame] | 1291 | int r; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1292 |  | 
| Ondrej Zary | fea4d14 | 2010-02-03 23:46:48 -0800 | [diff] [blame] | 1293 | usbtouch->irq->dev = interface_to_usbdev(usbtouch->interface); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1294 |  | 
| Oliver Neukum | 5d9efc5 | 2010-07-15 09:19:51 -0700 | [diff] [blame] | 1295 | r = usb_autopm_get_interface(usbtouch->interface) ? -EIO : 0; | 
|  | 1296 | if (r < 0) | 
|  | 1297 | goto out; | 
|  | 1298 |  | 
| Daniel Silverstone | 2330ed1 | 2009-11-23 08:38:16 -0800 | [diff] [blame] | 1299 | if (!usbtouch->type->irq_always) { | 
| Oliver Neukum | 5d9efc5 | 2010-07-15 09:19:51 -0700 | [diff] [blame] | 1300 | if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) { | 
|  | 1301 | r = -EIO; | 
|  | 1302 | goto out_put; | 
|  | 1303 | } | 
| Daniel Silverstone | 2330ed1 | 2009-11-23 08:38:16 -0800 | [diff] [blame] | 1304 | } | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1305 |  | 
| Oliver Neukum | 5d9efc5 | 2010-07-15 09:19:51 -0700 | [diff] [blame] | 1306 | usbtouch->interface->needs_remote_wakeup = 1; | 
|  | 1307 | out_put: | 
|  | 1308 | usb_autopm_put_interface(usbtouch->interface); | 
|  | 1309 | out: | 
|  | 1310 | return r; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1311 | } | 
|  | 1312 |  | 
|  | 1313 | static void usbtouch_close(struct input_dev *input) | 
|  | 1314 | { | 
| Dmitry Torokhov | 7791bda | 2007-04-12 01:34:39 -0400 | [diff] [blame] | 1315 | struct usbtouch_usb *usbtouch = input_get_drvdata(input); | 
| Oliver Neukum | 5d9efc5 | 2010-07-15 09:19:51 -0700 | [diff] [blame] | 1316 | int r; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1317 |  | 
| Daniel Silverstone | 2330ed1 | 2009-11-23 08:38:16 -0800 | [diff] [blame] | 1318 | if (!usbtouch->type->irq_always) | 
|  | 1319 | usb_kill_urb(usbtouch->irq); | 
| Oliver Neukum | 5d9efc5 | 2010-07-15 09:19:51 -0700 | [diff] [blame] | 1320 | r = usb_autopm_get_interface(usbtouch->interface); | 
|  | 1321 | usbtouch->interface->needs_remote_wakeup = 0; | 
|  | 1322 | if (!r) | 
|  | 1323 | usb_autopm_put_interface(usbtouch->interface); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1324 | } | 
|  | 1325 |  | 
| Oliver Neukum | ed4299e | 2010-07-15 09:16:39 -0700 | [diff] [blame] | 1326 | static int usbtouch_suspend | 
|  | 1327 | (struct usb_interface *intf, pm_message_t message) | 
|  | 1328 | { | 
|  | 1329 | struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); | 
|  | 1330 |  | 
|  | 1331 | usb_kill_urb(usbtouch->irq); | 
|  | 1332 |  | 
|  | 1333 | return 0; | 
|  | 1334 | } | 
|  | 1335 |  | 
|  | 1336 | static int usbtouch_resume(struct usb_interface *intf) | 
|  | 1337 | { | 
|  | 1338 | struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); | 
|  | 1339 | struct input_dev *input = usbtouch->input; | 
|  | 1340 | int result = 0; | 
|  | 1341 |  | 
|  | 1342 | mutex_lock(&input->mutex); | 
|  | 1343 | if (input->users || usbtouch->type->irq_always) | 
|  | 1344 | result = usb_submit_urb(usbtouch->irq, GFP_NOIO); | 
|  | 1345 | mutex_unlock(&input->mutex); | 
|  | 1346 |  | 
|  | 1347 | return result; | 
|  | 1348 | } | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1349 |  | 
| Oliver Neukum | a8aef62 | 2010-07-15 09:21:40 -0700 | [diff] [blame] | 1350 | static int usbtouch_reset_resume(struct usb_interface *intf) | 
|  | 1351 | { | 
|  | 1352 | struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); | 
|  | 1353 | struct input_dev *input = usbtouch->input; | 
|  | 1354 | int err = 0; | 
|  | 1355 |  | 
|  | 1356 | /* reinit the device */ | 
|  | 1357 | if (usbtouch->type->init) { | 
|  | 1358 | err = usbtouch->type->init(usbtouch); | 
|  | 1359 | if (err) { | 
|  | 1360 | dbg("%s - type->init() failed, err: %d", | 
|  | 1361 | __func__, err); | 
|  | 1362 | return err; | 
|  | 1363 | } | 
|  | 1364 | } | 
|  | 1365 |  | 
|  | 1366 | /* restart IO if needed */ | 
|  | 1367 | mutex_lock(&input->mutex); | 
|  | 1368 | if (input->users) | 
|  | 1369 | err = usb_submit_urb(usbtouch->irq, GFP_NOIO); | 
|  | 1370 | mutex_unlock(&input->mutex); | 
|  | 1371 |  | 
|  | 1372 | return err; | 
|  | 1373 | } | 
|  | 1374 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1375 | static void usbtouch_free_buffers(struct usb_device *udev, | 
|  | 1376 | struct usbtouch_usb *usbtouch) | 
|  | 1377 | { | 
| Daniel Mack | 997ea58 | 2010-04-12 13:17:25 +0200 | [diff] [blame] | 1378 | usb_free_coherent(udev, usbtouch->type->rept_size, | 
|  | 1379 | usbtouch->data, usbtouch->data_dma); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1380 | kfree(usbtouch->buffer); | 
|  | 1381 | } | 
|  | 1382 |  | 
| Ondrej Zary | f4a5e35 | 2010-02-03 23:54:59 -0800 | [diff] [blame] | 1383 | static struct usb_endpoint_descriptor * | 
|  | 1384 | usbtouch_get_input_endpoint(struct usb_host_interface *interface) | 
|  | 1385 | { | 
|  | 1386 | int i; | 
|  | 1387 |  | 
|  | 1388 | for (i = 0; i < interface->desc.bNumEndpoints; i++) | 
|  | 1389 | if (usb_endpoint_dir_in(&interface->endpoint[i].desc)) | 
|  | 1390 | return &interface->endpoint[i].desc; | 
|  | 1391 |  | 
|  | 1392 | return NULL; | 
|  | 1393 | } | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1394 |  | 
|  | 1395 | static int usbtouch_probe(struct usb_interface *intf, | 
|  | 1396 | const struct usb_device_id *id) | 
|  | 1397 | { | 
|  | 1398 | struct usbtouch_usb *usbtouch; | 
|  | 1399 | struct input_dev *input_dev; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1400 | struct usb_endpoint_descriptor *endpoint; | 
|  | 1401 | struct usb_device *udev = interface_to_usbdev(intf); | 
|  | 1402 | struct usbtouch_device_info *type; | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 1403 | int err = -ENOMEM; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1404 |  | 
| Daniel Ritz | ec42d44 | 2008-07-03 10:45:37 -0400 | [diff] [blame] | 1405 | /* some devices are ignored */ | 
|  | 1406 | if (id->driver_info == DEVTYPE_IGNORE) | 
|  | 1407 | return -ENODEV; | 
|  | 1408 |  | 
| Ondrej Zary | f4a5e35 | 2010-02-03 23:54:59 -0800 | [diff] [blame] | 1409 | endpoint = usbtouch_get_input_endpoint(intf->cur_altsetting); | 
|  | 1410 | if (!endpoint) | 
|  | 1411 | return -ENXIO; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1412 |  | 
|  | 1413 | usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL); | 
|  | 1414 | input_dev = input_allocate_device(); | 
|  | 1415 | if (!usbtouch || !input_dev) | 
|  | 1416 | goto out_free; | 
|  | 1417 |  | 
|  | 1418 | type = &usbtouch_dev_info[id->driver_info]; | 
|  | 1419 | usbtouch->type = type; | 
|  | 1420 | if (!type->process_pkt) | 
|  | 1421 | type->process_pkt = usbtouch_process_pkt; | 
|  | 1422 |  | 
| Daniel Mack | 997ea58 | 2010-04-12 13:17:25 +0200 | [diff] [blame] | 1423 | usbtouch->data = usb_alloc_coherent(udev, type->rept_size, | 
|  | 1424 | GFP_KERNEL, &usbtouch->data_dma); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1425 | if (!usbtouch->data) | 
|  | 1426 | goto out_free; | 
|  | 1427 |  | 
| Daniel Ritz | 62aa366 | 2008-01-17 12:01:18 -0500 | [diff] [blame] | 1428 | if (type->get_pkt_len) { | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1429 | usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL); | 
|  | 1430 | if (!usbtouch->buffer) | 
|  | 1431 | goto out_free_buffers; | 
|  | 1432 | } | 
|  | 1433 |  | 
|  | 1434 | usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL); | 
|  | 1435 | if (!usbtouch->irq) { | 
| Harvey Harrison | ea3e6c5 | 2008-05-05 11:36:18 -0400 | [diff] [blame] | 1436 | dbg("%s - usb_alloc_urb failed: usbtouch->irq", __func__); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1437 | goto out_free_buffers; | 
|  | 1438 | } | 
|  | 1439 |  | 
| Ondrej Zary | fea4d14 | 2010-02-03 23:46:48 -0800 | [diff] [blame] | 1440 | usbtouch->interface = intf; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1441 | usbtouch->input = input_dev; | 
|  | 1442 |  | 
|  | 1443 | if (udev->manufacturer) | 
|  | 1444 | strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name)); | 
|  | 1445 |  | 
|  | 1446 | if (udev->product) { | 
|  | 1447 | if (udev->manufacturer) | 
|  | 1448 | strlcat(usbtouch->name, " ", sizeof(usbtouch->name)); | 
|  | 1449 | strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name)); | 
|  | 1450 | } | 
|  | 1451 |  | 
|  | 1452 | if (!strlen(usbtouch->name)) | 
|  | 1453 | snprintf(usbtouch->name, sizeof(usbtouch->name), | 
|  | 1454 | "USB Touchscreen %04x:%04x", | 
|  | 1455 | le16_to_cpu(udev->descriptor.idVendor), | 
|  | 1456 | le16_to_cpu(udev->descriptor.idProduct)); | 
|  | 1457 |  | 
|  | 1458 | usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys)); | 
| Vladimir Shebordaev | 7b6dff9 | 2007-09-06 21:32:16 -0400 | [diff] [blame] | 1459 | strlcat(usbtouch->phys, "/input0", sizeof(usbtouch->phys)); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1460 |  | 
|  | 1461 | input_dev->name = usbtouch->name; | 
|  | 1462 | input_dev->phys = usbtouch->phys; | 
|  | 1463 | usb_to_input_id(udev, &input_dev->id); | 
| Dmitry Torokhov | c0f82d5 | 2007-04-12 01:35:03 -0400 | [diff] [blame] | 1464 | input_dev->dev.parent = &intf->dev; | 
| Dmitry Torokhov | 7791bda | 2007-04-12 01:34:39 -0400 | [diff] [blame] | 1465 |  | 
|  | 1466 | input_set_drvdata(input_dev, usbtouch); | 
|  | 1467 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1468 | input_dev->open = usbtouch_open; | 
|  | 1469 | input_dev->close = usbtouch_close; | 
|  | 1470 |  | 
| Jiri Slaby | 7b19ada | 2007-10-18 23:40:32 -0700 | [diff] [blame] | 1471 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 
|  | 1472 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1473 | input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0); | 
|  | 1474 | input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0); | 
|  | 1475 | if (type->max_press) | 
|  | 1476 | input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press, | 
|  | 1477 | type->max_press, 0, 0); | 
|  | 1478 |  | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 1479 | if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT) | 
|  | 1480 | usb_fill_int_urb(usbtouch->irq, udev, | 
| Ondrej Zary | fea4d14 | 2010-02-03 23:46:48 -0800 | [diff] [blame] | 1481 | usb_rcvintpipe(udev, endpoint->bEndpointAddress), | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1482 | usbtouch->data, type->rept_size, | 
|  | 1483 | usbtouch_irq, usbtouch, endpoint->bInterval); | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 1484 | else | 
|  | 1485 | usb_fill_bulk_urb(usbtouch->irq, udev, | 
|  | 1486 | usb_rcvbulkpipe(udev, endpoint->bEndpointAddress), | 
|  | 1487 | usbtouch->data, type->rept_size, | 
|  | 1488 | usbtouch_irq, usbtouch); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1489 |  | 
| Ondrej Zary | fea4d14 | 2010-02-03 23:46:48 -0800 | [diff] [blame] | 1490 | usbtouch->irq->dev = udev; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1491 | usbtouch->irq->transfer_dma = usbtouch->data_dma; | 
|  | 1492 | usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 
|  | 1493 |  | 
| Oliver Neukum | a8aef62 | 2010-07-15 09:21:40 -0700 | [diff] [blame] | 1494 | /* device specific allocations */ | 
|  | 1495 | if (type->alloc) { | 
|  | 1496 | err = type->alloc(usbtouch); | 
|  | 1497 | if (err) { | 
|  | 1498 | dbg("%s - type->alloc() failed, err: %d", __func__, err); | 
|  | 1499 | goto out_free_urb; | 
|  | 1500 | } | 
|  | 1501 | } | 
|  | 1502 |  | 
|  | 1503 | /* device specific initialisation*/ | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1504 | if (type->init) { | 
|  | 1505 | err = type->init(usbtouch); | 
|  | 1506 | if (err) { | 
| Harvey Harrison | ea3e6c5 | 2008-05-05 11:36:18 -0400 | [diff] [blame] | 1507 | dbg("%s - type->init() failed, err: %d", __func__, err); | 
| Oliver Neukum | a8aef62 | 2010-07-15 09:21:40 -0700 | [diff] [blame] | 1508 | goto out_do_exit; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1509 | } | 
|  | 1510 | } | 
|  | 1511 |  | 
|  | 1512 | err = input_register_device(usbtouch->input); | 
|  | 1513 | if (err) { | 
| Harvey Harrison | ea3e6c5 | 2008-05-05 11:36:18 -0400 | [diff] [blame] | 1514 | dbg("%s - input_register_device failed, err: %d", __func__, err); | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 1515 | goto out_do_exit; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1516 | } | 
|  | 1517 |  | 
|  | 1518 | usb_set_intfdata(intf, usbtouch); | 
|  | 1519 |  | 
| Ondrej Zary | 1e87a43 | 2010-02-04 00:20:35 -0800 | [diff] [blame] | 1520 | if (usbtouch->type->irq_always) { | 
| Oliver Neukum | 5d9efc5 | 2010-07-15 09:19:51 -0700 | [diff] [blame] | 1521 | /* this can't fail */ | 
|  | 1522 | usb_autopm_get_interface(intf); | 
| Ondrej Zary | 1e87a43 | 2010-02-04 00:20:35 -0800 | [diff] [blame] | 1523 | err = usb_submit_urb(usbtouch->irq, GFP_KERNEL); | 
|  | 1524 | if (err) { | 
| Oliver Neukum | 5d9efc5 | 2010-07-15 09:19:51 -0700 | [diff] [blame] | 1525 | usb_autopm_put_interface(intf); | 
| Ondrej Zary | 1e87a43 | 2010-02-04 00:20:35 -0800 | [diff] [blame] | 1526 | err("%s - usb_submit_urb failed with result: %d", | 
|  | 1527 | __func__, err); | 
|  | 1528 | goto out_unregister_input; | 
|  | 1529 | } | 
|  | 1530 | } | 
| Daniel Silverstone | 2330ed1 | 2009-11-23 08:38:16 -0800 | [diff] [blame] | 1531 |  | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1532 | return 0; | 
|  | 1533 |  | 
| Ondrej Zary | 1e87a43 | 2010-02-04 00:20:35 -0800 | [diff] [blame] | 1534 | out_unregister_input: | 
|  | 1535 | input_unregister_device(input_dev); | 
|  | 1536 | input_dev = NULL; | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 1537 | out_do_exit: | 
|  | 1538 | if (type->exit) | 
|  | 1539 | type->exit(usbtouch); | 
| Ondrej Zary | 1e87a43 | 2010-02-04 00:20:35 -0800 | [diff] [blame] | 1540 | out_free_urb: | 
|  | 1541 | usb_free_urb(usbtouch->irq); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1542 | out_free_buffers: | 
|  | 1543 | usbtouch_free_buffers(udev, usbtouch); | 
|  | 1544 | out_free: | 
|  | 1545 | input_free_device(input_dev); | 
|  | 1546 | kfree(usbtouch); | 
| Daniel Ritz | 5d89266 | 2006-07-31 21:43:24 +0200 | [diff] [blame] | 1547 | return err; | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1548 | } | 
|  | 1549 |  | 
|  | 1550 | static void usbtouch_disconnect(struct usb_interface *intf) | 
|  | 1551 | { | 
|  | 1552 | struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); | 
|  | 1553 |  | 
| Harvey Harrison | ea3e6c5 | 2008-05-05 11:36:18 -0400 | [diff] [blame] | 1554 | dbg("%s - called", __func__); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1555 |  | 
|  | 1556 | if (!usbtouch) | 
|  | 1557 | return; | 
|  | 1558 |  | 
| Harvey Harrison | ea3e6c5 | 2008-05-05 11:36:18 -0400 | [diff] [blame] | 1559 | dbg("%s - usbtouch is initialized, cleaning up", __func__); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1560 | usb_set_intfdata(intf, NULL); | 
| Oliver Neukum | 722232bc | 2009-11-23 08:10:50 -0800 | [diff] [blame] | 1561 | /* this will stop IO via close */ | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1562 | input_unregister_device(usbtouch->input); | 
|  | 1563 | usb_free_urb(usbtouch->irq); | 
| Ondrej Zary | 5197424 | 2010-02-04 00:17:18 -0800 | [diff] [blame] | 1564 | if (usbtouch->type->exit) | 
|  | 1565 | usbtouch->type->exit(usbtouch); | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1566 | usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); | 
|  | 1567 | kfree(usbtouch); | 
|  | 1568 | } | 
|  | 1569 |  | 
|  | 1570 | MODULE_DEVICE_TABLE(usb, usbtouch_devices); | 
|  | 1571 |  | 
|  | 1572 | static struct usb_driver usbtouch_driver = { | 
|  | 1573 | .name		= "usbtouchscreen", | 
|  | 1574 | .probe		= usbtouch_probe, | 
|  | 1575 | .disconnect	= usbtouch_disconnect, | 
| Oliver Neukum | ed4299e | 2010-07-15 09:16:39 -0700 | [diff] [blame] | 1576 | .suspend	= usbtouch_suspend, | 
|  | 1577 | .resume		= usbtouch_resume, | 
| Oliver Neukum | a8aef62 | 2010-07-15 09:21:40 -0700 | [diff] [blame] | 1578 | .reset_resume	= usbtouch_reset_resume, | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1579 | .id_table	= usbtouch_devices, | 
| Oliver Neukum | 5d9efc5 | 2010-07-15 09:19:51 -0700 | [diff] [blame] | 1580 | .supports_autosuspend = 1, | 
| Daniel Ritz | 1d3e202 | 2006-03-29 22:41:07 +0200 | [diff] [blame] | 1581 | }; | 
|  | 1582 |  | 
|  | 1583 | static int __init usbtouch_init(void) | 
|  | 1584 | { | 
|  | 1585 | return usb_register(&usbtouch_driver); | 
|  | 1586 | } | 
|  | 1587 |  | 
|  | 1588 | static void __exit usbtouch_cleanup(void) | 
|  | 1589 | { | 
|  | 1590 | usb_deregister(&usbtouch_driver); | 
|  | 1591 | } | 
|  | 1592 |  | 
|  | 1593 | module_init(usbtouch_init); | 
|  | 1594 | module_exit(usbtouch_cleanup); | 
|  | 1595 |  | 
|  | 1596 | MODULE_AUTHOR(DRIVER_AUTHOR); | 
|  | 1597 | MODULE_DESCRIPTION(DRIVER_DESC); | 
|  | 1598 | MODULE_LICENSE("GPL"); | 
|  | 1599 |  | 
|  | 1600 | MODULE_ALIAS("touchkitusb"); | 
|  | 1601 | MODULE_ALIAS("itmtouch"); | 
|  | 1602 | MODULE_ALIAS("mtouchusb"); |