Own fork of C027_Support

Dependents:   MbedSmartRestMain MbedSmartRestMain

Fork of C027_Support by u-blox

Revision:
79:291df065e345
Parent:
78:caf0014375cb
Child:
80:34985b4d821e
diff -r caf0014375cb -r 291df065e345 MDM.cpp
--- a/MDM.cpp	Tue May 20 11:40:07 2014 +0000
+++ b/MDM.cpp	Mon May 26 11:55:16 2014 +0000
@@ -12,6 +12,9 @@
 //! check for timeout
 #define TIMEOUT(t, ms)  ((ms != TIMEOUT_BLOCKING) && (ms < t.read_ms())) 
 
+#define REG_OK(r)       ((r == REG_HOME) || (r == REG_ROAMING)) 
+#define REG_DONE(r)     ((r == REG_HOME) || (r == REG_ROAMING) || (r == REG_DENIED)) 
+
 #ifdef MDM_DEBUG
 void dumpAtCmd(const char* buf, int len)
 {
@@ -162,11 +165,12 @@
                     if (sscanf(cmd, "CREG: %*d,%d,%d,%d",&a,&b,&c) == 3) {
                         // _net.sid = a;
                         // _net.nid = b;
-                        if      (c == 0) _net.reg = REG_NONE;     // not registered, home network
-                        else if (c == 1) _net.reg = REG_HOME;     // registered, home network
-                        else if (c == 2) _net.reg = REG_NONE;     // not registered, but MT is currently searching a new operator to register to
-                        else if (c == 3) _net.reg = REG_DENIED;   // registration denied
-                        else if (c == 5) _net.reg = REG_ROAMING;  // registered, roaming
+                        if      (c == 0) _net.csd = REG_NONE;     // not registered, home network
+                        else if (c == 1) _net.csd = REG_HOME;     // registered, home network
+                        else if (c == 2) _net.csd = REG_NONE;     // not registered, but MT is currently searching a new operator to register to
+                        else if (c == 3) _net.csd = REG_DENIED;   // registration denied
+                        else if (c == 5) _net.csd = REG_ROAMING;  // registered, roaming
+                        _net.psd = _net.csd; // fake PSD registration (CDMA is always registered)
                         _net.act = ACT_CDMA;
                     // +CSS: <mode>[,<format>,<oper>[,<AcT>]]
                     } else if (sscanf(cmd, "CSS %*c,%2s,%*d",s) == 1) {
@@ -174,35 +178,41 @@
                     }
                 } else {
                     // GSM/UMTS Specific -------------------------------------------
-                    // +CREG: <n>,<stat>[,<lac>,<ci>[,AcT]] // reply to AT+CREG
-                    // +CREG: <stat>[,<lac>,<ci>[,AcT]] // URC
-                    b = 255;
-                    r = sscanf(cmd, "CREG: %*d,%d,\"%X\",\"%X\",%d",&a,&b,&c,&d);
-                    if (r <= 0)
-                        r = sscanf(cmd, "CREG: %d,\"%X\",\"%X\",%d",&a,&b,&c,&d);
-                    if (r >= 1) {
-                        // network status
-                        if      (a == 0) _net.reg = REG_NONE;     // 0: not registered, home network
-                        else if (a == 1) _net.reg = REG_HOME;     // 1: registered, home network
-                        else if (a == 2) _net.reg = REG_NONE;     // 2: not registered, but MT is currently searching a new operator to register to
-                        else if (a == 3) _net.reg = REG_DENIED;   // 3: registration denied
-                        else if (a == 4) _net.reg = REG_UNKNOWN;  // 4: unknown
-                        else if (a == 5) _net.reg = REG_ROAMING;  // 5: registered, roaming
-                        if ((r >= 2) && (b != 0xFFFF))      _net.lac = b; // location area code
-                        if ((r >= 3) && (c != 0xFFFFFFFF))  _net.ci  = c; // cell ID
-                        // access technology
-                        if (r >= 4) {
-                            if      (d == 0) _net.act = ACT_GSM;      // 0: GSM
-                            else if (d == 1) _net.act = ACT_GSM;      // 1: GSM COMPACT
-                            else if (d == 2) _net.act = ACT_UTRAN;    // 2: UTRAN
-                            else if (d == 3) _net.act = ACT_EDGE;     // 3: GSM with EDGE availability
-                            else if (d == 4) _net.act = ACT_UTRAN;    // 4: UTRAN with HSDPA availability
-                            else if (d == 5) _net.act = ACT_UTRAN;    // 5: UTRAN with HSUPA availability
-                            else if (d == 6) _net.act = ACT_UTRAN;    // 6: UTRAN with HSDPA and HSUPA availability
+                    // +UUPSDD: <profile_id> 
+                    if (sscanf(cmd, "UUPSDD: %d",&a) == 1) {
+                        if (*PROFILE == a) _ip = NOIP;
+                    } else {
+                        // +CREG|CGREG: <n>,<stat>[,<lac>,<ci>[,AcT[,<rac>]]] // reply to AT+CREG|AT+CGREG
+                        // +CREG|CGREG: <stat>[,<lac>,<ci>[,AcT[,<rac>]]]     // URC
+                        b = 0xFFFF; c = 0xFFFFFFFF; d = -1;
+                        r = sscanf(cmd, "%s %*d,%d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d);
+                        if (r <= 1)
+                            r = sscanf(cmd, "%s %d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d);
+                        if (r >= 2) {
+                            Reg *reg = !strcmp(s, "CREG:")  ? &_net.csd : 
+                                       !strcmp(s, "CGREG:") ? &_net.psd : NULL;
+                            if (reg) {
+                                // network status
+                                if      (a == 0) *reg = REG_NONE;     // 0: not registered, home network
+                                else if (a == 1) *reg = REG_HOME;     // 1: registered, home network
+                                else if (a == 2) *reg = REG_NONE;     // 2: not registered, but MT is currently searching a new operator to register to
+                                else if (a == 3) *reg = REG_DENIED;   // 3: registration denied
+                                else if (a == 4) *reg = REG_UNKNOWN;  // 4: unknown
+                                else if (a == 5) *reg = REG_ROAMING;  // 5: registered, roaming
+                                if ((r >= 3) && (b != 0xFFFF))      _net.lac = b; // location area code
+                                if ((r >= 4) && (c != 0xFFFFFFFF))  _net.ci  = c; // cell ID
+                                // access technology
+                                if (r >= 5) {
+                                    if      (d == 0) _net.act = ACT_GSM;      // 0: GSM
+                                    else if (d == 1) _net.act = ACT_GSM;      // 1: GSM COMPACT
+                                    else if (d == 2) _net.act = ACT_UTRAN;    // 2: UTRAN
+                                    else if (d == 3) _net.act = ACT_EDGE;     // 3: GSM with EDGE availability
+                                    else if (d == 4) _net.act = ACT_UTRAN;    // 4: UTRAN with HSDPA availability
+                                    else if (d == 5) _net.act = ACT_UTRAN;    // 5: UTRAN with HSUPA availability
+                                    else if (d == 6) _net.act = ACT_UTRAN;    // 6: UTRAN with HSDPA and HSUPA availability
+                                }
+                            }
                         }
-                    // +UUPSDD: <profile_id> 
-                    } else if (sscanf(cmd, "UUPSDD: %d",&a) == 1) {
-                        if (*PROFILE == a) _ip = NOIP;
                     }
                 }
             }
@@ -277,10 +287,17 @@
         INFO("Modem::wakeup\r\n");
         DigitalOut pin(pn, 1);
         while (i--) {
-            pin = 0;
-            RELAX_MS(5); // SARA-G/U
-            pin = 1;
-            RELAX_MS(100);
+            // SARA-U2/LISA-U2 50..80us
+            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);
+            
+            // 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))
@@ -407,7 +424,15 @@
                 return false;  
             _dev.lpm = LPM_ACTIVE;
         }
+        // enable the psd registration unsolicited result code
+        sendFormated("AT+CGREG=2\r\n");
+        if (RESP_OK != waitFinalResp())
+            return false;
     } 
+    // 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;
     // Setup SMS in text mode 
     sendFormated("AT+CMGF=1\r\n");
     if (RESP_OK != waitFinalResp())
@@ -420,10 +445,6 @@
     sendFormated("AT+CIMI\r\n");
     if (RESP_OK != waitFinalResp(_cbString, _dev.imsi))
         return false;
-    // 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;
     if (status)
         memcpy(status, &_dev, sizeof(DevStatus));
     return true; 
@@ -489,9 +510,9 @@
     INFO("Modem::register\r\n");
     while (!checkNetStatus(status) && !TIMEOUT(timer, timeout_ms))
         RELAX_MS(1000);
-    if (_net.reg == REG_DENIED)
-        ERROR("Network Registration Denied\r\n");
-    return (_net.reg == REG_ROAMING) || (_net.reg == REG_HOME);
+    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);
 }
 
 bool MDMParser::checkNetStatus(NetStatus* status /*= NULL*/)
