Add a bunch of APNs

Fork of C027_Support by Xinlei Cao

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) {