18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/****************************************************************************** 38c2ecf20Sopenharmony_ci * usbtouchscreen.c 48c2ecf20Sopenharmony_ci * Driver for USB Touchscreens, supporting those devices: 58c2ecf20Sopenharmony_ci * - eGalax Touchkit 68c2ecf20Sopenharmony_ci * includes eTurboTouch CT-410/510/700 78c2ecf20Sopenharmony_ci * - 3M/Microtouch EX II series 88c2ecf20Sopenharmony_ci * - ITM 98c2ecf20Sopenharmony_ci * - PanJit TouchSet 108c2ecf20Sopenharmony_ci * - eTurboTouch 118c2ecf20Sopenharmony_ci * - Gunze AHL61 128c2ecf20Sopenharmony_ci * - DMC TSC-10/25 138c2ecf20Sopenharmony_ci * - IRTOUCHSYSTEMS/UNITOP 148c2ecf20Sopenharmony_ci * - IdealTEK URTC1000 158c2ecf20Sopenharmony_ci * - General Touch 168c2ecf20Sopenharmony_ci * - GoTop Super_Q2/GogoPen/PenPower tablets 178c2ecf20Sopenharmony_ci * - JASTEC USB touch controller/DigiTech DTR-02U 188c2ecf20Sopenharmony_ci * - Zytronic capacitive touchscreen 198c2ecf20Sopenharmony_ci * - NEXIO/iNexio 208c2ecf20Sopenharmony_ci * - Elo TouchSystems 2700 IntelliTouch 218c2ecf20Sopenharmony_ci * - EasyTouch USB Dual/Multi touch controller from Data Modul 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> 248c2ecf20Sopenharmony_ci * Copyright (C) by Todd E. Johnson (mtouchusb.c) 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * Driver is based on touchkitusb.c 278c2ecf20Sopenharmony_ci * - ITM parts are from itmtouch.c 288c2ecf20Sopenharmony_ci * - 3M parts are from mtouchusb.c 298c2ecf20Sopenharmony_ci * - PanJit parts are from an unmerged driver by Lanslott Gish 308c2ecf20Sopenharmony_ci * - DMC TSC 10/25 are from Holger Schurig, with ideas from an unmerged 318c2ecf20Sopenharmony_ci * driver from Marius Vollmer 328c2ecf20Sopenharmony_ci * 338c2ecf20Sopenharmony_ci *****************************************************************************/ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci//#define DEBUG 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#include <linux/kernel.h> 388c2ecf20Sopenharmony_ci#include <linux/slab.h> 398c2ecf20Sopenharmony_ci#include <linux/input.h> 408c2ecf20Sopenharmony_ci#include <linux/module.h> 418c2ecf20Sopenharmony_ci#include <linux/usb.h> 428c2ecf20Sopenharmony_ci#include <linux/usb/input.h> 438c2ecf20Sopenharmony_ci#include <linux/hid.h> 448c2ecf20Sopenharmony_ci#include <linux/mutex.h> 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic bool swap_xy; 478c2ecf20Sopenharmony_cimodule_param(swap_xy, bool, 0644); 488c2ecf20Sopenharmony_ciMODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic bool hwcalib_xy; 518c2ecf20Sopenharmony_cimodule_param(hwcalib_xy, bool, 0644); 528c2ecf20Sopenharmony_ciMODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available"); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci/* device specifc data/functions */ 558c2ecf20Sopenharmony_cistruct usbtouch_usb; 568c2ecf20Sopenharmony_cistruct usbtouch_device_info { 578c2ecf20Sopenharmony_ci int min_xc, max_xc; 588c2ecf20Sopenharmony_ci int min_yc, max_yc; 598c2ecf20Sopenharmony_ci int min_press, max_press; 608c2ecf20Sopenharmony_ci int rept_size; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci /* 638c2ecf20Sopenharmony_ci * Always service the USB devices irq not just when the input device is 648c2ecf20Sopenharmony_ci * open. This is useful when devices have a watchdog which prevents us 658c2ecf20Sopenharmony_ci * from periodically polling the device. Leave this unset unless your 668c2ecf20Sopenharmony_ci * touchscreen device requires it, as it does consume more of the USB 678c2ecf20Sopenharmony_ci * bandwidth. 688c2ecf20Sopenharmony_ci */ 698c2ecf20Sopenharmony_ci bool irq_always; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci /* 748c2ecf20Sopenharmony_ci * used to get the packet len. possible return values: 758c2ecf20Sopenharmony_ci * > 0: packet len 768c2ecf20Sopenharmony_ci * = 0: skip one byte 778c2ecf20Sopenharmony_ci * < 0: -return value more bytes needed 788c2ecf20Sopenharmony_ci */ 798c2ecf20Sopenharmony_ci int (*get_pkt_len) (unsigned char *pkt, int len); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt); 828c2ecf20Sopenharmony_ci int (*alloc) (struct usbtouch_usb *usbtouch); 838c2ecf20Sopenharmony_ci int (*init) (struct usbtouch_usb *usbtouch); 848c2ecf20Sopenharmony_ci void (*exit) (struct usbtouch_usb *usbtouch); 858c2ecf20Sopenharmony_ci}; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci/* a usbtouch device */ 888c2ecf20Sopenharmony_cistruct usbtouch_usb { 898c2ecf20Sopenharmony_ci unsigned char *data; 908c2ecf20Sopenharmony_ci dma_addr_t data_dma; 918c2ecf20Sopenharmony_ci int data_size; 928c2ecf20Sopenharmony_ci unsigned char *buffer; 938c2ecf20Sopenharmony_ci int buf_len; 948c2ecf20Sopenharmony_ci struct urb *irq; 958c2ecf20Sopenharmony_ci struct usb_interface *interface; 968c2ecf20Sopenharmony_ci struct input_dev *input; 978c2ecf20Sopenharmony_ci struct usbtouch_device_info *type; 988c2ecf20Sopenharmony_ci struct mutex pm_mutex; /* serialize access to open/suspend */ 998c2ecf20Sopenharmony_ci bool is_open; 1008c2ecf20Sopenharmony_ci char name[128]; 1018c2ecf20Sopenharmony_ci char phys[64]; 1028c2ecf20Sopenharmony_ci void *priv; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci int x, y; 1058c2ecf20Sopenharmony_ci int touch, press; 1068c2ecf20Sopenharmony_ci}; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci/* device types */ 1108c2ecf20Sopenharmony_cienum { 1118c2ecf20Sopenharmony_ci DEVTYPE_IGNORE = -1, 1128c2ecf20Sopenharmony_ci DEVTYPE_EGALAX, 1138c2ecf20Sopenharmony_ci DEVTYPE_PANJIT, 1148c2ecf20Sopenharmony_ci DEVTYPE_3M, 1158c2ecf20Sopenharmony_ci DEVTYPE_ITM, 1168c2ecf20Sopenharmony_ci DEVTYPE_ETURBO, 1178c2ecf20Sopenharmony_ci DEVTYPE_GUNZE, 1188c2ecf20Sopenharmony_ci DEVTYPE_DMC_TSC10, 1198c2ecf20Sopenharmony_ci DEVTYPE_IRTOUCH, 1208c2ecf20Sopenharmony_ci DEVTYPE_IRTOUCH_HIRES, 1218c2ecf20Sopenharmony_ci DEVTYPE_IDEALTEK, 1228c2ecf20Sopenharmony_ci DEVTYPE_GENERAL_TOUCH, 1238c2ecf20Sopenharmony_ci DEVTYPE_GOTOP, 1248c2ecf20Sopenharmony_ci DEVTYPE_JASTEC, 1258c2ecf20Sopenharmony_ci DEVTYPE_E2I, 1268c2ecf20Sopenharmony_ci DEVTYPE_ZYTRONIC, 1278c2ecf20Sopenharmony_ci DEVTYPE_TC45USB, 1288c2ecf20Sopenharmony_ci DEVTYPE_NEXIO, 1298c2ecf20Sopenharmony_ci DEVTYPE_ELO, 1308c2ecf20Sopenharmony_ci DEVTYPE_ETOUCH, 1318c2ecf20Sopenharmony_ci}; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci#define USB_DEVICE_HID_CLASS(vend, prod) \ 1348c2ecf20Sopenharmony_ci .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \ 1358c2ecf20Sopenharmony_ci | USB_DEVICE_ID_MATCH_DEVICE, \ 1368c2ecf20Sopenharmony_ci .idVendor = (vend), \ 1378c2ecf20Sopenharmony_ci .idProduct = (prod), \ 1388c2ecf20Sopenharmony_ci .bInterfaceClass = USB_INTERFACE_CLASS_HID 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic const struct usb_device_id usbtouch_devices[] = { 1418c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 1428c2ecf20Sopenharmony_ci /* ignore the HID capable devices, handled by usbhid */ 1438c2ecf20Sopenharmony_ci {USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE}, 1448c2ecf20Sopenharmony_ci {USB_DEVICE_HID_CLASS(0x0eef, 0x0002), .driver_info = DEVTYPE_IGNORE}, 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci /* normal device IDs */ 1478c2ecf20Sopenharmony_ci {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX}, 1488c2ecf20Sopenharmony_ci {USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX}, 1498c2ecf20Sopenharmony_ci {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX}, 1508c2ecf20Sopenharmony_ci {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX}, 1518c2ecf20Sopenharmony_ci {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX}, 1528c2ecf20Sopenharmony_ci {USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX}, 1538c2ecf20Sopenharmony_ci {USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX}, 1548c2ecf20Sopenharmony_ci#endif 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 1578c2ecf20Sopenharmony_ci {USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT}, 1588c2ecf20Sopenharmony_ci {USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT}, 1598c2ecf20Sopenharmony_ci {USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT}, 1608c2ecf20Sopenharmony_ci {USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT}, 1618c2ecf20Sopenharmony_ci#endif 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_3M 1648c2ecf20Sopenharmony_ci {USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M}, 1658c2ecf20Sopenharmony_ci#endif 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_ITM 1688c2ecf20Sopenharmony_ci {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, 1698c2ecf20Sopenharmony_ci {USB_DEVICE(0x16e3, 0xf9e9), .driver_info = DEVTYPE_ITM}, 1708c2ecf20Sopenharmony_ci#endif 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 1738c2ecf20Sopenharmony_ci {USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO}, 1748c2ecf20Sopenharmony_ci#endif 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_GUNZE 1778c2ecf20Sopenharmony_ci {USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE}, 1788c2ecf20Sopenharmony_ci#endif 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 1818c2ecf20Sopenharmony_ci {USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10}, 1828c2ecf20Sopenharmony_ci#endif 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH 1858c2ecf20Sopenharmony_ci {USB_DEVICE(0x255e, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, 1868c2ecf20Sopenharmony_ci {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, 1878c2ecf20Sopenharmony_ci {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, 1888c2ecf20Sopenharmony_ci {USB_DEVICE(0x6615, 0x0012), .driver_info = DEVTYPE_IRTOUCH_HIRES}, 1898c2ecf20Sopenharmony_ci#endif 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 1928c2ecf20Sopenharmony_ci {USB_DEVICE(0x1391, 0x1000), .driver_info = DEVTYPE_IDEALTEK}, 1938c2ecf20Sopenharmony_ci#endif 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH 1968c2ecf20Sopenharmony_ci {USB_DEVICE(0x0dfc, 0x0001), .driver_info = DEVTYPE_GENERAL_TOUCH}, 1978c2ecf20Sopenharmony_ci#endif 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 2008c2ecf20Sopenharmony_ci {USB_DEVICE(0x08f2, 0x007f), .driver_info = DEVTYPE_GOTOP}, 2018c2ecf20Sopenharmony_ci {USB_DEVICE(0x08f2, 0x00ce), .driver_info = DEVTYPE_GOTOP}, 2028c2ecf20Sopenharmony_ci {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP}, 2038c2ecf20Sopenharmony_ci#endif 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_JASTEC 2068c2ecf20Sopenharmony_ci {USB_DEVICE(0x0f92, 0x0001), .driver_info = DEVTYPE_JASTEC}, 2078c2ecf20Sopenharmony_ci#endif 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_E2I 2108c2ecf20Sopenharmony_ci {USB_DEVICE(0x1ac7, 0x0001), .driver_info = DEVTYPE_E2I}, 2118c2ecf20Sopenharmony_ci#endif 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC 2148c2ecf20Sopenharmony_ci {USB_DEVICE(0x14c8, 0x0003), .driver_info = DEVTYPE_ZYTRONIC}, 2158c2ecf20Sopenharmony_ci#endif 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB 2188c2ecf20Sopenharmony_ci /* TC5UH */ 2198c2ecf20Sopenharmony_ci {USB_DEVICE(0x0664, 0x0309), .driver_info = DEVTYPE_TC45USB}, 2208c2ecf20Sopenharmony_ci /* TC4UM */ 2218c2ecf20Sopenharmony_ci {USB_DEVICE(0x0664, 0x0306), .driver_info = DEVTYPE_TC45USB}, 2228c2ecf20Sopenharmony_ci#endif 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO 2258c2ecf20Sopenharmony_ci /* data interface only */ 2268c2ecf20Sopenharmony_ci {USB_DEVICE_AND_INTERFACE_INFO(0x10f0, 0x2002, 0x0a, 0x00, 0x00), 2278c2ecf20Sopenharmony_ci .driver_info = DEVTYPE_NEXIO}, 2288c2ecf20Sopenharmony_ci {USB_DEVICE_AND_INTERFACE_INFO(0x1870, 0x0001, 0x0a, 0x00, 0x00), 2298c2ecf20Sopenharmony_ci .driver_info = DEVTYPE_NEXIO}, 2308c2ecf20Sopenharmony_ci#endif 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_ELO 2338c2ecf20Sopenharmony_ci {USB_DEVICE(0x04e7, 0x0020), .driver_info = DEVTYPE_ELO}, 2348c2ecf20Sopenharmony_ci#endif 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH 2378c2ecf20Sopenharmony_ci {USB_DEVICE(0x7374, 0x0001), .driver_info = DEVTYPE_ETOUCH}, 2388c2ecf20Sopenharmony_ci#endif 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci {} 2418c2ecf20Sopenharmony_ci}; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci/***************************************************************************** 2458c2ecf20Sopenharmony_ci * e2i Part 2468c2ecf20Sopenharmony_ci */ 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_E2I 2498c2ecf20Sopenharmony_cistatic int e2i_init(struct usbtouch_usb *usbtouch) 2508c2ecf20Sopenharmony_ci{ 2518c2ecf20Sopenharmony_ci int ret; 2528c2ecf20Sopenharmony_ci struct usb_device *udev = interface_to_usbdev(usbtouch->interface); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 2558c2ecf20Sopenharmony_ci 0x01, 0x02, 0x0000, 0x0081, 2568c2ecf20Sopenharmony_ci NULL, 0, USB_CTRL_SET_TIMEOUT); 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci dev_dbg(&usbtouch->interface->dev, 2598c2ecf20Sopenharmony_ci "%s - usb_control_msg - E2I_RESET - bytes|err: %d\n", 2608c2ecf20Sopenharmony_ci __func__, ret); 2618c2ecf20Sopenharmony_ci return ret; 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_cistatic int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci int tmp = (pkt[0] << 8) | pkt[1]; 2678c2ecf20Sopenharmony_ci dev->x = (pkt[2] << 8) | pkt[3]; 2688c2ecf20Sopenharmony_ci dev->y = (pkt[4] << 8) | pkt[5]; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci tmp = tmp - 0xA000; 2718c2ecf20Sopenharmony_ci dev->touch = (tmp > 0); 2728c2ecf20Sopenharmony_ci dev->press = (tmp > 0 ? tmp : 0); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci return 1; 2758c2ecf20Sopenharmony_ci} 2768c2ecf20Sopenharmony_ci#endif 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci/***************************************************************************** 2808c2ecf20Sopenharmony_ci * eGalax part 2818c2ecf20Sopenharmony_ci */ 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci#ifndef MULTI_PACKET 2868c2ecf20Sopenharmony_ci#define MULTI_PACKET 2878c2ecf20Sopenharmony_ci#endif 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci#define EGALAX_PKT_TYPE_MASK 0xFE 2908c2ecf20Sopenharmony_ci#define EGALAX_PKT_TYPE_REPT 0x80 2918c2ecf20Sopenharmony_ci#define EGALAX_PKT_TYPE_DIAG 0x0A 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_cistatic int egalax_init(struct usbtouch_usb *usbtouch) 2948c2ecf20Sopenharmony_ci{ 2958c2ecf20Sopenharmony_ci int ret, i; 2968c2ecf20Sopenharmony_ci unsigned char *buf; 2978c2ecf20Sopenharmony_ci struct usb_device *udev = interface_to_usbdev(usbtouch->interface); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci /* 3008c2ecf20Sopenharmony_ci * An eGalax diagnostic packet kicks the device into using the right 3018c2ecf20Sopenharmony_ci * protocol. We send a "check active" packet. The response will be 3028c2ecf20Sopenharmony_ci * read later and ignored. 3038c2ecf20Sopenharmony_ci */ 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci buf = kmalloc(3, GFP_KERNEL); 3068c2ecf20Sopenharmony_ci if (!buf) 3078c2ecf20Sopenharmony_ci return -ENOMEM; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci buf[0] = EGALAX_PKT_TYPE_DIAG; 3108c2ecf20Sopenharmony_ci buf[1] = 1; /* length */ 3118c2ecf20Sopenharmony_ci buf[2] = 'A'; /* command - check active */ 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 3148c2ecf20Sopenharmony_ci ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 3158c2ecf20Sopenharmony_ci 0, 3168c2ecf20Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 3178c2ecf20Sopenharmony_ci 0, 0, buf, 3, 3188c2ecf20Sopenharmony_ci USB_CTRL_SET_TIMEOUT); 3198c2ecf20Sopenharmony_ci if (ret >= 0) { 3208c2ecf20Sopenharmony_ci ret = 0; 3218c2ecf20Sopenharmony_ci break; 3228c2ecf20Sopenharmony_ci } 3238c2ecf20Sopenharmony_ci if (ret != -EPIPE) 3248c2ecf20Sopenharmony_ci break; 3258c2ecf20Sopenharmony_ci } 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci kfree(buf); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci return ret; 3308c2ecf20Sopenharmony_ci} 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_cistatic int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 3338c2ecf20Sopenharmony_ci{ 3348c2ecf20Sopenharmony_ci if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) 3358c2ecf20Sopenharmony_ci return 0; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci dev->x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F); 3388c2ecf20Sopenharmony_ci dev->y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F); 3398c2ecf20Sopenharmony_ci dev->touch = pkt[0] & 0x01; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci return 1; 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_cistatic int egalax_get_pkt_len(unsigned char *buf, int len) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci switch (buf[0] & EGALAX_PKT_TYPE_MASK) { 3478c2ecf20Sopenharmony_ci case EGALAX_PKT_TYPE_REPT: 3488c2ecf20Sopenharmony_ci return 5; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci case EGALAX_PKT_TYPE_DIAG: 3518c2ecf20Sopenharmony_ci if (len < 2) 3528c2ecf20Sopenharmony_ci return -1; 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci return buf[1] + 2; 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci return 0; 3588c2ecf20Sopenharmony_ci} 3598c2ecf20Sopenharmony_ci#endif 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci/***************************************************************************** 3628c2ecf20Sopenharmony_ci * EasyTouch part 3638c2ecf20Sopenharmony_ci */ 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci#ifndef MULTI_PACKET 3688c2ecf20Sopenharmony_ci#define MULTI_PACKET 3698c2ecf20Sopenharmony_ci#endif 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci#define ETOUCH_PKT_TYPE_MASK 0xFE 3728c2ecf20Sopenharmony_ci#define ETOUCH_PKT_TYPE_REPT 0x80 3738c2ecf20Sopenharmony_ci#define ETOUCH_PKT_TYPE_REPT2 0xB0 3748c2ecf20Sopenharmony_ci#define ETOUCH_PKT_TYPE_DIAG 0x0A 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_cistatic int etouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 3778c2ecf20Sopenharmony_ci{ 3788c2ecf20Sopenharmony_ci if ((pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT && 3798c2ecf20Sopenharmony_ci (pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT2) 3808c2ecf20Sopenharmony_ci return 0; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci dev->x = ((pkt[1] & 0x1F) << 7) | (pkt[2] & 0x7F); 3838c2ecf20Sopenharmony_ci dev->y = ((pkt[3] & 0x1F) << 7) | (pkt[4] & 0x7F); 3848c2ecf20Sopenharmony_ci dev->touch = pkt[0] & 0x01; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci return 1; 3878c2ecf20Sopenharmony_ci} 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_cistatic int etouch_get_pkt_len(unsigned char *buf, int len) 3908c2ecf20Sopenharmony_ci{ 3918c2ecf20Sopenharmony_ci switch (buf[0] & ETOUCH_PKT_TYPE_MASK) { 3928c2ecf20Sopenharmony_ci case ETOUCH_PKT_TYPE_REPT: 3938c2ecf20Sopenharmony_ci case ETOUCH_PKT_TYPE_REPT2: 3948c2ecf20Sopenharmony_ci return 5; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci case ETOUCH_PKT_TYPE_DIAG: 3978c2ecf20Sopenharmony_ci if (len < 2) 3988c2ecf20Sopenharmony_ci return -1; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci return buf[1] + 2; 4018c2ecf20Sopenharmony_ci } 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci return 0; 4048c2ecf20Sopenharmony_ci} 4058c2ecf20Sopenharmony_ci#endif 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci/***************************************************************************** 4088c2ecf20Sopenharmony_ci * PanJit Part 4098c2ecf20Sopenharmony_ci */ 4108c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 4118c2ecf20Sopenharmony_cistatic int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 4128c2ecf20Sopenharmony_ci{ 4138c2ecf20Sopenharmony_ci dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; 4148c2ecf20Sopenharmony_ci dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; 4158c2ecf20Sopenharmony_ci dev->touch = pkt[0] & 0x01; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci return 1; 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci#endif 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci/***************************************************************************** 4238c2ecf20Sopenharmony_ci * 3M/Microtouch Part 4248c2ecf20Sopenharmony_ci */ 4258c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_3M 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci#define MTOUCHUSB_ASYNC_REPORT 1 4288c2ecf20Sopenharmony_ci#define MTOUCHUSB_RESET 7 4298c2ecf20Sopenharmony_ci#define MTOUCHUSB_REQ_CTRLLR_ID 10 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci#define MTOUCHUSB_REQ_CTRLLR_ID_LEN 16 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_cistatic int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 4348c2ecf20Sopenharmony_ci{ 4358c2ecf20Sopenharmony_ci if (hwcalib_xy) { 4368c2ecf20Sopenharmony_ci dev->x = (pkt[4] << 8) | pkt[3]; 4378c2ecf20Sopenharmony_ci dev->y = 0xffff - ((pkt[6] << 8) | pkt[5]); 4388c2ecf20Sopenharmony_ci } else { 4398c2ecf20Sopenharmony_ci dev->x = (pkt[8] << 8) | pkt[7]; 4408c2ecf20Sopenharmony_ci dev->y = (pkt[10] << 8) | pkt[9]; 4418c2ecf20Sopenharmony_ci } 4428c2ecf20Sopenharmony_ci dev->touch = (pkt[2] & 0x40) ? 1 : 0; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci return 1; 4458c2ecf20Sopenharmony_ci} 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_cistruct mtouch_priv { 4488c2ecf20Sopenharmony_ci u8 fw_rev_major; 4498c2ecf20Sopenharmony_ci u8 fw_rev_minor; 4508c2ecf20Sopenharmony_ci}; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_cistatic ssize_t mtouch_firmware_rev_show(struct device *dev, 4538c2ecf20Sopenharmony_ci struct device_attribute *attr, char *output) 4548c2ecf20Sopenharmony_ci{ 4558c2ecf20Sopenharmony_ci struct usb_interface *intf = to_usb_interface(dev); 4568c2ecf20Sopenharmony_ci struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 4578c2ecf20Sopenharmony_ci struct mtouch_priv *priv = usbtouch->priv; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci return scnprintf(output, PAGE_SIZE, "%1x.%1x\n", 4608c2ecf20Sopenharmony_ci priv->fw_rev_major, priv->fw_rev_minor); 4618c2ecf20Sopenharmony_ci} 4628c2ecf20Sopenharmony_cistatic DEVICE_ATTR(firmware_rev, 0444, mtouch_firmware_rev_show, NULL); 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_cistatic struct attribute *mtouch_attrs[] = { 4658c2ecf20Sopenharmony_ci &dev_attr_firmware_rev.attr, 4668c2ecf20Sopenharmony_ci NULL 4678c2ecf20Sopenharmony_ci}; 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_cistatic const struct attribute_group mtouch_attr_group = { 4708c2ecf20Sopenharmony_ci .attrs = mtouch_attrs, 4718c2ecf20Sopenharmony_ci}; 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_cistatic int mtouch_get_fw_revision(struct usbtouch_usb *usbtouch) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci struct usb_device *udev = interface_to_usbdev(usbtouch->interface); 4768c2ecf20Sopenharmony_ci struct mtouch_priv *priv = usbtouch->priv; 4778c2ecf20Sopenharmony_ci u8 *buf; 4788c2ecf20Sopenharmony_ci int ret; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci buf = kzalloc(MTOUCHUSB_REQ_CTRLLR_ID_LEN, GFP_NOIO); 4818c2ecf20Sopenharmony_ci if (!buf) 4828c2ecf20Sopenharmony_ci return -ENOMEM; 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 4858c2ecf20Sopenharmony_ci MTOUCHUSB_REQ_CTRLLR_ID, 4868c2ecf20Sopenharmony_ci USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 4878c2ecf20Sopenharmony_ci 0, 0, buf, MTOUCHUSB_REQ_CTRLLR_ID_LEN, 4888c2ecf20Sopenharmony_ci USB_CTRL_SET_TIMEOUT); 4898c2ecf20Sopenharmony_ci if (ret != MTOUCHUSB_REQ_CTRLLR_ID_LEN) { 4908c2ecf20Sopenharmony_ci dev_warn(&usbtouch->interface->dev, 4918c2ecf20Sopenharmony_ci "Failed to read FW rev: %d\n", ret); 4928c2ecf20Sopenharmony_ci ret = ret < 0 ? ret : -EIO; 4938c2ecf20Sopenharmony_ci goto free; 4948c2ecf20Sopenharmony_ci } 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci priv->fw_rev_major = buf[3]; 4978c2ecf20Sopenharmony_ci priv->fw_rev_minor = buf[4]; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci ret = 0; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_cifree: 5028c2ecf20Sopenharmony_ci kfree(buf); 5038c2ecf20Sopenharmony_ci return ret; 5048c2ecf20Sopenharmony_ci} 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_cistatic int mtouch_alloc(struct usbtouch_usb *usbtouch) 5078c2ecf20Sopenharmony_ci{ 5088c2ecf20Sopenharmony_ci int ret; 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci usbtouch->priv = kmalloc(sizeof(struct mtouch_priv), GFP_KERNEL); 5118c2ecf20Sopenharmony_ci if (!usbtouch->priv) 5128c2ecf20Sopenharmony_ci return -ENOMEM; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci ret = sysfs_create_group(&usbtouch->interface->dev.kobj, 5158c2ecf20Sopenharmony_ci &mtouch_attr_group); 5168c2ecf20Sopenharmony_ci if (ret) { 5178c2ecf20Sopenharmony_ci kfree(usbtouch->priv); 5188c2ecf20Sopenharmony_ci usbtouch->priv = NULL; 5198c2ecf20Sopenharmony_ci return ret; 5208c2ecf20Sopenharmony_ci } 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci return 0; 5238c2ecf20Sopenharmony_ci} 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_cistatic int mtouch_init(struct usbtouch_usb *usbtouch) 5268c2ecf20Sopenharmony_ci{ 5278c2ecf20Sopenharmony_ci int ret, i; 5288c2ecf20Sopenharmony_ci struct usb_device *udev = interface_to_usbdev(usbtouch->interface); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci ret = mtouch_get_fw_revision(usbtouch); 5318c2ecf20Sopenharmony_ci if (ret) 5328c2ecf20Sopenharmony_ci return ret; 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 5358c2ecf20Sopenharmony_ci MTOUCHUSB_RESET, 5368c2ecf20Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 5378c2ecf20Sopenharmony_ci 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); 5388c2ecf20Sopenharmony_ci dev_dbg(&usbtouch->interface->dev, 5398c2ecf20Sopenharmony_ci "%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d\n", 5408c2ecf20Sopenharmony_ci __func__, ret); 5418c2ecf20Sopenharmony_ci if (ret < 0) 5428c2ecf20Sopenharmony_ci return ret; 5438c2ecf20Sopenharmony_ci msleep(150); 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 5468c2ecf20Sopenharmony_ci ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 5478c2ecf20Sopenharmony_ci MTOUCHUSB_ASYNC_REPORT, 5488c2ecf20Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 5498c2ecf20Sopenharmony_ci 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); 5508c2ecf20Sopenharmony_ci dev_dbg(&usbtouch->interface->dev, 5518c2ecf20Sopenharmony_ci "%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d\n", 5528c2ecf20Sopenharmony_ci __func__, ret); 5538c2ecf20Sopenharmony_ci if (ret >= 0) 5548c2ecf20Sopenharmony_ci break; 5558c2ecf20Sopenharmony_ci if (ret != -EPIPE) 5568c2ecf20Sopenharmony_ci return ret; 5578c2ecf20Sopenharmony_ci } 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci /* Default min/max xy are the raw values, override if using hw-calib */ 5608c2ecf20Sopenharmony_ci if (hwcalib_xy) { 5618c2ecf20Sopenharmony_ci input_set_abs_params(usbtouch->input, ABS_X, 0, 0xffff, 0, 0); 5628c2ecf20Sopenharmony_ci input_set_abs_params(usbtouch->input, ABS_Y, 0, 0xffff, 0, 0); 5638c2ecf20Sopenharmony_ci } 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci return 0; 5668c2ecf20Sopenharmony_ci} 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_cistatic void mtouch_exit(struct usbtouch_usb *usbtouch) 5698c2ecf20Sopenharmony_ci{ 5708c2ecf20Sopenharmony_ci struct mtouch_priv *priv = usbtouch->priv; 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci sysfs_remove_group(&usbtouch->interface->dev.kobj, &mtouch_attr_group); 5738c2ecf20Sopenharmony_ci kfree(priv); 5748c2ecf20Sopenharmony_ci} 5758c2ecf20Sopenharmony_ci#endif 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci/***************************************************************************** 5798c2ecf20Sopenharmony_ci * ITM Part 5808c2ecf20Sopenharmony_ci */ 5818c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_ITM 5828c2ecf20Sopenharmony_cistatic int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 5838c2ecf20Sopenharmony_ci{ 5848c2ecf20Sopenharmony_ci int touch; 5858c2ecf20Sopenharmony_ci /* 5868c2ecf20Sopenharmony_ci * ITM devices report invalid x/y data if not touched. 5878c2ecf20Sopenharmony_ci * if the screen was touched before but is not touched any more 5888c2ecf20Sopenharmony_ci * report touch as 0 with the last valid x/y data once. then stop 5898c2ecf20Sopenharmony_ci * reporting data until touched again. 5908c2ecf20Sopenharmony_ci */ 5918c2ecf20Sopenharmony_ci dev->press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F); 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci touch = ~pkt[7] & 0x20; 5948c2ecf20Sopenharmony_ci if (!touch) { 5958c2ecf20Sopenharmony_ci if (dev->touch) { 5968c2ecf20Sopenharmony_ci dev->touch = 0; 5978c2ecf20Sopenharmony_ci return 1; 5988c2ecf20Sopenharmony_ci } 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci return 0; 6018c2ecf20Sopenharmony_ci } 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F); 6048c2ecf20Sopenharmony_ci dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F); 6058c2ecf20Sopenharmony_ci dev->touch = touch; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci return 1; 6088c2ecf20Sopenharmony_ci} 6098c2ecf20Sopenharmony_ci#endif 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci/***************************************************************************** 6138c2ecf20Sopenharmony_ci * eTurboTouch part 6148c2ecf20Sopenharmony_ci */ 6158c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 6168c2ecf20Sopenharmony_ci#ifndef MULTI_PACKET 6178c2ecf20Sopenharmony_ci#define MULTI_PACKET 6188c2ecf20Sopenharmony_ci#endif 6198c2ecf20Sopenharmony_cistatic int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 6208c2ecf20Sopenharmony_ci{ 6218c2ecf20Sopenharmony_ci unsigned int shift; 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci /* packets should start with sync */ 6248c2ecf20Sopenharmony_ci if (!(pkt[0] & 0x80)) 6258c2ecf20Sopenharmony_ci return 0; 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci shift = (6 - (pkt[0] & 0x03)); 6288c2ecf20Sopenharmony_ci dev->x = ((pkt[3] << 7) | pkt[4]) >> shift; 6298c2ecf20Sopenharmony_ci dev->y = ((pkt[1] << 7) | pkt[2]) >> shift; 6308c2ecf20Sopenharmony_ci dev->touch = (pkt[0] & 0x10) ? 1 : 0; 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci return 1; 6338c2ecf20Sopenharmony_ci} 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_cistatic int eturbo_get_pkt_len(unsigned char *buf, int len) 6368c2ecf20Sopenharmony_ci{ 6378c2ecf20Sopenharmony_ci if (buf[0] & 0x80) 6388c2ecf20Sopenharmony_ci return 5; 6398c2ecf20Sopenharmony_ci if (buf[0] == 0x01) 6408c2ecf20Sopenharmony_ci return 3; 6418c2ecf20Sopenharmony_ci return 0; 6428c2ecf20Sopenharmony_ci} 6438c2ecf20Sopenharmony_ci#endif 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci/***************************************************************************** 6478c2ecf20Sopenharmony_ci * Gunze part 6488c2ecf20Sopenharmony_ci */ 6498c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_GUNZE 6508c2ecf20Sopenharmony_cistatic int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 6518c2ecf20Sopenharmony_ci{ 6528c2ecf20Sopenharmony_ci if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80)) 6538c2ecf20Sopenharmony_ci return 0; 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F); 6568c2ecf20Sopenharmony_ci dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F); 6578c2ecf20Sopenharmony_ci dev->touch = pkt[0] & 0x20; 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci return 1; 6608c2ecf20Sopenharmony_ci} 6618c2ecf20Sopenharmony_ci#endif 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci/***************************************************************************** 6648c2ecf20Sopenharmony_ci * DMC TSC-10/25 Part 6658c2ecf20Sopenharmony_ci * 6668c2ecf20Sopenharmony_ci * Documentation about the controller and it's protocol can be found at 6678c2ecf20Sopenharmony_ci * http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf 6688c2ecf20Sopenharmony_ci * http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf 6698c2ecf20Sopenharmony_ci */ 6708c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci/* supported data rates. currently using 130 */ 6738c2ecf20Sopenharmony_ci#define TSC10_RATE_POINT 0x50 6748c2ecf20Sopenharmony_ci#define TSC10_RATE_30 0x40 6758c2ecf20Sopenharmony_ci#define TSC10_RATE_50 0x41 6768c2ecf20Sopenharmony_ci#define TSC10_RATE_80 0x42 6778c2ecf20Sopenharmony_ci#define TSC10_RATE_100 0x43 6788c2ecf20Sopenharmony_ci#define TSC10_RATE_130 0x44 6798c2ecf20Sopenharmony_ci#define TSC10_RATE_150 0x45 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci/* commands */ 6828c2ecf20Sopenharmony_ci#define TSC10_CMD_RESET 0x55 6838c2ecf20Sopenharmony_ci#define TSC10_CMD_RATE 0x05 6848c2ecf20Sopenharmony_ci#define TSC10_CMD_DATA1 0x01 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_cistatic int dmc_tsc10_init(struct usbtouch_usb *usbtouch) 6878c2ecf20Sopenharmony_ci{ 6888c2ecf20Sopenharmony_ci struct usb_device *dev = interface_to_usbdev(usbtouch->interface); 6898c2ecf20Sopenharmony_ci int ret = -ENOMEM; 6908c2ecf20Sopenharmony_ci unsigned char *buf; 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci buf = kmalloc(2, GFP_NOIO); 6938c2ecf20Sopenharmony_ci if (!buf) 6948c2ecf20Sopenharmony_ci goto err_nobuf; 6958c2ecf20Sopenharmony_ci /* reset */ 6968c2ecf20Sopenharmony_ci buf[0] = buf[1] = 0xFF; 6978c2ecf20Sopenharmony_ci ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), 6988c2ecf20Sopenharmony_ci TSC10_CMD_RESET, 6998c2ecf20Sopenharmony_ci USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 7008c2ecf20Sopenharmony_ci 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT); 7018c2ecf20Sopenharmony_ci if (ret < 0) 7028c2ecf20Sopenharmony_ci goto err_out; 7038c2ecf20Sopenharmony_ci if (buf[0] != 0x06) { 7048c2ecf20Sopenharmony_ci ret = -ENODEV; 7058c2ecf20Sopenharmony_ci goto err_out; 7068c2ecf20Sopenharmony_ci } 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci /* TSC-25 data sheet specifies a delay after the RESET command */ 7098c2ecf20Sopenharmony_ci msleep(150); 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci /* set coordinate output rate */ 7128c2ecf20Sopenharmony_ci buf[0] = buf[1] = 0xFF; 7138c2ecf20Sopenharmony_ci ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), 7148c2ecf20Sopenharmony_ci TSC10_CMD_RATE, 7158c2ecf20Sopenharmony_ci USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 7168c2ecf20Sopenharmony_ci TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); 7178c2ecf20Sopenharmony_ci if (ret < 0) 7188c2ecf20Sopenharmony_ci goto err_out; 7198c2ecf20Sopenharmony_ci if ((buf[0] != 0x06) && (buf[0] != 0x15 || buf[1] != 0x01)) { 7208c2ecf20Sopenharmony_ci ret = -ENODEV; 7218c2ecf20Sopenharmony_ci goto err_out; 7228c2ecf20Sopenharmony_ci } 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci /* start sending data */ 7258c2ecf20Sopenharmony_ci ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 7268c2ecf20Sopenharmony_ci TSC10_CMD_DATA1, 7278c2ecf20Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 7288c2ecf20Sopenharmony_ci 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); 7298c2ecf20Sopenharmony_cierr_out: 7308c2ecf20Sopenharmony_ci kfree(buf); 7318c2ecf20Sopenharmony_cierr_nobuf: 7328c2ecf20Sopenharmony_ci return ret; 7338c2ecf20Sopenharmony_ci} 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_cistatic int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 7378c2ecf20Sopenharmony_ci{ 7388c2ecf20Sopenharmony_ci dev->x = ((pkt[2] & 0x03) << 8) | pkt[1]; 7398c2ecf20Sopenharmony_ci dev->y = ((pkt[4] & 0x03) << 8) | pkt[3]; 7408c2ecf20Sopenharmony_ci dev->touch = pkt[0] & 0x01; 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci return 1; 7438c2ecf20Sopenharmony_ci} 7448c2ecf20Sopenharmony_ci#endif 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci/***************************************************************************** 7488c2ecf20Sopenharmony_ci * IRTOUCH Part 7498c2ecf20Sopenharmony_ci */ 7508c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH 7518c2ecf20Sopenharmony_cistatic int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 7528c2ecf20Sopenharmony_ci{ 7538c2ecf20Sopenharmony_ci dev->x = (pkt[3] << 8) | pkt[2]; 7548c2ecf20Sopenharmony_ci dev->y = (pkt[5] << 8) | pkt[4]; 7558c2ecf20Sopenharmony_ci dev->touch = (pkt[1] & 0x03) ? 1 : 0; 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci return 1; 7588c2ecf20Sopenharmony_ci} 7598c2ecf20Sopenharmony_ci#endif 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci/***************************************************************************** 7628c2ecf20Sopenharmony_ci * ET&T TC5UH/TC4UM part 7638c2ecf20Sopenharmony_ci */ 7648c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB 7658c2ecf20Sopenharmony_cistatic int tc45usb_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 7668c2ecf20Sopenharmony_ci{ 7678c2ecf20Sopenharmony_ci dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; 7688c2ecf20Sopenharmony_ci dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; 7698c2ecf20Sopenharmony_ci dev->touch = pkt[0] & 0x01; 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci return 1; 7728c2ecf20Sopenharmony_ci} 7738c2ecf20Sopenharmony_ci#endif 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci/***************************************************************************** 7768c2ecf20Sopenharmony_ci * IdealTEK URTC1000 Part 7778c2ecf20Sopenharmony_ci */ 7788c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 7798c2ecf20Sopenharmony_ci#ifndef MULTI_PACKET 7808c2ecf20Sopenharmony_ci#define MULTI_PACKET 7818c2ecf20Sopenharmony_ci#endif 7828c2ecf20Sopenharmony_cistatic int idealtek_get_pkt_len(unsigned char *buf, int len) 7838c2ecf20Sopenharmony_ci{ 7848c2ecf20Sopenharmony_ci if (buf[0] & 0x80) 7858c2ecf20Sopenharmony_ci return 5; 7868c2ecf20Sopenharmony_ci if (buf[0] == 0x01) 7878c2ecf20Sopenharmony_ci return len; 7888c2ecf20Sopenharmony_ci return 0; 7898c2ecf20Sopenharmony_ci} 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_cistatic int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 7928c2ecf20Sopenharmony_ci{ 7938c2ecf20Sopenharmony_ci switch (pkt[0] & 0x98) { 7948c2ecf20Sopenharmony_ci case 0x88: 7958c2ecf20Sopenharmony_ci /* touch data in IdealTEK mode */ 7968c2ecf20Sopenharmony_ci dev->x = (pkt[1] << 5) | (pkt[2] >> 2); 7978c2ecf20Sopenharmony_ci dev->y = (pkt[3] << 5) | (pkt[4] >> 2); 7988c2ecf20Sopenharmony_ci dev->touch = (pkt[0] & 0x40) ? 1 : 0; 7998c2ecf20Sopenharmony_ci return 1; 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci case 0x98: 8028c2ecf20Sopenharmony_ci /* touch data in MT emulation mode */ 8038c2ecf20Sopenharmony_ci dev->x = (pkt[2] << 5) | (pkt[1] >> 2); 8048c2ecf20Sopenharmony_ci dev->y = (pkt[4] << 5) | (pkt[3] >> 2); 8058c2ecf20Sopenharmony_ci dev->touch = (pkt[0] & 0x40) ? 1 : 0; 8068c2ecf20Sopenharmony_ci return 1; 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci default: 8098c2ecf20Sopenharmony_ci return 0; 8108c2ecf20Sopenharmony_ci } 8118c2ecf20Sopenharmony_ci} 8128c2ecf20Sopenharmony_ci#endif 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci/***************************************************************************** 8158c2ecf20Sopenharmony_ci * General Touch Part 8168c2ecf20Sopenharmony_ci */ 8178c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH 8188c2ecf20Sopenharmony_cistatic int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 8198c2ecf20Sopenharmony_ci{ 8208c2ecf20Sopenharmony_ci dev->x = (pkt[2] << 8) | pkt[1]; 8218c2ecf20Sopenharmony_ci dev->y = (pkt[4] << 8) | pkt[3]; 8228c2ecf20Sopenharmony_ci dev->press = pkt[5] & 0xff; 8238c2ecf20Sopenharmony_ci dev->touch = pkt[0] & 0x01; 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci return 1; 8268c2ecf20Sopenharmony_ci} 8278c2ecf20Sopenharmony_ci#endif 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci/***************************************************************************** 8308c2ecf20Sopenharmony_ci * GoTop Part 8318c2ecf20Sopenharmony_ci */ 8328c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 8338c2ecf20Sopenharmony_cistatic int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 8348c2ecf20Sopenharmony_ci{ 8358c2ecf20Sopenharmony_ci dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; 8368c2ecf20Sopenharmony_ci dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; 8378c2ecf20Sopenharmony_ci dev->touch = pkt[0] & 0x01; 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci return 1; 8408c2ecf20Sopenharmony_ci} 8418c2ecf20Sopenharmony_ci#endif 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci/***************************************************************************** 8448c2ecf20Sopenharmony_ci * JASTEC Part 8458c2ecf20Sopenharmony_ci */ 8468c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_JASTEC 8478c2ecf20Sopenharmony_cistatic int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 8488c2ecf20Sopenharmony_ci{ 8498c2ecf20Sopenharmony_ci dev->x = ((pkt[0] & 0x3f) << 6) | (pkt[2] & 0x3f); 8508c2ecf20Sopenharmony_ci dev->y = ((pkt[1] & 0x3f) << 6) | (pkt[3] & 0x3f); 8518c2ecf20Sopenharmony_ci dev->touch = (pkt[0] & 0x40) >> 6; 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci return 1; 8548c2ecf20Sopenharmony_ci} 8558c2ecf20Sopenharmony_ci#endif 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci/***************************************************************************** 8588c2ecf20Sopenharmony_ci * Zytronic Part 8598c2ecf20Sopenharmony_ci */ 8608c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC 8618c2ecf20Sopenharmony_cistatic int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 8628c2ecf20Sopenharmony_ci{ 8638c2ecf20Sopenharmony_ci struct usb_interface *intf = dev->interface; 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci switch (pkt[0]) { 8668c2ecf20Sopenharmony_ci case 0x3A: /* command response */ 8678c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "%s: Command response %d\n", __func__, pkt[1]); 8688c2ecf20Sopenharmony_ci break; 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci case 0xC0: /* down */ 8718c2ecf20Sopenharmony_ci dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); 8728c2ecf20Sopenharmony_ci dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); 8738c2ecf20Sopenharmony_ci dev->touch = 1; 8748c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "%s: down %d,%d\n", __func__, dev->x, dev->y); 8758c2ecf20Sopenharmony_ci return 1; 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci case 0x80: /* up */ 8788c2ecf20Sopenharmony_ci dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); 8798c2ecf20Sopenharmony_ci dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); 8808c2ecf20Sopenharmony_ci dev->touch = 0; 8818c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "%s: up %d,%d\n", __func__, dev->x, dev->y); 8828c2ecf20Sopenharmony_ci return 1; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci default: 8858c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, "%s: Unknown return %d\n", __func__, pkt[0]); 8868c2ecf20Sopenharmony_ci break; 8878c2ecf20Sopenharmony_ci } 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci return 0; 8908c2ecf20Sopenharmony_ci} 8918c2ecf20Sopenharmony_ci#endif 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci/***************************************************************************** 8948c2ecf20Sopenharmony_ci * NEXIO Part 8958c2ecf20Sopenharmony_ci */ 8968c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci#define NEXIO_TIMEOUT 5000 8998c2ecf20Sopenharmony_ci#define NEXIO_BUFSIZE 1024 9008c2ecf20Sopenharmony_ci#define NEXIO_THRESHOLD 50 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_cistruct nexio_priv { 9038c2ecf20Sopenharmony_ci struct urb *ack; 9048c2ecf20Sopenharmony_ci unsigned char *ack_buf; 9058c2ecf20Sopenharmony_ci}; 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_cistruct nexio_touch_packet { 9088c2ecf20Sopenharmony_ci u8 flags; /* 0xe1 = touch, 0xe1 = release */ 9098c2ecf20Sopenharmony_ci __be16 data_len; /* total bytes of touch data */ 9108c2ecf20Sopenharmony_ci __be16 x_len; /* bytes for X axis */ 9118c2ecf20Sopenharmony_ci __be16 y_len; /* bytes for Y axis */ 9128c2ecf20Sopenharmony_ci u8 data[]; 9138c2ecf20Sopenharmony_ci} __attribute__ ((packed)); 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_cistatic unsigned char nexio_ack_pkt[2] = { 0xaa, 0x02 }; 9168c2ecf20Sopenharmony_cistatic unsigned char nexio_init_pkt[4] = { 0x82, 0x04, 0x0a, 0x0f }; 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_cistatic void nexio_ack_complete(struct urb *urb) 9198c2ecf20Sopenharmony_ci{ 9208c2ecf20Sopenharmony_ci} 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_cistatic int nexio_alloc(struct usbtouch_usb *usbtouch) 9238c2ecf20Sopenharmony_ci{ 9248c2ecf20Sopenharmony_ci struct nexio_priv *priv; 9258c2ecf20Sopenharmony_ci int ret = -ENOMEM; 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci usbtouch->priv = kmalloc(sizeof(struct nexio_priv), GFP_KERNEL); 9288c2ecf20Sopenharmony_ci if (!usbtouch->priv) 9298c2ecf20Sopenharmony_ci goto out_buf; 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci priv = usbtouch->priv; 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci priv->ack_buf = kmemdup(nexio_ack_pkt, sizeof(nexio_ack_pkt), 9348c2ecf20Sopenharmony_ci GFP_KERNEL); 9358c2ecf20Sopenharmony_ci if (!priv->ack_buf) 9368c2ecf20Sopenharmony_ci goto err_priv; 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci priv->ack = usb_alloc_urb(0, GFP_KERNEL); 9398c2ecf20Sopenharmony_ci if (!priv->ack) { 9408c2ecf20Sopenharmony_ci dev_dbg(&usbtouch->interface->dev, 9418c2ecf20Sopenharmony_ci "%s - usb_alloc_urb failed: usbtouch->ack\n", __func__); 9428c2ecf20Sopenharmony_ci goto err_ack_buf; 9438c2ecf20Sopenharmony_ci } 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci return 0; 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_cierr_ack_buf: 9488c2ecf20Sopenharmony_ci kfree(priv->ack_buf); 9498c2ecf20Sopenharmony_cierr_priv: 9508c2ecf20Sopenharmony_ci kfree(priv); 9518c2ecf20Sopenharmony_ciout_buf: 9528c2ecf20Sopenharmony_ci return ret; 9538c2ecf20Sopenharmony_ci} 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_cistatic int nexio_init(struct usbtouch_usb *usbtouch) 9568c2ecf20Sopenharmony_ci{ 9578c2ecf20Sopenharmony_ci struct usb_device *dev = interface_to_usbdev(usbtouch->interface); 9588c2ecf20Sopenharmony_ci struct usb_host_interface *interface = usbtouch->interface->cur_altsetting; 9598c2ecf20Sopenharmony_ci struct nexio_priv *priv = usbtouch->priv; 9608c2ecf20Sopenharmony_ci int ret = -ENOMEM; 9618c2ecf20Sopenharmony_ci int actual_len, i; 9628c2ecf20Sopenharmony_ci unsigned char *buf; 9638c2ecf20Sopenharmony_ci char *firmware_ver = NULL, *device_name = NULL; 9648c2ecf20Sopenharmony_ci int input_ep = 0, output_ep = 0; 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci /* find first input and output endpoint */ 9678c2ecf20Sopenharmony_ci for (i = 0; i < interface->desc.bNumEndpoints; i++) { 9688c2ecf20Sopenharmony_ci if (!input_ep && 9698c2ecf20Sopenharmony_ci usb_endpoint_dir_in(&interface->endpoint[i].desc)) 9708c2ecf20Sopenharmony_ci input_ep = interface->endpoint[i].desc.bEndpointAddress; 9718c2ecf20Sopenharmony_ci if (!output_ep && 9728c2ecf20Sopenharmony_ci usb_endpoint_dir_out(&interface->endpoint[i].desc)) 9738c2ecf20Sopenharmony_ci output_ep = interface->endpoint[i].desc.bEndpointAddress; 9748c2ecf20Sopenharmony_ci } 9758c2ecf20Sopenharmony_ci if (!input_ep || !output_ep) 9768c2ecf20Sopenharmony_ci return -ENXIO; 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci buf = kmalloc(NEXIO_BUFSIZE, GFP_NOIO); 9798c2ecf20Sopenharmony_ci if (!buf) 9808c2ecf20Sopenharmony_ci goto out_buf; 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci /* two empty reads */ 9838c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 9848c2ecf20Sopenharmony_ci ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep), 9858c2ecf20Sopenharmony_ci buf, NEXIO_BUFSIZE, &actual_len, 9868c2ecf20Sopenharmony_ci NEXIO_TIMEOUT); 9878c2ecf20Sopenharmony_ci if (ret < 0) 9888c2ecf20Sopenharmony_ci goto out_buf; 9898c2ecf20Sopenharmony_ci } 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci /* send init command */ 9928c2ecf20Sopenharmony_ci memcpy(buf, nexio_init_pkt, sizeof(nexio_init_pkt)); 9938c2ecf20Sopenharmony_ci ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, output_ep), 9948c2ecf20Sopenharmony_ci buf, sizeof(nexio_init_pkt), &actual_len, 9958c2ecf20Sopenharmony_ci NEXIO_TIMEOUT); 9968c2ecf20Sopenharmony_ci if (ret < 0) 9978c2ecf20Sopenharmony_ci goto out_buf; 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci /* read replies */ 10008c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 10018c2ecf20Sopenharmony_ci memset(buf, 0, NEXIO_BUFSIZE); 10028c2ecf20Sopenharmony_ci ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep), 10038c2ecf20Sopenharmony_ci buf, NEXIO_BUFSIZE, &actual_len, 10048c2ecf20Sopenharmony_ci NEXIO_TIMEOUT); 10058c2ecf20Sopenharmony_ci if (ret < 0 || actual_len < 1 || buf[1] != actual_len) 10068c2ecf20Sopenharmony_ci continue; 10078c2ecf20Sopenharmony_ci switch (buf[0]) { 10088c2ecf20Sopenharmony_ci case 0x83: /* firmware version */ 10098c2ecf20Sopenharmony_ci if (!firmware_ver) 10108c2ecf20Sopenharmony_ci firmware_ver = kstrdup(&buf[2], GFP_NOIO); 10118c2ecf20Sopenharmony_ci break; 10128c2ecf20Sopenharmony_ci case 0x84: /* device name */ 10138c2ecf20Sopenharmony_ci if (!device_name) 10148c2ecf20Sopenharmony_ci device_name = kstrdup(&buf[2], GFP_NOIO); 10158c2ecf20Sopenharmony_ci break; 10168c2ecf20Sopenharmony_ci } 10178c2ecf20Sopenharmony_ci } 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci printk(KERN_INFO "Nexio device: %s, firmware version: %s\n", 10208c2ecf20Sopenharmony_ci device_name, firmware_ver); 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci kfree(firmware_ver); 10238c2ecf20Sopenharmony_ci kfree(device_name); 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci usb_fill_bulk_urb(priv->ack, dev, usb_sndbulkpipe(dev, output_ep), 10268c2ecf20Sopenharmony_ci priv->ack_buf, sizeof(nexio_ack_pkt), 10278c2ecf20Sopenharmony_ci nexio_ack_complete, usbtouch); 10288c2ecf20Sopenharmony_ci ret = 0; 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ciout_buf: 10318c2ecf20Sopenharmony_ci kfree(buf); 10328c2ecf20Sopenharmony_ci return ret; 10338c2ecf20Sopenharmony_ci} 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_cistatic void nexio_exit(struct usbtouch_usb *usbtouch) 10368c2ecf20Sopenharmony_ci{ 10378c2ecf20Sopenharmony_ci struct nexio_priv *priv = usbtouch->priv; 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci usb_kill_urb(priv->ack); 10408c2ecf20Sopenharmony_ci usb_free_urb(priv->ack); 10418c2ecf20Sopenharmony_ci kfree(priv->ack_buf); 10428c2ecf20Sopenharmony_ci kfree(priv); 10438c2ecf20Sopenharmony_ci} 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_cistatic int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) 10468c2ecf20Sopenharmony_ci{ 10478c2ecf20Sopenharmony_ci struct nexio_touch_packet *packet = (void *) pkt; 10488c2ecf20Sopenharmony_ci struct nexio_priv *priv = usbtouch->priv; 10498c2ecf20Sopenharmony_ci unsigned int data_len = be16_to_cpu(packet->data_len); 10508c2ecf20Sopenharmony_ci unsigned int x_len = be16_to_cpu(packet->x_len); 10518c2ecf20Sopenharmony_ci unsigned int y_len = be16_to_cpu(packet->y_len); 10528c2ecf20Sopenharmony_ci int x, y, begin_x, begin_y, end_x, end_y, w, h, ret; 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci /* got touch data? */ 10558c2ecf20Sopenharmony_ci if ((pkt[0] & 0xe0) != 0xe0) 10568c2ecf20Sopenharmony_ci return 0; 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci if (data_len > 0xff) 10598c2ecf20Sopenharmony_ci data_len -= 0x100; 10608c2ecf20Sopenharmony_ci if (x_len > 0xff) 10618c2ecf20Sopenharmony_ci x_len -= 0x80; 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci /* send ACK */ 10648c2ecf20Sopenharmony_ci ret = usb_submit_urb(priv->ack, GFP_ATOMIC); 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_ci if (!usbtouch->type->max_xc) { 10678c2ecf20Sopenharmony_ci usbtouch->type->max_xc = 2 * x_len; 10688c2ecf20Sopenharmony_ci input_set_abs_params(usbtouch->input, ABS_X, 10698c2ecf20Sopenharmony_ci 0, usbtouch->type->max_xc, 0, 0); 10708c2ecf20Sopenharmony_ci usbtouch->type->max_yc = 2 * y_len; 10718c2ecf20Sopenharmony_ci input_set_abs_params(usbtouch->input, ABS_Y, 10728c2ecf20Sopenharmony_ci 0, usbtouch->type->max_yc, 0, 0); 10738c2ecf20Sopenharmony_ci } 10748c2ecf20Sopenharmony_ci /* 10758c2ecf20Sopenharmony_ci * The device reports state of IR sensors on X and Y axes. 10768c2ecf20Sopenharmony_ci * Each byte represents "darkness" percentage (0-100) of one element. 10778c2ecf20Sopenharmony_ci * 17" touchscreen reports only 64 x 52 bytes so the resolution is low. 10788c2ecf20Sopenharmony_ci * This also means that there's a limited multi-touch capability but 10798c2ecf20Sopenharmony_ci * it's disabled (and untested) here as there's no X driver for that. 10808c2ecf20Sopenharmony_ci */ 10818c2ecf20Sopenharmony_ci begin_x = end_x = begin_y = end_y = -1; 10828c2ecf20Sopenharmony_ci for (x = 0; x < x_len; x++) { 10838c2ecf20Sopenharmony_ci if (begin_x == -1 && packet->data[x] > NEXIO_THRESHOLD) { 10848c2ecf20Sopenharmony_ci begin_x = x; 10858c2ecf20Sopenharmony_ci continue; 10868c2ecf20Sopenharmony_ci } 10878c2ecf20Sopenharmony_ci if (end_x == -1 && begin_x != -1 && packet->data[x] < NEXIO_THRESHOLD) { 10888c2ecf20Sopenharmony_ci end_x = x - 1; 10898c2ecf20Sopenharmony_ci for (y = x_len; y < data_len; y++) { 10908c2ecf20Sopenharmony_ci if (begin_y == -1 && packet->data[y] > NEXIO_THRESHOLD) { 10918c2ecf20Sopenharmony_ci begin_y = y - x_len; 10928c2ecf20Sopenharmony_ci continue; 10938c2ecf20Sopenharmony_ci } 10948c2ecf20Sopenharmony_ci if (end_y == -1 && 10958c2ecf20Sopenharmony_ci begin_y != -1 && packet->data[y] < NEXIO_THRESHOLD) { 10968c2ecf20Sopenharmony_ci end_y = y - 1 - x_len; 10978c2ecf20Sopenharmony_ci w = end_x - begin_x; 10988c2ecf20Sopenharmony_ci h = end_y - begin_y; 10998c2ecf20Sopenharmony_ci#if 0 11008c2ecf20Sopenharmony_ci /* multi-touch */ 11018c2ecf20Sopenharmony_ci input_report_abs(usbtouch->input, 11028c2ecf20Sopenharmony_ci ABS_MT_TOUCH_MAJOR, max(w,h)); 11038c2ecf20Sopenharmony_ci input_report_abs(usbtouch->input, 11048c2ecf20Sopenharmony_ci ABS_MT_TOUCH_MINOR, min(x,h)); 11058c2ecf20Sopenharmony_ci input_report_abs(usbtouch->input, 11068c2ecf20Sopenharmony_ci ABS_MT_POSITION_X, 2*begin_x+w); 11078c2ecf20Sopenharmony_ci input_report_abs(usbtouch->input, 11088c2ecf20Sopenharmony_ci ABS_MT_POSITION_Y, 2*begin_y+h); 11098c2ecf20Sopenharmony_ci input_report_abs(usbtouch->input, 11108c2ecf20Sopenharmony_ci ABS_MT_ORIENTATION, w > h); 11118c2ecf20Sopenharmony_ci input_mt_sync(usbtouch->input); 11128c2ecf20Sopenharmony_ci#endif 11138c2ecf20Sopenharmony_ci /* single touch */ 11148c2ecf20Sopenharmony_ci usbtouch->x = 2 * begin_x + w; 11158c2ecf20Sopenharmony_ci usbtouch->y = 2 * begin_y + h; 11168c2ecf20Sopenharmony_ci usbtouch->touch = packet->flags & 0x01; 11178c2ecf20Sopenharmony_ci begin_y = end_y = -1; 11188c2ecf20Sopenharmony_ci return 1; 11198c2ecf20Sopenharmony_ci } 11208c2ecf20Sopenharmony_ci } 11218c2ecf20Sopenharmony_ci begin_x = end_x = -1; 11228c2ecf20Sopenharmony_ci } 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci } 11258c2ecf20Sopenharmony_ci return 0; 11268c2ecf20Sopenharmony_ci} 11278c2ecf20Sopenharmony_ci#endif 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci/***************************************************************************** 11318c2ecf20Sopenharmony_ci * ELO part 11328c2ecf20Sopenharmony_ci */ 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_ELO 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_cistatic int elo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 11378c2ecf20Sopenharmony_ci{ 11388c2ecf20Sopenharmony_ci dev->x = (pkt[3] << 8) | pkt[2]; 11398c2ecf20Sopenharmony_ci dev->y = (pkt[5] << 8) | pkt[4]; 11408c2ecf20Sopenharmony_ci dev->touch = pkt[6] > 0; 11418c2ecf20Sopenharmony_ci dev->press = pkt[6]; 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci return 1; 11448c2ecf20Sopenharmony_ci} 11458c2ecf20Sopenharmony_ci#endif 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci/***************************************************************************** 11498c2ecf20Sopenharmony_ci * the different device descriptors 11508c2ecf20Sopenharmony_ci */ 11518c2ecf20Sopenharmony_ci#ifdef MULTI_PACKET 11528c2ecf20Sopenharmony_cistatic void usbtouch_process_multi(struct usbtouch_usb *usbtouch, 11538c2ecf20Sopenharmony_ci unsigned char *pkt, int len); 11548c2ecf20Sopenharmony_ci#endif 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_cistatic struct usbtouch_device_info usbtouch_dev_info[] = { 11578c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_ELO 11588c2ecf20Sopenharmony_ci [DEVTYPE_ELO] = { 11598c2ecf20Sopenharmony_ci .min_xc = 0x0, 11608c2ecf20Sopenharmony_ci .max_xc = 0x0fff, 11618c2ecf20Sopenharmony_ci .min_yc = 0x0, 11628c2ecf20Sopenharmony_ci .max_yc = 0x0fff, 11638c2ecf20Sopenharmony_ci .max_press = 0xff, 11648c2ecf20Sopenharmony_ci .rept_size = 8, 11658c2ecf20Sopenharmony_ci .read_data = elo_read_data, 11668c2ecf20Sopenharmony_ci }, 11678c2ecf20Sopenharmony_ci#endif 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX 11708c2ecf20Sopenharmony_ci [DEVTYPE_EGALAX] = { 11718c2ecf20Sopenharmony_ci .min_xc = 0x0, 11728c2ecf20Sopenharmony_ci .max_xc = 0x07ff, 11738c2ecf20Sopenharmony_ci .min_yc = 0x0, 11748c2ecf20Sopenharmony_ci .max_yc = 0x07ff, 11758c2ecf20Sopenharmony_ci .rept_size = 16, 11768c2ecf20Sopenharmony_ci .process_pkt = usbtouch_process_multi, 11778c2ecf20Sopenharmony_ci .get_pkt_len = egalax_get_pkt_len, 11788c2ecf20Sopenharmony_ci .read_data = egalax_read_data, 11798c2ecf20Sopenharmony_ci .init = egalax_init, 11808c2ecf20Sopenharmony_ci }, 11818c2ecf20Sopenharmony_ci#endif 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 11848c2ecf20Sopenharmony_ci [DEVTYPE_PANJIT] = { 11858c2ecf20Sopenharmony_ci .min_xc = 0x0, 11868c2ecf20Sopenharmony_ci .max_xc = 0x0fff, 11878c2ecf20Sopenharmony_ci .min_yc = 0x0, 11888c2ecf20Sopenharmony_ci .max_yc = 0x0fff, 11898c2ecf20Sopenharmony_ci .rept_size = 8, 11908c2ecf20Sopenharmony_ci .read_data = panjit_read_data, 11918c2ecf20Sopenharmony_ci }, 11928c2ecf20Sopenharmony_ci#endif 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_3M 11958c2ecf20Sopenharmony_ci [DEVTYPE_3M] = { 11968c2ecf20Sopenharmony_ci .min_xc = 0x0, 11978c2ecf20Sopenharmony_ci .max_xc = 0x4000, 11988c2ecf20Sopenharmony_ci .min_yc = 0x0, 11998c2ecf20Sopenharmony_ci .max_yc = 0x4000, 12008c2ecf20Sopenharmony_ci .rept_size = 11, 12018c2ecf20Sopenharmony_ci .read_data = mtouch_read_data, 12028c2ecf20Sopenharmony_ci .alloc = mtouch_alloc, 12038c2ecf20Sopenharmony_ci .init = mtouch_init, 12048c2ecf20Sopenharmony_ci .exit = mtouch_exit, 12058c2ecf20Sopenharmony_ci }, 12068c2ecf20Sopenharmony_ci#endif 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_ITM 12098c2ecf20Sopenharmony_ci [DEVTYPE_ITM] = { 12108c2ecf20Sopenharmony_ci .min_xc = 0x0, 12118c2ecf20Sopenharmony_ci .max_xc = 0x0fff, 12128c2ecf20Sopenharmony_ci .min_yc = 0x0, 12138c2ecf20Sopenharmony_ci .max_yc = 0x0fff, 12148c2ecf20Sopenharmony_ci .max_press = 0xff, 12158c2ecf20Sopenharmony_ci .rept_size = 8, 12168c2ecf20Sopenharmony_ci .read_data = itm_read_data, 12178c2ecf20Sopenharmony_ci }, 12188c2ecf20Sopenharmony_ci#endif 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO 12218c2ecf20Sopenharmony_ci [DEVTYPE_ETURBO] = { 12228c2ecf20Sopenharmony_ci .min_xc = 0x0, 12238c2ecf20Sopenharmony_ci .max_xc = 0x07ff, 12248c2ecf20Sopenharmony_ci .min_yc = 0x0, 12258c2ecf20Sopenharmony_ci .max_yc = 0x07ff, 12268c2ecf20Sopenharmony_ci .rept_size = 8, 12278c2ecf20Sopenharmony_ci .process_pkt = usbtouch_process_multi, 12288c2ecf20Sopenharmony_ci .get_pkt_len = eturbo_get_pkt_len, 12298c2ecf20Sopenharmony_ci .read_data = eturbo_read_data, 12308c2ecf20Sopenharmony_ci }, 12318c2ecf20Sopenharmony_ci#endif 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_GUNZE 12348c2ecf20Sopenharmony_ci [DEVTYPE_GUNZE] = { 12358c2ecf20Sopenharmony_ci .min_xc = 0x0, 12368c2ecf20Sopenharmony_ci .max_xc = 0x0fff, 12378c2ecf20Sopenharmony_ci .min_yc = 0x0, 12388c2ecf20Sopenharmony_ci .max_yc = 0x0fff, 12398c2ecf20Sopenharmony_ci .rept_size = 4, 12408c2ecf20Sopenharmony_ci .read_data = gunze_read_data, 12418c2ecf20Sopenharmony_ci }, 12428c2ecf20Sopenharmony_ci#endif 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 12458c2ecf20Sopenharmony_ci [DEVTYPE_DMC_TSC10] = { 12468c2ecf20Sopenharmony_ci .min_xc = 0x0, 12478c2ecf20Sopenharmony_ci .max_xc = 0x03ff, 12488c2ecf20Sopenharmony_ci .min_yc = 0x0, 12498c2ecf20Sopenharmony_ci .max_yc = 0x03ff, 12508c2ecf20Sopenharmony_ci .rept_size = 5, 12518c2ecf20Sopenharmony_ci .init = dmc_tsc10_init, 12528c2ecf20Sopenharmony_ci .read_data = dmc_tsc10_read_data, 12538c2ecf20Sopenharmony_ci }, 12548c2ecf20Sopenharmony_ci#endif 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH 12578c2ecf20Sopenharmony_ci [DEVTYPE_IRTOUCH] = { 12588c2ecf20Sopenharmony_ci .min_xc = 0x0, 12598c2ecf20Sopenharmony_ci .max_xc = 0x0fff, 12608c2ecf20Sopenharmony_ci .min_yc = 0x0, 12618c2ecf20Sopenharmony_ci .max_yc = 0x0fff, 12628c2ecf20Sopenharmony_ci .rept_size = 8, 12638c2ecf20Sopenharmony_ci .read_data = irtouch_read_data, 12648c2ecf20Sopenharmony_ci }, 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_ci [DEVTYPE_IRTOUCH_HIRES] = { 12678c2ecf20Sopenharmony_ci .min_xc = 0x0, 12688c2ecf20Sopenharmony_ci .max_xc = 0x7fff, 12698c2ecf20Sopenharmony_ci .min_yc = 0x0, 12708c2ecf20Sopenharmony_ci .max_yc = 0x7fff, 12718c2ecf20Sopenharmony_ci .rept_size = 8, 12728c2ecf20Sopenharmony_ci .read_data = irtouch_read_data, 12738c2ecf20Sopenharmony_ci }, 12748c2ecf20Sopenharmony_ci#endif 12758c2ecf20Sopenharmony_ci 12768c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK 12778c2ecf20Sopenharmony_ci [DEVTYPE_IDEALTEK] = { 12788c2ecf20Sopenharmony_ci .min_xc = 0x0, 12798c2ecf20Sopenharmony_ci .max_xc = 0x0fff, 12808c2ecf20Sopenharmony_ci .min_yc = 0x0, 12818c2ecf20Sopenharmony_ci .max_yc = 0x0fff, 12828c2ecf20Sopenharmony_ci .rept_size = 8, 12838c2ecf20Sopenharmony_ci .process_pkt = usbtouch_process_multi, 12848c2ecf20Sopenharmony_ci .get_pkt_len = idealtek_get_pkt_len, 12858c2ecf20Sopenharmony_ci .read_data = idealtek_read_data, 12868c2ecf20Sopenharmony_ci }, 12878c2ecf20Sopenharmony_ci#endif 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH 12908c2ecf20Sopenharmony_ci [DEVTYPE_GENERAL_TOUCH] = { 12918c2ecf20Sopenharmony_ci .min_xc = 0x0, 12928c2ecf20Sopenharmony_ci .max_xc = 0x7fff, 12938c2ecf20Sopenharmony_ci .min_yc = 0x0, 12948c2ecf20Sopenharmony_ci .max_yc = 0x7fff, 12958c2ecf20Sopenharmony_ci .rept_size = 7, 12968c2ecf20Sopenharmony_ci .read_data = general_touch_read_data, 12978c2ecf20Sopenharmony_ci }, 12988c2ecf20Sopenharmony_ci#endif 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 13018c2ecf20Sopenharmony_ci [DEVTYPE_GOTOP] = { 13028c2ecf20Sopenharmony_ci .min_xc = 0x0, 13038c2ecf20Sopenharmony_ci .max_xc = 0x03ff, 13048c2ecf20Sopenharmony_ci .min_yc = 0x0, 13058c2ecf20Sopenharmony_ci .max_yc = 0x03ff, 13068c2ecf20Sopenharmony_ci .rept_size = 4, 13078c2ecf20Sopenharmony_ci .read_data = gotop_read_data, 13088c2ecf20Sopenharmony_ci }, 13098c2ecf20Sopenharmony_ci#endif 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_JASTEC 13128c2ecf20Sopenharmony_ci [DEVTYPE_JASTEC] = { 13138c2ecf20Sopenharmony_ci .min_xc = 0x0, 13148c2ecf20Sopenharmony_ci .max_xc = 0x0fff, 13158c2ecf20Sopenharmony_ci .min_yc = 0x0, 13168c2ecf20Sopenharmony_ci .max_yc = 0x0fff, 13178c2ecf20Sopenharmony_ci .rept_size = 4, 13188c2ecf20Sopenharmony_ci .read_data = jastec_read_data, 13198c2ecf20Sopenharmony_ci }, 13208c2ecf20Sopenharmony_ci#endif 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_E2I 13238c2ecf20Sopenharmony_ci [DEVTYPE_E2I] = { 13248c2ecf20Sopenharmony_ci .min_xc = 0x0, 13258c2ecf20Sopenharmony_ci .max_xc = 0x7fff, 13268c2ecf20Sopenharmony_ci .min_yc = 0x0, 13278c2ecf20Sopenharmony_ci .max_yc = 0x7fff, 13288c2ecf20Sopenharmony_ci .rept_size = 6, 13298c2ecf20Sopenharmony_ci .init = e2i_init, 13308c2ecf20Sopenharmony_ci .read_data = e2i_read_data, 13318c2ecf20Sopenharmony_ci }, 13328c2ecf20Sopenharmony_ci#endif 13338c2ecf20Sopenharmony_ci 13348c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC 13358c2ecf20Sopenharmony_ci [DEVTYPE_ZYTRONIC] = { 13368c2ecf20Sopenharmony_ci .min_xc = 0x0, 13378c2ecf20Sopenharmony_ci .max_xc = 0x03ff, 13388c2ecf20Sopenharmony_ci .min_yc = 0x0, 13398c2ecf20Sopenharmony_ci .max_yc = 0x03ff, 13408c2ecf20Sopenharmony_ci .rept_size = 5, 13418c2ecf20Sopenharmony_ci .read_data = zytronic_read_data, 13428c2ecf20Sopenharmony_ci .irq_always = true, 13438c2ecf20Sopenharmony_ci }, 13448c2ecf20Sopenharmony_ci#endif 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB 13478c2ecf20Sopenharmony_ci [DEVTYPE_TC45USB] = { 13488c2ecf20Sopenharmony_ci .min_xc = 0x0, 13498c2ecf20Sopenharmony_ci .max_xc = 0x0fff, 13508c2ecf20Sopenharmony_ci .min_yc = 0x0, 13518c2ecf20Sopenharmony_ci .max_yc = 0x0fff, 13528c2ecf20Sopenharmony_ci .rept_size = 5, 13538c2ecf20Sopenharmony_ci .read_data = tc45usb_read_data, 13548c2ecf20Sopenharmony_ci }, 13558c2ecf20Sopenharmony_ci#endif 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO 13588c2ecf20Sopenharmony_ci [DEVTYPE_NEXIO] = { 13598c2ecf20Sopenharmony_ci .rept_size = 1024, 13608c2ecf20Sopenharmony_ci .irq_always = true, 13618c2ecf20Sopenharmony_ci .read_data = nexio_read_data, 13628c2ecf20Sopenharmony_ci .alloc = nexio_alloc, 13638c2ecf20Sopenharmony_ci .init = nexio_init, 13648c2ecf20Sopenharmony_ci .exit = nexio_exit, 13658c2ecf20Sopenharmony_ci }, 13668c2ecf20Sopenharmony_ci#endif 13678c2ecf20Sopenharmony_ci#ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH 13688c2ecf20Sopenharmony_ci [DEVTYPE_ETOUCH] = { 13698c2ecf20Sopenharmony_ci .min_xc = 0x0, 13708c2ecf20Sopenharmony_ci .max_xc = 0x07ff, 13718c2ecf20Sopenharmony_ci .min_yc = 0x0, 13728c2ecf20Sopenharmony_ci .max_yc = 0x07ff, 13738c2ecf20Sopenharmony_ci .rept_size = 16, 13748c2ecf20Sopenharmony_ci .process_pkt = usbtouch_process_multi, 13758c2ecf20Sopenharmony_ci .get_pkt_len = etouch_get_pkt_len, 13768c2ecf20Sopenharmony_ci .read_data = etouch_read_data, 13778c2ecf20Sopenharmony_ci }, 13788c2ecf20Sopenharmony_ci#endif 13798c2ecf20Sopenharmony_ci}; 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci/***************************************************************************** 13838c2ecf20Sopenharmony_ci * Generic Part 13848c2ecf20Sopenharmony_ci */ 13858c2ecf20Sopenharmony_cistatic void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, 13868c2ecf20Sopenharmony_ci unsigned char *pkt, int len) 13878c2ecf20Sopenharmony_ci{ 13888c2ecf20Sopenharmony_ci struct usbtouch_device_info *type = usbtouch->type; 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci if (!type->read_data(usbtouch, pkt)) 13918c2ecf20Sopenharmony_ci return; 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_ci input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch); 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci if (swap_xy) { 13968c2ecf20Sopenharmony_ci input_report_abs(usbtouch->input, ABS_X, usbtouch->y); 13978c2ecf20Sopenharmony_ci input_report_abs(usbtouch->input, ABS_Y, usbtouch->x); 13988c2ecf20Sopenharmony_ci } else { 13998c2ecf20Sopenharmony_ci input_report_abs(usbtouch->input, ABS_X, usbtouch->x); 14008c2ecf20Sopenharmony_ci input_report_abs(usbtouch->input, ABS_Y, usbtouch->y); 14018c2ecf20Sopenharmony_ci } 14028c2ecf20Sopenharmony_ci if (type->max_press) 14038c2ecf20Sopenharmony_ci input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press); 14048c2ecf20Sopenharmony_ci input_sync(usbtouch->input); 14058c2ecf20Sopenharmony_ci} 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_ci#ifdef MULTI_PACKET 14098c2ecf20Sopenharmony_cistatic void usbtouch_process_multi(struct usbtouch_usb *usbtouch, 14108c2ecf20Sopenharmony_ci unsigned char *pkt, int len) 14118c2ecf20Sopenharmony_ci{ 14128c2ecf20Sopenharmony_ci unsigned char *buffer; 14138c2ecf20Sopenharmony_ci int pkt_len, pos, buf_len, tmp; 14148c2ecf20Sopenharmony_ci 14158c2ecf20Sopenharmony_ci /* process buffer */ 14168c2ecf20Sopenharmony_ci if (unlikely(usbtouch->buf_len)) { 14178c2ecf20Sopenharmony_ci /* try to get size */ 14188c2ecf20Sopenharmony_ci pkt_len = usbtouch->type->get_pkt_len( 14198c2ecf20Sopenharmony_ci usbtouch->buffer, usbtouch->buf_len); 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci /* drop? */ 14228c2ecf20Sopenharmony_ci if (unlikely(!pkt_len)) 14238c2ecf20Sopenharmony_ci goto out_flush_buf; 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_ci /* need to append -pkt_len bytes before able to get size */ 14268c2ecf20Sopenharmony_ci if (unlikely(pkt_len < 0)) { 14278c2ecf20Sopenharmony_ci int append = -pkt_len; 14288c2ecf20Sopenharmony_ci if (unlikely(append > len)) 14298c2ecf20Sopenharmony_ci append = len; 14308c2ecf20Sopenharmony_ci if (usbtouch->buf_len + append >= usbtouch->type->rept_size) 14318c2ecf20Sopenharmony_ci goto out_flush_buf; 14328c2ecf20Sopenharmony_ci memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append); 14338c2ecf20Sopenharmony_ci usbtouch->buf_len += append; 14348c2ecf20Sopenharmony_ci 14358c2ecf20Sopenharmony_ci pkt_len = usbtouch->type->get_pkt_len( 14368c2ecf20Sopenharmony_ci usbtouch->buffer, usbtouch->buf_len); 14378c2ecf20Sopenharmony_ci if (pkt_len < 0) 14388c2ecf20Sopenharmony_ci return; 14398c2ecf20Sopenharmony_ci } 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci /* append */ 14428c2ecf20Sopenharmony_ci tmp = pkt_len - usbtouch->buf_len; 14438c2ecf20Sopenharmony_ci if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size) 14448c2ecf20Sopenharmony_ci goto out_flush_buf; 14458c2ecf20Sopenharmony_ci memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp); 14468c2ecf20Sopenharmony_ci usbtouch_process_pkt(usbtouch, usbtouch->buffer, pkt_len); 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci buffer = pkt + tmp; 14498c2ecf20Sopenharmony_ci buf_len = len - tmp; 14508c2ecf20Sopenharmony_ci } else { 14518c2ecf20Sopenharmony_ci buffer = pkt; 14528c2ecf20Sopenharmony_ci buf_len = len; 14538c2ecf20Sopenharmony_ci } 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci /* loop over the received packet, process */ 14568c2ecf20Sopenharmony_ci pos = 0; 14578c2ecf20Sopenharmony_ci while (pos < buf_len) { 14588c2ecf20Sopenharmony_ci /* get packet len */ 14598c2ecf20Sopenharmony_ci pkt_len = usbtouch->type->get_pkt_len(buffer + pos, 14608c2ecf20Sopenharmony_ci buf_len - pos); 14618c2ecf20Sopenharmony_ci 14628c2ecf20Sopenharmony_ci /* unknown packet: skip one byte */ 14638c2ecf20Sopenharmony_ci if (unlikely(!pkt_len)) { 14648c2ecf20Sopenharmony_ci pos++; 14658c2ecf20Sopenharmony_ci continue; 14668c2ecf20Sopenharmony_ci } 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_ci /* full packet: process */ 14698c2ecf20Sopenharmony_ci if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) { 14708c2ecf20Sopenharmony_ci usbtouch_process_pkt(usbtouch, buffer + pos, pkt_len); 14718c2ecf20Sopenharmony_ci } else { 14728c2ecf20Sopenharmony_ci /* incomplete packet: save in buffer */ 14738c2ecf20Sopenharmony_ci memcpy(usbtouch->buffer, buffer + pos, buf_len - pos); 14748c2ecf20Sopenharmony_ci usbtouch->buf_len = buf_len - pos; 14758c2ecf20Sopenharmony_ci return; 14768c2ecf20Sopenharmony_ci } 14778c2ecf20Sopenharmony_ci pos += pkt_len; 14788c2ecf20Sopenharmony_ci } 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_ciout_flush_buf: 14818c2ecf20Sopenharmony_ci usbtouch->buf_len = 0; 14828c2ecf20Sopenharmony_ci return; 14838c2ecf20Sopenharmony_ci} 14848c2ecf20Sopenharmony_ci#endif 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_cistatic void usbtouch_irq(struct urb *urb) 14888c2ecf20Sopenharmony_ci{ 14898c2ecf20Sopenharmony_ci struct usbtouch_usb *usbtouch = urb->context; 14908c2ecf20Sopenharmony_ci struct device *dev = &usbtouch->interface->dev; 14918c2ecf20Sopenharmony_ci int retval; 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_ci switch (urb->status) { 14948c2ecf20Sopenharmony_ci case 0: 14958c2ecf20Sopenharmony_ci /* success */ 14968c2ecf20Sopenharmony_ci break; 14978c2ecf20Sopenharmony_ci case -ETIME: 14988c2ecf20Sopenharmony_ci /* this urb is timing out */ 14998c2ecf20Sopenharmony_ci dev_dbg(dev, 15008c2ecf20Sopenharmony_ci "%s - urb timed out - was the device unplugged?\n", 15018c2ecf20Sopenharmony_ci __func__); 15028c2ecf20Sopenharmony_ci return; 15038c2ecf20Sopenharmony_ci case -ECONNRESET: 15048c2ecf20Sopenharmony_ci case -ENOENT: 15058c2ecf20Sopenharmony_ci case -ESHUTDOWN: 15068c2ecf20Sopenharmony_ci case -EPIPE: 15078c2ecf20Sopenharmony_ci /* this urb is terminated, clean up */ 15088c2ecf20Sopenharmony_ci dev_dbg(dev, "%s - urb shutting down with status: %d\n", 15098c2ecf20Sopenharmony_ci __func__, urb->status); 15108c2ecf20Sopenharmony_ci return; 15118c2ecf20Sopenharmony_ci default: 15128c2ecf20Sopenharmony_ci dev_dbg(dev, "%s - nonzero urb status received: %d\n", 15138c2ecf20Sopenharmony_ci __func__, urb->status); 15148c2ecf20Sopenharmony_ci goto exit; 15158c2ecf20Sopenharmony_ci } 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_ci usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length); 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ciexit: 15208c2ecf20Sopenharmony_ci usb_mark_last_busy(interface_to_usbdev(usbtouch->interface)); 15218c2ecf20Sopenharmony_ci retval = usb_submit_urb(urb, GFP_ATOMIC); 15228c2ecf20Sopenharmony_ci if (retval) 15238c2ecf20Sopenharmony_ci dev_err(dev, "%s - usb_submit_urb failed with result: %d\n", 15248c2ecf20Sopenharmony_ci __func__, retval); 15258c2ecf20Sopenharmony_ci} 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_cistatic int usbtouch_open(struct input_dev *input) 15288c2ecf20Sopenharmony_ci{ 15298c2ecf20Sopenharmony_ci struct usbtouch_usb *usbtouch = input_get_drvdata(input); 15308c2ecf20Sopenharmony_ci int r; 15318c2ecf20Sopenharmony_ci 15328c2ecf20Sopenharmony_ci usbtouch->irq->dev = interface_to_usbdev(usbtouch->interface); 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_ci r = usb_autopm_get_interface(usbtouch->interface) ? -EIO : 0; 15358c2ecf20Sopenharmony_ci if (r < 0) 15368c2ecf20Sopenharmony_ci goto out; 15378c2ecf20Sopenharmony_ci 15388c2ecf20Sopenharmony_ci mutex_lock(&usbtouch->pm_mutex); 15398c2ecf20Sopenharmony_ci if (!usbtouch->type->irq_always) { 15408c2ecf20Sopenharmony_ci if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) { 15418c2ecf20Sopenharmony_ci r = -EIO; 15428c2ecf20Sopenharmony_ci goto out_put; 15438c2ecf20Sopenharmony_ci } 15448c2ecf20Sopenharmony_ci } 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci usbtouch->interface->needs_remote_wakeup = 1; 15478c2ecf20Sopenharmony_ci usbtouch->is_open = true; 15488c2ecf20Sopenharmony_ciout_put: 15498c2ecf20Sopenharmony_ci mutex_unlock(&usbtouch->pm_mutex); 15508c2ecf20Sopenharmony_ci usb_autopm_put_interface(usbtouch->interface); 15518c2ecf20Sopenharmony_ciout: 15528c2ecf20Sopenharmony_ci return r; 15538c2ecf20Sopenharmony_ci} 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_cistatic void usbtouch_close(struct input_dev *input) 15568c2ecf20Sopenharmony_ci{ 15578c2ecf20Sopenharmony_ci struct usbtouch_usb *usbtouch = input_get_drvdata(input); 15588c2ecf20Sopenharmony_ci int r; 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_ci mutex_lock(&usbtouch->pm_mutex); 15618c2ecf20Sopenharmony_ci if (!usbtouch->type->irq_always) 15628c2ecf20Sopenharmony_ci usb_kill_urb(usbtouch->irq); 15638c2ecf20Sopenharmony_ci usbtouch->is_open = false; 15648c2ecf20Sopenharmony_ci mutex_unlock(&usbtouch->pm_mutex); 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci r = usb_autopm_get_interface(usbtouch->interface); 15678c2ecf20Sopenharmony_ci usbtouch->interface->needs_remote_wakeup = 0; 15688c2ecf20Sopenharmony_ci if (!r) 15698c2ecf20Sopenharmony_ci usb_autopm_put_interface(usbtouch->interface); 15708c2ecf20Sopenharmony_ci} 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_cistatic int usbtouch_suspend 15738c2ecf20Sopenharmony_ci(struct usb_interface *intf, pm_message_t message) 15748c2ecf20Sopenharmony_ci{ 15758c2ecf20Sopenharmony_ci struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_ci usb_kill_urb(usbtouch->irq); 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci return 0; 15808c2ecf20Sopenharmony_ci} 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_cistatic int usbtouch_resume(struct usb_interface *intf) 15838c2ecf20Sopenharmony_ci{ 15848c2ecf20Sopenharmony_ci struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 15858c2ecf20Sopenharmony_ci int result = 0; 15868c2ecf20Sopenharmony_ci 15878c2ecf20Sopenharmony_ci mutex_lock(&usbtouch->pm_mutex); 15888c2ecf20Sopenharmony_ci if (usbtouch->is_open || usbtouch->type->irq_always) 15898c2ecf20Sopenharmony_ci result = usb_submit_urb(usbtouch->irq, GFP_NOIO); 15908c2ecf20Sopenharmony_ci mutex_unlock(&usbtouch->pm_mutex); 15918c2ecf20Sopenharmony_ci 15928c2ecf20Sopenharmony_ci return result; 15938c2ecf20Sopenharmony_ci} 15948c2ecf20Sopenharmony_ci 15958c2ecf20Sopenharmony_cistatic int usbtouch_reset_resume(struct usb_interface *intf) 15968c2ecf20Sopenharmony_ci{ 15978c2ecf20Sopenharmony_ci struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 15988c2ecf20Sopenharmony_ci int err = 0; 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci /* reinit the device */ 16018c2ecf20Sopenharmony_ci if (usbtouch->type->init) { 16028c2ecf20Sopenharmony_ci err = usbtouch->type->init(usbtouch); 16038c2ecf20Sopenharmony_ci if (err) { 16048c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, 16058c2ecf20Sopenharmony_ci "%s - type->init() failed, err: %d\n", 16068c2ecf20Sopenharmony_ci __func__, err); 16078c2ecf20Sopenharmony_ci return err; 16088c2ecf20Sopenharmony_ci } 16098c2ecf20Sopenharmony_ci } 16108c2ecf20Sopenharmony_ci 16118c2ecf20Sopenharmony_ci /* restart IO if needed */ 16128c2ecf20Sopenharmony_ci mutex_lock(&usbtouch->pm_mutex); 16138c2ecf20Sopenharmony_ci if (usbtouch->is_open) 16148c2ecf20Sopenharmony_ci err = usb_submit_urb(usbtouch->irq, GFP_NOIO); 16158c2ecf20Sopenharmony_ci mutex_unlock(&usbtouch->pm_mutex); 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_ci return err; 16188c2ecf20Sopenharmony_ci} 16198c2ecf20Sopenharmony_ci 16208c2ecf20Sopenharmony_cistatic void usbtouch_free_buffers(struct usb_device *udev, 16218c2ecf20Sopenharmony_ci struct usbtouch_usb *usbtouch) 16228c2ecf20Sopenharmony_ci{ 16238c2ecf20Sopenharmony_ci usb_free_coherent(udev, usbtouch->data_size, 16248c2ecf20Sopenharmony_ci usbtouch->data, usbtouch->data_dma); 16258c2ecf20Sopenharmony_ci kfree(usbtouch->buffer); 16268c2ecf20Sopenharmony_ci} 16278c2ecf20Sopenharmony_ci 16288c2ecf20Sopenharmony_cistatic struct usb_endpoint_descriptor * 16298c2ecf20Sopenharmony_ciusbtouch_get_input_endpoint(struct usb_host_interface *interface) 16308c2ecf20Sopenharmony_ci{ 16318c2ecf20Sopenharmony_ci int i; 16328c2ecf20Sopenharmony_ci 16338c2ecf20Sopenharmony_ci for (i = 0; i < interface->desc.bNumEndpoints; i++) 16348c2ecf20Sopenharmony_ci if (usb_endpoint_dir_in(&interface->endpoint[i].desc)) 16358c2ecf20Sopenharmony_ci return &interface->endpoint[i].desc; 16368c2ecf20Sopenharmony_ci 16378c2ecf20Sopenharmony_ci return NULL; 16388c2ecf20Sopenharmony_ci} 16398c2ecf20Sopenharmony_ci 16408c2ecf20Sopenharmony_cistatic int usbtouch_probe(struct usb_interface *intf, 16418c2ecf20Sopenharmony_ci const struct usb_device_id *id) 16428c2ecf20Sopenharmony_ci{ 16438c2ecf20Sopenharmony_ci struct usbtouch_usb *usbtouch; 16448c2ecf20Sopenharmony_ci struct input_dev *input_dev; 16458c2ecf20Sopenharmony_ci struct usb_endpoint_descriptor *endpoint; 16468c2ecf20Sopenharmony_ci struct usb_device *udev = interface_to_usbdev(intf); 16478c2ecf20Sopenharmony_ci struct usbtouch_device_info *type; 16488c2ecf20Sopenharmony_ci int err = -ENOMEM; 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ci /* some devices are ignored */ 16518c2ecf20Sopenharmony_ci if (id->driver_info == DEVTYPE_IGNORE) 16528c2ecf20Sopenharmony_ci return -ENODEV; 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_ci endpoint = usbtouch_get_input_endpoint(intf->cur_altsetting); 16558c2ecf20Sopenharmony_ci if (!endpoint) 16568c2ecf20Sopenharmony_ci return -ENXIO; 16578c2ecf20Sopenharmony_ci 16588c2ecf20Sopenharmony_ci usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL); 16598c2ecf20Sopenharmony_ci input_dev = input_allocate_device(); 16608c2ecf20Sopenharmony_ci if (!usbtouch || !input_dev) 16618c2ecf20Sopenharmony_ci goto out_free; 16628c2ecf20Sopenharmony_ci 16638c2ecf20Sopenharmony_ci mutex_init(&usbtouch->pm_mutex); 16648c2ecf20Sopenharmony_ci 16658c2ecf20Sopenharmony_ci type = &usbtouch_dev_info[id->driver_info]; 16668c2ecf20Sopenharmony_ci usbtouch->type = type; 16678c2ecf20Sopenharmony_ci if (!type->process_pkt) 16688c2ecf20Sopenharmony_ci type->process_pkt = usbtouch_process_pkt; 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci usbtouch->data_size = type->rept_size; 16718c2ecf20Sopenharmony_ci if (type->get_pkt_len) { 16728c2ecf20Sopenharmony_ci /* 16738c2ecf20Sopenharmony_ci * When dealing with variable-length packets we should 16748c2ecf20Sopenharmony_ci * not request more than wMaxPacketSize bytes at once 16758c2ecf20Sopenharmony_ci * as we do not know if there is more data coming or 16768c2ecf20Sopenharmony_ci * we filled exactly wMaxPacketSize bytes and there is 16778c2ecf20Sopenharmony_ci * nothing else. 16788c2ecf20Sopenharmony_ci */ 16798c2ecf20Sopenharmony_ci usbtouch->data_size = min(usbtouch->data_size, 16808c2ecf20Sopenharmony_ci usb_endpoint_maxp(endpoint)); 16818c2ecf20Sopenharmony_ci } 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_ci usbtouch->data = usb_alloc_coherent(udev, usbtouch->data_size, 16848c2ecf20Sopenharmony_ci GFP_KERNEL, &usbtouch->data_dma); 16858c2ecf20Sopenharmony_ci if (!usbtouch->data) 16868c2ecf20Sopenharmony_ci goto out_free; 16878c2ecf20Sopenharmony_ci 16888c2ecf20Sopenharmony_ci if (type->get_pkt_len) { 16898c2ecf20Sopenharmony_ci usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL); 16908c2ecf20Sopenharmony_ci if (!usbtouch->buffer) 16918c2ecf20Sopenharmony_ci goto out_free_buffers; 16928c2ecf20Sopenharmony_ci } 16938c2ecf20Sopenharmony_ci 16948c2ecf20Sopenharmony_ci usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL); 16958c2ecf20Sopenharmony_ci if (!usbtouch->irq) { 16968c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, 16978c2ecf20Sopenharmony_ci "%s - usb_alloc_urb failed: usbtouch->irq\n", __func__); 16988c2ecf20Sopenharmony_ci goto out_free_buffers; 16998c2ecf20Sopenharmony_ci } 17008c2ecf20Sopenharmony_ci 17018c2ecf20Sopenharmony_ci usbtouch->interface = intf; 17028c2ecf20Sopenharmony_ci usbtouch->input = input_dev; 17038c2ecf20Sopenharmony_ci 17048c2ecf20Sopenharmony_ci if (udev->manufacturer) 17058c2ecf20Sopenharmony_ci strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name)); 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_ci if (udev->product) { 17088c2ecf20Sopenharmony_ci if (udev->manufacturer) 17098c2ecf20Sopenharmony_ci strlcat(usbtouch->name, " ", sizeof(usbtouch->name)); 17108c2ecf20Sopenharmony_ci strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name)); 17118c2ecf20Sopenharmony_ci } 17128c2ecf20Sopenharmony_ci 17138c2ecf20Sopenharmony_ci if (!strlen(usbtouch->name)) 17148c2ecf20Sopenharmony_ci snprintf(usbtouch->name, sizeof(usbtouch->name), 17158c2ecf20Sopenharmony_ci "USB Touchscreen %04x:%04x", 17168c2ecf20Sopenharmony_ci le16_to_cpu(udev->descriptor.idVendor), 17178c2ecf20Sopenharmony_ci le16_to_cpu(udev->descriptor.idProduct)); 17188c2ecf20Sopenharmony_ci 17198c2ecf20Sopenharmony_ci usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys)); 17208c2ecf20Sopenharmony_ci strlcat(usbtouch->phys, "/input0", sizeof(usbtouch->phys)); 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci input_dev->name = usbtouch->name; 17238c2ecf20Sopenharmony_ci input_dev->phys = usbtouch->phys; 17248c2ecf20Sopenharmony_ci usb_to_input_id(udev, &input_dev->id); 17258c2ecf20Sopenharmony_ci input_dev->dev.parent = &intf->dev; 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_ci input_set_drvdata(input_dev, usbtouch); 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci input_dev->open = usbtouch_open; 17308c2ecf20Sopenharmony_ci input_dev->close = usbtouch_close; 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_ci input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 17338c2ecf20Sopenharmony_ci input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 17348c2ecf20Sopenharmony_ci input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0); 17358c2ecf20Sopenharmony_ci input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0); 17368c2ecf20Sopenharmony_ci if (type->max_press) 17378c2ecf20Sopenharmony_ci input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press, 17388c2ecf20Sopenharmony_ci type->max_press, 0, 0); 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ci if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT) 17418c2ecf20Sopenharmony_ci usb_fill_int_urb(usbtouch->irq, udev, 17428c2ecf20Sopenharmony_ci usb_rcvintpipe(udev, endpoint->bEndpointAddress), 17438c2ecf20Sopenharmony_ci usbtouch->data, usbtouch->data_size, 17448c2ecf20Sopenharmony_ci usbtouch_irq, usbtouch, endpoint->bInterval); 17458c2ecf20Sopenharmony_ci else 17468c2ecf20Sopenharmony_ci usb_fill_bulk_urb(usbtouch->irq, udev, 17478c2ecf20Sopenharmony_ci usb_rcvbulkpipe(udev, endpoint->bEndpointAddress), 17488c2ecf20Sopenharmony_ci usbtouch->data, usbtouch->data_size, 17498c2ecf20Sopenharmony_ci usbtouch_irq, usbtouch); 17508c2ecf20Sopenharmony_ci 17518c2ecf20Sopenharmony_ci usbtouch->irq->dev = udev; 17528c2ecf20Sopenharmony_ci usbtouch->irq->transfer_dma = usbtouch->data_dma; 17538c2ecf20Sopenharmony_ci usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 17548c2ecf20Sopenharmony_ci 17558c2ecf20Sopenharmony_ci /* device specific allocations */ 17568c2ecf20Sopenharmony_ci if (type->alloc) { 17578c2ecf20Sopenharmony_ci err = type->alloc(usbtouch); 17588c2ecf20Sopenharmony_ci if (err) { 17598c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, 17608c2ecf20Sopenharmony_ci "%s - type->alloc() failed, err: %d\n", 17618c2ecf20Sopenharmony_ci __func__, err); 17628c2ecf20Sopenharmony_ci goto out_free_urb; 17638c2ecf20Sopenharmony_ci } 17648c2ecf20Sopenharmony_ci } 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_ci /* device specific initialisation*/ 17678c2ecf20Sopenharmony_ci if (type->init) { 17688c2ecf20Sopenharmony_ci err = type->init(usbtouch); 17698c2ecf20Sopenharmony_ci if (err) { 17708c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, 17718c2ecf20Sopenharmony_ci "%s - type->init() failed, err: %d\n", 17728c2ecf20Sopenharmony_ci __func__, err); 17738c2ecf20Sopenharmony_ci goto out_do_exit; 17748c2ecf20Sopenharmony_ci } 17758c2ecf20Sopenharmony_ci } 17768c2ecf20Sopenharmony_ci 17778c2ecf20Sopenharmony_ci err = input_register_device(usbtouch->input); 17788c2ecf20Sopenharmony_ci if (err) { 17798c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, 17808c2ecf20Sopenharmony_ci "%s - input_register_device failed, err: %d\n", 17818c2ecf20Sopenharmony_ci __func__, err); 17828c2ecf20Sopenharmony_ci goto out_do_exit; 17838c2ecf20Sopenharmony_ci } 17848c2ecf20Sopenharmony_ci 17858c2ecf20Sopenharmony_ci usb_set_intfdata(intf, usbtouch); 17868c2ecf20Sopenharmony_ci 17878c2ecf20Sopenharmony_ci if (usbtouch->type->irq_always) { 17888c2ecf20Sopenharmony_ci /* this can't fail */ 17898c2ecf20Sopenharmony_ci usb_autopm_get_interface(intf); 17908c2ecf20Sopenharmony_ci err = usb_submit_urb(usbtouch->irq, GFP_KERNEL); 17918c2ecf20Sopenharmony_ci if (err) { 17928c2ecf20Sopenharmony_ci usb_autopm_put_interface(intf); 17938c2ecf20Sopenharmony_ci dev_err(&intf->dev, 17948c2ecf20Sopenharmony_ci "%s - usb_submit_urb failed with result: %d\n", 17958c2ecf20Sopenharmony_ci __func__, err); 17968c2ecf20Sopenharmony_ci goto out_unregister_input; 17978c2ecf20Sopenharmony_ci } 17988c2ecf20Sopenharmony_ci } 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci return 0; 18018c2ecf20Sopenharmony_ci 18028c2ecf20Sopenharmony_ciout_unregister_input: 18038c2ecf20Sopenharmony_ci input_unregister_device(input_dev); 18048c2ecf20Sopenharmony_ci input_dev = NULL; 18058c2ecf20Sopenharmony_ciout_do_exit: 18068c2ecf20Sopenharmony_ci if (type->exit) 18078c2ecf20Sopenharmony_ci type->exit(usbtouch); 18088c2ecf20Sopenharmony_ciout_free_urb: 18098c2ecf20Sopenharmony_ci usb_free_urb(usbtouch->irq); 18108c2ecf20Sopenharmony_ciout_free_buffers: 18118c2ecf20Sopenharmony_ci usbtouch_free_buffers(udev, usbtouch); 18128c2ecf20Sopenharmony_ciout_free: 18138c2ecf20Sopenharmony_ci input_free_device(input_dev); 18148c2ecf20Sopenharmony_ci kfree(usbtouch); 18158c2ecf20Sopenharmony_ci return err; 18168c2ecf20Sopenharmony_ci} 18178c2ecf20Sopenharmony_ci 18188c2ecf20Sopenharmony_cistatic void usbtouch_disconnect(struct usb_interface *intf) 18198c2ecf20Sopenharmony_ci{ 18208c2ecf20Sopenharmony_ci struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 18218c2ecf20Sopenharmony_ci 18228c2ecf20Sopenharmony_ci if (!usbtouch) 18238c2ecf20Sopenharmony_ci return; 18248c2ecf20Sopenharmony_ci 18258c2ecf20Sopenharmony_ci dev_dbg(&intf->dev, 18268c2ecf20Sopenharmony_ci "%s - usbtouch is initialized, cleaning up\n", __func__); 18278c2ecf20Sopenharmony_ci 18288c2ecf20Sopenharmony_ci usb_set_intfdata(intf, NULL); 18298c2ecf20Sopenharmony_ci /* this will stop IO via close */ 18308c2ecf20Sopenharmony_ci input_unregister_device(usbtouch->input); 18318c2ecf20Sopenharmony_ci usb_free_urb(usbtouch->irq); 18328c2ecf20Sopenharmony_ci if (usbtouch->type->exit) 18338c2ecf20Sopenharmony_ci usbtouch->type->exit(usbtouch); 18348c2ecf20Sopenharmony_ci usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); 18358c2ecf20Sopenharmony_ci kfree(usbtouch); 18368c2ecf20Sopenharmony_ci} 18378c2ecf20Sopenharmony_ci 18388c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, usbtouch_devices); 18398c2ecf20Sopenharmony_ci 18408c2ecf20Sopenharmony_cistatic struct usb_driver usbtouch_driver = { 18418c2ecf20Sopenharmony_ci .name = "usbtouchscreen", 18428c2ecf20Sopenharmony_ci .probe = usbtouch_probe, 18438c2ecf20Sopenharmony_ci .disconnect = usbtouch_disconnect, 18448c2ecf20Sopenharmony_ci .suspend = usbtouch_suspend, 18458c2ecf20Sopenharmony_ci .resume = usbtouch_resume, 18468c2ecf20Sopenharmony_ci .reset_resume = usbtouch_reset_resume, 18478c2ecf20Sopenharmony_ci .id_table = usbtouch_devices, 18488c2ecf20Sopenharmony_ci .supports_autosuspend = 1, 18498c2ecf20Sopenharmony_ci}; 18508c2ecf20Sopenharmony_ci 18518c2ecf20Sopenharmony_cimodule_usb_driver(usbtouch_driver); 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_ciMODULE_AUTHOR("Daniel Ritz <daniel.ritz@gmx.ch>"); 18548c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("USB Touchscreen Driver"); 18558c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 18568c2ecf20Sopenharmony_ci 18578c2ecf20Sopenharmony_ciMODULE_ALIAS("touchkitusb"); 18588c2ecf20Sopenharmony_ciMODULE_ALIAS("itmtouch"); 18598c2ecf20Sopenharmony_ciMODULE_ALIAS("mtouchusb"); 1860