CQ出版 Interface 2014年10月号のC027(MAX7-Q)GPSテスト記事のプログラム。 CQ publishing Interface 2014.10 issue, C027 GPS(MAX-7Q) test program.
Dependencies: C027 C027_Support mbed
Diff: C027_Support/MDM.cpp
- Revision:
- 3:002503ab7199
- Parent:
- 2:bc413454a83e
diff -r bc413454a83e -r 002503ab7199 C027_Support/MDM.cpp --- a/C027_Support/MDM.cpp Mon Jul 28 15:45:16 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1260 +0,0 @@ -#include "mbed.h" -#include <ctype.h> -#include <string.h> -#include "MDM.h" - -#define TRACE (1/*1=off,0=trace*/)?:printf -#define DEBUG // enable this for AT command debugging -#define PROFILE "0" // this is the psd profile used -// some helper -#define ISSOCKET(s) (((s) >= 0) && ((s) < (sizeof(_sockets)/sizeof(*_sockets)))) -#define WAIT_MS(ms) wait_ms(ms) // you may choose to use Thread::wait(ms) - -#define MAX_SIZE 128 // max expected messages - -#ifdef DEBUG -void dump(const char* buf, int len) -{ - while (len --) { - char ch = *buf++; - if (ch == '\r') printf("\\r"); - else if (ch == '\n') printf("\\n"); - else if (ch >= 0x20) printf("%c", ch); - else printf("\\x%02x", ch); - } -} - -Timer dbgTime; - - #if 1 // colored terminal output using ANSI escape sequences - #define COL(c,t) "\33[" c t "\33[" "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) -#endif - -MDMParser* MDMParser::inst; - -MDMParser::MDMParser(void) -{ - inst = this; - memset(&_dev, 0, sizeof(_dev)); - memset(&_net, 0, sizeof(_net)); - _net.lac = 0xFFFF; - _net.ci = 0xFFFFFFFF; - _ip = NOIP; - memset(_sockets, 0, sizeof(_sockets)); -#ifdef DEBUG - dbgTime.start(); -#endif -} - -int MDMParser::send(const char* buf, int len) -{ -#ifdef DEBUG - printf("%10.3f ", dbgTime.read_ms()*0.001); - printf("AT send %4d \"", len); - dump(buf,len); - printf("\"\r\n"); -#endif - return _send(buf, len); -} - -int MDMParser::sendFormated(const char* format, ...) { - char buf[MAX_SIZE]; - va_list args; - va_start(args, format); - int len = vsnprintf(buf,sizeof(buf), format, args); - va_end(args); - return send(buf, len); -} - -int MDMParser::waitFinalResp(_CALLBACKPTR cb /* = NULL*/, - void* param /* = NULL*/, - int timeout_ms /*= 5000*/) -{ - char buf[MAX_SIZE + 64 /* add some more space for framing */]; - Timer timer; - timer.start(); - do { - int ret = getLine(buf, sizeof(buf)); -#ifdef DEBUG - if ((ret != WAIT) && (ret != NOT_FOUND)) - { - 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(" > ") : - "..." ; - printf("%10.3f ", dbgTime.read_ms()*0.001); - printf("AT read %s %3d \"", s, len); - dump(buf, len); - printf("\"\r\n"); - } -#endif - if ((ret != WAIT) && (ret != NOT_FOUND)) - { - int type = TYPE(ret); - if (type == TYPE_OK) return RESP_OK; - if (type == TYPE_ERROR) return RESP_ERROR; - if (type == TYPE_PROMPT) return RESP_PROMPT; - // handle unsolicited commands here - if (type == TYPE_PLUS) { - const char* cmd = buf+3; - int a, b, c, d, r; - char s[32]; - - // SMS Command --------------------------------- - // +CNMI: <mem>,<index> - if (sscanf(cmd, "CMTI: \"%*[^\"]\",%d", &a) == 1) { - TRACE("New SMS at index %d\r\n", a); - // Socket Specific Command --------------------------------- - // +UUSORD: <socket>,<length> - } else if ((sscanf(cmd, "UUSORD: %d,%d", &a, &b) == 2) && - ISSOCKET(a) /*&& (_sockets[a].state == SOCK_CONNECTED)*/) { - TRACE("Socket %d: %d bytes pending\r\n", a, b); - _sockets[a].pending = b; - // +UUSORF: <socket>,<length> - } else if ((sscanf(cmd, "UUSORF: %d,%d", &a, &b) == 2) && - ISSOCKET(a) /*&& (_sockets[a].state == SOCK_CONNECTED)*/) { - TRACE("Socket %d: %d bytes pending\r\n", a, b); - _sockets[a].pending = b; - // +UUSOCL: <socket> - } else if ((sscanf(cmd, "UUSOCL: %d", &a) == 1) && - ISSOCKET(a) && (_sockets[a].state == SOCK_CONNECTED)) { - TRACE("Socket %d: closed by remote host\r\n", a); - _sockets[a].state = SOCK_CREATED/*=CLOSED*/; - } - if (_dev.dev == DEV_LISA_C200) { - // CDMA Specific ------------------------------------------- - // +CREG: <n><SID>,<NID>,<stat> - 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 - _net.act = ACT_CDMA; - // +CSS: <mode>[,<format>,<oper>[,<AcT>]] - } else if (sscanf(cmd, "CSS %*c,%2s,%*d",s) == 1) { - //_net.reg = (strcmp("Z", s) == 0) ? REG_UNKNOWN : REG_HOME; - } - } else { - // GSM/UMTS Specific ------------------------------------------- - // +CREG: <n>, <stat>[,<lac>,<ci>[,AcT]] - b = 255; - r = sscanf(cmd, "CREG: %*d,%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> - } else if (sscanf(cmd, "UUPSDD: %d",&a) == 1) { - if (*PROFILE == a) _ip = NOIP; - } - } - } - if (cb) { - int len = LENGTH(ret); - int ret = cb(type, buf, len, param); - if (WAIT != ret) - return ret; - } - } - // relax a bit - WAIT_MS(10); - } - while ((timeout_ms == TIMEOUT_BLOCKING) || - (timer.read_ms() < timeout_ms)); - timer.stop(); - timer.reset(); - return WAIT; -} - -int MDMParser::_cbString(int type, const char* buf, int len, char* str) -{ - if (str && (type == TYPE_UNKNOWN)) { - if (sscanf(buf, "\r\n%s\r\n", str) == 1) - /*nothing*/; - } - return WAIT; -} - -int MDMParser::_cbInt(int type, const char* buf, int len, int* val) -{ - if (val && (type == TYPE_UNKNOWN)) { - if (sscanf(buf, "\r\n%d\r\n", val) == 1) - /*nothing*/; - } - return WAIT; -} - -// ---------------------------------------------------------------- - -bool MDMParser::connect( - const char* simpin, - const char* apn, const char* username, const char* password, - bool dump) -{ - DevStatus devStatus = {}; - WAIT_MS(2000); - bool mdmOk = init(simpin, &devStatus); - if (dump) dumpDevStatus(&devStatus); - if (!mdmOk) - return false; - // wait until we are connected - int i = 60; - NetStatus netStatus = {}; - while (!checkNetStatus(&netStatus)) - { - if ((netStatus.reg == REG_DENIED) || (i == 0)) - break;; - i --; - WAIT_MS(1000); - } - if (dump) dumpNetStatus(&netStatus); - if ((netStatus.reg == REG_DENIED) || (i == 0)) - return false; - IP ip = join(apn,username,password); - if (dump) dumpIp(ip); - if (ip == NOIP) - return false; - return true; -} - -bool MDMParser::init(const char* simpin, DevStatus* status) -{ - int i = 5; - // we should wait some time before - while (i--) { - // check interface and disable local echo - sendFormated("AT\r\n"); - if(RESP_OK == waitFinalResp(NULL,NULL,1000)) - break; - } - if (i < 0) - return false; - // echo off - sendFormated("AT E0\r\n"); - if(RESP_OK != waitFinalResp()) - return false; - // enable verbose error messages - sendFormated("AT+CMEE=2\r\n"); - if(RESP_OK != waitFinalResp()) - return false; - // set baud rate - sendFormated("AT+IPR=115200\r\n"); - if (RESP_OK != waitFinalResp()) - return false; - WAIT_MS(40); - // identify the module - sendFormated("ATI\r\n"); - if (RESP_OK != waitFinalResp(_cbATI, &_dev.dev)) - return false; - if (_dev.dev == DEV_UNKNOWN) - return false; - // 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; - // get the model identification - sendFormated("AT+GMM\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _dev.model)) - return false; - // get the sw version - sendFormated("AT+GMR\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _dev.ver)) - return false; - // Return the pseudo ESN or MEID - sendFormated("AT+GSN\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _dev.meid)) - return false; -#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; - _dev.lpm = LPM_ACTIVE; - } -#endif - } else { - if (_dev.dev == DEV_LISA_U200) { - // enable the network identification feature - sendFormated("AT+UGPIOC=20,2\r\n"); - if (RESP_OK != waitFinalResp()) - return false; - } else { - // enable the network identification feature - sendFormated("AT+UGPIOC=16,2\r\n"); - if (RESP_OK != waitFinalResp()) - return false; - } - // check the sim card - for (int i = 0; (i < 5) && (_dev.sim != SIM_READY); i++) { - sendFormated("AT+CPIN?\r\n"); - 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; - // Enter PIN if needed - if (_dev.sim == SIM_PIN) { - if (!simpin) { - TRACE("SIM PIN not available\r\n"); - return false; - } - sendFormated("AT+CPIN=%s\r\n", simpin); - if (RESP_OK != waitFinalResp(_cbCPIN, &_dev.sim)) - return false; - } else if (_dev.sim != SIM_READY) { - WAIT_MS(1000); - } - } - if (_dev.sim != SIM_READY) - return false; - // get the manufacturer - sendFormated("AT+CGMI\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _dev.manu)) - return false; - // get the model identification - sendFormated("AT+CGMM\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _dev.model)) - return false; - // get the - sendFormated("AT+CGMR\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _dev.ver)) - return false; - // 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; - // Returns the product serial number, IMEI (International Mobile Equipment Identity) - sendFormated("AT+CGSN\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _dev.imei)) - return false; -#if 0 - // Configure New message indication - sendFormated("AT+CNMI=2,1,0,0,0\r\n"); - if (RESP_OK != waitFinalResp()) - return false; -#endif - // 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; - _dev.lpm = LPM_ACTIVE; - } - } - // Setup SMS in text mode - sendFormated("AT+CMGF=1\r\n"); - if (RESP_OK != waitFinalResp()) - return false; - // setup new message indication - sendFormated("AT+CNMI=1,1\r\n"); - if (RESP_OK != waitFinalResp()) - return false; - // Request IMSI (International Mobile Subscriber Identification) - sendFormated("AT+CIMI\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _dev.imsi)) - return false; - if (status) - memcpy(status, &_dev, sizeof(DevStatus)); - return true; -} - -int MDMParser::_cbATI(int type, const char* buf, int len, Dev* dev) -{ - if ((type == TYPE_UNKNOWN) && dev) { - if (strstr(buf, "SARA-G350")) { - *dev = DEV_SARA_G350; - /*TRACE("Identified Device: SARA-G350 2G\\n")*/; - } else if (strstr(buf, "LISA-U200")) { - *dev = DEV_LISA_U200; - /*TRACE("Identified Device: LISA-U200 2G/3G\r\n")*/; - } else if (strstr(buf, "LISA-C200")) { - *dev= DEV_LISA_C200; - /*TRACE("Identified Device: LISA-C200 CDMA\r\n")*/; - } - } - return WAIT; -} - -int MDMParser::_cbCPIN(int type, const char* buf, int len, Sim* sim) -{ - if ((type == TYPE_PLUS) && sim){ - char s[16]; - if (sscanf(buf, "\r\n+CPIN: %[^\r]\r<n", s) >= 1) { - *sim = (strcmp("READY", s) == 0) ? SIM_READY : SIM_PIN; - } - } - return WAIT; -} - -int MDMParser::_cbCCID(int type, const char* buf, int len, char* ccid) -{ - if ((type == TYPE_PLUS) && ccid){ - if (sscanf(buf, "\r\n+CCID: %[^\r]\r\n", ccid) == 1) - /*TRACE("Got CCID: %s\r\n", ccid)*/; - } - return WAIT; -} - -bool MDMParser::checkNetStatus(NetStatus* status /*= NULL*/) -{ - // enable the network registration unsolicited result code -// sendFormated("AT+CREG=%d\r\n", (_dev.dev == DEV_LISA_C200) ? 1 : 2); - sendFormated("AT+CGREG=%d\r\n", 2); - if (RESP_OK != waitFinalResp()) - return false; - // check registration -// sendFormated("AT+CREG?\r\n"); - sendFormated("AT+CGREG?\r\n"); - if (RESP_OK != waitFinalResp()) - return false; - if ((_net.reg != REG_ROAMING) && (_net.reg != REG_HOME)) - return false; - // check modem specific status messages - if (_dev.dev == DEV_LISA_C200) { - sendFormated("AT+CSS?\r\n"); - if (RESP_OK != waitFinalResp()) - return false; - // get the Telephone number - sendFormated("AT$MDN?\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _net.num)) - return false; - // check if we have a Mobile Directory Number - if (memcmp(_net.num, "0000", 4) == 0) - return false; - // get the the Network access identifier string - char nai[64]; - sendFormated("AT$QCMIPNAI?\r\n"); - if (RESP_OK != waitFinalResp(_cbString, nai)) - return false; - } else { - // check GPRS attach status - int state = 0; - sendFormated("AT+CGATT?\r\n"); - if (RESP_OK != waitFinalResp(_cbCGATT, &state, 3*60*1000)) - return false; - if (state != 1) - return false; - // check operator selection - sendFormated("AT+COPS?\r\n"); - if (RESP_OK != waitFinalResp(_cbCOPS, &_net, 3*60*1000)) - return false; - // Returns the MSISDNs related to this subscriber - sendFormated("AT+CNUM\r\n"); - if (RESP_OK != waitFinalResp(_cbCNUM, _net.num)) - return false; - } - // Returns the signal strength indication - sendFormated("AT+CSQ\r\n"); - if (RESP_OK != waitFinalResp(_cbCSQ, &_net)) - return false; - if (status) { - memcpy(status, &_net, sizeof(NetStatus)); - } - return true; -} - -int MDMParser::_cbCGATT(int type, const char* buf, int len, int* state) -{ - if ((type == TYPE_PLUS) && state){ - if (sscanf(buf, "\r\n+CGATT: %d\r\n", state) == 1) - /*TRACE("Got CGATT: %d\r\n", state)*/; - } - return WAIT; -} - -int MDMParser::_cbCOPS(int type, const char* buf, int len, NetStatus* status) -{ - if ((type == TYPE_PLUS) && status){ - int act = 99; - // +COPS: <mode>[,<format>,<oper>[,<AcT>]] - if (sscanf(buf, "\r\n+COPS: %*d,%*d,\"%[^\"]\",%d",status->opr,&act) >= 1) { - if (act == 0) status->act = ACT_GSM; // 0: GSM, - else if (act == 2) status->act = ACT_UTRAN; // 2: UTRAN - } - } - return WAIT; -} - -int MDMParser::_cbCNUM(int type, const char* buf, int len, char* num) -{ - if ((type == TYPE_PLUS) && num){ - int a; - if ((sscanf(buf, "\r\n+CNUM: \"My Number\",\"%31[^\"]\",%d", num, &a) == 2) && - ((a == 129) || (a == 145))) { - } - } - return WAIT; -} - -int MDMParser::_cbCSQ(int type, const char* buf, int len, NetStatus* status) -{ - if ((type == TYPE_PLUS) && status){ - int a,b; - char _ber[] = { 49, 43, 37, 25, 19, 13, 7, 0 }; // see 3GPP TS 45.008 [20] subclause 8.2.4 - // +CSQ: <rssi>,<qual> - if (sscanf(buf, "\r\n+CSQ: %d,%d",&a,&b) == 2) { - if (a != 99) status->rssi = -113 + 2*a; // 0: -113 1: -111 ... 30: -53 dBm with 2 dBm steps - if ((b != 99) && (b < sizeof(_ber))) status->ber = _ber[b]; // - } - } - return WAIT; -} -bool MDMParser::powerOff(void) -{ - sendFormated("AT+CPWROFF\r\n"); - if (RESP_OK != waitFinalResp(NULL,NULL,120)) - return false; - return true; -} - -// ---------------------------------------------------------------- -// internet connection - -MDMParser::IP MDMParser::join(const char* apn /*= NULL*/, const char* username /*= NULL*/, const char* password /*= NULL*/) -{ - _ip = NOIP; - if (_dev.dev == DEV_LISA_C200) { - // TODO: is there something to do here? -#if 0 - //Get local IP address - sendFormated("AT+CMIP?\r\n"); - if (RESP_OK != waitFinalResp(_cbCMIP, &_ip)) - return NOIP; -#else - return 0x01010101; // a fake IP -#endif - } else { - // check gprs attach status - sendFormated("AT+CGATT?\r\n"); - if (RESP_OK != waitFinalResp()) - return NOIP; - - // Check the profile - int a = 0; - sendFormated("AT+UPSND=" PROFILE ",8\r\n"); - if (RESP_OK != waitFinalResp(_cbUPSND, &a)) - return NOIP; - if (a == 1) { - // 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;; - } - // 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; - // Activate the profile and make connection - sendFormated("AT+UPSDA=" PROFILE ",3\r\n"); - if (RESP_OK != waitFinalResp(NULL,NULL,150*1000)) - return NOIP; - //Get local IP address - sendFormated("AT+UPSND=" PROFILE ",0\r\n"); - if (RESP_OK != waitFinalResp(_cbUPSND, &_ip)) - return NOIP; - } - return _ip; -} - -int MDMParser::_cbCMIP(int type, const char* buf, int len, IP* ip) -{ - if ((type == TYPE_PLUS) && ip) { - int a,b,c,d; - if (sscanf(buf, "\r\n+CMIP: " IPSTR, &a,&b,&c,&d) == 4) - *ip = IPADR(a,b,c,d); - } - return WAIT; -} - -int MDMParser::_cbUPSND(int type, const char* buf, int len, int* act) -{ - if ((type == TYPE_PLUS) && act) { - if (sscanf(buf, "\r\n+UPSND: %*d,%*d,%d", act) == 1) - /*nothing*/; - } - return WAIT; -} - -int MDMParser::_cbUPSND(int type, const char* buf, int len, IP* ip) -{ - if ((type == TYPE_PLUS) && ip) { - int a,b,c,d; - // +UPSND=<profile_id>,<param_tag>[,<dynamic_param_val>] - if (sscanf(buf, "\r\n+UPSND: " PROFILE ",0,\"" IPSTR "\"", &a,&b,&c,&d) == 4) - *ip = IPADR(a,b,c,d); - } - return WAIT; -} - -int MDMParser::_cbUDNSRN(int type, const char* buf, int len, IP* ip) -{ - if ((type == TYPE_PLUS) && ip) { - int a,b,c,d; - if (sscanf(buf, "\r\n+UDNSRN: \""IPSTR"\"", &a,&b,&c,&d) == 4) - *ip = IPADR(a,b,c,d); - } - return WAIT; -} - -bool MDMParser::disconnect(void) -{ - if (_ip == NOIP) - return true; - if (_dev.dev == DEV_LISA_C200) { - // TODO: is there something to do here? - } else { - sendFormated("AT+UPSDA=" PROFILE ",4\r\n"); - if (RESP_OK != waitFinalResp()) - return false; - } - _ip = NOIP; - return true; -} - -MDMParser::IP MDMParser::gethostbyname(const char* host) -{ - IP ip = NOIP; - int a,b,c,d; - if (sscanf(host, IPSTR, &a,&b,&c,&d) == 4) - ip = IPADR(a,b,c,d); - else { - sendFormated("AT+UDNSRN=0,\"%s\"\r\n", host); - if (RESP_OK != waitFinalResp(_cbUDNSRN, &ip)) - return false; - } - return ip; -} - -// ---------------------------------------------------------------- -// sockets - -int MDMParser::_cbUSOCR(int type, const char* buf, int len, int* socket) -{ - if ((type == TYPE_PLUS) && socket) { - const char* p = strstr(buf,"+USOCR: "); - if (p) - *socket = atoi(p+8); - } - return WAIT; -} - -int MDMParser::socketSocket(IpProtocol ipproto, int port) -{ - TRACE("socketSocket(%d)\r\n", ipproto); - if(ipproto == IPPROTO_TCP) { - sendFormated("AT+USOCR=6\r\n"); - } else 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; - 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; - 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 MDMParser::socketIsConnected(int socket) -{ - TRACE("socketIsConnected(%d)\r\n", socket); - if (!ISSOCKET(socket)) - return false; - TRACE(" ... %d\r\n", _sockets[socket].state); - return _sockets[socket].state == SOCK_CONNECTED; -} - -bool MDMParser::socketSetBlocking(int socket, int timeout_ms) -{ - TRACE("socketSetBlocking(%d,%d)\r\n", socket, timeout_ms); - if (!ISSOCKET(socket)) - return false; - _sockets[socket].timeout_ms = timeout_ms; - return true; -} - -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 MDMParser::socketFree(int socket) -{ - TRACE("socketFree(%d)\r\n", socket); - socketClose(socket); - if (!ISSOCKET(socket) || (_sockets[socket].state != SOCK_CREATED)) - return false; - _sockets[socket].state = SOCK_FREE; - return true; -} - -#define USO_MAX_WRITE 1024 //!< maximum number of bytes to write to socket - -int MDMParser::socketSend(int socket, const char * buf, int len) -{ - TRACE("socketSend(%d,,%d)\r\n", socket,len); - int cnt = len; - while (cnt > 0) { - int blk = USO_MAX_WRITE; - if (cnt < blk) - blk = cnt; - sendFormated("AT+USOWR=%d,%d\r\n",socket,blk); - if (RESP_PROMPT != waitFinalResp()) - return SOCKET_ERROR; - WAIT_MS(50); - send(buf, blk); - if (RESP_OK != waitFinalResp()) - return SOCKET_ERROR; - buf += blk; - cnt -= blk; - } - return (len - cnt); -} - -int MDMParser::socketSendTo(int socket, IP ip, int port, const char * buf, int len) -{ - TRACE("socketSendTo(%d," IPSTR ",%d,,%d)\r\n", socket, IPNUM(ip),port,len); - int cnt = len; - while (cnt > 0) { - 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; - WAIT_MS(50); - send(buf, blk); - if (RESP_OK != waitFinalResp()) - return SOCKET_ERROR; - buf += blk; - cnt -= blk; - } - return (len - cnt); -} - -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 MDMParser::_cbUSORD(int type, const char* buf, int len, char* out) -{ - if ((type == TYPE_PLUS) && out) { - int sz, sk; - if ((sscanf(buf, "\r\n+USORD: %d,%d,", &sk, &sz) == 2) && - (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) { - memcpy(out, &buf[len-1-sz], sz); - } - } - return WAIT; -} - -int MDMParser::socketRecv(int socket, char* buf, int len) -{ - int cnt = 0; - TRACE("socketRecv(%d,,%d)\r\n", socket, len); - if (!ISSOCKET(socket)) - return SOCKET_ERROR; - memset(buf, '\0', len); - 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; - } - len -= blk; - cnt += blk; - buf += blk; - _sockets[socket].pending -= blk; - } else if ((_sockets[socket].state == SOCK_CONNECTED) && ( - (_sockets[socket].timeout_ms == TIMEOUT_BLOCKING) || - (timer.read_ms() < _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 - } - } - - timer.stop(); - timer.reset(); - return cnt; -} - -int MDMParser::_cbUSORF(int type, const char* buf, int len, USORFparam* param) -{ - 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] == '\"')) { - memcpy(param->buf, &buf[len-1-sz], sz); - param->ip = IPADR(a,b,c,d); - param->port = p; - } - } - return WAIT; -} - -int MDMParser::socketRecvFrom(int socket, IP* ip, int* port, char* buf, int len) -{ - int cnt = 0; - TRACE("socketRecvFrom(%d,,%d)\r\n", socket, len); - if (!ISSOCKET(socket)) - return SOCKET_ERROR; - memset(buf, '\0', len); - 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; - } - *ip = param.ip; - *port = param.port; - len -= blk; - cnt += blk; - buf += blk; - _sockets[socket].pending -= blk; - } else if ((_sockets[socket].timeout_ms == TIMEOUT_BLOCKING) || - (timer.read_ms() < _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 - } - } - timer.stop(); - timer.reset(); - return cnt; -} - -// ---------------------------------------------------------------- - -int MDMParser::_cbCMGL(int type, const char* buf, int len, CMGLparam* param) -{ - if ((type == TYPE_PLUS) && param && param->num) { - // +CMGL: <ix>,... - int ix; - if (sscanf(buf, "\r\n+CMGL: %d,", &ix) == 1) - { - *param->ix++ = ix; - param->num--; - } - } - return WAIT; -} - -int MDMParser::smsList(const char* stat /*= "ALL"*/, int* ix /*=NULL*/, int num /*= 0*/) { - 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; -} - -bool MDMParser::smsSend(const char* num, const char* buf) -{ - sendFormated("AT+CMGS=\"%s\"\r",num); - if (RESP_PROMPT != waitFinalResp(NULL,NULL,150*1000)) { - return false; - } - send(buf, strlen(buf)); - const char ctrlZ = 0x1A; - send(&ctrlZ, sizeof(ctrlZ)); - if (RESP_OK != waitFinalResp()) { - return false; - } - return true; -} - -bool MDMParser::smsDelete(int ix) -{ - sendFormated("AT+CMGD=%d\r\n",ix); - if (RESP_OK != waitFinalResp()) { - return false; - } - return true; -} - -int MDMParser::_cbCMGR(int type, const char* buf, int len, CMGRparam* param) -{ - if (param) { - if (type == TYPE_PLUS) { - if (sscanf(buf, "\r\n+CMGR: \"%*[^\"]\",\"%[^\"]", param->num) == 1) { - } - } else if ((type == TYPE_UNKNOWN) && (buf[len-2] == '\r') && (buf[len-1] == '\n')) { - memcpy(param->buf, buf, len-2); - param->buf[len-2] = '\0'; - } - } - return WAIT; -} - -bool MDMParser::smsRead(int ix, char* num, char* buf, int len) -{ - 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; -} - -// ---------------------------------------------------------------- - -void MDMParser::dumpDevStatus(MDMParser::DevStatus* status) -{ - printf("Modem Device Status:\r\n"); - const char* txtDev[] = { "Unknown", "SARA-G350", "LISA-U200", "LISA-C200" }; - if (status->dev < sizeof(txtDev)/sizeof(*txtDev) && (status->dev != MDMParser::DEV_UNKNOWN)) - printf(" Device: %s\r\n", txtDev[status->dev]); - const char* txtLpm[] = { "Disabled", "Enabled", "Active" }; - if (status->lpm < sizeof(txtLpm)/sizeof(*txtLpm)) - printf(" Power Save: %s\r\n", txtLpm[status->lpm]); - const char* txtSim[] = { "Unknown", "Pin", "Ready" }; - if (status->sim < sizeof(txtSim)/sizeof(*txtSim) && (status->sim != MDMParser::SIM_UNKNOWN)) - printf(" SIM: %s\r\n", txtSim[status->sim]); - if (*status->ccid) - printf(" CCID: %s\r\n", status->ccid); - if (*status->imei) - printf(" IMEI: %s\r\n", status->imei); - if (*status->imsi) - printf(" IMSI: %s\r\n", status->imsi); - if (*status->meid) - printf(" MEID: %s\r\n", status->meid); // LISA-C - if (*status->manu) - printf(" Manufacturer: %s\r\n", status->manu); - if (*status->model) - printf(" Model: %s\r\n", status->model); - if (*status->ver) - printf(" Version: %s\r\n", status->ver); -} - -void MDMParser::dumpNetStatus(MDMParser::NetStatus *status) -{ - printf("Modem Network Status:\r\n"); - const char* txtReg[] = { "Unknown", "Denied", "None", "Home", "Roaming" }; - if (status->reg < sizeof(txtReg)/sizeof(*txtReg) && (status->reg != MDMParser::REG_UNKNOWN)) - printf(" Registration: %s\r\n", txtReg[status->reg]); - const char* txtAct[] = { "Unknown", "GSM", "Edge", "3G", "CDMA" }; - if (status->act < sizeof(txtAct)/sizeof(*txtAct) && (status->act != MDMParser::ACT_UNKNOWN)) - printf(" Access Technology: %s\r\n", txtAct[status->act]); - if (status->rssi) - printf(" Signal Strength: %d dBm\r\n", status->rssi); - if (status->ber) - printf(" Bit Error Rate: %d\r\n", status->ber); - if (*status->opr) - printf(" Operator: %s\r\n", status->opr); - if (status->lac != 0xFFFF) - printf(" Location Area Code: %04X\r\n", status->lac); - if (status->ci != 0xFFFFFFFF) - printf(" Cell ID: %08X\r\n", status->ci); - if (*status->num) - printf(" Phone Number: %s\r\n", status->num); -} - -void MDMParser::dumpIp(MDMParser::IP ip) -{ - if (ip != NOIP) - printf("Modem IP Address: " IPSTR "\r\n", IPNUM(ip)); -} - -// ---------------------------------------------------------------- - -int MDMParser::_cbCUSD(int type, const char* buf, int len, char* resp) -{ - if ((type == TYPE_PLUS) && resp) { - // +USD: \"%*[^\"]\",\"%[^\"]\",,\"%*[^\"]\",%d,%d,%d,%d,\"*[^\"]\",%d,%d"..); - if (sscanf(buf, "\r\n+CUSD: %*d,\"%[^\"]\",%*d", resp) == 1) { - /*nothing*/ - } - } - return WAIT; -} - -bool MDMParser::ussdCommand(const char* cmd, char* buf) -{ - *buf = '\0'; - sendFormated("AT+CUSD=1,\"%s\"\r\n",cmd); - if (RESP_OK != waitFinalResp(_cbCUSD, buf)) { - return false; - } - return true; -} - -// ---------------------------------------------------------------- -int MDMParser::_parseMatch(Pipe<char>* pipe, int len, const char* sta, const char* end) -{ - int o = 0; - if (sta) { - while (*sta) { - if (++o > len) return WAIT; - char ch = pipe->next(); - if (*sta++ != ch) return NOT_FOUND; - } - } - if (!end) return o; // no termination - // at least any char - if (++o > len) return WAIT; - pipe->next(); - // check the end - int x = 0; - while (end[x]) { - if (++o > len) return WAIT; - char ch = pipe->next(); - x = (end[x] == ch) ? x + 1 : - (end[0] == ch) ? 1 : - 0; - } - return o; -} - -int MDMParser::_parseFormated(Pipe<char>* pipe, int len, const char* fmt) -{ - int o = 0; - int num = 0; - if (fmt) { - while (*fmt) { - if (++o > len) return WAIT; - char ch = pipe->next(); - if (*fmt == '%') { - fmt++; - if (*fmt == 'd') { // numeric - fmt ++; - num = 0; - while (ch >= '0' && ch <= '9') { - num = num * 10 + (ch - '0'); - if (++o > len) return WAIT; - ch = pipe->next(); - } - } - else if (*fmt == 'c') { // char buffer (takes last numeric as length) - fmt ++; - while (num --) { - if (++o > len) return WAIT; - ch = pipe->next(); - } - } - } - if (*fmt++ != ch) return NOT_FOUND; - } - } - return o; -} - - -int MDMParser::_getLine(Pipe<char>* pipe, char* buf, int len) -{ - int unkn = 0; - int sz = pipe->size(); - int fr = pipe->free(); - if (len > sz) - len = sz; - while (len > 0) - { - static struct { - const char* fmt; int type; - } lutF[] = { - { "\r\n+USORD: %d,%d,\"%c\"", TYPE_PLUS }, - { "\r\n+USORF: %d,\""IPSTR"\",%d,%d,\"%c\"", TYPE_PLUS }, - }; - static struct { - const char* sta; const char* end; int type; - } lut[] = { - { "\r\nOK\r\n", NULL, TYPE_OK }, - { "\r\nERROR\r\n", NULL, TYPE_ERROR }, - { "\r\n+CME ERROR:", "\r\n", TYPE_ERROR }, - { "\r\n+CMS ERROR:", "\r\n", TYPE_ERROR }, - { "\r\nRING\r\n", NULL, TYPE_RING }, - { "\r\nCONNECT\r\n", NULL, TYPE_CONNECT }, - { "\r\nNO CARRIER\r\n", NULL, TYPE_NOCARRIER }, - { "\r\nNO DIALTONE\r\n", NULL, TYPE_NODIALTONE }, - { "\r\nBUSY\r\n", NULL, TYPE_BUSY }, - { "\r\nNO ANSWER\r\n", NULL, TYPE_NOANSWER }, - { "\r\n+", "\r\n", TYPE_PLUS }, - { "\r\n@", NULL, TYPE_PROMPT }, // Sockets - { "\r\n>", NULL, TYPE_PROMPT }, // SMS - }; - for (int i = 0; i < sizeof(lutF)/sizeof(*lutF); i ++) { - pipe->set(unkn); - int ln = _parseFormated(pipe, len, lutF[i].fmt); - if (ln == WAIT && fr) - return WAIT; - if ((ln != NOT_FOUND) && (unkn > 0)) - return TYPE_UNKNOWN | pipe->get(buf, unkn); - if (ln > 0) - return lutF[i].type | pipe->get(buf, ln); - } - for (int i = 0; i < sizeof(lut)/sizeof(*lut); i ++) { - pipe->set(unkn); - int ln = _parseMatch(pipe, len, lut[i].sta, lut[i].end); - if (ln == WAIT && fr) - return WAIT; - if ((ln != NOT_FOUND) && (unkn > 0)) - return TYPE_UNKNOWN | pipe->get(buf, unkn); - if (ln > 0) - return lut[i].type | pipe->get(buf, ln); - } - // UNKNOWN - unkn ++; - len--; - } - return WAIT; -} - -// ---------------------------------------------------------------- -// Serial Implementation -// ---------------------------------------------------------------- - -MDMSerial::MDMSerial(PinName tx /*= MDMTXD*/, PinName rx /*= MDMRXD*/, - int baudrate /*= MDMBAUD*/, -#if DEVICE_SERIAL_FC - PinName rts /*= MDMRTS*/, PinName cts /*= MDMCTS*/, -#endif - int rxSize /*= 256*/, int txSize /*= 128*/) : - SerialPipe(tx, rx, rxSize, txSize) -{ - baud(baudrate); -#if DEVICE_SERIAL_FC - if ((rts != NC) || (cts != NC)) - { - Flow flow = (cts == NC) ? RTS : - (rts == NC) ? CTS : RTSCTS ; - set_flow_control(flow, rts, cts); - if (cts != NC) _dev.lpm = LPM_ENABLED; - } -#endif -} - -int MDMSerial::_send(const void* buf, int len) -{ - return put((const char*)buf, len, true/*=blocking*/); -} - -int MDMSerial::getLine(char* buffer, int length) -{ - return _getLine(&_pipeRx, buffer, length); -} - -// ---------------------------------------------------------------- -// USB Implementation -// ---------------------------------------------------------------- - -#ifdef HAVE_MDMUSB -// TODO properly implement with USB -MDMUsb::MDMUsb(void) { } -int MDMUsb::_send(const void* buf, int len) { return len; } -int MDMUsb::getLine(char* buffer, int length) { return NOT_FOUND; } -#endif