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

Files at this revision

API Documentation at this revision

Comitter:
mazgch
Date:
Tue Jun 17 07:03:48 2014 +0000
Parent:
94:d697fe11f3e5
Child:
96:2aa03444fee3
Child:
98:c786461edd40
Commit message:
added use of mutex and wait for Rtos systems

Changed in this revision

GPS.cpp Show annotated file Show diff for this revision Revisions of this file
MDM.cpp Show annotated file Show diff for this revision Revisions of this file
MDM.h Show annotated file Show diff for this revision Revisions of this file
Pipe.h Show annotated file Show diff for this revision Revisions of this file
Relax.h Show diff for this revision Revisions of this file
SerialPipe.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/GPS.cpp	Thu Jun 12 12:41:26 2014 +0000
+++ b/GPS.cpp	Tue Jun 17 07:03:48 2014 +0000
@@ -1,7 +1,6 @@
 #include "mbed.h"
 #include <ctype.h>
 #include "GPS.h"
-#include "Relax.h"
 #ifdef TARGET_UBLOX_C027
  #include "C027_api.h"
 #endif
@@ -261,16 +260,14 @@
 bool GPSSerial::init(PinName pn)
 {
     // send a byte to wakup the device again
-    putc(0);
+    putc(0xFF);
     // wait until we get some bytes
     int size = _pipeRx.size();
-    int i = 30;
-    while (i--) {
-        RELAX_MS(10);
-        if(size != _pipeRx.size())
-            break;
-    }   
-    return (i >= 0);
+    Timer timer;
+    timer.start();
+    while ((100 > timer.read_ms()) && (size == _pipeRx.size()))
+        /* nothing / just wait */;
+    return (size != _pipeRx.size());
 }
 
 int GPSSerial::getMessage(char* buf, int len)
@@ -314,9 +311,9 @@
 {
     if (pn != NC) {
         DigitalOut pin(pn, 0);
-        wait_us(1);
+        ::wait_us(1);
         pin = 1;
-        RELAX_MS(100);
+        ::wait_ms(100);
     }
     return !I2C::write(_i2cAdr,&REGSTREAM,sizeof(REGSTREAM));
 }
--- a/MDM.cpp	Thu Jun 12 12:41:26 2014 +0000
+++ b/MDM.cpp	Tue Jun 17 07:03:48 2014 +0000
@@ -1,6 +1,5 @@
 #include "mbed.h"
 #include "MDM.h"
-#include "Relax.h"
 #ifdef TARGET_UBLOX_C027
  #include "C027_api.h"
 #endif
@@ -16,8 +15,27 @@
 #define REG_OK(r)       ((r == REG_HOME) || (r == REG_ROAMING)) 
 //! registration done check helper (no need to poll further)
 #define REG_DONE(r)     ((r == REG_HOME) || (r == REG_ROAMING) || (r == REG_DENIED)) 
+//! helper to make sure that lock unlock pair is always balaced 
+#define LOCK()         { lock() 
+//! helper to make sure that lock unlock pair is always balaced 
+#define UNLOCK()       } unlock()
 
 #ifdef MDM_DEBUG
+ #if 1 // colored terminal output using ANSI escape sequences
+  #define COL(c) "\033[" c
+ #else
+  #define COL(c) 
+ #endif
+ #define DEF COL("39m")
+ #define BLA COL("30m")
+ #define RED COL("31m")
+ #define GRE COL("32m")
+ #define YEL COL("33m")
+ #define BLU COL("34m")
+ #define MAG COL("35m")
+ #define CYA COL("36m")
+ #define WHY COL("37m")
+ 
 void dumpAtCmd(const char* buf, int len)
 {
     ::printf(" %3d \"", len);
@@ -42,27 +60,15 @@
     ::printf("\"\r\n");
 }
  
- #define ERROR(fmt) (_debugLevel < 0) ? : ::printf(RED(fmt))
- #define INFO(fmt)  (_debugLevel < 1) ? : ::printf(GRE(fmt))
- #define TRACE(...) (_debugLevel < 2) ? : ::printf(__VA_ARGS__)
- 
- #if 1 // colored terminal output using ANSI escape sequences
-  #define COL(c,t) "\033[" c t "\033[" "39m"
- #else
-  #define COL(c,t) t
- #endif
- #define BLA(t) COL("30m",t)
- #define RED(t) COL("31m",t)
- #define GRE(t) COL("32m",t)
- #define YEL(t) COL("33m",t)
- #define BLU(t) COL("34m",t)
- #define MAG(t) COL("35m",t)
- #define CYA(t) COL("36m",t)
- #define WHY(t) COL("37m",t)
+ #define ERROR(...)     (_debugLevel < 0) ? : ::printf(RED), ::printf(__VA_ARGS__), ::printf(DEF) 
+ #define TEST(...)                            ::printf(CYA), ::printf(__VA_ARGS__), ::printf(DEF)  
+ #define INFO(...)      (_debugLevel < 1) ? : ::printf(GRE), ::printf(__VA_ARGS__), ::printf(DEF) 
+ #define TRACE(...)     (_debugLevel < 2) ? : ::printf(__VA_ARGS__)
  
 #else
  
  #define ERROR(...) (void)0 // no tracing
+ #define TEST(...)  (void)0 // no tracing
  #define INFO(...)  (void)0 // no tracing
  #define TRACE(...) (void)0 // no tracing
 
@@ -120,13 +126,13 @@
         {
             int len = LENGTH(ret);
             int type = TYPE(ret);
-            const char* s = (type == TYPE_UNKNOWN)? YEL("UNK") : 
-                            (type == TYPE_TEXT)   ? MAG("TXT") : 
-                            (type == TYPE_OK   )  ? GRE("OK ") : 
-                            (type == TYPE_ERROR)  ? RED("ERR") : 
-                            (type == TYPE_PLUS)   ? CYA(" + ") : 
-                            (type == TYPE_PROMPT) ? BLU(" > ") : 
-                                                        "..."  ;
+            const char* s = (type == TYPE_UNKNOWN)? YEL "UNK" DEF : 
+                            (type == TYPE_TEXT)   ? MAG "TXT" DEF : 
+                            (type == TYPE_OK   )  ? GRE "OK " DEF : 
+                            (type == TYPE_ERROR)  ? RED "ERR" DEF : 
+                            (type == TYPE_PLUS)   ? CYA " + " DEF : 
+                            (type == TYPE_PROMPT) ? BLU " > " DEF : 
+                                                        "..." ;
             ::printf("%10.3f AT read %s", _debugTime.read_ms()*0.001, s);
             dumpAtCmd(buf, len);
         }
