final 1

Fork of C027_Support by jajn HA

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  #define MDM_IF(onboard,shield) onboard
00011 #else
00012  #define MDM_IF(onboard,shield) shield
00013 #endif
00014 
00015 //! include debug capabilty on more powerful targets with a dedicated debug port 
00016 #if defined(TARGET_LPC1768) || defined(TARGET_LPC4088) || defined(TARGET_K64F)
00017  #define MDM_DEBUG 
00018 #endif 
00019 
00020 /** basic modem parser class 
00021 */
00022 class MDMParser
00023 {
00024 public:
00025     //! Constructor 
00026     MDMParser(void);
00027     //! get static instance
00028     static MDMParser* getInstance() { return inst; };
00029     
00030     // ----------------------------------------------------------------
00031     // Types 
00032     // ----------------------------------------------------------------
00033     //! MT Device Types 
00034     typedef enum { DEV_UNKNOWN, 
00035                    DEV_SARA_G35, DEV_LISA_U2, DEV_LISA_C2, 
00036                    DEV_SARA_U2, DEV_LEON_G2, DEV_TOBY_L2, DEV_MPCI_L2 } Dev; 
00037     //! SIM Status
00038     typedef enum { SIM_UNKNOWN, SIM_MISSING, SIM_PIN, SIM_READY } Sim;
00039     //! SIM Status
00040     typedef enum { LPM_DISABLED, LPM_ENABLED, LPM_ACTIVE } Lpm; 
00041     //! Device status
00042     typedef struct { 
00043         Dev dev;            //!< Device Type
00044         Lpm lpm;            //!< Power Saving 
00045         Sim sim;            //!< SIM Card Status
00046         char ccid[20+1];    //!< Integrated Circuit Card ID
00047         char imsi[15+1];    //!< International Mobile Station Identity
00048         char imei[15+1];    //!< International Mobile Equipment Identity
00049         char meid[18+1];    //!< Mobile Equipment IDentifier
00050         char manu[16];      //!< Manufacturer (u-blox)
00051         char model[16];     //!< Model Name (LISA-U200, LISA-C200 or SARA-G350)
00052         char ver[16];       //!< Software Version
00053     } DevStatus;
00054     //! Registration Status
00055     typedef enum { REG_UNKNOWN, REG_DENIED, REG_NONE, REG_HOME, REG_ROAMING } Reg; 
00056     //! Access Technology
00057     typedef enum { ACT_UNKNOWN, ACT_GSM, ACT_EDGE, ACT_UTRAN, ACT_CDMA, ACT_LTE } AcT; 
00058     //! Network Status
00059     typedef struct { 
00060         Reg csd;        //!< CSD Registration Status (Circuit Switched Data)
00061         Reg psd;        //!< PSD Registration status (Packet Switched Data)
00062         Reg eps;        //!< EPS Registration status
00063         AcT act;        //!< Access Technology
00064         int rssi;       //!< Received Signal Strength Indication (in dBm, range -113..-51)
00065         int ber;        //!< Bit Error Rate (BER), see 3GPP TS 45.008 [20] subclause 8.2.4
00066         char opr[16+1]; //!< Operator Name
00067         char num[32];   //!< Mobile Directory Number
00068         unsigned short lac;  //!< location area code in hexadecimal format (2 bytes in hex)
00069         unsigned int ci;     //!< Cell ID in hexadecimal format (2 to 4 bytes in hex)
00070     } NetStatus;
00071     //! An IP v4 address
00072     typedef uint32_t IP;
00073     #define NOIP ((MDMParser::IP)0) //!< No IP address
00074     // ip number formating and conversion
00075     #define IPSTR           "%d.%d.%d.%d"
00076     #define IPNUM(ip)       ((ip)>>24)&0xff, \
00077                             ((ip)>>16)&0xff, \
00078                             ((ip)>> 8)&0xff, \
00079                             ((ip)>> 0)&0xff
00080     #define IPADR(a,b,c,d) ((((IP)(a))<<24) | \
00081                             (((IP)(b))<<16) | \
00082                             (((IP)(c))<< 8) | \
00083                             (((IP)(d))<< 0))
00084 
00085     
00086     // ----------------------------------------------------------------
00087     // Device 
00088     // ----------------------------------------------------------------
00089     
00090     typedef enum { AUTH_NONE, AUTH_PAP, AUTH_CHAP, AUTH_DETECT } Auth; 
00091     
00092     /** Combined Init, checkNetStatus, join suitable for simple applications
00093         \param simpin a optional pin of the SIM card
00094         \param apn  the of the network provider e.g. "internet" or "apn.provider.com"
00095         \param username is the user name text string for the authentication phase
00096         \param password is the password text string for the authentication phase
00097         \param auth is the authentication mode (CHAP,PAP,NONE or DETECT)
00098         \return true if successful, false otherwise
00099     */
00100     bool connect(const char* simpin = NULL, 
00101             const char* apn = NULL, const char* username = NULL, 
00102             const char* password = NULL, Auth auth = AUTH_DETECT,
00103             PinName pn MDM_IF( = MDMPWRON, = D4));    
00104 
00105     /** register (Attach) the MT to the GPRS service. 
00106         \param simpin a optional pin of the SIM card
00107         \param status an optional struture to with device information 
00108         \return true if successful, false otherwise
00109     */
00110     virtual bool init(const char* simpin = NULL, DevStatus* status = NULL, 
00111                 PinName pn MDM_IF( = MDMPWRON, = D4));
00112 
00113     /** get the current device status
00114         \param strocture holding the device information. 
00115     */
00116     void getDevStatus(MDMParser::DevStatus* dev) { memcpy(dev, &_dev, sizeof(DevStatus)); }
00117     
00118     /** register to the network 
00119         \param status an optional structure to with network information 
00120         \param timeout_ms -1 blocking, else non blocking timeout in ms
00121         \return true if successful and connected to network, false otherwise
00122     */
00123     bool registerNet(NetStatus* status = NULL, int timeout_ms = 180000);
00124     
00125     /** check if the network is available 
00126         \param status an optional structure to with network information 
00127         \return true if successful and connected to network, false otherwise
00128     */
00129     bool checkNetStatus(NetStatus* status = NULL);
00130     
00131     /** Power off the MT, This function has to be called prior to 
00132         switching off the supply. 
00133         \return true if successfully, false otherwise
00134     */ 
00135     bool powerOff(void);
00136     
00137     // ----------------------------------------------------------------
00138     // Data Connection (GPRS)
00139     // ----------------------------------------------------------------
00140     
00141     /** register (Attach) the MT to the GPRS service. 
00142         \param apn  the of the network provider e.g. "internet" or "apn.provider.com"
00143         \param username is the user name text string for the authentication phase
00144         \param password is the password text string for the authentication phase
00145         \param auth is the authentication mode (CHAP,PAP,NONE or DETECT)
00146         \return the ip that is assigned 
00147     */
00148     MDMParser::IP join(const char* apn = NULL, const char* username = NULL, 
00149                        const char* password = NULL, Auth auth = AUTH_DETECT);
00150     
00151     /** deregister (detach) the MT from the GPRS service.
00152         \return true if successful, false otherwise
00153     */
00154     bool disconnect(void);
00155     
00156     /** Translates a domain name to an IP address
00157         \param host the domain name to translate e.g. "u-blox.com"
00158         \return the IP if successful, 0 otherwise
00159     */
00160     MDMParser::IP gethostbyname(const char* host);
00161     
00162     /** get the current assigned IP address
00163         \return the ip that is assigned 
00164     */
00165     MDMParser::IP getIpAddress(void) { return _ip; }
00166 
00167     // ----------------------------------------------------------------
00168     // Sockets
00169     // ----------------------------------------------------------------
00170     
00171     //! Type of IP protocol 
00172     typedef enum { IPPROTO_TCP, IPPROTO_UDP } IpProtocol; 
00173     
00174     //! Socket error return codes
00175     #define SOCKET_ERROR -1
00176     
00177     /** Create a socket for a ip protocol (and optionaly bind)
00178         \param ipproto the protocol (UDP or TCP) 
00179         \param port in case of UDP, this optional port where it is bind
00180         \return the socket handle if successful or SOCKET_ERROR on failure 
00181     */
00182     int socketSocket(IpProtocol ipproto, int port = -1);
00183     
00184     /** make a socket connection
00185         \param socket the socket handle
00186         \param host the domain name to connect e.g. "u-blox.com"
00187         \param port the port to connect
00188         \return true if successfully, false otherwise
00189     */
00190     bool socketConnect(int socket, const char* host, int port);
00191         
00192     /** make a socket connection
00193         \param socket the socket handle
00194         \return true if connected, false otherwise
00195     */
00196     bool socketIsConnected(int socket);
00197      
00198     /** Get the number of bytes pending for reading for this socket
00199         \param socket the socket handle
00200         \param timeout_ms -1 blocking, else non blocking timeout in ms
00201         \return 0 if successful or SOCKET_ERROR on failure 
00202     */
00203     bool socketSetBlocking(int socket, int timeout_ms);
00204     
00205     /** Write socket data 
00206         \param socket the socket handle
00207         \param buf the buffer to write
00208         \param len the size of the buffer to write
00209         \return the size written or SOCKET_ERROR on failure 
00210     */
00211     int socketSend(int socket, const char * buf, int len);
00212     
00213     /** Write socket data to a IP
00214         \param socket the socket handle
00215         \param ip the ip to send to
00216         \param port the port to send to
00217         \param buf the buffer to write
00218         \param len the size of the buffer to write
00219         \return the size written or SOCKET_ERROR on failure 
00220     */
00221     int socketSendTo(int socket, IP ip, int port, const char * buf, int len);
00222     
00223     /** Get the number of bytes pending for reading for this socket
00224         \param socket the socket handle
00225         \return the number of bytes pending or SOCKET_ERROR on failure 
00226     */
00227     int socketReadable(int socket);
00228     
00229     /** Read this socket
00230         \param socket the socket handle
00231         \param buf the buffer to read into
00232         \param len the size of the buffer to read into
00233         \return the number of bytes read or SOCKET_ERROR on failure 
00234     */
00235     int socketRecv(int socket, char* buf, int len);
00236     
00237     /** Read from this socket
00238         \param socket the socket handle
00239         \param ip the ip of host where the data originates from
00240         \param port the port where the data originates from
00241         \param buf the buffer to read into
00242         \param len the size of the buffer to read into
00243         \return the number of bytes read or SOCKET_ERROR on failure 
00244     */
00245     int socketRecvFrom(int socket, IP* ip, int* port, char* buf, int len);
00246     
00247     /** Close a connectied socket (that was connected with #socketConnect)
00248         \param socket the socket handle
00249         \return true if successfully, false otherwise
00250     */    
00251     bool socketClose(int socket);
00252     
00253     /** Free the socket (that was allocated before by #socketSocket)
00254         \param socket the socket handle
00255         \return true if successfully, false otherwise
00256     */    
00257     bool socketFree(int socket);
00258         
00259     // ----------------------------------------------------------------
00260     // SMS Short Message Service
00261     // ----------------------------------------------------------------
00262     
00263     /** count the number of sms in the device and optionally return a 
00264         list with indexes from the storage locations in the device.
00265         \param stat what type of messages you can use use 
00266                     "REC UNREAD", "REC READ", "STO UNSENT", "STO SENT", "ALL"
00267         \param ix   list where to save the storage positions
00268         \param num  number of elements in the list 
00269         \return the number of messages, this can be bigger than num, -1 on failure
00270     */
00271     int smsList(const char* stat = "ALL", int* ix = NULL, int num = 0);
00272     
00273     /** Read a Message from a storage position
00274         \param ix the storage position to read
00275         \param num the originator address (~16 chars)
00276         \param buf a buffer where to save the sm
00277         \param len the length of the sm
00278         \return true if successful, false otherwise
00279     */
00280     bool smsRead(int ix, char* num, char* buf, int len);
00281     
00282     /** Send a message to a recipient 
00283         \param ix the storage position to delete
00284         \return true if successful, false otherwise
00285     */
00286     bool smsDelete(int ix);
00287     
00288     /** Send a message to a recipient 
00289         \param num the phone number of the recipient
00290         \param buf the content of the message to sent
00291         \return true if successful, false otherwise
00292     */
00293     bool smsSend(const char* num, const char* buf);
00294     
00295     // ----------------------------------------------------------------
00296     // USSD Unstructured Supplementary Service Data
00297     // ----------------------------------------------------------------
00298     
00299     /** Read a Message from a storage position
00300         \param cmd the ussd command to send e.g "*#06#"
00301         \param buf a buffer where to save the reply
00302         \return true if successful, false otherwise
00303     */
00304     bool ussdCommand(const char* cmd, char* buf);
00305     
00306     // ----------------------------------------------------------------
00307     // FILE 
00308     // ----------------------------------------------------------------
00309     
00310     /** Delete a file in the local file system
00311         \param filename the name of the file 
00312         \return true if successful, false otherwise
00313     */
00314     bool delFile(const char* filename);
00315     
00316     /** Write some data to a file in the local file system
00317         \param filename the name of the file 
00318         \param buf the data to write 
00319         \param len the size of the data to write
00320         \return the number of bytes written
00321     */
00322     int writeFile(const char* filename, const char* buf, int len);
00323     
00324     /** REad a file from the local file system
00325         \param filename the name of the file 
00326         \param buf a buffer to hold the data 
00327         \param len the size to read
00328         \return the number of bytes read
00329     */
00330     int readFile(const char* filename, char* buf, int len);
00331     
00332     // ----------------------------------------------------------------
00333     // DEBUG/DUMP status to standard out (printf)
00334     // ----------------------------------------------------------------
00335     
00336     /*! Set the debug level 
00337         \param level -1 = OFF, 0 = ERROR, 1 = INFO(default), 2 = TRACE, 3 = ATCMD,TEST
00338         \return true if successful, false not possible
00339     */ 
00340     bool setDebug (int level);
00341 
00342     //! helper type for DPRINT
00343     typedef int (*_DPRINT)(void* param, char const * format, ...);
00344     
00345     //! helper to declate templates and void versions
00346 #define _DUMP_TEMPLATE(func, type, arg) \
00347     template<class T> \
00348     inline void func(type arg, \
00349                 int (*dprint)( T* param, char const * format, ...), \
00350                 T* param) { func(arg, (_DPRINT)dprint, (void*)param); } \
00351     static void func(type arg, \
00352                 _DPRINT dprint = (_DPRINT)fprintf, \
00353                 void* param = (void*)stdout);
00354 
00355     /** dump the device status to stdout using printf
00356         \param status the status to convert to textual form, 
00357                unavailable fields are ommited (not printed)
00358         \param dprint a function pointer
00359         \param param  the irst argument passed to dprint
00360     */
00361     _DUMP_TEMPLATE(dumpDevStatus, MDMParser::DevStatus*, status)
00362 
00363     /** dump the network status to stdout using printf
00364         \param status the status to convert to textual form, 
00365                unavailable fields are ommited (not printed)
00366         \param dprint a function pointer
00367         \param param  the irst argument passed to dprint
00368     */
00369     _DUMP_TEMPLATE(dumpNetStatus, MDMParser::NetStatus*, status)
00370     
00371     /** dump the ip address to stdout using printf
00372         \param ip the ip to convert to textual form, 
00373                unavailable fields are ommited (not printed)
00374         \param dprint a function pointer
00375         \param param  the irst argument passed to dprint
00376     */
00377     _DUMP_TEMPLATE(dumpIp, MDMParser::IP, ip)
00378    
00379     // ----------------------------------------------------------------
00380     // Parseing
00381     // ----------------------------------------------------------------
00382     
00383     enum { 
00384         // waitFinalResp Responses
00385         NOT_FOUND     =  0,
00386         WAIT          = -1, // TIMEOUT
00387         RESP_OK       = -2, 
00388         RESP_ERROR    = -3,
00389         RESP_PROMPT   = -4,
00390     
00391         // getLine Responses
00392         #define LENGTH(x)  (x & 0x00FFFF) //!< extract/mask the length
00393         #define TYPE(x)    (x & 0xFF0000) //!< extract/mask the type
00394         
00395         TYPE_UNKNOWN    = 0x000000,
00396         TYPE_OK         = 0x110000,
00397         TYPE_ERROR      = 0x120000,
00398         TYPE_RING       = 0x210000,
00399         TYPE_CONNECT    = 0x220000,
00400         TYPE_NOCARRIER  = 0x230000,
00401         TYPE_NODIALTONE = 0x240000,
00402         TYPE_BUSY       = 0x250000,
00403         TYPE_NOANSWER   = 0x260000,
00404         TYPE_PROMPT     = 0x300000,
00405         TYPE_PLUS       = 0x400000,
00406         TYPE_TEXT       = 0x500000,
00407         
00408         // special timout constant
00409         TIMEOUT_BLOCKING = -1
00410     };
00411     
00412     /** Get a line from the physical interface. This function need 
00413         to be implemented in a inherited class. Usually just calls 
00414         #_getLine on the rx buffer pipe. 
00415             
00416         \param buf the buffer to store it
00417         \param buf size of the buffer
00418         \return type and length if something was found, 
00419                 WAIT if not enough data is available
00420                 NOT_FOUND if nothing was found
00421     */ 
00422     virtual int getLine(char* buf, int len) = 0; 
00423     
00424     /* clear the pending input data
00425     */
00426     virtual void purge(void) = 0;
00427     
00428     /** Write data to the device 
00429         \param buf the buffer to write
00430         \param buf size of the buffer to write
00431         \return bytes written
00432     */
00433     virtual int send(const char* buf, int len);
00434     
00435     /** Write formated date to the physical interface (printf style)
00436         \param fmt the format string
00437         \param .. variable arguments to be formated
00438         \return bytes written
00439     */
00440     int sendFormated(const char* format, ...);
00441     
00442     /** callback function for #waitFinalResp with void* as argument
00443         \param type the #getLine response
00444         \param buf the parsed line
00445         \param len the size of the parsed line
00446         \param param the optional argument passed to #waitFinalResp
00447         \return WAIT if processing should continue, 
00448                 any other value aborts #waitFinalResp and this retunr value retuned
00449     */
00450     typedef int (*_CALLBACKPTR)(int type, const char* buf, int len, void* param);
00451     
00452     /** Wait for a final respons
00453         \param cb the optional callback function
00454         \param param the optional callback function parameter
00455         \param timeout_ms the timeout to wait (See Estimated command 
00456                response time of AT manual)
00457     */
00458     int waitFinalResp(_CALLBACKPTR cb = NULL, 
00459                       void* param = NULL, 
00460                       int timeout_ms = 10000);
00461 
00462     /** template version of #waitFinalResp when using callbacks, 
00463         This template will allow the compiler to do type cheking but 
00464         internally symply casts the arguments and call the (void*) 
00465         version of #waitFinalResp.
00466         \sa waitFinalResp
00467     */ 
00468     template<class T>
00469     inline int waitFinalResp(int (*cb)(int type, const char* buf, int len, T* param), 
00470                     T* param, 
00471                     int timeout_ms = 10000) 
00472     {
00473         return waitFinalResp((_CALLBACKPTR)cb, (void*)param, timeout_ms);
00474     }
00475     
00476 protected:
00477     /** Write bytes to the physical interface. This function should be 
00478         implemented in a inherited class.
00479         \param buf the buffer to write
00480         \param buf size of the buffer to write
00481         \return bytes written
00482     */
00483     virtual int _send(const void* buf, int len) = 0;
00484 
00485     /** Helper: Parse a line from the receiving buffered pipe
00486         \param pipe the receiving buffer pipe 
00487         \param buf the parsed line
00488         \param len the size of the parsed line
00489         \return type and length if something was found, 
00490                 WAIT if not enough data is available
00491                 NOT_FOUND if nothing was found
00492     */
00493     static int _getLine(Pipe<char> * pipe, char* buffer, int length);
00494     
00495     /** Helper: Parse a match from the pipe
00496         \param pipe the buffered pipe
00497         \param number of bytes to parse at maximum, 
00498         \param sta the starting string, NULL if none
00499         \param end the terminating string, NULL if none
00500         \return size of parsed match 
00501     */   
00502     static int _parseMatch(Pipe<char> * pipe, int len, const char* sta, const char* end);
00503     
00504     /** Helper: Parse a match from the pipe
00505         \param pipe the buffered pipe
00506         \param number of bytes to parse at maximum, 
00507         \param fmt the formating string (%d any number, %c any char of last %d len)
00508         \return size of parsed match
00509     */   
00510     static int _parseFormated(Pipe<char> * pipe, int len, const char* fmt);
00511 
00512 protected:
00513     // for rtos over riding by useing Rtos<MDMxx> 
00514     /** override in a rtos system, you us the wait function of a Thread
00515         \param ms the number of milliseconds to wait
00516     */
00517     virtual void wait_ms(int ms)   { if (ms) ::wait_ms(ms); }
00518     //! override the lock in a rtos system
00519     virtual void lock(void)        { } 
00520     //! override the unlock in a rtos system
00521     virtual void unlock(void)      { } 
00522 protected:
00523     bool _activateProfile(const char* apn, const char* username, const char* password, Auth auth);
00524     bool _activateProfileByCid(int cid, const char* apn, const char* username, const char* password, Auth auth);
00525     // parsing callbacks for different AT commands and their parameter arguments
00526     static int _cbString(int type, const char* buf, int len, char* str);
00527     static int _cbInt(int type, const char* buf, int len, int* val);
00528     // device
00529     static int _cbATI(int type, const char* buf, int len, Dev* dev);
00530     static int _cbCPIN(int type, const char* buf, int len, Sim* sim);
00531     static int _cbCCID(int type, const char* buf, int len, char* ccid);
00532     // network 
00533     static int _cbCSQ(int type, const char* buf, int len, NetStatus* status);
00534     static int _cbCOPS(int type, const char* buf, int len, NetStatus* status);
00535     static int _cbCNUM(int type, const char* buf, int len, char* num);
00536     static int _cbUACTIND(int type, const char* buf, int len, int* i);
00537     static int _cbUDOPN(int type, const char* buf, int len, char* mccmnc);
00538     // sockets
00539     static int _cbCMIP(int type, const char* buf, int len, IP* ip);
00540     static int _cbUPSND(int type, const char* buf, int len, int* act);
00541     static int _cbUPSND(int type, const char* buf, int len, IP* ip);
00542     static int _cbUDNSRN(int type, const char* buf, int len, IP* ip);
00543     static int _cbUSOCR(int type, const char* buf, int len, int* handle);
00544     static int _cbUSORD(int type, const char* buf, int len, char* out);
00545     typedef struct { char* buf; IP ip; int port; } USORFparam;
00546     static int _cbUSORF(int type, const char* buf, int len, USORFparam* param);
00547     typedef struct { char* buf; char* num; } CMGRparam;
00548     static int _cbCUSD(int type, const char* buf, int len, char* resp);
00549     // sms
00550     typedef struct { int* ix; int num; } CMGLparam;
00551     static int _cbCMGL(int type, const char* buf, int len, CMGLparam* param);
00552     static int _cbCMGR(int type, const char* buf, int len, CMGRparam* param);
00553     // file
00554     typedef struct { const char* filename; char* buf; int sz; int len; } URDFILEparam;
00555     static int _cbUDELFILE(int type, const char* buf, int len, void*);
00556     static int _cbURDFILE(int type, const char* buf, int len, URDFILEparam* param);
00557     // variables
00558     DevStatus   _dev; //!< collected device information
00559     NetStatus   _net; //!< collected network information 
00560     IP          _ip;  //!< assigned ip address
00561     // management struture for sockets
00562     typedef struct { int handle; int timeout_ms; volatile bool connected; volatile int pending; } SockCtrl;
00563     // LISA-C has 6 TCP and 6 UDP sockets 
00564     // LISA-U and SARA-G have 7 sockets
00565     SockCtrl _sockets[12];
00566     int _findSocket(int handle = SOCKET_ERROR/* = CREATE*/);
00567     static MDMParser* inst;
00568     bool _init;
00569 #ifdef TARGET_UBLOX_C027
00570     bool _onboard;
00571 #endif
00572 #ifdef MDM_DEBUG
00573     int _debugLevel;
00574     Timer _debugTime;
00575     void _debugPrint(int level, const char* color, const char* format, ...);
00576 #endif
00577 };
00578 
00579 // -----------------------------------------------------------------------
00580 
00581 /** modem class which uses a serial port 
00582     as physical interface. 
00583 */
00584 class MDMSerial :  public SerialPipe, public MDMParser
00585 {
00586 public: 
00587     /** Constructor
00588     
00589         \param tx is the serial ports transmit pin (modem to CPU)
00590         \param rx is the serial ports receive pin (CPU to modem)
00591         \param baudrate the baudrate of the modem use 115200
00592         \param rts is the serial ports ready to send pin (CPU to modem) 
00593                this pin is optional 
00594         \param cts is the serial ports clear to send pin (modem to CPU) 
00595                this pin is optional, but required for power saving to be enabled
00596         \param rxSize the size of the serial rx buffer
00597         \param txSize the size of the serial tx buffer
00598     */
00599     MDMSerial(PinName tx    MDM_IF( = MDMTXD,  = D1 ), 
00600               PinName rx    MDM_IF( = MDMRXD,  = D0 ), 
00601               int baudrate  MDM_IF( = MDMBAUD, = 115200 ),
00602  #if DEVICE_SERIAL_FC
00603               PinName rts   MDM_IF( = MDMRTS,  = NC /* D2 resistor R62 on shield not mounted */ ), 
00604               PinName cts   MDM_IF( = MDMCTS,  = NC /* D3 resistor R63 on shield not mounted */ ),
00605  #endif
00606               int rxSize    = 256 , 
00607               int txSize    = 128 );
00608     //! Destructor          
00609     virtual ~MDMSerial(void);
00610      
00611     /** Get a line from the physical interface. 
00612         \param buf the buffer to store it
00613         \param buf size of the buffer
00614         \return type and length if something was found, 
00615                 WAIT if not enough data is available
00616                 NOT_FOUND if nothing was found
00617     */ 
00618     virtual int getLine(char* buffer, int length);
00619     
00620     /* clear the pending input data */
00621     virtual void purge(void) 
00622     { 
00623         while (readable())
00624             getc();
00625     }
00626 protected:
00627     /** Write bytes to the physical interface.
00628         \param buf the buffer to write
00629         \param buf size of the buffer to write
00630         \return bytes written
00631     */
00632     virtual int _send(const void* buf, int len);
00633 };
00634 
00635 // -----------------------------------------------------------------------
00636 
00637 //#define HAVE_MDMUSB
00638 #ifdef HAVE_MDMUSB
00639 class MDMUsb :  /*public UsbSerial,*/ public MDMParser
00640 {
00641 public: 
00642     //! Constructor          
00643     MDMUsb(void);
00644     //! Destructor          
00645     virtual ~MDMUsb(void);
00646     virtual int getLine(char* buffer, int length);
00647     virtual void purge(void) { }
00648 protected:
00649     virtual int _send(const void* buf, int len);
00650 };
00651 #endif
00652 
00653 // -----------------------------------------------------------------------
00654 
00655 #ifdef RTOS_H
00656 /** Use this template to override the lock and wait functions of the 
00657     modem driver in a Rtos system. For example declare it the modem 
00658     object as MDMRtos<MDMSerial> instead of MDMSerial.
00659 */
00660 template <class T>
00661 class MDMRtos :  public T
00662 {
00663 protected:
00664     //! we assume that the modem runs in a thread so we yield when waiting
00665     virtual void wait_ms(int ms)   {
00666         if (ms) Thread::wait(ms);
00667         else    Thread::yield();
00668     }
00669     //! lock a mutex when accessing the modem
00670     virtual void lock(void)     { _mtx.lock(); }  
00671     //! unlock the modem when done accessing it
00672     virtual void unlock(void)   { _mtx.unlock(); }
00673     // the mutex resource
00674     Mutex _mtx;
00675 };
00676 #endif