论坛风格切换切换到宽版
发帖 回复
返回列表  提醒:不能用迅雷等P2P下载,否则下载失败标(二级)的板块,需二级才能下载,没二级不要购买,下载不了
  • 1051阅读
  • 0回复

RK3288  USB  触摸屏驱动 [复制链接]

上一主题 下一主题
离线mark83136
 

性别:
帅哥
发帖
1210
金币
360
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看楼主 倒序阅读 使用道具 0楼 发表于: 2015-07-07
1] ~w?)..'  
/****************************************************************************** '-RacNY  
* usbtouchscreen.c gHstdp_3  
* Driver for USB Touchscreens, supporting those devices: \*e\MOp6  
*  - eGalax Touchkit @lE'D":?  
*    includes eTurboTouch CT-410/510/700 ;mk[!  
*  - 3M/Microtouch  EX II series I@9'd$YY  
*  - ITM _;;Zz&c  
*  - PanJit TouchSet <R@,wzK  
*  - eTurboTouch 9/(jY$Ar  
*  - Gunze AHL61 %k1Pyv;]  
*  - DMC TSC-10/25 esnq/  
*  - IRTOUCHSYSTEMS/UNITOP "hf |7E_  
*  - IdealTEK URTC1000 Wvr{l  
*  - General Touch h.PBe  
*  - GoTop Super_Q2/GogoPen/PenPower tablets }Rw,4  
*  - JASTEC USB touch controller/DigiTech DTR-02U 6j<!W+~G  
*  - Zytronic capacitive touchscreen OA[e}Vn  
*  - NEXIO/iNexio =zyA~}M2  
* n^T,R  
* Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> qt~=47<d  
* Copyright (C) by Todd E. Johnson (mtouchusb.c) \4>,L_O  
* &2`p#riAS  
* This program is free software; you can redistribute it and/or =,(TP  
* modify it under the terms of the GNU General Public License as ~x9 ]?T  
* published by the Free Software Foundation; either version 2 of the @9B*V~ <  
* License, or (at your option) any later version. Xv-p7$?f  
* RTm/-6[N  
* This program is distributed in the hope that it will be useful, but +1y$#~dl  
* WITHOUT ANY WARRANTY; without even the implied warranty of c[,h|~K/_?  
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU [Vo5$w  
* General Public License for more details. ~_D.&-xUF  
* T^1 Z_|A  
* You should have received a copy of the GNU General Public License h<Aq|*  
* along with this program; if not, write to the Free Software pZ.b X  
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. (jc& Fk  
* {p84fR1P  
* Driver is based on touchkitusb.c 8D*nU3O   
* - ITM parts are from itmtouch.c w*ans}P7  
* - 3M parts are from mtouchusb.c /D&&7;jJ  
* - PanJit parts are from an unmerged driver by Lanslott Gish Vb (b3  
* - DMC TSC 10/25 are from Holger Schurig, with ideas from an unmerged pUXoSnIq:  
*   driver from Marius Vollmer =:^aBN#  
* P0n1I7|  
*****************************************************************************/ gA!@oiq@  
yWi-ic [n  
//#define DEBUG sE pI)9  
Y &C b  
#include <linux/kernel.h> aj1]ZT \  
#include <linux/slab.h> |vI`u[P  
#include <linux/input.h> nF,F#V8l  
#include <linux/module.h> %y6(+I #P  
#include <linux/init.h> G](4!G&  
#include <linux/usb.h> Q\N*)&Sd<M  
#include <linux/usb/input.h> cq4~(PXT g  
#include <linux/hid.h> K oJ=0jM#  
q!ZM Wg  
LjI`$r.B  
#define DRIVER_VERSION        "v0.6" D:1@1Jr  
#define DRIVER_AUTHOR        "Daniel Ritz <daniel.ritz@gmx.ch>" 7FG;fJ;&NZ  
#define DRIVER_DESC        "USB Touchscreen Driver" p{g4`o  
}5;4'l8  
static int swap_xy; 6:ettdj  
module_param(swap_xy, bool, 0644); fST.p|b7  
MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); 1!<t8,W4  
Q/+`9z+c  
static int hwcalib_xy; @NLcO}  
module_param(hwcalib_xy, bool, 0644); ZZY#.  
MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available"); ~L)~p%rbi  
94"+l@K  
/* device specifc data/functions */ h_%q`y,  
struct usbtouch_usb; X-c|jn7  
struct usbtouch_device_info { SVe]2ONd  
    int min_xc, max_xc; AW]\n;f  
    int min_yc, max_yc; LhJUoX  
    int min_press, max_press; NKu[6J?)  
    int rept_size; ?=? _32O  
g#J` 7n  
    /* } oPO`  
     * Always service the USB devices irq not just when the input device is 3uLG$`N   
     * open. This is useful when devices have a watchdog which prevents us 5=pE*ETJ  
     * from periodically polling the device. Leave this unset unless your u 272)@R  
     * touchscreen device requires it, as it does consume more of the USB ^_WR) F'K  
     * bandwidth. ]r Uj<[O  
     */ @J[@Pu O  
    bool irq_always; ?jmP] MM  
F]ao Ty  
    void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len); J9Ao*IW~  
x-BU$bx5  
    /* w% %q/![uy  
     * used to get the packet len. possible return values: *w+'I*QSt~  
     * > 0: packet len 5h5izA'0'  
     * = 0: skip one byte nip6|dN  
     * < 0: -return value more bytes needed Z`Y&cKsn  
     */ 2 XP }:e  
    int  (*get_pkt_len) (unsigned char *pkt, int len); , >LJpv  
gHg=G+Q@  
    int  (*read_data)   (struct usbtouch_usb *usbtouch, unsigned char *pkt); "q=Cye  
    int  (*alloc)       (struct usbtouch_usb *usbtouch); 7v5]% %E/  
    int  (*init)        (struct usbtouch_usb *usbtouch); my (@~'  
    void (*exit)        (struct usbtouch_usb *usbtouch); !oWB5x~:P  
}; {VcRur}&Y8  
3s6obw$ki  
/* a usbtouch device */ c1#0o) q*7  
struct usbtouch_usb { &jE\D^>ko  
    unsigned char *data; ]o6 ZZK  
    dma_addr_t data_dma; W$4$%r8  
    unsigned char *buffer; mY"7/dw<v  
    int buf_len; >8f~2dH2%  
    struct urb *irq; qSY\a\.<  
    struct usb_interface *interface; 2W,9HSu8  
    struct input_dev *input; YYWD\Y`8  
    struct usbtouch_device_info *type; }y(t')=9  
    char name[128]; ] ZV[}7I.  
    char phys[64]; CMj =4e  
    void *priv; 4agW<c#  
fap`;AuwK  
    int x, y; R"B{IWQi  
    int touch, press; R(1:I@<?E  
}; 3=O [Q:8  
6S`_L  
)|~K&qn`  
/* device types */ on_h'?2  
enum { nWd!ovd  
    DEVTYPE_IGNORE = -1, dyQ7@K.E  
    DEVTYPE_EGALAX, P5Xp #pa  
    DEVTYPE_PANJIT, @ {/)k%U  
    DEVTYPE_3M, [\8rh^LFi  
    DEVTYPE_ITM, m Q2i$ 0u  
    DEVTYPE_ETURBO, DQG%`-J  
    DEVTYPE_GUNZE, z !K2UTX  
    DEVTYPE_DMC_TSC10, =pL$*`]?  
    DEVTYPE_IRTOUCH, yGa0/o18!?  
    DEVTYPE_IDEALTEK, zMSwU]4I!  
    DEVTYPE_GENERAL_TOUCH, csP4Oq\g[  
    DEVTYPE_GOTOP, Mu3G/|t(  
    DEVTYPE_JASTEC, K=gg<E<  
    DEVTYPE_E2I, x-%O1frc  
    DEVTYPE_ZYTRONIC, )OI}IWDl  
    DEVTYPE_TC45USB, .p[uIRd`  
    DEVTYPE_NEXIO, S?688  
}; JwG(WLb:  
'uu*DgEr  
#define USB_DEVICE_HID_CLASS(vend, prod) \ 5rsz2;#p  
    .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \ be+-p  
        | USB_DEVICE_ID_MATCH_INT_PROTOCOL \ '2lV(>"  
        | USB_DEVICE_ID_MATCH_DEVICE, \ t&?jJ7 (&8  
    .idVendor = (vend), \ g[} L ?  
    .idProduct = (prod), \ /~,*DH$)  
    .bInterfaceClass = USB_INTERFACE_CLASS_HID, \ L3eF BF/  
    .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE MCE@EFD`\  
}&0LoW/  
static const struct usb_device_id usbtouch_devices[] = { %]P{)*y-?  
#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX <B6md i'R  
    /* ignore the HID capable devices, handled by usbhid */ ?!RbS#QV}  
    {USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE}, gj^)T_E_  
    {USB_DEVICE_HID_CLASS(0x0eef, 0x0002), .driver_info = DEVTYPE_IGNORE}, EQyX!  
ZqclmCi  
    /* normal device IDs */ A/y|pg5  
    {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX}, +`d92Tz  
    {USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX}, aL(G0@(  
    {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX}, [4"(\r\f  
    {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX}, Tvv>9gS  
    {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX}, ffP]U4  
    {USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX}, ] (e ,J  
    {USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX}, gC$_yd6m L  
#endif ]L3U2H`7  
Q>5f@aN  
#ifdef CONFIG_TOUCHSCREEN_USB_PANJIT DOWWG!mx  
    {USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT}, +$C9@CZM9  
    {USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT}, F_079~bJ  
    {USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT}, & AK\Pw)  
    {USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT}, e66Ag}Sw|  