@@ -224,12 +230,15 @@
                 if (WAIT != ret)
                     return ret; 
             }
-            if (type == TYPE_OK)        return RESP_OK;
-            if (type == TYPE_ERROR)     return RESP_ERROR;
-            if (type == TYPE_PROMPT)    return RESP_PROMPT;
+            if (type == TYPE_OK)
+                return RESP_OK;
+            if (type == TYPE_ERROR)
+                return RESP_ERROR;
+            if (type == TYPE_PROMPT)    
+                return RESP_PROMPT;
         }
         // relax a bit
-        RELAX_MS(10); 
+        wait_ms(10); 
     }
     while (!TIMEOUT(timer, timeout_ms));
     return WAIT;
@@ -285,30 +294,32 @@
 bool MDMParser::init(const char* simpin, DevStatus* status, PinName pn)
 {
     int i = 10;
+    LOCK();
     memset(&_dev, 0, sizeof(_dev));
     if (pn != NC) {
         INFO("Modem::wakeup\r\n");
         DigitalOut pin(pn, 1);
         while (i--) {
             // SARA-U2/LISA-U2 50..80us
-            pin = 0; wait_us(50);
-            pin = 1; wait_ms(10); 
+            pin = 0; ::wait_us(50);
+            pin = 1; ::wait_ms(10); 
             
             // SARA-G35 >5ms, LISA-C2 > 150ms
-            pin = 0; wait_ms(150);
-            pin = 1; wait_ms(100);
+            pin = 0; ::wait_ms(150);
+            pin = 1; ::wait_ms(100);
             
             // purge any messages 
             while (WAIT != waitFinalResp(NULL,NULL,0))
                 /* nothing */;
+            
             // check interface and disable local echo
             sendFormated("AT\r\n");
-            if(RESP_OK == waitFinalResp(NULL,NULL,500))
-                break;
+            int r = waitFinalResp(NULL,NULL,500);
+            if(RESP_OK == r) break;
         }
         if (i < 0) {
-            ERROR("No Reply from Modem");
-            return false;
+            ERROR("No Reply from Modem\r\n");
+            goto failure;
         }
     }
     _init = true;
@@ -317,47 +328,47 @@
     // echo off
     sendFormated("AT E0\r\n");
     if(RESP_OK != waitFinalResp())
-        return false;
+        goto failure; 
     // enable verbose error messages
     sendFormated("AT+CMEE=2\r\n");
     if(RESP_OK != waitFinalResp())
-        return false;
+        goto failure;
     // set baud rate
     sendFormated("AT+IPR=115200\r\n");
     if (RESP_OK != waitFinalResp())
-        return false;
-    RELAX_MS(40);
+        goto failure;
+    wait_ms(40);
     // identify the module 
     sendFormated("ATI\r\n");
     if (RESP_OK != waitFinalResp(_cbATI, &_dev.dev))
-        return false;
+        goto failure;
     if (_dev.dev == DEV_UNKNOWN)
-        return false;
+        goto failure;
     // device specific init
     if (_dev.dev == DEV_LISA_C200) {
         // get the manufacturer
         sendFormated("AT+GMI\r\n");
         if (RESP_OK != waitFinalResp(_cbString, _dev.manu))
-            return false;
+            goto failure;
         // get the model identification
         sendFormated("AT+GMM\r\n");
         if (RESP_OK != waitFinalResp(_cbString, _dev.model))
-            return false;
+            goto failure;
         // get the sw version
         sendFormated("AT+GMR\r\n");
         if (RESP_OK != waitFinalResp(_cbString, _dev.ver))
-            return false;
-        // Return the pseudo ESN or MEID
+            goto failure;
+        // get the pseudo ESN or MEID
         sendFormated("AT+GSN\r\n");
         if (RESP_OK != waitFinalResp(_cbString, _dev.meid))
-            return false;
+            goto failure;
 #if 0
         // enable power saving
         if (_dev.lpm != LPM_DISABLED) {
              // enable power saving (requires flow control, cts at least)
             sendFormated("AT+UPSV=1,1280\r\n");
             if (RESP_OK != waitFinalResp())
-                return false;  
+                goto failure;  
             _dev.lpm = LPM_ACTIVE;
         }
 #endif
@@ -366,12 +377,12 @@
             // enable the network identification feature 
             sendFormated("AT+UGPIOC=20,2\r\n");
             if (RESP_OK != waitFinalResp())
-                return false;
+                goto failure;
         } else {
             // enable the network identification feature 
             sendFormated("AT+UGPIOC=16,2\r\n");
             if (RESP_OK != waitFinalResp())
-                return false;
+                goto failure;
         }
         // check the sim card
         for (int i = 0; (i < 5) && (_dev.sim != SIM_READY); i++) {
@@ -379,90 +390,98 @@
             int ret = waitFinalResp(_cbCPIN, &_dev.sim);
             // having an error here is ok (sim may still be initializing)
             if ((RESP_OK != ret) && (RESP_ERROR != ret))
-                return false;
+                goto failure;
             // Enter PIN if needed
             if (_dev.sim == SIM_PIN) {
                 if (!simpin) {
                     ERROR("SIM PIN not available\r\n");
-                    return false;
+                    goto failure;
                 }
                 sendFormated("AT+CPIN=%s\r\n", simpin);
                 if (RESP_OK != waitFinalResp(_cbCPIN, &_dev.sim))
-                    return false;
+                    goto failure;
             } else if (_dev.sim != SIM_READY) {
-                RELAX_MS(1000);
+                wait_ms(1000);
             }
         }
         if (_dev.sim != SIM_READY) {
             if (_dev.sim == SIM_MISSING)
                 ERROR("SIM not inserted\r\n");
-            return false;
+            goto failure;
         }
         // get the manufacturer
         sendFormated("AT+CGMI\r\n");
         if (RESP_OK != waitFinalResp(_cbString, _dev.manu))
-            return false;
+            goto failure;
         // get the model identification
         sendFormated("AT+CGMM\r\n");
         if (RESP_OK != waitFinalResp(_cbString, _dev.model))
-            return false;
+            goto failure;
         // get the 
         sendFormated("AT+CGMR\r\n");
         if (RESP_OK != waitFinalResp(_cbString, _dev.ver))
-            return false;            
+            goto failure;            
         // Returns the ICCID (Integrated Circuit Card ID) of the SIM-card. 
         // ICCID is a serial number identifying the SIM.
         sendFormated("AT+CCID\r\n");
         if (RESP_OK != waitFinalResp(_cbCCID, _dev.ccid))
-            return false;
+            goto failure;
         // Returns the product serial number, IMEI (International Mobile Equipment Identity)
         sendFormated("AT+CGSN\r\n");
         if (RESP_OK != waitFinalResp(_cbString, _dev.imei))
-            return false;
+            goto failure;
         // enable power saving
         if (_dev.lpm != LPM_DISABLED) {
              // enable power saving (requires flow control, cts at least)
             sendFormated("AT+UPSV=1\r\n");
             if (RESP_OK != waitFinalResp())
-                return false;  
+                goto failure;  
             _dev.lpm = LPM_ACTIVE;
         }
         // enable the psd registration unsolicited result code
         sendFormated("AT+CGREG=2\r\n");
         if (RESP_OK != waitFinalResp())
-            return false;
+            goto failure;
     } 
     // enable the network registration unsolicited result code
     sendFormated("AT+CREG=%d\r\n", (_dev.dev == DEV_LISA_C200) ? 1 : 2);
     if (RESP_OK != waitFinalResp())
