Fork of Ublox Lib
Fork of C027_Support by
Revision 139:5df09023c4e9, committed 2016-12-06
- Comitter:
- atarbey
- Date:
- Tue Dec 06 10:43:13 2016 +0000
- Parent:
- 138:dafbbf31bf76
- Commit message:
- Forked from Ublox Library
Changed in this revision
diff -r dafbbf31bf76 -r 5df09023c4e9 GPS.cpp --- a/GPS.cpp Thu Feb 25 13:22:34 2016 +0000 +++ b/GPS.cpp Tue Dec 06 10:43:13 2016 +0000 @@ -1,9 +1,6 @@ #include "mbed.h" #include <ctype.h> #include "GPS.h" -#ifdef TARGET_UBLOX_C027 - #include "C027_api.h" -#endif void GPSParser::powerOff(void) {
diff -r dafbbf31bf76 -r 5df09023c4e9 GPS.h --- a/GPS.h Thu Feb 25 13:22:34 2016 +0000 +++ b/GPS.h Tue Dec 06 10:43:13 2016 +0000 @@ -214,8 +214,8 @@ \param adr the I2C address of the GPS set to (66<<1) \param rxSize the size of the serial rx buffer */ - GPSI2C(PinName sda GPS_IF( = GPSSDA, = D14 ), - PinName scl GPS_IF( = GPSSCL, = D15 ), + GPSI2C(PinName sda GPS_IF( = GPSSDA, = PA_10 ), + PinName scl GPS_IF( = GPSSCL, = PA_9 ), unsigned char i2cAdr GPS_IF( = GPSADR, = (66<<1) ), int rxSize = 256 ); //! Destructor
diff -r dafbbf31bf76 -r 5df09023c4e9 MDM.cpp --- a/MDM.cpp Thu Feb 25 13:22:34 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2350 +0,0 @@ -#include "mbed.h" -#include "MDM.h" -#ifdef TARGET_UBLOX_C027 - #include "C027_api.h" -#endif -#include "MDMAPN.h" - -#define PROFILE "0" //!< this is the psd profile used -#define MAX_SIZE 128 //!< max expected messages -// num sockets -#define NUMSOCKETS (sizeof(_sockets)/sizeof(*_sockets)) -//! test if it is a socket is ok to use -#define ISSOCKET(s) (((s) >= 0) && ((s) < NUMSOCKETS) && (_sockets[s].handle != SOCKET_ERROR)) -//! check for timeout -#define TIMEOUT(t, ms) ((ms != TIMEOUT_BLOCKING) && (ms < t.read_ms())) -// num HTTP profiles -#define NUMPROFILES (sizeof(_httpProfiles)/sizeof(*_httpProfiles)) -//! test if it is an HTTP profile is ok to use -#define ISPROFILE(p) (((p) >= 0) && ((p) < NUMPROFILES) && (_httpProfiles[p].handle != HTTP_PROF_ERROR)) -//! registration ok check helper -#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); - while (len --) { - char ch = *buf++; - if ((ch > 0x1F) && (ch != 0x7F)) { // is printable - if (ch == '%') ::printf("%%"); - else if (ch == '"') ::printf("\\\""); - else if (ch == '\\') ::printf("\\\\"); - else putchar(ch); - } else { - if (ch == '\a') ::printf("\\a"); // BEL (0x07) - else if (ch == '\b') ::printf("\\b"); // Backspace (0x08) - else if (ch == '\t') ::printf("\\t"); // Horizontal Tab (0x09) - else if (ch == '\n') ::printf("\\n"); // Linefeed (0x0A) - else if (ch == '\v') ::printf("\\v"); // Vertical Tab (0x0B) - else if (ch == '\f') ::printf("\\f"); // Formfeed (0x0C) - else if (ch == '\r') ::printf("\\r"); // Carriage Return (0x0D) - else ::printf("\\x%02x", (unsigned char)ch); - } - } - ::printf("\"\r\n"); -} - -void MDMParser::_debugPrint(int level, const char* color, const char* format, ...) -{ - if (_debugLevel >= level) - { - va_list args; - va_start (args, format); - if (color) ::printf(color); - ::vprintf(format, args); - if (color) ::printf(DEF); - va_end (args); - } -} - - #define ERROR(...) _debugPrint(0, RED, __VA_ARGS__) - #define INFO(...) _debugPrint(1, GRE, __VA_ARGS__) - #define TRACE(...) _debugPrint(2, DEF, __VA_ARGS__) - #define TEST(...) _debugPrint(3, CYA, __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 - -#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; - _init = false; - memset(_sockets, 0, sizeof(_sockets)); - for (int socket = 0; socket < NUMSOCKETS; socket ++) - _sockets[socket].handle = SOCKET_ERROR; - memset(_httpProfiles, 0, sizeof(_httpProfiles)); - for (int profile = 0; profile < NUMPROFILES; profile ++) - _httpProfiles[profile].handle = HTTP_PROF_ERROR; -#ifdef MDM_DEBUG - _debugLevel = 1; - _debugTime.start(); -#endif -} - -int MDMParser::send(const char* buf, int len) -{ -#ifdef MDM_DEBUG - if (_debugLevel >= 3) { - ::printf("%10.3f AT send ", _debugTime.read_ms()*0.001); - dumpAtCmd(buf,len); - } -#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 MDM_DEBUG - if ((_debugLevel >= 3) && (ret != WAIT) && (ret != NOT_FOUND)) - { - int len = LENGTH(ret); - int type = TYPE(ret); - 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); - } -#endif - if ((ret != WAIT) && (ret != NOT_FOUND)) - { - int type = TYPE(ret); - // 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)) { - int socket = _findSocket(a); - TRACE("Socket %d: handle %d has %d bytes pending\r\n", socket, a, b); - if (socket != SOCKET_ERROR) - _sockets[socket].pending = b; - // +UUSORF: <socket>,<length> - } else if ((sscanf(cmd, "UUSORF: %d,%d", &a, &b) == 2)) { - int socket = _findSocket(a); - TRACE("Socket %d: handle %d has %d bytes pending\r\n", socket, a, b); - if (socket != SOCKET_ERROR) - _sockets[socket].pending = b; - // +UUSOCL: <socket> - } else if ((sscanf(cmd, "UUSOCL: %d", &a) == 1)) { - int socket = _findSocket(a); - TRACE("Socket %d: handle %d closed by remote host\r\n", socket, a); - if ((socket != SOCKET_ERROR) && _sockets[socket].connected) - _sockets[socket].connected = false; - // +UULOC: <date>,<time>,<lat>,<long>,<alt>,<uncertainty>,<speed>, <direction>,<vertical_acc>,<sensor_used>,<SV_used>,<antenna_status>, <jamming_status> - }else if (sscanf(cmd, "UULOC: %d/%d/%d,%d:%d:%d.%*d,%f,%f,%d,%d,%d,%d,%d,%d,%d,%*d,%*d",\ - &_loc[0].time.tm_mday, &_loc[0].time.tm_mon, &_loc[0].time.tm_year, &_loc[0].time.tm_hour, &_loc[0].time.tm_min, &_loc[0].time.tm_sec,\ - &_loc[0].latitude, &_loc[0].longitude, &_loc[0].altitutude, &_loc[0].uncertainty, &_loc[0].speed, &_loc[0].direction, &_loc[0].verticalAcc, \ - &b, &_loc[0].svUsed) == 15) { - TRACE("Parsed UULOC position at index 0\r\n"); - _loc[0].sensor = (b==0)? CELL_LAST : (b==1)? CELL_GNSS : (b==2)? CELL_LOCATE : (b==3)? CELL_HYBRID : CELL_LAST; - _loc[0].time.tm_mon -= 1; - _loc[0].time.tm_wday=0; - _loc[0].time.tm_yday=0; - _loc[0].validData = true; - _locExpPos=1; - _locRcvPos++; - // +UULOC: <sol>,<num>,<sensor_used>,<date>,<time>,<lat>,<long>,<alt>,<uncertainty>,<speed>, <direction>,<vertical_acc>,,<SV_used>,<antenna_status>, <jamming_status> - }else if (sscanf(cmd, "UULOC: %d,%d,%d,%d/%d/%d,%d:%d:%d.%*d,%f,%f,%d,%d,%d,%d,%d,%d,%*d,%*d",\ - &a,&_locExpPos,&b, \ - &_loc[CELL_MAX_HYP-1].time.tm_mday, &_loc[CELL_MAX_HYP-1].time.tm_mon, &_loc[CELL_MAX_HYP-1].time.tm_year, &_loc[CELL_MAX_HYP-1].time.tm_hour, &_loc[CELL_MAX_HYP-1].time.tm_min, &_loc[CELL_MAX_HYP-1].time.tm_sec,\ - &_loc[CELL_MAX_HYP-1].latitude, &_loc[CELL_MAX_HYP-1].longitude, &_loc[CELL_MAX_HYP-1].altitutude, &_loc[CELL_MAX_HYP-1].uncertainty, &_loc[CELL_MAX_HYP-1].speed, &_loc[CELL_MAX_HYP-1].direction, &_loc[CELL_MAX_HYP-1].verticalAcc, \ - &_loc[CELL_MAX_HYP-1].svUsed) == 17) { - if (--a>=0){ - TRACE("Parsed UULOC position at index %d\r\n",a); - memcpy(&_loc[a], &_loc[CELL_MAX_HYP-1], sizeof(*_loc)); - _loc[a].sensor = (b==0)? CELL_LAST : (b==1)? CELL_GNSS : (b==2)? CELL_LOCATE : (b==3)? CELL_HYBRID : CELL_LAST; - _loc[a].time.tm_mon -= 1; - _loc[a].time.tm_wday=0; - _loc[a].time.tm_yday=0; - _loc[a].validData = true; - _locRcvPos++; - } - //+UULOC: <sol>,<num>,<sensor_used>,<date>,<time>,<lat>,<long>,<alt>,<lat50>,<long50>,<major50>,<minor50>,<orientation50>,<confidence50>[,<lat95>,<long95>,<major95>,<minor95>,<orientation95>,<confidence95>] - }else if (sscanf(cmd, "UULOC: %d,%d,%d,%d/%d/%d,%d:%d:%d.%*d,%f,%f,%d,%*f,%*f,%d,%*d,%*d,%*d",\ - &a,&_locExpPos,&b, \ - &_loc[CELL_MAX_HYP-1].time.tm_mday, &_loc[CELL_MAX_HYP-1].time.tm_mon, &_loc[CELL_MAX_HYP-1].time.tm_year, &_loc[CELL_MAX_HYP-1].time.tm_hour, &_loc[CELL_MAX_HYP-1].time.tm_min, &_loc[CELL_MAX_HYP-1].time.tm_sec,\ - &_loc[CELL_MAX_HYP-1].latitude, &_loc[CELL_MAX_HYP-1].longitude, &_loc[CELL_MAX_HYP-1].altitutude, &_loc[CELL_MAX_HYP-1].uncertainty) == 13) { - if (--a>=0){ - TRACE("Parsed UULOC position at index %d\r\n",a); - memcpy(&_loc[a], &_loc[CELL_MAX_HYP-1], sizeof(*_loc)); - _loc[a].sensor = (b==0)? CELL_LAST : (b==1)? CELL_GNSS : (b==2)? CELL_LOCATE : (b==3)? CELL_HYBRID : CELL_LAST; - _loc[a].time.tm_mon -= 1; - _loc[a].time.tm_wday=0; - _loc[a].time.tm_yday=0; - _loc[a].validData = true; - _locRcvPos++; - } - // +UHTTPCR: <profile_id>,<op_code>,<param_val> - } else if ((sscanf(cmd, "UUHTTPCR: %d,%d,%d", &a, &b, &c) == 3)) { - _httpProfiles[a].cmd = b; //command - _httpProfiles[a].result = c; //result - TRACE("%s for profile %d: result code is %d\r\n", getHTTPcmd(b), a, c); - } - if (_dev.dev == DEV_LISA_C2) { - // 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.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) { - //_net.reg = (strcmp("Z", s) == 0) ? REG_UNKNOWN : REG_HOME; - } - } else { - // GSM/UMTS Specific ------------------------------------------- - // +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 : - !strcmp(s, "CEREG:") ? &_net.eps : 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 - else if (a == 6) *reg = REG_HOME; // 6: registered, sms only, home - 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 - else if (d == 7) _net.act = ACT_LTE; // 7: LTE - } - } - } - } - } - } - if (cb) { - int len = LENGTH(ret); - int ret = cb(type, buf, len, param); - if (WAIT != ret) - return ret; - } - if (type == TYPE_OK) - return RESP_OK; - if (type == TYPE_ERROR) - return RESP_ERROR; - if (type == TYPE_ERROR_CME) - return RESP_ERROR_CME; - if (type == TYPE_PROMPT) - return RESP_PROMPT; - } - // relax a bit - wait_ms(10); - } - while (!TIMEOUT(timer, timeout_ms)); - 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, Auth auth, - PinName pn) -{ - bool ok = init(simpin, NULL, pn); -#ifdef MDM_DEBUG - if (_debugLevel >= 1) dumpDevStatus(&_dev); -#endif - if (!ok) - return false; - ok = registerNet(); -#ifdef MDM_DEBUG - if (_debugLevel >= 1) dumpNetStatus(&_net); -#endif - if (!ok) - return false; - IP ip = join(apn,username,password,auth); -#ifdef MDM_DEBUG - if (_debugLevel >= 1) dumpIp(ip); -#endif - if (ip == NOIP) - return false; - return true; -} - -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); - - // SARA-G35 >5ms, LISA-C2 > 150ms, LEON-G2 >5ms - pin = 0; ::wait_ms(150); - pin = 1; ::wait_ms(100); - - // purge any messages - purge(); - - // check interface - sendFormated("AT\r\n"); - int r = waitFinalResp(NULL,NULL,1000); - if(RESP_OK == r) break; - } - if (i < 0) { - ERROR("No Reply from Modem\r\n"); - goto failure; - } - } - _init = true; - - INFO("Modem::init\r\n"); - // echo off - sendFormated("AT E0\r\n"); - if(RESP_OK != waitFinalResp()) - goto failure; - // enable verbose error messages - sendFormated("AT+CMEE=2\r\n"); - if(RESP_OK != waitFinalResp()) - goto failure; - // set baud rate - sendFormated("AT+IPR=115200\r\n"); - if (RESP_OK != waitFinalResp()) - goto failure; - // wait some time until baudrate is applied - wait_ms(200); // SARA-G > 40ms - // identify the module - sendFormated("ATI\r\n"); - if (RESP_OK != waitFinalResp(_cbATI, &_dev.dev)) - goto failure; - if (_dev.dev == DEV_UNKNOWN) - goto failure; - // device specific init - if (_dev.dev == DEV_LISA_C2) { - // get the manufacturer - sendFormated("AT+GMI\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _dev.manu)) - goto failure; - // get the model identification - sendFormated("AT+GMM\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _dev.model)) - goto failure; - // get the sw version - sendFormated("AT+GMR\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _dev.ver)) - goto failure; - // get the pseudo ESN or MEID - sendFormated("AT+GSN\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _dev.meid)) - 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()) - goto failure; - _dev.lpm = LPM_ACTIVE; - } -#endif - } else { - if ((_dev.dev == DEV_LISA_U2) || (_dev.dev == DEV_LEON_G2) || - (_dev.dev == DEV_TOBY_L2)) { - // enable the network identification feature - sendFormated("AT+UGPIOC=20,2\r\n"); - if (RESP_OK != waitFinalResp()) - goto failure; - } else if ((_dev.dev == DEV_SARA_U2) || (_dev.dev == DEV_SARA_G35)) { - // enable the network identification feature - sendFormated("AT+UGPIOC=16,2\r\n"); - if (RESP_OK != waitFinalResp()) - goto failure; - } - // 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)) - goto failure; - // Enter PIN if needed - if (_dev.sim == SIM_PIN) { - if (!simpin) { - ERROR("SIM PIN not available\r\n"); - goto failure; - } - sendFormated("AT+CPIN=\"%s\"\r\n", simpin); - if (RESP_OK != waitFinalResp(_cbCPIN, &_dev.sim)) - goto failure; - } else if (_dev.sim != SIM_READY) { - wait_ms(1000); - } - } - if (_dev.sim != SIM_READY) { - if (_dev.sim == SIM_MISSING) - ERROR("SIM not inserted\r\n"); - goto failure; - } - // get the manufacturer - sendFormated("AT+CGMI\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _dev.manu)) - goto failure; - // get the model identification - sendFormated("AT+CGMM\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _dev.model)) - goto failure; - // get the version - sendFormated("ATI9\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _dev.ver)) - 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)) - goto failure; - // Returns the product serial number, IMEI (International Mobile Equipment Identity) - sendFormated("AT+CGSN\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _dev.imei)) - 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()) - goto failure; - _dev.lpm = LPM_ACTIVE; - } - // enable the psd registration unsolicited result code - sendFormated("AT+CGREG=2\r\n"); - if (RESP_OK != waitFinalResp()) - goto failure; - } - // enable the network registration unsolicited result code - sendFormated("AT+CREG=%d\r\n", (_dev.dev == DEV_LISA_C2) ? 1 : 2); - if (RESP_OK != waitFinalResp()) - goto failure; - // Setup SMS in text mode - sendFormated("AT+CMGF=1\r\n"); - if (RESP_OK != waitFinalResp()) - goto failure; - // setup new message indication - sendFormated("AT+CNMI=2,1\r\n"); - if (RESP_OK != waitFinalResp()) - goto failure; - // Request IMSI (International Mobile Subscriber Identification) - sendFormated("AT+CIMI\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _dev.imsi)) - 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)) { - _init = false; - ok = true; - } - UNLOCK(); - } - return ok; -} - -int MDMParser::_cbATI(int type, const char* buf, int len, Dev* dev) -{ - if ((type == TYPE_UNKNOWN) && dev) { - if (strstr(buf, "SARA-G35")) *dev = DEV_SARA_G35; - else if (strstr(buf, "LISA-U200-03S")) *dev = DEV_LISA_U2_03S; - else if (strstr(buf, "LISA-U2")) *dev = DEV_LISA_U2; - else if (strstr(buf, "LISA-C2")) *dev = DEV_LISA_C2; - else if (strstr(buf, "SARA-U2")) *dev = DEV_SARA_U2; - else if (strstr(buf, "LEON-G2")) *dev = DEV_LEON_G2; - else if (strstr(buf, "TOBY-L2")) *dev = DEV_TOBY_L2; - else if (strstr(buf, "MPCI-L2")) *dev = DEV_MPCI_L2; - } - return WAIT; -} - -int MDMParser::_cbCPIN(int type, const char* buf, int len, Sim* sim) -{ - if (sim) { - if (type == TYPE_PLUS){ - char s[16]; - if (sscanf(buf, "\r\n+CPIN: %[^\r]\r\n", s) >= 1) - *sim = (0 == strcmp("READY", s)) ? SIM_READY : SIM_PIN; - } else if (type == TYPE_ERROR) { - if (strstr(buf, "+CME ERROR: SIM not inserted")) - *sim = SIM_MISSING; - } - } - 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::registerNet(NetStatus* status /*= NULL*/, int timeout_ms /*= 180000*/) -{ - Timer timer; - timer.start(); - INFO("Modem::register\r\n"); - while (!checkNetStatus(status) && !TIMEOUT(timer, timeout_ms)) - 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"); - if (_net.eps == REG_DENIED) ERROR("EPS Registration Denied\r\n"); - return REG_OK(_net.csd) || REG_OK(_net.psd) || REG_OK(_net.eps); -} - -bool MDMParser::checkNetStatus(NetStatus* status /*= NULL*/) -{ - bool ok = false; - LOCK(); - memset(&_net, 0, sizeof(_net)); - _net.lac = 0xFFFF; - _net.ci = 0xFFFFFFFF; - // check registration - sendFormated("AT+CREG?\r\n"); - waitFinalResp(); // don't fail as service could be not subscribed - if (_dev.dev != DEV_LISA_C2) { - // check PSD registration - sendFormated("AT+CGREG?\r\n"); - waitFinalResp(); // don't fail as service could be not subscribed - if ((_dev.dev == DEV_TOBY_L2) || (_dev.dev == DEV_MPCI_L2)) { - // check EPS network registration - sendFormated("AT+CEREG?\r\n"); - waitFinalResp(); // don't fail as service could be not subscribed - } - } - if (REG_OK(_net.csd) || REG_OK(_net.psd) || REG_OK(_net.eps)) - { - // check modem specific status messages - if (_dev.dev == DEV_LISA_C2) { - sendFormated("AT+CSS?\r\n"); - if (RESP_OK != waitFinalResp()) - goto failure; - while (1) { - // get the Telephone number - sendFormated("AT$MDN?\r\n"); - if (RESP_OK != waitFinalResp(_cbString, _net.num)) - goto failure; - // check if we have a Mobile Directory Number - if (*_net.num && (memcmp(_net.num, "000000", 6) != 0)) - break; - - INFO("Device not yet activated\r\n"); - INFO("Make sure you have a valid contract with the network operator for this device.\r\n"); - // Check if the the version contains a V for Verizon - // Verizon: E0.V.xx.00.xxR, - // Sprint E0.S.xx.00.xxR - if (_dev.ver[3] == 'V') { - int i; - INFO("Start device over-the-air activation (this can take a few minutes)\r\n"); - sendFormated("AT+CDV=*22899\r\n"); - i = 1; - if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) { - ERROR("Device over-the-air activation failed\r\n"); - goto failure; - } - INFO("Device over-the-air activation successful\r\n"); - - INFO("Start PRL over-the-air update (this can take a few minutes)\r\n"); - sendFormated("AT+CDV=*22891\r\n"); - i = 1; - if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) { - ERROR("PRL over-the-air update failed\r\n"); - 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"); - 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)) - goto failure; - } else { - sendFormated("AT+COPS?\r\n"); - if (RESP_OK != waitFinalResp(_cbCOPS, &_net)) - goto failure; - // get the MSISDNs related to this subscriber - sendFormated("AT+CNUM\r\n"); - if (RESP_OK != waitFinalResp(_cbCNUM, _net.num)) - goto failure; - } - // get the signal strength indication - sendFormated("AT+CSQ\r\n"); - if (RESP_OK != waitFinalResp(_cbCSQ, &_net)) - goto failure; - } - if (status) { - memcpy(status, &_net, sizeof(NetStatus)); - } - ok = REG_DONE(_net.csd) && - (REG_DONE(_net.psd) || REG_DONE(_net.eps)); - UNLOCK(); - return ok; -failure: - unlock(); - return false; -} - -int MDMParser::_cbCOPS(int type, const char* buf, int len, NetStatus* status) -{ - if ((type == TYPE_PLUS) && status){ - int act = 99; - int mode = 99; - // +COPS: <mode>[,<format>,<oper>[,<AcT>]] - if (sscanf(buf, "\r\n+COPS: %d,%*d,\"%[^\"]\",%d",&mode,status->opr,&act) >= 1) { - if (act == 0) status->act = ACT_GSM; // 0: GSM, - else if (act == 2) status->act = ACT_UTRAN; // 2: UTRAN - else if (act == 7) status->act = ACT_LTE; // 2: UTRAN - if (mode == 0) status->regStatus = COPS_AUTOMATIC_REG; - else if (mode == 1) status->regStatus = COPS_MANUAL_REG; - else if (mode == 2) status->regStatus = COPS_DISABLED_REG; - } - } - 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, 31: >-51 dBm - if ((b != 99) && (b < sizeof(_ber))) status->ber = _ber[b]; // - } - } - return WAIT; -} - - -int MDMParser::_cbUACTIND(int type, const char* buf, int len, int* i) -{ - if ((type == TYPE_PLUS) && i){ - int a; - if (sscanf(buf, "\r\n+UACTIND: %d", &a) == 1) { - *i = a; - } - } - return WAIT; -} - -// ---------------------------------------------------------------- -// internet connection - -bool MDMParser::_activateProfile(const char* apn, const char* username, const char* password, Auth auth) -{ - // Set up the APN - if (*apn) { - sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn); - if (RESP_OK != waitFinalResp()) - return false; - } - if (*username) { - sendFormated("AT+UPSD=" PROFILE ",2,\"%s\"\r\n", username); - if (RESP_OK != waitFinalResp()) - return false; - } - if (*password) { - sendFormated("AT+UPSD=" PROFILE ",3,\"%s\"\r\n", password); - if (RESP_OK != waitFinalResp()) - return false; - } - // Set up the dynamic IP address assignment. - sendFormated("AT+UPSD=" PROFILE ",7,\"0.0.0.0\"\r\n"); - if (RESP_OK != waitFinalResp()) - return false; - // try different Authentication Protocols - // 0 = none - // 1 = PAP (Password Authentication Protocol) - // 2 = CHAP (Challenge Handshake Authentication Protocol) - for (int i = AUTH_NONE; i <= AUTH_CHAP; i ++) { - if ((auth == AUTH_DETECT) || (auth == i)) { - // Set up the Authentication Protocol - sendFormated("AT+UPSD=" PROFILE ",6,%d\r\n",i); - if (RESP_OK != waitFinalResp()) - return false; - // Activate the profile and make connection - sendFormated("AT+UPSDA=" PROFILE ",3\r\n"); - if (RESP_OK == waitFinalResp(NULL,NULL,150*1000)) - return true; - } - } - return false; -} - -bool MDMParser::_activateProfileReuseExternal(void) -{ - int cid = -1; - sendFormated("AT+CGDCONT?\r\n"); - if (RESP_OK != waitFinalResp(_cbCGDCONT, &cid)) - return false; - if (cid == -1) - return false; - // we found a context that provides us a valid IP so lets reuse it for the internal IP stack - sendFormated("AT+UPSD=" PROFILE ",100,%d\r\n", cid); - if (RESP_OK != waitFinalResp()) - return false; - // Activate the profile and make connection - sendFormated("AT+UPSDA=" PROFILE ",3\r\n"); - return (RESP_OK == waitFinalResp(NULL,NULL,150*1000)); -} - -bool MDMParser::_activateProfileByCid(int cid, const char* apn, const char* username, const char* password, Auth auth) -{ - sendFormated("AT+CGDCONT=%d,\"IP\",\"%s\"\r\n", cid, apn); - if (RESP_OK != waitFinalResp()) - return false; - sendFormated("AT+UAUTHREQ=%d,%d,\"%s\",\"%s\"\r\n", cid, auth, username, password); - if (RESP_OK != waitFinalResp()) - return false; - sendFormated("AT+UPSD=" PROFILE ",100,%d\r\n", cid); - if (RESP_OK != waitFinalResp()) - return false; - // Activate the profile and make connection - sendFormated("AT+UPSDA=" PROFILE ",3\r\n"); - return (RESP_OK == waitFinalResp(NULL,NULL,150*1000)); -} - -int MDMParser::_cbCGDCONT(int type, const char* buf, int len, int* cid) -{ - // accept with and without leading \r\n in +CGDCONT: - if ((type == TYPE_PLUS) && (buf[0] == '\r') && (buf[1] == '\n') && (len >= 2)) - buf += 2, len -= 2, type = TYPE_UNKNOWN; - if (type == TYPE_UNKNOWN) { - int a,b,c,d,t; - //+CGDCONT: <cid>,"IP","<apn name>","<ip adr>",0,0,0,0,0,0 - if (sscanf(buf, "+CGDCONT: %d,\"IP\",\"%*[^\"]\",\"" IPSTR "\",%*d,%*d,%*d,%*d,%*d,%*d", &t, &a,&b,&c,&d) == 5) { - if (IPADR(a,b,c,d) != NOIP) - *cid = t; - } - } - return WAIT; -} - -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_C2) { - // make a dumy dns lookup (which will fail, so ignore the result) - sendFormated("AT+UDNSRN=0,\"u-blox.com\"\r\n"); - waitFinalResp(); - // This fake lookup will enable the IP connection and we - // should have an IP after this, so we check it - - //Get local IP address - sendFormated("AT+CMIP?\r\n"); - if (RESP_OK != waitFinalResp(_cbCMIP, &_ip)) - goto failure; - - } else { - // check gprs attach status - sendFormated("AT+CGATT=1\r\n"); - if (RESP_OK != waitFinalResp(NULL,NULL,3*60*1000)) - goto failure; - // Check the profile - int a = 0; - bool force = true; - sendFormated("AT+UPSND=" PROFILE ",8\r\n"); - if (RESP_OK != waitFinalResp(_cbUPSND, &a)) - 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)) - goto failure; - a = 0; - } - if (a == 0) { - bool ok = false; - // try to lookup the apn settings from our local database by mccmnc - const char* config = NULL; - if (!apn && !username && !password) - config = apnconfig(_dev.imsi); - do { - if (config) { - apn = _APN_GET(config); - username = _APN_GET(config); - password = _APN_GET(config); - } - // convert pointer to empty strings - apn = apn ? apn : ""; - username = username ? username : ""; - password = password ? password : ""; - auth = (*username && *password) ? auth : AUTH_NONE; - TRACE("Testing APN Settings(\"%s\",\"%s\",\"%s\",%d)\r\n", apn, username, password, auth); - if ((_dev.dev != DEV_TOBY_L2) && (_dev.dev != DEV_MPCI_L2)) - ok = _activateProfile(apn, username, password, auth); - else { - ok = _activateProfileReuseExternal(); - if (ok) - TRACE("Reusing External Context\r\n"); - else - ok = _activateProfileByCid(1, apn, username, password, auth); - } - } while (!ok && config && *config); // maybe use next setting ? - if (!ok) { - ERROR("Your modem APN/password/username may be wrong\r\n"); - goto failure; - } - } - //Get local IP address - sendFormated("AT+UPSND=" PROFILE ",0\r\n"); - if (RESP_OK != waitFinalResp(_cbUPSND, &_ip)) - goto failure; - } - UNLOCK(); - return _ip; -failure: - unlock(); - return NOIP; -} - -int MDMParser::_cbUDOPN(int type, const char* buf, int len, char* mccmnc) -{ - if ((type == TYPE_PLUS) && mccmnc) { - if (sscanf(buf, "\r\n+UDOPN: 0,\"%[^\"]\"", mccmnc) == 1) - ; - } - return WAIT; -} - -int MDMParser::_cbCMIP(int type, const char* buf, int len, IP* ip) -{ - if ((type == TYPE_UNKNOWN) && ip) { - int a,b,c,d; - if (sscanf(buf, "\r\n" 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) -{ - bool ok = false; - LOCK(); - INFO("Modem::disconnect\r\n"); - if (_ip != NOIP) { - if (_dev.dev == DEV_LISA_C2) { - // 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; - } - } - } - UNLOCK(); - return ok; -} - -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 { - LOCK(); - sendFormated("AT+UDNSRN=0,\"%s\"\r\n", host); - if (RESP_OK != waitFinalResp(_cbUDNSRN, &ip)) - ip = NOIP; - UNLOCK(); - } - return ip; -} - -// ---------------------------------------------------------------- -// sockets - -int MDMParser::_cbUSOCR(int type, const char* buf, int len, int* handle) -{ - if ((type == TYPE_PLUS) && handle) { - // +USOCR: socket - if (sscanf(buf, "\r\n+USOCR: %d", handle) == 1) - /*nothing*/; - } - return WAIT; -} - -int MDMParser::socketSocket(IpProtocol ipproto, int port) -{ - int socket; - LOCK(); - // find an free socket - socket = _findSocket(); - TRACE("socketSocket(%d)\r\n", ipproto); - if (socket != SOCKET_ERROR) { - if (ipproto == IPPROTO_UDP) { - // sending port can only be set on 2G/3G modules - if ((port != -1) && (_dev.dev != DEV_LISA_C2)) { - sendFormated("AT+USOCR=17,%d\r\n", port); - } else { - sendFormated("AT+USOCR=17\r\n"); - } - } else /*(ipproto == IPPROTO_TCP)*/ { - sendFormated("AT+USOCR=6\r\n"); - } - int handle = SOCKET_ERROR; - if ((RESP_OK == waitFinalResp(_cbUSOCR, &handle)) && - (handle != SOCKET_ERROR)) { - TRACE("Socket %d: handle %d was created\r\n", socket, handle); - _sockets[socket].handle = handle; - _sockets[socket].timeout_ms = TIMEOUT_BLOCKING; - _sockets[socket].connected = false; - _sockets[socket].pending = 0; - } - else - socket = SOCKET_ERROR; - } - UNLOCK(); - return socket; -} - -bool MDMParser::socketConnect(int socket, const char * host, int port) -{ - IP ip = gethostbyname(host); - if (ip == NOIP) - return false; - // connect to socket - bool ok = false; - LOCK(); - if (ISSOCKET(socket) && (!_sockets[socket].connected)) { - TRACE("socketConnect(%d,%s,%d)\r\n", socket,host,port); - sendFormated("AT+USOCO=%d,\"" IPSTR "\",%d\r\n", _sockets[socket].handle, IPNUM(ip), port); - if (RESP_OK == waitFinalResp()) - ok = _sockets[socket].connected = true; - } - UNLOCK(); - return ok; -} - -bool MDMParser::socketIsConnected(int socket) -{ - bool ok = false; - LOCK(); - ok = ISSOCKET(socket) && _sockets[socket].connected; - TRACE("socketIsConnected(%d) %s\r\n", socket, ok?"yes":"no"); - 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)) { - _sockets[socket].timeout_ms = timeout_ms; - ok = true; - } - UNLOCK(); - return ok; -} - -bool MDMParser::socketClose(int socket) -{ - bool ok = false; - LOCK(); - if (ISSOCKET(socket) && _sockets[socket].connected) { - TRACE("socketClose(%d)\r\n", socket); - sendFormated("AT+USOCL=%d\r\n", _sockets[socket].handle); - if (RESP_OK == waitFinalResp()) { - _sockets[socket].connected = false; - ok = true; - } - } - UNLOCK(); - return ok; -} - -bool MDMParser::socketFree(int socket) -{ - // make sure it is closed - socketClose(socket); - bool ok = true; - LOCK(); - if (ISSOCKET(socket)) { - TRACE("socketFree(%d)\r\n", socket); - _sockets[socket].handle = SOCKET_ERROR; - _sockets[socket].timeout_ms = TIMEOUT_BLOCKING; - _sockets[socket].connected = false; - _sockets[socket].pending = 0; - ok = true; - } - UNLOCK(); - return ok; -} - -#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; - bool ok = false; - LOCK(); - if (ISSOCKET(socket)) { - sendFormated("AT+USOWR=%d,%d\r\n",_sockets[socket].handle,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; - } - 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; - bool ok = false; - LOCK(); - if (ISSOCKET(socket)) { - sendFormated("AT+USOST=%d,\"" IPSTR "\",%d,%d\r\n",_sockets[socket].handle,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; - } - return (len - cnt); -} - -int MDMParser::socketReadable(int socket) -{ - int pending = SOCKET_ERROR; - LOCK(); - if (ISSOCKET(socket) && _sockets[socket].connected) { - TRACE("socketReadable(%d)\r\n", socket); - // allow to receive unsolicited commands - waitFinalResp(NULL, NULL, 0); - if (_sockets[socket].connected) - pending = _sockets[socket].pending; - } - UNLOCK(); - return 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); -#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 (len < blk) blk = len; - bool ok = false; - LOCK(); - if (ISSOCKET(socket)) { - if (_sockets[socket].connected) { - if (_sockets[socket].pending < blk) - blk = _sockets[socket].pending; - if (blk > 0) { - sendFormated("AT+USORD=%d,%d\r\n",_sockets[socket].handle, 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 { - len = 0; - ok = true; - } - } - UNLOCK(); - if (!ok) { - TRACE("socketRecv: ERROR\r\n"); - return SOCKET_ERROR; - } - } - TRACE("socketRecv: %d \"%*s\"\r\n", cnt, cnt, buf-cnt); - 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; - 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; - } - } - 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); -#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 (len < blk) blk = len; - 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",_sockets[socket].handle, 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; - } - } - UNLOCK(); - if (!ok) { - TRACE("socketRecv: ERROR\r\n"); - return SOCKET_ERROR; - } - } - timer.stop(); - timer.reset(); - TRACE("socketRecv: %d \"%*s\"\r\n", cnt, cnt, buf-cnt); - return cnt; -} - -int MDMParser::_findSocket(int handle) { - for (int socket = 0; socket < NUMSOCKETS; socket ++) { - if (_sockets[socket].handle == handle) - return socket; - } - return SOCKET_ERROR; -} - -// ---------------------------------------------------------------- -// HTTP - -int MDMParser::httpFindProfile() -{ - int profile = HTTP_PROF_ERROR; //default value - LOCK(); - // find a free HTTP profile - profile = _findProfile(); - TRACE("httpFindProfile: profile is %d\r\n", profile); - if (profile != HTTP_PROF_ERROR) { - _httpProfiles[profile].handle = 1; - _httpProfiles[profile].timeout_ms = TIMEOUT_BLOCKING; - _httpProfiles[profile].pending = false; - _httpProfiles[profile].cmd = -1; - _httpProfiles[profile].result = -1; - } - UNLOCK(); - return profile; -} - -int MDMParser::_findProfile(int handle) { - for (int profile = 0; profile < NUMPROFILES; profile++) { - if (_httpProfiles[profile].handle == handle) - return profile; - } - return HTTP_PROF_ERROR; -} - -bool MDMParser::httpSetBlocking(int profile, int timeout_ms) -{ - bool ok = false; - LOCK(); - TRACE("httpSetBlocking(%d,%d)\r\n", profile, timeout_ms); - if (ISPROFILE(profile)) { - _httpProfiles[profile].timeout_ms = timeout_ms; - ok = true; - } - UNLOCK(); - return ok; -} - -bool MDMParser::httpSetProfileForCmdMng(int profile) -{ - bool ok = false; - LOCK(); - TRACE("httpSetProfileForCmdMng(%d)\r\n", profile); - if (ISPROFILE(profile)) { - _httpProfiles[profile].pending = true; - _httpProfiles[profile].result = -1; - ok = true; - } - UNLOCK(); - return ok; -} - -bool MDMParser::httpFreeProfile(int profile) -{ - bool ok = true; - LOCK(); - if (ISPROFILE(profile)) { - TRACE("httpFreeProfile(%d)\r\n", profile); - _httpProfiles[profile].handle = HTTP_PROF_ERROR; - _httpProfiles[profile].timeout_ms = TIMEOUT_BLOCKING; - _httpProfiles[profile].pending = false; - _httpProfiles[profile].cmd = -1; - _httpProfiles[profile].result = -1; - ok = true; - } - UNLOCK(); - return ok; -} - -bool MDMParser::httpResetProfile(int httpProfile) -{ - bool ok = false; - - LOCK(); - TRACE("httpResetProfile(%d)\r\n", httpProfile); - sendFormated("AT+UHTTP=%d\r\n", httpProfile); - if (RESP_OK == waitFinalResp()) - ok = true; - UNLOCK(); - - return ok; -} - -bool MDMParser::httpSetPar(int httpProfile, HttpOpCode httpOpCode, const char * httpInPar) -{ - bool ok = false; - IP ip = NOIP; - int httpInParNum = 0; - - LOCK(); - TRACE("httpSetPar(%d,%d,\"%s\")\r\n", httpProfile, httpOpCode, httpInPar); - switch(httpOpCode){ - case HTTP_IP_ADDRESS: //0 - ip = gethostbyname(httpInPar); - if (ip == NOIP) - return false; - - sendFormated("AT+UHTTP=%d,%d,\"" IPSTR "\"\r\n", httpProfile, httpOpCode, IPNUM(ip)); - if (RESP_OK == waitFinalResp()) - ok = true; - break; - - case HTTP_SERVER_NAME: //1 - case HTTP_USER_NAME: //2 - case HTTP_PASSWORD: //3 - sendFormated("AT+UHTTP=%d,%d,\"%s\"\r\n", httpProfile, httpOpCode, httpInPar); - if (RESP_OK == waitFinalResp()) - ok = true; - break; - - case HTTP_AUTH_TYPE: //4 - case HTTP_SERVER_PORT: //5 - httpInParNum = atoi(httpInPar); - sendFormated("AT+UHTTP=%d,%d,%d\r\n", httpProfile, httpOpCode, httpInParNum); - if (RESP_OK == waitFinalResp()) - ok = true; - break; - - case HTTP_SECURE: //6 - if(_dev.dev != DEV_LISA_C2) - { - httpInParNum = atoi(httpInPar); - sendFormated("AT+UHTTP=%d,%d,%d\r\n", httpProfile, httpOpCode, httpInParNum); - if (RESP_OK == waitFinalResp()) - ok = true; - } else { - TRACE("httpSetPar: HTTP secure option not supported by module\r\n"); - ok = false; - } - break; - - default: - TRACE("httpSetPar: unknown httpOpCode %s\r\n", httpOpCode); - ok = false; - break; - } - UNLOCK(); - return ok; -} - -bool MDMParser::httpCommand(int httpProfile, HttpCmd httpCmdCode, const char* httpPath, const char* httpOut, \ - const char* httpIn, int httpContentType, const char* httpCustomPar, char* buf, int len) -{ - bool ok = false; -#ifdef MDM_DEBUG - memset(buf, '\0', len); -#endif - LOCK(); - TRACE("%s\r\n", getHTTPcmd(httpCmdCode)); - switch (httpCmdCode) - { - case HTTP_HEAD: - sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\"\r\n", httpProfile, HTTP_HEAD, httpPath, httpOut); - break; - - case HTTP_GET: - sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\"\r\n", httpProfile, HTTP_GET, httpPath, httpOut); - break; - - case HTTP_DELETE: - sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\"\r\n", httpProfile, HTTP_DELETE, httpPath, httpOut); - break; - - case HTTP_PUT: - //in this case the parameter httpIn is a filename - sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\"\r\n", httpProfile, HTTP_PUT, httpPath, httpOut, httpIn); - break; - - case HTTP_POST_FILE: - //in this case the parameter httpIn is a filename - if(_dev.dev != DEV_LISA_C2) - { - if(httpContentType != 6) - sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \ - httpProfile, HTTP_POST_FILE, httpPath, httpOut, httpIn, httpContentType); - else - sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d,%d\r\n", \ - httpProfile, HTTP_POST_FILE, httpPath, httpOut, httpIn, httpContentType, httpCustomPar); - } - else{ - if((httpContentType != 5) && (httpContentType != 6) && (httpCustomPar == NULL)) - { - //parameters values consistent with the AT commands specs of LISA-C200 - //(in particular httpCustomPar has to be not defined) - sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \ - httpProfile, HTTP_POST_FILE, httpPath, httpOut, httpIn, httpContentType); - } else { - TRACE("httpCommand: command not supported by module"); - return ok; //error - } - } - break; - - case HTTP_POST_DATA: - //in this case the parameter httpIn is a string containing data - if(_dev.dev != DEV_LISA_C2) - { - if(httpContentType != 6) - sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \ - httpProfile, HTTP_POST_DATA, httpPath, httpOut, httpIn, httpContentType); - else - sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d,%d\r\n", \ - httpProfile, HTTP_POST_DATA, httpPath, httpOut, httpIn, httpContentType, httpCustomPar); - } else { - if((httpContentType != 5) && (httpContentType != 6) && (httpCustomPar == NULL)) - { - //parameters values consistent with the AT commands specs of LISA-C200 - //(in particular httpCustomPar has to be not defined) - sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \ - httpProfile, HTTP_POST_DATA, httpPath, httpOut, httpIn, httpContentType); - } else { - TRACE("httpCommand: command not supported by module"); - return ok; //error - } - } - break; - - default: - TRACE("HTTP command not recognized\r\n"); - return ok; //error - } - - if (RESP_OK == waitFinalResp()) - { - Timer timer; - timer.start(); - httpSetProfileForCmdMng(httpProfile); - while (_httpProfiles[httpProfile].pending) //waiting for unsolicited - { - ok = false; //reset variable - if(_httpProfiles[httpProfile].result != -1) - { - //received unsolicited: starting its analysis - _httpProfiles[httpProfile].pending = false; - if(_httpProfiles[httpProfile].result == 1) - { - //HTTP command successfully executed - if(_dev.dev != DEV_LISA_C2) - { - TRACE("httpCommand: reading files with a dimension " \ - "also greater than MAX_SIZE bytes\r\n"); - if(readFileNew(httpOut,buf,len) >=0 ) - ok = true; - } else { - TRACE("httpCommand: reading files with a dimension " \ - "less than MAX_SIZE bytes, otherwise error\r\n"); - if(readFile(httpOut,buf,len) >=0 ) - ok = true; - } - } else { - //HTTP command not successfully executed - ok = false; - } - } else if (!TIMEOUT(timer, _httpProfiles[httpProfile].timeout_ms)) { - ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs - } else { - //not received unsolicited and expired timer - TRACE("httpCommand: not received unsolicited and expired timer\r\n"); - ok = false; - } - if (!ok) { - TRACE("%s: ERROR\r\n", getHTTPcmd(httpCmdCode)); - _httpProfiles[httpProfile].pending = false; //no more while loops - } - } - } - UNLOCK(); - return ok; -} - -const char* MDMParser::getHTTPcmd(int httpCmdCode) -{ - switch (httpCmdCode) - { - case HTTP_HEAD: - return "HTTP HEAD command"; - case HTTP_GET: - return "HTTP GET command"; - case HTTP_DELETE: - return "HTTP DELETE command"; - case HTTP_PUT: - return "HTTP PUT command"; - case HTTP_POST_FILE: - return "HTTP POST file command"; - case HTTP_POST_DATA: - return "HTTP POST data command"; - default: - return "HTTP command not recognized"; - } -} - -// ---------------------------------------------------------------- - -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*/) { - 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)) - 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)) { - send(buf, strlen(buf)); - const char ctrlZ = 0x1A; - send(&ctrlZ, sizeof(ctrlZ)); - ok = (RESP_OK == waitFinalResp()); - } - UNLOCK(); - return ok; -} - -bool MDMParser::smsDelete(int ix) -{ - bool ok = false; - LOCK(); - sendFormated("AT+CMGD=%d\r\n",ix); - ok = (RESP_OK == waitFinalResp()); - UNLOCK(); - return ok; -} - -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) -{ - bool ok = false; - LOCK(); - CMGRparam param; - param.num = num; - param.buf = buf; - sendFormated("AT+CMGR=%d\r\n",ix); - ok = (RESP_OK == waitFinalResp(_cbCMGR, ¶m)); - UNLOCK(); - return ok; -} - -// ---------------------------------------------------------------- - -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) -{ - bool ok = false; - LOCK(); - *buf = '\0'; - if (_dev.dev != DEV_LISA_C2) { - sendFormated("AT+CUSD=1,\"%s\"\r\n",cmd); - ok = (RESP_OK == waitFinalResp(_cbCUSD, buf)); - } - UNLOCK(); - return ok; -} - -// ---------------------------------------------------------------- - -int MDMParser::_cbUDELFILE(int type, const char* buf, int len, void*) -{ - if ((type == TYPE_ERROR) && strstr(buf, "+CME ERROR: FILE NOT FOUND")) - return RESP_OK; // file does not exist, so all ok... - return WAIT; -} - -bool MDMParser::delFile(const char* filename) -{ - bool ok = false; - LOCK(); - sendFormated("AT+UDELFILE=\"%s\"\r\n", filename); - ok = (RESP_OK == waitFinalResp(_cbUDELFILE)); - 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()) { - send(buf, len); - ok = (RESP_OK == waitFinalResp()); - } - UNLOCK(); - return ok ? len : -1; -} - -int MDMParser::readFile(const char* filename, char* buf, int len) -{ - URDFILEparam param; - param.filename = filename; - param.buf = buf; - param.sz = len; - param.len = 0; - LOCK(); - sendFormated("AT+URDFILE=\"%s\"\r\n", filename, len); - if (RESP_OK != waitFinalResp(_cbURDFILE, ¶m)) - param.len = -1; - UNLOCK(); - return param.len; -} - -int MDMParser::_cbURDFILE(int type, const char* buf, int len, URDFILEparam* param) -{ - if ((type == TYPE_PLUS) && param && param->filename && param->buf) { - char filename[48]; - int sz; - if ((sscanf(buf, "\r\n+URDFILE: \"%[^\"]\",%d,", filename, &sz) == 2) && - (0 == strcmp(param->filename, filename)) && - (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) { - param->len = (sz < param->sz) ? sz : param->sz; - memcpy(param->buf, &buf[len-1-sz], param->len); - } - } - return WAIT; -} - -//The following function is useful for reading files with a dimension greater than MAX_SIZE bytes -int MDMParser::readFileNew(const char* filename, char* buf, int len) -{ - int countBytes = -1; //counter for file reading (default value) - - if(_dev.dev != DEV_LISA_C2) - { - //retrieve information about the file, in particular its size - int filesize = infoFile(filename); - TRACE("readFileNew: filename is %s; filesize is %d\r\n", filename, filesize); - - if (len < filesize) - TRACE("readFileNew: WARNING. Buffer dimension is %d bytes," \ - "while file size is %d bytes\r\n", len, filesize); - - if (filesize > 0) - { -#ifdef MDM_DEBUG - memset(buf, '\0', len); -#endif - int offset = 0; //start reading from 0 - int blockSize = MAX_SIZE; //still need space for headers and unsolicited commands - int bytesToRead = filesize; //bytes to read - - while (bytesToRead) - { - bool ok = false; - - if (bytesToRead < blockSize) - blockSize = bytesToRead; - - LOCK(); - if (blockSize > 0) { - - sendFormated("AT+URDBLOCK=\"%s\",%d,%d\r\n", filename, offset, blockSize); - - if (RESP_OK == waitFinalResp(_cbURDBLOCK, buf)) { - bytesToRead -= blockSize; - offset += blockSize; - buf += blockSize; - ok = true; - } else { - //error condition - countBytes = -1; - ok = false; - } - } - UNLOCK(); - - if (!ok) { - TRACE("readFileNew: ERROR\r\n"); - return countBytes; //in this case countBytes is -1 - } - } - - countBytes = offset; //total read bytes - return countBytes; - } - } else { - TRACE("httpCommand: command not supported by module"); - } - return countBytes; //it could be 0 or -1 (possible error) -} - -int MDMParser::_cbURDBLOCK(int type, const char* buf, int len, char* out) -{ - char fileNameRes[48]; - int sizeRes; - - if ((type == TYPE_PLUS) && out) { - if ((sscanf(buf, "\r\n+URDBLOCK: \"%[^\"]\",%d,", fileNameRes, &sizeRes) == 2) && - (buf[len-sizeRes-2] == '\"') && (buf[len-1] == '\"')) { - memcpy(out, &buf[len-1-sizeRes], sizeRes); - } - } - - return WAIT; -} - -int MDMParser::infoFile(const char* filename) -{ - int infoFile = 0; //default value - - LOCK(); - sendFormated("AT+ULSTFILE=2,\"%s\"\r\n", filename); - if (RESP_OK != waitFinalResp(_cbULSTFILE, &infoFile)) - infoFile = -1; //error condition - UNLOCK(); - - return infoFile; -} - -int MDMParser::_cbULSTFILE(int type, const char* buf, int len, int* infoFile) -{ - if (infoFile) { - if (type == TYPE_PLUS) { - if (sscanf(buf, "\r\n+ULSTFILE: %d\r\n", infoFile) == 1) { - } - } - } - return WAIT; -} - -// ---------------------------------------------------------------- -int MDMParser::cellLocSrvTcp(const char* token, const char* server_1, const char* server_2, int days/* = 14*/, \ - int period/* = 4*/, int resolution/* = 1*/) -{ - bool ok = false; - LOCK(); - if (_dev.dev == DEV_LISA_U2_03S || _dev.dev == DEV_SARA_U2 ){ - sendFormated("AT+UGSRV=\"%s\",\"%s\",\"%s\"\r\n", server_1, server_2, token, days, period, resolution); - ok = (RESP_OK == waitFinalResp()); - } else - ERROR("Command not supported\r\n"); - UNLOCK(); - return ok; -} - -int MDMParser::cellLocSrvUdp(const char* server_1 /*= "cell-live1.services.u-blox.com"*/, int port /*= 46434*/, \ - int latency/* = 1000*/, int mode/* = 0*/) -{ - bool ok = false; - LOCK(); - if (_dev.dev != DEV_TOBY_L2){ - sendFormated("AT+UGAOP=\"%s\",%d,%d,%d\r\n", server_1, port, latency, mode); - ok = (RESP_OK == waitFinalResp()); - } else - ERROR("Command not supported\r\n"); - UNLOCK(); - return ok; -} - -int MDMParser::cellLocUnsol(int mode) -{ - bool ok = false; - LOCK(); - if (_dev.dev == DEV_LISA_U2_03S){ - sendFormated("AT+ULOCIND=%d\r\n", mode); - ok = (RESP_OK == waitFinalResp()); - } else - ERROR("Command not supported\r\n"); - UNLOCK(); - return ok; -} - -int MDMParser::cellLocConfig(int scanMode) -{ - bool ok = false; - LOCK(); - if (_dev.dev != DEV_TOBY_L2){ - sendFormated("AT+ULOCCELL=%d\r\n", scanMode); - ok = (RESP_OK == waitFinalResp()); - }else - ERROR("Command not supported\r\n"); - UNLOCK(); - return ok; -} - -int MDMParser::cellLocRequest(CellSensType sensor, int timeout, int accuracy, CellRespType type/* =1*/, int hypotesis/* =1*/) -{ - bool ok = false; - - if (hypotesis > 1 && type != CELL_MULTIHYP){ - ERROR("Num hypotesis is not set accordelying to CellRespType\r\n"); - return false; - } - if (hypotesis > CELL_MAX_HYP){ - ERROR("Number of hypotesis is too big\r\n"); - return false; - } - LOCK(); - _locRcvPos=0; - _locExpPos=0; - for (int i=0; i < hypotesis; i++) - _loc[i].validData = false; - if (_dev.dev == DEV_LISA_U2_03S){ - sendFormated("AT+ULOC=2,%d,%d,%d,%d,%d\r\n", sensor, type, timeout, accuracy, hypotesis); - ok = (RESP_OK == waitFinalResp()); - } else if (_dev.dev != DEV_TOBY_L2){ - sendFormated("AT+ULOC=2,%d,1,%d,%d\r\n", sensor, timeout, accuracy); - ok = (RESP_OK == waitFinalResp()); - } else - ERROR("Command not supported\r\n"); - UNLOCK(); - return ok; -} -int MDMParser::cellLocGetRes() -{ - return _locRcvPos; -} -int MDMParser::cellLocGetExpRes() -{ - int res=0; - waitFinalResp(NULL,NULL,0); - LOCK(); - if (_locRcvPos>0) - res = _locExpPos; - UNLOCK(); - return res; -} - -int MDMParser::cellLocGetData(CellLocData *data, int index/*=0*/){ - - if (!_loc[index].validData) - return false; - LOCK(); - memcpy(data, &_loc[index], sizeof(*_loc)); - UNLOCK(); - return true; -} - -// ---------------------------------------------------------------- -bool MDMParser::setDebug(int level) -{ -#ifdef MDM_DEBUG - _debugLevel = (level < -1) ? -1 : - (level > 3) ? 3 : - level; -#endif - return _debugLevel == level; -} - -void MDMParser::dumpDevStatus(MDMParser::DevStatus* status, - _DPRINT dprint, void* param) -{ - dprint(param, "Modem::devStatus\r\n"); - const char* txtDev[] = { "Unknown", "SARA-G35", "LISA-U2", "LISA-U2-03S", "LISA-C2", - "SARA-U2", "LEON-G2", "TOBY-L2", "MPCI-L2" }; - if (status->dev < sizeof(txtDev)/sizeof(*txtDev) && (status->dev != DEV_UNKNOWN)) - dprint(param, " Device: %s\r\n", txtDev[status->dev]); - const char* txtLpm[] = { "Disabled", "Enabled", "Active" }; - if (status->lpm < sizeof(txtLpm)/sizeof(*txtLpm)) - dprint(param, " Power Save: %s\r\n", txtLpm[status->lpm]); - const char* txtSim[] = { "Unknown", "Missing", "Pin", "Ready" }; - if (status->sim < sizeof(txtSim)/sizeof(*txtSim) && (status->sim != SIM_UNKNOWN)) - dprint(param, " SIM: %s\r\n", txtSim[status->sim]); - if (*status->ccid) - dprint(param, " CCID: %s\r\n", status->ccid); - if (*status->imei) - dprint(param, " IMEI: %s\r\n", status->imei); - if (*status->imsi) - dprint(param, " IMSI: %s\r\n", status->imsi); - if (*status->meid) - dprint(param, " MEID: %s\r\n", status->meid); // LISA-C - if (*status->manu) - dprint(param, " Manufacturer: %s\r\n", status->manu); - if (*status->model) - dprint(param, " Model: %s\r\n", status->model); - if (*status->ver) - dprint(param, " Version: %s\r\n", status->ver); -} - -void MDMParser::dumpNetStatus(MDMParser::NetStatus *status, - _DPRINT dprint, void* param) -{ - dprint(param, "Modem::netStatus\r\n"); - const char* txtReg[] = { "Unknown", "Denied", "None", "Home", "Roaming" }; - if (status->csd < sizeof(txtReg)/sizeof(*txtReg) && (status->csd != REG_UNKNOWN)) - dprint(param, " CSD Registration: %s\r\n", txtReg[status->csd]); - if (status->psd < sizeof(txtReg)/sizeof(*txtReg) && (status->psd != REG_UNKNOWN)) - dprint(param, " PSD Registration: %s\r\n", txtReg[status->psd]); - if (status->eps < sizeof(txtReg)/sizeof(*txtReg) && (status->eps != REG_UNKNOWN)) - dprint(param, " EPS Registration: %s\r\n", txtReg[status->eps]); - const char* txtAct[] = { "Unknown", "GSM", "Edge", "3G", "CDMA", "LTE" }; - if (status->act < sizeof(txtAct)/sizeof(*txtAct) && (status->act != ACT_UNKNOWN)) - dprint(param, " Access Technology: %s\r\n", txtAct[status->act]); - if (status->rssi) - dprint(param, " Signal Strength: %d dBm\r\n", status->rssi); - if (status->ber) - dprint(param, " Bit Error Rate: %d\r\n", status->ber); - if (*status->opr) - dprint(param, " Operator: %s\r\n", status->opr); - if (status->lac != 0xFFFF) - dprint(param, " Location Area Code: %04X\r\n", status->lac); - if (status->ci != 0xFFFFFFFF) - dprint(param, " Cell ID: %08X\r\n", status->ci); - if (*status->num) - dprint(param, " Phone Number: %s\r\n", status->num); -} - -void MDMParser::dumpIp(MDMParser::IP ip, - _DPRINT dprint, void* param) -{ - if (ip != NOIP) - dprint(param, "Modem:IP " IPSTR "\r\n", IPNUM(ip)); -} - -// ---------------------------------------------------------------- -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(); - } - } - else if (*fmt == 's') { - fmt ++; - if (ch != '\"') return NOT_FOUND; - do { - if (++o > len) return WAIT; - ch = pipe->next(); - } while (ch != '\"'); - 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 }, - { "\r\n+URDFILE: %s,%d,\"%c\"", TYPE_PLUS }, - { "\r\n+URDBLOCK: %s,%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_CME }, - { "\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 - { "\n>", NULL, TYPE_PROMPT }, // File - }; - 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 -// ---------------------------------------------------------------- - -/*! Helper Dev Null Device - Small helper class used to shut off stderr/stdout. Sometimes stdin/stdout - is shared with the serial port of the modem. Having printfs inbetween the - AT commands you cause a failure of the modem. -*/ -class DevNull : public Stream { -public: - DevNull() : Stream(_name+1) { } //!< Constructor - void claim(const char* mode, FILE* file) - { freopen(_name, mode, file); } //!< claim a stream -protected: - virtual int _getc() { return EOF; } //!< Nothing - virtual int _putc(int c) { return c; } //!< Discard - static const char* _name; //!< File name -}; -const char* DevNull::_name = "/null"; //!< the null device name -static DevNull null; //!< the null device - -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) -{ - if (rx == USBRX) - null.claim("r", stdin); - if (tx == USBTX) { - null.claim("w", stdout); - null.claim("w", stderr); -#ifdef MDM_DEBUG - _debugLevel = -1; -#endif - } -#ifdef TARGET_UBLOX_C027 - _onboard = (tx == MDMTXD) && (rx == MDMRXD); - if (_onboard) - c027_mdm_powerOn(false); -#endif - 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 -} - -MDMSerial::~MDMSerial(void) -{ - powerOff(); -#ifdef TARGET_UBLOX_C027 - if (_onboard) - c027_mdm_powerOff(); -#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 -MDMUsb::MDMUsb(void) -{ -#ifdef MDM_DEBUG - _debugLevel = 1; -#endif -#ifdef TARGET_UBLOX_C027 - _onboard = true; - c027_mdm_powerOn(true); -#endif -} - -MDMUsb::~MDMUsb(void) -{ - powerOff(); -#ifdef TARGET_UBLOX_C027 - if (_onboard) - c027_mdm_powerOff(); -#endif -} - -int MDMUsb::_send(const void* buf, int len) { return 0; } - -int MDMUsb::getLine(char* buffer, int length) { return NOT_FOUND; } - -#endif \ No newline at end of file
diff -r dafbbf31bf76 -r 5df09023c4e9 MDM.h --- a/MDM.h Thu Feb 25 13:22:34 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,867 +0,0 @@ -#pragma once - -#include "mbed.h" -#include <stdarg.h> - -#include "Pipe.h" -#include "SerialPipe.h" - -#ifdef TARGET_UBLOX_C027 - // you can change this is you like to use a shield even on the C027 - #define MDM_IF(onboard,shield) onboard -#else - #define MDM_IF(onboard,shield) shield -#endif - -//! include debug capabilty on more powerful targets with a dedicated debug port -#if defined(TARGET_LPC1768) || defined(TARGET_LPC4088) || defined(TARGET_K64F) - #define MDM_DEBUG -#endif - -/** basic modem parser class -*/ -class MDMParser -{ -public: - //! Constructor - MDMParser(void); - //! get static instance - static MDMParser* getInstance() { return inst; }; - - // ---------------------------------------------------------------- - // Types - // ---------------------------------------------------------------- - //! MT Device Types - typedef enum { DEV_UNKNOWN, - DEV_SARA_G35, DEV_LISA_U2, DEV_LISA_U2_03S, DEV_LISA_C2, - DEV_SARA_U2, DEV_LEON_G2, DEV_TOBY_L2, DEV_MPCI_L2 } Dev; - //! SIM Status - typedef enum { SIM_UNKNOWN, SIM_MISSING, SIM_PIN, SIM_PUK, SIM_READY, WRONG_PIN } Sim; - //! SIM Status - typedef enum { LPM_DISABLED, LPM_ENABLED, LPM_ACTIVE } Lpm; - //! COPS status - typedef enum { COPS_UNKOWN, COPS_AUTOMATIC_REG, COPS_MANUAL_REG, COPS_DISABLED_REG} CopsMode; - //! Device status - typedef struct { - Dev dev; //!< Device Type - Lpm lpm; //!< Power Saving - Sim sim; //!< SIM Card Status - char ccid[20+1]; //!< Integrated Circuit Card ID - char imsi[15+1]; //!< International Mobile Station Identity - char imei[15+1]; //!< International Mobile Equipment Identity - char meid[18+1]; //!< Mobile Equipment IDentifier - char manu[16]; //!< Manufacturer (u-blox) - char model[16]; //!< Model Name (LISA-U200, LISA-C200 or SARA-G350) - char ver[16]; //!< Software Version - } DevStatus; - //! Registration Status - typedef enum { REG_UNKNOWN, REG_DENIED, REG_NONE, REG_HOME, REG_ROAMING } Reg; - //! Access Technology - typedef enum { ACT_UNKNOWN, ACT_GSM, ACT_EDGE, ACT_UTRAN, ACT_CDMA, ACT_LTE } AcT; - //! Network Status - typedef struct { - Reg csd; //!< CSD Registration Status (Circuit Switched Data) - Reg psd; //!< PSD Registration status (Packet Switched Data) - Reg eps; //!< EPS Registration status - AcT act; //!< Access Technology - int rssi; //!< Received Signal Strength Indication (in dBm, range -113..-51) - int ber; //!< Bit Error Rate (BER), see 3GPP TS 45.008 [20] subclause 8.2.4 - char opr[16+1]; //!< Operator Name - char num[32]; //!< Mobile Directory Number - unsigned short lac; //!< location area code in hexadecimal format (2 bytes in hex) - unsigned int ci; //!< Cell ID in hexadecimal format (2 to 4 bytes in hex) - CopsMode regStatus; //!< Cops mode - } NetStatus; - typedef enum { CELL_LAST = 0, CELL_GNSS, CELL_LOCATE, CELL_HYBRID} CellSensType; - typedef enum { CELL_DETAILED = 1, CELL_MULTIHYP = 2} CellRespType; - #define CELL_MAX_HYP (16 + 1) - int _locRcvPos; //!< Received positions - int _locExpPos; //!< Expected positions - //! Cell Locate Data - typedef struct { - bool validData; //!< Flag for indicating if data is valid - struct tm time; //!< GPS Timestamp - float longitude; //!< Estimated longitude, in degrees - float latitude; //!< Estimated latitude, in degrees - int altitutude; //!< Estimated altitude, in meters^2 - int uncertainty; //!< Maximum possible error, in meters - int speed; //!< Speed over ground m/s^2 - int direction; //!< Course over ground in degrees - int verticalAcc; //!< Vertical accuracy, in meters^2 - CellSensType sensor; //!< Sensor used for last calculation - int svUsed; //!< number of satellite used - }CellLocData; - //! An IP v4 address - typedef uint32_t IP; - #define NOIP ((MDMParser::IP)0) //!< No IP address - // ip number formating and conversion - #define IPSTR "%d.%d.%d.%d" - #define IPNUM(ip) ((ip)>>24)&0xff, \ - ((ip)>>16)&0xff, \ - ((ip)>> 8)&0xff, \ - ((ip)>> 0)&0xff - #define IPADR(a,b,c,d) ((((IP)(a))<<24) | \ - (((IP)(b))<<16) | \ - (((IP)(c))<< 8) | \ - (((IP)(d))<< 0)) - - - // ---------------------------------------------------------------- - // Device - // ---------------------------------------------------------------- - - typedef enum { AUTH_NONE, AUTH_PAP, AUTH_CHAP, AUTH_DETECT } Auth; - - /** Combined Init, checkNetStatus, join suitable for simple applications - \param simpin a optional pin of the SIM card - \param apn the of the network provider e.g. "internet" or "apn.provider.com" - \param username is the user name text string for the authentication phase - \param password is the password text string for the authentication phase - \param auth is the authentication mode (CHAP,PAP,NONE or DETECT) - \return true if successful, false otherwise - */ - bool connect(const char* simpin = NULL, - const char* apn = NULL, const char* username = NULL, - const char* password = NULL, Auth auth = AUTH_DETECT, - PinName pn MDM_IF( = MDMPWRON, = D4)); - - /** register (Attach) the MT to the GPRS service. - \param simpin a optional pin of the SIM card - \param status an optional struture to with device information - \return true if successful, false otherwise - */ - virtual bool init(const char* simpin = NULL, DevStatus* status = NULL, - PinName pn MDM_IF( = MDMPWRON, = D4)); - - /** get the current device status - \param strocture holding the device information. - */ - void getDevStatus(MDMParser::DevStatus* dev) { memcpy(dev, &_dev, sizeof(DevStatus)); } - - /** register to the network - \param status an optional structure to with network information - \param timeout_ms -1 blocking, else non blocking timeout in ms - \return true if successful and connected to network, false otherwise - */ - bool registerNet(NetStatus* status = NULL, int timeout_ms = 180000); - - /** check if the network is available - \param status an optional structure to with network information - \return true if successful and connected to network, false otherwise - */ - bool checkNetStatus(NetStatus* status = NULL); - - /** Power off the MT, This function has to be called prior to - switching off the supply. - \return true if successfully, false otherwise - */ - bool powerOff(void); - - // ---------------------------------------------------------------- - // Data Connection (GPRS) - // ---------------------------------------------------------------- - - /** register (Attach) the MT to the GPRS service. - \param apn the of the network provider e.g. "internet" or "apn.provider.com" - \param username is the user name text string for the authentication phase - \param password is the password text string for the authentication phase - \param auth is the authentication mode (CHAP,PAP,NONE or DETECT) - \return the ip that is assigned - */ - MDMParser::IP join(const char* apn = NULL, const char* username = NULL, - const char* password = NULL, Auth auth = AUTH_DETECT); - - /** deregister (detach) the MT from the GPRS service. - \return true if successful, false otherwise - */ - bool disconnect(void); - - /** Translates a domain name to an IP address - \param host the domain name to translate e.g. "u-blox.com" - \return the IP if successful, 0 otherwise - */ - MDMParser::IP gethostbyname(const char* host); - - /** get the current assigned IP address - \return the ip that is assigned - */ - MDMParser::IP getIpAddress(void) { return _ip; } - - // ---------------------------------------------------------------- - // Sockets - // ---------------------------------------------------------------- - - //! Type of IP protocol - typedef enum { IPPROTO_TCP, IPPROTO_UDP } IpProtocol; - - //! Socket error return codes - #define SOCKET_ERROR -1 - - /** Create a socket for a ip protocol (and optionaly bind) - \param ipproto the protocol (UDP or TCP) - \param port in case of UDP, this optional port where it is bind - \return the socket handle if successful or SOCKET_ERROR on failure - */ - int socketSocket(IpProtocol ipproto, int port = -1); - - /** make a socket connection - \param socket the socket handle - \param host the domain name to connect e.g. "u-blox.com" - \param port the port to connect - \return true if successfully, false otherwise - */ - bool socketConnect(int socket, const char* host, int port); - - /** make a socket connection - \param socket the socket handle - \return true if connected, false otherwise - */ - bool socketIsConnected(int socket); - - /** Get the number of bytes pending for reading for this socket - \param socket the socket handle - \param timeout_ms -1 blocking, else non blocking timeout in ms - \return 0 if successful or SOCKET_ERROR on failure - */ - bool socketSetBlocking(int socket, int timeout_ms); - - /** Write socket data - \param socket the socket handle - \param buf the buffer to write - \param len the size of the buffer to write - \return the size written or SOCKET_ERROR on failure - */ - int socketSend(int socket, const char * buf, int len); - - /** Write socket data to a IP - \param socket the socket handle - \param ip the ip to send to - \param port the port to send to - \param buf the buffer to write - \param len the size of the buffer to write - \return the size written or SOCKET_ERROR on failure - */ - int socketSendTo(int socket, IP ip, int port, const char * buf, int len); - - /** Get the number of bytes pending for reading for this socket - \param socket the socket handle - \return the number of bytes pending or SOCKET_ERROR on failure - */ - int socketReadable(int socket); - - /** Read this socket - \param socket the socket handle - \param buf the buffer to read into - \param len the size of the buffer to read into - \return the number of bytes read or SOCKET_ERROR on failure - */ - int socketRecv(int socket, char* buf, int len); - - /** Read from this socket - \param socket the socket handle - \param ip the ip of host where the data originates from - \param port the port where the data originates from - \param buf the buffer to read into - \param len the size of the buffer to read into - \return the number of bytes read or SOCKET_ERROR on failure - */ - int socketRecvFrom(int socket, IP* ip, int* port, char* buf, int len); - - /** Close a connectied socket (that was connected with #socketConnect) - \param socket the socket handle - \return true if successfully, false otherwise - */ - bool socketClose(int socket); - - /** Free the socket (that was allocated before by #socketSocket) - \param socket the socket handle - \return true if successfully, false otherwise - */ - bool socketFree(int socket); - - // ---------------------------------------------------------------- - // HTTP - // ---------------------------------------------------------------- - - //! Type of HTTP Operational Codes (reference to HTTP control +UHTTP) - typedef enum { HTTP_IP_ADDRESS, HTTP_SERVER_NAME, HTTP_USER_NAME, HTTP_PASSWORD, \ - HTTP_AUTH_TYPE, HTTP_SERVER_PORT, HTTP_SECURE } HttpOpCode; - - //! Type of HTTP Commands (reference to HTTP command +UHTTPC) - typedef enum { HTTP_HEAD, HTTP_GET, HTTP_DELETE, HTTP_PUT, \ - HTTP_POST_FILE, HTTP_POST_DATA } HttpCmd; - - //! HTTP Profile error return codes - #define HTTP_PROF_ERROR -1 - - /** find HTTP profile - \return true if successfully, false otherwise - */ - int httpFindProfile(); - - /** get the number of bytes pending for reading for this HTTP profile - \param profile the HTTP profile handle - \param timeout_ms -1 blocking, else non blocking timeout in ms - \return 0 if successful or SOCKET_ERROR on failure - */ - bool httpSetBlocking(int profile, int timeout_ms); - - /** set the HTTP profile for commands management - \param profile the HTTP profile handle - \return true if successfully, false otherwise - */ - bool httpSetProfileForCmdMng(int profile); - - /** free the HTTP profile - \param profile the HTTP profile handle - \return true if successfully, false otherwise - */ - bool httpFreeProfile(int profile); - - /** reset HTTP profile - \param httpProfile the HTTP profile to be reset - \return true if successfully, false otherwise - */ - bool httpResetProfile(int httpProfile); - - /** set HTTP parameters - \param httpProfile the HTTP profile identifier - \param httpOpCode the HTTP operation code - \param httpInPar the HTTP input parameter - \return true if successfully, false otherwise - */ - bool httpSetPar(int httpProfile, HttpOpCode httpOpCode, const char * httpInPar); - - /** HTTP commands management - \param httpProfile the HTTP profile identifier - \param httpCmdCode the HTTP command code - \param httpPath the path of HTTP server resource - \param httpOut the filename where the HTTP server response will be stored - \param httpIn the input data (filename or string) to be sent - to the HTTP server with the command request - \param httpContentType the HTTP Content-Type identifier - \param httpCustomPar the parameter for an user defined HTTP Content-Type - \param buf the buffer to read into - \param len the size of the buffer to read into - \return true if successfully, false otherwise - */ - bool httpCommand(int httpProfile, HttpCmd httpCmdCode, const char* httpPath, \ - const char* httpOut, const char* httpIn, int httpContentType, \ - const char* httpCustomPar, char* buf, int len); - - /** get HTTP commands - \param httpCmdCode the HTTP command code (reference also the enum format) - \return HTTP command in string format - */ - const char* getHTTPcmd(int httpCmdCode); - - // ---------------------------------------------------------------- - // SMS Short Message Service - // ---------------------------------------------------------------- - - /** count the number of sms in the device and optionally return a - list with indexes from the storage locations in the device. - \param stat what type of messages you can use use - "REC UNREAD", "REC READ", "STO UNSENT", "STO SENT", "ALL" - \param ix list where to save the storage positions - \param num number of elements in the list - \return the number of messages, this can be bigger than num, -1 on failure - */ - int smsList(const char* stat = "ALL", int* ix = NULL, int num = 0); - - /** Read a Message from a storage position - \param ix the storage position to read - \param num the originator address (~16 chars) - \param buf a buffer where to save the sm - \param len the length of the sm - \return true if successful, false otherwise - */ - bool smsRead(int ix, char* num, char* buf, int len); - - /** Send a message to a recipient - \param ix the storage position to delete - \return true if successful, false otherwise - */ - bool smsDelete(int ix); - - /** Send a message to a recipient - \param num the phone number of the recipient - \param buf the content of the message to sent - \return true if successful, false otherwise - */ - bool smsSend(const char* num, const char* buf); - - // ---------------------------------------------------------------- - // USSD Unstructured Supplementary Service Data - // ---------------------------------------------------------------- - - /** Read a Message from a storage position - \param cmd the ussd command to send e.g "*#06#" - \param buf a buffer where to save the reply - \return true if successful, false otherwise - */ - bool ussdCommand(const char* cmd, char* buf); - - // ---------------------------------------------------------------- - // FILE - // ---------------------------------------------------------------- - - /** Delete a file in the local file system - \param filename the name of the file - \return true if successful, false otherwise - */ - bool delFile(const char* filename); - - /** Write some data to a file in the local file system - \param filename the name of the file - \param buf the data to write - \param len the size of the data to write - \return the number of bytes written - */ - int writeFile(const char* filename, const char* buf, int len); - - /** Read a file from the local file system - \param filename the name of the file - \param buf a buffer to hold the data - \param len the size to read - \return the number of bytes read - */ - int readFile(const char* filename, char* buf, int len); - - /** Read a file from the local file system - (the file size is greater than MAX_SIZE bytes) - \param filename the name of the file - \param buf a buffer to hold the data - \param len the size to read - \return the number of bytes read - */ - int readFileNew(const char* filename, char* buf, int len); - - /** Retrieve information about the dimension of a file from the local FFS - \param filename the name of the file - \return the file dimension in number of bytes - */ - int infoFile(const char* filename); - - // ---------------------------------------------------------------- - // CellLocate - // ---------------------------------------------------------------- - - /** Configures CellLocate Tcp Aiding server - \server_1 Host name of the primary MGA server - \server_2 Host name of the secondary MGA server - \token Authentication Token for MGA server access - \days The number of days into the future the Offline data for the u-blox 7 - \period The number of weeks into the future the Offline data for u-blox M8 - \resolution Resolution of offline data for u-blox M8: 1 everyday, 0 every other day - */ - int cellLocSrvTcp(const char* token, const char* server_1 = "cell-live1.services.u-blox.com", \ - const char* server_2 = "cell-live2.services.u-blox.com", int days = 14, int period = 4, int resolution = 1); - - /** Configures CellLocate Udp Aiding server - \server_1 Host name of the primary MGA server - \port Server port - \latency Expected network latency in seconds from 0 to 10000ms - \mode Assist now management, mode of operation: 0 data downloaded at GNSS power up, - 1 automatically kept alive, manual download - */ - int cellLocSrvUdp(const char* server_1 = "cell-live1.services.u-blox.com", int port = 46434, int latency = 1000, int mode = 0); - - /** Configures CellLocate URCs in the case of +ULOC operations - \mode Urc configuration: 0 disabled, 1 enabled - */ - int cellLocUnsol(int mode); - - /** Configures CellLocate location sensor - \scanMode Network scan mode: 0 normal, 1 deep scan - */ - int cellLocConfig(int scanMode); - - /** Request CellLocate - This function is not blocking, the result has to be retrived using cellLocGet - \sensor Sensor selection: - \timeout Timeout period in seconds (1 - 999) - \accuracy Target accuracy in meters (1 - 999999) - \type - \hypotesis Maximum desired number of responses from CellLocate® (up to 16) - */ - int cellLocRequest(CellSensType sensor, int timeout, int accuracy, CellRespType type = CELL_DETAILED,int hypotesis = 1); - - /** Get a position record - \data pointer to a CellLocData struct where the location will be copied in - \index of the position to retrive - \return 1 if data has been retrived and copied, 0 otherwise - */ - int cellLocGetData(CellLocData *data, int index =0); - - /** Get number of position records received - \return number of position received - */ - int cellLocGetRes(); - /** Get expected number of position to be received - \return number of expected position to be received - */ - int cellLocGetExpRes(); - - // ---------------------------------------------------------------- - // DEBUG/DUMP status to standard out (printf) - // ---------------------------------------------------------------- - - /*! Set the debug level - \param level -1 = OFF, 0 = ERROR, 1 = INFO(default), 2 = TRACE, 3 = ATCMD,TEST - \return true if successful, false not possible - */ - bool setDebug(int level); - - //! helper type for DPRINT - typedef int (*_DPRINT)(void* param, char const * format, ...); - - //! helper to declate templates and void versions -#define _DUMP_TEMPLATE(func, type, arg) \ - template<class T> \ - inline void func(type arg, \ - int (*dprint)( T* param, char const * format, ...), \ - T* param) { func(arg, (_DPRINT)dprint, (void*)param); } \ - static void func(type arg, \ - _DPRINT dprint = (_DPRINT)fprintf, \ - void* param = (void*)stdout); - - /** dump the device status to stdout using printf - \param status the status to convert to textual form, - unavailable fields are ommited (not printed) - \param dprint a function pointer - \param param the irst argument passed to dprint - */ - _DUMP_TEMPLATE(dumpDevStatus, MDMParser::DevStatus*, status) - - /** dump the network status to stdout using printf - \param status the status to convert to textual form, - unavailable fields are ommited (not printed) - \param dprint a function pointer - \param param the irst argument passed to dprint - */ - _DUMP_TEMPLATE(dumpNetStatus, MDMParser::NetStatus*, status) - - /** dump the ip address to stdout using printf - \param ip the ip to convert to textual form, - unavailable fields are ommited (not printed) - \param dprint a function pointer - \param param the irst argument passed to dprint - */ - _DUMP_TEMPLATE(dumpIp, MDMParser::IP, ip) - - // ---------------------------------------------------------------- - // Parseing - // ---------------------------------------------------------------- - - enum { - // waitFinalResp Responses - NOT_FOUND = 0, - WAIT = -1, // TIMEOUT - RESP_OK = -2, - RESP_ERROR = -3, - RESP_PROMPT = -4, - RESP_ERROR_CME= -5, - - // getLine Responses - #define LENGTH(x) (x & 0x00FFFF) //!< extract/mask the length - #define TYPE(x) (x & 0xFF0000) //!< extract/mask the type - - TYPE_UNKNOWN = 0x000000, - TYPE_OK = 0x110000, - TYPE_ERROR = 0x120000, - TYPE_ERROR_CME = 0x130000, - TYPE_RING = 0x210000, - TYPE_CONNECT = 0x220000, - TYPE_NOCARRIER = 0x230000, - TYPE_NODIALTONE = 0x240000, - TYPE_BUSY = 0x250000, - TYPE_NOANSWER = 0x260000, - TYPE_PROMPT = 0x300000, - TYPE_PLUS = 0x400000, - TYPE_TEXT = 0x500000, - - // special timout constant - TIMEOUT_BLOCKING = -1 - }; - - /** Get a line from the physical interface. This function need - to be implemented in a inherited class. Usually just calls - #_getLine on the rx buffer pipe. - - \param buf the buffer to store it - \param buf size of the buffer - \return type and length if something was found, - WAIT if not enough data is available - NOT_FOUND if nothing was found - */ - virtual int getLine(char* buf, int len) = 0; - - /* clear the pending input data - */ - virtual void purge(void) = 0; - - /** Write data to the device - \param buf the buffer to write - \param buf size of the buffer to write - \return bytes written - */ - virtual int send(const char* buf, int len); - - /** Write formated date to the physical interface (printf style) - \param fmt the format string - \param .. variable arguments to be formated - \return bytes written - */ - int sendFormated(const char* format, ...); - - /** callback function for #waitFinalResp with void* as argument - \param type the #getLine response - \param buf the parsed line - \param len the size of the parsed line - \param param the optional argument passed to #waitFinalResp - \return WAIT if processing should continue, - any other value aborts #waitFinalResp and this retunr value retuned - */ - typedef int (*_CALLBACKPTR)(int type, const char* buf, int len, void* param); - - /** Wait for a final respons - \param cb the optional callback function - \param param the optional callback function parameter - \param timeout_ms the timeout to wait (See Estimated command - response time of AT manual) - */ - int waitFinalResp(_CALLBACKPTR cb = NULL, - void* param = NULL, - int timeout_ms = 10000); - - /** template version of #waitFinalResp when using callbacks, - This template will allow the compiler to do type cheking but - internally symply casts the arguments and call the (void*) - version of #waitFinalResp. - \sa waitFinalResp - */ - template<class T> - inline int waitFinalResp(int (*cb)(int type, const char* buf, int len, T* param), - T* param, - int timeout_ms = 10000) - { - return waitFinalResp((_CALLBACKPTR)cb, (void*)param, timeout_ms); - } - -protected: - /** Write bytes to the physical interface. This function should be - implemented in a inherited class. - \param buf the buffer to write - \param buf size of the buffer to write - \return bytes written - */ - virtual int _send(const void* buf, int len) = 0; - - /** Helper: Parse a line from the receiving buffered pipe - \param pipe the receiving buffer pipe - \param buf the parsed line - \param len the size of the parsed line - \return type and length if something was found, - WAIT if not enough data is available - NOT_FOUND if nothing was found - */ - static int _getLine(Pipe<char>* pipe, char* buffer, int length); - - /** Helper: Parse a match from the pipe - \param pipe the buffered pipe - \param number of bytes to parse at maximum, - \param sta the starting string, NULL if none - \param end the terminating string, NULL if none - \return size of parsed match - */ - static int _parseMatch(Pipe<char>* pipe, int len, const char* sta, const char* end); - - /** Helper: Parse a match from the pipe - \param pipe the buffered pipe - \param number of bytes to parse at maximum, - \param fmt the formating string (%d any number, %c any char of last %d len) - \return size of parsed match - */ - static int _parseFormated(Pipe<char>* pipe, int len, const char* fmt); - -protected: - // for rtos over riding by useing Rtos<MDMxx> - /** override in a rtos system, you us the wait function of a Thread - \param ms the number of milliseconds to wait - */ - virtual void wait_ms(int ms) { if (ms) ::wait_ms(ms); } - //! override the lock in a rtos system - virtual void lock(void) { } - //! override the unlock in a rtos system - virtual void unlock(void) { } -protected: - bool _activateProfile(const char* apn, const char* username, const char* password, Auth auth); - bool _activateProfileReuseExternal(void); - bool _activateProfileByCid(int cid, const char* apn, const char* username, const char* password, Auth auth); - // parsing callbacks for different AT commands and their parameter arguments - static int _cbString(int type, const char* buf, int len, char* str); - static int _cbInt(int type, const char* buf, int len, int* val); - // device - static int _cbATI(int type, const char* buf, int len, Dev* dev); - static int _cbCPIN(int type, const char* buf, int len, Sim* sim); - static int _cbCCID(int type, const char* buf, int len, char* ccid); - // network - static int _cbCSQ(int type, const char* buf, int len, NetStatus* status); - static int _cbCOPS(int type, const char* buf, int len, NetStatus* status); - static int _cbCNUM(int type, const char* buf, int len, char* num); - static int _cbUACTIND(int type, const char* buf, int len, int* i); - static int _cbCGDCONT(int type, const char* buf, int len, int* cid); - static int _cbUDOPN(int type, const char* buf, int len, char* mccmnc); - // sockets - static int _cbCMIP(int type, const char* buf, int len, IP* ip); - static int _cbUPSND(int type, const char* buf, int len, int* act); - static int _cbUPSND(int type, const char* buf, int len, IP* ip); - static int _cbUDNSRN(int type, const char* buf, int len, IP* ip); - static int _cbUSOCR(int type, const char* buf, int len, int* handle); - static int _cbUSORD(int type, const char* buf, int len, char* out); - typedef struct { char* buf; IP ip; int port; } USORFparam; - static int _cbUSORF(int type, const char* buf, int len, USORFparam* param); - typedef struct { char* buf; char* num; } CMGRparam; - static int _cbCUSD(int type, const char* buf, int len, char* resp); - // sms - typedef struct { int* ix; int num; } CMGLparam; - static int _cbCMGL(int type, const char* buf, int len, CMGLparam* param); - static int _cbCMGR(int type, const char* buf, int len, CMGRparam* param); - // file - typedef struct { const char* filename; char* buf; int sz; int len; } URDFILEparam; - static int _cbUDELFILE(int type, const char* buf, int len, void*); - static int _cbURDFILE(int type, const char* buf, int len, URDFILEparam* param); - static int _cbURDBLOCK(int type, const char* buf, int len, char* out); - static int _cbULSTFILE(int type, const char* buf, int len, int* infoFile); - // variables - DevStatus _dev; //!< collected device information - NetStatus _net; //!< collected network information - IP _ip; //!< assigned ip address - CellLocData _loc[CELL_MAX_HYP]; //!< CellLocate data - // management struture for sockets - typedef struct { int handle; int timeout_ms; volatile bool connected; volatile int pending; } SockCtrl; - // LISA-C has 6 TCP and 6 UDP sockets - // LISA-U and SARA-G have 7 sockets - SockCtrl _sockets[12]; - int _findSocket(int handle = SOCKET_ERROR/* = CREATE*/); - // management structure for HTTP profiles - // it's possible to have up to 4 different HTTP profiles (LISA-C200, LISA-U200 and SARA-G350) having: - // param handle the current HTTP profile is in handling state or not (default value is HTTP_ERROR) - // param timeout_ms the timeout for the current HTTP command - // param pending the status for the current HTTP command (in processing state or not) - // param cmd the code for the current HTTP command - // param result the result for the current HTTP command once processed - typedef struct { int handle; int timeout_ms; bool pending; int cmd; int result; } HttpProfCtrl; - HttpProfCtrl _httpProfiles[4]; - int _findProfile(int handle = HTTP_PROF_ERROR/* = CREATE*/); - static MDMParser* inst; - bool _init; -#ifdef TARGET_UBLOX_C027 - bool _onboard; -#endif -#ifdef MDM_DEBUG - int _debugLevel; - Timer _debugTime; - void _debugPrint(int level, const char* color, const char* format, ...); -#endif -}; - -// ----------------------------------------------------------------------- - -/** modem class which uses a serial port - as physical interface. -*/ -class MDMSerial : public SerialPipe, public MDMParser -{ -public: - /** Constructor - - \param tx is the serial ports transmit pin (modem to CPU) - \param rx is the serial ports receive pin (CPU to modem) - \param baudrate the baudrate of the modem use 115200 - \param rts is the serial ports ready to send pin (CPU to modem) - this pin is optional - \param cts is the serial ports clear to send pin (modem to CPU) - this pin is optional, but required for power saving to be enabled - \param rxSize the size of the serial rx buffer - \param txSize the size of the serial tx buffer - */ - MDMSerial(PinName tx MDM_IF( = MDMTXD, = D1 ), - PinName rx MDM_IF( = MDMRXD, = D0 ), - int baudrate MDM_IF( = MDMBAUD, = 115200 ), - #if DEVICE_SERIAL_FC - PinName rts MDM_IF( = MDMRTS, = NC /* D2 resistor R62 on shield not mounted */ ), - PinName cts MDM_IF( = MDMCTS, = NC /* D3 resistor R63 on shield not mounted */ ), - #endif - int rxSize = 256 , - int txSize = 128 ); - //! Destructor - virtual ~MDMSerial(void); - - /** Get a line from the physical interface. - \param buf the buffer to store it - \param buf size of the buffer - \return type and length if something was found, - WAIT if not enough data is available - NOT_FOUND if nothing was found - */ - virtual int getLine(char* buffer, int length); - - /* clear the pending input data */ - virtual void purge(void) - { - while (readable()) - getc(); - } -protected: - /** Write bytes to the physical interface. - \param buf the buffer to write - \param buf size of the buffer to write - \return bytes written - */ - virtual int _send(const void* buf, int len); -}; - -// ----------------------------------------------------------------------- - -//#define HAVE_MDMUSB -#ifdef HAVE_MDMUSB -class MDMUsb : /*public UsbSerial,*/ public MDMParser -{ -public: - //! Constructor - MDMUsb(void); - //! Destructor - virtual ~MDMUsb(void); - virtual int getLine(char* buffer, int length); - virtual void purge(void) { } -protected: - virtual int _send(const void* buf, int len); -}; -#endif - -// ----------------------------------------------------------------------- - -#ifdef RTOS_H -/** Use this template to override the lock and wait functions of the - modem driver in a Rtos system. For example declare it the modem - object as MDMRtos<MDMSerial> instead of MDMSerial. -*/ -template <class T> -class MDMRtos : public T -{ -protected: - //! we assume that the modem runs in a thread so we yield when waiting - virtual void wait_ms(int ms) { - if (ms) Thread::wait(ms); - else Thread::yield(); - } - //! lock a mutex when accessing the modem - virtual void lock(void) { _mtx.lock(); } - //! unlock the modem when done accessing it - virtual void unlock(void) { _mtx.unlock(); } - // the mutex resource - Mutex _mtx; -}; -#endif \ No newline at end of file
diff -r dafbbf31bf76 -r 5df09023c4e9 MDMAPN.h --- a/MDMAPN.h Thu Feb 25 13:22:34 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +0,0 @@ -#pragma once - -/* ---------------------------------------------------------------- - APN stands for Access Point Name, a setting on your modem or phone - that identifies an external network your phone can access for data - (e.g. 3G or 4G Internet service on your phone). - - The APN settings can be forced when calling the join function. - Below is a list of known APNs that us used if no apn config - is forced. This list could be extended by other settings. - - For further reading: - wiki apn: http://en.wikipedia.org/wiki/Access_Point_Name - wiki mcc/mnc: http://en.wikipedia.org/wiki/Mobile_country_code - google: https://www.google.de/search?q=APN+list ----------------------------------------------------------------- */ - -//! helper to generate the APN string -#define _APN(apn,username,password) apn "\0" username "\0" password "\0" - -//! helper to extract a field from the config string -#define _APN_GET(cfg) \ - *cfg ? cfg : ""; \ - cfg += strlen(cfg) + 1 - -//! APN lookup struct -typedef struct { - const char* mccmnc; //!< mobile country code (MCC) and mobile network code MNC - const char* cfg; //!< APN configuartion string, use _APN macro to generate -} APN_t; - -//! default APN settings used by many networks -static const char* apndef = _APN(,,) - _APN("internet",,); - -/*! this is a list of special APNs for different network operators - There is no need to enter the default apn internet in the table; - apndef will be used if no entry matches. - - The APN without username/password have to be listed first. -*/ -static const APN_t apnlut[] = { -// MCC Country -// { /* Operator */ "MCC-MNC[,MNC]" _APN(APN,USERNAME,PASSWORD) }, -// MCC must be 3 digits -// MNC must be either 2 or 3 digits -// MCC must be separated by '-' from MNC, multiple MNC can be separated by ',' - -// 232 Austria - AUT - { /* T-Mobile */ "232-03", _APN("m2m.business",,) }, - -// 460 China - CN - { /* CN Mobile */"460-00", _APN("cmnet",,) - _APN("cmwap",,) }, - { /* Unicom */ "460-01", _APN("3gnet",,) - _APN("uninet","uninet","uninet") }, - -// 262 Germany - DE - { /* T-Mobile */ "262-01", _APN("internet.t-mobile","t-mobile","tm") }, - { /* T-Mobile */ "262-02,06", - _APN("m2m.business",,) }, - -// 222 Italy - IT - { /* TIM */ "222-01", _APN("ibox.tim.it",,) }, - { /* Vodafone */ "222-10", _APN("web.omnitel.it",,) }, - { /* Wind */ "222-88", _APN("internet.wind.biz",,) }, - -// 440 Japan - JP - { /* Softbank */ "440-04,06,20,40,41,42,43,44,45,46,47,48,90,91,92,93,94,95" - ",96,97,98" - _APN("open.softbank.ne.jp","opensoftbank","ebMNuX1FIHg9d3DA") - _APN("smile.world","dna1trop","so2t3k3m2a") }, - { /* NTTDoCoMo */"440-09,10,11,12,13,14,15,16,17,18,19,21,22,23,24,25,26,27," - "28,29,30,31,32,33,34,35,36,37,38,39,58,59,60,61,62,63," - "64,65,66,67,68,69,87,99", - _APN("bmobilewap",,) /*BMobile*/ - _APN("mpr2.bizho.net","Mopera U",) /* DoCoMo */ - _APN("bmobile.ne.jp","bmobile@wifi2","bmobile") /*BMobile*/ }, - -// 204 Netherlands - NL - { /* Vodafone */ "204-04", _APN("public4.m2minternet.com",,) }, - -// 293 Slovenia - SI - { /* Si.mobil */ "293-40", _APN("internet.simobil.si",,) }, - { /* Tusmobil */ "293-70", _APN("internet.tusmobil.si",,) }, - -// 240 Sweden SE - { /* Telia */ "240-01", _APN("online.telia.se",,) }, - { /* Telenor */ "240-06,08", - _APN("services.telenor.se",,) }, - { /* Tele2 */ "240-07", _APN("mobileinternet.tele2.se",,) }, - -// 228 Switzerland - CH - { /* Swisscom */ "228-01", _APN("gprs.swisscom.ch",,) }, - { /* Orange */ "228-03", _APN("internet",,) /* contract */ - _APN("click",,) /* pre-pay */ }, - -// 234 United Kingdom - GB - { /* O2 */ "234-02,10,11", - _APN("mobile.o2.co.uk","faster","web") /* contract */ - _APN("mobile.o2.co.uk","bypass","web") /* pre-pay */ - _APN("payandgo.o2.co.uk","payandgo","payandgo") }, - { /* Vodafone */ "234-15", _APN("internet","web","web") /* contract */ - _APN("pp.vodafone.co.uk","wap","wap") /* pre-pay */ }, - { /* Three */ "234-20", _APN("three.co.uk",,) }, - -// 310 United States of America - US - { /* T-Mobile */ "310-026,260,490", - _APN("epc.tmobile.com",,) - _APN("fast.tmobile.com",,) /* LTE */ }, - { /* AT&T */ "310-030,150,170,260,410,560,680", - _APN("phone",,) - _APN("wap.cingular","WAP@CINGULARGPRS.COM","CINGULAR1") - _APN("isp.cingular","ISP@CINGULARGPRS.COM","CINGULAR1") }, - -// 901 International - INT - { /* Transatel */ "901-37", _APN("netgprs.com","tsl","tsl") }, -}; - -inline const char* apnconfig(const char* imsi) -{ - const char* config = NULL; - if (imsi && *imsi) { - // many carriers use internet without username and password, os use this as default - // now try to lookup the setting for our table - for (int i = 0; i < sizeof(apnlut)/sizeof(*apnlut) && !config; i ++) { - const char* p = apnlut[i].mccmnc; - // check the MCC - if ((0 == memcmp(imsi, p, 3))) { - p += 3; - // check all the MNC, MNC length can be 2 or 3 digits - while (((p[0] == '-') || (p[0] == ',')) && - (p[1] >= '0') && (p[1] <= '9') && - (p[2] >= '0') && (p[2] <= '9') && !config) { - int l = ((p[3] >= '0') && (p[3] <= '9')) ? 3 : 2; - if (0 == memcmp(imsi+3,p+1,l)) - config = apnlut[i].cfg; - p += 1 + l; - } - } - } - } - // use default if not found - if (!config) - config = apndef; - return config; -} \ No newline at end of file
diff -r dafbbf31bf76 -r 5df09023c4e9 Socket/Endpoint.h --- a/Socket/Endpoint.h Thu Feb 25 13:22:34 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* Copyright (C) 2012 mbed.org, MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING - * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -#ifndef ENDPOINT_H -#define ENDPOINT_H - -#include "MDM.h" - -class UDPSocket; - -class Endpoint { - friend class UDPSocket; -public: - Endpoint(void) { - _ip[0] = '\0'; - _port = 0; - _mdm = NULL; - } - - void reset_address(void) { - _ip[0] = '\0'; - _port = 0; - } - - int set_address(const char* host, const int port) { - _ip[0] = '\0'; - _port = 0; - if (_mdm == NULL) - _mdm = MDMParser::getInstance(); - if (_mdm == NULL) - return -1; - // resove the host name (eventually does a dns lookup) - MDMParser::IP ip = _mdm->gethostbyname(host); - if (ip == NOIP) - return -1; - sprintf(_ip, IPSTR, IPNUM(ip)); - _port = port; - return 0; - } - - char* get_address(void) { return _ip; } - - int get_port(void) { return _port; } - -protected: - MDMParser* _mdm; - char _ip[17]; - int _port; -}; - -#endif
diff -r dafbbf31bf76 -r 5df09023c4e9 Socket/Socket.h --- a/Socket/Socket.h Thu Feb 25 13:22:34 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -#ifndef SOCKET_H_ -#define SOCKET_H_ - -#include "MDM.h" - -/** Socket file descriptor and select wrapper - */ -class Socket { -public: - Socket() { - _socket = -1; - _timeout_ms = MDMParser::TIMEOUT_BLOCKING; - _mdm = NULL; - } - - void set_blocking(bool blocking, unsigned int timeout = 1500) { - _timeout_ms = blocking ? MDMParser::TIMEOUT_BLOCKING : (int)timeout; - if (_socket >= 0) { - _mdm->socketSetBlocking(_socket, _timeout_ms); - } - } - - int close() { - bool ret = false; - if (_socket >= 0) - { - ret = _mdm->socketClose(_socket); - _mdm->socketFree(_socket); - _socket = -1; - _timeout_ms = MDMParser::TIMEOUT_BLOCKING; - } - return ret ? 0 : -1; - } - - ~Socket() { close(); } - -protected: - int _socket; - int _timeout_ms; - MDMParser* _mdm; -}; - - -#endif /* SOCKET_H_ */
diff -r dafbbf31bf76 -r 5df09023c4e9 Socket/TCPSocketConnection.h --- a/Socket/TCPSocketConnection.h Thu Feb 25 13:22:34 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -#ifndef TCPSOCKET_H -#define TCPSOCKET_H - -#include "Socket.h" - -/** TCP socket connection - */ -class TCPSocketConnection: public Socket -{ - friend class TCPSocketServer; - -public: - /** TCP socket connection - */ - TCPSocketConnection() {} - - /** Connects this TCP socket to the server - \param host The host to connect to. It can either be an IP Address or a hostname that will be resolved with DNS. - \param port The host's port to connect to. - \return 0 on success, -1 on failure. - */ - int connect(const char* host, const int port) - { - if (_mdm == NULL) - _mdm = MDMParser::getInstance(); - if (_mdm == NULL) - return -1; - - if (_socket < 0) { - _socket = _mdm->socketSocket(MDMParser::IPPROTO_TCP); - if (_socket < 0) { - return -1; - } - } - - _mdm->socketSetBlocking(_socket, _timeout_ms); - if (!_mdm->socketConnect(_socket, host, port)) { - return -1; - } - return 0; - } - /** Check if the socket is connected - \return true if connected, false otherwise. - */ - bool is_connected(void) - { - if (_socket < 0) - return false; - return _mdm->socketIsConnected(_socket); - } - - /** Send data to the remote host. - \param data The buffer to send to the host. - \param length The length of the buffer to send. - \return the number of written bytes on success (>=0) or -1 on failure - */ - int send(char* data, int length) { return _mdm->socketSend(_socket, data, length); } - - /** Send all the data to the remote host. - \param data The buffer to send to the host. - \param length The length of the buffer to send. - \return the number of written bytes on success (>=0) or -1 on failure - */ - int send_all(char* data, int length) { return send(data,length); } - - /** Receive data from the remote host. - \param data The buffer in which to store the data received from the host. - \param length The maximum length of the buffer. - \return the number of received bytes on success (>=0) or -1 on failure - */ - int receive(char* data, int length) { return _mdm->socketRecv(_socket, data, length); } - - /** Receive all the data from the remote host. - \param data The buffer in which to store the data received from the host. - \param length The maximum length of the buffer. - \return the number of received bytes on success (>=0) or -1 on failure - */ - int receive_all(char* data, int length) { return receive(data,length); } - -}; - -#endif
diff -r dafbbf31bf76 -r 5df09023c4e9 Socket/UDPSocket.h --- a/Socket/UDPSocket.h Thu Feb 25 13:22:34 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -/* Copyright (C) 2012 mbed.org, MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING - * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef UDPSOCKET_H -#define UDPSOCKET_H - -#include "Socket/Socket.h" -#include "Socket/Endpoint.h" - -/** -UDP Socket -*/ -class UDPSocket : public Socket { - -public: - int init(void) - { - if (_mdm == NULL) - _mdm = MDMParser::getInstance(); - if (_mdm == NULL) - return -1; - return 0; - } - - int bind(int port) { - if (_socket < 0) { - _socket = _mdm->socketSocket(MDMParser::IPPROTO_UDP, port); - if (_socket < 0) { - return -1; - } - } - _mdm->socketSetBlocking(_socket, _timeout_ms); - return 0; - } - - int join_multicast_group(const char* address) { return -1; } - - int set_broadcasting(bool broadcast=true) { return -1; } - - int sendTo(Endpoint &remote, char *packet, int length) - { - char* str = remote.get_address(); - int port = remote.get_port(); - MDMParser::IP ip = _mdm->gethostbyname(str); - if (ip == NOIP) - return -1; - return _mdm->socketSendTo(_socket, ip, port, packet, length); - } - - int receiveFrom(Endpoint &remote, char *buffer, int length) - { - MDMParser::IP ip; - int port; - int ret = _mdm->socketRecvFrom(_socket, &ip, &port, buffer, length); - if (ret >= 0) { - char str[17]; - sprintf(str, IPSTR, IPNUM(ip)); - remote.set_address(str, port); - } - return ret; - } -}; - -#endif