Implementation of 3G USB Modem Huawei E372
Diff: PyrnUSBModem.cpp
- Revision:
- 0:67daedd6f74f
- Child:
- 1:fbf17fb09581
diff -r 000000000000 -r 67daedd6f74f PyrnUSBModem.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PyrnUSBModem.cpp Fri Feb 20 16:48:12 2015 +0000 @@ -0,0 +1,248 @@ + +#include "dbg.h" +#include "PyrnUSBModem.h" +#include "HuaweiUSBModemInitializer.h" + +// Command Processors + +class CPINProcessor : public IATCommandsProcessor { +public: + enum PIN_STATUS { STATUS_NONE ,STATUS_SIMPIN, STATUS_SIMPUK, STATUS_READY }; + CPINProcessor() : status(STATUS_NONE) { } + PIN_STATUS getStatus() { return status; } +private: + virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line) { + USB_DBG("GOT %s",line); + if(!strncmp(line, "+CPIN: READY",12)) { + status = STATUS_READY; + USB_DBG("STATUS_READY"); + } else if(!strncmp(line, "+CPIN: SIM PIN",14)) { + status = STATUS_SIMPIN; + USB_DBG("STATUS_SIMPIN"); + }else if(!strncmp(line, "+CPIN: SIM PUK",14)) { + status = STATUS_SIMPUK; + USB_DBG("STATUS_SIMPUK"); + } else + USB_DBG("STATUS_NONE"); + return OK; + } + virtual int onNewEntryPrompt(ATCommandsInterface* pInst) { return OK; } + volatile PIN_STATUS status; +}; + + +class CREGProcessor : public IATCommandsProcessor { +public: + enum PIN_STATUS { STATUS_REGISTERING, STATUS_OK, STATUS_FAILED }; + CREGProcessor() : status(STATUS_REGISTERING) { } + PIN_STATUS getStatus() { return status; } +private: + virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line) { + int r; + if( sscanf(line, "+CREG: %*d,%d", &r) == 1 ) { + switch(r) { + case 1: + case 5: + status = STATUS_OK; + break; + case 0: + case 2: + status = STATUS_REGISTERING; + break; + case 3: + default: + status = STATUS_FAILED; + break; + } + } + return OK; + } + virtual int onNewEntryPrompt(ATCommandsInterface* pInst) { return OK; } + volatile PIN_STATUS status; +}; + +class COPSProcessor : public IATCommandsProcessor { +public: + COPSProcessor() : valid(false) { + network[0] = '\0'; + apn[0] = '\0'; + bearer[0] = '\0'; + } + char* getNetwork() { return network; } + char* getAPN() { return apn; } + char* getBearer() { return bearer; } + bool isValid() { return valid; } +private: + virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line) { + int networkId; + int bearerId; + int s = sscanf(line, "+COPS: %*d,%*d,\"%d\",%d", &networkId, &bearerId); + if( s == 2 ) { + switch(networkId) { + case 23415: + strcpy(network, "Vodafone UK"); + strcpy(apn, "pp.vodafone.co.uk"); + valid = true; + break; + case 20810: + strcpy(network, "SFR FR"); + strcpy(apn, "websfr"); + valid = true; + break; + default: + break; + } + } else + return OK; + + switch(bearerId) { + case 0: strcpy(bearer, "GSM"); break; + case 1: strcpy(bearer, "GSM Compact"); break; + case 2: strcpy(bearer, "UTRAN"); break; + case 3: strcpy(bearer, "GSM w/EGPRS"); break; + case 4: strcpy(bearer, "UTRAN w/HSDPA"); break; + case 5: strcpy(bearer, "UTRAN w/HSUPA"); break; + case 6: strcpy(bearer, "UTRAN w/HSDPA and HSUPA"); break; + case 7: strcpy(bearer, "E-UTRAN"); break; + default: break; + } + return OK; + } + + virtual int onNewEntryPrompt(ATCommandsInterface* pInst) { return OK; } + + char network[24]; + char bearer[24]; + char apn[24]; + volatile bool valid; +}; + +PyrnUSBModem::PyrnUSBModem(USBHost *host): + dongle(), + atStream(dongle.getSerial(3)), + at(&atStream), + atOpen(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); +} + +bool PyrnUSBModem::init() { + + if(!dongle.connected()){ + while(!dongle.connected()) { + USB_INFO("Dongle try connect"); + dongle.tryConnect(); + Thread::wait(10); + } + if(!dongle.connected()) + return false; + } else + USB_INFO("Dongle is already connected ... continue"); + + if(atOpen) { + USB_INFO("Stream is already opened"); + return true; + } + + 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"); + return false; + } else { + USB_INFO("AT Simple command gone well!!"); + } + } else { + USB_WARN("Using an Unknown Dongle"); + } + + 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"); + break; + } else { + USB_INFO("CPIN OK"); + } + } else if (cpinProcessor.getStatus() == CPINProcessor::STATUS_SIMPUK) { + USB_INFO("CPIN IS PUKED"); + break; + } else { + USB_ERR("UNKNOWN STATUS"); + break; + } + } else { + USB_INFO("SIM PIN ERROR: SIM Probably not inserted\n"); + break; + } + retries--; + } while(retries); + + if(!pin) { + USB_ERR("Couldn't pin unlock ..."); + return false; + } + + //Wait for network registration + CREGProcessor cregProcessor; + do { + USB_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); + if(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING) { + Thread::wait(3000); + } + } while(cregProcessor.getStatus() == CREGProcessor::STATUS_REGISTERING); + if(cregProcessor.getStatus() == CREGProcessor::STATUS_FAILED) { + USB_ERR("Registration denied"); + return false; + } + + atOpen = true; + + return true; +} + +bool PyrnUSBModem::isConnected(void) { + return dongle.connected(); +} + +WANDongleSerialPort *PyrnUSBModem::getAtInterface(int i) { + return dongle.getWANSerial(i); +} \ No newline at end of file