-        return false;
+        goto failure;
     // Setup SMS in text mode 
     sendFormated("AT+CMGF=1\r\n");
     if (RESP_OK != waitFinalResp())
-        return false;
+        goto failure;
     // setup new message indication
     sendFormated("AT+CNMI=2,1\r\n");
     if (RESP_OK != waitFinalResp())
-        return false;
+        goto failure;
     // Request IMSI (International Mobile Subscriber Identification)
     sendFormated("AT+CIMI\r\n");
     if (RESP_OK != waitFinalResp(_cbString, _dev.imsi))
-        return false;
+        goto failure;
     if (status)
         memcpy(status, &_dev, sizeof(DevStatus));
+    UNLOCK();
     return true; 
+failure:
+    unlock();
+    return false; 
 }
 
 bool MDMParser::powerOff(void)
 {
+    bool ok = false;
     if (_init) {
+        LOCK();
         INFO("Modem::powerOff\r\n");
         sendFormated("AT+CPWROFF\r\n");
-        if (RESP_OK != waitFinalResp(NULL,NULL,120*1000))
-            return false;
-        _init = false;
+        if (RESP_OK == waitFinalResp(NULL,NULL,120*1000)) {
+            _init = false;
+            ok = true;
+        }
+        UNLOCK();
     }
-    return true;
+    return ok;
 }
 
 int MDMParser::_cbATI(int type, const char* buf, int len, Dev* dev)
@@ -512,7 +531,7 @@
     timer.start();
     INFO("Modem::register\r\n");
     while (!checkNetStatus(status) && !TIMEOUT(timer, timeout_ms))
-        RELAX_MS(1000);
+        wait_ms(1000);
     if (_net.csd == REG_DENIED) ERROR("CSD Registration Denied\r\n");
     if (_net.psd == REG_DENIED) ERROR("PSD Registration Denied\r\n");
     return REG_OK(_net.csd) || REG_OK(_net.psd);
@@ -520,6 +539,8 @@
 
 bool MDMParser::checkNetStatus(NetStatus* status /*= NULL*/)
 {
+    bool ok = false;
+    LOCK();
     memset(&_net, 0, sizeof(_net));
     _net.lac = 0xFFFF;
     _net.ci = 0xFFFFFFFF;
@@ -537,12 +558,12 @@
         if (_dev.dev == DEV_LISA_C200) {
             sendFormated("AT+CSS?\r\n");
             if (RESP_OK != waitFinalResp())
-                return false;
+                goto failure;
             while (1) {
                 // get the Telephone number
                 sendFormated("AT$MDN?\r\n");
                 if (RESP_OK != waitFinalResp(_cbString, _net.num))
-                    return false;
+                    goto failure;
                 // check if we have a Mobile Directory Number
                 if (*_net.num && (memcmp(_net.num, "000000", 6) != 0))
                     break;
@@ -559,7 +580,7 @@
                     i = 1;
                     if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) {
                         ERROR("Device over-the-air activation failed\r\n");
-                        return false;
+                        goto failure;
                     }
                     INFO("Device over-the-air activation successful\r\n");
                     
@@ -568,39 +589,44 @@
                     i = 1;
                     if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) {
                         ERROR("PRL over-the-air update failed\r\n");
-                        return false;
+                        goto failure;
                     }
                     INFO("PRL over-the-air update successful\r\n");
                     
                 } else { 
                     // Sprint or Aeris 
                     INFO("Wait for OMA-DM over-the-air activation (this can take a few minutes)\r\n");
-                    RELAX_MS(120*1000);
+                    wait_ms(120*1000);
                 }
             }
             // get the the Network access identifier string
             char nai[64];
             sendFormated("AT$QCMIPNAI?\r\n");
             if (RESP_OK != waitFinalResp(_cbString, nai))
-                return false;
+                goto failure;
         } else {
             sendFormated("AT+COPS?\r\n");
             if (RESP_OK != waitFinalResp(_cbCOPS, &_net))
-                return false;
-            // Returns the MSISDNs related to this subscriber
+                goto failure;
+            // get the MSISDNs related to this subscriber
             sendFormated("AT+CNUM\r\n");
             if (RESP_OK != waitFinalResp(_cbCNUM, _net.num))
-                return false;
+                goto failure;
         }  