#endif LATizu  
uH\EV`@'  
#ifdef CONFIG_TOUCHSCREEN_USB_3M YP,,vcut  
    {USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M}, k| OM?\  
#endif {IOc'W-C#2  
JSUD$|RiJ  
#ifdef CONFIG_TOUCHSCREEN_USB_ITM 7;Ze>"W>  
    {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, DN%}OcpZ  
    {USB_DEVICE(0x16e3, 0xf9e9), .driver_info = DEVTYPE_ITM}, R+!U.:-yz  
#endif 7rD 8  
"G%S m")  
#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO Q0xGd(\  
    {USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO}, O _9r-Zt^  
#endif \PS]c9@,rc  
j \r GU){  
#ifdef CONFIG_TOUCHSCREEN_USB_GUNZE !SuflGx,q  
    {USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE}, j&Hui>~  
#endif 8Yc-3ozH  
U*+-#  
#ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 sqhMnDn[  
    {USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10}, QtfL'su:  
#endif k -G9'c~  
4D&L]eJ  
#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH YT-ua{ .^  
    {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, pj_W^,*/  
    {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, z#gebr~_\  
#endif bIm4s  
k2Cq9kQq  
#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK XW aa`q  
    {USB_DEVICE(0x1391, 0x1000), .driver_info = DEVTYPE_IDEALTEK}, T"99m^y  
#endif '=nmdqP  
e(wc [bv  
#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH |ufT)+:  
    {USB_DEVICE(0x0dfc, 0x0001), .driver_info = DEVTYPE_GENERAL_TOUCH}, YC;@^  
#endif u>;aQtK~  
wfO -bzdw  
#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP rhLhFN{h  
    {USB_DEVICE(0x08f2, 0x007f), .driver_info = DEVTYPE_GOTOP}, 0WzoI2Q  
    {USB_DEVICE(0x08f2, 0x00ce), .driver_info = DEVTYPE_GOTOP}, }Rz,}^B  
    {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP}, c) Eu(j\#  
#endif TeuZVy8a  
Foq3==*p  
#ifdef CONFIG_TOUCHSCREEN_USB_JASTEC Lu^uY7 ?}  
    {USB_DEVICE(0x0f92, 0x0001), .driver_info = DEVTYPE_JASTEC}, H, 3Bf  
#endif t{UVX%b  
W?SAa7+  
#ifdef CONFIG_TOUCHSCREEN_USB_E2I P, ZQ*Ju  
    {USB_DEVICE(0x1ac7, 0x0001), .driver_info = DEVTYPE_E2I}, ac\aH#J_nC  
#endif { 1~]}K2  
i;pg9Vw  
#ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC !Gnm<|.  
    {USB_DEVICE(0x14c8, 0x0003), .driver_info = DEVTYPE_ZYTRONIC}, a;dWM(;Kw  
#endif .WSn Y71  
n3?P8m$  
#ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB V=fu[#<@Ig  
    /* TC5UH */ L [PqEN\i  
    {USB_DEVICE(0x0664, 0x0309), .driver_info = DEVTYPE_TC45USB}, <mP_K^9c  
    /* TC4UM */ Ur 1k3  
    {USB_DEVICE(0x0664, 0x0306), .driver_info = DEVTYPE_TC45USB}, ,eTdQI;   
#endif T$mT;k  
pS-o*!\C.  
#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO rmBzLZ}  
    /* data interface only */ _*=4xmB.=  
    {USB_DEVICE_AND_INTERFACE_INFO(0x10f0, 0x2002, 0x0a, 0x00, 0x00), Zbl*U(KU?  
        .driver_info = DEVTYPE_NEXIO}, uxdB}H,  
    {USB_DEVICE_AND_INTERFACE_INFO(0x1870, 0x0001, 0x0a, 0x00, 0x00), V|A.M-XLv4  
        .driver_info = DEVTYPE_NEXIO}, oeKl\cgFx  
#endif `hY%HzV=  
BO}IN#  
    {} y}FG5'5$13  
}; }+lK'6  
Q65M(x+oy  
gLSI?  
/***************************************************************************** k6DJ(.n'%a  
* e2i Part xK0;saG#  
*/ iLQO .'{U  
m!zv t  
#ifdef CONFIG_TOUCHSCREEN_USB_E2I wY8Vc"  
static int e2i_init(struct usbtouch_usb *usbtouch) [jN Vk3  
{ D*46,>Tv  
    int ret; k~;~i)Eg  
    struct usb_device *udev = interface_to_usbdev(usbtouch->interface); Z}zka<y6K6  
j/O9LygB  
    ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), b"@-9ke5I  
                          0x01, 0x02, 0x0000, 0x0081, !M}-N  
                          NULL, 0, USB_CTRL_SET_TIMEOUT); Z  OAg7  
CBdr 1  
    dbg("%s - usb_control_msg - E2I_RESET - bytes|err: %d", Y#):1C1  
        __func__, ret); sMAH;'`!Eu  
    return ret; )w}'kih  
} ~Gc@#Msj  
y+wy<[u  
static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt) AvIheR  
{ P5dD&  
    int tmp = (pkt[0] << 8) | pkt[1]; .@r{Tq,%q8  
    dev->x  = (pkt[2] << 8) | pkt[3]; W|;`R{<I%  
    dev->y  = (pkt[4] << 8) | pkt[5]; s(5(zcBK  
s%#u)nw19  
    tmp = tmp - 0xA000; U4a8z<l$  
    dev->touch = (tmp > 0); p? +!*BZ  
    dev->press = (tmp > 0 ? tmp : 0); uFuH/(}K[  
"AqLR  
    return 1; j^Qk\(^#IV  
} <b4} B   
#endif C<QpUJ`k  
kVeY} 8  
"a _S7K  
/***************************************************************************** O d6'bO;G  
* eGalax part B\|^$z2  
*/ Z[RifqaBby  
V LeYO5'L  
#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX &H,UWtU+  
Vl(id_~_  
#ifndef MULTI_PACKET tT A  
#define MULTI_PACKET =%}(Dvjv  
#endif $^e_4]k  
S=L#8CID  
#define EGALAX_PKT_TYPE_MASK        0xFE %"E!E1_Sv  
#define EGALAX_PKT_TYPE_REPT        0x80 1_xkGc-z<  
#define EGALAX_PKT_TYPE_DIAG        0x0A 0aGauG[  
,rY}IwM w  
static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt) K^/.v<w  
{ v!S(T];)  
    if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) Q^Vch(`&P  
        return 0; _+~jZ]o N  
isnpSN"z  
    dev->x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F); ~T._ v;IT  
    dev->y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F); 8SiWAOQAL  
    dev->touch = pkt[0] & 0x01; :E|+[}|  
kDiR2K&  
    return 1; H?=[9?1wI5  
} o9{1_7K  
5}]gL  
static int egalax_get_pkt_len(unsigned char *buf, int len) /byF:iYI  
{ tsB}'+!v#  
    switch (buf[0] & EGALAX_PKT_TYPE_MASK) { *rm[\  
    case EGALAX_PKT_TYPE_REPT: m KKa0"  
        return 5; 2C_I3S ~U  
MqWM!v-M  
    case EGALAX_PKT_TYPE_DIAG: : T4ap_Ycq  
        if (len < 2) lP(<4mdP  
            return -1; .D=#HEshk  
hg^k lQD  
        return buf[1] + 2; li`  
    } :' !_PN  
} f!wQx b  
    return 0; 4 tt=u]:  
} %CrpUx  
#endif 'Te'wh=Y  
1(VskFtZF  
rN~V^k  
/***************************************************************************** )d5mZE!3  
* PanJit Part k~1{|HxrE  
*/ J B  !Q  
#ifdef CONFIG_TOUCHSCREEN_USB_PANJIT 4d-"kx3X  
static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt) %C >Win)g  
{ |y]8gL^  
    dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; Eo{js?1G_  
    dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; `b5pa`\4  
    dev->touch = pkt[0] & 0x01; qUNXT  
qS[nf>"  
    return 1; -fx$)d~  
} ]u >~:  
#endif n6GB2<y  
 [ "Jt2  
mLeK7?GL  
/***************************************************************************** w 5Yt mnP  
* 3M/Microtouch Part DIc -"5~  
*/ @yn1#E,  
#ifdef CONFIG_TOUCHSCREEN_USB_3M }xy[ &-dh  
0qo :M3  
#define MTOUCHUSB_ASYNC_REPORT          1 * @'N/W/8  
#define MTOUCHUSB_RESET                 7 >VvA&p71b  
#define MTOUCHUSB_REQ_CTRLLR_ID         10 <#:ey^q<  
oei2$uu  
static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) ]KRw[}z  
{ |VML.u:N  
    if (hwcalib_xy) { e:RgCDWL  
        dev->x = (pkt[4] << 8) | pkt[3]; m2PI^?|e  
        dev->y = 0xffff - ((pkt[6] << 8) | pkt[5]); V5HK6-T  
    } else { - |&&lxrwh  
        dev->x = (pkt[8] << 8) | pkt[7]; :pgpE0  
        dev->y = (pkt[10] << 8) | pkt[9]; rIWQD%Afm  
    } 5g;i{T/6~x  
    dev->touch = (pkt[2] & 0x40) ? 1 : 0; </jTWc'}  
Meo. V|1  
    return 1; I=9sTR)  
} 4Yya+[RY  
_ "H&  
static int mtouch_init(struct usbtouch_usb *usbtouch) p;9"0rj,z  
{ EHX/XM  
    int ret, i; QlK]2r9  
    struct usb_device *udev = interface_to_usbdev(usbtouch->interface); K)F6TvWv  
4b :q84  
    ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), (od9adSehV  
                          MTOUCHUSB_RESET, 0hM!#BU5K  
                          USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, XMw*4j2E  
                          1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); K+ @R [  
    dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", w>h\643  
        __func__, ret); x3Ze\N8w  
    if (ret < 0) \d}>@@U&  
        return ret; :"I!$_E'  
    msleep(150); S!+}\*  
