Implementation of 3G USB Modem Huawei E372
Diff: PyrnUSBModem.cpp
- Revision:
- 2:61ac95f0af72
- Parent:
- 1:fbf17fb09581
diff -r fbf17fb09581 -r 61ac95f0af72 PyrnUSBModem.cpp --- 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