-        // Returns the signal strength indication
+        // get the signal strength indication
         sendFormated("AT+CSQ\r\n");
         if (RESP_OK != waitFinalResp(_cbCSQ, &_net))
-            return false;
+            goto failure;
     }
     if (status) {
         memcpy(status, &_net, sizeof(NetStatus));
     }
-    return REG_DONE(_net.csd) && REG_DONE(_net.psd);
+    ok = REG_DONE(_net.csd) && REG_DONE(_net.psd);
+    UNLOCK();
+    return ok;
+failure:
+    unlock();
+    return false;
 }
 
 int MDMParser::_cbCOPS(int type, const char* buf, int len, NetStatus* status)
@@ -658,6 +684,7 @@
 MDMParser::IP MDMParser::join(const char* apn /*= NULL*/, const char* username /*= NULL*/, 
                               const char* password /*= NULL*/, Auth auth /*= AUTH_DETECT*/)
 {
+    LOCK();
     INFO("Modem::join\r\n");
     _ip = NOIP;
     if (_dev.dev == DEV_LISA_C200) {
@@ -670,24 +697,24 @@
         //Get local IP address
         sendFormated("AT+CMIP?\r\n");
         if (RESP_OK != waitFinalResp(_cbCMIP, &_ip))
-            return NOIP;
+            goto failure;
     } else { 
         // check gprs attach status 
         sendFormated("AT+CGATT=1\r\n");
         if (RESP_OK != waitFinalResp(NULL,NULL,3*60*1000)) 
-            return NOIP;
+            goto failure;
         
         // Check the profile
         int a = 0;
         bool force = true;
         sendFormated("AT+UPSND=" PROFILE ",8\r\n");
         if (RESP_OK != waitFinalResp(_cbUPSND, &a))
-            return NOIP;
+            goto failure;
         if (a == 1 && force) {
             // disconnect the profile already if it is connected 
             sendFormated("AT+UPSDA=" PROFILE ",4\r\n");
             if (RESP_OK != waitFinalResp(NULL,NULL,40*1000))
-                return NOIP;
+                goto failure;
             a = 0;
         }
         if (a == 0) {
@@ -700,7 +727,7 @@
             // Set up the dynamic IP address assignment.
             sendFormated("AT+UPSD=" PROFILE ",7,\"0.0.0.0\"\r\n");
             if (RESP_OK != waitFinalResp())
-                return NOIP;
+                goto failure;
  
             do {
                 if (config) {
@@ -713,17 +740,17 @@
                 if (apn && *apn) {
                     sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn);
                     if (RESP_OK != waitFinalResp())
-                        return NOIP;
+                        goto failure;
                 }
                 if (username && *username) {
                     sendFormated("AT+UPSD=" PROFILE ",2,\"%s\"\r\n", username);
                     if (RESP_OK != waitFinalResp())
-                        return NOIP;
+                        goto failure;
                 }
                 if (password && *password) {
                     sendFormated("AT+UPSD=" PROFILE ",3,\"%s\"\r\n", password);
                     if (RESP_OK != waitFinalResp())
-                        return NOIP;
+                        goto failure;
                 }
                 // try different Authentication Protocols
                 // 0 = none 
@@ -734,7 +761,7 @@
                         // Set up the Authentication Protocol
                         sendFormated("AT+UPSD=" PROFILE ",6,%d\r\n", i);
                         if (RESP_OK != waitFinalResp())
-                            return NOIP;
+                            goto failure;
                         // Activate the profile and make connection
                         sendFormated("AT+UPSDA=" PROFILE ",3\r\n");
                         if (RESP_OK == waitFinalResp(NULL,NULL,150*1000))
@@ -744,15 +771,19 @@
             } while (config && *config); // maybe use next setting ? 
             if (!ok) {
                 ERROR("Your modem APN/password/username may be wrong\r\n");
-                return NOIP;
+                goto failure;
             }
         }
         //Get local IP address
         sendFormated("AT+UPSND=" PROFILE ",0\r\n");
         if (RESP_OK != waitFinalResp(_cbUPSND, &_ip))
-            return NOIP;
+            goto failure;
     }
+    UNLOCK();
     return _ip;
+failure: 
+    unlock();
+    return NOIP;
 }
 
 int MDMParser::_cbUDOPN(int type, const char* buf, int len, char* mccmnc)