6h:2,h pE  
    for (i = 0; i < 3; i++) { S<UWv@`U"  
        ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 2*ByVK  
                      MTOUCHUSB_ASYNC_REPORT, |58xR.S'g  
                      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 6#(==}Sm+  
                      1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); VH7nyqEM  
        dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",  6>&h9@  
            __func__, ret); =`Lci1#pu}  
        if (ret >= 0) Wg!JQRHtT  
            break; u@pimRVo  
        if (ret != -EPIPE) QSSA)  
            return ret; .6[7D  
    } xSy`VuSl  
kqQT^6S   
    /* Default min/max xy are the raw values, override if using hw-calib */ 6,a:s:$>}R  
    if (hwcalib_xy) { qvG@kuz8g5  
        input_set_abs_params(usbtouch->input, ABS_X, 0, 0xffff, 0, 0); ^c|_%/  
        input_set_abs_params(usbtouch->input, ABS_Y, 0, 0xffff, 0, 0); L(+I  
    } szC<ht?z  
$* hqF1Q  
    return 0; |Q?^Ba  
} }ej>uZVe<  
#endif t4v@d  
Xli$4 uL   
k{ ~0BK  
/***************************************************************************** wGg_ vAn  
* ITM Part <sli!rv  
*/ -+{<a!Nb  
#ifdef CONFIG_TOUCHSCREEN_USB_ITM o&ETs)n|  
static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt) .W s\%S  
{ E.eUd4XG  
    int touch; !QS j*)V#  
    /* H5>?{(m  
     * ITM devices report invalid x/y data if not touched. RG_.0'5=hc  
     * if the screen was touched before but is not touched any more D$Eq~VQ  
     * report touch as 0 with the last valid x/y data once. then stop y ~n1S~5cI  
     * reporting data until touched again. *WaqNMD[%  
     */ W`v$-o-  
    dev->press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F); SNtk1pG>  
->L>`<7(  
    touch = ~pkt[7] & 0x20; h?'~/@  
    if (!touch) { ]Bj2;<@y  
        if (dev->touch) { Z@,[a  
            dev->touch = 0; %z~=Jz^  
            return 1; je8 5G`{DC  
        } l}SHR|7<  
);;UA6CD  
        return 0; 5Mz:$5Tm  
    } Kf1NMin7  
!|\l*  
    dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F); 2F :8=_sA  
    dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F); AVi&cvhs  
    dev->touch = touch; i&YWutG  
=;"=o5g_  
    return 1; EKus0"|  
} Z+=M_{`{  
#endif -}3nIk<N  
Q_>W!)p Gz  
y*%uGG5  
/***************************************************************************** BU#3fPl  
* eTurboTouch part niqknqW<t  
*/ 6EeO\Qj{  
#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO Ej8g/{  
#ifndef MULTI_PACKET YPW UncV  
#define MULTI_PACKET H*e+ 2  
#endif S$ffTdRz  
static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) ;y_]w6|n  
{ u}b%-:-  
    unsigned int shift; *3)kr=x  
5th?m>  
    /* packets should start with sync */ B"8jEYT5  
    if (!(pkt[0] & 0x80)) ?lML+  
        return 0; Gk]ZP31u  
)k;;O7C k  
    shift = (6 - (pkt[0] & 0x03)); "}V_.I* +  
    dev->x = ((pkt[3] << 7) | pkt[4]) >> shift; 4*&k~0#t  
    dev->y = ((pkt[1] << 7) | pkt[2]) >> shift; P V:J>!]  
    dev->touch = (pkt[0] & 0x10) ? 1 : 0; U*b7 Pxq;  
T<-_#}.Hn  
    return 1; [Q+k2J_h  
} p6Z|)1O]  
3{f g3?  
static int eturbo_get_pkt_len(unsigned char *buf, int len) <{GVA0nr  
{ w@<II-9L)<  
    if (buf[0] & 0x80) Ek1c>s,t  
        return 5; #*:^\z_Jd  
    if (buf[0] == 0x01) aCI3Tx&2qT  
        return 3; 7B)1U_L0H  
    return 0; GbclR:G  
} x x4GP2  
#endif 7[w<v(Rc  
ZP5 !O[Ut  
r0 )ne|&Hp  
/***************************************************************************** u>n"FL 'e  
* Gunze part ~`C _B]3|  
*/ 'It8h$^j  
#ifdef CONFIG_TOUCHSCREEN_USB_GUNZE tM^4K r~o,  
static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt) w7o`B R  
{ >W;NMcN~  
    if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80)) P/dnH  
        return 0; tKeTHj;jO  
P/girce0  
    dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F); bD{k=jum  
    dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F); V@!)Pw  
    dev->touch = pkt[0] & 0x20; hg(<>_~  
Vh;zV Y  
    return 1; m$kQbPlatN  
} #5Z`Q^  
#endif {VE h@yn  
 7P7OTN  
/***************************************************************************** ;,C]WZ.w  
* DMC TSC-10/25 Part &J*M  
* %^pi  
* Documentation about the controller and it's protocol can be found at v$W[(  
*   http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf dy&UF,l6  
*   http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf Zn'tNt/  
*/ <aJQV)]\  
#ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 ~DI$O[KpR%  
||_hET  
/* supported data rates. currently using 130 */ w8UuwFG?<  
#define TSC10_RATE_POINT    0x50 M .b8 -`V  
#define TSC10_RATE_30        0x40 "|L" C+tE  
#define TSC10_RATE_50        0x41 t82'K@sq  
#define TSC10_RATE_80        0x42 { K]5[bMT  
#define TSC10_RATE_100        0x43 hlaN'j <C  
#define TSC10_RATE_130        0x44 >F7w]XH  
#define TSC10_RATE_150        0x45 i(^U<DW$  
]~KLdgru_  
/* commands */ }OL"38P  
#define TSC10_CMD_RESET        0x55 X,7y|tb  
#define TSC10_CMD_RATE        0x05 #Ub_m@@ 4  
#define TSC10_CMD_DATA1        0x01 pn gto  
rP3HR 5  
static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) o)AwM"  
{ $'4 98%K2  
    struct usb_device *dev = interface_to_usbdev(usbtouch->interface); \=A A,Il  
    int ret = -ENOMEM; \ ;npdFy  
    unsigned char *buf; DK)W ,z|  
