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