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.

Dependents:   HTTPClient_Cellular_HelloWorld Cellular_HelloMQTT MbedSmartRestMain Car_Bon_car_module ... more

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