jO-?t9^  
    buf = kmalloc(2, GFP_NOIO); )U?_&LY)[M  
    if (!buf) ZgP%sF  
        goto err_nobuf; CJBf5I3  
    /* reset */ N1c=cZDV  
    buf[0] = buf[1] = 0xFF; _\ToA9m  
    ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), &X$T "Dp  
                          TSC10_CMD_RESET, &riGzU]  
                          USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, }}JMwT  
                          0, 0, buf, 2, USB_CTRL_SET_TIMEOUT); elOeXYO0  
    if (ret < 0) %9J@##+  
        goto err_out; Az`Aa0h]7  
    if (buf[0] != 0x06) { vk& gR  
        ret = -ENODEV; <v:VA!]  
        goto err_out; 2 |s ohF  
    } 6pt_cpbR  
Tlsh[@Q  
    /* set coordinate output rate */ jwDlz.sW!  
    buf[0] = buf[1] = 0xFF; q@|+`>h  
    ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), *qd:f!Q3  
                          TSC10_CMD_RATE, jT{T#_  
                          USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, P[nc8z[  
                          TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); {ez $kz  
    if (ret < 0) +I3jI <  
        goto err_out; =ejj@c  
    if ((buf[0] != 0x06) && (buf[0] != 0x15 || buf[1] != 0x01)) { 94u{k1d x  
        ret = -ENODEV; /4:bx#;A  
        goto err_out; >lQo _p(;  
    } ,=:K&5mCv  
9y7N}T6  
    /* start sending data */ iC gZ3M]  
    ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), 'cW^S7  
                          TSC10_CMD_DATA1, 06&J!,p :  
                          USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 3S0.sU~_U  
                          0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); PsY![CPrW  
err_out: 9u B?-.  
    kfree(buf); .DCHc,DxA  
err_nobuf: d7OygDb<  
    return ret; [ GLH8R  
} 25Dl4<-Z  
f%Q{}fC{*  
Kc/1LeAik  
static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 4xy\  
{ ^X=Q{nB  
    dev->x = ((pkt[2] & 0x03) << 8) | pkt[1]; i"2OsGT  
    dev->y = ((pkt[4] & 0x03) << 8) | pkt[3]; 37#&:[w>  
    dev->touch = pkt[0] & 0x01; )pB#7aEw  
M tN>5k c  
    return 1; TR"C<&y$j  
} vl"w,@V7  
#endif bjZJP\6  
Y[ G_OoU  
'%N?r,x C  
/***************************************************************************** 4"d,=P.{  
* IRTOUCH Part h [TwaR  
*/ wu41Mz7  
#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH =$>=EBH,cm  
static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) SQp|  
{ -9Q(3$}  
    dev->x = (pkt[3] << 8) | pkt[2]; cG|fau<G  
    dev->y = (pkt[5] << 8) | pkt[4];  *}?[tR5  
    dev->touch = (pkt[1] & 0x03) ? 1 : 0; \Z-th,t  
3uL f0D  
    return 1; O[@!1SKT0  
} Ox3=1M0  
#endif /<LZt<K  
uYJS=NGNA  
/***************************************************************************** b?H"/Mu.  
* ET&T TC5UH/TC4UM part JGs: RD'  
*/ 87 Z[0>  
#ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB Q@D7 \<t  
static int tc45usb_read_data(struct usbtouch_usb *dev, unsigned char *pkt) ;kFD769DLw  
{ ' \JE>#  
    dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; )M0YX?5A R  
    dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; bLqy7S9x  
    dev->touch = pkt[0] & 0x01; "<,lqIqA;  
Y },E3<  
    return 1; S?J!.(  
} Y:^hd809  
#endif %iyc1]w{  
=i/Df ?  
/***************************************************************************** uP~,]ci7  
* IdealTEK URTC1000 Part !_QI<=X  
*/ ^y+k6bE  
#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK pUIN`ya[[  
#ifndef MULTI_PACKET u3T-U_:jSV  
#define MULTI_PACKET 7?P'f3)fG  
#endif |IgR1kp+.  
static int idealtek_get_pkt_len(unsigned char *buf, int len) %~rEJB@{  
{ lriezI  
    if (buf[0] & 0x80) "LBMpgpU  
        return 5; i3-5~@M  
    if (buf[0] == 0x01) &<&tdShI  
        return len; c&['T+X  
    return 0; \CB^9-V3  
} hkK>h  
`3TR`,=  
static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt) 9~SPoR/_0  
{ {K^5q{u  
    switch (pkt[0] & 0x98) { qv!(In>u  
    case 0x88: )nUdU = m  
        /* touch data in IdealTEK mode */ LdUz;sb  
        dev->x = (pkt[1] << 5) | (pkt[2] >> 2); }%g[1 #%(  
        dev->y = (pkt[3] << 5) | (pkt[4] >> 2); dOjly,!  
        dev->touch = (pkt[0] & 0x40) ? 1 : 0; ]_KWN$pd  
        return 1; vNO&0~  
d$ouH%^cGu  
    case 0x98: >A Ep\ *  
        /* touch data in MT emulation mode */ hf`y_H+\7  
        dev->x = (pkt[2] << 5) | (pkt[1] >> 2); cVi_#9u"  
        dev->y = (pkt[4] << 5) | (pkt[3] >> 2); ,NO[Piok  
        dev->touch = (pkt[0] & 0x40) ? 1 : 0; "4b{YWv  
        return 1; #MC#K{Xd  
z)Rkd0/X  
    default: GM|& ,}  
        return 0; ,&[o:jTk  
    }  \XDiw~0  
} kZ9Gl!g  
#endif E|=x+M1sH  
g=:o'W$@  
/***************************************************************************** SSe;&Jk2d  
* General Touch Part V&zeC/xSq  
*/ 8mX!mYO3c  
#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH ko%mZ0Y  
static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) [^"}jbn/  
{ G|cjI*  
    dev->x = (pkt[2] << 8) | pkt[1]; @&jR^`Y.  
    dev->y = (pkt[4] << 8) | pkt[3]; fTxd8an{  
    dev->press = pkt[5] & 0xff; pH~\~  
    dev->touch = pkt[0] & 0x01; z~{08M7  
wgz]R  
    return 1; xQR/Xp!h  
} P| NGAd  
#endif 8vx ca]DcV  
w1Bkz\95  
/***************************************************************************** GcM1*)$ 4  
* GoTop Part {$S"S j  
*/ r] /Ej!|  
#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP 0f4 y"9m  
static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt) )xp3 ElH  
{ VgPlIIHh5  
    dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; /&6{}n  
    dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; D#nHg  
    dev->touch = pkt[0] & 0x01; 4s{=/,f  
|AvPg  
    return 1; `;mgJD  
} y[J9"k(@  
#endif uQG|r)  
#( .G;e;w  
/***************************************************************************** @tT`s^e  
* JASTEC Part Y`g O:d8  
*/ fhi}x(  
#ifdef CONFIG_TOUCHSCREEN_USB_JASTEC <*vR_?!  
static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt) hy/ g*>  
{ =1Plu5  
    dev->x = ((pkt[0] & 0x3f) << 6) | (pkt[2] & 0x3f); k;qS1[a  
    dev->y = ((pkt[1] & 0x3f) << 6) | (pkt[3] & 0x3f); <v1H1'gv  
    dev->touch = (pkt[0] & 0x40) >> 6; a>C;HO  
oVK?lQ~y  
    return 1; <ppdy,j:  
} a3n Wt  
#endif p$"~v A .  
(ot,CpI(I  
/***************************************************************************** 7,)E1dx -V  
* Zytronic Part 0}GO$%l  
*/ +<$(ez  
#ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC N_G&nw  
static int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt) o^@#pU <  
{ j6s j2D  
    switch (pkt[0]) { ?* ~4~ZE E  
    case 0x3A: /* command response */ JbEEI(Q>g  
        dbg("%s: Command response %d", __func__, pkt[1]); 23|JgKuA  
        break; "d}']M?-h  
Mn5(Kw?o2J  
    case 0xC0: /* down */ P%B|HnG^  
        dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); HRTNIx  
        dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); Tkr~)2,(I!  
        dev->touch = 1; z<Z0/a2'1  
        dbg("%s: down %d,%d", __func__, dev->x, dev->y); N75U.;U0  
        return 1; sudh=_+>  
WiH8j$;xu  
    case 0x80: /* up */ F=&,=r' Q8  
        dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); w#2apaz  
        dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); C;ab-gh  
        dev->touch = 0; /#5rt&q  
        dbg("%s: up %d,%d", __func__, dev->x, dev->y); qo:Zc`t(R  
        return 1; Dj= {%  
$Ptl&0MN%  
    default: J+CGhk  
        dbg("%s: Unknown return %d", __func__, pkt[0]); 3N]ushMO  
        break; q'fOlq  
    } =ZS Yg K  
<IU   
    return 0; ipG 0ie+  
} 'RwfW|~6  
#endif =Crl{Ax  
bv41et+Kb  
/***************************************************************************** =H: N!!:  
* NEXIO Part |5(CzXR]  
*/ 2K3j3|T  
#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO Q@p' nE,  
m, +E5^  
#define NEXIO_TIMEOUT    5000 3]iw3M  
#define NEXIO_BUFSIZE    1024 ^0"fPG`  
#define NEXIO_THRESHOLD    50 Ww~C[8q  
lB_4jc  
struct nexio_priv { `4ga~Ch  
    struct urb *ack; Bd*Ok]  
    unsigned char *ack_buf; |0^IX   
}; E Id>%0s5  
pVl7] _=m  
struct nexio_touch_packet { /g0' +DP  
    u8    flags;        /* 0xe1 = touch, 0xe1 = release */ io"NqR#"v  
    __be16    data_len;    /* total bytes of touch data */ x`2dN/wDhf  
    __be16    x_len;        /* bytes for X axis */ (7_ezWSl>  
    __be16    y_len;        /* bytes for Y axis */ .R)Ho4CE  
    u8    data[]; j!L7r'AV5  
} __attribute__ ((packed)); 6wOj,}2Mn  
<`q-#-V@  
static unsigned char nexio_ack_pkt[2] = { 0xaa, 0x02 }; { zL4dJw  
static unsigned char nexio_init_pkt[4] = { 0x82, 0x04, 0x0a, 0x0f }; Dd OK&  
)#Ecm<.^  
static void nexio_ack_complete(struct urb *urb) -0'< 7FSQ  
{ :\mdVS!o  
} /2r&ga&  
8u*Q^-fpo0  
static int nexio_alloc(struct usbtouch_usb *usbtouch) $Q|6W &?[;  
{ }If,O  
    struct nexio_priv *priv; )+)qFGVz  
    int ret = -ENOMEM; #cikpHLXG  
*Qngx  
    usbtouch->priv = kmalloc(sizeof(struct nexio_priv), GFP_KERNEL); Y3V2}  
    if (!usbtouch->priv) !!6@r|.  
        goto out_buf; 2#R0Bd  
G=Xas"|  
    priv = usbtouch->priv; ](+u'8  
3nq4Y'  
    priv->ack_buf = kmemdup(nexio_ack_pkt, sizeof(nexio_ack_pkt), #VZ-gy4$\B  
                GFP_KERNEL); < A`srmS?  
    if (!priv->ack_buf) (e 2.Ru  
        goto err_priv; #pD=TMefC  
}PMlG  
    priv->ack = usb_alloc_urb(0, GFP_KERNEL); fTy{`}>  
    if (!priv->ack) { 8M4GforP  
        dbg("%s - usb_alloc_urb failed: usbtouch->ack", __func__); 3E@ &  
        goto err_ack_buf; H_iQR9Ak7  
    } AAi4} 8+\  
%@I= $8j  
    return 0; +>tSO!}[  
* P12d  
err_ack_buf: (^ J2(  
    kfree(priv->ack_buf); wG 5H^>6u>  
err_priv: eH;{Ln  
    kfree(priv); | m#"  
out_buf: .%\R L/  
    return ret; `'rvDaP  
} t,5AoK/NL9  
0sq?>$~Kc*  
static int nexio_init(struct usbtouch_usb *usbtouch) f1\mE~#}  
{ CT.hBz -S  
    struct usb_device *dev = interface_to_usbdev(usbtouch->interface); w\JTMS$  
    struct usb_host_interface *interface = usbtouch->interface->cur_altsetting; 4f213h  
    struct nexio_priv *priv = usbtouch->priv; ?R@u'4yK  
    int ret = -ENOMEM; On;7  
    int actual_len, i; L>`inrpz=w  
    unsigned char *buf; :9|CpC`.  
    char *firmware_ver = NULL, *device_name = NULL;  o^d  
    int input_ep = 0, output_ep = 0; ;%/}(&E2  
q' t"  
    /* find first input and output endpoint */ $B )jSxSy  
    for (i = 0; i < interface->desc.bNumEndpoints; i++) { nI`9|W  
        if (!input_ep && JGlp7wro  
            usb_endpoint_dir_in(&interface->endpoint.desc)) dY?>:ce  
            input_ep = interface->endpoint.desc.bEndpointAddress; Z(ToemF)hi  
        if (!output_ep && S2V+%Z _J  
            usb_endpoint_dir_out(&interface->endpoint.desc)) Gbb*p+ (  
            output_ep = interface->endpoint.desc.bEndpointAddress; !imjfkG  
    } 1?y QjW,  
    if (!input_ep || !output_ep) q$B|a5a?  
        return -ENXIO; _]kw |[)  
\uOR1z  
    buf = kmalloc(NEXIO_BUFSIZE, GFP_NOIO); .V{y9e+  
    if (!buf) +qa^K%K  
        goto out_buf; a^)@ }4  
;C5 J ^xHI  
    /* two empty reads */ RPTIDA))  
    for (i = 0; i < 2; i++) { NV18~5#</  
        ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep), Zx|VOl,;  
                   buf, NEXIO_BUFSIZE, &actual_len, l=>FoJf!*<  
                   NEXIO_TIMEOUT);  )jH|j  
        if (ret < 0) fp$U%uj  
            goto out_buf; i7O8f^|  
    } jGn2Q L  
`G>BvS5h  
    /* send init command */ -pN'r/$3V  
    memcpy(buf, nexio_init_pkt, sizeof(nexio_init_pkt)); &bwI7cO  
    ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, output_ep), _lZWy$rm%  
               buf, sizeof(nexio_init_pkt), &actual_len, NvJ}|w,Z  
               NEXIO_TIMEOUT); e~G um  
    if (ret < 0) z#srgyLt  
        goto out_buf; z4s{a(Tsd  
o+T, O+i  
    /* read replies */ s,8g^aF4  
    for (i = 0; i < 3; i++) { MgQb" qx  
        memset(buf, 0, NEXIO_BUFSIZE); _vOSOnU  
        ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep), wN$u^]  
                   buf, NEXIO_BUFSIZE, &actual_len, kO' NT:  
                   NEXIO_TIMEOUT); e8hwXz  
        if (ret < 0 || actual_len < 1 || buf[1] != actual_len) .10$n*  
            continue; &BRi& &f  
        switch (buf[0]) { ,M9Hdm  
        case 0x83:    /* firmware version */ 6z1>(Za7>  
            if (!firmware_ver) Z:<6Ck  
                firmware_ver = kstrdup(&buf[2], GFP_NOIO); +`~kt4W  
            break; \r&9PkHWo  
        case 0x84:    /* device name */ b[my5O l  
            if (!device_name) a>)|SfsE  
                device_name = kstrdup(&buf[2], GFP_NOIO); b^&nr[DC  
            break; 7HEUmKb"  
        } VuA)Ye  
    } LVNJlRK  
XjJ[7"hs*  
    printk(KERN_INFO "Nexio device: %s, firmware version: %s\n", l'#a2Pl  
           device_name, firmware_ver); =.6JvX<d1*  
u\}"l2 r  
    kfree(firmware_ver); y (=$z/  
    kfree(device_name); S!.H _=z%p  
gP>`DPgb^  
    usb_fill_bulk_urb(priv->ack, dev, usb_sndbulkpipe(dev, output_ep), %gV~e@|  
              priv->ack_buf, sizeof(nexio_ack_pkt), cDLjjK7:   
              nexio_ack_complete, usbtouch); eW;0{P  
    ret = 0; [UYE.$Y#(  
Q1u/QA:z7  
out_buf: ,&rHBNS  
    kfree(buf); zr1A4%S"  
    return ret; 1zJ)x?  
} F@kd[>/[  
f]]UNS$AYQ  
static void nexio_exit(struct usbtouch_usb *usbtouch) OVU+V 0w1a  
{ N&-J,p~  
    struct nexio_priv *priv = usbtouch->priv; 'mE!,KeS;  
>Ef{e6  
    usb_kill_urb(priv->ack); &265 B_'D  
    usb_free_urb(priv->ack); U9:I"f,  
    kfree(priv->ack_buf); .WT ar9e#  
    kfree(priv); x10u?@  
} @hj5j;NHK  
^U]B&+m  
static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) NT<vs"<B  
{ <%:,{u6  
    struct nexio_touch_packet *packet = (void *) pkt; \LQ54^eB  
    struct nexio_priv *priv = usbtouch->priv; v0'`K 5M  
    unsigned int data_len = be16_to_cpu(packet->data_len); si`h(VD9w  
    unsigned int x_len = be16_to_cpu(packet->x_len); @0U={qX  
    unsigned int y_len = be16_to_cpu(packet->y_len); hScC< =W  
    int x, y, begin_x, begin_y, end_x, end_y, w, h, ret; #m36p+U  
+:#UU;W  
    /* got touch data? */ xHi.N*~D  
    if ((pkt[0] & 0xe0) != 0xe0) &u~#bDh  
        return 0; ;A;FR3=)  
,K~r':ht  
    if (data_len > 0xff) ><3!J+<?  
        data_len -= 0x100; rJ)8KY>  
    if (x_len > 0xff) ZBl!7_[_  
        x_len -= 0x80; U@<]>.$  
xJ|_R,>.H  
    /* send ACK */ ="__*J#nze  
    ret = usb_submit_urb(priv->ack, GFP_ATOMIC); Z@ QJ5F1y  
WHKe\8zWq  
    if (!usbtouch->type->max_xc) { <X ~P62<  
        usbtouch->type->max_xc = 2 * x_len; K *xca(6  
        input_set_abs_params(usbtouch->input, ABS_X, XX[CTh?O%  
                     0, usbtouch->type->max_xc, 0, 0); XCUU(H  
        usbtouch->type->max_yc = 2 * y_len; #/LU@+  
        input_set_abs_params(usbtouch->input, ABS_Y, yHjuT+/wM,  
                     0, usbtouch->type->max_yc, 0, 0); 8a,pDE  
    } ]c~W$h+F  
    /* b_rHt s  
     * The device reports state of IR sensors on X and Y axes. U3b&/z|b?  
     * Each byte represents "darkness" percentage (0-100) of one element. RA$q{$arb  
     * 17" touchscreen reports only 64 x 52 bytes so the resolution is low. 5><KTya?=  
     * This also means that there's a limited multi-touch capability but 1&#qq*{  
     * it's disabled (and untested) here as there's no X driver for that. o%sx(g=q6  
     */ n>\2_$uDI  
    begin_x = end_x = begin_y = end_y = -1; mq6TwM  
    for (x = 0; x < x_len; x++) { [ F7ru4"{  
        if (begin_x == -1 && packet->data[x] > NEXIO_THRESHOLD) { 9A!B|s  
            begin_x = x; "z9 p(|oZ  
            continue; q3}WO] TBj  
        } 8qWN~Gk1p{  
        if (end_x == -1 && begin_x != -1 && packet->data[x] < NEXIO_THRESHOLD) { \<0xg[  
            end_x = x - 1; =Cg1I\  
            for (y = x_len; y < data_len; y++) { O#72h]  
                if (begin_y == -1 && packet->data[y] > NEXIO_THRESHOLD) { %E*Q0/  
                    begin_y = y - x_len; tv'=xDCp  
                    continue; lNba[;_  
                } R8C#D B  
                if (end_y == -1 && iM(Q-%HP_  
                    begin_y != -1 && packet->data[y] < NEXIO_THRESHOLD) { $i]G'fj  
                    end_y = y - 1 - x_len; =u 3YRqz  
                    w = end_x - begin_x; p`/c&}  
                    h = end_y - begin_y; "^NsbA+  
#if 0 jN T+?2  
                    /* multi-touch */ RAB'%CY4  
                    input_report_abs(usbtouch->input, 2pmqP-pKd  
                            ABS_MT_TOUCH_MAJOR, max(w,h)); (L'|n *Cr  
                    input_report_abs(usbtouch->input, 8"yZS)09  
                            ABS_MT_TOUCH_MINOR, min(x,h)); WO!'("  
                    input_report_abs(usbtouch->input, =>htX(k}  
                            ABS_MT_POSITION_X, 2*begin_x+w); #$ooV1E  
                    input_report_abs(usbtouch->input, 5N(OW:M  
                            ABS_MT_POSITION_Y, 2*begin_y+h); _:7:ixN[Ie  
                    input_report_abs(usbtouch->input, E(g$f.9  
                            ABS_MT_ORIENTATION, w > h); CWa~~h<r-  
                    input_mt_sync(usbtouch->input); P^[y~I#{  
#endif UAe8Ct=YJ  
                    /* single touch */ L25%KGg' o  
                    usbtouch->x = 2 * begin_x + w; 4~ i?xo=;v  
                    usbtouch->y = 2 * begin_y + h; bZWdd6  
                    usbtouch->touch = packet->flags & 0x01; 7(l>Ck3B#  
                    begin_y = end_y = -1; = :BTv[lv  
                    return 1; Yan}H}Oq  
                } ;LqpX!Pi f  
            } 2Og<e|  
            begin_x = end_x = -1; kwUy^"O  
        } _"[Ls?tRX  
H*HL:o-[  
    } "/nbcQ*s*E  
    return 0; NOFuX9/'w  
} SFR<T  
#endif -CLBf'a  
b} FhC"'i  
BlfadM;  
/***************************************************************************** y}1Pc*  
* the different device descriptors Gj^*  
*/ N;gY5;0m  
#ifdef MULTI_PACKET o[)*Y`xq<w  
static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, >!Dp'6  
                   unsigned char *pkt, int len); pGd@%/]AO  
#endif "p]!="\  
V{UY_ e8W  
static struct usbtouch_device_info usbtouch_dev_info[] = { b3Q k;yz  
#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX M $f6. j  
    [DEVTYPE_EGALAX] = { 3JEg3|M(  
        .min_xc        = 0x0, 3,?LpdTS  
        .max_xc        = 0x07ff, Ot`znJU@  
        .min_yc        = 0x0, Xo$SQ0K  
        .max_yc        = 0x07ff, 4W#DLip9  
        .rept_size    = 16, XAZPbvG|$  
        .process_pkt    = usbtouch_process_multi, -9Dr;2\  
        .get_pkt_len    = egalax_get_pkt_len, >t{-_4Yv?  
        .read_data    = egalax_read_data, {gh<SZsE  
    }, 9yz@hdG  
#endif RM;Uq >l  
!e:_$$j  
#ifdef CONFIG_TOUCHSCREEN_USB_PANJIT  +;-ZU  
    [DEVTYPE_PANJIT] = { 0n}v"61q  
        .min_xc        = 0x0, z69u@  
        .max_xc        = 0x0fff, u\;d^A  
        .min_yc        = 0x0, +)LCYDRV7  
        .max_yc        = 0x0fff, .N7<bt@~)  
        .rept_size    = 8, C1>zwU_zo  
        .read_data    = panjit_read_data, #p ;O3E@  
    }, UA|\D]xe  
#endif H: S<O%f  
3N 5@<:2`  
#ifdef CONFIG_TOUCHSCREEN_USB_3M v*OV\h.  
    [DEVTYPE_3M] = { iI>7I<_  
        .min_xc        = 0x0, HX)]@qL  
        .max_xc        = 0x4000, TF9A4  
        .min_yc        = 0x0, bB>.dC  
        .max_yc        = 0x4000, N<ux4tz  
        .rept_size    = 11, OADW;fj  
        .read_data    = mtouch_read_data, Y'5(exW  
        .init        = mtouch_init, s/B_  
    }, ~KRS0 ^  
#endif @]]&^ 7  
7377g'jL  
#ifdef CONFIG_TOUCHSCREEN_USB_ITM $s4.Aj  
    [DEVTYPE_ITM] = { J ?EDz,  
        .min_xc        = 0x0, IJt'[&D  
        .max_xc        = 0x0fff, 9ln=f=  
        .min_yc        = 0x0, a#k7 aOT0  
        .max_yc        = 0x0fff, 3H0B+F2XQ  
        .max_press    = 0xff, no W]E}nN  
        .rept_size    = 8, z1]nC]2  
        .read_data    = itm_read_data, @%G?Nht]o  
    }, ]-9w'K d  
