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