support library for C027 helper functions for Buffer Pipes, Buffered Serial Port (rtos capable) and GPS parsing. It includes modem APIs for USSD, SMS and Sockets.

Fork of C027_Support by u-blox

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MDM.h Source File

MDM.h

00001 #pragma once 
00002 
00003 #include "mbed.h"
00004 #include <stdarg.h>
00005 
00006 #include "Pipe.h"
00007 #include "SerialPipe.h"
00008 
00009 
00010 
00011 #ifdef TARGET_UBLOX_C027 
00012  // you can change this is you like to use a shield even on the C027
00013  #define MDM_IF(onboard,shield) onboard
00014 #else
00015  #define MDM_IF(onboard,shield) shield
00016 #endif
00017 
00018 //! include debug capabilty on more powerful targets with a dedicated debug port 
00019 #if defined(TARGET_LPC1768) || defined(TARGET_LPC4088) || defined(TARGET_K64F)
00020  #define MDM_DEBUG 
00021 #endif 
00022 
00023 /** basic modem parser class 
00024 */
00025 class MDMParser
00026 {
00027 public:
00028     //! Constructor 
00029     MDMParser(void);
00030     //! get static instance
00031     static MDMParser* getInstance() { return inst; };
00032     
00033     // ----------------------------------------------------------------
00034     // Types 
00035     // ----------------------------------------------------------------
00036     //! MT Device Types 
00037     typedef enum { DEV_UNKNOWN, 
00038                    DEV_SARA_G35, DEV_LISA_U2, DEV_LISA_U2_03S, DEV_LISA_C2, 
00039                    DEV_SARA_U2, DEV_LEON_G2, DEV_TOBY_L2, DEV_MPCI_L2 } Dev; 
00040     //! SIM Status
00041     typedef enum { SIM_UNKNOWN, SIM_MISSING, SIM_PIN, SIM_PUK, SIM_READY, WRONG_PIN } Sim;
00042     //! SIM Status
00043     typedef enum { LPM_DISABLED, LPM_ENABLED, LPM_ACTIVE } Lpm; 
00044     //! COPS status
00045     typedef enum { COPS_UNKOWN, COPS_AUTOMATIC_REG, COPS_MANUAL_REG, COPS_DISABLED_REG} CopsMode;
00046     //! Device status
00047     typedef struct { 
00048         Dev dev;            //!< Device Type
00049         Lpm lpm;            //!< Power Saving 
00050         Sim sim;            //!< SIM Card Status
00051         char ccid[20+1];    //!< Integrated Circuit Card ID
00052         char imsi[15+1];    //!< International Mobile Station Identity
00053         char imei[15+1];    //!< International Mobile Equipment Identity
00054         char meid[18+1];    //!< Mobile Equipment IDentifier
00055         char manu[16];      //!< Manufacturer (u-blox)
00056         char model[16];     //!< Model Name (LISA-U200, LISA-C200 or SARA-G350)
00057         char ver[16];       //!< Software Version
00058     } DevStatus;
00059     //! Registration Status
00060     typedef enum { REG_UNKNOWN, REG_DENIED, REG_NONE, REG_HOME, REG_ROAMING } Reg; 
00061     //! Access Technology
00062     typedef enum { ACT_UNKNOWN, ACT_GSM, ACT_EDGE, ACT_UTRAN, ACT_CDMA, ACT_LTE } AcT; 
00063     //! Network Status
00064     typedef struct { 
00065         Reg csd;        //!< CSD Registration Status (Circuit Switched Data)
00066         Reg psd;        //!< PSD Registration status (Packet Switched Data)
00067         Reg eps;        //!< EPS Registration status
00068         AcT act;        //!< Access Technology
00069         int rssi;       //!< Received Signal Strength Indication (in dBm, range -113..-51)
00070         int ber;        //!< Bit Error Rate (BER), see 3GPP TS 45.008 [20] subclause 8.2.4
00071         char opr[16+1]; //!< Operator Name
00072         char num[32];   //!< Mobile Directory Number
00073         unsigned short lac;  //!< location area code in hexadecimal format (2 bytes in hex)
00074         unsigned int ci;     //!< Cell ID in hexadecimal format (2 to 4 bytes in hex)
00075         CopsMode regStatus;    //!< Cops mode
00076     } NetStatus;
00077     typedef enum { CELL_LAST = 0, CELL_GNSS, CELL_LOCATE, CELL_HYBRID} CellSensType;
00078     typedef enum { CELL_DETAILED = 1, CELL_MULTIHYP = 2} CellRespType;
00079     #define CELL_MAX_HYP    (16 + 1)
00080     int _locRcvPos;     //!< Received positions
00081     int _locExpPos;     //!< Expected positions
00082    //! Cell Locate Data
00083    typedef struct {
00084        bool validData;      //!< Flag for indicating if data is valid
00085        struct tm time;      //!< GPS Timestamp
00086        float longitude;     //!< Estimated longitude, in degrees
00087        float latitude;      //!< Estimated latitude, in degrees
00088        int altitutude;      //!< Estimated altitude, in meters^2
00089        int uncertainty;     //!< Maximum possible error, in meters
00090        int speed;           //!< Speed over ground m/s^2
00091        int direction;       //!< Course over ground in degrees
00092        int verticalAcc;     //!< Vertical accuracy, in meters^2
00093        CellSensType sensor;      //!< Sensor used for last calculation
00094        int svUsed;          //!< number of satellite used
00095    }CellLocData;    
00096     //! An IP v4 address
00097     typedef uint32_t IP;
00098     #define NOIP ((MDMParser::IP)0) //!< No IP address
00099     // ip number formating and conversion
00100     #define IPSTR           "%d.%d.%d.%d"
00101     #define IPNUM(ip)       ((ip)>>24)&0xff, \
00102                             ((ip)>>16)&0xff, \
00103                             ((ip)>> 8)&0xff, \
00104                             ((ip)>> 0)&0xff
00105     #define IPADR(a,b,c,d) ((((IP)(a))<<24) | \
00106                             (((IP)(b))<<16) | \
00107                             (((IP)(c))<< 8) | \
00108                             (((IP)(d))<< 0))
00109 
00110     
00111     // ----------------------------------------------------------------
00112     // Device 
00113     // ----------------------------------------------------------------
00114     
00115     typedef enum { AUTH_NONE, AUTH_PAP, AUTH_CHAP, AUTH_DETECT } Auth; 
00116     
00117     /** Combined Init, checkNetStatus, join suitable for simple applications
00118         \param simpin a optional pin of the SIM card
00119         \param apn  the of the network provider e.g. "internet" or "apn.provider.com"
00120         \param username is the user name text string for the authentication phase
00121         \param password is the password text string for the authentication phase
00122         \param auth is the authentication mode (CHAP,PAP,NONE or DETECT)
00123         \return true if successful, false otherwise
00124     */
00125     bool connect(const char* simpin = NULL, 
00126             const char* apn = NULL, const char* username = NULL, 
00127             const char* password = NULL, Auth auth = AUTH_DETECT,
00128             PinName pn MDM_IF( = MDMPWRON, = D4));    
00129 
00130     /** register (Attach) the MT to the GPRS service. 
00131         \param simpin a optional pin of the SIM card
00132         \param status an optional struture to with device information 
00133         \return true if successful, false otherwise
00134     */
00135     virtual bool init(const char* simpin = NULL, DevStatus* status = NULL, 
00136                 PinName pn MDM_IF( = MDMPWRON, = D4));
00137 
00138     /** get the current device status
00139         \param strocture holding the device information. 
00140     */
00141     void getDevStatus(MDMParser::DevStatus* dev) { memcpy(dev, &_dev, sizeof(DevStatus)); }
00142     
00143     /** register to the network 
00144         \param status an optional structure to with network information 
00145         \param timeout_ms -1 blocking, else non blocking timeout in ms
00146         \return true if successful and connected to network, false otherwise
00147     */
00148     bool registerNet(NetStatus* status = NULL, int timeout_ms = 180000);
00149     
00150     /** check if the network is available 
00151         \param status an optional structure to with network information 
00152         \return true if successful and connected to network, false otherwise
00153     */
00154     bool checkNetStatus(NetStatus* status = NULL);
00155     
00156     /** Power off the MT, This function has to be called prior to 
00157         switching off the supply. 
00158         \return true if successfully, false otherwise
00159     */ 
00160     bool powerOff(void);
00161     
00162     // ----------------------------------------------------------------
00163     // Data Connection (GPRS)
00164     // ----------------------------------------------------------------
00165     
00166     /** register (Attach) the MT to the GPRS service. 
00167         \param apn  the of the network provider e.g. "internet" or "apn.provider.com"
00168         \param username is the user name text string for the authentication phase
00169         \param password is the password text string for the authentication phase
00170         \param auth is the authentication mode (CHAP,PAP,NONE or DETECT)
00171         \return the ip that is assigned 
00172     */
00173     MDMParser::IP join(const char* apn = NULL, const char* username = NULL, 
00174                        const char* password = NULL, Auth auth = AUTH_DETECT);
00175     
00176     /** deregister (detach) the MT from the GPRS service.
00177         \return true if successful, false otherwise
00178     */
00179     bool disconnect(void);
00180     
00181     /** Translates a domain name to an IP address
00182         \param host the domain name to translate e.g. "u-blox.com"
00183         \return the IP if successful, 0 otherwise
00184     */
00185     MDMParser::IP gethostbyname(const char* host);
00186     
00187     /** get the current assigned IP address
00188         \return the ip that is assigned 
00189     */
00190     MDMParser::IP getIpAddress(void) { return _ip; }
00191 
00192     // ----------------------------------------------------------------
00193     // Sockets
00194     // ----------------------------------------------------------------
00195     
00196     //! Type of IP protocol 
00197     typedef enum { IPPROTO_TCP, IPPROTO_UDP } IpProtocol; 
00198     
00199     //! Socket error return codes
00200     #define SOCKET_ERROR -1
00201     
00202     /** Create a socket for a ip protocol (and optionaly bind)
00203         \param ipproto the protocol (UDP or TCP) 
00204         \param port in case of UDP, this optional port where it is bind
00205         \return the socket handle if successful or SOCKET_ERROR on failure 
00206     */
00207     int socketSocket(IpProtocol ipproto, int port = -1);
00208     
00209     /** make a socket connection
00210         \param socket the socket handle
00211         \param host the domain name to connect e.g. "u-blox.com"
00212         \param port the port to connect
00213         \return true if successfully, false otherwise
00214     */
00215     bool socketConnect(int socket, const char* host, int port);
00216         
00217     /** make a socket connection
00218         \param socket the socket handle
00219         \return true if connected, false otherwise
00220     */
00221     bool socketIsConnected(int socket);
00222      
00223     /** Get the number of bytes pending for reading for this socket
00224         \param socket the socket handle
00225         \param timeout_ms -1 blocking, else non blocking timeout in ms
00226         \return 0 if successful or SOCKET_ERROR on failure 
00227     */
00228     bool socketSetBlocking(int socket, int timeout_ms);
00229     
00230     /** Write socket data 
00231         \param socket the socket handle
00232         \param buf the buffer to write
00233         \param len the size of the buffer to write
00234         \return the size written or SOCKET_ERROR on failure 
00235     */
00236     int socketSend(int socket, const char * buf, int len);
00237     
00238     /** Write socket data to a IP
00239         \param socket the socket handle
00240         \param ip the ip to send to
00241         \param port the port to send to
00242         \param buf the buffer to write
00243         \param len the size of the buffer to write
00244         \return the size written or SOCKET_ERROR on failure 
00245     */
00246     int socketSendTo(int socket, IP ip, int port, const char * buf, int len);
00247     
00248     /** Get the number of bytes pending for reading for this socket
00249         \param socket the socket handle
00250         \return the number of bytes pending or SOCKET_ERROR on failure 
00251     */
00252     int socketReadable(int socket);
00253     
00254     /** Read this socket
00255         \param socket the socket handle
00256         \param buf the buffer to read into
00257         \param len the size of the buffer to read into
00258         \return the number of bytes read or SOCKET_ERROR on failure 
00259     */
00260     int socketRecv(int socket, char* buf, int len);
00261     
00262     /** Read from this socket
00263         \param socket the socket handle
00264         \param ip the ip of host where the data originates from
00265         \param port the port where the data originates from
00266         \param buf the buffer to read into
00267         \param len the size of the buffer to read into
00268         \return the number of bytes read or SOCKET_ERROR on failure 
00269     */
00270     int socketRecvFrom(int socket, IP* ip, int* port, char* buf, int len);
00271     
00272     /** Close a connectied socket (that was connected with #socketConnect)
00273         \param socket the socket handle
00274         \return true if successfully, false otherwise
00275     */    
00276     bool socketClose(int socket);
00277     
00278     /** Free the socket (that was allocated before by #socketSocket)
00279         \param socket the socket handle
00280         \return true if successfully, false otherwise
00281     */    
00282     bool socketFree(int socket);
00283 
00284     // ----------------------------------------------------------------
00285     // HTTP
00286     // ----------------------------------------------------------------
00287     
00288     //! Type of HTTP Operational Codes (reference to HTTP control +UHTTP) 
00289     typedef enum { HTTP_IP_ADDRESS, HTTP_SERVER_NAME, HTTP_USER_NAME, HTTP_PASSWORD, \
00290                    HTTP_AUTH_TYPE, HTTP_SERVER_PORT, HTTP_SECURE } HttpOpCode;
00291     
00292     //! Type of HTTP Commands (reference to HTTP command +UHTTPC)
00293     typedef enum { HTTP_HEAD, HTTP_GET, HTTP_DELETE, HTTP_PUT, \
00294                    HTTP_POST_FILE, HTTP_POST_DATA } HttpCmd;
00295     
00296     //! HTTP Profile error return codes
00297     #define HTTP_PROF_ERROR -1
00298     
00299     /** find HTTP profile
00300         \return true if successfully, false otherwise
00301     */
00302     int httpFindProfile();
00303     
00304     /** get the number of bytes pending for reading for this HTTP profile
00305         \param profile the HTTP profile handle
00306         \param timeout_ms -1 blocking, else non blocking timeout in ms
00307         \return 0 if successful or SOCKET_ERROR on failure 
00308     */
00309     bool httpSetBlocking(int profile, int timeout_ms);
00310     
00311     /** set the HTTP profile for commands management
00312         \param profile the HTTP profile handle
00313         \return true if successfully, false otherwise
00314     */
00315     bool httpSetProfileForCmdMng(int profile);
00316     
00317     /** free the HTTP profile
00318         \param profile the HTTP profile handle
00319         \return true if successfully, false otherwise
00320     */
00321     bool httpFreeProfile(int profile);
00322     
00323     /** reset HTTP profile
00324         \param httpProfile the HTTP profile to be reset
00325         \return true if successfully, false otherwise
00326     */
00327     bool httpResetProfile(int httpProfile);
00328     
00329     /** set HTTP parameters
00330         \param httpProfile the HTTP profile identifier
00331         \param httpOpCode the HTTP operation code
00332         \param httpInPar the HTTP input parameter
00333         \return true if successfully, false otherwise
00334     */
00335     bool httpSetPar(int httpProfile, HttpOpCode httpOpCode, const char * httpInPar);
00336     
00337     /** HTTP commands management
00338         \param httpProfile the HTTP profile identifier
00339         \param httpCmdCode the HTTP command code
00340         \param httpPath the path of HTTP server resource
00341         \param httpOut the filename where the HTTP server response will be stored
00342         \param httpIn the input data (filename or string) to be sent 
00343                       to the HTTP server with the command request
00344         \param httpContentType the HTTP Content-Type identifier
00345         \param httpCustomPar the parameter for an user defined HTTP Content-Type
00346         \param buf the buffer to read into
00347         \param len the size of the buffer to read into
00348         \return true if successfully, false otherwise
00349     */
00350     bool httpCommand(int httpProfile, HttpCmd httpCmdCode, const char* httpPath, \
00351                      const char* httpOut, const char* httpIn, int httpContentType, \
00352                      const char* httpCustomPar, char* buf, int len);
00353     
00354     /** get HTTP commands
00355         \param httpCmdCode the HTTP command code (reference also the enum format)
00356         \return HTTP command in string format
00357     */
00358     const char* getHTTPcmd(int httpCmdCode);
00359     
00360     // ----------------------------------------------------------------
00361     // SMS Short Message Service
00362     // ----------------------------------------------------------------
00363     
00364     /** count the number of sms in the device and optionally return a 
00365         list with indexes from the storage locations in the device.
00366         \param stat what type of messages you can use use 
00367                     "REC UNREAD", "REC READ", "STO UNSENT", "STO SENT", "ALL"
00368         \param ix   list where to save the storage positions
00369         \param num  number of elements in the list 
00370         \return the number of messages, this can be bigger than num, -1 on failure
00371     */
00372     int smsList(const char* stat = "ALL", int* ix = NULL, int num = 0);
00373     
00374     /** Read a Message from a storage position
00375         \param ix the storage position to read
00376         \param num the originator address (~16 chars)
00377         \param buf a buffer where to save the sm
00378         \param len the length of the sm
00379         \return true if successful, false otherwise
00380     */
00381     bool smsRead(int ix, char* num, char* buf, int len);
00382     
00383     /** Send a message to a recipient 
00384         \param ix the storage position to delete
00385         \return true if successful, false otherwise
00386     */
00387     bool smsDelete(int ix);
00388     
00389     /** Send a message to a recipient 
00390         \param num the phone number of the recipient
00391         \param buf the content of the message to sent
00392         \return true if successful, false otherwise
00393     */
00394     bool smsSend(const char* num, const char* buf);
00395     
00396     // ----------------------------------------------------------------
00397     // USSD Unstructured Supplementary Service Data
00398     // ----------------------------------------------------------------
00399     
00400     /** Read a Message from a storage position
00401         \param cmd the ussd command to send e.g "*#06#"
00402         \param buf a buffer where to save the reply
00403         \return true if successful, false otherwise
00404     */
00405     bool ussdCommand(const char* cmd, char* buf);
00406     
00407     // ----------------------------------------------------------------
00408     // FILE 
00409     // ----------------------------------------------------------------
00410     
00411     /** Delete a file in the local file system
00412         \param filename the name of the file 
00413         \return true if successful, false otherwise
00414     */
00415     bool delFile(const char* filename);
00416     
00417     /** Write some data to a file in the local file system
00418         \param filename the name of the file 
00419         \param buf the data to write 
00420         \param len the size of the data to write
00421         \return the number of bytes written
00422     */
00423     int writeFile(const char* filename, const char* buf, int len);
00424     
00425     /** Read a file from the local file system
00426         \param filename the name of the file 
00427         \param buf a buffer to hold the data 
00428         \param len the size to read
00429         \return the number of bytes read
00430     */
00431     int readFile(const char* filename, char* buf, int len);
00432     
00433     /** Read a file from the local file system
00434         (the file size is greater than MAX_SIZE bytes)
00435         \param filename the name of the file 
00436         \param buf a buffer to hold the data 
00437         \param len the size to read
00438         \return the number of bytes read
00439     */
00440     int readFileNew(const char* filename, char* buf, int len);
00441     
00442     /** Retrieve information about the dimension of a file from the local FFS
00443         \param filename the name of the file
00444         \return the file dimension in number of bytes 
00445     */
00446     int infoFile(const char* filename);
00447     
00448     // ----------------------------------------------------------------
00449     // CellLocate
00450     // ----------------------------------------------------------------
00451 
00452      /** Configures CellLocate Tcp Aiding server
00453         \server_1   Host name of the primary MGA server
00454         \server_2   Host name of the secondary MGA server
00455         \token      Authentication Token for MGA server access
00456         \days       The number of days into the future the Offline data for the u-blox 7
00457         \period     The number of weeks into the future the Offline data for u-blox M8
00458         \resolution Resolution of offline data for u-blox M8: 1 everyday, 0 every other day
00459     */
00460     int cellLocSrvTcp(const char* token, const char* server_1 = "cell-live1.services.u-blox.com", \
00461             const char* server_2 = "cell-live2.services.u-blox.com", int days = 14, int period = 4, int resolution = 1);
00462 
00463     /** Configures  CellLocate Udp Aiding server
00464         \server_1   Host name of the primary MGA server
00465         \port       Server port
00466         \latency    Expected network latency in seconds from 0 to 10000ms
00467         \mode       Assist now management, mode of operation: 0 data downloaded at GNSS power up,
00468                     1 automatically kept alive, manual download
00469     */
00470     int cellLocSrvUdp(const char* server_1 = "cell-live1.services.u-blox.com", int port = 46434, int latency = 1000, int mode = 0);
00471 
00472     /** Configures CellLocate URCs in the case of +ULOC operations
00473         \mode       Urc configuration: 0 disabled, 1 enabled
00474      */
00475     int cellLocUnsol(int mode);
00476 
00477     /**  Configures CellLocate location sensor 
00478          \scanMode Network scan mode: 0 normal, 1 deep scan
00479      */
00480     int cellLocConfig(int scanMode);
00481 
00482     /** Request CellLocate 
00483         This function is not blocking, the result has to be retrived using cellLocGet
00484          \sensor        Sensor selection: 
00485          \timeout       Timeout period in seconds (1 - 999)
00486          \accuracy      Target accuracy in meters (1 - 999999)
00487          \type
00488          \hypotesis  Maximum desired number of responses from CellLocate® (up to 16)
00489      */
00490     int cellLocRequest(CellSensType sensor, int timeout, int accuracy, CellRespType type = CELL_DETAILED,int hypotesis = 1);
00491 
00492     /** Get a position record
00493         \data pointer to a CellLocData struct where the location will be copied in
00494         \index of the position to retrive
00495         \return 1 if data has been retrived and copied, 0 otherwise
00496     */
00497     int cellLocGetData(CellLocData *data, int index =0);
00498     
00499     /** Get number of position records received       
00500         \return number of position received
00501     */
00502     int cellLocGetRes();
00503     /** Get expected number of position to be received       
00504         \return number of expected position to be received
00505     */
00506     int cellLocGetExpRes();
00507     
00508     // ----------------------------------------------------------------
00509     // DEBUG/DUMP status to standard out (printf)
00510     // ----------------------------------------------------------------
00511     
00512     /*! Set the debug level 
00513         \param level -1 = OFF, 0 = ERROR, 1 = INFO(default), 2 = TRACE, 3 = ATCMD,TEST
00514         \return true if successful, false not possible
00515     */ 
00516     bool setDebug (int level);
00517 
00518     //! helper type for DPRINT
00519     typedef int (*_DPRINT)(void* param, char const * format, ...);
00520     
00521     //! helper to declate templates and void versions
00522 #define _DUMP_TEMPLATE(func, type, arg) \
00523     template<class T> \
00524     inline void func(type arg, \
00525                 int (*dprint)( T* param, char const * format, ...), \
00526                 T* param) { func(arg, (_DPRINT)dprint, (void*)param); } \
00527     static void func(type arg, \
00528                 _DPRINT dprint = (_DPRINT)fprintf, \
00529                 void* param = (void*)stdout);
00530 
00531     /** dump the device status to stdout using printf
00532         \param status the status to convert to textual form, 
00533                unavailable fields are ommited (not printed)
00534         \param dprint a function pointer
00535         \param param  the irst argument passed to dprint
00536     */
00537     _DUMP_TEMPLATE(dumpDevStatus, MDMParser::DevStatus*, status)
00538 
00539     /** dump the network status to stdout using printf
00540         \param status the status to convert to textual form, 
00541                unavailable fields are ommited (not printed)
00542         \param dprint a function pointer
00543         \param param  the irst argument passed to dprint
00544     */
00545     _DUMP_TEMPLATE(dumpNetStatus, MDMParser::NetStatus*, status)
00546     
00547     /** dump the ip address to stdout using printf
00548         \param ip the ip to convert to textual form, 
00549                unavailable fields are ommited (not printed)
00550         \param dprint a function pointer
00551         \param param  the irst argument passed to dprint
00552     */
00553     _DUMP_TEMPLATE(dumpIp, MDMParser::IP, ip)
00554    
00555     // ----------------------------------------------------------------
00556     // Parseing
00557     // ----------------------------------------------------------------
00558     
00559     enum { 
00560         // waitFinalResp Responses
00561         NOT_FOUND     =  0,
00562         WAIT          = -1, // TIMEOUT
00563         RESP_OK       = -2, 
00564         RESP_ERROR    = -3,
00565         RESP_PROMPT   = -4,
00566         RESP_ERROR_CME= -5,
00567     
00568         // getLine Responses
00569         #define LENGTH(x)  (x & 0x00FFFF) //!< extract/mask the length
00570         #define TYPE(x)    (x & 0xFF0000) //!< extract/mask the type
00571         
00572         TYPE_UNKNOWN    = 0x000000,
00573         TYPE_OK         = 0x110000,
00574         TYPE_ERROR      = 0x120000,
00575         TYPE_ERROR_CME  = 0x130000,
00576         TYPE_RING       = 0x210000,
00577         TYPE_CONNECT    = 0x220000,
00578         TYPE_NOCARRIER  = 0x230000,
00579         TYPE_NODIALTONE = 0x240000,
00580         TYPE_BUSY       = 0x250000,
00581         TYPE_NOANSWER   = 0x260000,
00582         TYPE_PROMPT     = 0x300000,
00583         TYPE_PLUS       = 0x400000,
00584         TYPE_TEXT       = 0x500000,
00585         
00586         // special timout constant
00587         TIMEOUT_BLOCKING = -1
00588     };
00589     
00590     /** Get a line from the physical interface. This function need 
00591         to be implemented in a inherited class. Usually just calls 
00592         #_getLine on the rx buffer pipe. 
00593             
00594         \param buf the buffer to store it
00595         \param buf size of the buffer
00596         \return type and length if something was found, 
00597                 WAIT if not enough data is available
00598                 NOT_FOUND if nothing was found
00599     */ 
00600     virtual int getLine(char* buf, int len) = 0; 
00601     
00602     /* clear the pending input data
00603     */
00604     virtual void purge(void) = 0;
00605     
00606     /** Write data to the device 
00607         \param buf the buffer to write
00608         \param buf size of the buffer to write
00609         \return bytes written
00610     */
00611     virtual int send(const char* buf, int len);
00612     
00613     /** Write formated date to the physical interface (printf style)
00614         \param fmt the format string
00615         \param .. variable arguments to be formated
00616         \return bytes written
00617     */
00618     int sendFormated(const char* format, ...);
00619     
00620     /** callback function for #waitFinalResp with void* as argument
00621         \param type the #getLine response
00622         \param buf the parsed line
00623         \param len the size of the parsed line
00624         \param param the optional argument passed to #waitFinalResp
00625         \return WAIT if processing should continue, 
00626                 any other value aborts #waitFinalResp and this retunr value retuned
00627     */
00628     typedef int (*_CALLBACKPTR)(int type, const char* buf, int len, void* param);
00629     
00630     /** Wait for a final respons
00631         \param cb the optional callback function
00632         \param param the optional callback function parameter
00633         \param timeout_ms the timeout to wait (See Estimated command 
00634                response time of AT manual)
00635     */
00636     int waitFinalResp(_CALLBACKPTR cb = NULL, 
00637                       void* param = NULL, 
00638                       int timeout_ms = 10000);
00639 
00640     /** template version of #waitFinalResp when using callbacks, 
00641         This template will allow the compiler to do type cheking but 
00642         internally symply casts the arguments and call the (void*) 
00643         version of #waitFinalResp.
00644         \sa waitFinalResp
00645     */ 
00646     template<class T>
00647     inline int waitFinalResp(int (*cb)(int type, const char* buf, int len, T* param), 
00648                     T* param, 
00649                     int timeout_ms = 10000) 
00650     {
00651         return waitFinalResp((_CALLBACKPTR)cb, (void*)param, timeout_ms);
00652     }
00653     
00654 protected:
00655     /** Write bytes to the physical interface. This function should be 
00656         implemented in a inherited class.
00657         \param buf the buffer to write
00658         \param buf size of the buffer to write
00659         \return bytes written
00660     */
00661     virtual int _send(const void* buf, int len) = 0;
00662 
00663     /** Helper: Parse a line from the receiving buffered pipe
00664         \param pipe the receiving buffer pipe 
00665         \param buf the parsed line
00666         \param len the size of the parsed line
00667         \return type and length if something was found, 
00668                 WAIT if not enough data is available
00669                 NOT_FOUND if nothing was found
00670     */
00671     static int _getLine(Pipe<char> * pipe, char* buffer, int length);
00672     
00673     /** Helper: Parse a match from the pipe
00674         \param pipe the buffered pipe
00675         \param number of bytes to parse at maximum, 
00676         \param sta the starting string, NULL if none
00677         \param end the terminating string, NULL if none
00678         \return size of parsed match 
00679     */   
00680     static int _parseMatch(Pipe<char> * pipe, int len, const char* sta, const char* end);
00681     
00682     /** Helper: Parse a match from the pipe
00683         \param pipe the buffered pipe
00684         \param number of bytes to parse at maximum, 
00685         \param fmt the formating string (%d any number, %c any char of last %d len)
00686         \return size of parsed match
00687     */   
00688     static int _parseFormated(Pipe<char> * pipe, int len, const char* fmt);
00689 
00690 protected:
00691     // for rtos over riding by useing Rtos<MDMxx> 
00692     /** override in a rtos system, you us the wait function of a Thread
00693         \param ms the number of milliseconds to wait
00694     */
00695     virtual void wait_ms(int ms)   { if (ms) ::wait_ms(ms); }
00696     //! override the lock in a rtos system
00697     virtual void lock(void)        { } 
00698     //! override the unlock in a rtos system
00699     virtual void unlock(void)      { } 
00700 protected:
00701     bool _activateProfile(const char* apn, const char* username, const char* password, Auth auth);
00702     bool _activateProfileReuseExternal(void);
00703     bool _activateProfileByCid(int cid, const char* apn, const char* username, const char* password, Auth auth);
00704     // parsing callbacks for different AT commands and their parameter arguments
00705     static int _cbString(int type, const char* buf, int len, char* str);
00706     static int _cbInt(int type, const char* buf, int len, int* val);
00707     // device
00708     static int _cbATI(int type, const char* buf, int len, Dev* dev);
00709     static int _cbCPIN(int type, const char* buf, int len, Sim* sim);
00710     static int _cbCCID(int type, const char* buf, int len, char* ccid);
00711     // network 
00712     static int _cbCSQ(int type, const char* buf, int len, NetStatus* status);
00713     static int _cbCOPS(int type, const char* buf, int len, NetStatus* status);
00714     static int _cbCNUM(int type, const char* buf, int len, char* num);
00715     static int _cbUACTIND(int type, const char* buf, int len, int* i);
00716     static int _cbCGDCONT(int type, const char* buf, int len, int* cid);
00717     static int _cbUDOPN(int type, const char* buf, int len, char* mccmnc);
00718     // sockets
00719     static int _cbCMIP(int type, const char* buf, int len, IP* ip);
00720     static int _cbUPSND(int type, const char* buf, int len, int* act);
00721     static int _cbUPSND(int type, const char* buf, int len, IP* ip);
00722     static int _cbUDNSRN(int type, const char* buf, int len, IP* ip);
00723     static int _cbUSOCR(int type, const char* buf, int len, int* handle);
00724     static int _cbUSORD(int type, const char* buf, int len, char* out);
00725     typedef struct { char* buf; IP ip; int port; } USORFparam;
00726     static int _cbUSORF(int type, const char* buf, int len, USORFparam* param);
00727     typedef struct { char* buf; char* num; } CMGRparam;
00728     static int _cbCUSD(int type, const char* buf, int len, char* resp);
00729     // sms
00730     typedef struct { int* ix; int num; } CMGLparam;
00731     static int _cbCMGL(int type, const char* buf, int len, CMGLparam* param);
00732     static int _cbCMGR(int type, const char* buf, int len, CMGRparam* param);
00733     // file
00734     typedef struct { const char* filename; char* buf; int sz; int len; } URDFILEparam;
00735     static int _cbUDELFILE(int type, const char* buf, int len, void*);
00736     static int _cbURDFILE(int type, const char* buf, int len, URDFILEparam* param);
00737     static int _cbURDBLOCK(int type, const char* buf, int len, char* out);
00738     static int _cbULSTFILE(int type, const char* buf, int len, int* infoFile);
00739     // variables
00740     DevStatus   _dev; //!< collected device information
00741     NetStatus   _net; //!< collected network information 
00742     IP          _ip;  //!< assigned ip address
00743     CellLocData _loc[CELL_MAX_HYP]; //!< CellLocate data
00744     // management struture for sockets
00745     typedef struct { int handle; int timeout_ms; volatile bool connected; volatile int pending; } SockCtrl;
00746     // LISA-C has 6 TCP and 6 UDP sockets 
00747     // LISA-U and SARA-G have 7 sockets
00748     SockCtrl _sockets[12];
00749     int _findSocket(int handle = SOCKET_ERROR/* = CREATE*/);
00750     // management structure for HTTP profiles
00751     // it's possible to have up to 4 different HTTP profiles (LISA-C200, LISA-U200 and SARA-G350) having:
00752     // param handle the current HTTP profile is in handling state or not (default value is HTTP_ERROR)
00753     // param timeout_ms the timeout for the current HTTP command
00754     // param pending the status for the current HTTP command (in processing state or not)
00755     // param cmd the code for the current HTTP command
00756     // param result the result for the current HTTP command once processed
00757     typedef struct {  int handle; int timeout_ms; bool pending; int cmd; int result; } HttpProfCtrl;
00758     HttpProfCtrl _httpProfiles[4];
00759     int _findProfile(int handle = HTTP_PROF_ERROR/* = CREATE*/);
00760     static MDMParser* inst;
00761     bool _init;
00762 #ifdef TARGET_UBLOX_C027
00763     bool _onboard;
00764 #endif
00765     
00766 #ifdef MDM_DEBUG
00767    
00768     Timer _debugTime;
00769     void _debugPrint(int level, const char* color, const char* format, ...);
00770 #endif
00771 };
00772 
00773 // -----------------------------------------------------------------------
00774 
00775 /** modem class which uses a serial port 
00776     as physical interface. 
00777 */
00778 class MDMSerial :  public SerialPipe, public MDMParser
00779 {
00780 public: 
00781     /** Constructor
00782     
00783         \param tx is the serial ports transmit pin (modem to CPU)
00784         \param rx is the serial ports receive pin (CPU to modem)
00785         \param baudrate the baudrate of the modem use 115200
00786         \param rts is the serial ports ready to send pin (CPU to modem) 
00787                this pin is optional 
00788         \param cts is the serial ports clear to send pin (modem to CPU) 
00789                this pin is optional, but required for power saving to be enabled
00790         \param rxSize the size of the serial rx buffer
00791         \param txSize the size of the serial tx buffer
00792     */
00793     MDMSerial(PinName tx    MDM_IF( = MDMTXD,  = D1 ), 
00794               PinName rx    MDM_IF( = MDMRXD,  = D0 ), 
00795               int baudrate  MDM_IF( = MDMBAUD, = 115200 ),
00796  #if DEVICE_SERIAL_FC
00797               PinName rts   MDM_IF( = MDMRTS,  = NC /* D2 resistor R62 on shield not mounted */ ), 
00798               PinName cts   MDM_IF( = MDMCTS,  = NC /* D3 resistor R63 on shield not mounted */ ),
00799  #endif
00800               int rxSize    = 256 , 
00801               int txSize    = 128 );
00802     //! Destructor          
00803     virtual ~MDMSerial(void);
00804      
00805     /** Get a line from the physical interface. 
00806         \param buf the buffer to store it
00807         \param buf size of the buffer
00808         \return type and length if something was found, 
00809                 WAIT if not enough data is available
00810                 NOT_FOUND if nothing was found
00811     */ 
00812     virtual int getLine(char* buffer, int length);
00813     
00814     /* clear the pending input data */
00815     virtual void purge(void) 
00816     { 
00817         while (readable())
00818             getc();
00819     }
00820 protected:
00821     /** Write bytes to the physical interface.
00822         \param buf the buffer to write
00823         \param buf size of the buffer to write
00824         \return bytes written
00825     */
00826     virtual int _send(const void* buf, int len);
00827 };
00828 
00829 // -----------------------------------------------------------------------
00830 
00831 //#define HAVE_MDMUSB
00832 #ifdef HAVE_MDMUSB
00833 class MDMUsb :  /*public UsbSerial,*/ public MDMParser
00834 {
00835 public: 
00836     //! Constructor          
00837     MDMUsb(void);
00838     //! Destructor          
00839     virtual ~MDMUsb(void);
00840     virtual int getLine(char* buffer, int length);
00841     virtual void purge(void) { }
00842 protected:
00843     virtual int _send(const void* buf, int len);
00844 };
00845 #endif
00846 
00847 // -----------------------------------------------------------------------
00848 
00849 #ifdef RTOS_H
00850 /** Use this template to override the lock and wait functions of the 
00851     modem driver in a Rtos system. For example declare it the modem 
00852     object as MDMRtos<MDMSerial> instead of MDMSerial.
00853 */
00854 template <class T>
00855 class MDMRtos :  public T
00856 {
00857 protected:
00858     //! we assume that the modem runs in a thread so we yield when waiting
00859     virtual void wait_ms(int ms)   {
00860         if (ms) Thread::wait(ms);
00861         else    Thread::yield();
00862     }
00863     //! lock a mutex when accessing the modem
00864     virtual void lock(void)     { _mtx.lock(); }  
00865     //! unlock the modem when done accessing it
00866     virtual void unlock(void)   { _mtx.unlock(); }
00867     // the mutex resource
00868     Mutex _mtx;
00869 };
00870 #endif