Implementation of 3G USB Modem Huawei E372
PyrnUSBModem.cpp
- Committer:
- clemounet
- Date:
- 2015-02-20
- Revision:
- 0:67daedd6f74f
- Child:
- 1:fbf17fb09581
File content as of revision 0:67daedd6f74f:
#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); }