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 20d05e84e6SDmitry Torokhov * 2114e40206SJerrold Jones * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> 22d05e84e6SDmitry Torokhov * Copyright (C) by Todd E. Johnson (mtouchusb.c) 23d05e84e6SDmitry Torokhov * 24d05e84e6SDmitry Torokhov * This program is free software; you can redistribute it and/or 25d05e84e6SDmitry Torokhov * modify it under the terms of the GNU General Public License as 26d05e84e6SDmitry Torokhov * published by the Free Software Foundation; either version 2 of the 27d05e84e6SDmitry Torokhov * License, or (at your option) any later version. 28d05e84e6SDmitry Torokhov * 29d05e84e6SDmitry Torokhov * This program is distributed in the hope that it will be useful, but 30d05e84e6SDmitry Torokhov * WITHOUT ANY WARRANTY; without even the implied warranty of 31d05e84e6SDmitry Torokhov * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 32d05e84e6SDmitry Torokhov * General Public License for more details. 33d05e84e6SDmitry Torokhov * 34d05e84e6SDmitry Torokhov * You should have received a copy of the GNU General Public License 35d05e84e6SDmitry Torokhov * along with this program; if not, write to the Free Software 36d05e84e6SDmitry Torokhov * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 37d05e84e6SDmitry Torokhov * 38d05e84e6SDmitry Torokhov * Driver is based on touchkitusb.c 39d05e84e6SDmitry Torokhov * - ITM parts are from itmtouch.c 40d05e84e6SDmitry Torokhov * - 3M parts are from mtouchusb.c 41d05e84e6SDmitry Torokhov * - PanJit parts are from an unmerged driver by Lanslott Gish 42d05e84e6SDmitry Torokhov * - DMC TSC 10/25 are from Holger Schurig, with ideas from an unmerged 43d05e84e6SDmitry Torokhov * driver from Marius Vollmer 44d05e84e6SDmitry Torokhov * 45d05e84e6SDmitry Torokhov *****************************************************************************/ 46d05e84e6SDmitry Torokhov 47d05e84e6SDmitry Torokhov //#define DEBUG 48d05e84e6SDmitry Torokhov 49d05e84e6SDmitry Torokhov #include <linux/kernel.h> 50d05e84e6SDmitry Torokhov #include <linux/slab.h> 51d05e84e6SDmitry Torokhov #include <linux/input.h> 52d05e84e6SDmitry Torokhov #include <linux/module.h> 53d05e84e6SDmitry Torokhov #include <linux/init.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 63*90ab5ee9SRusty 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 67*90ab5ee9SRusty 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; 108d05e84e6SDmitry Torokhov unsigned char *buffer; 109d05e84e6SDmitry Torokhov int buf_len; 110d05e84e6SDmitry Torokhov struct urb *irq; 111fea4d14bSOndrej Zary struct usb_interface *interface; 112d05e84e6SDmitry Torokhov struct input_dev *input; 113d05e84e6SDmitry Torokhov struct usbtouch_device_info *type; 114d05e84e6SDmitry Torokhov char name[128]; 115d05e84e6SDmitry Torokhov char phys[64]; 1165197424cSOndrej Zary void *priv; 117d05e84e6SDmitry Torokhov 118d05e84e6SDmitry Torokhov int x, y; 119d05e84e6SDmitry Torokhov int touch, press; 120d05e84e6SDmitry Torokhov }; 121d05e84e6SDmitry Torokhov 122d05e84e6SDmitry Torokhov 123d05e84e6SDmitry Torokhov /* device types */ 124d05e84e6SDmitry Torokhov enum { 125ec42d448SDaniel Ritz DEVTYPE_IGNORE = -1, 126d05e84e6SDmitry Torokhov DEVTYPE_EGALAX, 127d05e84e6SDmitry Torokhov DEVTYPE_PANJIT, 128d05e84e6SDmitry Torokhov DEVTYPE_3M, 129d05e84e6SDmitry Torokhov DEVTYPE_ITM, 130d05e84e6SDmitry Torokhov DEVTYPE_ETURBO, 131d05e84e6SDmitry Torokhov DEVTYPE_GUNZE, 132d05e84e6SDmitry Torokhov DEVTYPE_DMC_TSC10, 133df561fcdSOndrej Zary DEVTYPE_IRTOUCH, 134a14a8401SOndrej Zary DEVTYPE_IDEALTEK, 1359d5657dbSIlya Frolov DEVTYPE_GENERAL_TOUCH, 13614e40206SJerrold Jones DEVTYPE_GOTOP, 137f7370699SJim Persson DEVTYPE_JASTEC, 1389e3b2583SFlorian Echtler DEVTYPE_E2I, 1392330ed18SDaniel Silverstone DEVTYPE_ZYTRONIC, 14038771bb4SPetr Štetiar DEVTYPE_TC45USB, 1415197424cSOndrej Zary DEVTYPE_NEXIO, 142d2cc817aSMichael Gebetsroither DEVTYPE_ELO, 143d05e84e6SDmitry Torokhov }; 144d05e84e6SDmitry Torokhov 145ec42d448SDaniel Ritz #define USB_DEVICE_HID_CLASS(vend, prod) \ 146ec42d448SDaniel Ritz .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \ 147139ebe8dSDaniel Ritz | USB_DEVICE_ID_MATCH_INT_PROTOCOL \ 148ec42d448SDaniel Ritz | USB_DEVICE_ID_MATCH_DEVICE, \ 149ec42d448SDaniel Ritz .idVendor = (vend), \ 150ec42d448SDaniel Ritz .idProduct = (prod), \ 151ec42d448SDaniel Ritz .bInterfaceClass = USB_INTERFACE_CLASS_HID, \ 152ec42d448SDaniel Ritz .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE 153ec42d448SDaniel Ritz 1549cb3ce52SMárton Németh static const struct usb_device_id usbtouch_devices[] = { 155c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 156ec42d448SDaniel Ritz /* ignore the HID capable devices, handled by usbhid */ 157ec42d448SDaniel Ritz {USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE}, 158ec42d448SDaniel Ritz {USB_DEVICE_HID_CLASS(0x0eef, 0x0002), .driver_info = DEVTYPE_IGNORE}, 159ec42d448SDaniel Ritz 160ec42d448SDaniel Ritz /* normal device IDs */ 161d05e84e6SDmitry Torokhov {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX}, 162d05e84e6SDmitry Torokhov {USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX}, 163d05e84e6SDmitry Torokhov {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX}, 164d05e84e6SDmitry Torokhov {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX}, 165d05e84e6SDmitry Torokhov {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX}, 166d05e84e6SDmitry Torokhov {USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX}, 167d05e84e6SDmitry Torokhov {USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX}, 168d05e84e6SDmitry Torokhov #endif 169d05e84e6SDmitry Torokhov 170c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 171d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT}, 172d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT}, 173d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT}, 174d05e84e6SDmitry Torokhov {USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT}, 175d05e84e6SDmitry Torokhov #endif 176d05e84e6SDmitry Torokhov 177c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_3M 178d05e84e6SDmitry Torokhov {USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M}, 179d05e84e6SDmitry Torokhov #endif 180d05e84e6SDmitry Torokhov 181c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ITM 182d05e84e6SDmitry Torokhov {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, 18309910509SGlenn Sommer {USB_DEVICE(0x16e3, 0xf9e9), .driver_info = DEVTYPE_ITM}, 184d05e84e6SDmitry Torokhov #endif 185d05e84e6SDmitry Torokhov 186c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 187d05e84e6SDmitry Torokhov {USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO}, 188d05e84e6SDmitry Torokhov #endif 189d05e84e6SDmitry Torokhov 190c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE 191d05e84e6SDmitry Torokhov {USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE}, 192d05e84e6SDmitry Torokhov #endif 193d05e84e6SDmitry Torokhov 194c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 195d05e84e6SDmitry Torokhov {USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10}, 196d05e84e6SDmitry Torokhov #endif 197d05e84e6SDmitry Torokhov 198df561fcdSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH 199df561fcdSOndrej Zary {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, 200df561fcdSOndrej Zary {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, 201df561fcdSOndrej Zary #endif 202df561fcdSOndrej Zary 203a14a8401SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 204a14a8401SOndrej Zary {USB_DEVICE(0x1391, 0x1000), .driver_info = DEVTYPE_IDEALTEK}, 205a14a8401SOndrej Zary #endif 206a14a8401SOndrej Zary 2079d5657dbSIlya Frolov #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH 2089d5657dbSIlya Frolov {USB_DEVICE(0x0dfc, 0x0001), .driver_info = DEVTYPE_GENERAL_TOUCH}, 2099d5657dbSIlya Frolov #endif 2109d5657dbSIlya Frolov 21114e40206SJerrold Jones #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 21214e40206SJerrold Jones {USB_DEVICE(0x08f2, 0x007f), .driver_info = DEVTYPE_GOTOP}, 21314e40206SJerrold Jones {USB_DEVICE(0x08f2, 0x00ce), .driver_info = DEVTYPE_GOTOP}, 21414e40206SJerrold Jones {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP}, 21514e40206SJerrold Jones #endif 21614e40206SJerrold Jones 217f7370699SJim Persson #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC 218f7370699SJim Persson {USB_DEVICE(0x0f92, 0x0001), .driver_info = DEVTYPE_JASTEC}, 219f7370699SJim Persson #endif 220f7370699SJim Persson 2219e3b2583SFlorian Echtler #ifdef CONFIG_TOUCHSCREEN_USB_E2I 2229e3b2583SFlorian Echtler {USB_DEVICE(0x1ac7, 0x0001), .driver_info = DEVTYPE_E2I}, 2239e3b2583SFlorian Echtler #endif 2242330ed18SDaniel Silverstone 2252330ed18SDaniel Silverstone #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC 2262330ed18SDaniel Silverstone {USB_DEVICE(0x14c8, 0x0003), .driver_info = DEVTYPE_ZYTRONIC}, 2272330ed18SDaniel Silverstone #endif 2282330ed18SDaniel Silverstone 22938771bb4SPetr Štetiar #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB 23038771bb4SPetr Štetiar /* TC5UH */ 23138771bb4SPetr Štetiar {USB_DEVICE(0x0664, 0x0309), .driver_info = DEVTYPE_TC45USB}, 23238771bb4SPetr Štetiar /* TC4UM */ 23338771bb4SPetr Štetiar {USB_DEVICE(0x0664, 0x0306), .driver_info = DEVTYPE_TC45USB}, 234dbe1420bSPetr Štetiar #endif 235dbe1420bSPetr Štetiar 2365197424cSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO 2375197424cSOndrej Zary /* data interface only */ 2385197424cSOndrej Zary {USB_DEVICE_AND_INTERFACE_INFO(0x10f0, 0x2002, 0x0a, 0x00, 0x00), 2395197424cSOndrej Zary .driver_info = DEVTYPE_NEXIO}, 2405197424cSOndrej Zary {USB_DEVICE_AND_INTERFACE_INFO(0x1870, 0x0001, 0x0a, 0x00, 0x00), 2415197424cSOndrej Zary .driver_info = DEVTYPE_NEXIO}, 2425197424cSOndrej Zary #endif 2435197424cSOndrej Zary 244d2cc817aSMichael Gebetsroither #ifdef CONFIG_TOUCHSCREEN_USB_ELO 245d2cc817aSMichael Gebetsroither {USB_DEVICE(0x04e7, 0x0020), .driver_info = DEVTYPE_ELO}, 246d2cc817aSMichael Gebetsroither #endif 247d2cc817aSMichael Gebetsroither 248d05e84e6SDmitry Torokhov {} 249d05e84e6SDmitry Torokhov }; 250d05e84e6SDmitry Torokhov 251d05e84e6SDmitry Torokhov 252d05e84e6SDmitry Torokhov /***************************************************************************** 2539e3b2583SFlorian Echtler * e2i Part 2549e3b2583SFlorian Echtler */ 2559e3b2583SFlorian Echtler 2569e3b2583SFlorian Echtler #ifdef CONFIG_TOUCHSCREEN_USB_E2I 2579e3b2583SFlorian Echtler static int e2i_init(struct usbtouch_usb *usbtouch) 2589e3b2583SFlorian Echtler { 2599e3b2583SFlorian Echtler int ret; 260fea4d14bSOndrej Zary struct usb_device *udev = interface_to_usbdev(usbtouch->interface); 2619e3b2583SFlorian Echtler 262fea4d14bSOndrej Zary ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 2639e3b2583SFlorian Echtler 0x01, 0x02, 0x0000, 0x0081, 2649e3b2583SFlorian Echtler NULL, 0, USB_CTRL_SET_TIMEOUT); 2659e3b2583SFlorian Echtler 2669e3b2583SFlorian Echtler dbg("%s - usb_control_msg - E2I_RESET - bytes|err: %d", 2679e3b2583SFlorian Echtler __func__, ret); 2689e3b2583SFlorian Echtler return ret; 2699e3b2583SFlorian Echtler } 2709e3b2583SFlorian Echtler 2719e3b2583SFlorian Echtler static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 2729e3b2583SFlorian Echtler { 2739e3b2583SFlorian Echtler int tmp = (pkt[0] << 8) | pkt[1]; 2749e3b2583SFlorian Echtler dev->x = (pkt[2] << 8) | pkt[3]; 2759e3b2583SFlorian Echtler dev->y = (pkt[4] << 8) | pkt[5]; 2769e3b2583SFlorian Echtler 2779e3b2583SFlorian Echtler tmp = tmp - 0xA000; 2789e3b2583SFlorian Echtler dev->touch = (tmp > 0); 2799e3b2583SFlorian Echtler dev->press = (tmp > 0 ? tmp : 0); 2809e3b2583SFlorian Echtler 2819e3b2583SFlorian Echtler return 1; 2829e3b2583SFlorian Echtler } 2839e3b2583SFlorian Echtler #endif 2849e3b2583SFlorian Echtler 2859e3b2583SFlorian Echtler 2869e3b2583SFlorian Echtler /***************************************************************************** 287d05e84e6SDmitry Torokhov * eGalax part 288d05e84e6SDmitry Torokhov */ 289d05e84e6SDmitry Torokhov 290c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 291d05e84e6SDmitry Torokhov 29262aa366dSDaniel Ritz #ifndef MULTI_PACKET 29362aa366dSDaniel Ritz #define MULTI_PACKET 29462aa366dSDaniel Ritz #endif 29562aa366dSDaniel Ritz 296d05e84e6SDmitry Torokhov #define EGALAX_PKT_TYPE_MASK 0xFE 297d05e84e6SDmitry Torokhov #define EGALAX_PKT_TYPE_REPT 0x80 298d05e84e6SDmitry Torokhov #define EGALAX_PKT_TYPE_DIAG 0x0A 299d05e84e6SDmitry Torokhov 300d05e84e6SDmitry Torokhov static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 301d05e84e6SDmitry Torokhov { 302d05e84e6SDmitry Torokhov if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) 303d05e84e6SDmitry Torokhov return 0; 304d05e84e6SDmitry Torokhov 305d05e84e6SDmitry Torokhov dev->x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F); 306d05e84e6SDmitry Torokhov dev->y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F); 307d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x01; 308d05e84e6SDmitry Torokhov 309d05e84e6SDmitry Torokhov return 1; 310d05e84e6SDmitry Torokhov } 311d05e84e6SDmitry Torokhov 312d05e84e6SDmitry Torokhov static int egalax_get_pkt_len(unsigned char *buf, int len) 313d05e84e6SDmitry Torokhov { 314d05e84e6SDmitry Torokhov switch (buf[0] & EGALAX_PKT_TYPE_MASK) { 315d05e84e6SDmitry Torokhov case EGALAX_PKT_TYPE_REPT: 316d05e84e6SDmitry Torokhov return 5; 317d05e84e6SDmitry Torokhov 318d05e84e6SDmitry Torokhov case EGALAX_PKT_TYPE_DIAG: 319d05e84e6SDmitry Torokhov if (len < 2) 320d05e84e6SDmitry Torokhov return -1; 321d05e84e6SDmitry Torokhov 322d05e84e6SDmitry Torokhov return buf[1] + 2; 323d05e84e6SDmitry Torokhov } 324d05e84e6SDmitry Torokhov 325d05e84e6SDmitry Torokhov return 0; 326d05e84e6SDmitry Torokhov } 327d05e84e6SDmitry Torokhov #endif 328d05e84e6SDmitry Torokhov 329d05e84e6SDmitry Torokhov 330d05e84e6SDmitry Torokhov /***************************************************************************** 331d05e84e6SDmitry Torokhov * PanJit Part 332d05e84e6SDmitry Torokhov */ 333c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 334d05e84e6SDmitry Torokhov static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 335d05e84e6SDmitry Torokhov { 336d05e84e6SDmitry Torokhov dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; 337d05e84e6SDmitry Torokhov dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; 338d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x01; 339d05e84e6SDmitry Torokhov 340d05e84e6SDmitry Torokhov return 1; 341d05e84e6SDmitry Torokhov } 342d05e84e6SDmitry Torokhov #endif 343d05e84e6SDmitry Torokhov 344d05e84e6SDmitry Torokhov 345d05e84e6SDmitry Torokhov /***************************************************************************** 346d05e84e6SDmitry Torokhov * 3M/Microtouch Part 347d05e84e6SDmitry Torokhov */ 348c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_3M 349d05e84e6SDmitry Torokhov 350d05e84e6SDmitry Torokhov #define MTOUCHUSB_ASYNC_REPORT 1 351d05e84e6SDmitry Torokhov #define MTOUCHUSB_RESET 7 352d05e84e6SDmitry Torokhov #define MTOUCHUSB_REQ_CTRLLR_ID 10 353d05e84e6SDmitry Torokhov 354d05e84e6SDmitry Torokhov static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 355d05e84e6SDmitry Torokhov { 356c9cbf3d3SDan Streetman if (hwcalib_xy) { 357c9cbf3d3SDan Streetman dev->x = (pkt[4] << 8) | pkt[3]; 358c9cbf3d3SDan Streetman dev->y = 0xffff - ((pkt[6] << 8) | pkt[5]); 359c9cbf3d3SDan Streetman } else { 360d05e84e6SDmitry Torokhov dev->x = (pkt[8] << 8) | pkt[7]; 361d05e84e6SDmitry Torokhov dev->y = (pkt[10] << 8) | pkt[9]; 362c9cbf3d3SDan Streetman } 363d05e84e6SDmitry Torokhov dev->touch = (pkt[2] & 0x40) ? 1 : 0; 364d05e84e6SDmitry Torokhov 365d05e84e6SDmitry Torokhov return 1; 366d05e84e6SDmitry Torokhov } 367d05e84e6SDmitry Torokhov 368d05e84e6SDmitry Torokhov static int mtouch_init(struct usbtouch_usb *usbtouch) 369d05e84e6SDmitry Torokhov { 370d05e84e6SDmitry Torokhov int ret, i; 371fea4d14bSOndrej Zary struct usb_device *udev = interface_to_usbdev(usbtouch->interface); 372d05e84e6SDmitry Torokhov 373fea4d14bSOndrej Zary ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 374d05e84e6SDmitry Torokhov MTOUCHUSB_RESET, 375d05e84e6SDmitry Torokhov USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 376d05e84e6SDmitry Torokhov 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); 377d05e84e6SDmitry Torokhov dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", 378ea3e6c59SHarvey Harrison __func__, ret); 379d05e84e6SDmitry Torokhov if (ret < 0) 380d05e84e6SDmitry Torokhov return ret; 381d05e84e6SDmitry Torokhov msleep(150); 382d05e84e6SDmitry Torokhov 383d05e84e6SDmitry Torokhov for (i = 0; i < 3; i++) { 384fea4d14bSOndrej Zary ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 385d05e84e6SDmitry Torokhov MTOUCHUSB_ASYNC_REPORT, 386d05e84e6SDmitry Torokhov USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 387d05e84e6SDmitry Torokhov 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); 388d05e84e6SDmitry Torokhov dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", 389ea3e6c59SHarvey Harrison __func__, ret); 390d05e84e6SDmitry Torokhov if (ret >= 0) 391d05e84e6SDmitry Torokhov break; 392d05e84e6SDmitry Torokhov if (ret != -EPIPE) 393d05e84e6SDmitry Torokhov return ret; 394d05e84e6SDmitry Torokhov } 395d05e84e6SDmitry Torokhov 396c9cbf3d3SDan Streetman /* Default min/max xy are the raw values, override if using hw-calib */ 397c9cbf3d3SDan Streetman if (hwcalib_xy) { 398c9cbf3d3SDan Streetman input_set_abs_params(usbtouch->input, ABS_X, 0, 0xffff, 0, 0); 399c9cbf3d3SDan Streetman input_set_abs_params(usbtouch->input, ABS_Y, 0, 0xffff, 0, 0); 400c9cbf3d3SDan Streetman } 401c9cbf3d3SDan Streetman 402d05e84e6SDmitry Torokhov return 0; 403d05e84e6SDmitry Torokhov } 404d05e84e6SDmitry Torokhov #endif 405d05e84e6SDmitry Torokhov 406d05e84e6SDmitry Torokhov 407d05e84e6SDmitry Torokhov /***************************************************************************** 408d05e84e6SDmitry Torokhov * ITM Part 409d05e84e6SDmitry Torokhov */ 410c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ITM 411d05e84e6SDmitry Torokhov static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 412d05e84e6SDmitry Torokhov { 413d05e84e6SDmitry Torokhov int touch; 414d05e84e6SDmitry Torokhov /* 415d05e84e6SDmitry Torokhov * ITM devices report invalid x/y data if not touched. 416d05e84e6SDmitry Torokhov * if the screen was touched before but is not touched any more 417d05e84e6SDmitry Torokhov * report touch as 0 with the last valid x/y data once. then stop 418d05e84e6SDmitry Torokhov * reporting data until touched again. 419d05e84e6SDmitry Torokhov */ 420d05e84e6SDmitry Torokhov dev->press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F); 421d05e84e6SDmitry Torokhov 422d05e84e6SDmitry Torokhov touch = ~pkt[7] & 0x20; 423d05e84e6SDmitry Torokhov if (!touch) { 424d05e84e6SDmitry Torokhov if (dev->touch) { 425d05e84e6SDmitry Torokhov dev->touch = 0; 426d05e84e6SDmitry Torokhov return 1; 427d05e84e6SDmitry Torokhov } 428d05e84e6SDmitry Torokhov 429d05e84e6SDmitry Torokhov return 0; 430d05e84e6SDmitry Torokhov } 431d05e84e6SDmitry Torokhov 432d05e84e6SDmitry Torokhov dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F); 433d05e84e6SDmitry Torokhov dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F); 434d05e84e6SDmitry Torokhov dev->touch = touch; 435d05e84e6SDmitry Torokhov 436d05e84e6SDmitry Torokhov return 1; 437d05e84e6SDmitry Torokhov } 438d05e84e6SDmitry Torokhov #endif 439d05e84e6SDmitry Torokhov 440d05e84e6SDmitry Torokhov 441d05e84e6SDmitry Torokhov /***************************************************************************** 442d05e84e6SDmitry Torokhov * eTurboTouch part 443d05e84e6SDmitry Torokhov */ 444c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 44562aa366dSDaniel Ritz #ifndef MULTI_PACKET 44662aa366dSDaniel Ritz #define MULTI_PACKET 44762aa366dSDaniel Ritz #endif 448d05e84e6SDmitry Torokhov static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 449d05e84e6SDmitry Torokhov { 450d05e84e6SDmitry Torokhov unsigned int shift; 451d05e84e6SDmitry Torokhov 452d05e84e6SDmitry Torokhov /* packets should start with sync */ 453d05e84e6SDmitry Torokhov if (!(pkt[0] & 0x80)) 454d05e84e6SDmitry Torokhov return 0; 455d05e84e6SDmitry Torokhov 456d05e84e6SDmitry Torokhov shift = (6 - (pkt[0] & 0x03)); 457d05e84e6SDmitry Torokhov dev->x = ((pkt[3] << 7) | pkt[4]) >> shift; 458d05e84e6SDmitry Torokhov dev->y = ((pkt[1] << 7) | pkt[2]) >> shift; 459d05e84e6SDmitry Torokhov dev->touch = (pkt[0] & 0x10) ? 1 : 0; 460d05e84e6SDmitry Torokhov 461d05e84e6SDmitry Torokhov return 1; 462d05e84e6SDmitry Torokhov } 463d05e84e6SDmitry Torokhov 464d05e84e6SDmitry Torokhov static int eturbo_get_pkt_len(unsigned char *buf, int len) 465d05e84e6SDmitry Torokhov { 466d05e84e6SDmitry Torokhov if (buf[0] & 0x80) 467d05e84e6SDmitry Torokhov return 5; 468d05e84e6SDmitry Torokhov if (buf[0] == 0x01) 469d05e84e6SDmitry Torokhov return 3; 470d05e84e6SDmitry Torokhov return 0; 471d05e84e6SDmitry Torokhov } 472d05e84e6SDmitry Torokhov #endif 473d05e84e6SDmitry Torokhov 474d05e84e6SDmitry Torokhov 475d05e84e6SDmitry Torokhov /***************************************************************************** 476d05e84e6SDmitry Torokhov * Gunze part 477d05e84e6SDmitry Torokhov */ 478c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE 479d05e84e6SDmitry Torokhov static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 480d05e84e6SDmitry Torokhov { 481d05e84e6SDmitry Torokhov if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80)) 482d05e84e6SDmitry Torokhov return 0; 483d05e84e6SDmitry Torokhov 484d05e84e6SDmitry Torokhov dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F); 485d05e84e6SDmitry Torokhov dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F); 486d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x20; 487d05e84e6SDmitry Torokhov 488d05e84e6SDmitry Torokhov return 1; 489d05e84e6SDmitry Torokhov } 490d05e84e6SDmitry Torokhov #endif 491d05e84e6SDmitry Torokhov 492d05e84e6SDmitry Torokhov /***************************************************************************** 493d05e84e6SDmitry Torokhov * DMC TSC-10/25 Part 494d05e84e6SDmitry Torokhov * 495d05e84e6SDmitry Torokhov * Documentation about the controller and it's protocol can be found at 496d05e84e6SDmitry Torokhov * http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf 497d05e84e6SDmitry Torokhov * http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf 498d05e84e6SDmitry Torokhov */ 499c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 500d05e84e6SDmitry Torokhov 501d05e84e6SDmitry Torokhov /* supported data rates. currently using 130 */ 502d05e84e6SDmitry Torokhov #define TSC10_RATE_POINT 0x50 503d05e84e6SDmitry Torokhov #define TSC10_RATE_30 0x40 504d05e84e6SDmitry Torokhov #define TSC10_RATE_50 0x41 505d05e84e6SDmitry Torokhov #define TSC10_RATE_80 0x42 506d05e84e6SDmitry Torokhov #define TSC10_RATE_100 0x43 507d05e84e6SDmitry Torokhov #define TSC10_RATE_130 0x44 508d05e84e6SDmitry Torokhov #define TSC10_RATE_150 0x45 509d05e84e6SDmitry Torokhov 510d05e84e6SDmitry Torokhov /* commands */ 511d05e84e6SDmitry Torokhov #define TSC10_CMD_RESET 0x55 512d05e84e6SDmitry Torokhov #define TSC10_CMD_RATE 0x05 513d05e84e6SDmitry Torokhov #define TSC10_CMD_DATA1 0x01 514d05e84e6SDmitry Torokhov 515d05e84e6SDmitry Torokhov static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) 516d05e84e6SDmitry Torokhov { 517fea4d14bSOndrej Zary struct usb_device *dev = interface_to_usbdev(usbtouch->interface); 51876d057ceSOliver Neukum int ret = -ENOMEM; 51976d057ceSOliver Neukum unsigned char *buf; 520d05e84e6SDmitry Torokhov 521a8aef622SOliver Neukum buf = kmalloc(2, GFP_NOIO); 52276d057ceSOliver Neukum if (!buf) 52376d057ceSOliver Neukum goto err_nobuf; 524d05e84e6SDmitry Torokhov /* reset */ 525d05e84e6SDmitry Torokhov buf[0] = buf[1] = 0xFF; 526d05e84e6SDmitry Torokhov ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), 527d05e84e6SDmitry Torokhov TSC10_CMD_RESET, 528d05e84e6SDmitry Torokhov USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 529d05e84e6SDmitry Torokhov 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT); 530d05e84e6SDmitry Torokhov if (ret < 0) 53176d057ceSOliver Neukum goto err_out; 5322ec6f246SNuno Lucas if (buf[0] != 0x06) { 53376d057ceSOliver Neukum ret = -ENODEV; 53476d057ceSOliver Neukum goto err_out; 53576d057ceSOliver Neukum } 536d05e84e6SDmitry Torokhov 537d05e84e6SDmitry Torokhov /* set coordinate output rate */ 538d05e84e6SDmitry Torokhov buf[0] = buf[1] = 0xFF; 539d05e84e6SDmitry Torokhov ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), 540d05e84e6SDmitry Torokhov TSC10_CMD_RATE, 541d05e84e6SDmitry Torokhov USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 542d05e84e6SDmitry Torokhov TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); 543d05e84e6SDmitry Torokhov if (ret < 0) 54476d057ceSOliver Neukum goto err_out; 5452ec6f246SNuno Lucas if ((buf[0] != 0x06) && (buf[0] != 0x15 || buf[1] != 0x01)) { 54676d057ceSOliver Neukum ret = -ENODEV; 54776d057ceSOliver Neukum goto err_out; 54876d057ceSOliver Neukum } 549d05e84e6SDmitry Torokhov 550d05e84e6SDmitry Torokhov /* start sending data */ 551d05e84e6SDmitry Torokhov ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), 552d05e84e6SDmitry Torokhov TSC10_CMD_DATA1, 553d05e84e6SDmitry Torokhov USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 554d05e84e6SDmitry Torokhov 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); 55576d057ceSOliver Neukum err_out: 55676d057ceSOliver Neukum kfree(buf); 55776d057ceSOliver Neukum err_nobuf: 558d05e84e6SDmitry Torokhov return ret; 559d05e84e6SDmitry Torokhov } 560d05e84e6SDmitry Torokhov 561d05e84e6SDmitry Torokhov 562d05e84e6SDmitry Torokhov static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 563d05e84e6SDmitry Torokhov { 564d05e84e6SDmitry Torokhov dev->x = ((pkt[2] & 0x03) << 8) | pkt[1]; 565d05e84e6SDmitry Torokhov dev->y = ((pkt[4] & 0x03) << 8) | pkt[3]; 566d05e84e6SDmitry Torokhov dev->touch = pkt[0] & 0x01; 567d05e84e6SDmitry Torokhov 568d05e84e6SDmitry Torokhov return 1; 569d05e84e6SDmitry Torokhov } 570d05e84e6SDmitry Torokhov #endif 571d05e84e6SDmitry Torokhov 572d05e84e6SDmitry Torokhov 573d05e84e6SDmitry Torokhov /***************************************************************************** 574df561fcdSOndrej Zary * IRTOUCH Part 575df561fcdSOndrej Zary */ 576df561fcdSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH 577df561fcdSOndrej Zary static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 578df561fcdSOndrej Zary { 579df561fcdSOndrej Zary dev->x = (pkt[3] << 8) | pkt[2]; 580df561fcdSOndrej Zary dev->y = (pkt[5] << 8) | pkt[4]; 581df561fcdSOndrej Zary dev->touch = (pkt[1] & 0x03) ? 1 : 0; 582df561fcdSOndrej Zary 583df561fcdSOndrej Zary return 1; 584df561fcdSOndrej Zary } 585df561fcdSOndrej Zary #endif 586df561fcdSOndrej Zary 587dbe1420bSPetr Štetiar /***************************************************************************** 58838771bb4SPetr Štetiar * ET&T TC5UH/TC4UM part 589dbe1420bSPetr Štetiar */ 59038771bb4SPetr Štetiar #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB 59138771bb4SPetr Štetiar static int tc45usb_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 592dbe1420bSPetr Štetiar { 593dbe1420bSPetr Štetiar dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; 594dbe1420bSPetr Štetiar dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; 595dbe1420bSPetr Štetiar dev->touch = pkt[0] & 0x01; 596dbe1420bSPetr Štetiar 597dbe1420bSPetr Štetiar return 1; 598dbe1420bSPetr Štetiar } 599dbe1420bSPetr Štetiar #endif 600df561fcdSOndrej Zary 601df561fcdSOndrej Zary /***************************************************************************** 602a14a8401SOndrej Zary * IdealTEK URTC1000 Part 603a14a8401SOndrej Zary */ 604a14a8401SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 60562aa366dSDaniel Ritz #ifndef MULTI_PACKET 60662aa366dSDaniel Ritz #define MULTI_PACKET 60762aa366dSDaniel Ritz #endif 608a14a8401SOndrej Zary static int idealtek_get_pkt_len(unsigned char *buf, int len) 609a14a8401SOndrej Zary { 610a14a8401SOndrej Zary if (buf[0] & 0x80) 611a14a8401SOndrej Zary return 5; 612a14a8401SOndrej Zary if (buf[0] == 0x01) 613a14a8401SOndrej Zary return len; 614a14a8401SOndrej Zary return 0; 615a14a8401SOndrej Zary } 616a14a8401SOndrej Zary 617a14a8401SOndrej Zary static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 618a14a8401SOndrej Zary { 619a14a8401SOndrej Zary switch (pkt[0] & 0x98) { 620a14a8401SOndrej Zary case 0x88: 621a14a8401SOndrej Zary /* touch data in IdealTEK mode */ 622a14a8401SOndrej Zary dev->x = (pkt[1] << 5) | (pkt[2] >> 2); 623a14a8401SOndrej Zary dev->y = (pkt[3] << 5) | (pkt[4] >> 2); 624a14a8401SOndrej Zary dev->touch = (pkt[0] & 0x40) ? 1 : 0; 625a14a8401SOndrej Zary return 1; 626a14a8401SOndrej Zary 627a14a8401SOndrej Zary case 0x98: 628a14a8401SOndrej Zary /* touch data in MT emulation mode */ 629a14a8401SOndrej Zary dev->x = (pkt[2] << 5) | (pkt[1] >> 2); 630a14a8401SOndrej Zary dev->y = (pkt[4] << 5) | (pkt[3] >> 2); 631a14a8401SOndrej Zary dev->touch = (pkt[0] & 0x40) ? 1 : 0; 632a14a8401SOndrej Zary return 1; 633a14a8401SOndrej Zary 634a14a8401SOndrej Zary default: 635a14a8401SOndrej Zary return 0; 636a14a8401SOndrej Zary } 637a14a8401SOndrej Zary } 638a14a8401SOndrej Zary #endif 639a14a8401SOndrej Zary 6409d5657dbSIlya Frolov /***************************************************************************** 6419d5657dbSIlya Frolov * General Touch Part 6429d5657dbSIlya Frolov */ 6439d5657dbSIlya Frolov #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH 6449d5657dbSIlya Frolov static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 6459d5657dbSIlya Frolov { 646eb083ba2SRoy Yin dev->x = (pkt[2] << 8) | pkt[1]; 647eb083ba2SRoy Yin dev->y = (pkt[4] << 8) | pkt[3]; 6489d5657dbSIlya Frolov dev->press = pkt[5] & 0xff; 6499d5657dbSIlya Frolov dev->touch = pkt[0] & 0x01; 6509d5657dbSIlya Frolov 6519d5657dbSIlya Frolov return 1; 6529d5657dbSIlya Frolov } 6539d5657dbSIlya Frolov #endif 654a14a8401SOndrej Zary 655a14a8401SOndrej Zary /***************************************************************************** 65614e40206SJerrold Jones * GoTop Part 65714e40206SJerrold Jones */ 65814e40206SJerrold Jones #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 65914e40206SJerrold Jones static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 66014e40206SJerrold Jones { 66114e40206SJerrold Jones dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; 66214e40206SJerrold Jones dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; 66314e40206SJerrold Jones dev->touch = pkt[0] & 0x01; 664f7370699SJim Persson 665f7370699SJim Persson return 1; 666f7370699SJim Persson } 667f7370699SJim Persson #endif 668f7370699SJim Persson 669f7370699SJim Persson /***************************************************************************** 670f7370699SJim Persson * JASTEC Part 671f7370699SJim Persson */ 672f7370699SJim Persson #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC 673f7370699SJim Persson static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 674f7370699SJim Persson { 675f7370699SJim Persson dev->x = ((pkt[0] & 0x3f) << 6) | (pkt[2] & 0x3f); 676f7370699SJim Persson dev->y = ((pkt[1] & 0x3f) << 6) | (pkt[3] & 0x3f); 677f7370699SJim Persson dev->touch = (pkt[0] & 0x40) >> 6; 678f7370699SJim Persson 67914e40206SJerrold Jones return 1; 68014e40206SJerrold Jones } 68114e40206SJerrold Jones #endif 68214e40206SJerrold Jones 6832330ed18SDaniel Silverstone /***************************************************************************** 6842330ed18SDaniel Silverstone * Zytronic Part 6852330ed18SDaniel Silverstone */ 6862330ed18SDaniel Silverstone #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC 6872330ed18SDaniel Silverstone static int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 6882330ed18SDaniel Silverstone { 6892330ed18SDaniel Silverstone switch (pkt[0]) { 6902330ed18SDaniel Silverstone case 0x3A: /* command response */ 6912330ed18SDaniel Silverstone dbg("%s: Command response %d", __func__, pkt[1]); 6922330ed18SDaniel Silverstone break; 6932330ed18SDaniel Silverstone 6942330ed18SDaniel Silverstone case 0xC0: /* down */ 6952330ed18SDaniel Silverstone dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); 6962330ed18SDaniel Silverstone dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); 6972330ed18SDaniel Silverstone dev->touch = 1; 6982330ed18SDaniel Silverstone dbg("%s: down %d,%d", __func__, dev->x, dev->y); 6992330ed18SDaniel Silverstone return 1; 7002330ed18SDaniel Silverstone 7012330ed18SDaniel Silverstone case 0x80: /* up */ 7022330ed18SDaniel Silverstone dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); 7032330ed18SDaniel Silverstone dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); 7042330ed18SDaniel Silverstone dev->touch = 0; 7052330ed18SDaniel Silverstone dbg("%s: up %d,%d", __func__, dev->x, dev->y); 7062330ed18SDaniel Silverstone return 1; 7072330ed18SDaniel Silverstone 7082330ed18SDaniel Silverstone default: 7092330ed18SDaniel Silverstone dbg("%s: Unknown return %d", __func__, pkt[0]); 7102330ed18SDaniel Silverstone break; 7112330ed18SDaniel Silverstone } 7122330ed18SDaniel Silverstone 7132330ed18SDaniel Silverstone return 0; 7142330ed18SDaniel Silverstone } 7152330ed18SDaniel Silverstone #endif 71614e40206SJerrold Jones 71714e40206SJerrold Jones /***************************************************************************** 7185197424cSOndrej Zary * NEXIO Part 7195197424cSOndrej Zary */ 7205197424cSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO 7215197424cSOndrej Zary 7225197424cSOndrej Zary #define NEXIO_TIMEOUT 5000 7235197424cSOndrej Zary #define NEXIO_BUFSIZE 1024 7245197424cSOndrej Zary #define NEXIO_THRESHOLD 50 7255197424cSOndrej Zary 7265197424cSOndrej Zary struct nexio_priv { 7275197424cSOndrej Zary struct urb *ack; 7285197424cSOndrej Zary unsigned char *ack_buf; 7295197424cSOndrej Zary }; 7305197424cSOndrej Zary 7315197424cSOndrej Zary struct nexio_touch_packet { 7325197424cSOndrej Zary u8 flags; /* 0xe1 = touch, 0xe1 = release */ 7335197424cSOndrej Zary __be16 data_len; /* total bytes of touch data */ 7345197424cSOndrej Zary __be16 x_len; /* bytes for X axis */ 7355197424cSOndrej Zary __be16 y_len; /* bytes for Y axis */ 7365197424cSOndrej Zary u8 data[]; 7375197424cSOndrej Zary } __attribute__ ((packed)); 7385197424cSOndrej Zary 7395197424cSOndrej Zary static unsigned char nexio_ack_pkt[2] = { 0xaa, 0x02 }; 7405197424cSOndrej Zary static unsigned char nexio_init_pkt[4] = { 0x82, 0x04, 0x0a, 0x0f }; 7415197424cSOndrej Zary 7425197424cSOndrej Zary static void nexio_ack_complete(struct urb *urb) 7435197424cSOndrej Zary { 7445197424cSOndrej Zary } 7455197424cSOndrej Zary 746a8aef622SOliver Neukum static int nexio_alloc(struct usbtouch_usb *usbtouch) 747a8aef622SOliver Neukum { 748a8aef622SOliver Neukum struct nexio_priv *priv; 749a8aef622SOliver Neukum int ret = -ENOMEM; 750a8aef622SOliver Neukum 751a8aef622SOliver Neukum usbtouch->priv = kmalloc(sizeof(struct nexio_priv), GFP_KERNEL); 752a8aef622SOliver Neukum if (!usbtouch->priv) 753a8aef622SOliver Neukum goto out_buf; 754a8aef622SOliver Neukum 755a8aef622SOliver Neukum priv = usbtouch->priv; 756a8aef622SOliver Neukum 757a8aef622SOliver Neukum priv->ack_buf = kmemdup(nexio_ack_pkt, sizeof(nexio_ack_pkt), 758a8aef622SOliver Neukum GFP_KERNEL); 759a8aef622SOliver Neukum if (!priv->ack_buf) 760a8aef622SOliver Neukum goto err_priv; 761a8aef622SOliver Neukum 762a8aef622SOliver Neukum priv->ack = usb_alloc_urb(0, GFP_KERNEL); 763a8aef622SOliver Neukum if (!priv->ack) { 764a8aef622SOliver Neukum dbg("%s - usb_alloc_urb failed: usbtouch->ack", __func__); 765a8aef622SOliver Neukum goto err_ack_buf; 766a8aef622SOliver Neukum } 767a8aef622SOliver Neukum 768a8aef622SOliver Neukum return 0; 769a8aef622SOliver Neukum 770a8aef622SOliver Neukum err_ack_buf: 771a8aef622SOliver Neukum kfree(priv->ack_buf); 772a8aef622SOliver Neukum err_priv: 773a8aef622SOliver Neukum kfree(priv); 774a8aef622SOliver Neukum out_buf: 775a8aef622SOliver Neukum return ret; 776a8aef622SOliver Neukum } 777a8aef622SOliver Neukum 7785197424cSOndrej Zary static int nexio_init(struct usbtouch_usb *usbtouch) 7795197424cSOndrej Zary { 7805197424cSOndrej Zary struct usb_device *dev = interface_to_usbdev(usbtouch->interface); 7815197424cSOndrej Zary struct usb_host_interface *interface = usbtouch->interface->cur_altsetting; 782a8aef622SOliver Neukum struct nexio_priv *priv = usbtouch->priv; 7835197424cSOndrej Zary int ret = -ENOMEM; 7845197424cSOndrej Zary int actual_len, i; 7855197424cSOndrej Zary unsigned char *buf; 7865197424cSOndrej Zary char *firmware_ver = NULL, *device_name = NULL; 7875197424cSOndrej Zary int input_ep = 0, output_ep = 0; 7885197424cSOndrej Zary 7895197424cSOndrej Zary /* find first input and output endpoint */ 7905197424cSOndrej Zary for (i = 0; i < interface->desc.bNumEndpoints; i++) { 7915197424cSOndrej Zary if (!input_ep && 7925197424cSOndrej Zary usb_endpoint_dir_in(&interface->endpoint[i].desc)) 7935197424cSOndrej Zary input_ep = interface->endpoint[i].desc.bEndpointAddress; 7945197424cSOndrej Zary if (!output_ep && 7955197424cSOndrej Zary usb_endpoint_dir_out(&interface->endpoint[i].desc)) 7965197424cSOndrej Zary output_ep = interface->endpoint[i].desc.bEndpointAddress; 7975197424cSOndrej Zary } 7985197424cSOndrej Zary if (!input_ep || !output_ep) 7995197424cSOndrej Zary return -ENXIO; 8005197424cSOndrej Zary 801a8aef622SOliver Neukum buf = kmalloc(NEXIO_BUFSIZE, GFP_NOIO); 8025197424cSOndrej Zary if (!buf) 8035197424cSOndrej Zary goto out_buf; 8045197424cSOndrej Zary 8055197424cSOndrej Zary /* two empty reads */ 8065197424cSOndrej Zary for (i = 0; i < 2; i++) { 8075197424cSOndrej Zary ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep), 8085197424cSOndrej Zary buf, NEXIO_BUFSIZE, &actual_len, 8095197424cSOndrej Zary NEXIO_TIMEOUT); 8105197424cSOndrej Zary if (ret < 0) 8115197424cSOndrej Zary goto out_buf; 8125197424cSOndrej Zary } 8135197424cSOndrej Zary 8145197424cSOndrej Zary /* send init command */ 8155197424cSOndrej Zary memcpy(buf, nexio_init_pkt, sizeof(nexio_init_pkt)); 8165197424cSOndrej Zary ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, output_ep), 8175197424cSOndrej Zary buf, sizeof(nexio_init_pkt), &actual_len, 8185197424cSOndrej Zary NEXIO_TIMEOUT); 8195197424cSOndrej Zary if (ret < 0) 8205197424cSOndrej Zary goto out_buf; 8215197424cSOndrej Zary 8225197424cSOndrej Zary /* read replies */ 8235197424cSOndrej Zary for (i = 0; i < 3; i++) { 8245197424cSOndrej Zary memset(buf, 0, NEXIO_BUFSIZE); 8255197424cSOndrej Zary ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep), 8265197424cSOndrej Zary buf, NEXIO_BUFSIZE, &actual_len, 8275197424cSOndrej Zary NEXIO_TIMEOUT); 8285197424cSOndrej Zary if (ret < 0 || actual_len < 1 || buf[1] != actual_len) 8295197424cSOndrej Zary continue; 8305197424cSOndrej Zary switch (buf[0]) { 8315197424cSOndrej Zary case 0x83: /* firmware version */ 8325197424cSOndrej Zary if (!firmware_ver) 833a8aef622SOliver Neukum firmware_ver = kstrdup(&buf[2], GFP_NOIO); 8345197424cSOndrej Zary break; 8355197424cSOndrej Zary case 0x84: /* device name */ 8365197424cSOndrej Zary if (!device_name) 837a8aef622SOliver Neukum device_name = kstrdup(&buf[2], GFP_NOIO); 8385197424cSOndrej Zary break; 8395197424cSOndrej Zary } 8405197424cSOndrej Zary } 8415197424cSOndrej Zary 8425197424cSOndrej Zary printk(KERN_INFO "Nexio device: %s, firmware version: %s\n", 8435197424cSOndrej Zary device_name, firmware_ver); 8445197424cSOndrej Zary 8455197424cSOndrej Zary kfree(firmware_ver); 8465197424cSOndrej Zary kfree(device_name); 8475197424cSOndrej Zary 8485197424cSOndrej Zary usb_fill_bulk_urb(priv->ack, dev, usb_sndbulkpipe(dev, output_ep), 8495197424cSOndrej Zary priv->ack_buf, sizeof(nexio_ack_pkt), 8505197424cSOndrej Zary nexio_ack_complete, usbtouch); 8515197424cSOndrej Zary ret = 0; 8525197424cSOndrej Zary 8535197424cSOndrej Zary out_buf: 8545197424cSOndrej Zary kfree(buf); 8555197424cSOndrej Zary return ret; 8565197424cSOndrej Zary } 8575197424cSOndrej Zary 8585197424cSOndrej Zary static void nexio_exit(struct usbtouch_usb *usbtouch) 8595197424cSOndrej Zary { 8605197424cSOndrej Zary struct nexio_priv *priv = usbtouch->priv; 8615197424cSOndrej Zary 8625197424cSOndrej Zary usb_kill_urb(priv->ack); 8635197424cSOndrej Zary usb_free_urb(priv->ack); 8645197424cSOndrej Zary kfree(priv->ack_buf); 8655197424cSOndrej Zary kfree(priv); 8665197424cSOndrej Zary } 8675197424cSOndrej Zary 8685197424cSOndrej Zary static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) 8695197424cSOndrej Zary { 8705197424cSOndrej Zary struct nexio_touch_packet *packet = (void *) pkt; 8715197424cSOndrej Zary struct nexio_priv *priv = usbtouch->priv; 8724aa5bbecSDmitry Torokhov unsigned int data_len = be16_to_cpu(packet->data_len); 8734aa5bbecSDmitry Torokhov unsigned int x_len = be16_to_cpu(packet->x_len); 8744aa5bbecSDmitry Torokhov unsigned int y_len = be16_to_cpu(packet->y_len); 8754aa5bbecSDmitry Torokhov int x, y, begin_x, begin_y, end_x, end_y, w, h, ret; 8765197424cSOndrej Zary 8775197424cSOndrej Zary /* got touch data? */ 8785197424cSOndrej Zary if ((pkt[0] & 0xe0) != 0xe0) 8795197424cSOndrej Zary return 0; 8805197424cSOndrej Zary 8814aa5bbecSDmitry Torokhov if (data_len > 0xff) 8824aa5bbecSDmitry Torokhov data_len -= 0x100; 8834aa5bbecSDmitry Torokhov if (x_len > 0xff) 8844aa5bbecSDmitry Torokhov x_len -= 0x80; 885388bbcadSOndrej Zary 8865197424cSOndrej Zary /* send ACK */ 8875197424cSOndrej Zary ret = usb_submit_urb(priv->ack, GFP_ATOMIC); 8885197424cSOndrej Zary 8895197424cSOndrej Zary if (!usbtouch->type->max_xc) { 8904aa5bbecSDmitry Torokhov usbtouch->type->max_xc = 2 * x_len; 8914aa5bbecSDmitry Torokhov input_set_abs_params(usbtouch->input, ABS_X, 8924aa5bbecSDmitry Torokhov 0, usbtouch->type->max_xc, 0, 0); 8934aa5bbecSDmitry Torokhov usbtouch->type->max_yc = 2 * y_len; 8944aa5bbecSDmitry Torokhov input_set_abs_params(usbtouch->input, ABS_Y, 8954aa5bbecSDmitry Torokhov 0, usbtouch->type->max_yc, 0, 0); 8965197424cSOndrej Zary } 8975197424cSOndrej Zary /* 8985197424cSOndrej Zary * The device reports state of IR sensors on X and Y axes. 8995197424cSOndrej Zary * Each byte represents "darkness" percentage (0-100) of one element. 9005197424cSOndrej Zary * 17" touchscreen reports only 64 x 52 bytes so the resolution is low. 9015197424cSOndrej Zary * This also means that there's a limited multi-touch capability but 9025197424cSOndrej Zary * it's disabled (and untested) here as there's no X driver for that. 9035197424cSOndrej Zary */ 9045197424cSOndrej Zary begin_x = end_x = begin_y = end_y = -1; 9054aa5bbecSDmitry Torokhov for (x = 0; x < x_len; x++) { 9065197424cSOndrej Zary if (begin_x == -1 && packet->data[x] > NEXIO_THRESHOLD) { 9075197424cSOndrej Zary begin_x = x; 9085197424cSOndrej Zary continue; 9095197424cSOndrej Zary } 9105197424cSOndrej Zary if (end_x == -1 && begin_x != -1 && packet->data[x] < NEXIO_THRESHOLD) { 9115197424cSOndrej Zary end_x = x - 1; 9124aa5bbecSDmitry Torokhov for (y = x_len; y < data_len; y++) { 9135197424cSOndrej Zary if (begin_y == -1 && packet->data[y] > NEXIO_THRESHOLD) { 9144aa5bbecSDmitry Torokhov begin_y = y - x_len; 9155197424cSOndrej Zary continue; 9165197424cSOndrej Zary } 9175197424cSOndrej Zary if (end_y == -1 && 9185197424cSOndrej Zary begin_y != -1 && packet->data[y] < NEXIO_THRESHOLD) { 9194aa5bbecSDmitry Torokhov end_y = y - 1 - x_len; 9205197424cSOndrej Zary w = end_x - begin_x; 9215197424cSOndrej Zary h = end_y - begin_y; 9225197424cSOndrej Zary #if 0 9235197424cSOndrej Zary /* multi-touch */ 9245197424cSOndrej Zary input_report_abs(usbtouch->input, 9255197424cSOndrej Zary ABS_MT_TOUCH_MAJOR, max(w,h)); 9265197424cSOndrej Zary input_report_abs(usbtouch->input, 9275197424cSOndrej Zary ABS_MT_TOUCH_MINOR, min(x,h)); 9285197424cSOndrej Zary input_report_abs(usbtouch->input, 9295197424cSOndrej Zary ABS_MT_POSITION_X, 2*begin_x+w); 9305197424cSOndrej Zary input_report_abs(usbtouch->input, 9315197424cSOndrej Zary ABS_MT_POSITION_Y, 2*begin_y+h); 9325197424cSOndrej Zary input_report_abs(usbtouch->input, 9335197424cSOndrej Zary ABS_MT_ORIENTATION, w > h); 9345197424cSOndrej Zary input_mt_sync(usbtouch->input); 9355197424cSOndrej Zary #endif 9365197424cSOndrej Zary /* single touch */ 9375197424cSOndrej Zary usbtouch->x = 2 * begin_x + w; 9385197424cSOndrej Zary usbtouch->y = 2 * begin_y + h; 9395197424cSOndrej Zary usbtouch->touch = packet->flags & 0x01; 9405197424cSOndrej Zary begin_y = end_y = -1; 9415197424cSOndrej Zary return 1; 9425197424cSOndrej Zary } 9435197424cSOndrej Zary } 9445197424cSOndrej Zary begin_x = end_x = -1; 9455197424cSOndrej Zary } 9465197424cSOndrej Zary 9475197424cSOndrej Zary } 9485197424cSOndrej Zary return 0; 9495197424cSOndrej Zary } 9505197424cSOndrej Zary #endif 9515197424cSOndrej Zary 9525197424cSOndrej Zary 9535197424cSOndrej Zary /***************************************************************************** 954d2cc817aSMichael Gebetsroither * ELO part 955d2cc817aSMichael Gebetsroither */ 956d2cc817aSMichael Gebetsroither 957d2cc817aSMichael Gebetsroither #ifdef CONFIG_TOUCHSCREEN_USB_ELO 958d2cc817aSMichael Gebetsroither 959d2cc817aSMichael Gebetsroither static int elo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 960d2cc817aSMichael Gebetsroither { 961d2cc817aSMichael Gebetsroither dev->x = (pkt[3] << 8) | pkt[2]; 962d2cc817aSMichael Gebetsroither dev->y = (pkt[5] << 8) | pkt[4]; 963d2cc817aSMichael Gebetsroither dev->touch = pkt[6] > 0; 964d2cc817aSMichael Gebetsroither dev->press = pkt[6]; 965d2cc817aSMichael Gebetsroither 966d2cc817aSMichael Gebetsroither return 1; 967d2cc817aSMichael Gebetsroither } 968d2cc817aSMichael Gebetsroither #endif 969d2cc817aSMichael Gebetsroither 970d2cc817aSMichael Gebetsroither 971d2cc817aSMichael Gebetsroither /***************************************************************************** 972d05e84e6SDmitry Torokhov * the different device descriptors 973d05e84e6SDmitry Torokhov */ 97462aa366dSDaniel Ritz #ifdef MULTI_PACKET 97562aa366dSDaniel Ritz static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, 97662aa366dSDaniel Ritz unsigned char *pkt, int len); 97762aa366dSDaniel Ritz #endif 97862aa366dSDaniel Ritz 979d05e84e6SDmitry Torokhov static struct usbtouch_device_info usbtouch_dev_info[] = { 980d2cc817aSMichael Gebetsroither #ifdef CONFIG_TOUCHSCREEN_USB_ELO 981d2cc817aSMichael Gebetsroither [DEVTYPE_ELO] = { 982d2cc817aSMichael Gebetsroither .min_xc = 0x0, 983d2cc817aSMichael Gebetsroither .max_xc = 0x0fff, 984d2cc817aSMichael Gebetsroither .min_yc = 0x0, 985d2cc817aSMichael Gebetsroither .max_yc = 0x0fff, 986d2cc817aSMichael Gebetsroither .max_press = 0xff, 987d2cc817aSMichael Gebetsroither .rept_size = 8, 988d2cc817aSMichael Gebetsroither .read_data = elo_read_data, 989d2cc817aSMichael Gebetsroither }, 990d2cc817aSMichael Gebetsroither #endif 991d2cc817aSMichael Gebetsroither 992c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 993d05e84e6SDmitry Torokhov [DEVTYPE_EGALAX] = { 994d05e84e6SDmitry Torokhov .min_xc = 0x0, 995d05e84e6SDmitry Torokhov .max_xc = 0x07ff, 996d05e84e6SDmitry Torokhov .min_yc = 0x0, 997d05e84e6SDmitry Torokhov .max_yc = 0x07ff, 998d05e84e6SDmitry Torokhov .rept_size = 16, 999d05e84e6SDmitry Torokhov .process_pkt = usbtouch_process_multi, 1000d05e84e6SDmitry Torokhov .get_pkt_len = egalax_get_pkt_len, 1001d05e84e6SDmitry Torokhov .read_data = egalax_read_data, 1002d05e84e6SDmitry Torokhov }, 1003d05e84e6SDmitry Torokhov #endif 1004d05e84e6SDmitry Torokhov 1005c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 1006d05e84e6SDmitry Torokhov [DEVTYPE_PANJIT] = { 1007d05e84e6SDmitry Torokhov .min_xc = 0x0, 1008d05e84e6SDmitry Torokhov .max_xc = 0x0fff, 1009d05e84e6SDmitry Torokhov .min_yc = 0x0, 1010d05e84e6SDmitry Torokhov .max_yc = 0x0fff, 1011d05e84e6SDmitry Torokhov .rept_size = 8, 1012d05e84e6SDmitry Torokhov .read_data = panjit_read_data, 1013d05e84e6SDmitry Torokhov }, 1014d05e84e6SDmitry Torokhov #endif 1015d05e84e6SDmitry Torokhov 1016c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_3M 1017d05e84e6SDmitry Torokhov [DEVTYPE_3M] = { 1018d05e84e6SDmitry Torokhov .min_xc = 0x0, 1019d05e84e6SDmitry Torokhov .max_xc = 0x4000, 1020d05e84e6SDmitry Torokhov .min_yc = 0x0, 1021d05e84e6SDmitry Torokhov .max_yc = 0x4000, 1022d05e84e6SDmitry Torokhov .rept_size = 11, 1023d05e84e6SDmitry Torokhov .read_data = mtouch_read_data, 1024d05e84e6SDmitry Torokhov .init = mtouch_init, 1025d05e84e6SDmitry Torokhov }, 1026d05e84e6SDmitry Torokhov #endif 1027d05e84e6SDmitry Torokhov 1028c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ITM 1029d05e84e6SDmitry Torokhov [DEVTYPE_ITM] = { 1030d05e84e6SDmitry Torokhov .min_xc = 0x0, 1031d05e84e6SDmitry Torokhov .max_xc = 0x0fff, 1032d05e84e6SDmitry Torokhov .min_yc = 0x0, 1033d05e84e6SDmitry Torokhov .max_yc = 0x0fff, 1034d05e84e6SDmitry Torokhov .max_press = 0xff, 1035d05e84e6SDmitry Torokhov .rept_size = 8, 1036d05e84e6SDmitry Torokhov .read_data = itm_read_data, 1037d05e84e6SDmitry Torokhov }, 1038d05e84e6SDmitry Torokhov #endif 1039d05e84e6SDmitry Torokhov 1040c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 1041d05e84e6SDmitry Torokhov [DEVTYPE_ETURBO] = { 1042d05e84e6SDmitry Torokhov .min_xc = 0x0, 1043d05e84e6SDmitry Torokhov .max_xc = 0x07ff, 1044d05e84e6SDmitry Torokhov .min_yc = 0x0, 1045d05e84e6SDmitry Torokhov .max_yc = 0x07ff, 1046d05e84e6SDmitry Torokhov .rept_size = 8, 1047d05e84e6SDmitry Torokhov .process_pkt = usbtouch_process_multi, 1048d05e84e6SDmitry Torokhov .get_pkt_len = eturbo_get_pkt_len, 1049d05e84e6SDmitry Torokhov .read_data = eturbo_read_data, 1050d05e84e6SDmitry Torokhov }, 1051d05e84e6SDmitry Torokhov #endif 1052d05e84e6SDmitry Torokhov 1053c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_GUNZE 1054d05e84e6SDmitry Torokhov [DEVTYPE_GUNZE] = { 1055d05e84e6SDmitry Torokhov .min_xc = 0x0, 1056d05e84e6SDmitry Torokhov .max_xc = 0x0fff, 1057d05e84e6SDmitry Torokhov .min_yc = 0x0, 1058d05e84e6SDmitry Torokhov .max_yc = 0x0fff, 1059d05e84e6SDmitry Torokhov .rept_size = 4, 1060d05e84e6SDmitry Torokhov .read_data = gunze_read_data, 1061d05e84e6SDmitry Torokhov }, 1062d05e84e6SDmitry Torokhov #endif 1063d05e84e6SDmitry Torokhov 1064c6f8d706SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 1065d05e84e6SDmitry Torokhov [DEVTYPE_DMC_TSC10] = { 1066d05e84e6SDmitry Torokhov .min_xc = 0x0, 1067d05e84e6SDmitry Torokhov .max_xc = 0x03ff, 1068d05e84e6SDmitry Torokhov .min_yc = 0x0, 1069d05e84e6SDmitry Torokhov .max_yc = 0x03ff, 1070d05e84e6SDmitry Torokhov .rept_size = 5, 1071d05e84e6SDmitry Torokhov .init = dmc_tsc10_init, 1072d05e84e6SDmitry Torokhov .read_data = dmc_tsc10_read_data, 1073d05e84e6SDmitry Torokhov }, 1074d05e84e6SDmitry Torokhov #endif 1075df561fcdSOndrej Zary 1076df561fcdSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH 1077df561fcdSOndrej Zary [DEVTYPE_IRTOUCH] = { 1078df561fcdSOndrej Zary .min_xc = 0x0, 1079df561fcdSOndrej Zary .max_xc = 0x0fff, 1080df561fcdSOndrej Zary .min_yc = 0x0, 1081df561fcdSOndrej Zary .max_yc = 0x0fff, 1082df561fcdSOndrej Zary .rept_size = 8, 1083df561fcdSOndrej Zary .read_data = irtouch_read_data, 1084df561fcdSOndrej Zary }, 1085df561fcdSOndrej Zary #endif 1086a14a8401SOndrej Zary 1087a14a8401SOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 1088a14a8401SOndrej Zary [DEVTYPE_IDEALTEK] = { 1089a14a8401SOndrej Zary .min_xc = 0x0, 1090a14a8401SOndrej Zary .max_xc = 0x0fff, 1091a14a8401SOndrej Zary .min_yc = 0x0, 1092a14a8401SOndrej Zary .max_yc = 0x0fff, 1093a14a8401SOndrej Zary .rept_size = 8, 1094a14a8401SOndrej Zary .process_pkt = usbtouch_process_multi, 1095a14a8401SOndrej Zary .get_pkt_len = idealtek_get_pkt_len, 1096a14a8401SOndrej Zary .read_data = idealtek_read_data, 1097a14a8401SOndrej Zary }, 1098a14a8401SOndrej Zary #endif 10999d5657dbSIlya Frolov 11009d5657dbSIlya Frolov #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH 11019d5657dbSIlya Frolov [DEVTYPE_GENERAL_TOUCH] = { 11029d5657dbSIlya Frolov .min_xc = 0x0, 1103eb083ba2SRoy Yin .max_xc = 0x7fff, 11049d5657dbSIlya Frolov .min_yc = 0x0, 1105eb083ba2SRoy Yin .max_yc = 0x7fff, 11069d5657dbSIlya Frolov .rept_size = 7, 11079d5657dbSIlya Frolov .read_data = general_touch_read_data, 110814e40206SJerrold Jones }, 11099d5657dbSIlya Frolov #endif 11109d5657dbSIlya Frolov 111114e40206SJerrold Jones #ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 111214e40206SJerrold Jones [DEVTYPE_GOTOP] = { 111314e40206SJerrold Jones .min_xc = 0x0, 111414e40206SJerrold Jones .max_xc = 0x03ff, 111514e40206SJerrold Jones .min_yc = 0x0, 111614e40206SJerrold Jones .max_yc = 0x03ff, 111714e40206SJerrold Jones .rept_size = 4, 111814e40206SJerrold Jones .read_data = gotop_read_data, 111914e40206SJerrold Jones }, 112014e40206SJerrold Jones #endif 1121f7370699SJim Persson 1122f7370699SJim Persson #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC 1123f7370699SJim Persson [DEVTYPE_JASTEC] = { 1124f7370699SJim Persson .min_xc = 0x0, 1125f7370699SJim Persson .max_xc = 0x0fff, 1126f7370699SJim Persson .min_yc = 0x0, 1127f7370699SJim Persson .max_yc = 0x0fff, 1128f7370699SJim Persson .rept_size = 4, 1129f7370699SJim Persson .read_data = jastec_read_data, 1130f7370699SJim Persson }, 1131f7370699SJim Persson #endif 11329e3b2583SFlorian Echtler 11339e3b2583SFlorian Echtler #ifdef CONFIG_TOUCHSCREEN_USB_E2I 11349e3b2583SFlorian Echtler [DEVTYPE_E2I] = { 11359e3b2583SFlorian Echtler .min_xc = 0x0, 11369e3b2583SFlorian Echtler .max_xc = 0x7fff, 11379e3b2583SFlorian Echtler .min_yc = 0x0, 11389e3b2583SFlorian Echtler .max_yc = 0x7fff, 11399e3b2583SFlorian Echtler .rept_size = 6, 11409e3b2583SFlorian Echtler .init = e2i_init, 11419e3b2583SFlorian Echtler .read_data = e2i_read_data, 11429e3b2583SFlorian Echtler }, 11439e3b2583SFlorian Echtler #endif 11442330ed18SDaniel Silverstone 11452330ed18SDaniel Silverstone #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC 11462330ed18SDaniel Silverstone [DEVTYPE_ZYTRONIC] = { 11472330ed18SDaniel Silverstone .min_xc = 0x0, 11482330ed18SDaniel Silverstone .max_xc = 0x03ff, 11492330ed18SDaniel Silverstone .min_yc = 0x0, 11502330ed18SDaniel Silverstone .max_yc = 0x03ff, 11512330ed18SDaniel Silverstone .rept_size = 5, 11522330ed18SDaniel Silverstone .read_data = zytronic_read_data, 11532330ed18SDaniel Silverstone .irq_always = true, 11542330ed18SDaniel Silverstone }, 11552330ed18SDaniel Silverstone #endif 1156dbe1420bSPetr Štetiar 115738771bb4SPetr Štetiar #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB 115838771bb4SPetr Štetiar [DEVTYPE_TC45USB] = { 1159dbe1420bSPetr Štetiar .min_xc = 0x0, 1160dbe1420bSPetr Štetiar .max_xc = 0x0fff, 1161dbe1420bSPetr Štetiar .min_yc = 0x0, 1162dbe1420bSPetr Štetiar .max_yc = 0x0fff, 1163dbe1420bSPetr Štetiar .rept_size = 5, 116438771bb4SPetr Štetiar .read_data = tc45usb_read_data, 1165dbe1420bSPetr Štetiar }, 1166dbe1420bSPetr Štetiar #endif 11675197424cSOndrej Zary 11685197424cSOndrej Zary #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO 11695197424cSOndrej Zary [DEVTYPE_NEXIO] = { 1170388bbcadSOndrej Zary .rept_size = 1024, 11715197424cSOndrej Zary .irq_always = true, 11725197424cSOndrej Zary .read_data = nexio_read_data, 1173a8aef622SOliver Neukum .alloc = nexio_alloc, 11745197424cSOndrej Zary .init = nexio_init, 11755197424cSOndrej Zary .exit = nexio_exit, 11765197424cSOndrej Zary }, 11775197424cSOndrej Zary #endif 1178d05e84e6SDmitry Torokhov }; 1179d05e84e6SDmitry Torokhov 1180d05e84e6SDmitry Torokhov 1181d05e84e6SDmitry Torokhov /***************************************************************************** 1182d05e84e6SDmitry Torokhov * Generic Part 1183d05e84e6SDmitry Torokhov */ 1184d05e84e6SDmitry Torokhov static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, 1185d05e84e6SDmitry Torokhov unsigned char *pkt, int len) 1186d05e84e6SDmitry Torokhov { 1187d05e84e6SDmitry Torokhov struct usbtouch_device_info *type = usbtouch->type; 1188d05e84e6SDmitry Torokhov 1189d05e84e6SDmitry Torokhov if (!type->read_data(usbtouch, pkt)) 1190d05e84e6SDmitry Torokhov return; 1191d05e84e6SDmitry Torokhov 1192d05e84e6SDmitry Torokhov input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch); 1193d05e84e6SDmitry Torokhov 1194d05e84e6SDmitry Torokhov if (swap_xy) { 1195d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_X, usbtouch->y); 1196d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_Y, usbtouch->x); 1197d05e84e6SDmitry Torokhov } else { 1198d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_X, usbtouch->x); 1199d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_Y, usbtouch->y); 1200d05e84e6SDmitry Torokhov } 1201d05e84e6SDmitry Torokhov if (type->max_press) 1202d05e84e6SDmitry Torokhov input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press); 1203d05e84e6SDmitry Torokhov input_sync(usbtouch->input); 1204d05e84e6SDmitry Torokhov } 1205d05e84e6SDmitry Torokhov 1206d05e84e6SDmitry Torokhov 1207d05e84e6SDmitry Torokhov #ifdef MULTI_PACKET 1208d05e84e6SDmitry Torokhov static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, 1209d05e84e6SDmitry Torokhov unsigned char *pkt, int len) 1210d05e84e6SDmitry Torokhov { 1211d05e84e6SDmitry Torokhov unsigned char *buffer; 1212d05e84e6SDmitry Torokhov int pkt_len, pos, buf_len, tmp; 1213d05e84e6SDmitry Torokhov 1214d05e84e6SDmitry Torokhov /* process buffer */ 1215d05e84e6SDmitry Torokhov if (unlikely(usbtouch->buf_len)) { 1216d05e84e6SDmitry Torokhov /* try to get size */ 1217d05e84e6SDmitry Torokhov pkt_len = usbtouch->type->get_pkt_len( 1218d05e84e6SDmitry Torokhov usbtouch->buffer, usbtouch->buf_len); 1219d05e84e6SDmitry Torokhov 1220d05e84e6SDmitry Torokhov /* drop? */ 1221d05e84e6SDmitry Torokhov if (unlikely(!pkt_len)) 1222d05e84e6SDmitry Torokhov goto out_flush_buf; 1223d05e84e6SDmitry Torokhov 1224d05e84e6SDmitry Torokhov /* need to append -pkt_len bytes before able to get size */ 1225d05e84e6SDmitry Torokhov if (unlikely(pkt_len < 0)) { 1226d05e84e6SDmitry Torokhov int append = -pkt_len; 1227d05e84e6SDmitry Torokhov if (unlikely(append > len)) 1228d05e84e6SDmitry Torokhov append = len; 1229d05e84e6SDmitry Torokhov if (usbtouch->buf_len + append >= usbtouch->type->rept_size) 1230d05e84e6SDmitry Torokhov goto out_flush_buf; 1231d05e84e6SDmitry Torokhov memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append); 1232d05e84e6SDmitry Torokhov usbtouch->buf_len += append; 1233d05e84e6SDmitry Torokhov 1234d05e84e6SDmitry Torokhov pkt_len = usbtouch->type->get_pkt_len( 1235d05e84e6SDmitry Torokhov usbtouch->buffer, usbtouch->buf_len); 1236d05e84e6SDmitry Torokhov if (pkt_len < 0) 1237d05e84e6SDmitry Torokhov return; 1238d05e84e6SDmitry Torokhov } 1239d05e84e6SDmitry Torokhov 1240d05e84e6SDmitry Torokhov /* append */ 1241d05e84e6SDmitry Torokhov tmp = pkt_len - usbtouch->buf_len; 1242d05e84e6SDmitry Torokhov if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size) 1243d05e84e6SDmitry Torokhov goto out_flush_buf; 1244d05e84e6SDmitry Torokhov memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp); 1245d05e84e6SDmitry Torokhov usbtouch_process_pkt(usbtouch, usbtouch->buffer, pkt_len); 1246d05e84e6SDmitry Torokhov 1247d05e84e6SDmitry Torokhov buffer = pkt + tmp; 1248d05e84e6SDmitry Torokhov buf_len = len - tmp; 1249d05e84e6SDmitry Torokhov } else { 1250d05e84e6SDmitry Torokhov buffer = pkt; 1251d05e84e6SDmitry Torokhov buf_len = len; 1252d05e84e6SDmitry Torokhov } 1253d05e84e6SDmitry Torokhov 1254d05e84e6SDmitry Torokhov /* loop over the received packet, process */ 1255d05e84e6SDmitry Torokhov pos = 0; 1256d05e84e6SDmitry Torokhov while (pos < buf_len) { 1257d05e84e6SDmitry Torokhov /* get packet len */ 125862aa366dSDaniel Ritz pkt_len = usbtouch->type->get_pkt_len(buffer + pos, 125962aa366dSDaniel Ritz buf_len - pos); 1260d05e84e6SDmitry Torokhov 126162aa366dSDaniel Ritz /* unknown packet: skip one byte */ 126262aa366dSDaniel Ritz if (unlikely(!pkt_len)) { 126362aa366dSDaniel Ritz pos++; 126462aa366dSDaniel Ritz continue; 126562aa366dSDaniel Ritz } 1266d05e84e6SDmitry Torokhov 1267d05e84e6SDmitry Torokhov /* full packet: process */ 1268d05e84e6SDmitry Torokhov if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) { 1269d05e84e6SDmitry Torokhov usbtouch_process_pkt(usbtouch, buffer + pos, pkt_len); 1270d05e84e6SDmitry Torokhov } else { 1271d05e84e6SDmitry Torokhov /* incomplete packet: save in buffer */ 1272d05e84e6SDmitry Torokhov memcpy(usbtouch->buffer, buffer + pos, buf_len - pos); 1273d05e84e6SDmitry Torokhov usbtouch->buf_len = buf_len - pos; 1274d05e84e6SDmitry Torokhov return; 1275d05e84e6SDmitry Torokhov } 1276d05e84e6SDmitry Torokhov pos += pkt_len; 1277d05e84e6SDmitry Torokhov } 1278d05e84e6SDmitry Torokhov 1279d05e84e6SDmitry Torokhov out_flush_buf: 1280d05e84e6SDmitry Torokhov usbtouch->buf_len = 0; 1281d05e84e6SDmitry Torokhov return; 1282d05e84e6SDmitry Torokhov } 1283d05e84e6SDmitry Torokhov #endif 1284d05e84e6SDmitry Torokhov 1285d05e84e6SDmitry Torokhov 1286d05e84e6SDmitry Torokhov static void usbtouch_irq(struct urb *urb) 1287d05e84e6SDmitry Torokhov { 1288d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = urb->context; 1289d05e84e6SDmitry Torokhov int retval; 1290d05e84e6SDmitry Torokhov 1291d05e84e6SDmitry Torokhov switch (urb->status) { 1292d05e84e6SDmitry Torokhov case 0: 1293d05e84e6SDmitry Torokhov /* success */ 1294d05e84e6SDmitry Torokhov break; 1295d05e84e6SDmitry Torokhov case -ETIME: 1296d05e84e6SDmitry Torokhov /* this urb is timing out */ 1297d05e84e6SDmitry Torokhov dbg("%s - urb timed out - was the device unplugged?", 1298ea3e6c59SHarvey Harrison __func__); 1299d05e84e6SDmitry Torokhov return; 1300d05e84e6SDmitry Torokhov case -ECONNRESET: 1301d05e84e6SDmitry Torokhov case -ENOENT: 1302d05e84e6SDmitry Torokhov case -ESHUTDOWN: 13035197424cSOndrej Zary case -EPIPE: 1304d05e84e6SDmitry Torokhov /* this urb is terminated, clean up */ 1305d05e84e6SDmitry Torokhov dbg("%s - urb shutting down with status: %d", 1306ea3e6c59SHarvey Harrison __func__, urb->status); 1307d05e84e6SDmitry Torokhov return; 1308d05e84e6SDmitry Torokhov default: 1309d05e84e6SDmitry Torokhov dbg("%s - nonzero urb status received: %d", 1310ea3e6c59SHarvey Harrison __func__, urb->status); 1311d05e84e6SDmitry Torokhov goto exit; 1312d05e84e6SDmitry Torokhov } 1313d05e84e6SDmitry Torokhov 1314d05e84e6SDmitry Torokhov usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length); 1315d05e84e6SDmitry Torokhov 1316d05e84e6SDmitry Torokhov exit: 13175d9efc59SOliver Neukum usb_mark_last_busy(interface_to_usbdev(usbtouch->interface)); 1318d05e84e6SDmitry Torokhov retval = usb_submit_urb(urb, GFP_ATOMIC); 1319d05e84e6SDmitry Torokhov if (retval) 1320d05e84e6SDmitry Torokhov err("%s - usb_submit_urb failed with result: %d", 1321ea3e6c59SHarvey Harrison __func__, retval); 1322d05e84e6SDmitry Torokhov } 1323d05e84e6SDmitry Torokhov 1324d05e84e6SDmitry Torokhov static int usbtouch_open(struct input_dev *input) 1325d05e84e6SDmitry Torokhov { 1326d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = input_get_drvdata(input); 13275d9efc59SOliver Neukum int r; 1328d05e84e6SDmitry Torokhov 1329fea4d14bSOndrej Zary usbtouch->irq->dev = interface_to_usbdev(usbtouch->interface); 1330d05e84e6SDmitry Torokhov 13315d9efc59SOliver Neukum r = usb_autopm_get_interface(usbtouch->interface) ? -EIO : 0; 13325d9efc59SOliver Neukum if (r < 0) 13335d9efc59SOliver Neukum goto out; 13345d9efc59SOliver Neukum 13352330ed18SDaniel Silverstone if (!usbtouch->type->irq_always) { 13365d9efc59SOliver Neukum if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) { 13375d9efc59SOliver Neukum r = -EIO; 13385d9efc59SOliver Neukum goto out_put; 13395d9efc59SOliver Neukum } 13402330ed18SDaniel Silverstone } 1341d05e84e6SDmitry Torokhov 13425d9efc59SOliver Neukum usbtouch->interface->needs_remote_wakeup = 1; 13435d9efc59SOliver Neukum out_put: 13445d9efc59SOliver Neukum usb_autopm_put_interface(usbtouch->interface); 13455d9efc59SOliver Neukum out: 13465d9efc59SOliver Neukum return r; 1347d05e84e6SDmitry Torokhov } 1348d05e84e6SDmitry Torokhov 1349d05e84e6SDmitry Torokhov static void usbtouch_close(struct input_dev *input) 1350d05e84e6SDmitry Torokhov { 1351d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = input_get_drvdata(input); 13525d9efc59SOliver Neukum int r; 1353d05e84e6SDmitry Torokhov 13542330ed18SDaniel Silverstone if (!usbtouch->type->irq_always) 1355d05e84e6SDmitry Torokhov usb_kill_urb(usbtouch->irq); 13565d9efc59SOliver Neukum r = usb_autopm_get_interface(usbtouch->interface); 13575d9efc59SOliver Neukum usbtouch->interface->needs_remote_wakeup = 0; 13585d9efc59SOliver Neukum if (!r) 13595d9efc59SOliver Neukum usb_autopm_put_interface(usbtouch->interface); 1360d05e84e6SDmitry Torokhov } 1361d05e84e6SDmitry Torokhov 1362ed4299e1SOliver Neukum static int usbtouch_suspend 1363ed4299e1SOliver Neukum (struct usb_interface *intf, pm_message_t message) 1364ed4299e1SOliver Neukum { 1365ed4299e1SOliver Neukum struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 1366ed4299e1SOliver Neukum 1367ed4299e1SOliver Neukum usb_kill_urb(usbtouch->irq); 1368ed4299e1SOliver Neukum 1369ed4299e1SOliver Neukum return 0; 1370ed4299e1SOliver Neukum } 1371ed4299e1SOliver Neukum 1372ed4299e1SOliver Neukum static int usbtouch_resume(struct usb_interface *intf) 1373ed4299e1SOliver Neukum { 1374ed4299e1SOliver Neukum struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 1375ed4299e1SOliver Neukum struct input_dev *input = usbtouch->input; 1376ed4299e1SOliver Neukum int result = 0; 1377ed4299e1SOliver Neukum 1378ed4299e1SOliver Neukum mutex_lock(&input->mutex); 1379ed4299e1SOliver Neukum if (input->users || usbtouch->type->irq_always) 1380ed4299e1SOliver Neukum result = usb_submit_urb(usbtouch->irq, GFP_NOIO); 1381ed4299e1SOliver Neukum mutex_unlock(&input->mutex); 1382ed4299e1SOliver Neukum 1383ed4299e1SOliver Neukum return result; 1384ed4299e1SOliver Neukum } 1385d05e84e6SDmitry Torokhov 1386a8aef622SOliver Neukum static int usbtouch_reset_resume(struct usb_interface *intf) 1387a8aef622SOliver Neukum { 1388a8aef622SOliver Neukum struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 1389a8aef622SOliver Neukum struct input_dev *input = usbtouch->input; 1390a8aef622SOliver Neukum int err = 0; 1391a8aef622SOliver Neukum 1392a8aef622SOliver Neukum /* reinit the device */ 1393a8aef622SOliver Neukum if (usbtouch->type->init) { 1394a8aef622SOliver Neukum err = usbtouch->type->init(usbtouch); 1395a8aef622SOliver Neukum if (err) { 1396a8aef622SOliver Neukum dbg("%s - type->init() failed, err: %d", 1397a8aef622SOliver Neukum __func__, err); 1398a8aef622SOliver Neukum return err; 1399a8aef622SOliver Neukum } 1400a8aef622SOliver Neukum } 1401a8aef622SOliver Neukum 1402a8aef622SOliver Neukum /* restart IO if needed */ 1403a8aef622SOliver Neukum mutex_lock(&input->mutex); 1404a8aef622SOliver Neukum if (input->users) 1405a8aef622SOliver Neukum err = usb_submit_urb(usbtouch->irq, GFP_NOIO); 1406a8aef622SOliver Neukum mutex_unlock(&input->mutex); 1407a8aef622SOliver Neukum 1408a8aef622SOliver Neukum return err; 1409a8aef622SOliver Neukum } 1410a8aef622SOliver Neukum 1411d05e84e6SDmitry Torokhov static void usbtouch_free_buffers(struct usb_device *udev, 1412d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch) 1413d05e84e6SDmitry Torokhov { 1414997ea58eSDaniel Mack usb_free_coherent(udev, usbtouch->type->rept_size, 1415d05e84e6SDmitry Torokhov usbtouch->data, usbtouch->data_dma); 1416d05e84e6SDmitry Torokhov kfree(usbtouch->buffer); 1417d05e84e6SDmitry Torokhov } 1418d05e84e6SDmitry Torokhov 1419f4a5e359SOndrej Zary static struct usb_endpoint_descriptor * 1420f4a5e359SOndrej Zary usbtouch_get_input_endpoint(struct usb_host_interface *interface) 1421f4a5e359SOndrej Zary { 1422f4a5e359SOndrej Zary int i; 1423f4a5e359SOndrej Zary 1424f4a5e359SOndrej Zary for (i = 0; i < interface->desc.bNumEndpoints; i++) 1425f4a5e359SOndrej Zary if (usb_endpoint_dir_in(&interface->endpoint[i].desc)) 1426f4a5e359SOndrej Zary return &interface->endpoint[i].desc; 1427f4a5e359SOndrej Zary 1428f4a5e359SOndrej Zary return NULL; 1429f4a5e359SOndrej Zary } 1430d05e84e6SDmitry Torokhov 1431d05e84e6SDmitry Torokhov static int usbtouch_probe(struct usb_interface *intf, 1432d05e84e6SDmitry Torokhov const struct usb_device_id *id) 1433d05e84e6SDmitry Torokhov { 1434d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch; 1435d05e84e6SDmitry Torokhov struct input_dev *input_dev; 1436d05e84e6SDmitry Torokhov struct usb_endpoint_descriptor *endpoint; 1437d05e84e6SDmitry Torokhov struct usb_device *udev = interface_to_usbdev(intf); 1438d05e84e6SDmitry Torokhov struct usbtouch_device_info *type; 1439d05e84e6SDmitry Torokhov int err = -ENOMEM; 1440d05e84e6SDmitry Torokhov 1441ec42d448SDaniel Ritz /* some devices are ignored */ 1442ec42d448SDaniel Ritz if (id->driver_info == DEVTYPE_IGNORE) 1443ec42d448SDaniel Ritz return -ENODEV; 1444ec42d448SDaniel Ritz 1445f4a5e359SOndrej Zary endpoint = usbtouch_get_input_endpoint(intf->cur_altsetting); 1446f4a5e359SOndrej Zary if (!endpoint) 1447f4a5e359SOndrej Zary return -ENXIO; 1448d05e84e6SDmitry Torokhov 1449d05e84e6SDmitry Torokhov usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL); 1450d05e84e6SDmitry Torokhov input_dev = input_allocate_device(); 1451d05e84e6SDmitry Torokhov if (!usbtouch || !input_dev) 1452d05e84e6SDmitry Torokhov goto out_free; 1453d05e84e6SDmitry Torokhov 1454d05e84e6SDmitry Torokhov type = &usbtouch_dev_info[id->driver_info]; 1455d05e84e6SDmitry Torokhov usbtouch->type = type; 1456d05e84e6SDmitry Torokhov if (!type->process_pkt) 1457d05e84e6SDmitry Torokhov type->process_pkt = usbtouch_process_pkt; 1458d05e84e6SDmitry Torokhov 1459997ea58eSDaniel Mack usbtouch->data = usb_alloc_coherent(udev, type->rept_size, 1460d05e84e6SDmitry Torokhov GFP_KERNEL, &usbtouch->data_dma); 1461d05e84e6SDmitry Torokhov if (!usbtouch->data) 1462d05e84e6SDmitry Torokhov goto out_free; 1463d05e84e6SDmitry Torokhov 146462aa366dSDaniel Ritz if (type->get_pkt_len) { 1465d05e84e6SDmitry Torokhov usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL); 1466d05e84e6SDmitry Torokhov if (!usbtouch->buffer) 1467d05e84e6SDmitry Torokhov goto out_free_buffers; 1468d05e84e6SDmitry Torokhov } 1469d05e84e6SDmitry Torokhov 1470d05e84e6SDmitry Torokhov usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL); 1471d05e84e6SDmitry Torokhov if (!usbtouch->irq) { 1472ea3e6c59SHarvey Harrison dbg("%s - usb_alloc_urb failed: usbtouch->irq", __func__); 1473d05e84e6SDmitry Torokhov goto out_free_buffers; 1474d05e84e6SDmitry Torokhov } 1475d05e84e6SDmitry Torokhov 1476fea4d14bSOndrej Zary usbtouch->interface = intf; 1477d05e84e6SDmitry Torokhov usbtouch->input = input_dev; 1478d05e84e6SDmitry Torokhov 1479d05e84e6SDmitry Torokhov if (udev->manufacturer) 1480d05e84e6SDmitry Torokhov strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name)); 1481d05e84e6SDmitry Torokhov 1482d05e84e6SDmitry Torokhov if (udev->product) { 1483d05e84e6SDmitry Torokhov if (udev->manufacturer) 1484d05e84e6SDmitry Torokhov strlcat(usbtouch->name, " ", sizeof(usbtouch->name)); 1485d05e84e6SDmitry Torokhov strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name)); 1486d05e84e6SDmitry Torokhov } 1487d05e84e6SDmitry Torokhov 1488d05e84e6SDmitry Torokhov if (!strlen(usbtouch->name)) 1489d05e84e6SDmitry Torokhov snprintf(usbtouch->name, sizeof(usbtouch->name), 1490d05e84e6SDmitry Torokhov "USB Touchscreen %04x:%04x", 1491d05e84e6SDmitry Torokhov le16_to_cpu(udev->descriptor.idVendor), 1492d05e84e6SDmitry Torokhov le16_to_cpu(udev->descriptor.idProduct)); 1493d05e84e6SDmitry Torokhov 1494d05e84e6SDmitry Torokhov usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys)); 14957b6dff98SVladimir Shebordaev strlcat(usbtouch->phys, "/input0", sizeof(usbtouch->phys)); 1496d05e84e6SDmitry Torokhov 1497d05e84e6SDmitry Torokhov input_dev->name = usbtouch->name; 1498d05e84e6SDmitry Torokhov input_dev->phys = usbtouch->phys; 1499d05e84e6SDmitry Torokhov usb_to_input_id(udev, &input_dev->id); 1500d05e84e6SDmitry Torokhov input_dev->dev.parent = &intf->dev; 1501d05e84e6SDmitry Torokhov 1502d05e84e6SDmitry Torokhov input_set_drvdata(input_dev, usbtouch); 1503d05e84e6SDmitry Torokhov 1504d05e84e6SDmitry Torokhov input_dev->open = usbtouch_open; 1505d05e84e6SDmitry Torokhov input_dev->close = usbtouch_close; 1506d05e84e6SDmitry Torokhov 15077b19ada2SJiri Slaby input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 15087b19ada2SJiri Slaby input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 1509d05e84e6SDmitry Torokhov input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0); 1510d05e84e6SDmitry Torokhov input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0); 1511d05e84e6SDmitry Torokhov if (type->max_press) 1512d05e84e6SDmitry Torokhov input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press, 1513d05e84e6SDmitry Torokhov type->max_press, 0, 0); 1514d05e84e6SDmitry Torokhov 15155197424cSOndrej Zary if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT) 1516fea4d14bSOndrej Zary usb_fill_int_urb(usbtouch->irq, udev, 1517fea4d14bSOndrej Zary usb_rcvintpipe(udev, endpoint->bEndpointAddress), 1518d05e84e6SDmitry Torokhov usbtouch->data, type->rept_size, 1519d05e84e6SDmitry Torokhov usbtouch_irq, usbtouch, endpoint->bInterval); 15205197424cSOndrej Zary else 15215197424cSOndrej Zary usb_fill_bulk_urb(usbtouch->irq, udev, 15225197424cSOndrej Zary usb_rcvbulkpipe(udev, endpoint->bEndpointAddress), 15235197424cSOndrej Zary usbtouch->data, type->rept_size, 15245197424cSOndrej Zary usbtouch_irq, usbtouch); 1525d05e84e6SDmitry Torokhov 1526fea4d14bSOndrej Zary usbtouch->irq->dev = udev; 1527d05e84e6SDmitry Torokhov usbtouch->irq->transfer_dma = usbtouch->data_dma; 1528d05e84e6SDmitry Torokhov usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 1529d05e84e6SDmitry Torokhov 1530a8aef622SOliver Neukum /* device specific allocations */ 1531a8aef622SOliver Neukum if (type->alloc) { 1532a8aef622SOliver Neukum err = type->alloc(usbtouch); 1533a8aef622SOliver Neukum if (err) { 1534a8aef622SOliver Neukum dbg("%s - type->alloc() failed, err: %d", __func__, err); 1535a8aef622SOliver Neukum goto out_free_urb; 1536a8aef622SOliver Neukum } 1537a8aef622SOliver Neukum } 1538a8aef622SOliver Neukum 1539a8aef622SOliver Neukum /* device specific initialisation*/ 1540d05e84e6SDmitry Torokhov if (type->init) { 1541d05e84e6SDmitry Torokhov err = type->init(usbtouch); 1542d05e84e6SDmitry Torokhov if (err) { 1543ea3e6c59SHarvey Harrison dbg("%s - type->init() failed, err: %d", __func__, err); 1544a8aef622SOliver Neukum goto out_do_exit; 1545d05e84e6SDmitry Torokhov } 1546d05e84e6SDmitry Torokhov } 1547d05e84e6SDmitry Torokhov 1548d05e84e6SDmitry Torokhov err = input_register_device(usbtouch->input); 1549d05e84e6SDmitry Torokhov if (err) { 1550ea3e6c59SHarvey Harrison dbg("%s - input_register_device failed, err: %d", __func__, err); 15515197424cSOndrej Zary goto out_do_exit; 1552d05e84e6SDmitry Torokhov } 1553d05e84e6SDmitry Torokhov 1554d05e84e6SDmitry Torokhov usb_set_intfdata(intf, usbtouch); 1555d05e84e6SDmitry Torokhov 15561e87a430SOndrej Zary if (usbtouch->type->irq_always) { 15575d9efc59SOliver Neukum /* this can't fail */ 15585d9efc59SOliver Neukum usb_autopm_get_interface(intf); 15591e87a430SOndrej Zary err = usb_submit_urb(usbtouch->irq, GFP_KERNEL); 15601e87a430SOndrej Zary if (err) { 15615d9efc59SOliver Neukum usb_autopm_put_interface(intf); 15621e87a430SOndrej Zary err("%s - usb_submit_urb failed with result: %d", 15631e87a430SOndrej Zary __func__, err); 15641e87a430SOndrej Zary goto out_unregister_input; 15651e87a430SOndrej Zary } 15661e87a430SOndrej Zary } 15672330ed18SDaniel Silverstone 1568d05e84e6SDmitry Torokhov return 0; 1569d05e84e6SDmitry Torokhov 15701e87a430SOndrej Zary out_unregister_input: 15711e87a430SOndrej Zary input_unregister_device(input_dev); 15721e87a430SOndrej Zary input_dev = NULL; 15735197424cSOndrej Zary out_do_exit: 15745197424cSOndrej Zary if (type->exit) 15755197424cSOndrej Zary type->exit(usbtouch); 15761e87a430SOndrej Zary out_free_urb: 15771e87a430SOndrej Zary usb_free_urb(usbtouch->irq); 1578d05e84e6SDmitry Torokhov out_free_buffers: 1579d05e84e6SDmitry Torokhov usbtouch_free_buffers(udev, usbtouch); 1580d05e84e6SDmitry Torokhov out_free: 1581d05e84e6SDmitry Torokhov input_free_device(input_dev); 1582d05e84e6SDmitry Torokhov kfree(usbtouch); 1583d05e84e6SDmitry Torokhov return err; 1584d05e84e6SDmitry Torokhov } 1585d05e84e6SDmitry Torokhov 1586d05e84e6SDmitry Torokhov static void usbtouch_disconnect(struct usb_interface *intf) 1587d05e84e6SDmitry Torokhov { 1588d05e84e6SDmitry Torokhov struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 1589d05e84e6SDmitry Torokhov 1590ea3e6c59SHarvey Harrison dbg("%s - called", __func__); 1591d05e84e6SDmitry Torokhov 1592d05e84e6SDmitry Torokhov if (!usbtouch) 1593d05e84e6SDmitry Torokhov return; 1594d05e84e6SDmitry Torokhov 1595ea3e6c59SHarvey Harrison dbg("%s - usbtouch is initialized, cleaning up", __func__); 1596d05e84e6SDmitry Torokhov usb_set_intfdata(intf, NULL); 1597722232bcSOliver Neukum /* this will stop IO via close */ 1598d05e84e6SDmitry Torokhov input_unregister_device(usbtouch->input); 1599d05e84e6SDmitry Torokhov usb_free_urb(usbtouch->irq); 16005197424cSOndrej Zary if (usbtouch->type->exit) 16015197424cSOndrej Zary usbtouch->type->exit(usbtouch); 1602d05e84e6SDmitry Torokhov usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); 1603d05e84e6SDmitry Torokhov kfree(usbtouch); 1604d05e84e6SDmitry Torokhov } 1605d05e84e6SDmitry Torokhov 1606d05e84e6SDmitry Torokhov MODULE_DEVICE_TABLE(usb, usbtouch_devices); 1607d05e84e6SDmitry Torokhov 1608d05e84e6SDmitry Torokhov static struct usb_driver usbtouch_driver = { 1609d05e84e6SDmitry Torokhov .name = "usbtouchscreen", 1610d05e84e6SDmitry Torokhov .probe = usbtouch_probe, 1611d05e84e6SDmitry Torokhov .disconnect = usbtouch_disconnect, 1612ed4299e1SOliver Neukum .suspend = usbtouch_suspend, 1613ed4299e1SOliver Neukum .resume = usbtouch_resume, 1614a8aef622SOliver Neukum .reset_resume = usbtouch_reset_resume, 1615d05e84e6SDmitry Torokhov .id_table = usbtouch_devices, 16165d9efc59SOliver Neukum .supports_autosuspend = 1, 1617d05e84e6SDmitry Torokhov }; 1618d05e84e6SDmitry Torokhov 161908642e7cSGreg Kroah-Hartman module_usb_driver(usbtouch_driver); 1620d05e84e6SDmitry Torokhov 1621d05e84e6SDmitry Torokhov MODULE_AUTHOR(DRIVER_AUTHOR); 1622d05e84e6SDmitry Torokhov MODULE_DESCRIPTION(DRIVER_DESC); 1623d05e84e6SDmitry Torokhov MODULE_LICENSE("GPL"); 1624d05e84e6SDmitry Torokhov 1625d05e84e6SDmitry Torokhov MODULE_ALIAS("touchkitusb"); 1626d05e84e6SDmitry Torokhov MODULE_ALIAS("itmtouch"); 1627d05e84e6SDmitry Torokhov MODULE_ALIAS("mtouchusb"); 1628