@@ -503,7 +524,13 @@
     sendFormated("AT+CREG?\r\n");
     if (RESP_OK != waitFinalResp())
         return false;
-    if ((_net.reg == REG_ROAMING) || (_net.reg == REG_HOME))
+    if (_dev.dev != DEV_LISA_C200) {
+        // check PSD registration
+        sendFormated("AT+CGREG?\r\n");
+        if (RESP_OK != waitFinalResp())
+            return false;
+    }
+    if (REG_OK(_net.csd) || REG_OK(_net.psd))
     {
         // check modem specific status messages 
         if (_dev.dev == DEV_LISA_C200) {
@@ -515,7 +542,7 @@
             if (RESP_OK != waitFinalResp(_cbString, _net.num))
                 return false;
             // check if we have a Mobile Directory Number
-            if (!*_net.num || (memcmp(_net.num, "0000", 4) == 0))
+            if (!*_net.num || (memcmp(_net.num, "000000", 6) == 0))
                 return false;
             // get the the Network access identifier string
             char nai[64];
@@ -523,10 +550,6 @@
             if (RESP_OK != waitFinalResp(_cbString, nai))
                 return false;
         } else {
-            // check GPRS attach status
-            sendFormated("AT+CGATT?\r\n");
-            if (RESP_OK != waitFinalResp(_cbCGATT, &_net.gprs))
-                return false;
             // check operator selection 
             sendFormated("AT+COPS?\r\n");
             if (RESP_OK != waitFinalResp(_cbCOPS, &_net))
@@ -544,19 +567,7 @@
     if (status) {
         memcpy(status, &_net, sizeof(NetStatus));
     }
-    return ((_net.reg == REG_HOME) || (_net.reg == REG_ROAMING) || (_net.reg == REG_DENIED));
-}
-
-int MDMParser::_cbCGATT(int type, const char* buf, int len, Gprs* gprs)
-{
-    if ((type == TYPE_PLUS) && gprs){
-        int i;
-        if (sscanf(buf, "\r\n+CGATT: %d\r\n", &i) == 1) {
-            if      (i == 0) *gprs = GPRS_DETACHED;
-            else if (i == 1) *gprs = GPRS_ATTACHED;
-        }
-    }
-    return WAIT;
+    return REG_DONE(_net.csd) && REG_DONE(_net.psd);
 }
 
 int MDMParser::_cbCOPS(int type, const char* buf, int len, NetStatus* status)
@@ -600,7 +611,8 @@
 // ----------------------------------------------------------------
 // internet connection 
 
-MDMParser::IP MDMParser::join(const char* apn /*= NULL*/, const char* username /*= NULL*/, const char* password /*= NULL*/)
+MDMParser::IP MDMParser::join(const char* apn /*= NULL*/, const char* username /*= NULL*/, 
+                              const char* password /*= NULL*/, Auth auth /*= AUTH_DETECT*/)
 {
     INFO("Modem::join\r\n");
     _ip = NOIP;
@@ -623,40 +635,61 @@
         
         // Check the profile
         int a = 0;
+        bool force = true;
         sendFormated("AT+UPSND=" PROFILE ",8\r\n");
         if (RESP_OK != waitFinalResp(_cbUPSND, &a))
             return NOIP;
-        if (a == 1) {
+        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;;
+            a = 0;
         }
-        // Set up the APN
-        if (apn) {
-            sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn);
-            if (RESP_OK != waitFinalResp())
-                return NOIP;
-        }
-        if (username) {    
-            sendFormated("AT+UPSD=" PROFILE ",2,\"%s\"\r\n", username);
+        if (a == 0) {
+            // Set up the APN
+            if (apn) {
+                sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn);
+                if (RESP_OK != waitFinalResp())
+                    return NOIP;
+            }
+            if (username) {    
+                sendFormated("AT+UPSD=" PROFILE ",2,\"%s\"\r\n", username);
+                if (RESP_OK != waitFinalResp())
+                    return NOIP;
+            }
+            if (password) {
+                sendFormated("AT+UPSD=" PROFILE ",3,\"%s\"\r\n", password);
+                if (RESP_OK != waitFinalResp())
+                    return NOIP;
+            }
+            // Set up the dynamic IP address assignment.
+            sendFormated("AT+UPSD=" PROFILE ",7,\"0.0.0.0\"\r\n");
             if (RESP_OK != waitFinalResp())
                 return NOIP;
-        }
-        if (password) {
-            sendFormated("AT+UPSD=" PROFILE ",3,\"%s\"\r\n", password);
-            if (RESP_OK != waitFinalResp())
+            // try different Authentication Protocols
+            // 0 = none 
+            // 1 = PAP (Password Authentication Protocol)
+            // 2 = CHAP (Challenge Handshake Authentication Protocol)
+            int i = AUTH_NONE;
+            while (i <= AUTH_CHAP)
+            {
+                if ((auth == AUTH_DETECT) || (auth == i)) {
+                    // Set up the dynamic IP address assignment.
+                    sendFormated("AT+UPSD=" PROFILE ",6,%d\r\n", i);
+                    if (RESP_OK != waitFinalResp())
+                        return NOIP;
+                    // Activate the profile and make connection
+                    sendFormated("AT+UPSDA=" PROFILE ",3\r\n");
+                    if (RESP_OK == waitFinalResp(NULL,NULL,150*1000))
+                        break;
+                }
+                i ++;
+            }
+            if (i > AUTH_CHAP) {
+                ERROR("Your modem APN/password/username may be wrong\r\n");
                 return NOIP;
-        }
-        // Set up the dynamic IP address assignment.
-        sendFormated("AT+UPSD=" PROFILE ",7,\"0.0.0.0\"\r\n");
-        if (RESP_OK != waitFinalResp())
-            return NOIP;
-        // Activate the profile and make connection
-        sendFormated("AT+UPSDA=" PROFILE ",3\r\n");
-        if (RESP_OK != waitFinalResp(NULL,NULL,150*1000)) {
-            ERROR("Your modem APN/password/username may be wrong\r\n");
-            return NOIP;
+            }
         }
         //Get local IP address
         sendFormated("AT+UPSND=" PROFILE ",0\r\n");
@@ -1128,11 +1161,10 @@
 {
     dprint(param, "Modem::netStatus\r\n");
     const char* txtReg[] = { "Unknown", "Denied", "None", "Home", "Roaming" };
-    if (status->reg < sizeof(txtReg)/sizeof(*txtReg) && (status->reg != MDMParser::REG_UNKNOWN))
-        dprint(param, "  Registration:       %s\r\n", txtReg[status->reg]);
-    const char* txtGprs[] = { "Unknown", "Detached", "Attached" };
-    if (status->gprs < sizeof(txtGprs)/sizeof(*txtGprs) && (status->gprs != MDMParser::GPRS_UNKNOWN))
-        dprint(param, "  Gprs:               %s\r\n", txtGprs[status->gprs]);
+    if (status->csd < sizeof(txtReg)/sizeof(*txtReg) && (status->csd != MDMParser::REG_UNKNOWN))
+        dprint(param, "  CSD Registration:   %s\r\n", txtReg[status->csd]);
+    if (status->psd < sizeof(txtReg)/sizeof(*txtReg) && (status->psd != MDMParser::REG_UNKNOWN))
+        dprint(param, "  PSD Registration:   %s\r\n", txtReg[status->psd]);
     const char* txtAct[] = { "Unknown", "GSM", "Edge", "3G", "CDMA" };
     if (status->act < sizeof(txtAct)/sizeof(*txtAct) && (status->act != MDMParser::ACT_UNKNOWN))
         dprint(param, "  Access Technology:  %s\r\n", txtAct[status->act]);