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

This library is intended to be used with u-blox products such as the C027 or a shield with u-blox cellular and GPS modules like the cellular and positioning shield from Embedded Artist.

For 2G/GSM and 3G/UMTS you need to:

  • have a SIM card and know its PIN number
  • need to know you network operators APN setting These setting should be passed to the connect or init and join functions. You can also extend the APN database in MDMAPN.h.

For CDMA products you need to make sure that you have provisioned and activated the modem with either Sprint or Verizon.

Revision:
84:a05edb010176
Parent:
82:055dcfcf9dcc
Child:
85:dd8f4f0d0ca9
--- a/MDM.cpp	Wed May 28 07:14:21 2014 +0000
+++ b/MDM.cpp	Thu Jun 05 15:16:57 2014 +0000
@@ -5,6 +5,42 @@
  #include "C027_api.h"
 #endif
 
+/* ----------------------------------------------------------------
+   APN stands for Access Point Name, a setting on your modem or phone
+   that identifies an external network your phone can access for data 
+   (e.g., 3G or 4G Internet service on your phone). 
+   
+   The APN settings can be forced when calling the join function.
+   Below is a list of known APNs that us used if no apn config 
+   is forced. This list could be extended by other settings.
+   
+   For further reading:
+   wiki apn: http://en.wikipedia.org/wiki/Access_Point_Name
+   wiki mcc/mnc: http://en.wikipedia.org/wiki/Mobile_country_code
+   google: https://www.google.de/search?q=APN+list   
+---------------------------------------------------------------- */
+//! helper 
+#define _APN(a,u,p) a "\0" u "\0" p "\0"
+//! default APN settings used by many networks
+static const char* apndef =     _APN("internet",,); 
+//! this is a list of special APNs for different network operators 
+static const struct { const char* mccmnc; const char* cfg; } apnlut[] = {
+// Germany 
+    { /*T-Mobile*/ "26201",     _APN("internet.t-mobile","t-mobile","tm") },
+// Switzerland
+    { /*Swisscom*/ "22801",     _APN("gprs.swisscom.ch",,) },
+// USA
+    { /*T-Mobile*/ "310026|310260|310490",
+                                _APN("epc.tmobile.com",,) 
+                                _APN("fast.tmobile.com",,) /*LTE*/ },
+    { /*AT&T*/     "310030|310150|310170|310260|310410|310560|310680",
+                                _APN("phone",,)
+                                _APN("wap.cingular","WAP@CINGULARGPRS.COM","CINGULAR1")
+                                _APN("isp.cingular","ISP@CINGULARGPRS.COM","CINGULAR1") },
+    // ...     
+};
+// ----------------------------------------------------------------
+                
 #define PROFILE         "0"   //!< this is the psd profile used
 #define MAX_SIZE        128   //!< max expected messages
 //! test if it is a socket
@@ -173,7 +209,7 @@
                         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>]]
+                        // +CSS: <mode>[,<format>,<oper>[,<AcT>]]
                     } else if (sscanf(cmd, "CSS %*c,%2s,%*d",s) == 1) {
                         //_net.reg = (strcmp("Z", s) == 0) ? REG_UNKNOWN : REG_HOME;
                     }
@@ -430,6 +466,10 @@
         sendFormated("AT+CGREG=2\r\n");
         if (RESP_OK != waitFinalResp())
             return false;
+        // set operator selection 
+        sendFormated("AT+COPS=0,0\r\n");
+        if (RESP_OK != waitFinalResp(NULL,NULL,180*1000))
+            return false;
     } 
     // enable the network registration unsolicited result code
     sendFormated("AT+CREG=%d\r\n", (_dev.dev == DEV_LISA_C200) ? 1 : 2);
@@ -585,7 +625,6 @@
             if (RESP_OK != waitFinalResp(_cbString, nai))
                 return false;
         } else {
-            // check operator selection 
             sendFormated("AT+COPS?\r\n");
             if (RESP_OK != waitFinalResp(_cbCOPS, &_net))
                 return false;
@@ -689,50 +728,73 @@
             // 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;;
+                return NOIP;
             a = 0;
         }
         if (a == 0) {
-            // Set up the APN
-            if (apn) {
-                sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn);
-                if (RESP_OK != waitFinalResp())
-                    return NOIP;
+            bool ok = false;
+            // try to lookup the apn settings from our local database by mccmnc
+            const char* config = NULL;
+            if (!apn && !username && !password) {
+                char mccmnc[8] = "";
+                config = apndef;
+                sendFormated("AT+UDOPN=0\r\n");
+                if ((RESP_OK == waitFinalResp(_cbUDOPN, mccmnc)) && *mccmnc) {
+                    // many carriers use internet without username and password, os use this as default
+                    // now try to lookup the setting for our table
+                    for (int i = 0; i < sizeof(apnlut)/sizeof(*apnlut); i ++) {
+                        if (strstr(apnlut[i].mccmnc, mccmnc)) {
+                            config = apnlut[i].cfg;
+                            break;
+                        }
+                    }
+                }
             }
-            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;
-            // 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;
+ 
+            do {
+                if (config) {
+                    apn      = *config ? config : "";
+                    config  += strlen(config)+1;
+                    username = *config ? config : "";
+                    config  += strlen(config)+1;
+                    password = *config ? config : "";
+                    config  += strlen(config)+1;
+                    if (!*config) config  = NULL;
+                    TRACE("Testing APN Settings(\"%s\",\"%s\",\"%s\")\r\n", apn, username, password);
                 }
-                i ++;
-            }
-            if (i > AUTH_CHAP) {
+                // Set up the APN
+                sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn?apn:"");
+                if (RESP_OK != waitFinalResp())
+                    return NOIP;
+                sendFormated("AT+UPSD=" PROFILE ",2,\"%s\"\r\n", username?username:"");
+                if (RESP_OK != waitFinalResp())
+                    return NOIP;
+                sendFormated("AT+UPSD=" PROFILE ",3,\"%s\"\r\n", password?password:"");
+                if (RESP_OK != waitFinalResp())
+                    return NOIP;
+                // try different Authentication Protocols
+                // 0 = none 
+                // 1 = PAP (Password Authentication Protocol)
+                // 2 = CHAP (Challenge Handshake Authentication Protocol)
+                for (int i = AUTH_NONE; i <= AUTH_CHAP && !ok; i ++) {
+                    if ((auth == AUTH_DETECT) || (auth == i)) {
+                        // Set up the Authentication Protocol
+                        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))
+                            ok = true;
+                    }
+                }
+            } while (config); // maybe use next setting ? 
+            if (!ok) {
                 ERROR("Your modem APN/password/username may be wrong\r\n");
                 return NOIP;
             }
@@ -745,6 +807,15 @@
     return _ip;
 }
 
+int MDMParser::_cbUDOPN(int type, const char* buf, int len, char* mccmnc)
+{
+    if ((type == TYPE_PLUS) && mccmnc) {
+        if (sscanf(buf, "\r\n+UDOPN: 0,\"%[^\"]\"", mccmnc) == 1)
+            ;
+    }
+    return WAIT;
+}
+
 int MDMParser::_cbCMIP(int type, const char* buf, int len, IP* ip)
 {
     if ((type == TYPE_PLUS) && ip) {