@@ -798,7 +829,7 @@
 {
     if ((type == TYPE_PLUS) && ip) {
         int a,b,c,d;
-        if (sscanf(buf, "\r\n+UDNSRN: \""IPSTR"\"", &a,&b,&c,&d) == 4)
+        if (sscanf(buf, "\r\n+UDNSRN: \"" IPSTR "\"", &a,&b,&c,&d) == 4)
             *ip = IPADR(a,b,c,d);
     }
     return WAIT;
@@ -806,18 +837,24 @@
 
 bool MDMParser::disconnect(void)
 {
-    if (_ip == NOIP)
-        return true;
+    bool ok = false;
+    LOCK();
     INFO("Modem::disconnect\r\n");
-    if (_dev.dev == DEV_LISA_C200) {
-        // There something to do here
-    } else { 
-        sendFormated("AT+UPSDA=" PROFILE ",4\r\n");
-        if (RESP_OK != waitFinalResp())
-            return false;
+    if (_ip != NOIP) {
+        if (_dev.dev == DEV_LISA_C200) {
+            // There something to do here
+            _ip = NOIP;
+            ok = true;
+        } else { 
+            sendFormated("AT+UPSDA=" PROFILE ",4\r\n");
+            if (RESP_OK != waitFinalResp()) {
+                _ip = NOIP;
+                ok = true;
+            }
+        }
     }
-    _ip = NOIP;
-    return true;
+    UNLOCK();
+    return ok;
 }
 
 MDMParser::IP MDMParser::gethostbyname(const char* host)
@@ -827,9 +864,11 @@
     if (sscanf(host, IPSTR, &a,&b,&c,&d) == 4)
         ip = IPADR(a,b,c,d);
     else {
+        LOCK();
         sendFormated("AT+UDNSRN=0,\"%s\"\r\n", host);
         if (RESP_OK != waitFinalResp(_cbUDNSRN, &ip))
-            return false;
+            ip = NOIP;
+        UNLOCK();
     }
     return ip;
 }
@@ -849,81 +888,101 @@
 
 int MDMParser::socketSocket(IpProtocol ipproto, int port)
 {
+    int socket = SOCKET_ERROR;
+    LOCK();
     TRACE("socketSocket(%d)\r\n", ipproto);
-    if(ipproto == IPPROTO_TCP) {
-        sendFormated("AT+USOCR=6\r\n");
-    } else if ((ipproto == IPPROTO_UDP) && (port == -1)){
+    if ((ipproto == IPPROTO_UDP) && (port == -1)){
         sendFormated("AT+USOCR=17\r\n");
     } else if (ipproto == IPPROTO_UDP){
         sendFormated("AT+USOCR=17,%d\r\n", port);
-    } else { // other types not supported
-        return SOCKET_ERROR;
-    }
-    int socket = -1;
+    } else /*(ipproto == IPPROTO_TCP)*/ {
+        sendFormated("AT+USOCR=6\r\n");
+    } 
     if (RESP_OK != waitFinalResp(_cbUSOCR, &socket))
-        return SOCKET_ERROR;
-    if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_FREE))
-        return SOCKET_ERROR;
-    // successfull
-    _sockets[socket].state = SOCK_CREATED;
-    _sockets[socket].pending = 0;
-    _sockets[socket].timeout_ms = TIMEOUT_BLOCKING;
+        socket = SOCKET_ERROR;
+    else if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_FREE))
+        socket = SOCKET_ERROR;
+    if (socket != SOCKET_ERROR) {
+        // successfull
+        _sockets[socket].state = SOCK_CREATED;
+        _sockets[socket].pending = 0;
+        _sockets[socket].timeout_ms = TIMEOUT_BLOCKING;
+    }
+    UNLOCK();
     return socket;
 }
 
 bool MDMParser::socketConnect(int socket, const char * host, int port)
 {
-    TRACE("socketConnect(%d,%s,%d)\r\n", socket, host,port);
     IP ip = gethostbyname(host);
     if (ip == NOIP)
         return false;
     // connect to socket
-    if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CREATED))
-        return false;
-    sendFormated("AT+USOCO=%d,\"" IPSTR "\",%d\r\n", socket, IPNUM(ip), port);
-    if (RESP_OK != waitFinalResp())
-        return false;
-    _sockets[socket].state = SOCK_CONNECTED;
-    return true;
+    bool ok = false; 
+    LOCK();
+    if (ISSOCKET(socket) && (_sockets[socket].state == SOCK_CREATED)) {
+        TRACE("socketConnect(%d,%s,%d)\r\n", socket,host,port);
+        sendFormated("AT+USOCO=%d,\"" IPSTR "\",%d\r\n", socket, IPNUM(ip), port);
+        if (RESP_OK == waitFinalResp())
+            ok = _sockets[socket].state = SOCK_CONNECTED;
+    }
+    UNLOCK();
+    return ok;
 }
 
 bool MDMParser::socketIsConnected(int socket)
 {
+    bool ok = false;
+    LOCK();
     TRACE("socketIsConnected(%d)\r\n", socket);
-    if (!ISSOCKET(socket))
-        return false;
-    return _sockets[socket].state == SOCK_CONNECTED;
+    ok = ISSOCKET(socket) && 
+         _sockets[socket].state == SOCK_CONNECTED;
+    UNLOCK();
+    return ok;
 }
 
 bool MDMParser::socketSetBlocking(int socket, int timeout_ms)
 {
+    bool ok = false;
+    LOCK();
     TRACE("socketSetBlocking(%d,%d)\r\n", socket, timeout_ms);
-    if (!ISSOCKET(socket))
-        return false;
-    _sockets[socket].timeout_ms = timeout_ms;
-    return true;
+    if (ISSOCKET(socket)) {
+        _sockets[socket].timeout_ms = timeout_ms;
+        ok = true;
+    }
+    UNLOCK();
+    return ok;
 }
 
 bool  MDMParser::socketClose(int socket)
 {
-    TRACE("socketClose(%d)\r\n", socket);
-    if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CONNECTED))
-        return false;
-    sendFormated("AT+USOCL=%d\r\n", socket);
-    if (RESP_OK != waitFinalResp())
-        return false;
-    _sockets[socket].state = SOCK_CREATED;
-    return true;
+    bool ok = false;
+    LOCK();
+    if (ISSOCKET(socket) && (_sockets[socket].state == SOCK_CONNECTED)) {
+        TRACE("socketClose(%d)\r\n", socket);
+        sendFormated("AT+USOCL=%d\r\n", socket);
+        if (RESP_OK == waitFinalResp()) {
+            _sockets[socket].state = SOCK_CREATED;
+            ok = true;
+        }
+    }
+    UNLOCK();
+    return ok;
 }
 
 bool  MDMParser::socketFree(int socket)
 {
-    TRACE("socketFree(%d)\r\n", socket);
+    // make sure it is closed
     socketClose(socket);
-    if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CREATED))
-        return false;
-    _sockets[socket].state = SOCK_FREE;
-    return true;
+    bool ok = true;
+    LOCK();
+    if (ISSOCKET(socket) && (_sockets[socket].state == SOCK_CREATED)) {
+        TRACE("socketFree(%d)\r\n", socket);
+        _sockets[socket].state = SOCK_FREE;
+        ok = true;
+    }
+    UNLOCK();
+    return ok;
 }
 
 #define USO_MAX_WRITE 1024 //!< maximum number of bytes to write to socket
@@ -936,12 +995,17 @@
         int blk = USO_MAX_WRITE;
         if (cnt < blk) 
             blk = cnt;