#endif .rITzwgB  
<_ENC>NP  
#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO jRd$Vt  
    [DEVTYPE_ETURBO] = { jJ-C\ v  
        .min_xc        = 0x0, oR,6esA+6n  
        .max_xc        = 0x07ff, Wa7wV 9  
        .min_yc        = 0x0, T2/:C7zL  
        .max_yc        = 0x07ff, PZ`11#bbm  
        .rept_size    = 8, Q4hY\\Hi  
        .process_pkt    = usbtouch_process_multi, %B( rW?p&  
        .get_pkt_len    = eturbo_get_pkt_len, J8i,[,KcE  
        .read_data    = eturbo_read_data, &x[7?Y L  
    }, pB#I_?(  
#endif UfPHV%Wd  
#\ `kg#&  
#ifdef CONFIG_TOUCHSCREEN_USB_GUNZE N'WC!K.e  
    [DEVTYPE_GUNZE] = { [`oVMR  
        .min_xc        = 0x0, [8^q3o7n  
        .max_xc        = 0x0fff, CGzu(@dd\  
        .min_yc        = 0x0, 2aX*|DGpw  
        .max_yc        = 0x0fff, #4b]j".P!n  
        .rept_size    = 4, m./PRV1$x  
        .read_data    = gunze_read_data, \hZ%NL j  
    }, 0#Lmajs  
#endif %T\hL\L?  
! xG*W6IT  
#ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 fggs ;Le  
    [DEVTYPE_DMC_TSC10] = { #CaPj:>[  
        .min_xc        = 0x0, 6o7t eX  
        .max_xc        = 0x03ff, (S?Y3l|  
        .min_yc        = 0x0, ~mARgv  
        .max_yc        = 0x03ff, P!E2.K,  
        .rept_size    = 5, F-,chp  
        .init        = dmc_tsc10_init, (/N&_r4x  
        .read_data    = dmc_tsc10_read_data, J-Tiwl  
    }, *; ]}`r  
#endif g+4y^x(X@1  
(or"5}\6-  
#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH y:}qoT_.  
    [DEVTYPE_IRTOUCH] = { * dw.Ug  
        .min_xc        = 0x0, xsn=Ji2 F  
        .max_xc        = 0x0fff, iGu%_-S  
        .min_yc        = 0x0, 8"9&x} tl-  
        .max_yc        = 0x0fff, O"+0 b|  
        .rept_size    = 8, C_kuW+H  
        .read_data    = irtouch_read_data, [GI~ &  
    }, 8ZVQM7O  
#endif n)98NSVDbT  
&.\7='$F  
#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK xBA"w:<  
    [DEVTYPE_IDEALTEK] = { DkEv1]6JI_  
        .min_xc        = 0x0, HyU:BW;  
        .max_xc        = 0x0fff, +q '1P}e  
        .min_yc        = 0x0, B(++*#T!^m  
        .max_yc        = 0x0fff, ,M;9|kE*  
        .rept_size    = 8, LK~aLa5wG  
        .process_pkt    = usbtouch_process_multi, v62_VT2v  
        .get_pkt_len    = idealtek_get_pkt_len, YE{ [f@i0  
        .read_data    = idealtek_read_data, /oHCV0!0  
    }, 3WJk04r  
#endif GQn:lu3j:  
p@su:B2Rl  
#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH kFWwz^x  
    [DEVTYPE_GENERAL_TOUCH] = { eMC^ORdY  
        .min_xc        = 0x0, 3TF_$bd{  
        .max_xc        = 0x7fff, \X:e9~  
        .min_yc        = 0x0, oNAnJ+_  
        .max_yc        = 0x7fff, 5'I+%66?h$  
        .rept_size    = 7, q[a\a7U z  
        .read_data    = general_touch_read_data, fx5S2%f^  
    }, j)mU`b_  
#endif {,Q )D$i  
lD0-S0i  
#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP #5@(^N5p`  
    [DEVTYPE_GOTOP] = { 6iyl8uL0J  
        .min_xc        = 0x0, }} =n]_f  
        .max_xc        = 0x03ff, I?3b}#&V9  
        .min_yc        = 0x0, <|}Z6Ti  
        .max_yc        = 0x03ff, pT]hPuC  
        .rept_size    = 4, Qh1pX}X  
        .read_data    = gotop_read_data, {r&mNbz  
    }, '" "v7  
#endif RW. qw4  
cERIj0~  
#ifdef CONFIG_TOUCHSCREEN_USB_JASTEC {5E8eQ  
    [DEVTYPE_JASTEC] = { 6(bN*.  
        .min_xc        = 0x0, #:gd9os :  
        .max_xc        = 0x0fff, mrP48#Y+l  
        .min_yc        = 0x0,  j%Au0k  
        .max_yc        = 0x0fff, o+E~iC u5  
        .rept_size    = 4, _-_iw&F  
        .read_data    = jastec_read_data, gu(:'5cX  
    }, 2d[q5p  
#endif \34vE@V*  
NZvgkci_(u  
#ifdef CONFIG_TOUCHSCREEN_USB_E2I f,TW|Y'{g  
    [DEVTYPE_E2I] = { >zW2w2O3  
        .min_xc        = 0x0, ^Spu/55_  
        .max_xc        = 0x7fff, s|Mo3_>  
        .min_yc        = 0x0, )j36Y =r3  
        .max_yc        = 0x7fff, ?Ij(B}D  
        .rept_size    = 6, 'v6@5t19j  
        .init        = e2i_init, *#Cx-J  
        .read_data    = e2i_read_data, _`udd)Y2  
    }, 6!m#;8 4  
#endif 2LtDS?)@  
3CoZ2  
#ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC I@cw=_EQL  
    [DEVTYPE_ZYTRONIC] = { !/XNpQP  
        .min_xc        = 0x0, gZ,h9 5'  
        .max_xc        = 0x03ff, vhfjZ  
        .min_yc        = 0x0, 6Rn?pe^  
        .max_yc        = 0x03ff, Fc5.?X-  
        .rept_size    = 5, YhN<vZ}U!~  
        .read_data    = zytronic_read_data, MbRTOH  
        .irq_always     = true, F06o-xH=  
    }, + `|A/w  
#endif duY?LJ@g  
4Hj)Av <O(  
#ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB 5qz,FKx5  
    [DEVTYPE_TC45USB] = { GTP'js  
        .min_xc        = 0x0, %F 2h C x  
        .max_xc        = 0x0fff, [Yt{h9  
        .min_yc        = 0x0, # rkq ?:Q  
        .max_yc        = 0x0fff, qIi \[Ugh  
        .rept_size    = 5, :<J7g`f  
        .read_data    = tc45usb_read_data, Z =+Z96  
    }, FH,]'  
#endif Y2r}W3F=  
>C|pY6  
#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO su%(!XJQpg  
    [DEVTYPE_NEXIO] = { ` 2W^Ui,4  
        .rept_size    = 1024, f{P1.?a  
        .irq_always    = true, k>($[;k|b  
        .read_data    = nexio_read_data, 5#DMizv6  
        .alloc        = nexio_alloc, eYUb>M)  
        .init        = nexio_init, 1h$?,  
        .exit        = nexio_exit, V`I4"}M1  
    }, w2DC5ei'  
#endif :21d  
}; =^4Z]d  
28!C#.(h  
lFzVd N  
/***************************************************************************** {kpF etXt?  
* Generic Part d0(zB5'}  
*/ 4IeCb?  
static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, E8PDIjp  
                                 unsigned char *pkt, int len) xo[o^go  
{ `Lr], >aG  
    struct usbtouch_device_info *type = usbtouch->type; 2%%\jlT_  
/v 8"i^;}  
    if (!type->read_data(usbtouch, pkt)) p'R<yB)V  
            return; >d + }$dB  
hXTfmFy{n  
    input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch); e5' I W__  
\,#$,dUXD  
    if (swap_xy) { 1/}H 0\9'  
        input_report_abs(usbtouch->input, ABS_X, usbtouch->y); 6w^P{%ul  
        input_report_abs(usbtouch->input, ABS_Y, usbtouch->x); )~U1sW&t  
    } else { Y(PCc}/\  
        input_report_abs(usbtouch->input, ABS_X, usbtouch->x); *#=Ijr~  
        input_report_abs(usbtouch->input, ABS_Y, usbtouch->y); KQ\K :#  
    } CHgip&(.F  
    if (type->max_press) Ge q]wv8  
        input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press); P 9?cp{*  
    input_sync(usbtouch->input); *tXyd<_Hd  
} RAW;ze*"  
*vb"mB  
0S{23L4C  
#ifdef MULTI_PACKET CWdsOS=  
static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, U=n7RPw  
                                   unsigned char *pkt, int len) w!f2~j~  
{ c1f"z1Z  
    unsigned char *buffer; ;(i6 X)  
    int pkt_len, pos, buf_len, tmp; H>TO8;5(  
#mQ@4k9i  
    /* process buffer */ ',EI[ ]+  
    if (unlikely(usbtouch->buf_len)) { }A3/(  
        /* try to get size */ FGV L[\  
        pkt_len = usbtouch->type->get_pkt_len( fL*7u\m:  
                usbtouch->buffer, usbtouch->buf_len); 2) X#&IE  
s=8H< 'l  
        /* drop? */ [^hW>O=@TN  
        if (unlikely(!pkt_len)) `5Y*) q  
            goto out_flush_buf; /!5Wd(:  
6 U.Jaai:  
        /* need to append -pkt_len bytes before able to get size */ 6GxLaI  
        if (unlikely(pkt_len < 0)) {  t`o"K  
            int append = -pkt_len; noWF0+ %  
            if (unlikely(append > len)) .QvD603%5  
                   append = len; )9eI o&Nl  
            if (usbtouch->buf_len + append >= usbtouch->type->rept_size) +CSpL2@  
                goto out_flush_buf; xi (@\A  
            memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append); Hx.|5n,5  
            usbtouch->buf_len += append; #h;   
2`=jKt  
            pkt_len = usbtouch->type->get_pkt_len( io#}z4"'qY  
                    usbtouch->buffer, usbtouch->buf_len); zhn ?;Fi  
            if (pkt_len < 0) 0Ui.nz j  
                return; `J.,dqGb  
        } ^'X I%fEf  
=KPmZ,/w  
        /* append */ ;<+efYmyc  
        tmp = pkt_len - usbtouch->buf_len; w'@gzK  
        if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size) l(>6Yq  
            goto out_flush_buf; Pe%[d[ k  
        memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp); qTuR[(  
        usbtouch_process_pkt(usbtouch, usbtouch->buffer, pkt_len); DGvuo 8  
^to*ET{0  
        buffer = pkt + tmp; r^ r+h[V  
        buf_len = len - tmp; + <bj}"  
    } else { k(ouE|B  
        buffer = pkt; !gX xM,R  
        buf_len = len; H{}&|;0  
    } Myc-lCE  
<nk|Z'G E  
    /* loop over the received packet, process */ d.&_j`\F  
    pos = 0; "c%wq 0  
    while (pos < buf_len) { #cY[c1cNv  
        /* get packet len */ ifn=De3+  
        pkt_len = usbtouch->type->get_pkt_len(buffer + pos, Cv#aBH'N  
                            buf_len - pos); "VaWZ*  
DGFSD Py[  
        /* unknown packet: skip one byte */ D6ZHvY8R  
        if (unlikely(!pkt_len)) { k3Yu"GY^  
            pos++; 'w:ugb9]  
            continue; ?1=.scmgDG  
        } <'\Nv._2a  
dk&F?B{6T  
        /* full packet: process */ cK$yr)7  
        if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) { 971=OEyq*  
            usbtouch_process_pkt(usbtouch, buffer + pos, pkt_len); T!jh`;D+  
        } else { ".}R$ W  
            /* incomplete packet: save in buffer */ 9^*RK6  
            memcpy(usbtouch->buffer, buffer + pos, buf_len - pos); 4?pb!@l  
            usbtouch->buf_len = buf_len - pos; x1:mT[[$  
            return; W|< c[S  
        } HlE8AbEg  
        pos += pkt_len; }IygU 6{G  
    } J4qk^1m.  
6J;!p/C8E  
out_flush_buf: dDS{XR  
    usbtouch->buf_len = 0; nlv,j&  
    return; ;+75"=[YT  
} YJ~<pH  
#endif ed'[_T}T3t  
Yc#Uu8f-  
 +P(*S  
static void usbtouch_irq(struct urb *urb) 2$JZ(qnN  
{ *~8F.c x  
    struct usbtouch_usb *usbtouch = urb->context; j~'.XD={  
    int retval; KS_+R@3Z  
C^q|(G)  
    switch (urb->status) { ?0~g1"Y-*K  
    case 0: 5AT^puL]]  
        /* success */ +?\JQ|  
        break; aR2N,<Cp5  
    case -ETIME: }8#olZ/(q  
        /* this urb is timing out */ RLf-Rdx/  
        dbg("%s - urb timed out - was the device unplugged?", SGKAx<U  
            __func__); Jxl'!8t  
        return; P#TPI*qw  
    case -ECONNRESET: &[yC M!  
    case -ENOENT: z$&B7?  
    case -ESHUTDOWN: %; &lVIU0  
    case -EPIPE: hk !=ZE3  
        /* this urb is terminated, clean up */ L;:|bVH  
        dbg("%s - urb shutting down with status: %d", *k(FbZ  
            __func__, urb->status); bqn(5)%{  
        return; ]I*RuDv}  
    default: 1(;{w +nM  
        dbg("%s - nonzero urb status received: %d", C).\ J !  
            __func__, urb->status); [Fh YQI  
        goto exit; ]v<8 l4p;  
    } }hy4EJ  
?q6#M&|j/I  
    usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length); .$~3RjM  
)Q1aAS3  
exit: P 0\`4Cr!  
    usb_mark_last_busy(interface_to_usbdev(usbtouch->interface)); TX5??o  
    retval = usb_submit_urb(urb, GFP_ATOMIC); ^S|qGu,G  
    if (retval) ]2u   
        err("%s - usb_submit_urb failed with result: %d", 0=,Nz  
            __func__, retval); ,?LE5]  
} [w}-)&c  
]Q FI>  
static int usbtouch_open(struct input_dev *input) IWYQ67Yj   
{ SB%D%Zx6'%  
    struct usbtouch_usb *usbtouch = input_get_drvdata(input); `N[@lV\xp!  
    int r; Op0*tj2i),  
TJYhgna  
    usbtouch->irq->dev = interface_to_usbdev(usbtouch->interface); (pH)QG  
bEF2- FO  
    r = usb_autopm_get_interface(usbtouch->interface) ? -EIO : 0; 09 McUR@  
    if (r < 0) 3^KR{N p  
        goto out; 9{(q[C5m  
.?:#<=1  
    if (!usbtouch->type->irq_always) { r?)1)?JnHe  
        if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) { ] 6(%tU  
            r = -EIO; 8}yrsF #  
            goto out_put; e oE)Mq  
        } 2lfEJw($  
    } = V')}f~C  
[+FiD  
    usbtouch->interface->needs_remote_wakeup = 1; `BZ|[ q3  
out_put: 8$c) ]Bv  
    usb_autopm_put_interface(usbtouch->interface); 7Td 9mkO  
out: E3a^"V3p  
    return r; OM.-apzC  
} ,i6U*  
=m<b+@?T  
static void usbtouch_close(struct input_dev *input) 'g <"@SS+  
{ -e$ T}3IV  
    struct usbtouch_usb *usbtouch = input_get_drvdata(input); U _pPI$ =  
    int r; Lp%J:ogV`  
;8=Bee4  
    if (!usbtouch->type->irq_always) ##By!F TP  
        usb_kill_urb(usbtouch->irq); )z&C&Gqz  
    r = usb_autopm_get_interface(usbtouch->interface); mm_)=Ipj>  
    usbtouch->interface->needs_remote_wakeup = 0; @ddCVxd  
    if (!r) KHP/Y {mH  
        usb_autopm_put_interface(usbtouch->interface); w nBvJb]4l  
} tJ\v>s-f  
BZv:E?1z  
static int usbtouch_suspend fhn$~8[_A  
(struct usb_interface *intf, pm_message_t message) WUau KRR.  
{ pj7a l;  
    struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); 7 2i&-`&4  
cGs& Kn;h  
    usb_kill_urb(usbtouch->irq); xrXfZ>$5bM  
Tcv/EST  
    return 0; "%Ief4  
} kXdXyq  
VN09g&  
static int usbtouch_resume(struct usb_interface *intf) ,2U  
{ 9b6U] z,  
    struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); gcI<bY  
    struct input_dev *input = usbtouch->input; CqWO 0  
    int result = 0; tSni[,4Kq  
D?dS/agA  
    mutex_lock(&input->mutex); >KQ/ c  
    if (input->users || usbtouch->type->irq_always) c0l?+:0M  
        result = usb_submit_urb(usbtouch->irq, GFP_NOIO); >;"%Db  
    mutex_unlock(&input->mutex); Vo[.^0  
XFWE^*e=B  
    return result; CXGMc)#>f  
} F<iV;+  
@/N]_2@8;  
static int usbtouch_reset_resume(struct usb_interface *intf) >B``+ Z^2  
{ [OPF3W3z  
    struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); _J2?B?S/j  
    struct input_dev *input = usbtouch->input; 9]T61Z{OW1  
    int err = 0; zXUB6. e  
89KFZ[.}]  
    /* reinit the device */ )b%zYD9p  
    if (usbtouch->type->init) { d%L/[.&  
        err = usbtouch->type->init(usbtouch); 3=?,Dv0P  
        if (err) { K[?@nl?,z  
            dbg("%s - type->init() failed, err: %d", w`< {   
                __func__, err); <Vt"%C  
            return err; `tuGy}S2  
        } ;P}007;  
    } ~-G_c=E?  
wmX(%5vY^  
    /* restart IO if needed */ iZ/iMDfC  
    mutex_lock(&input->mutex); Piw i  
    if (input->users) ,dosF Q  
        err = usb_submit_urb(usbtouch->irq, GFP_NOIO); oV9{{  
    mutex_unlock(&input->mutex); YIIc@ )  
(]?M=?0\  
    return err; ' Qlj"U  
} RH7!3ye  
7$Wbf4  
static void usbtouch_free_buffers(struct usb_device *udev, o*E32#l  
                  struct usbtouch_usb *usbtouch) x <aR|r  
{ NU'2QSU8  
    usb_free_coherent(udev, usbtouch->type->rept_size, (["V( $  
              usbtouch->data, usbtouch->data_dma); ugj I$u  
    kfree(usbtouch->buffer); 0k_3]Li=(  
} ]R!YRu  
p Djt\R<f  
static struct usb_endpoint_descriptor * BW3Q03SW6  
usbtouch_get_input_endpoint(struct usb_host_interface *interface) {wk#n.c  
{ 8 .K; 2  
    int i; j4`+RS+q  
0"GLgj:9  
    for (i = 0; i < interface->desc.bNumEndpoints; i++) u|\?6fz  
        if (usb_endpoint_dir_in(&interface->endpoint.desc)) A5\ Hq  
            return &interface->endpoint.desc;  > T:0  
xDPR^xY  
    return NULL; " &`>+Yw  
} g-ZXj4Ph!  
{,(iL8,^  
static int usbtouch_probe(struct usb_interface *intf, tnBCO%uG  
              const struct usb_device_id *id) 9; 9ge  
{ TI2K_'  
    struct usbtouch_usb *usbtouch; OwNo$b]h`  
    struct input_dev *input_dev; f;OB"p  
    struct usb_endpoint_descriptor *endpoint; v>mK~0.$  
    struct usb_device *udev = interface_to_usbdev(intf); Ek_<2!%X  
    struct usbtouch_device_info *type; WCk. K  
    int err = -ENOMEM; o9C# 5%9  
"j_cI-@6  
    /* some devices are ignored */ &sYxe:H  
    if (id->driver_info == DEVTYPE_IGNORE) /2*Bd E[yG  
        return -ENODEV; r=7!S8'  
3xdJ<Lrq  
    endpoint = usbtouch_get_input_endpoint(intf->cur_altsetting); YRv96|c,  
    if (!endpoint) 5G`fVsb  
        return -ENXIO; #_K<-m%9  
0S&J=2D!  
    usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL); @Cx goX^  
    input_dev = input_allocate_device(); >lyE@S sA  
    if (!usbtouch || !input_dev) Jk7 Am-.0  
        goto out_free; +%WW8OX   
rz`"$g+#  
    type = &usbtouch_dev_info[id->driver_info]; ox\D04:M  
    usbtouch->type = type; \P"Ol\@  
    if (!type->process_pkt) 9KJ}A i  
        type->process_pkt = usbtouch_process_pkt; Z.x]6  
LCzeE7x  
    usbtouch->data = usb_alloc_coherent(udev, type->rept_size, ~J5B?@2hK  
                        GFP_KERNEL, &usbtouch->data_dma); ]Wjcr2Wq  
    if (!usbtouch->data) Bc-/s(/Eq  
        goto out_free; gq4X(rsyD  
-II03 S1  
    if (type->get_pkt_len) { x;/dSfv_  
        usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL); {gD`yoPrV  
        if (!usbtouch->buffer) %~>-nqS  
            goto out_free_buffers; qzO5p=}  
    } ;i/? fw[h  
Mc(|+S@w'  
    usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL); AGO"),  
    if (!usbtouch->irq) { ufw[Ei$I:  
        dbg("%s - usb_alloc_urb failed: usbtouch->irq", __func__); GZn=Hgv8  
        goto out_free_buffers; !"-.D4*r  
    } Y}Dk>IG  
5Fj9.K~k  
    usbtouch->interface = intf; 4gVIuF*pS  
    usbtouch->input = input_dev; OQKc_z'"  
>,_0Mem2Rr  
    if (udev->manufacturer) "Y4glomR[  
        strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name)); &RI;!qn6(  
]ZW-`UMO  
    if (udev->product) { $"MVr5q6  
        if (udev->manufacturer) wf\7sz  
            strlcat(usbtouch->name, " ", sizeof(usbtouch->name)); Ho[]03  
        strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name)); cnw+^8  
    } /EegP@[  
S;D]ym  
    if (!strlen(usbtouch->name)) V\]j^$  
        snprintf(usbtouch->name, sizeof(usbtouch->name), BpX`49  
            "USB Touchscreen %04x:%04x", Qgv g*KX  
             le16_to_cpu(udev->descriptor.idVendor), Q00v(6V46  
             le16_to_cpu(udev->descriptor.idProduct)); \1n (Jr.<  
0*oavY*  
    usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys)); WU@_aw[  
    strlcat(usbtouch->phys, "/input0", sizeof(usbtouch->phys)); J~oxqw}  
DO+~    
    input_dev->name = usbtouch->name; ^SsnCn-e  
    input_dev->phys = usbtouch->phys; ~t$ng l$  
    usb_to_input_id(udev, &input_dev->id); M&gi$Qs[E  
    input_dev->dev.parent = &intf->dev; }QQ 7jE  
x(4"!#  
    input_set_drvdata(input_dev, usbtouch); D`'Cnt/  
)`ixT)   
    input_dev->open = usbtouch_open; 'iOa j0f  
    input_dev->close = usbtouch_close; ._<, Eodv  
#`K{vj  
    input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); Qnt9x,1m_  
    input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); #Ak|p#7 ^  
    input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0); 2Qh)/=8lM  
    input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0); =YfzB!ld  
    if (type->max_press) "O|.e`C%^  
        input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press, Iu5 9W >  
                             type->max_press, 0, 0); ~3Zz.!F  
:2/ jI:L~  
    if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT) `g)  
        usb_fill_int_urb(usbtouch->irq, udev, T}29(xz-(h  
             usb_rcvintpipe(udev, endpoint->bEndpointAddress), d<HO~+9  
             usbtouch->data, type->rept_size, YK$[)x\S  
             usbtouch_irq, usbtouch, endpoint->bInterval);  4~ L1~Gk  
    else 3;wiwN'  
        usb_fill_bulk_urb(usbtouch->irq, udev, 7zA+UWr  
             usb_rcvbulkpipe(udev, endpoint->bEndpointAddress), %X}vuE[[UC  
             usbtouch->data, type->rept_size, l]Xbd{  
             usbtouch_irq, usbtouch); A"s?;hv\fS  
bAN>\zG+  
    usbtouch->irq->dev = udev; +xsGa{`  
    usbtouch->irq->transfer_dma = usbtouch->data_dma; %6Vb1?x  
    usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; W=LJhCpRHj  
gy~2LY!}  
    /* device specific allocations */ i_l{#*t  
    if (type->alloc) { ?9!9lSH6%  
        err = type->alloc(usbtouch); fo`R=|L[  
        if (err) { 8bs'Ek{'o  
            dbg("%s - type->alloc() failed, err: %d", __func__, err); C&%NO;Ole  
            goto out_free_urb; %hw4IcWJ|  
        } eH!V%dX  
    } @g+v2(f2v  
uudd'L  
    /* device specific initialisation*/ 2Oyw#1tdn  
    if (type->init) { "L1LL iS  
        err = type->init(usbtouch);  98^7pa  
        if (err) { 3 |LRb/|  
            dbg("%s - type->init() failed, err: %d", __func__, err); ` "-P g5  
            goto out_do_exit; JKO*bbj  
        } /vi Ic %=  
    } 4K dYiuz0`  
!b4AeiL>w  
    err = input_register_device(usbtouch->input); )'e1@CR  
    if (err) { WS(m#WFQr  
        dbg("%s - input_register_device failed, err: %d", __func__, err); Z]bG"K3l  
        goto out_do_exit; P>)J:.tr0  
    } +]NpcE'  
0dS(g&ZR  
    usb_set_intfdata(intf, usbtouch); h&v].l  
}R5EuR m\  
    if (usbtouch->type->irq_always) { ,aBy1K  
        /* this can't fail */ <Kr`R+Q$DN  
        usb_autopm_get_interface(intf); eT5IL(mH  
        err = usb_submit_urb(usbtouch->irq, GFP_KERNEL); ycki0&n3  
        if (err) { 8'b ZR]  
            usb_autopm_put_interface(intf); < 1m `  
            err("%s - usb_submit_urb failed with result: %d", zSk`Ou8M  
                __func__, err); FwHqID_!:l  
            goto out_unregister_input; jq8TfJ|   
        } -%P}LaC <  
    } PVdN)tG5  
