1*4882a593Smuzhiyun /*=========================================================================== 2*4882a593Smuzhiyun FILE: 3*4882a593Smuzhiyun QMIDevice.h 4*4882a593Smuzhiyun 5*4882a593Smuzhiyun DESCRIPTION: 6*4882a593Smuzhiyun Functions related to the QMI interface device 7*4882a593Smuzhiyun 8*4882a593Smuzhiyun FUNCTIONS: 9*4882a593Smuzhiyun Generic functions 10*4882a593Smuzhiyun IsDeviceValid 11*4882a593Smuzhiyun PrintHex 12*4882a593Smuzhiyun GobiSetDownReason 13*4882a593Smuzhiyun GobiClearDownReason 14*4882a593Smuzhiyun GobiTestDownReason 15*4882a593Smuzhiyun 16*4882a593Smuzhiyun Driver level asynchronous read functions 17*4882a593Smuzhiyun ResubmitIntURB 18*4882a593Smuzhiyun ReadCallback 19*4882a593Smuzhiyun IntCallback 20*4882a593Smuzhiyun StartRead 21*4882a593Smuzhiyun KillRead 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun Internal read/write functions 24*4882a593Smuzhiyun ReadAsync 25*4882a593Smuzhiyun UpSem 26*4882a593Smuzhiyun ReadSync 27*4882a593Smuzhiyun WriteSyncCallback 28*4882a593Smuzhiyun WriteSync 29*4882a593Smuzhiyun 30*4882a593Smuzhiyun Internal memory management functions 31*4882a593Smuzhiyun GetClientID 32*4882a593Smuzhiyun ReleaseClientID 33*4882a593Smuzhiyun FindClientMem 34*4882a593Smuzhiyun AddToReadMemList 35*4882a593Smuzhiyun PopFromReadMemList 36*4882a593Smuzhiyun AddToNotifyList 37*4882a593Smuzhiyun NotifyAndPopNotifyList 38*4882a593Smuzhiyun AddToURBList 39*4882a593Smuzhiyun PopFromURBList 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun Internal userspace wrapper functions 42*4882a593Smuzhiyun UserspaceunlockedIOCTL 43*4882a593Smuzhiyun 44*4882a593Smuzhiyun Userspace wrappers 45*4882a593Smuzhiyun UserspaceOpen 46*4882a593Smuzhiyun UserspaceIOCTL 47*4882a593Smuzhiyun UserspaceClose 48*4882a593Smuzhiyun UserspaceRead 49*4882a593Smuzhiyun UserspaceWrite 50*4882a593Smuzhiyun UserspacePoll 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun Initializer and destructor 53*4882a593Smuzhiyun RegisterQMIDevice 54*4882a593Smuzhiyun DeregisterQMIDevice 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun Driver level client management 57*4882a593Smuzhiyun QMIReady 58*4882a593Smuzhiyun QMIWDSCallback 59*4882a593Smuzhiyun SetupQMIWDSCallback 60*4882a593Smuzhiyun QMIDMSGetMEID 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun Copyright (c) 2011, Code Aurora Forum. All rights reserved. 63*4882a593Smuzhiyun 64*4882a593Smuzhiyun Redistribution and use in source and binary forms, with or without 65*4882a593Smuzhiyun modification, are permitted provided that the following conditions are met: 66*4882a593Smuzhiyun * Redistributions of source code must retain the above copyright 67*4882a593Smuzhiyun notice, this list of conditions and the following disclaimer. 68*4882a593Smuzhiyun * Redistributions in binary form must reproduce the above copyright 69*4882a593Smuzhiyun notice, this list of conditions and the following disclaimer in the 70*4882a593Smuzhiyun documentation and/or other materials provided with the distribution. 71*4882a593Smuzhiyun * Neither the name of Code Aurora Forum nor 72*4882a593Smuzhiyun the names of its contributors may be used to endorse or promote 73*4882a593Smuzhiyun products derived from this software without specific prior written 74*4882a593Smuzhiyun permission. 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun 77*4882a593Smuzhiyun THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 78*4882a593Smuzhiyun AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 79*4882a593Smuzhiyun IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 80*4882a593Smuzhiyun ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 81*4882a593Smuzhiyun LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 82*4882a593Smuzhiyun CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 83*4882a593Smuzhiyun SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 84*4882a593Smuzhiyun INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 85*4882a593Smuzhiyun CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 86*4882a593Smuzhiyun ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 87*4882a593Smuzhiyun POSSIBILITY OF SUCH DAMAGE. 88*4882a593Smuzhiyun ===========================================================================*/ 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun //--------------------------------------------------------------------------- 91*4882a593Smuzhiyun // Pragmas 92*4882a593Smuzhiyun //--------------------------------------------------------------------------- 93*4882a593Smuzhiyun #pragma once 94*4882a593Smuzhiyun 95*4882a593Smuzhiyun //--------------------------------------------------------------------------- 96*4882a593Smuzhiyun // Include Files 97*4882a593Smuzhiyun //--------------------------------------------------------------------------- 98*4882a593Smuzhiyun #include "Structs.h" 99*4882a593Smuzhiyun #include "QMI.h" 100*4882a593Smuzhiyun 101*4882a593Smuzhiyun /*=========================================================================*/ 102*4882a593Smuzhiyun // Generic functions 103*4882a593Smuzhiyun /*=========================================================================*/ 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun #ifdef __QUECTEL_INTER__ 106*4882a593Smuzhiyun 107*4882a593Smuzhiyun // Basic test to see if device memory is valid 108*4882a593Smuzhiyun static bool IsDeviceValid( sGobiUSBNet * pDev ); 109*4882a593Smuzhiyun 110*4882a593Smuzhiyun /*=========================================================================*/ 111*4882a593Smuzhiyun // Driver level asynchronous read functions 112*4882a593Smuzhiyun /*=========================================================================*/ 113*4882a593Smuzhiyun 114*4882a593Smuzhiyun // Resubmit interrupt URB, re-using same values 115*4882a593Smuzhiyun static int ResubmitIntURB( struct urb * pIntURB ); 116*4882a593Smuzhiyun 117*4882a593Smuzhiyun // Read callback 118*4882a593Smuzhiyun // Put the data in storage and notify anyone waiting for data 119*4882a593Smuzhiyun #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 )) 120*4882a593Smuzhiyun static void ReadCallback( struct urb * pReadURB ); 121*4882a593Smuzhiyun #else 122*4882a593Smuzhiyun static void ReadCallback(struct urb *pReadURB, struct pt_regs *regs); 123*4882a593Smuzhiyun #endif 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun // Inturrupt callback 126*4882a593Smuzhiyun // Data is available, start a read URB 127*4882a593Smuzhiyun #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 )) 128*4882a593Smuzhiyun static void IntCallback( struct urb * pIntURB ); 129*4882a593Smuzhiyun #else 130*4882a593Smuzhiyun static void IntCallback(struct urb *pIntURB, struct pt_regs *regs); 131*4882a593Smuzhiyun #endif 132*4882a593Smuzhiyun 133*4882a593Smuzhiyun /*=========================================================================*/ 134*4882a593Smuzhiyun // Internal read/write functions 135*4882a593Smuzhiyun /*=========================================================================*/ 136*4882a593Smuzhiyun 137*4882a593Smuzhiyun // Start asynchronous read 138*4882a593Smuzhiyun // Reading client's data store, not device 139*4882a593Smuzhiyun static int ReadAsync( 140*4882a593Smuzhiyun sGobiUSBNet * pDev, 141*4882a593Smuzhiyun u16 clientID, 142*4882a593Smuzhiyun u16 transactionID, 143*4882a593Smuzhiyun void (*pCallback)(sGobiUSBNet *, u16, void *), 144*4882a593Smuzhiyun void * pData ); 145*4882a593Smuzhiyun 146*4882a593Smuzhiyun // Notification function for synchronous read 147*4882a593Smuzhiyun static void UpSem( 148*4882a593Smuzhiyun sGobiUSBNet * pDev, 149*4882a593Smuzhiyun u16 clientID, 150*4882a593Smuzhiyun void * pData ); 151*4882a593Smuzhiyun 152*4882a593Smuzhiyun // Start synchronous read 153*4882a593Smuzhiyun // Reading client's data store, not device 154*4882a593Smuzhiyun static int ReadSync( 155*4882a593Smuzhiyun sGobiUSBNet * pDev, 156*4882a593Smuzhiyun void ** ppOutBuffer, 157*4882a593Smuzhiyun u16 clientID, 158*4882a593Smuzhiyun u16 transactionID ); 159*4882a593Smuzhiyun 160*4882a593Smuzhiyun // Write callback 161*4882a593Smuzhiyun #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 )) 162*4882a593Smuzhiyun static void WriteSyncCallback( struct urb * pWriteURB ); 163*4882a593Smuzhiyun #else 164*4882a593Smuzhiyun static void WriteSyncCallback(struct urb *pWriteURB, struct pt_regs *regs); 165*4882a593Smuzhiyun #endif 166*4882a593Smuzhiyun 167*4882a593Smuzhiyun // Start synchronous write 168*4882a593Smuzhiyun static int WriteSync( 169*4882a593Smuzhiyun sGobiUSBNet * pDev, 170*4882a593Smuzhiyun char * pInWriteBuffer, 171*4882a593Smuzhiyun int size, 172*4882a593Smuzhiyun u16 clientID ); 173*4882a593Smuzhiyun 174*4882a593Smuzhiyun /*=========================================================================*/ 175*4882a593Smuzhiyun // Internal memory management functions 176*4882a593Smuzhiyun /*=========================================================================*/ 177*4882a593Smuzhiyun 178*4882a593Smuzhiyun // Create client and allocate memory 179*4882a593Smuzhiyun static int GetClientID( 180*4882a593Smuzhiyun sGobiUSBNet * pDev, 181*4882a593Smuzhiyun u8 serviceType ); 182*4882a593Smuzhiyun 183*4882a593Smuzhiyun // Release client and free memory 184*4882a593Smuzhiyun static void ReleaseClientID( 185*4882a593Smuzhiyun sGobiUSBNet * pDev, 186*4882a593Smuzhiyun u16 clientID ); 187*4882a593Smuzhiyun 188*4882a593Smuzhiyun // Find this client's memory 189*4882a593Smuzhiyun static sClientMemList * FindClientMem( 190*4882a593Smuzhiyun sGobiUSBNet * pDev, 191*4882a593Smuzhiyun u16 clientID ); 192*4882a593Smuzhiyun 193*4882a593Smuzhiyun // Add Data to this client's ReadMem list 194*4882a593Smuzhiyun static bool AddToReadMemList( 195*4882a593Smuzhiyun sGobiUSBNet * pDev, 196*4882a593Smuzhiyun u16 clientID, 197*4882a593Smuzhiyun u16 transactionID, 198*4882a593Smuzhiyun void * pData, 199*4882a593Smuzhiyun u16 dataSize ); 200*4882a593Smuzhiyun 201*4882a593Smuzhiyun // Remove data from this client's ReadMem list if it matches 202*4882a593Smuzhiyun // the specified transaction ID. 203*4882a593Smuzhiyun static bool PopFromReadMemList( 204*4882a593Smuzhiyun sGobiUSBNet * pDev, 205*4882a593Smuzhiyun u16 clientID, 206*4882a593Smuzhiyun u16 transactionID, 207*4882a593Smuzhiyun void ** ppData, 208*4882a593Smuzhiyun u16 * pDataSize ); 209*4882a593Smuzhiyun 210*4882a593Smuzhiyun // Add Notify entry to this client's notify List 211*4882a593Smuzhiyun static bool AddToNotifyList( 212*4882a593Smuzhiyun sGobiUSBNet * pDev, 213*4882a593Smuzhiyun u16 clientID, 214*4882a593Smuzhiyun u16 transactionID, 215*4882a593Smuzhiyun void (* pNotifyFunct)(sGobiUSBNet *, u16, void *), 216*4882a593Smuzhiyun void * pData ); 217*4882a593Smuzhiyun 218*4882a593Smuzhiyun // Remove first Notify entry from this client's notify list 219*4882a593Smuzhiyun // and Run function 220*4882a593Smuzhiyun static bool NotifyAndPopNotifyList( 221*4882a593Smuzhiyun sGobiUSBNet * pDev, 222*4882a593Smuzhiyun u16 clientID, 223*4882a593Smuzhiyun u16 transactionID ); 224*4882a593Smuzhiyun 225*4882a593Smuzhiyun // Add URB to this client's URB list 226*4882a593Smuzhiyun static bool AddToURBList( 227*4882a593Smuzhiyun sGobiUSBNet * pDev, 228*4882a593Smuzhiyun u16 clientID, 229*4882a593Smuzhiyun struct urb * pURB ); 230*4882a593Smuzhiyun 231*4882a593Smuzhiyun // Remove URB from this client's URB list 232*4882a593Smuzhiyun static struct urb * PopFromURBList( 233*4882a593Smuzhiyun sGobiUSBNet * pDev, 234*4882a593Smuzhiyun u16 clientID ); 235*4882a593Smuzhiyun 236*4882a593Smuzhiyun /*=========================================================================*/ 237*4882a593Smuzhiyun // Internal userspace wrappers 238*4882a593Smuzhiyun /*=========================================================================*/ 239*4882a593Smuzhiyun 240*4882a593Smuzhiyun // Userspace unlocked ioctl 241*4882a593Smuzhiyun static long UserspaceunlockedIOCTL( 242*4882a593Smuzhiyun struct file * pFilp, 243*4882a593Smuzhiyun unsigned int cmd, 244*4882a593Smuzhiyun unsigned long arg ); 245*4882a593Smuzhiyun 246*4882a593Smuzhiyun /*=========================================================================*/ 247*4882a593Smuzhiyun // Userspace wrappers 248*4882a593Smuzhiyun /*=========================================================================*/ 249*4882a593Smuzhiyun 250*4882a593Smuzhiyun // Userspace open 251*4882a593Smuzhiyun static int UserspaceOpen( 252*4882a593Smuzhiyun struct inode * pInode, 253*4882a593Smuzhiyun struct file * pFilp ); 254*4882a593Smuzhiyun 255*4882a593Smuzhiyun #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,36 )) 256*4882a593Smuzhiyun // Userspace ioctl 257*4882a593Smuzhiyun static int UserspaceIOCTL( 258*4882a593Smuzhiyun struct inode * pUnusedInode, 259*4882a593Smuzhiyun struct file * pFilp, 260*4882a593Smuzhiyun unsigned int cmd, 261*4882a593Smuzhiyun unsigned long arg ); 262*4882a593Smuzhiyun #endif 263*4882a593Smuzhiyun 264*4882a593Smuzhiyun // Userspace close 265*4882a593Smuzhiyun #define quectel_no_for_each_process 266*4882a593Smuzhiyun #ifdef quectel_no_for_each_process 267*4882a593Smuzhiyun static int UserspaceClose( 268*4882a593Smuzhiyun struct inode * pInode, 269*4882a593Smuzhiyun struct file * pFilp ); 270*4882a593Smuzhiyun #else 271*4882a593Smuzhiyun #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,14 )) 272*4882a593Smuzhiyun static int UserspaceClose( 273*4882a593Smuzhiyun struct file * pFilp, 274*4882a593Smuzhiyun fl_owner_t unusedFileTable ); 275*4882a593Smuzhiyun #else 276*4882a593Smuzhiyun static int UserspaceClose( struct file * pFilp ); 277*4882a593Smuzhiyun #endif 278*4882a593Smuzhiyun #endif 279*4882a593Smuzhiyun 280*4882a593Smuzhiyun // Userspace read (synchronous) 281*4882a593Smuzhiyun static ssize_t UserspaceRead( 282*4882a593Smuzhiyun struct file * pFilp, 283*4882a593Smuzhiyun char __user * pBuf, 284*4882a593Smuzhiyun size_t size, 285*4882a593Smuzhiyun loff_t * pUnusedFpos ); 286*4882a593Smuzhiyun 287*4882a593Smuzhiyun // Userspace write (synchronous) 288*4882a593Smuzhiyun static ssize_t UserspaceWrite( 289*4882a593Smuzhiyun struct file * pFilp, 290*4882a593Smuzhiyun const char __user * pBuf, 291*4882a593Smuzhiyun size_t size, 292*4882a593Smuzhiyun loff_t * pUnusedFpos ); 293*4882a593Smuzhiyun 294*4882a593Smuzhiyun static unsigned int UserspacePoll( 295*4882a593Smuzhiyun struct file * pFilp, 296*4882a593Smuzhiyun struct poll_table_struct * pPollTable ); 297*4882a593Smuzhiyun 298*4882a593Smuzhiyun /*=========================================================================*/ 299*4882a593Smuzhiyun // Driver level client management 300*4882a593Smuzhiyun /*=========================================================================*/ 301*4882a593Smuzhiyun 302*4882a593Smuzhiyun // Check if QMI is ready for use 303*4882a593Smuzhiyun static bool QMIReady( 304*4882a593Smuzhiyun sGobiUSBNet * pDev, 305*4882a593Smuzhiyun u16 timeout ); 306*4882a593Smuzhiyun 307*4882a593Smuzhiyun // QMI WDS callback function 308*4882a593Smuzhiyun static void QMIWDSCallback( 309*4882a593Smuzhiyun sGobiUSBNet * pDev, 310*4882a593Smuzhiyun u16 clientID, 311*4882a593Smuzhiyun void * pData ); 312*4882a593Smuzhiyun 313*4882a593Smuzhiyun // Fire off reqests and start async read for QMI WDS callback 314*4882a593Smuzhiyun static int SetupQMIWDSCallback( sGobiUSBNet * pDev ); 315*4882a593Smuzhiyun 316*4882a593Smuzhiyun // Register client, send req and parse MEID response, release client 317*4882a593Smuzhiyun static int QMIDMSGetMEID( sGobiUSBNet * pDev ); 318*4882a593Smuzhiyun 319*4882a593Smuzhiyun // Register client, send req and parse Data format response, release client 320*4882a593Smuzhiyun static int QMIWDASetDataFormat( sGobiUSBNet * pDev, int qmap_mode, int *rx_urb_size ); 321*4882a593Smuzhiyun #endif 322*4882a593Smuzhiyun 323*4882a593Smuzhiyun // Print Hex data, for debug purposes 324*4882a593Smuzhiyun void QuecPrintHex( 325*4882a593Smuzhiyun void * pBuffer, 326*4882a593Smuzhiyun u16 bufSize ); 327*4882a593Smuzhiyun 328*4882a593Smuzhiyun // Sets mDownReason and turns carrier off 329*4882a593Smuzhiyun void QuecGobiSetDownReason( 330*4882a593Smuzhiyun sGobiUSBNet * pDev, 331*4882a593Smuzhiyun u8 reason ); 332*4882a593Smuzhiyun 333*4882a593Smuzhiyun // Clear mDownReason and may turn carrier on 334*4882a593Smuzhiyun void QuecGobiClearDownReason( 335*4882a593Smuzhiyun sGobiUSBNet * pDev, 336*4882a593Smuzhiyun u8 reason ); 337*4882a593Smuzhiyun 338*4882a593Smuzhiyun // Tests mDownReason and returns whether reason is set 339*4882a593Smuzhiyun bool QuecGobiTestDownReason( 340*4882a593Smuzhiyun sGobiUSBNet * pDev, 341*4882a593Smuzhiyun u8 reason ); 342*4882a593Smuzhiyun 343*4882a593Smuzhiyun // Start continuous read "thread" 344*4882a593Smuzhiyun int QuecStartRead( sGobiUSBNet * pDev ); 345*4882a593Smuzhiyun 346*4882a593Smuzhiyun // Kill continuous read "thread" 347*4882a593Smuzhiyun void QuecKillRead( sGobiUSBNet * pDev ); 348*4882a593Smuzhiyun 349*4882a593Smuzhiyun /*=========================================================================*/ 350*4882a593Smuzhiyun // Initializer and destructor 351*4882a593Smuzhiyun /*=========================================================================*/ 352*4882a593Smuzhiyun 353*4882a593Smuzhiyun // QMI Device initialization function 354*4882a593Smuzhiyun int QuecRegisterQMIDevice( sGobiUSBNet * pDev ); 355*4882a593Smuzhiyun 356*4882a593Smuzhiyun // QMI Device cleanup function 357*4882a593Smuzhiyun void QuecDeregisterQMIDevice( sGobiUSBNet * pDev ); 358*4882a593Smuzhiyun 359*4882a593Smuzhiyun int QuecQMIWDASetDataFormat( sGobiUSBNet * pDev, int qmap_mode, int *rx_urb_size ); 360*4882a593Smuzhiyun 361*4882a593Smuzhiyun #define PrintHex QuecPrintHex 362*4882a593Smuzhiyun #define GobiSetDownReason QuecGobiSetDownReason 363*4882a593Smuzhiyun #define GobiClearDownReason QuecGobiClearDownReason 364*4882a593Smuzhiyun #define GobiTestDownReason QuecGobiTestDownReason 365*4882a593Smuzhiyun #define StartRead QuecStartRead 366*4882a593Smuzhiyun #define KillRead QuecKillRead 367*4882a593Smuzhiyun #define RegisterQMIDevice QuecRegisterQMIDevice 368*4882a593Smuzhiyun #define DeregisterQMIDevice QuecDeregisterQMIDevice 369