+        bool ok = false;
+        LOCK();
         sendFormated("AT+USOWR=%d,%d\r\n",socket,blk);
-        if (RESP_PROMPT != waitFinalResp())
-            return SOCKET_ERROR;
-        RELAX_MS(50);
-        send(buf, blk);
-        if (RESP_OK != waitFinalResp()) 
+        if (RESP_PROMPT == waitFinalResp()) {
+            wait_ms(50);
+            send(buf, blk);
+            if (RESP_OK == waitFinalResp()) 
+                ok = true;
+        }
+        UNLOCK();
+        if (!ok) 
             return SOCKET_ERROR;
         buf += blk;
         cnt -= blk;
@@ -957,12 +1021,17 @@
         int blk = USO_MAX_WRITE;
         if (cnt < blk) 
             blk = cnt;
-       sendFormated("AT+USOST=%d,\"" IPSTR "\",%d,%d\r\n",socket,IPNUM(ip),port,blk);
-        if (RESP_PROMPT != waitFinalResp())
-            return SOCKET_ERROR;
-        RELAX_MS(50);
-        send(buf, blk);
-        if (RESP_OK != waitFinalResp())
+        bool ok = false;
+        LOCK();
+        sendFormated("AT+USOST=%d,\"" IPSTR "\",%d,%d\r\n",socket,IPNUM(ip),port,blk);
+        if (RESP_PROMPT == waitFinalResp()) {
+            wait_ms(50);
+            send(buf, blk);
+            if (RESP_OK == waitFinalResp())
+                ok = true;
+        }
+        UNLOCK();
+        if (!ok)
             return SOCKET_ERROR;
         buf += blk;
         cnt -= blk;
@@ -972,14 +1041,17 @@
 
 int MDMParser::socketReadable(int socket)
 {
-    TRACE("socketReadable(%d)\r\n", socket);
-    if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CONNECTED))
-        return SOCKET_ERROR;
-    // allow to receive unsolicited commands 
-    waitFinalResp(NULL, NULL, 0);
-    if (_sockets[socket].state != SOCK_CONNECTED)
-        return SOCKET_ERROR;
-    return _sockets[socket].pending;
+    int pending = SOCKET_ERROR;
+    LOCK();
+    if (ISSOCKET(socket) && (_sockets[socket].state == SOCK_CONNECTED)) {
+        TRACE("socketReadable(%d)\r\n", socket);
+        // allow to receive unsolicited commands 
+        waitFinalResp(NULL, NULL, 0);
+        if (_sockets[socket].state == SOCK_CONNECTED)
+           pending = _sockets[socket].pending; 
+    }
+    UNLOCK();
+    return pending;
 }
 
 int MDMParser::_cbUSORD(int type, const char* buf, int len, char* out)
