final 1
Fork of C027_Support by
Diff: MDM.cpp
- Revision:
- 95:8282dbbe1492
- Parent:
- 90:3915192f6d7e
- Child:
- 98:c786461edd40
diff -r d697fe11f3e5 -r 8282dbbe1492 MDM.cpp --- a/MDM.cpp Thu Jun 12 12:41:26 2014 +0000 +++ b/MDM.cpp Tue Jun 17 07:03:48 2014 +0000 @@ -1,6 +1,5 @@ #include "mbed.h" #include "MDM.h" -#include "Relax.h" #ifdef TARGET_UBLOX_C027 #include "C027_api.h" #endif @@ -16,8 +15,27 @@ #define REG_OK(r) ((r == REG_HOME) || (r == REG_ROAMING)) //! registration done check helper (no need to poll further) #define REG_DONE(r) ((r == REG_HOME) || (r == REG_ROAMING) || (r == REG_DENIED)) +//! helper to make sure that lock unlock pair is always balaced +#define LOCK() { lock() +//! helper to make sure that lock unlock pair is always balaced +#define UNLOCK() } unlock() #ifdef MDM_DEBUG + #if 1 // colored terminal output using ANSI escape sequences + #define COL(c) "\033[" c + #else + #define COL(c) + #endif + #define DEF COL("39m") + #define BLA COL("30m") + #define RED COL("31m") + #define GRE COL("32m") + #define YEL COL("33m") + #define BLU COL("34m") + #define MAG COL("35m") + #define CYA COL("36m") + #define WHY COL("37m") + void dumpAtCmd(const char* buf, int len) { ::printf(" %3d \"", len); @@ -42,27 +60,15 @@ ::printf("\"\r\n"); } - #define ERROR(fmt) (_debugLevel < 0) ? : ::printf(RED(fmt)) - #define INFO(fmt) (_debugLevel < 1) ? : ::printf(GRE(fmt)) - #define TRACE(...) (_debugLevel < 2) ? : ::printf(__VA_ARGS__) - - #if 1 // colored terminal output using ANSI escape sequences - #define COL(c,t) "\033[" c t "\033[" "39m" - #else - #define COL(c,t) t - #endif - #define BLA(t) COL("30m",t) - #define RED(t) COL("31m",t) - #define GRE(t) COL("32m",t) - #define YEL(t) COL("33m",t) - #define BLU(t) COL("34m",t) - #define MAG(t) COL("35m",t) - #define CYA(t) COL("36m",t) - #define WHY(t) COL("37m",t) + #define ERROR(...) (_debugLevel < 0) ? : ::printf(RED), ::printf(__VA_ARGS__), ::printf(DEF) + #define TEST(...) ::printf(CYA), ::printf(__VA_ARGS__), ::printf(DEF) + #define INFO(...) (_debugLevel < 1) ? : ::printf(GRE), ::printf(__VA_ARGS__), ::printf(DEF) + #define TRACE(...) (_debugLevel < 2) ? : ::printf(__VA_ARGS__) #else #define ERROR(...) (void)0 // no tracing + #define TEST(...) (void)0 // no tracing #define INFO(...) (void)0 // no tracing #define TRACE(...) (void)0 // no tracing @@ -120,13 +126,13 @@ { int len = LENGTH(ret); int type = TYPE(ret); - const char* s = (type == TYPE_UNKNOWN)? YEL("UNK") : - (type == TYPE_TEXT) ? MAG("TXT") : - (type == TYPE_OK ) ? GRE("OK ") : - (type == TYPE_ERROR) ? RED("ERR") : - (type == TYPE_PLUS) ? CYA(" + ") : - (type == TYPE_PROMPT) ? BLU(" > ") : - "..." ; + const char* s = (type == TYPE_UNKNOWN)? YEL "UNK" DEF : + (type == TYPE_TEXT) ? MAG "TXT" DEF : + (type == TYPE_OK ) ? GRE "OK " DEF : + (type == TYPE_ERROR) ? RED "ERR" DEF : + (type == TYPE_PLUS) ? CYA " + " DEF : + (type == TYPE_PROMPT) ? BLU " > " DEF : + "..." ; ::printf("%10.3f AT read %s", _debugTime.read_ms()*0.001, s); dumpAtCmd(buf, len); } @@ -224,12 +230,15 @@ if (WAIT != ret) return ret; } - if (type == TYPE_OK) return RESP_OK; - if (type == TYPE_ERROR) return RESP_ERROR; - if (type == TYPE_PROMPT) return RESP_PROMPT; + if (type == TYPE_OK) + return RESP_OK; + if (type == TYPE_ERROR) + return RESP_ERROR; + if (type == TYPE_PROMPT) + return RESP_PROMPT; } // relax a bit - RELAX_MS(10); + wait_ms(10); } while (!TIMEOUT(timer, timeout_ms)); return WAIT; @@ -285,30 +294,32 @@ bool MDMParser::init(const char* simpin, DevStatus* status, PinName pn) { int i = 10; + LOCK(); memset(&_dev, 0, sizeof(_dev)); if (pn != NC) { INFO("Modem::wakeup\r\n"); DigitalOut pin(pn, 1); while (i--) { // SARA-U2/LISA-U2 50..80us - pin = 0; wait_us(50); - pin = 1; wait_ms(10); + 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); + 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)) - break; + int r = waitFinalResp(NULL,NULL,500); + if(RESP_OK == r) break; } if (i < 0) { - ERROR("No Reply from Modem"); - return false; + ERROR("No Reply from Modem\r\n"); + goto failure; } } _init = true; @@ -317,47 +328,47 @@ // echo off sendFormated("AT E0\r\n"); if(RESP_OK != waitFinalResp()) - return false; + goto failure; // enable verbose error messages sendFormated("AT+CMEE=2\r\n"); if(RESP_OK != waitFinalResp()) - return false; + goto failure; // set baud rate sendFormated("AT+IPR=115200\r\n"); if (RESP_OK != waitFinalResp()) - return false; - RELAX_MS(40); + goto failure; + wait_ms(40); // identify the module sendFormated("ATI\r\n"); if (RESP_OK != waitFinalResp(_cbATI, &_dev.dev)) - return false; + goto failure; if (_dev.dev == DEV_UNKNOWN) - return false; + goto failure; // device specific init if (_dev.dev == DEV_LISA_C200) { // get the manufacturer sendFormated("AT+GMI\r\n"); if (RESP_OK != waitFinalResp(_cbString, _dev.manu)) - return false; + goto failure; // get the model identification sendFormated("AT+GMM\r\n"); if (RESP_OK != waitFinalResp(_cbString, _dev.model)) - return false; + goto failure; // get the sw version sendFormated("AT+GMR\r\n"); if (RESP_OK != waitFinalResp(_cbString, _dev.ver)) - return false; - // Return the pseudo ESN or MEID + goto failure; + // get the pseudo ESN or MEID sendFormated("AT+GSN\r\n"); if (RESP_OK != waitFinalResp(_cbString, _dev.meid)) - return false; + goto failure; #if 0 // enable power saving if (_dev.lpm != LPM_DISABLED) { // enable power saving (requires flow control, cts at least) sendFormated("AT+UPSV=1,1280\r\n"); if (RESP_OK != waitFinalResp()) - return false; + goto failure; _dev.lpm = LPM_ACTIVE; } #endif @@ -366,12 +377,12 @@ // enable the network identification feature sendFormated("AT+UGPIOC=20,2\r\n"); if (RESP_OK != waitFinalResp()) - return false; + goto failure; } else { // enable the network identification feature sendFormated("AT+UGPIOC=16,2\r\n"); if (RESP_OK != waitFinalResp()) - return false; + goto failure; } // check the sim card for (int i = 0; (i < 5) && (_dev.sim != SIM_READY); i++) { @@ -379,90 +390,98 @@ int ret = waitFinalResp(_cbCPIN, &_dev.sim); // having an error here is ok (sim may still be initializing) if ((RESP_OK != ret) && (RESP_ERROR != ret)) - return false; + goto failure; // Enter PIN if needed if (_dev.sim == SIM_PIN) { if (!simpin) { ERROR("SIM PIN not available\r\n"); - return false; + goto failure; } sendFormated("AT+CPIN=%s\r\n", simpin); if (RESP_OK != waitFinalResp(_cbCPIN, &_dev.sim)) - return false; + goto failure; } else if (_dev.sim != SIM_READY) { - RELAX_MS(1000); + wait_ms(1000); } } if (_dev.sim != SIM_READY) { if (_dev.sim == SIM_MISSING) ERROR("SIM not inserted\r\n"); - return false; + goto failure; } // get the manufacturer sendFormated("AT+CGMI\r\n"); if (RESP_OK != waitFinalResp(_cbString, _dev.manu)) - return false; + goto failure; // get the model identification sendFormated("AT+CGMM\r\n"); if (RESP_OK != waitFinalResp(_cbString, _dev.model)) - return false; + goto failure; // get the sendFormated("AT+CGMR\r\n"); if (RESP_OK != waitFinalResp(_cbString, _dev.ver)) - return false; + goto failure; // Returns the ICCID (Integrated Circuit Card ID) of the SIM-card. // ICCID is a serial number identifying the SIM. sendFormated("AT+CCID\r\n"); if (RESP_OK != waitFinalResp(_cbCCID, _dev.ccid)) - return false; + goto failure; // Returns the product serial number, IMEI (International Mobile Equipment Identity) sendFormated("AT+CGSN\r\n"); if (RESP_OK != waitFinalResp(_cbString, _dev.imei)) - return false; + goto failure; // enable power saving if (_dev.lpm != LPM_DISABLED) { // enable power saving (requires flow control, cts at least) sendFormated("AT+UPSV=1\r\n"); if (RESP_OK != waitFinalResp()) - return false; + goto failure; _dev.lpm = LPM_ACTIVE; } // enable the psd registration unsolicited result code sendFormated("AT+CGREG=2\r\n"); if (RESP_OK != waitFinalResp()) - return false; + goto failure; } // 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; + goto failure; // Setup SMS in text mode sendFormated("AT+CMGF=1\r\n"); if (RESP_OK != waitFinalResp()) - return false; + goto failure; // setup new message indication sendFormated("AT+CNMI=2,1\r\n"); if (RESP_OK != waitFinalResp()) - return false; + goto failure; // Request IMSI (International Mobile Subscriber Identification) sendFormated("AT+CIMI\r\n"); if (RESP_OK != waitFinalResp(_cbString, _dev.imsi)) - return false; + goto failure; if (status) memcpy(status, &_dev, sizeof(DevStatus)); + UNLOCK(); return true; +failure: + unlock(); + return false; } bool MDMParser::powerOff(void) { + bool ok = false; if (_init) { + LOCK(); INFO("Modem::powerOff\r\n"); sendFormated("AT+CPWROFF\r\n"); - if (RESP_OK != waitFinalResp(NULL,NULL,120*1000)) - return false; - _init = false; + if (RESP_OK == waitFinalResp(NULL,NULL,120*1000)) { + _init = false; + ok = true; + } + UNLOCK(); } - return true; + return ok; } int MDMParser::_cbATI(int type, const char* buf, int len, Dev* dev) @@ -512,7 +531,7 @@ timer.start(); INFO("Modem::register\r\n"); while (!checkNetStatus(status) && !TIMEOUT(timer, timeout_ms)) - RELAX_MS(1000); + wait_ms(1000); 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); @@ -520,6 +539,8 @@ bool MDMParser::checkNetStatus(NetStatus* status /*= NULL*/) { + bool ok = false; + LOCK(); memset(&_net, 0, sizeof(_net)); _net.lac = 0xFFFF; _net.ci = 0xFFFFFFFF; @@ -537,12 +558,12 @@ if (_dev.dev == DEV_LISA_C200) { sendFormated("AT+CSS?\r\n"); if (RESP_OK != waitFinalResp()) - return false; + goto failure; while (1) { // get the Telephone number sendFormated("AT$MDN?\r\n"); if (RESP_OK != waitFinalResp(_cbString, _net.num)) - return false; + goto failure; // check if we have a Mobile Directory Number if (*_net.num && (memcmp(_net.num, "000000", 6) != 0)) break; @@ -559,7 +580,7 @@ i = 1; if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) { ERROR("Device over-the-air activation failed\r\n"); - return false; + goto failure; } INFO("Device over-the-air activation successful\r\n"); @@ -568,39 +589,44 @@ i = 1; if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) { ERROR("PRL over-the-air update failed\r\n"); - return false; + goto failure; } INFO("PRL over-the-air update successful\r\n"); } else { // Sprint or Aeris INFO("Wait for OMA-DM over-the-air activation (this can take a few minutes)\r\n"); - RELAX_MS(120*1000); + wait_ms(120*1000); } } // get the the Network access identifier string char nai[64]; sendFormated("AT$QCMIPNAI?\r\n"); if (RESP_OK != waitFinalResp(_cbString, nai)) - return false; + goto failure; } else { sendFormated("AT+COPS?\r\n"); if (RESP_OK != waitFinalResp(_cbCOPS, &_net)) - return false; - // Returns the MSISDNs related to this subscriber + goto failure; + // get the MSISDNs related to this subscriber sendFormated("AT+CNUM\r\n"); if (RESP_OK != waitFinalResp(_cbCNUM, _net.num)) - return false; + goto failure; } - // Returns the signal strength indication + // get the signal strength indication sendFormated("AT+CSQ\r\n"); if (RESP_OK != waitFinalResp(_cbCSQ, &_net)) - return false; + goto failure; } if (status) { memcpy(status, &_net, sizeof(NetStatus)); } - return REG_DONE(_net.csd) && REG_DONE(_net.psd); + ok = REG_DONE(_net.csd) && REG_DONE(_net.psd); + UNLOCK(); + return ok; +failure: + unlock(); + return false; } int MDMParser::_cbCOPS(int type, const char* buf, int len, NetStatus* status) @@ -658,6 +684,7 @@ MDMParser::IP MDMParser::join(const char* apn /*= NULL*/, const char* username /*= NULL*/, const char* password /*= NULL*/, Auth auth /*= AUTH_DETECT*/) { + LOCK(); INFO("Modem::join\r\n"); _ip = NOIP; if (_dev.dev == DEV_LISA_C200) { @@ -670,24 +697,24 @@ //Get local IP address sendFormated("AT+CMIP?\r\n"); if (RESP_OK != waitFinalResp(_cbCMIP, &_ip)) - return NOIP; + goto failure; } else { // check gprs attach status sendFormated("AT+CGATT=1\r\n"); if (RESP_OK != waitFinalResp(NULL,NULL,3*60*1000)) - return NOIP; + goto failure; // Check the profile int a = 0; bool force = true; sendFormated("AT+UPSND=" PROFILE ",8\r\n"); if (RESP_OK != waitFinalResp(_cbUPSND, &a)) - return NOIP; + goto failure; 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; + goto failure; a = 0; } if (a == 0) { @@ -700,7 +727,7 @@ // Set up the dynamic IP address assignment. sendFormated("AT+UPSD=" PROFILE ",7,\"0.0.0.0\"\r\n"); if (RESP_OK != waitFinalResp()) - return NOIP; + goto failure; do { if (config) { @@ -713,17 +740,17 @@ if (apn && *apn) { sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn); if (RESP_OK != waitFinalResp()) - return NOIP; + goto failure; } if (username && *username) { sendFormated("AT+UPSD=" PROFILE ",2,\"%s\"\r\n", username); if (RESP_OK != waitFinalResp()) - return NOIP; + goto failure; } if (password && *password) { sendFormated("AT+UPSD=" PROFILE ",3,\"%s\"\r\n", password); if (RESP_OK != waitFinalResp()) - return NOIP; + goto failure; } // try different Authentication Protocols // 0 = none @@ -734,7 +761,7 @@ // Set up the Authentication Protocol sendFormated("AT+UPSD=" PROFILE ",6,%d\r\n", i); if (RESP_OK != waitFinalResp()) - return NOIP; + goto failure; // Activate the profile and make connection sendFormated("AT+UPSDA=" PROFILE ",3\r\n"); if (RESP_OK == waitFinalResp(NULL,NULL,150*1000)) @@ -744,15 +771,19 @@ } while (config && *config); // maybe use next setting ? if (!ok) { ERROR("Your modem APN/password/username may be wrong\r\n"); - return NOIP; + goto failure; } } //Get local IP address sendFormated("AT+UPSND=" PROFILE ",0\r\n"); if (RESP_OK != waitFinalResp(_cbUPSND, &_ip)) - return NOIP; + goto failure; } + UNLOCK(); return _ip; +failure: + unlock(); + return NOIP; } int MDMParser::_cbUDOPN(int type, const char* buf, int len, char* mccmnc) @@ -798,7 +829,7 @@ { if ((type == TYPE_PLUS) && ip) { int a,b,c,d; - if (sscanf(buf, "\r\n+UDNSRN: \""IPSTR"\"", &a,&b,&c,&d) == 4) + if (sscanf(buf, "\r\n+UDNSRN: \"" IPSTR "\"", &a,&b,&c,&d) == 4) *ip = IPADR(a,b,c,d); } return WAIT; @@ -806,18 +837,24 @@ bool MDMParser::disconnect(void) { - if (_ip == NOIP) - return true; + bool ok = false; + LOCK(); INFO("Modem::disconnect\r\n"); - if (_dev.dev == DEV_LISA_C200) { - // There something to do here - } else { - sendFormated("AT+UPSDA=" PROFILE ",4\r\n"); - if (RESP_OK != waitFinalResp()) - return false; + if (_ip != NOIP) { + if (_dev.dev == DEV_LISA_C200) { + // There something to do here + _ip = NOIP; + ok = true; + } else { + sendFormated("AT+UPSDA=" PROFILE ",4\r\n"); + if (RESP_OK != waitFinalResp()) { + _ip = NOIP; + ok = true; + } + } } - _ip = NOIP; - return true; + UNLOCK(); + return ok; } MDMParser::IP MDMParser::gethostbyname(const char* host) @@ -827,9 +864,11 @@ if (sscanf(host, IPSTR, &a,&b,&c,&d) == 4) ip = IPADR(a,b,c,d); else { + LOCK(); sendFormated("AT+UDNSRN=0,\"%s\"\r\n", host); if (RESP_OK != waitFinalResp(_cbUDNSRN, &ip)) - return false; + ip = NOIP; + UNLOCK(); } return ip; } @@ -849,81 +888,101 @@ int MDMParser::socketSocket(IpProtocol ipproto, int port) { + int socket = SOCKET_ERROR; + LOCK(); TRACE("socketSocket(%d)\r\n", ipproto); - if(ipproto == IPPROTO_TCP) { - sendFormated("AT+USOCR=6\r\n"); - } else if ((ipproto == IPPROTO_UDP) && (port == -1)){ + if ((ipproto == IPPROTO_UDP) && (port == -1)){ sendFormated("AT+USOCR=17\r\n"); } else if (ipproto == IPPROTO_UDP){ sendFormated("AT+USOCR=17,%d\r\n", port); - } else { // other types not supported - return SOCKET_ERROR; - } - int socket = -1; + } else /*(ipproto == IPPROTO_TCP)*/ { + sendFormated("AT+USOCR=6\r\n"); + } if (RESP_OK != waitFinalResp(_cbUSOCR, &socket)) - return SOCKET_ERROR; - if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_FREE)) - return SOCKET_ERROR; - // successfull - _sockets[socket].state = SOCK_CREATED; - _sockets[socket].pending = 0; - _sockets[socket].timeout_ms = TIMEOUT_BLOCKING; + socket = SOCKET_ERROR; + else if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_FREE)) + socket = SOCKET_ERROR; + if (socket != SOCKET_ERROR) { + // successfull + _sockets[socket].state = SOCK_CREATED; + _sockets[socket].pending = 0; + _sockets[socket].timeout_ms = TIMEOUT_BLOCKING; + } + UNLOCK(); return socket; } bool MDMParser::socketConnect(int socket, const char * host, int port) { - TRACE("socketConnect(%d,%s,%d)\r\n", socket, host,port); IP ip = gethostbyname(host); if (ip == NOIP) return false; // connect to socket - if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CREATED)) - return false; - sendFormated("AT+USOCO=%d,\"" IPSTR "\",%d\r\n", socket, IPNUM(ip), port); - if (RESP_OK != waitFinalResp()) - return false; - _sockets[socket].state = SOCK_CONNECTED; - return true; + bool ok = false; + LOCK(); + if (ISSOCKET(socket) && (_sockets[socket].state == SOCK_CREATED)) { + TRACE("socketConnect(%d,%s,%d)\r\n", socket,host,port); + sendFormated("AT+USOCO=%d,\"" IPSTR "\",%d\r\n", socket, IPNUM(ip), port); + if (RESP_OK == waitFinalResp()) + ok = _sockets[socket].state = SOCK_CONNECTED; + } + UNLOCK(); + return ok; } bool MDMParser::socketIsConnected(int socket) { + bool ok = false; + LOCK(); TRACE("socketIsConnected(%d)\r\n", socket); - if (!ISSOCKET(socket)) - return false; - return _sockets[socket].state == SOCK_CONNECTED; + ok = ISSOCKET(socket) && + _sockets[socket].state == SOCK_CONNECTED; + UNLOCK(); + return ok; } bool MDMParser::socketSetBlocking(int socket, int timeout_ms) { + bool ok = false; + LOCK(); TRACE("socketSetBlocking(%d,%d)\r\n", socket, timeout_ms); - if (!ISSOCKET(socket)) - return false; - _sockets[socket].timeout_ms = timeout_ms; - return true; + if (ISSOCKET(socket)) { + _sockets[socket].timeout_ms = timeout_ms; + ok = true; + } + UNLOCK(); + return ok; } bool MDMParser::socketClose(int socket) { - TRACE("socketClose(%d)\r\n", socket); - if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CONNECTED)) - return false; - sendFormated("AT+USOCL=%d\r\n", socket); - if (RESP_OK != waitFinalResp()) - return false; - _sockets[socket].state = SOCK_CREATED; - return true; + bool ok = false; + LOCK(); + if (ISSOCKET(socket) && (_sockets[socket].state == SOCK_CONNECTED)) { + TRACE("socketClose(%d)\r\n", socket); + sendFormated("AT+USOCL=%d\r\n", socket); + if (RESP_OK == waitFinalResp()) { + _sockets[socket].state = SOCK_CREATED; + ok = true; + } + } + UNLOCK(); + return ok; } bool MDMParser::socketFree(int socket) { - TRACE("socketFree(%d)\r\n", socket); + // make sure it is closed socketClose(socket); - if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CREATED)) - return false; - _sockets[socket].state = SOCK_FREE; - return true; + bool ok = true; + LOCK(); + if (ISSOCKET(socket) && (_sockets[socket].state == SOCK_CREATED)) { + TRACE("socketFree(%d)\r\n", socket); + _sockets[socket].state = SOCK_FREE; + ok = true; + } + UNLOCK(); + return ok; } #define USO_MAX_WRITE 1024 //!< maximum number of bytes to write to socket @@ -936,12 +995,17 @@ int blk = USO_MAX_WRITE; if (cnt < blk) blk = cnt; + bool ok = false; + LOCK(); sendFormated("AT+USOWR=%d,%d\r\n",socket,blk); - if (RESP_PROMPT != waitFinalResp()) - return SOCKET_ERROR; - RELAX_MS(50); - send(buf, blk); - if (RESP_OK != waitFinalResp()) + if (RESP_PROMPT == waitFinalResp()) { + wait_ms(50); + send(buf, blk); + if (RESP_OK == waitFinalResp()) + ok = true; + } + UNLOCK(); + if (!ok) return SOCKET_ERROR; buf += blk; cnt -= blk; @@ -957,12 +1021,17 @@ int blk = USO_MAX_WRITE; if (cnt < blk) blk = cnt; - sendFormated("AT+USOST=%d,\"" IPSTR "\",%d,%d\r\n",socket,IPNUM(ip),port,blk); - if (RESP_PROMPT != waitFinalResp()) - return SOCKET_ERROR; - RELAX_MS(50); - send(buf, blk); - if (RESP_OK != waitFinalResp()) + bool ok = false; + LOCK(); + sendFormated("AT+USOST=%d,\"" IPSTR "\",%d,%d\r\n",socket,IPNUM(ip),port,blk); + if (RESP_PROMPT == waitFinalResp()) { + wait_ms(50); + send(buf, blk); + if (RESP_OK == waitFinalResp()) + ok = true; + } + UNLOCK(); + if (!ok) return SOCKET_ERROR; buf += blk; cnt -= blk; @@ -972,14 +1041,17 @@ int MDMParser::socketReadable(int socket) { - TRACE("socketReadable(%d)\r\n", socket); - if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CONNECTED)) - return SOCKET_ERROR; - // allow to receive unsolicited commands - waitFinalResp(NULL, NULL, 0); - if (_sockets[socket].state != SOCK_CONNECTED) - return SOCKET_ERROR; - return _sockets[socket].pending; + int pending = SOCKET_ERROR; + LOCK(); + if (ISSOCKET(socket) && (_sockets[socket].state == SOCK_CONNECTED)) { + TRACE("socketReadable(%d)\r\n", socket); + // allow to receive unsolicited commands + waitFinalResp(NULL, NULL, 0); + if (_sockets[socket].state == SOCK_CONNECTED) + pending = _sockets[socket].pending; + } + UNLOCK(); + return pending; } int MDMParser::_cbUSORD(int type, const char* buf, int len, char* out) @@ -998,32 +1070,43 @@ { int cnt = 0; TRACE("socketRecv(%d,,%d)\r\n", socket, len); - if (!ISSOCKET(socket)) - return SOCKET_ERROR; +#ifdef MDM_DEBUG memset(buf, '\0', len); +#endif Timer timer; timer.start(); while (len) { int blk = MAX_SIZE; // still need space for headers and unsolicited commands - if (_sockets[socket].pending < blk) - blk = _sockets[socket].pending; if (len < blk) blk = len; - if (blk) { - sendFormated("AT+USORD=%d,%d\r\n",socket, blk); - if (RESP_OK != waitFinalResp(_cbUSORD, buf)) { - return SOCKET_ERROR; + bool ok = false; + LOCK(); + if (ISSOCKET(socket)) { + if (_sockets[socket].state == SOCK_CONNECTED) { + if (_sockets[socket].pending < blk) + blk = _sockets[socket].pending; + if (blk > 0) { + sendFormated("AT+USORD=%d,%d\r\n",socket, blk); + if (RESP_OK == waitFinalResp(_cbUSORD, buf)) { + _sockets[socket].pending -= blk; + len -= blk; + cnt += blk; + buf += blk; + ok = true; + } + } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) { + ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs + } else { + len = 0; + ok = true; + } + } else if (_sockets[socket].state == SOCK_CREATED) { + len = 0; + ok = true; } - len -= blk; - cnt += blk; - buf += blk; - _sockets[socket].pending -= blk; - } else if ((_sockets[socket].state == SOCK_CONNECTED) && - !TIMEOUT(timer, _sockets[socket].timeout_ms)) { - // allow to receive unsolicited commands - waitFinalResp(NULL, NULL, 10); - } else { - len = 0; // no more data and socket closed or timed-out } + UNLOCK(); + if (!ok) + return SOCKET_ERROR; } return cnt; } @@ -1032,9 +1115,9 @@ { if ((type == TYPE_PLUS) && param) { int sz, sk, p, a,b,c,d; - if ((sscanf(buf, "\r\n+USORF: %d,\""IPSTR"\",%d,%d,", - &sk,&a,&b,&c,&d,&p,&sz) == 7) && - (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) { + int r = sscanf(buf, "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,", + &sk,&a,&b,&c,&d,&p,&sz); + if ((r == 7) && (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) { memcpy(param->buf, &buf[len-1-sz], sz); param->ip = IPADR(a,b,c,d); param->port = p; @@ -1047,34 +1130,43 @@ { int cnt = 0; TRACE("socketRecvFrom(%d,,%d)\r\n", socket, len); - if (!ISSOCKET(socket)) - return SOCKET_ERROR; +#ifdef MDM_DEBUG memset(buf, '\0', len); +#endif Timer timer; timer.start(); while (len) { int blk = MAX_SIZE; // still need space for headers and unsolicited commands - if (_sockets[socket].pending < blk) - blk = _sockets[socket].pending; if (len < blk) blk = len; - if (blk) { - sendFormated("AT+USORF=%d,%d\r\n",socket, blk); - USORFparam param; - param.buf = buf; - if (RESP_OK != waitFinalResp(_cbUSORF, ¶m)) { - return SOCKET_ERROR; + bool ok = false; + LOCK(); + if (ISSOCKET(socket)) { + if (_sockets[socket].pending < blk) + blk = _sockets[socket].pending; + if (blk > 0) { + sendFormated("AT+USORF=%d,%d\r\n",socket, blk); + USORFparam param; + param.buf = buf; + if (RESP_OK == waitFinalResp(_cbUSORF, ¶m)) { + _sockets[socket].pending -= blk; + *ip = param.ip; + *port = param.port; + len -= blk; + cnt += blk; + buf += blk; + len = 0; // done + ok = true; + } + } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) { + ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs + } else { + len = 0; // no more data and socket closed or timed-out + ok = true; } - *ip = param.ip; - *port = param.port; - len -= blk; - cnt += blk; - buf += blk; - _sockets[socket].pending -= blk; - } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) { - // allow to receive unsolicited commands - waitFinalResp(NULL, NULL, 10); - } else - len = 0; // no more data and socket closed or timed-out + } + UNLOCK(); + if (!ok) + return SOCKET_ERROR; } timer.stop(); timer.reset(); @@ -1098,37 +1190,41 @@ } int MDMParser::smsList(const char* stat /*= "ALL"*/, int* ix /*=NULL*/, int num /*= 0*/) { + int ret = -1; + LOCK(); sendFormated("AT+CMGL=\"%s\"\r\n", stat); CMGLparam param; param.ix = ix; param.num = num; - if (RESP_OK != waitFinalResp(_cbCMGL, ¶m)) - return -1; - return num - param.num; + if (RESP_OK == waitFinalResp(_cbCMGL, ¶m)) + ret = num - param.num; + UNLOCK(); + return ret; } bool MDMParser::smsSend(const char* num, const char* buf) { + bool ok = false; + LOCK(); sendFormated("AT+CMGS=\"%s\"\r\n",num); - if (RESP_PROMPT != waitFinalResp(NULL,NULL,150*1000)) { - return false; + if (RESP_PROMPT == waitFinalResp(NULL,NULL,150*1000)) { + send(buf, strlen(buf)); + const char ctrlZ = 0x1A; + send(&ctrlZ, sizeof(ctrlZ)); + ok = (RESP_OK == waitFinalResp()); } - send(buf, strlen(buf)); - const char ctrlZ = 0x1A; - send(&ctrlZ, sizeof(ctrlZ)); - if (RESP_OK != waitFinalResp()) { - return false; - } - return true; + UNLOCK(); + return ok; } bool MDMParser::smsDelete(int ix) { + bool ok = false; + LOCK(); sendFormated("AT+CMGD=%d\r\n",ix); - if (RESP_OK != waitFinalResp()) { - return false; - } - return true; + ok = (RESP_OK == waitFinalResp()); + UNLOCK(); + return ok; } int MDMParser::_cbCMGR(int type, const char* buf, int len, CMGRparam* param) @@ -1147,14 +1243,15 @@ bool MDMParser::smsRead(int ix, char* num, char* buf, int len) { + bool ok = false; + LOCK(); CMGRparam param; param.num = num; param.buf = buf; sendFormated("AT+CMGR=%d\r\n",ix); - if (RESP_OK != waitFinalResp(_cbCMGR, ¶m)) { - return false; - } - return true; + ok = (RESP_OK == waitFinalResp(_cbCMGR, ¶m)); + UNLOCK(); + return ok; } // ---------------------------------------------------------------- @@ -1172,47 +1269,54 @@ bool MDMParser::ussdCommand(const char* cmd, char* buf) { - if (_dev.dev == DEV_LISA_C200) - return false; + bool ok = false; + LOCK(); *buf = '\0'; - sendFormated("AT+CUSD=1,\"%s\"\r\n",cmd); - if (RESP_OK != waitFinalResp(_cbCUSD, buf)) { - return false; + if (_dev.dev != DEV_LISA_C200) { + sendFormated("AT+CUSD=1,\"%s\"\r\n",cmd); + ok = (RESP_OK == waitFinalResp(_cbCUSD, buf)); } - return true; + UNLOCK(); + return ok; } // ---------------------------------------------------------------- bool MDMParser::delFile(const char* filename) { + bool ok = false; + LOCK(); sendFormated("AT+UDELFILE=\"%s\"\r\n", filename); - if (RESP_OK != waitFinalResp()) - return false; - return true; + ok = (RESP_OK == waitFinalResp()); + UNLOCK(); + return ok; } int MDMParser::writeFile(const char* filename, const char* buf, int len) { + bool ok = false; + LOCK(); sendFormated("AT+UDWNFILE=\"%s\",%d\r\n", filename, len); - if (RESP_PROMPT != waitFinalResp()) - return 0; - send(buf, len); - if (RESP_OK != waitFinalResp()) - return 0; - return len; + if (RESP_PROMPT == waitFinalResp()) { + send(buf, len); + ok = (RESP_OK == waitFinalResp()); + } + UNLOCK(); + return ok ? len : -1; } int MDMParser::readFile(const char* filename, char* buf, int len) { - sendFormated("AT+URDFILE=\"%s\"\r\n", filename, len); URDFILEparam param; param.filename = filename; param.buf = buf; param.sz = len; param.len = 0; - if (RESP_OK != waitFinalResp(_cbURDFILE, ¶m)) - return -1; + LOCK(); + sendFormated("AT+URDFILE=\"%s\"\r\n", filename, len); + if (RESP_OK != waitFinalResp(_cbURDFILE, ¶m)); + param.len = -1; + UNLOCK(); return param.len; } @@ -1388,7 +1492,7 @@ const char* fmt; int type; } lutF[] = { { "\r\n+USORD: %d,%d,\"%c\"", TYPE_PLUS }, - { "\r\n+USORF: %d,\""IPSTR"\",%d,%d,\"%c\"", TYPE_PLUS }, + { "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,\"%c\"", TYPE_PLUS }, { "\r\n+URDFILE: %s,%d,\"%c\"", TYPE_PLUS }, }; static struct {