![](/media/cache/profiles/aa7fd480bd75d86948e7f7aac11d2704.jpg.50x50_q85.jpg)
support library for C027 helper functions for Buffer Pipes, Buffered Serial Port (rtos capable) and GPS parsing. It includes modem APIs for USSD, SMS and Sockets.
Fork of C027_Support by
Diff: MDM.cpp
- Revision:
- 79:291df065e345
- Parent:
- 78:caf0014375cb
- Child:
- 80:34985b4d821e
--- a/MDM.cpp Tue May 20 11:40:07 2014 +0000 +++ b/MDM.cpp Mon May 26 11:55:16 2014 +0000 @@ -12,6 +12,9 @@ //! check for timeout #define TIMEOUT(t, ms) ((ms != TIMEOUT_BLOCKING) && (ms < t.read_ms())) +#define REG_OK(r) ((r == REG_HOME) || (r == REG_ROAMING)) +#define REG_DONE(r) ((r == REG_HOME) || (r == REG_ROAMING) || (r == REG_DENIED)) + #ifdef MDM_DEBUG void dumpAtCmd(const char* buf, int len) { @@ -162,11 +165,12 @@ if (sscanf(cmd, "CREG: %*d,%d,%d,%d",&a,&b,&c) == 3) { // _net.sid = a; // _net.nid = b; - if (c == 0) _net.reg = REG_NONE; // not registered, home network - else if (c == 1) _net.reg = REG_HOME; // registered, home network - else if (c == 2) _net.reg = REG_NONE; // not registered, but MT is currently searching a new operator to register to - else if (c == 3) _net.reg = REG_DENIED; // registration denied - else if (c == 5) _net.reg = REG_ROAMING; // registered, roaming + if (c == 0) _net.csd = REG_NONE; // not registered, home network + else if (c == 1) _net.csd = REG_HOME; // registered, home network + else if (c == 2) _net.csd = REG_NONE; // not registered, but MT is currently searching a new operator to register to + else if (c == 3) _net.csd = REG_DENIED; // registration denied + 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>]] } else if (sscanf(cmd, "CSS %*c,%2s,%*d",s) == 1) { @@ -174,35 +178,41 @@ } } else { // GSM/UMTS Specific ------------------------------------------- - // +CREG: <n>,<stat>[,<lac>,<ci>[,AcT]] // reply to AT+CREG - // +CREG: <stat>[,<lac>,<ci>[,AcT]] // URC - b = 255; - r = sscanf(cmd, "CREG: %*d,%d,\"%X\",\"%X\",%d",&a,&b,&c,&d); - if (r <= 0) - r = sscanf(cmd, "CREG: %d,\"%X\",\"%X\",%d",&a,&b,&c,&d); - if (r >= 1) { - // network status - if (a == 0) _net.reg = REG_NONE; // 0: not registered, home network - else if (a == 1) _net.reg = REG_HOME; // 1: registered, home network - else if (a == 2) _net.reg = REG_NONE; // 2: not registered, but MT is currently searching a new operator to register to - else if (a == 3) _net.reg = REG_DENIED; // 3: registration denied - else if (a == 4) _net.reg = REG_UNKNOWN; // 4: unknown - else if (a == 5) _net.reg = REG_ROAMING; // 5: registered, roaming - if ((r >= 2) && (b != 0xFFFF)) _net.lac = b; // location area code - if ((r >= 3) && (c != 0xFFFFFFFF)) _net.ci = c; // cell ID - // access technology - if (r >= 4) { - if (d == 0) _net.act = ACT_GSM; // 0: GSM - else if (d == 1) _net.act = ACT_GSM; // 1: GSM COMPACT - else if (d == 2) _net.act = ACT_UTRAN; // 2: UTRAN - else if (d == 3) _net.act = ACT_EDGE; // 3: GSM with EDGE availability - else if (d == 4) _net.act = ACT_UTRAN; // 4: UTRAN with HSDPA availability - else if (d == 5) _net.act = ACT_UTRAN; // 5: UTRAN with HSUPA availability - else if (d == 6) _net.act = ACT_UTRAN; // 6: UTRAN with HSDPA and HSUPA availability + // +UUPSDD: <profile_id> + if (sscanf(cmd, "UUPSDD: %d",&a) == 1) { + if (*PROFILE == a) _ip = NOIP; + } else { + // +CREG|CGREG: <n>,<stat>[,<lac>,<ci>[,AcT[,<rac>]]] // reply to AT+CREG|AT+CGREG + // +CREG|CGREG: <stat>[,<lac>,<ci>[,AcT[,<rac>]]] // URC + b = 0xFFFF; c = 0xFFFFFFFF; d = -1; + r = sscanf(cmd, "%s %*d,%d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d); + if (r <= 1) + r = sscanf(cmd, "%s %d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d); + if (r >= 2) { + Reg *reg = !strcmp(s, "CREG:") ? &_net.csd : + !strcmp(s, "CGREG:") ? &_net.psd : NULL; + if (reg) { + // network status + if (a == 0) *reg = REG_NONE; // 0: not registered, home network + else if (a == 1) *reg = REG_HOME; // 1: registered, home network + else if (a == 2) *reg = REG_NONE; // 2: not registered, but MT is currently searching a new operator to register to + else if (a == 3) *reg = REG_DENIED; // 3: registration denied + else if (a == 4) *reg = REG_UNKNOWN; // 4: unknown + else if (a == 5) *reg = REG_ROAMING; // 5: registered, roaming + if ((r >= 3) && (b != 0xFFFF)) _net.lac = b; // location area code + if ((r >= 4) && (c != 0xFFFFFFFF)) _net.ci = c; // cell ID + // access technology + if (r >= 5) { + if (d == 0) _net.act = ACT_GSM; // 0: GSM + else if (d == 1) _net.act = ACT_GSM; // 1: GSM COMPACT + else if (d == 2) _net.act = ACT_UTRAN; // 2: UTRAN + else if (d == 3) _net.act = ACT_EDGE; // 3: GSM with EDGE availability + else if (d == 4) _net.act = ACT_UTRAN; // 4: UTRAN with HSDPA availability + else if (d == 5) _net.act = ACT_UTRAN; // 5: UTRAN with HSUPA availability + else if (d == 6) _net.act = ACT_UTRAN; // 6: UTRAN with HSDPA and HSUPA availability + } + } } - // +UUPSDD: <profile_id> - } else if (sscanf(cmd, "UUPSDD: %d",&a) == 1) { - if (*PROFILE == a) _ip = NOIP; } } } @@ -277,10 +287,17 @@ INFO("Modem::wakeup\r\n"); DigitalOut pin(pn, 1); while (i--) { - pin = 0; - RELAX_MS(5); // SARA-G/U - pin = 1; - RELAX_MS(100); + // SARA-U2/LISA-U2 50..80us + pin = 0; wait_us(50); + pin = 1; wait_ms(10); + + // SARA-G35 >5ms, LISA-C2 > 150ms + pin = 0; wait_ms(150); + pin = 1; wait_ms(100); + + // purge any messages + while (WAIT != waitFinalResp(NULL,NULL,0)) + /* nothing */; // check interface and disable local echo sendFormated("AT\r\n"); if(RESP_OK == waitFinalResp(NULL,NULL,500)) @@ -407,7 +424,15 @@ return false; _dev.lpm = LPM_ACTIVE; } + // enable the psd registration unsolicited result code + sendFormated("AT+CGREG=2\r\n"); + if (RESP_OK != waitFinalResp()) + return false; } + // enable the network registration unsolicited result code + sendFormated("AT+CREG=%d\r\n", (_dev.dev == DEV_LISA_C200) ? 1 : 2); + if (RESP_OK != waitFinalResp()) + return false; // Setup SMS in text mode sendFormated("AT+CMGF=1\r\n"); if (RESP_OK != waitFinalResp()) @@ -420,10 +445,6 @@ sendFormated("AT+CIMI\r\n"); if (RESP_OK != waitFinalResp(_cbString, _dev.imsi)) return false; - // enable the network registration unsolicited result code - sendFormated("AT+CREG=%d\r\n", (_dev.dev == DEV_LISA_C200) ? 1 : 2); - if (RESP_OK != waitFinalResp()) - return false; if (status) memcpy(status, &_dev, sizeof(DevStatus)); return true; @@ -489,9 +510,9 @@ INFO("Modem::register\r\n"); while (!checkNetStatus(status) && !TIMEOUT(timer, timeout_ms)) RELAX_MS(1000); - if (_net.reg == REG_DENIED) - ERROR("Network Registration Denied\r\n"); - return (_net.reg == REG_ROAMING) || (_net.reg == REG_HOME); + if (_net.csd == REG_DENIED) ERROR("CSD Registration Denied\r\n"); + if (_net.psd == REG_DENIED) ERROR("PSD Registration Denied\r\n"); + return REG_OK(_net.csd) || REG_OK(_net.psd); } bool MDMParser::checkNetStatus(NetStatus* status /*= NULL*/) @@ -503,7 +524,13 @@ sendFormated("AT+CREG?\r\n"); if (RESP_OK != waitFinalResp()) return false; - if ((_net.reg == REG_ROAMING) || (_net.reg == REG_HOME)) + if (_dev.dev != DEV_LISA_C200) { + // check PSD registration + sendFormated("AT+CGREG?\r\n"); + if (RESP_OK != waitFinalResp()) + return false; + } + if (REG_OK(_net.csd) || REG_OK(_net.psd)) { // check modem specific status messages if (_dev.dev == DEV_LISA_C200) { @@ -515,7 +542,7 @@ if (RESP_OK != waitFinalResp(_cbString, _net.num)) return false; // check if we have a Mobile Directory Number - if (!*_net.num || (memcmp(_net.num, "0000", 4) == 0)) + if (!*_net.num || (memcmp(_net.num, "000000", 6) == 0)) return false; // get the the Network access identifier string char nai[64]; @@ -523,10 +550,6 @@ if (RESP_OK != waitFinalResp(_cbString, nai)) return false; } else { - // check GPRS attach status - sendFormated("AT+CGATT?\r\n"); - if (RESP_OK != waitFinalResp(_cbCGATT, &_net.gprs)) - return false; // check operator selection sendFormated("AT+COPS?\r\n"); if (RESP_OK != waitFinalResp(_cbCOPS, &_net)) @@ -544,19 +567,7 @@ if (status) { memcpy(status, &_net, sizeof(NetStatus)); } - return ((_net.reg == REG_HOME) || (_net.reg == REG_ROAMING) || (_net.reg == REG_DENIED)); -} - -int MDMParser::_cbCGATT(int type, const char* buf, int len, Gprs* gprs) -{ - if ((type == TYPE_PLUS) && gprs){ - int i; - if (sscanf(buf, "\r\n+CGATT: %d\r\n", &i) == 1) { - if (i == 0) *gprs = GPRS_DETACHED; - else if (i == 1) *gprs = GPRS_ATTACHED; - } - } - return WAIT; + return REG_DONE(_net.csd) && REG_DONE(_net.psd); } int MDMParser::_cbCOPS(int type, const char* buf, int len, NetStatus* status) @@ -600,7 +611,8 @@ // ---------------------------------------------------------------- // internet connection -MDMParser::IP MDMParser::join(const char* apn /*= NULL*/, const char* username /*= NULL*/, const char* password /*= NULL*/) +MDMParser::IP MDMParser::join(const char* apn /*= NULL*/, const char* username /*= NULL*/, + const char* password /*= NULL*/, Auth auth /*= AUTH_DETECT*/) { INFO("Modem::join\r\n"); _ip = NOIP; @@ -623,40 +635,61 @@ // Check the profile int a = 0; + bool force = true; sendFormated("AT+UPSND=" PROFILE ",8\r\n"); if (RESP_OK != waitFinalResp(_cbUPSND, &a)) return NOIP; - if (a == 1) { + if (a == 1 && force) { // 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;; + a = 0; } - // Set up the APN - if (apn) { - sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn); - if (RESP_OK != waitFinalResp()) - return NOIP; - } - if (username) { - sendFormated("AT+UPSD=" PROFILE ",2,\"%s\"\r\n", username); + if (a == 0) { + // Set up the APN + if (apn) { + sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn); + if (RESP_OK != waitFinalResp()) + return NOIP; + } + 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; - } - if (password) { - sendFormated("AT+UPSD=" PROFILE ",3,\"%s\"\r\n", password); - if (RESP_OK != waitFinalResp()) + // 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; + } + i ++; + } + if (i > AUTH_CHAP) { + ERROR("Your modem APN/password/username may be wrong\r\n"); 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; - // Activate the profile and make connection - sendFormated("AT+UPSDA=" PROFILE ",3\r\n"); - if (RESP_OK != waitFinalResp(NULL,NULL,150*1000)) { - ERROR("Your modem APN/password/username may be wrong\r\n"); - return NOIP; + } } //Get local IP address sendFormated("AT+UPSND=" PROFILE ",0\r\n"); @@ -1128,11 +1161,10 @@ { dprint(param, "Modem::netStatus\r\n"); const char* txtReg[] = { "Unknown", "Denied", "None", "Home", "Roaming" }; - if (status->reg < sizeof(txtReg)/sizeof(*txtReg) && (status->reg != MDMParser::REG_UNKNOWN)) - dprint(param, " Registration: %s\r\n", txtReg[status->reg]); - const char* txtGprs[] = { "Unknown", "Detached", "Attached" }; - if (status->gprs < sizeof(txtGprs)/sizeof(*txtGprs) && (status->gprs != MDMParser::GPRS_UNKNOWN)) - dprint(param, " Gprs: %s\r\n", txtGprs[status->gprs]); + if (status->csd < sizeof(txtReg)/sizeof(*txtReg) && (status->csd != MDMParser::REG_UNKNOWN)) + dprint(param, " CSD Registration: %s\r\n", txtReg[status->csd]); + if (status->psd < sizeof(txtReg)/sizeof(*txtReg) && (status->psd != MDMParser::REG_UNKNOWN)) + dprint(param, " PSD Registration: %s\r\n", txtReg[status->psd]); const char* txtAct[] = { "Unknown", "GSM", "Edge", "3G", "CDMA" }; if (status->act < sizeof(txtAct)/sizeof(*txtAct) && (status->act != MDMParser::ACT_UNKNOWN)) dprint(param, " Access Technology: %s\r\n", txtAct[status->act]);