@@ -998,32 +1070,43 @@
 {
     int cnt = 0;
     TRACE("socketRecv(%d,,%d)\r\n", socket, len);
-    if (!ISSOCKET(socket))
-        return SOCKET_ERROR;
+#ifdef MDM_DEBUG
     memset(buf, '\0', len);
+#endif
     Timer timer;
     timer.start();
     while (len) {
         int blk = MAX_SIZE; // still need space for headers and unsolicited  commands 
-        if (_sockets[socket].pending < blk)
-            blk = _sockets[socket].pending;
         if (len < blk) blk = len;
-        if (blk) {
-            sendFormated("AT+USORD=%d,%d\r\n",socket, blk);
-            if (RESP_OK != waitFinalResp(_cbUSORD, buf)) {
-                return SOCKET_ERROR;
+        bool ok = false;        
+        LOCK();
+        if (ISSOCKET(socket)) {
+            if (_sockets[socket].state == SOCK_CONNECTED) {
+                if (_sockets[socket].pending < blk)
+                    blk = _sockets[socket].pending;
+                if (blk > 0) {
+                    sendFormated("AT+USORD=%d,%d\r\n",socket, blk);
+                    if (RESP_OK == waitFinalResp(_cbUSORD, buf)) {
+                        _sockets[socket].pending -= blk;
+                        len -= blk;
+                        cnt += blk;
+                        buf += blk;
+                        ok = true;
+                    }
+                } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) {
+                    ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs
+                } else {
+                    len = 0;
+                    ok = true;
+                }
+            } else if (_sockets[socket].state == SOCK_CREATED) {
+                len = 0;
+                ok = true;
             }
-            len -= blk;
-            cnt += blk;
-            buf += blk;
-            _sockets[socket].pending -= blk;
-        } else if ((_sockets[socket].state == SOCK_CONNECTED) && 
-                   !TIMEOUT(timer, _sockets[socket].timeout_ms)) {
-            // allow to receive unsolicited commands 
-            waitFinalResp(NULL, NULL, 10);
-        } else {
-            len = 0; // no more data and socket closed or timed-out
         }
+        UNLOCK();
+        if (!ok)
+            return SOCKET_ERROR;
     }
     return cnt;
 }
@@ -1032,9 +1115,9 @@
 {
     if ((type == TYPE_PLUS) && param) {
         int sz, sk, p, a,b,c,d;
-        if ((sscanf(buf, "\r\n+USORF: %d,\""IPSTR"\",%d,%d,", 
-            &sk,&a,&b,&c,&d,&p,&sz) == 7) && 
-            (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
+        int r = sscanf(buf, "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,", 
+            &sk,&a,&b,&c,&d,&p,&sz);
+        if ((r == 7) && (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
             memcpy(param->buf, &buf[len-1-sz], sz);
             param->ip = IPADR(a,b,c,d);
             param->port = p;
@@ -1047,34 +1130,43 @@
 {
     int cnt = 0;
     TRACE("socketRecvFrom(%d,,%d)\r\n", socket, len);
-    if (!ISSOCKET(socket))
-        return SOCKET_ERROR;
+#ifdef MDM_DEBUG
     memset(buf, '\0', len);
+#endif
     Timer timer;
     timer.start();
     while (len) {
         int blk = MAX_SIZE; // still need space for headers and unsolicited commands 
-        if (_sockets[socket].pending < blk)
-            blk = _sockets[socket].pending;
         if (len < blk) blk = len;
-        if (blk) {
-            sendFormated("AT+USORF=%d,%d\r\n",socket, blk);
-            USORFparam param;
-            param.buf = buf;
-            if (RESP_OK != waitFinalResp(_cbUSORF, &param)) {
-                return SOCKET_ERROR;
+        bool ok = false;        
+        LOCK();
+        if (ISSOCKET(socket)) {
+            if (_sockets[socket].pending < blk)
+                blk = _sockets[socket].pending;
+            if (blk > 0) {
+                sendFormated("AT+USORF=%d,%d\r\n",socket, blk);
+                USORFparam param;
+                param.buf = buf;
+                if (RESP_OK == waitFinalResp(_cbUSORF, &param)) {
+                    _sockets[socket].pending -= blk;
+                    *ip = param.ip;
+                    *port = param.port;
+                    len -= blk;
+                    cnt += blk;
+                    buf += blk;
+                    len = 0; // done 
+                    ok = true;
+                }
+            } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) {
+                ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs
+            } else {
+                len = 0; // no more data and socket closed or timed-out
+                ok = true;
             }
-            *ip = param.ip;
-            *port = param.port;
-            len -= blk;
-            cnt += blk;
-            buf += blk;
-            _sockets[socket].pending -= blk;
-        } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) {
-            // allow to receive unsolicited commands 
-            waitFinalResp(NULL, NULL, 10);
-        } else
-            len = 0; // no more data and socket closed or timed-out
+        }
+        UNLOCK();
+        if (!ok)
+            return SOCKET_ERROR;
     }
     timer.stop();
     timer.reset();
@@ -1098,37 +1190,41 @@
 }
 
 int MDMParser::smsList(const char* stat /*= "ALL"*/, int* ix /*=NULL*/, int num /*= 0*/) {
+    int ret = -1;
+    LOCK();
     sendFormated("AT+CMGL=\"%s\"\r\n", stat);
     CMGLparam param;
     param.ix = ix;
     param.num = num;
-    if (RESP_OK != waitFinalResp(_cbCMGL, &param))
-        return -1;
-    return num - param.num;
+    if (RESP_OK == waitFinalResp(_cbCMGL, &param))
+        ret = num - param.num;
+    UNLOCK();
+    return ret;
 }
 
 bool MDMParser::smsSend(const char* num, const char* buf)
 {
+    bool ok = false;
+    LOCK();
     sendFormated("AT+CMGS=\"%s\"\r\n",num);
-    if (RESP_PROMPT != waitFinalResp(NULL,NULL,150*1000)) {
-        return false;
+    if (RESP_PROMPT == waitFinalResp(NULL,NULL,150*1000)) {
+        send(buf, strlen(buf));
+        const char ctrlZ = 0x1A;
+        send(&ctrlZ, sizeof(ctrlZ));
+        ok = (RESP_OK == waitFinalResp());
     }
-    send(buf, strlen(buf));
-    const char ctrlZ = 0x1A;
-    send(&ctrlZ, sizeof(ctrlZ));
-    if (RESP_OK != waitFinalResp()) {
-        return false;
-    }
-    return true;
+    UNLOCK();
+    return ok;
 }
 
 bool MDMParser::smsDelete(int ix)
 {
+    bool ok = false;
+    LOCK();
     sendFormated("AT+CMGD=%d\r\n",ix);
-    if (RESP_OK != waitFinalResp()) {
-        return false;
-    }
-    return true;
+    ok = (RESP_OK == waitFinalResp());
+    UNLOCK();
+    return ok;
 }
 
 int MDMParser::_cbCMGR(int type, const char* buf, int len, CMGRparam* param)
@@ -1147,14 +1243,15 @@
 
 bool MDMParser::smsRead(int ix, char* num, char* buf, int len)
 {
+    bool ok = false;
+    LOCK();
     CMGRparam param;
     param.num = num;
     param.buf = buf;
     sendFormated("AT+CMGR=%d\r\n",ix);
-    if (RESP_OK != waitFinalResp(_cbCMGR, &param)) {
-        return false;
-    }
-    return true;
+    ok = (RESP_OK == waitFinalResp(_cbCMGR, &param));
+    UNLOCK();
+    return ok;
 }
    
 // ----------------------------------------------------------------
@@ -1172,47 +1269,54 @@
 
 bool MDMParser::ussdCommand(const char* cmd, char* buf)
 {
-    if (_dev.dev == DEV_LISA_C200) 
-        return false;
+    bool ok = false;
+    LOCK();
     *buf = '\0';
-    sendFormated("AT+CUSD=1,\"%s\"\r\n",cmd);
-    if (RESP_OK != waitFinalResp(_cbCUSD, buf)) {
-        return false;
+    if (_dev.dev != DEV_LISA_C200) {
+        sendFormated("AT+CUSD=1,\"%s\"\r\n",cmd);
+        ok = (RESP_OK == waitFinalResp(_cbCUSD, buf));
     }
-    return true;
+    UNLOCK();
+    return ok;
 }
 
 // ----------------------------------------------------------------
    
 bool MDMParser::delFile(const char* filename)
 {
+    bool ok = false;
+    LOCK();
     sendFormated("AT+UDELFILE=\"%s\"\r\n", filename);
-    if (RESP_OK != waitFinalResp())
-        return false;
-    return true;
+    ok = (RESP_OK == waitFinalResp());
+    UNLOCK();
+    return ok;
 }
 
 int MDMParser::writeFile(const char* filename, const char* buf, int len)
 {
+    bool ok = false;
+    LOCK();
     sendFormated("AT+UDWNFILE=\"%s\",%d\r\n", filename, len);
-    if (RESP_PROMPT != waitFinalResp())
-        return 0;
-    send(buf, len);
-    if (RESP_OK != waitFinalResp())
-        return 0;
-    return len;
+    if (RESP_PROMPT == waitFinalResp()) {
+        send(buf, len);
+        ok = (RESP_OK == waitFinalResp());
+    }
+    UNLOCK();
+    return ok ? len : -1;
 }
 
 int MDMParser::readFile(const char* filename, char* buf, int len)
 {
-    sendFormated("AT+URDFILE=\"%s\"\r\n", filename, len);
     URDFILEparam param;
     param.filename = filename;
     param.buf = buf; 
     param.sz = len; 
     param.len = 0;
-    if (RESP_OK != waitFinalResp(_cbURDFILE, &param))
-        return -1;
+    LOCK();
+    sendFormated("AT+URDFILE=\"%s\"\r\n", filename, len);
+    if (RESP_OK != waitFinalResp(_cbURDFILE, &param));
+        param.len = -1;
+    UNLOCK();
     return param.len;
 }
 
@@ -1388,7 +1492,7 @@
               const char* fmt;                              int type; 
         } lutF[] = {
             { "\r\n+USORD: %d,%d,\"%c\"",                   TYPE_PLUS       },
-            { "\r\n+USORF: %d,\""IPSTR"\",%d,%d,\"%c\"",    TYPE_PLUS       },
+            { "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,\"%c\"",  TYPE_PLUS       },
             { "\r\n+URDFILE: %s,%d,\"%c\"",                 TYPE_PLUS       },
         };
         static struct { 
--- a/MDM.h	Thu Jun 12 12:41:26 2014 +0000
+++ b/MDM.h	Tue Jun 17 07:03:48 2014 +0000
@@ -493,6 +493,16 @@
     static int _parseFormated(Pipe<char>* pipe, int len, const char* fmt);
 
 protected:
+    // for rtos over riding by useing Rtos<MDMxx> 
+    /** override in a rtos system, you us the wait function of a Thread
+        \param ms the number of milliseconds to wait
+    */
+    virtual void wait_ms(int ms)   { if (ms) ::wait_ms(ms); }
+    //! override the lock in a rtos system
+    virtual void lock(void)        { } 
+    //! override the unlock in a rtos system
+    virtual void unlock(void)      { } 
+protected:
     // parsing callbacks for different AT commands and their parameter arguments
     static int _cbString(int type, const char* buf, int len, char* str);
     static int _cbInt(int type, const char* buf, int len, int* val);
@@ -530,7 +540,7 @@
     IP          _ip;  //!< assigned ip address
     // management struture for sockets
     typedef enum { SOCK_FREE, SOCK_CREATED, SOCK_CONNECTED } SockState;
-    typedef struct { SockState state; int pending; int timeout_ms; } SockCtrl;
+    typedef struct { volatile SockState state; volatile int pending; int timeout_ms; } SockCtrl;
     // LISA-C has 6 TCP and 6 UDP sockets starting at index 18
     // LISA-U and SARA-G have 7 sockets starting at index 1
     SockCtrl _sockets[32];
@@ -594,7 +604,6 @@
     virtual int _send(const void* buf, int len);
 };
 
- 
 // -----------------------------------------------------------------------
 
 //#define HAVE_MDMUSB
@@ -612,4 +621,27 @@
 };
 #endif
 
+// -----------------------------------------------------------------------
 
+#ifdef RTOS_H
+/** Use this template to override the lock and wait functions of the 
+    modem driver in a Rtos system. For example declare it the modem 
+    object as MDMRtos<MDMSerial> instead of MDMSerial.
+*/
+template <class T>
+class MDMRtos :  public T
+{
+protected:
+    //! we assume that the modem runs in a thread so we yield when waiting
+    virtual void wait_ms(int ms)   {
+        if (ms) Thread::wait(ms);
+        else    Thread::yield();
+    }
+    //! lock a mutex when accessing the modem
+    virtual void lock(void)     { _mtx.lock(); }  
+    //! unlock the modem when done accessing it
+    virtual void unlock(void)   { _mtx.unlock(); }
+    // the mutex resource
+    Mutex _mtx;
+};
+#endif
\ No newline at end of file
--- a/Pipe.h	Thu Jun 12 12:41:26 2014 +0000
+++ b/Pipe.h	Tue Jun 17 07:03:48 2014 +0000
@@ -1,5 +1,4 @@
 #pragma once 
-#include "Relax.h"
 
 /** pipe, this class implements a buffered pipe that can be savely 
     written and read between two context. E.g. Written from a task 
@@ -78,7 +77,7 @@
         int j = i;
         i = _inc(i);
         while (i == _r) // = !writeable() 
-            RELAX_MS(0);
+            /* nothing / just wait */;
         _b[j] = c;
         _w = i; 
         return c;
@@ -101,7 +100,7 @@
                 f = free();
                 if (f > 0) break;     // data avail
                 if (!t) return n - c; // no more space and not blocking
-                RELAX_MS(0);
+                /* nothing / just wait */;
             }
             // check free space
             if (c < f) f = c;
@@ -146,7 +145,7 @@
     {
         int r = _r;
         while (r == _w) // = !readable()
-            RELAX_MS(0);
+            /* nothing / just wait */;
         T t = _b[r];
         _r = _inc(r);
         return t;
@@ -169,7 +168,7 @@
                 f = size();
                 if (f)  break;        // free space
                 if (!t) return n - c; // no space and not blocking
-                RELAX_MS(0);
+                /* nothing / just wait */;
             }
             // check available data
             if (c < f) f = c;
--- a/Relax.h	Thu Jun 12 12:41:26 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-#pragma once 
-
-#include "mbed.h"
-
-#ifdef USING_RTOS
-#include "rtos.h"
-inline void RELAX_MS(unsigned int ms) {
-    if (ms) Thread::wait(ms);
-    else    Thread::yield();
-}
-#else
-inline void RELAX_MS(unsigned int ms) {
-    if (ms) wait_ms(ms);
-}
-#endif
--- a/SerialPipe.cpp	Thu Jun 12 12:41:26 2014 +0000
+++ b/SerialPipe.cpp	Tue Jun 17 07:03:48 2014 +0000
@@ -46,7 +46,7 @@
             }
             else if (!blocking)
                 break;
-            RELAX_MS(0);
+            /* nothing / just wait */;
         }
         while (count);
     }