ZqpK}I  
    return 0; [cZ/)tm  
=2DK?]K;  
out_unregister_input: ]q[(z  
    input_unregister_device(input_dev); &`vThs[x  
    input_dev = NULL; &+ PVY>q  
out_do_exit: ePIN<F;I  
    if (type->exit) nnE'zk<"  
        type->exit(usbtouch); PNo:vRtsq  
out_free_urb: V EsM  
    usb_free_urb(usbtouch->irq); b\o>4T  
out_free_buffers: _h,_HW)G  
    usbtouch_free_buffers(udev, usbtouch); -e_TJA  
out_free: %21|-B  
    input_free_device(input_dev); Uam %u  
    kfree(usbtouch); I*(kv7(c0  
    return err; F^%\AA]8  
} s6 (md<r  
Q)M-f;O  
static void usbtouch_disconnect(struct usb_interface *intf) Q*1'k%7  
{ *icaKy3  
    struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); DTo"{!  
GBR$k P  
    dbg("%s - called", __func__); *<SXzJ(  
f?eq-/UR  
    if (!usbtouch) 5!$sQ@#}D  
        return; 89{;R  
/38I (0  
    dbg("%s - usbtouch is initialized, cleaning up", __func__); ! 9*l!(  
    usb_set_intfdata(intf, NULL); XkoPN]0n  
    /* this will stop IO via close */ Fs=x+8'M  
    input_unregister_device(usbtouch->input); \T<F#a  
    usb_free_urb(usbtouch->irq); }aXSMxCd  
    if (usbtouch->type->exit) 0:4>rYBC   
        usbtouch->type->exit(usbtouch); n c~JAT# '  
    usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); p}/D{|xO  
    kfree(usbtouch); D8 PC;@m  
} )1@%!fr  
L>E{~yh  
MODULE_DEVICE_TABLE(usb, usbtouch_devices); fZsw+PSy  
;~[}B v  
static struct usb_driver usbtouch_driver = { #D JZ42  
    .name        = "usbtouchscreen", O:T 49:R}r  
    .probe        = usbtouch_probe, KC2Z@  
    .disconnect    = usbtouch_disconnect, 9xw"NcL  
    .suspend    = usbtouch_suspend, \ISg6v{/  
    .resume        = usbtouch_resume, T3SFG]H  
    .reset_resume    = usbtouch_reset_resume, eX}aa0  
    .id_table    = usbtouch_devices, /kRCCs8t}  
    .supports_autosuspend = 1, Z(R0IW  
}; <ME>#,  
}0@@_Y]CC  
static int __init usbtouch_init(void) v.TgB)  
{ Y9vi&G?Jl  
    return usb_register(&usbtouch_driver);  ggM~Chr  
} @W$ha y  
88[u^aC  
static void __exit usbtouch_cleanup(void) yIngenr$  
{ ohJDu{V  
    usb_deregister(&usbtouch_driver); !^0vi3I  
} ev+H{5W8  
J9j @V4  
module_init(usbtouch_init); }''0N1,/  
module_exit(usbtouch_cleanup); iT O Y  
<6,,:=#  
MODULE_AUTHOR(DRIVER_AUTHOR); >mJ`904L  
MODULE_DESCRIPTION(DRIVER_DESC); |F<iu2\  
MODULE_LICENSE("GPL"); }opMf6`w  
\{~CO{II  
MODULE_ALIAS("touchkitusb"); cVO- iPK  
MODULE_ALIAS("itmtouch"); Fi;OZ>;a  
MODULE_ALIAS("mtouchusb"); 0nB[Udk?  


评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

一般

差劲
快速回复
限150 字节
 
上一个 下一个