Implementation of 3G USB Modem Huawei E372

Dependents:   PYRN

Revision:
2:61ac95f0af72
Parent:
1:fbf17fb09581
--- a/PyrnUSBModem.cpp	Fri Feb 20 17:15:55 2015 +0000
+++ b/PyrnUSBModem.cpp	Tue Apr 14 13:27:07 2015 +0000
@@ -1,7 +1,11 @@
 
-#include "dbg.h"
 #include "PyrnUSBModem.h"
-#include "HuaweiUSBModemInitializer.h"
+
+#define __DEBUG__ 5
+#ifndef __MODULE__
+#define __MODULE__ "PyrnUSBModem.cpp"
+#endif
+#include "MyDebug.h"
 
 // Command Processors
 
@@ -12,18 +16,18 @@
     PIN_STATUS getStatus() { return status; }
 private:
     virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line) {
-        USB_DBG("GOT %s",line);
+        DBG("GOT %s",line);
         if(!strncmp(line, "+CPIN: READY",12)) {
             status = STATUS_READY; 
-            USB_DBG("STATUS_READY");
+            DBG("STATUS_READY");
         } else if(!strncmp(line, "+CPIN: SIM PIN",14)) {
             status = STATUS_SIMPIN;
-            USB_DBG("STATUS_SIMPIN");
+            DBG("STATUS_SIMPIN");
         }else if(!strncmp(line, "+CPIN: SIM PUK",14)) {
             status = STATUS_SIMPUK;
-            USB_DBG("STATUS_SIMPUK");
+            DBG("STATUS_SIMPUK");
         } else
-            USB_DBG("STATUS_NONE");
+            DBG("STATUS_NONE");
         return OK;
     }
     virtual int onNewEntryPrompt(ATCommandsInterface* pInst) { return OK; }
@@ -117,135 +121,210 @@
     volatile bool valid;
 };
 
-PyrnUSBModem::PyrnUSBModem(USBHost *host): 
+// ==================== MODEM =====================
+
+PyrnUSBModem::PyrnUSBModem():
+        initialiser(USBHost::getHostInst()),
         dongle(),   
         atStream(dongle.getSerial(3)),
-        pppStream(dongle.getSerial(3)),
+        pppStream(dongle.getSerial(0)),
         at(&atStream),
-        ppp(&pppStream),
+        ppp(&pppStream), 
         atOpen(false),
-        pppOpen(false) {
-    // If we support more dongle add the initializer here.
-    // furthermore add dongle specific initialisation int init().
-    HuaweiE372USBModemInitializer *huaweie372Initializer = new HuaweiE372USBModemInitializer(host);
-    dongle.addInitializer(huaweie372Initializer);
+        simReady(false),
+        pppOpen(false),
+        ipInit(false) {
+    DBG("Add E372 dongle initializer");
+    dongle.addInitializer(&initialiser);
 }
 
 bool PyrnUSBModem::init() {
-
+    int ret = 0;
+    
     if(!dongle.connected()){
-        while(!dongle.connected()) {
-          USB_INFO("Dongle try connect");
-          dongle.tryConnect();
-          Thread::wait(10);
+        bool detectConnectedModem = false;
+        for (int x=0; x<5;x++){
+            DBG("Trying to connect the dongle");
+            dongle.tryConnect();
+            if (dongle.connected()) {
+                DBG("Great the dongle is connected - I've tried %d times to connect", x);
+                detectConnectedModem = true;
+                break;                              // Break out of the for loop once the dongle is connected - otherwise try for a while more
+            }
+            Thread::wait(7000);
         }
-        if(!dongle.connected())
+        if (!detectConnectedModem) {
+            // OK we got this far - so give up trying and let someone know you can't see the modem
+            ERR("There is no dongle pluged into the board, or the module does not respond. Is the module/modem switched on?");
             return false;
-    } else 
-        USB_INFO("Dongle is already connected ... continue");
-
-    if(atOpen) {
-        USB_INFO("Stream is already opened");
-        return true;
+        }
+    } else {
+        INFO("Dongle is already connected ... continue");
     }
 
-    USB_INFO("Starting AT thread if needed");
-    int ret = at.open();
-    if(ret) {
-        USB_ERR("Opening AT failed");
-        return false;
-    }
-
-    USB_INFO("Sending initialisation commands");
-    ret = at.init();
-    if(ret) {
-        USB_ERR("Initialisation AT failed");
-        return false;
-    }
-
-    if(dongle.getDongleType() == WAN_DONGLE_TYPE_HUAWEI_E372) {
-        USB_INFO("Using a Vodafone E372 Dongle");
-        // Specific dongle initisation
-        ret = at.executeSimple("AT", NULL,5000);
-        if(ret != OK){
-            USB_ERR("AT Simple command ERROR");
+    if(atOpen) {
+        INFO("Stream is already opened go to SIM Check");
+    } else {
+        
+        INFO("Starting AT thread if needed");
+        ret = at.open();
+        if(ret) {
+            ERR("Opening AT failed");
             return false;
-        } else {
-            USB_INFO("AT Simple command gone well!!");
+        }
+    
+        INFO("Sending initialisation commands");
+        // Echo 1
+        // Format CRLF
+        // Unsollicited Codes disabled
+        ret = at.init("ATZ E1 V1 ^CURC=0");
+        if(ret) {
+            ERR("Initialisation AT failed");
+            return false;
         }
-    } else  {
-        USB_WARN("Using an Unknown Dongle");
+        
+        if(dongle.getDongleType() == WAN_DONGLE_TYPE_HUAWEI_E372) {
+            INFO("Using a Vodafone E372 Dongle");
+            ERR("Send CMEE cmd ...");
+            ret = at.executeSimple("AT+CMEE=1",NULL,5000);
+            if(ret != OK) {
+                ERR("CMEE cmd failed");
+                return false;
+            }
+        } else  {
+            WARN("Using an Unknown Dongle.. do specific init");
+        }
+        
+        atOpen = true;
     }
 
     ATCommandsInterface::ATResult result;
 
-    // SIM PIN Stuff here
-    bool pin = false;
-    int retries = 3;
-    do {
-        CPINProcessor cpinProcessor;
-        USB_INFO("Check CPIN STATE");
-        ret = at.execute("AT+CPIN?", &cpinProcessor, &result,5000);
-        USB_INFO("Result of command: Err code=%d\n", ret);
-        USB_INFO("ATResult: AT return=%d (code %d)\n", result.result, result.code);
-        if(ret == OK) {
-            if(cpinProcessor.getStatus() == CPINProcessor::STATUS_READY) {
-                USB_INFO("ME PIN READY\n");
-                pin = true;
-                break;
-            } else if (cpinProcessor.getStatus() == CPINProcessor::STATUS_SIMPIN)  {
-                USB_INFO("ME SIM PIN NEEDED\n");
-                ret = at.executeSimple("AT+CPIN=\"0000\"", NULL,5000);
-                if(ret != OK){
-                    USB_ERR("CPIN ERROR ... do not retry");
+    if(!simReady){
+        // SIM PIN Stuff here
+        int retries = 3;
+        do {
+            CPINProcessor cpinProcessor;
+            INFO("Check CPIN STATE");
+            ret = at.execute("AT+CPIN?", &cpinProcessor, &result,5000);
+            //INFO("Result of command: Err code=%d", ret);
+            //INFO("ATResult: AT return=%d (code %d)", result.result, result.code);
+            if(result.code == 14) {
+                 WARN("SIM IS Busy retry");
+                 retries++;
+                 Thread::wait(500);
+            } else if(ret == OK) {
+                if(cpinProcessor.getStatus() == CPINProcessor::STATUS_READY) {
+                    INFO("ME PIN READY");
+                    simReady = true;
+                    break;
+                } else if (cpinProcessor.getStatus() == CPINProcessor::STATUS_SIMPIN)  {
+                    INFO("ME SIM PIN NEEDED");
+                    ret = at.executeSimple("AT+CPIN=\"0000\"",NULL,5000);
+                    if(ret != OK){
+                        ERR("CPIN ERROR ... do not retry");
+                        break;
+                    } else {
+                        INFO("CPIN OK");
+                    }
+                } else if (cpinProcessor.getStatus() == CPINProcessor::STATUS_SIMPUK) {
+                    INFO("CPIN IS PUKED");
                     break;
                 } else {
-                    USB_INFO("CPIN OK");
+                    ERR("UNKNOWN STATUS");
+                    break;
                 }
-            } else if (cpinProcessor.getStatus() == CPINProcessor::STATUS_SIMPUK) {
-                USB_INFO("CPIN IS PUKED");
-                break;
             } else {
-                USB_ERR("UNKNOWN STATUS");
+                INFO("SIM PIN ERROR: SIM Probably not inserted");
                 break;
             }
-        } else {
-            USB_INFO("SIM PIN ERROR: SIM Probably not inserted\n");
-            break;
+            retries--;
+        } while(retries);
+        
+        if(!simReady) {
+            ERR("Couldn't pin unlock ...");
+            return false;
         }
-        retries--;
-    } while(retries);
+    } else {
+        INFO("SIM PIN have been unlocked somewhere!");
+    }
     
-    if(!pin) {
-        USB_ERR("Couldn't pin unlock ...");
-        return false;
-    }
-
     //Wait for network registration
     CREGProcessor cregProcessor;
     do {
-        USB_INFO("Waiting for network registration");
+        INFO("Waiting for network registration");
         ret = at.execute("AT+CREG?", &cregProcessor, &result);
-        USB_INFO("Result of command: Err code=%d\n", ret);
-        USB_INFO("ATResult: AT return=%d (code %d)\n", result.result, result.code);
+        //INFO("Result of command: Err code=%d", ret);
+        //INFO("ATResult: AT return=%d (code %d)", result.result, result.code);
         if(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING) {
-            Thread::wait(3000);
+            Thread::wait(500);
         }
     } while(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING);
     if(cregProcessor.getStatus() == CREGProcessor::STATUS_FAILED) {
-        USB_ERR("Registration denied");
+        ERR("Registration denied");
         return false;
     }
-    
-    atOpen = true;
 
     return true;
 }
 
-bool PyrnUSBModem::isConnected(void) {
+bool PyrnUSBModem::attached(void) {
     return dongle.connected();
 }
 
+bool PyrnUSBModem::pppConnected(void) {
+    return ppp.isConnected();
+}
+
+/*
 WANDongleSerialPort *PyrnUSBModem::getAtInterface(int i) {
     return dongle.getWANSerial(i);
+}*/
+
+int PyrnUSBModem::connect(const char* apn, const char* user, const char* password) {
+    int ret;
+
+    if(!init()) {
+        ERR("Modem could not register");
+        return -1;
+    }
+       
+    ATCommandsInterface::ATResult result;
+
+    if(apn != NULL) {
+        char cmd[48];
+        int tries = 30;
+        DBG("Setting APN to %s", apn);
+        sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", apn);
+        do {//Try 30 times because for some reasons it can fail *a lot* with the K3772-Z dongle
+            ret = at.executeSimple(cmd, &result);
+            //DBG("Result of command: Err code=%d", ret);
+            if(ret)
+                Thread::wait(500);
+        } while(ret && --tries);
+        // DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
+    }
+        
+    DBG("Connecting PPP");
+    ret = ppp.connect(user, password);
+    DBG("Result of connect: Err code=%d", ret);
+    
+    return ret;
+}
+
+int PyrnUSBModem::disconnect() {
+    DBG("Disconnecting from PPP");
+    int ret = ppp.disconnect();
+    if(ret) {
+        ERR("Disconnect returned %d, still trying to disconnect", ret);
+    }
+
+    Thread::wait(500);
+
+    return OK;
+}
+
+char* PyrnUSBModem::getIPAddress() {
+    // return NULL;//ppp.getIPAddress();
+    return ppp.getIPAddress();
 }
\ No newline at end of file