support library for C027 helper functions for Buffer Pipes, Buffered Serial Port (rtos capable) and GPS parsing. It includes modem APIs for USSD, SMS and Sockets.

Dependents:   HTTPClient_Cellular_HelloWorld Cellular_HelloMQTT MbedSmartRestMain Car_Bon_car_module ... more

This library is intended to be used with u-blox products such as the C027 or a shield with u-blox cellular and GPS modules like the cellular and positioning shield from Embedded Artist.

For 2G/GSM and 3G/UMTS you need to:

  • have a SIM card and know its PIN number
  • need to know you network operators APN setting These setting should be passed to the connect or init and join functions. You can also extend the APN database in MDMAPN.h.

For CDMA products you need to make sure that you have provisioned and activated the modem with either Sprint or Verizon.

Committer:
fdilenarda
Date:
Thu Jan 21 15:59:42 2016 +0000
Revision:
135:cbccf4052d45
Parent:
134:2fbd5723e063
Child:
136:8dc8f48275fc
added HTTP API

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mazgch 18:e5697801df29 1 #include "mbed.h"
mazgch 18:e5697801df29 2 #include "MDM.h"
mazgch 74:208e3e32d263 3 #ifdef TARGET_UBLOX_C027
mazgch 74:208e3e32d263 4 #include "C027_api.h"
mazgch 74:208e3e32d263 5 #endif
mazgch 85:dd8f4f0d0ca9 6 #include "MDMAPN.h"
mazgch 125:25a292afbac6 7
mazgch 74:208e3e32d263 8 #define PROFILE "0" //!< this is the psd profile used
mazgch 74:208e3e32d263 9 #define MAX_SIZE 128 //!< max expected messages
mazgch 103:197fa7920ad8 10 // num sockets
mazgch 104:c64ba749a422 11 #define NUMSOCKETS (sizeof(_sockets)/sizeof(*_sockets))
mazgch 104:c64ba749a422 12 //! test if it is a socket is ok to use
mazgch 104:c64ba749a422 13 #define ISSOCKET(s) (((s) >= 0) && ((s) < NUMSOCKETS) && (_sockets[s].handle != SOCKET_ERROR))
mazgch 75:ce6e12067d0c 14 //! check for timeout
mazgch 75:ce6e12067d0c 15 #define TIMEOUT(t, ms) ((ms != TIMEOUT_BLOCKING) && (ms < t.read_ms()))
fdilenarda 135:cbccf4052d45 16 // num HTTP profiles
fdilenarda 135:cbccf4052d45 17 #define NUMPROFILES (sizeof(_httpProfiles)/sizeof(*_httpProfiles))
fdilenarda 135:cbccf4052d45 18 //! test if it is an HTTP profile is ok to use
fdilenarda 135:cbccf4052d45 19 #define ISPROFILE(p) (((p) >= 0) && ((p) < NUMPROFILES) && (_httpProfiles[p].handle != HTTP_PROF_ERROR))
mazgch 80:34985b4d821e 20 //! registration ok check helper
mazgch 79:291df065e345 21 #define REG_OK(r) ((r == REG_HOME) || (r == REG_ROAMING))
mazgch 80:34985b4d821e 22 //! registration done check helper (no need to poll further)
mazgch 79:291df065e345 23 #define REG_DONE(r) ((r == REG_HOME) || (r == REG_ROAMING) || (r == REG_DENIED))
mazgch 95:8282dbbe1492 24 //! helper to make sure that lock unlock pair is always balaced
mazgch 95:8282dbbe1492 25 #define LOCK() { lock()
mazgch 95:8282dbbe1492 26 //! helper to make sure that lock unlock pair is always balaced
mazgch 95:8282dbbe1492 27 #define UNLOCK() } unlock()
mazgch 79:291df065e345 28
mazgch 74:208e3e32d263 29 #ifdef MDM_DEBUG
mazgch 95:8282dbbe1492 30 #if 1 // colored terminal output using ANSI escape sequences
mazgch 95:8282dbbe1492 31 #define COL(c) "\033[" c
mazgch 95:8282dbbe1492 32 #else
mazgch 95:8282dbbe1492 33 #define COL(c)
mazgch 95:8282dbbe1492 34 #endif
mazgch 95:8282dbbe1492 35 #define DEF COL("39m")
mazgch 95:8282dbbe1492 36 #define BLA COL("30m")
mazgch 95:8282dbbe1492 37 #define RED COL("31m")
mazgch 95:8282dbbe1492 38 #define GRE COL("32m")
mazgch 95:8282dbbe1492 39 #define YEL COL("33m")
mazgch 95:8282dbbe1492 40 #define BLU COL("34m")
mazgch 95:8282dbbe1492 41 #define MAG COL("35m")
mazgch 95:8282dbbe1492 42 #define CYA COL("36m")
mazgch 95:8282dbbe1492 43 #define WHY COL("37m")
mazgch 95:8282dbbe1492 44
mazgch 74:208e3e32d263 45 void dumpAtCmd(const char* buf, int len)
mazgch 21:c4d64830bf02 46 {
mazgch 75:ce6e12067d0c 47 ::printf(" %3d \"", len);
mazgch 21:c4d64830bf02 48 while (len --) {
mazgch 21:c4d64830bf02 49 char ch = *buf++;
mazgch 75:ce6e12067d0c 50 if ((ch > 0x1F) && (ch != 0x7F)) { // is printable
mazgch 75:ce6e12067d0c 51 if (ch == '%') ::printf("%%");
mazgch 75:ce6e12067d0c 52 else if (ch == '"') ::printf("\\\"");
mazgch 75:ce6e12067d0c 53 else if (ch == '\\') ::printf("\\\\");
mazgch 75:ce6e12067d0c 54 else putchar(ch);
mazgch 75:ce6e12067d0c 55 } else {
mazgch 75:ce6e12067d0c 56 if (ch == '\a') ::printf("\\a"); // BEL (0x07)
mazgch 75:ce6e12067d0c 57 else if (ch == '\b') ::printf("\\b"); // Backspace (0x08)
mazgch 75:ce6e12067d0c 58 else if (ch == '\t') ::printf("\\t"); // Horizontal Tab (0x09)
mazgch 75:ce6e12067d0c 59 else if (ch == '\n') ::printf("\\n"); // Linefeed (0x0A)
mazgch 75:ce6e12067d0c 60 else if (ch == '\v') ::printf("\\v"); // Vertical Tab (0x0B)
mazgch 75:ce6e12067d0c 61 else if (ch == '\f') ::printf("\\f"); // Formfeed (0x0C)
mazgch 75:ce6e12067d0c 62 else if (ch == '\r') ::printf("\\r"); // Carriage Return (0x0D)
mazgch 76:f7c3dd568dae 63 else ::printf("\\x%02x", (unsigned char)ch);
mazgch 75:ce6e12067d0c 64 }
mazgch 21:c4d64830bf02 65 }
mazgch 75:ce6e12067d0c 66 ::printf("\"\r\n");
mazgch 21:c4d64830bf02 67 }
mazgch 74:208e3e32d263 68
mazgch 117:74e4e0109a9e 69 void MDMParser::_debugPrint(int level, const char* color, const char* format, ...)
mazgch 117:74e4e0109a9e 70 {
mazgch 117:74e4e0109a9e 71 if (_debugLevel >= level)
mazgch 117:74e4e0109a9e 72 {
mazgch 117:74e4e0109a9e 73 va_list args;
mazgch 117:74e4e0109a9e 74 va_start (args, format);
mazgch 117:74e4e0109a9e 75 if (color) ::printf(color);
mazgch 117:74e4e0109a9e 76 ::vprintf(format, args);
mazgch 117:74e4e0109a9e 77 if (color) ::printf(DEF);
mazgch 117:74e4e0109a9e 78 va_end (args);
mazgch 117:74e4e0109a9e 79 }
mazgch 117:74e4e0109a9e 80 }
mazgch 117:74e4e0109a9e 81
mazgch 117:74e4e0109a9e 82 #define ERROR(...) _debugPrint(0, RED, __VA_ARGS__)
mazgch 117:74e4e0109a9e 83 #define INFO(...) _debugPrint(1, GRE, __VA_ARGS__)
mazgch 117:74e4e0109a9e 84 #define TRACE(...) _debugPrint(2, DEF, __VA_ARGS__)
mazgch 117:74e4e0109a9e 85 #define TEST(...) _debugPrint(3, CYA, __VA_ARGS__)
mazgch 74:208e3e32d263 86
mazgch 74:208e3e32d263 87 #else
mazgch 74:208e3e32d263 88
mazgch 75:ce6e12067d0c 89 #define ERROR(...) (void)0 // no tracing
mazgch 95:8282dbbe1492 90 #define TEST(...) (void)0 // no tracing
mazgch 74:208e3e32d263 91 #define INFO(...) (void)0 // no tracing
mazgch 74:208e3e32d263 92 #define TRACE(...) (void)0 // no tracing
mazgch 74:208e3e32d263 93
mazgch 31:a0bed6c1e05d 94 #endif
mazgch 21:c4d64830bf02 95
mazgch 44:9d12223b78ff 96 MDMParser* MDMParser::inst;
mazgch 44:9d12223b78ff 97
mazgch 21:c4d64830bf02 98 MDMParser::MDMParser(void)
mazgch 21:c4d64830bf02 99 {
mazgch 44:9d12223b78ff 100 inst = this;
mazgch 31:a0bed6c1e05d 101 memset(&_dev, 0, sizeof(_dev));
mazgch 31:a0bed6c1e05d 102 memset(&_net, 0, sizeof(_net));
mazgch 54:7ba8e4c218e2 103 _net.lac = 0xFFFF;
mazgch 54:7ba8e4c218e2 104 _net.ci = 0xFFFFFFFF;
mazgch 35:9275215a3a5b 105 _ip = NOIP;
mazgch 76:f7c3dd568dae 106 _init = false;
mazgch 31:a0bed6c1e05d 107 memset(_sockets, 0, sizeof(_sockets));
mazgch 104:c64ba749a422 108 for (int socket = 0; socket < NUMSOCKETS; socket ++)
mazgch 103:197fa7920ad8 109 _sockets[socket].handle = SOCKET_ERROR;
fdilenarda 135:cbccf4052d45 110 memset(_httpProfiles, 0, sizeof(_httpProfiles));
fdilenarda 135:cbccf4052d45 111 for (int profile = 0; profile < NUMPROFILES; profile ++)
fdilenarda 135:cbccf4052d45 112 _httpProfiles[profile].handle = HTTP_PROF_ERROR;
mazgch 74:208e3e32d263 113 #ifdef MDM_DEBUG
mazgch 76:f7c3dd568dae 114 _debugLevel = 1;
mazgch 74:208e3e32d263 115 _debugTime.start();
mazgch 74:208e3e32d263 116 #endif
mazgch 74:208e3e32d263 117 }
mazgch 74:208e3e32d263 118
mazgch 18:e5697801df29 119 int MDMParser::send(const char* buf, int len)
mazgch 18:e5697801df29 120 {
mazgch 74:208e3e32d263 121 #ifdef MDM_DEBUG
mazgch 74:208e3e32d263 122 if (_debugLevel >= 3) {
mazgch 75:ce6e12067d0c 123 ::printf("%10.3f AT send ", _debugTime.read_ms()*0.001);
mazgch 74:208e3e32d263 124 dumpAtCmd(buf,len);
mazgch 74:208e3e32d263 125 }
mazgch 21:c4d64830bf02 126 #endif
mazgch 18:e5697801df29 127 return _send(buf, len);
mazgch 18:e5697801df29 128 }
mazgch 18:e5697801df29 129
mazgch 21:c4d64830bf02 130 int MDMParser::sendFormated(const char* format, ...) {
mazgch 21:c4d64830bf02 131 char buf[MAX_SIZE];
mazgch 21:c4d64830bf02 132 va_list args;
mazgch 21:c4d64830bf02 133 va_start(args, format);
mazgch 21:c4d64830bf02 134 int len = vsnprintf(buf,sizeof(buf), format, args);
mazgch 21:c4d64830bf02 135 va_end(args);
mazgch 21:c4d64830bf02 136 return send(buf, len);
mazgch 21:c4d64830bf02 137 }
mazgch 21:c4d64830bf02 138
mazgch 26:07be5faf8925 139 int MDMParser::waitFinalResp(_CALLBACKPTR cb /* = NULL*/,
mazgch 26:07be5faf8925 140 void* param /* = NULL*/,
mazgch 26:07be5faf8925 141 int timeout_ms /*= 5000*/)
mazgch 26:07be5faf8925 142 {
mazgch 69:4d6fa520dfca 143 char buf[MAX_SIZE + 64 /* add some more space for framing */];
mazgch 21:c4d64830bf02 144 Timer timer;
mazgch 21:c4d64830bf02 145 timer.start();
mazgch 21:c4d64830bf02 146 do {
mazgch 21:c4d64830bf02 147 int ret = getLine(buf, sizeof(buf));
mazgch 74:208e3e32d263 148 #ifdef MDM_DEBUG
mazgch 74:208e3e32d263 149 if ((_debugLevel >= 3) && (ret != WAIT) && (ret != NOT_FOUND))
mazgch 21:c4d64830bf02 150 {
mazgch 31:a0bed6c1e05d 151 int len = LENGTH(ret);
mazgch 31:a0bed6c1e05d 152 int type = TYPE(ret);
mazgch 95:8282dbbe1492 153 const char* s = (type == TYPE_UNKNOWN)? YEL "UNK" DEF :
mazgch 95:8282dbbe1492 154 (type == TYPE_TEXT) ? MAG "TXT" DEF :
mazgch 95:8282dbbe1492 155 (type == TYPE_OK ) ? GRE "OK " DEF :
mazgch 95:8282dbbe1492 156 (type == TYPE_ERROR) ? RED "ERR" DEF :
mazgch 95:8282dbbe1492 157 (type == TYPE_PLUS) ? CYA " + " DEF :
mazgch 95:8282dbbe1492 158 (type == TYPE_PROMPT) ? BLU " > " DEF :
mazgch 95:8282dbbe1492 159 "..." ;
mazgch 75:ce6e12067d0c 160 ::printf("%10.3f AT read %s", _debugTime.read_ms()*0.001, s);
mazgch 74:208e3e32d263 161 dumpAtCmd(buf, len);
mazgch 21:c4d64830bf02 162 }
mazgch 21:c4d64830bf02 163 #endif
mazgch 21:c4d64830bf02 164 if ((ret != WAIT) && (ret != NOT_FOUND))
mazgch 18:e5697801df29 165 {
mazgch 21:c4d64830bf02 166 int type = TYPE(ret);
mazgch 21:c4d64830bf02 167 // handle unsolicited commands here
mazgch 21:c4d64830bf02 168 if (type == TYPE_PLUS) {
mazgch 21:c4d64830bf02 169 const char* cmd = buf+3;
mazgch 54:7ba8e4c218e2 170 int a, b, c, d, r;
mazgch 23:05a1aeeb5fd9 171 char s[32];
msinig 133:57b208dd96fb 172
mazgch 31:a0bed6c1e05d 173 // SMS Command ---------------------------------
mazgch 31:a0bed6c1e05d 174 // +CNMI: <mem>,<index>
mazgch 31:a0bed6c1e05d 175 if (sscanf(cmd, "CMTI: \"%*[^\"]\",%d", &a) == 1) {
mazgch 31:a0bed6c1e05d 176 TRACE("New SMS at index %d\r\n", a);
mazgch 21:c4d64830bf02 177 // Socket Specific Command ---------------------------------
mazgch 21:c4d64830bf02 178 // +UUSORD: <socket>,<length>
mazgch 103:197fa7920ad8 179 } else if ((sscanf(cmd, "UUSORD: %d,%d", &a, &b) == 2)) {
mazgch 103:197fa7920ad8 180 int socket = _findSocket(a);
mazgch 103:197fa7920ad8 181 TRACE("Socket %d: handle %d has %d bytes pending\r\n", socket, a, b);
mazgch 103:197fa7920ad8 182 if (socket != SOCKET_ERROR)
mazgch 103:197fa7920ad8 183 _sockets[socket].pending = b;
mazgch 69:4d6fa520dfca 184 // +UUSORF: <socket>,<length>
mazgch 103:197fa7920ad8 185 } else if ((sscanf(cmd, "UUSORF: %d,%d", &a, &b) == 2)) {
mazgch 103:197fa7920ad8 186 int socket = _findSocket(a);
mazgch 103:197fa7920ad8 187 TRACE("Socket %d: handle %d has %d bytes pending\r\n", socket, a, b);
mazgch 103:197fa7920ad8 188 if (socket != SOCKET_ERROR)
mazgch 103:197fa7920ad8 189 _sockets[socket].pending = b;
mazgch 21:c4d64830bf02 190 // +UUSOCL: <socket>
mazgch 103:197fa7920ad8 191 } else if ((sscanf(cmd, "UUSOCL: %d", &a) == 1)) {
mazgch 103:197fa7920ad8 192 int socket = _findSocket(a);
mazgch 103:197fa7920ad8 193 TRACE("Socket %d: handle %d closed by remote host\r\n", socket, a);
mazgch 103:197fa7920ad8 194 if ((socket != SOCKET_ERROR) && _sockets[socket].connected)
msinig 133:57b208dd96fb 195 _sockets[socket].connected = false;
msinig 133:57b208dd96fb 196 // +UULOC: <date>,<time>,<lat>,<long>,<alt>,<uncertainty>,<speed>, <direction>,<vertical_acc>,<sensor_used>,<SV_used>,<antenna_status>, <jamming_status>
msinig 133:57b208dd96fb 197 }else if (sscanf(cmd, "UULOC: %d/%d/%d,%d:%d:%d.%*d,%f,%f,%d,%d,%d,%d,%d,%d,%d,%*d,%*d",\
msinig 133:57b208dd96fb 198 &_loc.time.tm_mday, &_loc.time.tm_mon, &_loc.time.tm_year, &_loc.time.tm_hour, &_loc.time.tm_min, &_loc.time.tm_sec,\
msinig 133:57b208dd96fb 199 &_loc.latitue, &_loc.longitude, &_loc.altitutude, &_loc.uncertainty, &_loc.speed, &_loc.direction, &_loc.verticalAcc, \
msinig 133:57b208dd96fb 200 &_loc.sensorUsed, &_loc.svUsed) == 15) {
msinig 133:57b208dd96fb 201 _loc.time.tm_mon -= 1;
msinig 133:57b208dd96fb 202 _loc.time.tm_wday=0;
msinig 133:57b208dd96fb 203 _loc.time.tm_yday=0;
msinig 133:57b208dd96fb 204 _loc.validData = true;
msinig 133:57b208dd96fb 205 TRACE("Parsed UULOC position\r\n");
fdilenarda 135:cbccf4052d45 206 // +UHTTPCR: <profile_id>,<op_code>,<param_val>
fdilenarda 135:cbccf4052d45 207 } else if ((sscanf(cmd, "UUHTTPCR: %d,%d,%d", &a, &b, &c) == 3)) {
fdilenarda 135:cbccf4052d45 208 _httpProfiles[a].cmd = b; //command
fdilenarda 135:cbccf4052d45 209 _httpProfiles[a].result = c; //result
fdilenarda 135:cbccf4052d45 210 TRACE("%s for profile %d: result code is %d\r\n", getHTTPcmd(b), a, c);
fdilenarda 135:cbccf4052d45 211 }
fdilenarda 135:cbccf4052d45 212 if (_dev.dev == DEV_LISA_C2) {
mazgch 21:c4d64830bf02 213 // CDMA Specific -------------------------------------------
mazgch 21:c4d64830bf02 214 // +CREG: <n><SID>,<NID>,<stat>
mazgch 54:7ba8e4c218e2 215 if (sscanf(cmd, "CREG: %*d,%d,%d,%d",&a,&b,&c) == 3) {
mazgch 54:7ba8e4c218e2 216 // _net.sid = a;
mazgch 54:7ba8e4c218e2 217 // _net.nid = b;
mazgch 79:291df065e345 218 if (c == 0) _net.csd = REG_NONE; // not registered, home network
mazgch 79:291df065e345 219 else if (c == 1) _net.csd = REG_HOME; // registered, home network
mazgch 79:291df065e345 220 else if (c == 2) _net.csd = REG_NONE; // not registered, but MT is currently searching a new operator to register to
mazgch 79:291df065e345 221 else if (c == 3) _net.csd = REG_DENIED; // registration denied
mazgch 79:291df065e345 222 else if (c == 5) _net.csd = REG_ROAMING; // registered, roaming
mazgch 79:291df065e345 223 _net.psd = _net.csd; // fake PSD registration (CDMA is always registered)
mazgch 31:a0bed6c1e05d 224 _net.act = ACT_CDMA;
mazgch 84:a05edb010176 225 // +CSS: <mode>[,<format>,<oper>[,<AcT>]]
mazgch 21:c4d64830bf02 226 } else if (sscanf(cmd, "CSS %*c,%2s,%*d",s) == 1) {
mazgch 31:a0bed6c1e05d 227 //_net.reg = (strcmp("Z", s) == 0) ? REG_UNKNOWN : REG_HOME;
mazgch 21:c4d64830bf02 228 }
mazgch 21:c4d64830bf02 229 } else {
mazgch 21:c4d64830bf02 230 // GSM/UMTS Specific -------------------------------------------
mazgch 79:291df065e345 231 // +UUPSDD: <profile_id>
mazgch 79:291df065e345 232 if (sscanf(cmd, "UUPSDD: %d",&a) == 1) {
mazgch 79:291df065e345 233 if (*PROFILE == a) _ip = NOIP;
mazgch 79:291df065e345 234 } else {
mazgch 79:291df065e345 235 // +CREG|CGREG: <n>,<stat>[,<lac>,<ci>[,AcT[,<rac>]]] // reply to AT+CREG|AT+CGREG
mazgch 79:291df065e345 236 // +CREG|CGREG: <stat>[,<lac>,<ci>[,AcT[,<rac>]]] // URC
mazgch 79:291df065e345 237 b = 0xFFFF; c = 0xFFFFFFFF; d = -1;
mazgch 79:291df065e345 238 r = sscanf(cmd, "%s %*d,%d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d);
mazgch 79:291df065e345 239 if (r <= 1)
mazgch 79:291df065e345 240 r = sscanf(cmd, "%s %d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d);
mazgch 79:291df065e345 241 if (r >= 2) {
mazgch 79:291df065e345 242 Reg *reg = !strcmp(s, "CREG:") ? &_net.csd :
mazgch 123:66cef6353b13 243 !strcmp(s, "CGREG:") ? &_net.psd :
mazgch 123:66cef6353b13 244 !strcmp(s, "CEREG:") ? &_net.eps : NULL;
mazgch 79:291df065e345 245 if (reg) {
mazgch 79:291df065e345 246 // network status
mazgch 79:291df065e345 247 if (a == 0) *reg = REG_NONE; // 0: not registered, home network
mazgch 79:291df065e345 248 else if (a == 1) *reg = REG_HOME; // 1: registered, home network
mazgch 79:291df065e345 249 else if (a == 2) *reg = REG_NONE; // 2: not registered, but MT is currently searching a new operator to register to
mazgch 79:291df065e345 250 else if (a == 3) *reg = REG_DENIED; // 3: registration denied
mazgch 79:291df065e345 251 else if (a == 4) *reg = REG_UNKNOWN; // 4: unknown
mazgch 79:291df065e345 252 else if (a == 5) *reg = REG_ROAMING; // 5: registered, roaming
mazgch 123:66cef6353b13 253 else if (a == 6) *reg = REG_HOME; // 6: registered, sms only, home
mazgch 79:291df065e345 254 if ((r >= 3) && (b != 0xFFFF)) _net.lac = b; // location area code
mazgch 79:291df065e345 255 if ((r >= 4) && (c != 0xFFFFFFFF)) _net.ci = c; // cell ID
mazgch 79:291df065e345 256 // access technology
mazgch 79:291df065e345 257 if (r >= 5) {
mazgch 79:291df065e345 258 if (d == 0) _net.act = ACT_GSM; // 0: GSM
mazgch 79:291df065e345 259 else if (d == 1) _net.act = ACT_GSM; // 1: GSM COMPACT
mazgch 79:291df065e345 260 else if (d == 2) _net.act = ACT_UTRAN; // 2: UTRAN
mazgch 79:291df065e345 261 else if (d == 3) _net.act = ACT_EDGE; // 3: GSM with EDGE availability
mazgch 79:291df065e345 262 else if (d == 4) _net.act = ACT_UTRAN; // 4: UTRAN with HSDPA availability
mazgch 79:291df065e345 263 else if (d == 5) _net.act = ACT_UTRAN; // 5: UTRAN with HSUPA availability
mazgch 79:291df065e345 264 else if (d == 6) _net.act = ACT_UTRAN; // 6: UTRAN with HSDPA and HSUPA availability
mazgch 123:66cef6353b13 265 else if (d == 7) _net.act = ACT_LTE; // 7: LTE
mazgch 79:291df065e345 266 }
mazgch 79:291df065e345 267 }
mazgch 54:7ba8e4c218e2 268 }
mazgch 21:c4d64830bf02 269 }
mazgch 21:c4d64830bf02 270 }
mazgch 21:c4d64830bf02 271 }
mazgch 21:c4d64830bf02 272 if (cb) {
mazgch 21:c4d64830bf02 273 int len = LENGTH(ret);
mazgch 21:c4d64830bf02 274 int ret = cb(type, buf, len, param);
mazgch 21:c4d64830bf02 275 if (WAIT != ret)
mazgch 21:c4d64830bf02 276 return ret;
mazgch 21:c4d64830bf02 277 }
mazgch 95:8282dbbe1492 278 if (type == TYPE_OK)
mazgch 95:8282dbbe1492 279 return RESP_OK;
mazgch 95:8282dbbe1492 280 if (type == TYPE_ERROR)
mazgch 95:8282dbbe1492 281 return RESP_ERROR;
msinig 134:2fbd5723e063 282 if (type == TYPE_ERROR_CME)
msinig 134:2fbd5723e063 283 return RESP_ERROR_CME;
mazgch 95:8282dbbe1492 284 if (type == TYPE_PROMPT)
mazgch 95:8282dbbe1492 285 return RESP_PROMPT;
mazgch 21:c4d64830bf02 286 }
mazgch 21:c4d64830bf02 287 // relax a bit
mazgch 95:8282dbbe1492 288 wait_ms(10);
mazgch 21:c4d64830bf02 289 }
mazgch 75:ce6e12067d0c 290 while (!TIMEOUT(timer, timeout_ms));
mazgch 21:c4d64830bf02 291 return WAIT;
mazgch 21:c4d64830bf02 292 }
mazgch 21:c4d64830bf02 293
mazgch 31:a0bed6c1e05d 294 int MDMParser::_cbString(int type, const char* buf, int len, char* str)
mazgch 21:c4d64830bf02 295 {
mazgch 37:cc3433329d66 296 if (str && (type == TYPE_UNKNOWN)) {
mazgch 31:a0bed6c1e05d 297 if (sscanf(buf, "\r\n%s\r\n", str) == 1)
mazgch 31:a0bed6c1e05d 298 /*nothing*/;
mazgch 21:c4d64830bf02 299 }
mazgch 21:c4d64830bf02 300 return WAIT;
mazgch 21:c4d64830bf02 301 }
mazgch 21:c4d64830bf02 302
mazgch 31:a0bed6c1e05d 303 int MDMParser::_cbInt(int type, const char* buf, int len, int* val)
mazgch 31:a0bed6c1e05d 304 {
mazgch 37:cc3433329d66 305 if (val && (type == TYPE_UNKNOWN)) {
mazgch 31:a0bed6c1e05d 306 if (sscanf(buf, "\r\n%d\r\n", val) == 1)
mazgch 31:a0bed6c1e05d 307 /*nothing*/;
mazgch 31:a0bed6c1e05d 308 }
mazgch 31:a0bed6c1e05d 309 return WAIT;
mazgch 31:a0bed6c1e05d 310 }
mazgch 31:a0bed6c1e05d 311
mazgch 31:a0bed6c1e05d 312 // ----------------------------------------------------------------
mazgch 31:a0bed6c1e05d 313
mazgch 57:869bd35f44cc 314 bool MDMParser::connect(
mazgch 57:869bd35f44cc 315 const char* simpin,
mazgch 80:34985b4d821e 316 const char* apn, const char* username,
mazgch 80:34985b4d821e 317 const char* password, Auth auth,
mazgch 74:208e3e32d263 318 PinName pn)
mazgch 57:869bd35f44cc 319 {
mazgch 75:ce6e12067d0c 320 bool ok = init(simpin, NULL, pn);
mazgch 74:208e3e32d263 321 #ifdef MDM_DEBUG
mazgch 75:ce6e12067d0c 322 if (_debugLevel >= 1) dumpDevStatus(&_dev);
mazgch 74:208e3e32d263 323 #endif
mazgch 75:ce6e12067d0c 324 if (!ok)
mazgch 57:869bd35f44cc 325 return false;
mazgch 75:ce6e12067d0c 326 ok = registerNet();
mazgch 74:208e3e32d263 327 #ifdef MDM_DEBUG
mazgch 75:ce6e12067d0c 328 if (_debugLevel >= 1) dumpNetStatus(&_net);
mazgch 74:208e3e32d263 329 #endif
mazgch 75:ce6e12067d0c 330 if (!ok)
mazgch 57:869bd35f44cc 331 return false;
mazgch 80:34985b4d821e 332 IP ip = join(apn,username,password,auth);
mazgch 74:208e3e32d263 333 #ifdef MDM_DEBUG
mazgch 74:208e3e32d263 334 if (_debugLevel >= 1) dumpIp(ip);
mazgch 74:208e3e32d263 335 #endif
mazgch 57:869bd35f44cc 336 if (ip == NOIP)
mazgch 57:869bd35f44cc 337 return false;
mazgch 57:869bd35f44cc 338 return true;
mazgch 57:869bd35f44cc 339 }
mazgch 57:869bd35f44cc 340
mazgch 74:208e3e32d263 341 bool MDMParser::init(const char* simpin, DevStatus* status, PinName pn)
mazgch 21:c4d64830bf02 342 {
mazgch 74:208e3e32d263 343 int i = 10;
mazgch 95:8282dbbe1492 344 LOCK();
mazgch 76:f7c3dd568dae 345 memset(&_dev, 0, sizeof(_dev));
mazgch 74:208e3e32d263 346 if (pn != NC) {
mazgch 74:208e3e32d263 347 INFO("Modem::wakeup\r\n");
mazgch 74:208e3e32d263 348 DigitalOut pin(pn, 1);
mazgch 74:208e3e32d263 349 while (i--) {
mazgch 79:291df065e345 350 // SARA-U2/LISA-U2 50..80us
mazgch 95:8282dbbe1492 351 pin = 0; ::wait_us(50);
mazgch 95:8282dbbe1492 352 pin = 1; ::wait_ms(10);
mazgch 79:291df065e345 353
mazgch 98:c786461edd40 354 // SARA-G35 >5ms, LISA-C2 > 150ms, LEON-G2 >5ms
mazgch 95:8282dbbe1492 355 pin = 0; ::wait_ms(150);
mazgch 95:8282dbbe1492 356 pin = 1; ::wait_ms(100);
mazgch 79:291df065e345 357
mazgch 79:291df065e345 358 // purge any messages
mazgch 101:edfeb8af206e 359 purge();
mazgch 95:8282dbbe1492 360
mazgch 101:edfeb8af206e 361 // check interface
mazgch 74:208e3e32d263 362 sendFormated("AT\r\n");
mazgch 101:edfeb8af206e 363 int r = waitFinalResp(NULL,NULL,1000);
mazgch 95:8282dbbe1492 364 if(RESP_OK == r) break;
mazgch 74:208e3e32d263 365 }
mazgch 75:ce6e12067d0c 366 if (i < 0) {
mazgch 95:8282dbbe1492 367 ERROR("No Reply from Modem\r\n");
mazgch 95:8282dbbe1492 368 goto failure;
mazgch 75:ce6e12067d0c 369 }
mazgch 21:c4d64830bf02 370 }
mazgch 76:f7c3dd568dae 371 _init = true;
mazgch 75:ce6e12067d0c 372
mazgch 74:208e3e32d263 373 INFO("Modem::init\r\n");
mazgch 21:c4d64830bf02 374 // echo off
mazgch 21:c4d64830bf02 375 sendFormated("AT E0\r\n");
mazgch 52:8071747a7cb3 376 if(RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 377 goto failure;
mazgch 21:c4d64830bf02 378 // enable verbose error messages
mazgch 21:c4d64830bf02 379 sendFormated("AT+CMEE=2\r\n");
mazgch 52:8071747a7cb3 380 if(RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 381 goto failure;
mazgch 21:c4d64830bf02 382 // set baud rate
mazgch 21:c4d64830bf02 383 sendFormated("AT+IPR=115200\r\n");
mazgch 52:8071747a7cb3 384 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 385 goto failure;
mazgch 112:89b5b21db71e 386 // wait some time until baudrate is applied
mazgch 112:89b5b21db71e 387 wait_ms(200); // SARA-G > 40ms
mazgch 21:c4d64830bf02 388 // identify the module
mazgch 21:c4d64830bf02 389 sendFormated("ATI\r\n");
mazgch 52:8071747a7cb3 390 if (RESP_OK != waitFinalResp(_cbATI, &_dev.dev))
mazgch 95:8282dbbe1492 391 goto failure;
mazgch 32:8f12ac182bbb 392 if (_dev.dev == DEV_UNKNOWN)
mazgch 95:8282dbbe1492 393 goto failure;
mazgch 32:8f12ac182bbb 394 // device specific init
mazgch 125:25a292afbac6 395 if (_dev.dev == DEV_LISA_C2) {
mazgch 32:8f12ac182bbb 396 // get the manufacturer
mazgch 32:8f12ac182bbb 397 sendFormated("AT+GMI\r\n");
mazgch 52:8071747a7cb3 398 if (RESP_OK != waitFinalResp(_cbString, _dev.manu))
mazgch 95:8282dbbe1492 399 goto failure;
mazgch 32:8f12ac182bbb 400 // get the model identification
mazgch 32:8f12ac182bbb 401 sendFormated("AT+GMM\r\n");
mazgch 52:8071747a7cb3 402 if (RESP_OK != waitFinalResp(_cbString, _dev.model))
mazgch 95:8282dbbe1492 403 goto failure;
mazgch 32:8f12ac182bbb 404 // get the sw version
mazgch 32:8f12ac182bbb 405 sendFormated("AT+GMR\r\n");
mazgch 52:8071747a7cb3 406 if (RESP_OK != waitFinalResp(_cbString, _dev.ver))
mazgch 95:8282dbbe1492 407 goto failure;
mazgch 95:8282dbbe1492 408 // get the pseudo ESN or MEID
mazgch 21:c4d64830bf02 409 sendFormated("AT+GSN\r\n");
mazgch 52:8071747a7cb3 410 if (RESP_OK != waitFinalResp(_cbString, _dev.meid))
mazgch 95:8282dbbe1492 411 goto failure;
mazgch 50:d76aece8038f 412 #if 0
mazgch 50:d76aece8038f 413 // enable power saving
mazgch 50:d76aece8038f 414 if (_dev.lpm != LPM_DISABLED) {
mazgch 50:d76aece8038f 415 // enable power saving (requires flow control, cts at least)
mazgch 50:d76aece8038f 416 sendFormated("AT+UPSV=1,1280\r\n");
mazgch 52:8071747a7cb3 417 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 418 goto failure;
mazgch 50:d76aece8038f 419 _dev.lpm = LPM_ACTIVE;
mazgch 50:d76aece8038f 420 }
mazgch 50:d76aece8038f 421 #endif
mazgch 26:07be5faf8925 422 } else {
mazgch 125:25a292afbac6 423 if ((_dev.dev == DEV_LISA_U2) || (_dev.dev == DEV_LEON_G2) ||
mazgch 125:25a292afbac6 424 (_dev.dev == DEV_TOBY_L2)) {
mazgch 35:9275215a3a5b 425 // enable the network identification feature
mazgch 21:c4d64830bf02 426 sendFormated("AT+UGPIOC=20,2\r\n");
mazgch 52:8071747a7cb3 427 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 428 goto failure;
mazgch 125:25a292afbac6 429 } else if ((_dev.dev == DEV_SARA_U2) || (_dev.dev == DEV_SARA_G35)) {
mazgch 35:9275215a3a5b 430 // enable the network identification feature
mazgch 21:c4d64830bf02 431 sendFormated("AT+UGPIOC=16,2\r\n");
mazgch 52:8071747a7cb3 432 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 433 goto failure;
mazgch 21:c4d64830bf02 434 }
mazgch 21:c4d64830bf02 435 // check the sim card
mazgch 31:a0bed6c1e05d 436 for (int i = 0; (i < 5) && (_dev.sim != SIM_READY); i++) {
mazgch 21:c4d64830bf02 437 sendFormated("AT+CPIN?\r\n");
mazgch 31:a0bed6c1e05d 438 int ret = waitFinalResp(_cbCPIN, &_dev.sim);
mazgch 62:a02f026bdd7c 439 // having an error here is ok (sim may still be initializing)
mazgch 52:8071747a7cb3 440 if ((RESP_OK != ret) && (RESP_ERROR != ret))
mazgch 95:8282dbbe1492 441 goto failure;
mazgch 31:a0bed6c1e05d 442 // Enter PIN if needed
mazgch 77:55788e619858 443 if (_dev.sim == SIM_PIN) {
mazgch 57:869bd35f44cc 444 if (!simpin) {
mazgch 75:ce6e12067d0c 445 ERROR("SIM PIN not available\r\n");
mazgch 95:8282dbbe1492 446 goto failure;
mazgch 31:a0bed6c1e05d 447 }
mazgch 130:3189949981ec 448 sendFormated("AT+CPIN=\"%s\"\r\n", simpin);
mazgch 52:8071747a7cb3 449 if (RESP_OK != waitFinalResp(_cbCPIN, &_dev.sim))
mazgch 95:8282dbbe1492 450 goto failure;
mazgch 62:a02f026bdd7c 451 } else if (_dev.sim != SIM_READY) {
mazgch 95:8282dbbe1492 452 wait_ms(1000);
mazgch 62:a02f026bdd7c 453 }
mazgch 21:c4d64830bf02 454 }
mazgch 77:55788e619858 455 if (_dev.sim != SIM_READY) {
mazgch 77:55788e619858 456 if (_dev.sim == SIM_MISSING)
mazgch 77:55788e619858 457 ERROR("SIM not inserted\r\n");
mazgch 95:8282dbbe1492 458 goto failure;
mazgch 77:55788e619858 459 }
mazgch 32:8f12ac182bbb 460 // get the manufacturer
mazgch 32:8f12ac182bbb 461 sendFormated("AT+CGMI\r\n");
mazgch 52:8071747a7cb3 462 if (RESP_OK != waitFinalResp(_cbString, _dev.manu))
mazgch 95:8282dbbe1492 463 goto failure;
mazgch 32:8f12ac182bbb 464 // get the model identification
mazgch 32:8f12ac182bbb 465 sendFormated("AT+CGMM\r\n");
mazgch 52:8071747a7cb3 466 if (RESP_OK != waitFinalResp(_cbString, _dev.model))
mazgch 95:8282dbbe1492 467 goto failure;
mazgch 126:bfbb9e19f6e0 468 // get the version
mazgch 126:bfbb9e19f6e0 469 sendFormated("ATI9\r\n");
mazgch 52:8071747a7cb3 470 if (RESP_OK != waitFinalResp(_cbString, _dev.ver))
mazgch 126:bfbb9e19f6e0 471 goto failure;
mazgch 21:c4d64830bf02 472 // Returns the ICCID (Integrated Circuit Card ID) of the SIM-card.
mazgch 21:c4d64830bf02 473 // ICCID is a serial number identifying the SIM.
mazgch 21:c4d64830bf02 474 sendFormated("AT+CCID\r\n");
mazgch 52:8071747a7cb3 475 if (RESP_OK != waitFinalResp(_cbCCID, _dev.ccid))
mazgch 95:8282dbbe1492 476 goto failure;
mazgch 21:c4d64830bf02 477 // Returns the product serial number, IMEI (International Mobile Equipment Identity)
mazgch 21:c4d64830bf02 478 sendFormated("AT+CGSN\r\n");
mazgch 52:8071747a7cb3 479 if (RESP_OK != waitFinalResp(_cbString, _dev.imei))
mazgch 95:8282dbbe1492 480 goto failure;
mazgch 50:d76aece8038f 481 // enable power saving
mazgch 50:d76aece8038f 482 if (_dev.lpm != LPM_DISABLED) {
mazgch 50:d76aece8038f 483 // enable power saving (requires flow control, cts at least)
mazgch 50:d76aece8038f 484 sendFormated("AT+UPSV=1\r\n");
mazgch 52:8071747a7cb3 485 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 486 goto failure;
mazgch 50:d76aece8038f 487 _dev.lpm = LPM_ACTIVE;
mazgch 50:d76aece8038f 488 }
mazgch 79:291df065e345 489 // enable the psd registration unsolicited result code
mazgch 79:291df065e345 490 sendFormated("AT+CGREG=2\r\n");
mazgch 79:291df065e345 491 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 492 goto failure;
mazgch 21:c4d64830bf02 493 }
mazgch 79:291df065e345 494 // enable the network registration unsolicited result code
mazgch 125:25a292afbac6 495 sendFormated("AT+CREG=%d\r\n", (_dev.dev == DEV_LISA_C2) ? 1 : 2);
mazgch 79:291df065e345 496 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 497 goto failure;
mazgch 31:a0bed6c1e05d 498 // Setup SMS in text mode
mazgch 31:a0bed6c1e05d 499 sendFormated("AT+CMGF=1\r\n");
mazgch 52:8071747a7cb3 500 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 501 goto failure;
mazgch 31:a0bed6c1e05d 502 // setup new message indication
mazgch 75:ce6e12067d0c 503 sendFormated("AT+CNMI=2,1\r\n");
mazgch 52:8071747a7cb3 504 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 505 goto failure;
mazgch 21:c4d64830bf02 506 // Request IMSI (International Mobile Subscriber Identification)
mazgch 21:c4d64830bf02 507 sendFormated("AT+CIMI\r\n");
mazgch 52:8071747a7cb3 508 if (RESP_OK != waitFinalResp(_cbString, _dev.imsi))
mazgch 95:8282dbbe1492 509 goto failure;
mazgch 28:4d9509e3b1cf 510 if (status)
mazgch 31:a0bed6c1e05d 511 memcpy(status, &_dev, sizeof(DevStatus));
mazgch 95:8282dbbe1492 512 UNLOCK();
mazgch 31:a0bed6c1e05d 513 return true;
mazgch 95:8282dbbe1492 514 failure:
mazgch 95:8282dbbe1492 515 unlock();
mazgch 95:8282dbbe1492 516 return false;
mazgch 31:a0bed6c1e05d 517 }
mazgch 31:a0bed6c1e05d 518
mazgch 74:208e3e32d263 519 bool MDMParser::powerOff(void)
mazgch 74:208e3e32d263 520 {
mazgch 95:8282dbbe1492 521 bool ok = false;
mazgch 76:f7c3dd568dae 522 if (_init) {
mazgch 95:8282dbbe1492 523 LOCK();
mazgch 76:f7c3dd568dae 524 INFO("Modem::powerOff\r\n");
mazgch 76:f7c3dd568dae 525 sendFormated("AT+CPWROFF\r\n");
mazgch 95:8282dbbe1492 526 if (RESP_OK == waitFinalResp(NULL,NULL,120*1000)) {
mazgch 95:8282dbbe1492 527 _init = false;
mazgch 95:8282dbbe1492 528 ok = true;
mazgch 95:8282dbbe1492 529 }
mazgch 95:8282dbbe1492 530 UNLOCK();
mazgch 76:f7c3dd568dae 531 }
mazgch 95:8282dbbe1492 532 return ok;
mazgch 74:208e3e32d263 533 }
mazgch 74:208e3e32d263 534
mazgch 32:8f12ac182bbb 535 int MDMParser::_cbATI(int type, const char* buf, int len, Dev* dev)
mazgch 31:a0bed6c1e05d 536 {
mazgch 37:cc3433329d66 537 if ((type == TYPE_UNKNOWN) && dev) {
mazgch 125:25a292afbac6 538 if (strstr(buf, "SARA-G35")) *dev = DEV_SARA_G35;
msinig 133:57b208dd96fb 539 else if (strstr(buf, "LISA-U200-03S")) *dev = DEV_LISA_U2_03S;
msinig 133:57b208dd96fb 540 else if (strstr(buf, "LISA-U2")) *dev = DEV_LISA_U2;
mazgch 125:25a292afbac6 541 else if (strstr(buf, "LISA-C2")) *dev = DEV_LISA_C2;
mazgch 125:25a292afbac6 542 else if (strstr(buf, "SARA-U2")) *dev = DEV_SARA_U2;
mazgch 125:25a292afbac6 543 else if (strstr(buf, "LEON-G2")) *dev = DEV_LEON_G2;
mazgch 125:25a292afbac6 544 else if (strstr(buf, "TOBY-L2")) *dev = DEV_TOBY_L2;
mazgch 125:25a292afbac6 545 else if (strstr(buf, "MPCI-L2")) *dev = DEV_MPCI_L2;
mazgch 28:4d9509e3b1cf 546 }
mazgch 31:a0bed6c1e05d 547 return WAIT;
mazgch 31:a0bed6c1e05d 548 }
mazgch 31:a0bed6c1e05d 549
mazgch 31:a0bed6c1e05d 550 int MDMParser::_cbCPIN(int type, const char* buf, int len, Sim* sim)
mazgch 31:a0bed6c1e05d 551 {
mazgch 75:ce6e12067d0c 552 if (sim) {
mazgch 75:ce6e12067d0c 553 if (type == TYPE_PLUS){
mazgch 75:ce6e12067d0c 554 char s[16];
mazgch 75:ce6e12067d0c 555 if (sscanf(buf, "\r\n+CPIN: %[^\r]\r\n", s) >= 1)
mazgch 75:ce6e12067d0c 556 *sim = (0 == strcmp("READY", s)) ? SIM_READY : SIM_PIN;
mazgch 75:ce6e12067d0c 557 } else if (type == TYPE_ERROR) {
mazgch 75:ce6e12067d0c 558 if (strstr(buf, "+CME ERROR: SIM not inserted"))
mazgch 75:ce6e12067d0c 559 *sim = SIM_MISSING;
mazgch 31:a0bed6c1e05d 560 }
mazgch 31:a0bed6c1e05d 561 }
mazgch 31:a0bed6c1e05d 562 return WAIT;
mazgch 21:c4d64830bf02 563 }
mazgch 21:c4d64830bf02 564
mazgch 26:07be5faf8925 565 int MDMParser::_cbCCID(int type, const char* buf, int len, char* ccid)
mazgch 26:07be5faf8925 566 {
mazgch 26:07be5faf8925 567 if ((type == TYPE_PLUS) && ccid){
mazgch 26:07be5faf8925 568 if (sscanf(buf, "\r\n+CCID: %[^\r]\r\n", ccid) == 1)
mazgch 31:a0bed6c1e05d 569 /*TRACE("Got CCID: %s\r\n", ccid)*/;
mazgch 26:07be5faf8925 570 }
mazgch 26:07be5faf8925 571 return WAIT;
mazgch 26:07be5faf8925 572 }
mazgch 26:07be5faf8925 573
mazgch 75:ce6e12067d0c 574 bool MDMParser::registerNet(NetStatus* status /*= NULL*/, int timeout_ms /*= 180000*/)
mazgch 75:ce6e12067d0c 575 {
mazgch 75:ce6e12067d0c 576 Timer timer;
mazgch 75:ce6e12067d0c 577 timer.start();
mazgch 75:ce6e12067d0c 578 INFO("Modem::register\r\n");
mazgch 75:ce6e12067d0c 579 while (!checkNetStatus(status) && !TIMEOUT(timer, timeout_ms))
mazgch 95:8282dbbe1492 580 wait_ms(1000);
mazgch 79:291df065e345 581 if (_net.csd == REG_DENIED) ERROR("CSD Registration Denied\r\n");
mazgch 79:291df065e345 582 if (_net.psd == REG_DENIED) ERROR("PSD Registration Denied\r\n");
mazgch 123:66cef6353b13 583 if (_net.eps == REG_DENIED) ERROR("EPS Registration Denied\r\n");
mazgch 123:66cef6353b13 584 return REG_OK(_net.csd) || REG_OK(_net.psd) || REG_OK(_net.eps);
mazgch 75:ce6e12067d0c 585 }
mazgch 75:ce6e12067d0c 586
mazgch 28:4d9509e3b1cf 587 bool MDMParser::checkNetStatus(NetStatus* status /*= NULL*/)
mazgch 21:c4d64830bf02 588 {
mazgch 95:8282dbbe1492 589 bool ok = false;
mazgch 95:8282dbbe1492 590 LOCK();
mazgch 75:ce6e12067d0c 591 memset(&_net, 0, sizeof(_net));
mazgch 75:ce6e12067d0c 592 _net.lac = 0xFFFF;
mazgch 75:ce6e12067d0c 593 _net.ci = 0xFFFFFFFF;
mazgch 21:c4d64830bf02 594 // check registration
mazgch 21:c4d64830bf02 595 sendFormated("AT+CREG?\r\n");
mazgch 88:135fb4bb7aac 596 waitFinalResp(); // don't fail as service could be not subscribed
mazgch 125:25a292afbac6 597 if (_dev.dev != DEV_LISA_C2) {
mazgch 79:291df065e345 598 // check PSD registration
mazgch 79:291df065e345 599 sendFormated("AT+CGREG?\r\n");
mazgch 88:135fb4bb7aac 600 waitFinalResp(); // don't fail as service could be not subscribed
mazgch 125:25a292afbac6 601 if ((_dev.dev == DEV_TOBY_L2) || (_dev.dev == DEV_MPCI_L2)) {
mazgch 125:25a292afbac6 602 // check EPS network registration
mazgch 125:25a292afbac6 603 sendFormated("AT+CEREG?\r\n");
mazgch 125:25a292afbac6 604 waitFinalResp(); // don't fail as service could be not subscribed
mazgch 125:25a292afbac6 605 }
mazgch 79:291df065e345 606 }
mazgch 123:66cef6353b13 607 if (REG_OK(_net.csd) || REG_OK(_net.psd) || REG_OK(_net.eps))
mazgch 75:ce6e12067d0c 608 {
mazgch 75:ce6e12067d0c 609 // check modem specific status messages
mazgch 125:25a292afbac6 610 if (_dev.dev == DEV_LISA_C2) {
mazgch 75:ce6e12067d0c 611 sendFormated("AT+CSS?\r\n");
mazgch 75:ce6e12067d0c 612 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 613 goto failure;
mazgch 81:3966a5c17037 614 while (1) {
mazgch 81:3966a5c17037 615 // get the Telephone number
mazgch 81:3966a5c17037 616 sendFormated("AT$MDN?\r\n");
mazgch 81:3966a5c17037 617 if (RESP_OK != waitFinalResp(_cbString, _net.num))
mazgch 95:8282dbbe1492 618 goto failure;
mazgch 81:3966a5c17037 619 // check if we have a Mobile Directory Number
mazgch 81:3966a5c17037 620 if (*_net.num && (memcmp(_net.num, "000000", 6) != 0))
mazgch 81:3966a5c17037 621 break;
mazgch 81:3966a5c17037 622
mazgch 81:3966a5c17037 623 INFO("Device not yet activated\r\n");
mazgch 81:3966a5c17037 624 INFO("Make sure you have a valid contract with the network operator for this device.\r\n");
mazgch 81:3966a5c17037 625 // Check if the the version contains a V for Verizon
mazgch 81:3966a5c17037 626 // Verizon: E0.V.xx.00.xxR,
mazgch 81:3966a5c17037 627 // Sprint E0.S.xx.00.xxR
mazgch 81:3966a5c17037 628 if (_dev.ver[3] == 'V') {
mazgch 81:3966a5c17037 629 int i;
mazgch 81:3966a5c17037 630 INFO("Start device over-the-air activation (this can take a few minutes)\r\n");
mazgch 81:3966a5c17037 631 sendFormated("AT+CDV=*22899\r\n");
mazgch 81:3966a5c17037 632 i = 1;
mazgch 82:055dcfcf9dcc 633 if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) {
mazgch 81:3966a5c17037 634 ERROR("Device over-the-air activation failed\r\n");
mazgch 95:8282dbbe1492 635 goto failure;
mazgch 81:3966a5c17037 636 }
mazgch 81:3966a5c17037 637 INFO("Device over-the-air activation successful\r\n");
mazgch 81:3966a5c17037 638
mazgch 81:3966a5c17037 639 INFO("Start PRL over-the-air update (this can take a few minutes)\r\n");
mazgch 81:3966a5c17037 640 sendFormated("AT+CDV=*22891\r\n");
mazgch 81:3966a5c17037 641 i = 1;
mazgch 82:055dcfcf9dcc 642 if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) {
mazgch 81:3966a5c17037 643 ERROR("PRL over-the-air update failed\r\n");
mazgch 95:8282dbbe1492 644 goto failure;
mazgch 81:3966a5c17037 645 }
mazgch 81:3966a5c17037 646 INFO("PRL over-the-air update successful\r\n");
mazgch 81:3966a5c17037 647
mazgch 81:3966a5c17037 648 } else {
mazgch 81:3966a5c17037 649 // Sprint or Aeris
mazgch 81:3966a5c17037 650 INFO("Wait for OMA-DM over-the-air activation (this can take a few minutes)\r\n");
mazgch 95:8282dbbe1492 651 wait_ms(120*1000);
mazgch 81:3966a5c17037 652 }
mazgch 81:3966a5c17037 653 }
mazgch 75:ce6e12067d0c 654 // get the the Network access identifier string
mazgch 75:ce6e12067d0c 655 char nai[64];
mazgch 75:ce6e12067d0c 656 sendFormated("AT$QCMIPNAI?\r\n");
mazgch 75:ce6e12067d0c 657 if (RESP_OK != waitFinalResp(_cbString, nai))
mazgch 95:8282dbbe1492 658 goto failure;
mazgch 75:ce6e12067d0c 659 } else {
mazgch 75:ce6e12067d0c 660 sendFormated("AT+COPS?\r\n");
mazgch 75:ce6e12067d0c 661 if (RESP_OK != waitFinalResp(_cbCOPS, &_net))
mazgch 95:8282dbbe1492 662 goto failure;
mazgch 95:8282dbbe1492 663 // get the MSISDNs related to this subscriber
mazgch 75:ce6e12067d0c 664 sendFormated("AT+CNUM\r\n");
mazgch 75:ce6e12067d0c 665 if (RESP_OK != waitFinalResp(_cbCNUM, _net.num))
mazgch 95:8282dbbe1492 666 goto failure;
mazgch 75:ce6e12067d0c 667 }
mazgch 95:8282dbbe1492 668 // get the signal strength indication
mazgch 75:ce6e12067d0c 669 sendFormated("AT+CSQ\r\n");
mazgch 75:ce6e12067d0c 670 if (RESP_OK != waitFinalResp(_cbCSQ, &_net))
mazgch 95:8282dbbe1492 671 goto failure;
mazgch 75:ce6e12067d0c 672 }
mazgch 28:4d9509e3b1cf 673 if (status) {
mazgch 31:a0bed6c1e05d 674 memcpy(status, &_net, sizeof(NetStatus));
mazgch 25:4045d02e44f1 675 }
mazgch 123:66cef6353b13 676 ok = REG_DONE(_net.csd) &&
mazgch 123:66cef6353b13 677 (REG_DONE(_net.psd) || REG_DONE(_net.eps));
mazgch 95:8282dbbe1492 678 UNLOCK();
mazgch 95:8282dbbe1492 679 return ok;
mazgch 95:8282dbbe1492 680 failure:
mazgch 95:8282dbbe1492 681 unlock();
mazgch 95:8282dbbe1492 682 return false;
mazgch 31:a0bed6c1e05d 683 }
mazgch 31:a0bed6c1e05d 684
mazgch 31:a0bed6c1e05d 685 int MDMParser::_cbCOPS(int type, const char* buf, int len, NetStatus* status)
mazgch 31:a0bed6c1e05d 686 {
mazgch 31:a0bed6c1e05d 687 if ((type == TYPE_PLUS) && status){
mazgch 31:a0bed6c1e05d 688 int act = 99;
msinig 134:2fbd5723e063 689 int mode = 99;
mazgch 31:a0bed6c1e05d 690 // +COPS: <mode>[,<format>,<oper>[,<AcT>]]
msinig 134:2fbd5723e063 691 if (sscanf(buf, "\r\n+COPS: %d,%*d,\"%[^\"]\",%d",&mode,status->opr,&act) >= 1) {
mazgch 31:a0bed6c1e05d 692 if (act == 0) status->act = ACT_GSM; // 0: GSM,
mazgch 31:a0bed6c1e05d 693 else if (act == 2) status->act = ACT_UTRAN; // 2: UTRAN
mazgch 123:66cef6353b13 694 else if (act == 7) status->act = ACT_LTE; // 2: UTRAN
msinig 134:2fbd5723e063 695 if (mode == 0) status->regStatus = COPS_AUTOMATIC_REG;
msinig 134:2fbd5723e063 696 else if (mode == 1) status->regStatus = COPS_MANUAL_REG;
msinig 134:2fbd5723e063 697 else if (mode == 2) status->regStatus = COPS_DISABLED_REG;
mazgch 31:a0bed6c1e05d 698 }
mazgch 31:a0bed6c1e05d 699 }
mazgch 31:a0bed6c1e05d 700 return WAIT;
mazgch 31:a0bed6c1e05d 701 }
mazgch 31:a0bed6c1e05d 702
mazgch 31:a0bed6c1e05d 703 int MDMParser::_cbCNUM(int type, const char* buf, int len, char* num)
mazgch 31:a0bed6c1e05d 704 {
mazgch 31:a0bed6c1e05d 705 if ((type == TYPE_PLUS) && num){
mazgch 31:a0bed6c1e05d 706 int a;
mazgch 31:a0bed6c1e05d 707 if ((sscanf(buf, "\r\n+CNUM: \"My Number\",\"%31[^\"]\",%d", num, &a) == 2) &&
mazgch 31:a0bed6c1e05d 708 ((a == 129) || (a == 145))) {
mazgch 31:a0bed6c1e05d 709 }
mazgch 31:a0bed6c1e05d 710 }
mazgch 31:a0bed6c1e05d 711 return WAIT;
mazgch 31:a0bed6c1e05d 712 }
mazgch 31:a0bed6c1e05d 713
mazgch 54:7ba8e4c218e2 714 int MDMParser::_cbCSQ(int type, const char* buf, int len, NetStatus* status)
mazgch 31:a0bed6c1e05d 715 {
mazgch 54:7ba8e4c218e2 716 if ((type == TYPE_PLUS) && status){
mazgch 54:7ba8e4c218e2 717 int a,b;
mazgch 54:7ba8e4c218e2 718 char _ber[] = { 49, 43, 37, 25, 19, 13, 7, 0 }; // see 3GPP TS 45.008 [20] subclause 8.2.4
mazgch 31:a0bed6c1e05d 719 // +CSQ: <rssi>,<qual>
mazgch 54:7ba8e4c218e2 720 if (sscanf(buf, "\r\n+CSQ: %d,%d",&a,&b) == 2) {
mazgch 121:8da935c2c08c 721 if (a != 99) status->rssi = -113 + 2*a; // 0: -113 1: -111 ... 30: -53 dBm with 2 dBm steps, 31: >-51 dBm
mazgch 54:7ba8e4c218e2 722 if ((b != 99) && (b < sizeof(_ber))) status->ber = _ber[b]; //
mazgch 31:a0bed6c1e05d 723 }
mazgch 31:a0bed6c1e05d 724 }
mazgch 31:a0bed6c1e05d 725 return WAIT;
mazgch 31:a0bed6c1e05d 726 }
mazgch 21:c4d64830bf02 727
mazgch 124:65eb7d58f2da 728
mazgch 124:65eb7d58f2da 729 int MDMParser::_cbUACTIND(int type, const char* buf, int len, int* i)
mazgch 124:65eb7d58f2da 730 {
mazgch 124:65eb7d58f2da 731 if ((type == TYPE_PLUS) && i){
mazgch 124:65eb7d58f2da 732 int a;
mazgch 124:65eb7d58f2da 733 if (sscanf(buf, "\r\n+UACTIND: %d", &a) == 1) {
mazgch 124:65eb7d58f2da 734 *i = a;
mazgch 124:65eb7d58f2da 735 }
mazgch 124:65eb7d58f2da 736 }
mazgch 124:65eb7d58f2da 737 return WAIT;
mazgch 124:65eb7d58f2da 738 }
mazgch 124:65eb7d58f2da 739
mazgch 21:c4d64830bf02 740 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 741 // internet connection
mazgch 21:c4d64830bf02 742
mazgch 128:0415646a9934 743 bool MDMParser::_activateProfile(const char* apn, const char* username, const char* password, Auth auth)
mazgch 128:0415646a9934 744 {
mazgch 128:0415646a9934 745 // Set up the APN
mazgch 128:0415646a9934 746 if (*apn) {
mazgch 128:0415646a9934 747 sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn);
mazgch 128:0415646a9934 748 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 749 return false;
mazgch 128:0415646a9934 750 }
mazgch 128:0415646a9934 751 if (*username) {
mazgch 128:0415646a9934 752 sendFormated("AT+UPSD=" PROFILE ",2,\"%s\"\r\n", username);
mazgch 128:0415646a9934 753 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 754 return false;
mazgch 128:0415646a9934 755 }
mazgch 128:0415646a9934 756 if (*password) {
mazgch 128:0415646a9934 757 sendFormated("AT+UPSD=" PROFILE ",3,\"%s\"\r\n", password);
mazgch 128:0415646a9934 758 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 759 return false;
mazgch 128:0415646a9934 760 }
mazgch 128:0415646a9934 761 // Set up the dynamic IP address assignment.
mazgch 128:0415646a9934 762 sendFormated("AT+UPSD=" PROFILE ",7,\"0.0.0.0\"\r\n");
mazgch 128:0415646a9934 763 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 764 return false;
mazgch 128:0415646a9934 765 // try different Authentication Protocols
mazgch 128:0415646a9934 766 // 0 = none
mazgch 128:0415646a9934 767 // 1 = PAP (Password Authentication Protocol)
mazgch 128:0415646a9934 768 // 2 = CHAP (Challenge Handshake Authentication Protocol)
mazgch 128:0415646a9934 769 for (int i = AUTH_NONE; i <= AUTH_CHAP; i ++) {
mazgch 128:0415646a9934 770 if ((auth == AUTH_DETECT) || (auth == i)) {
mazgch 128:0415646a9934 771 // Set up the Authentication Protocol
mazgch 128:0415646a9934 772 sendFormated("AT+UPSD=" PROFILE ",6,%d\r\n",i);
mazgch 128:0415646a9934 773 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 774 return false;
mazgch 128:0415646a9934 775 // Activate the profile and make connection
mazgch 128:0415646a9934 776 sendFormated("AT+UPSDA=" PROFILE ",3\r\n");
mazgch 128:0415646a9934 777 if (RESP_OK == waitFinalResp(NULL,NULL,150*1000))
mazgch 128:0415646a9934 778 return true;
mazgch 128:0415646a9934 779 }
mazgch 128:0415646a9934 780 }
mazgch 128:0415646a9934 781 return false;
mazgch 128:0415646a9934 782 }
mazgch 128:0415646a9934 783
mazgch 131:965a7cbc1e58 784 bool MDMParser::_activateProfileReuseExternal(void)
mazgch 131:965a7cbc1e58 785 {
mazgch 131:965a7cbc1e58 786 int cid = -1;
mazgch 131:965a7cbc1e58 787 sendFormated("AT+CGDCONT?\r\n");
mazgch 131:965a7cbc1e58 788 if (RESP_OK != waitFinalResp(_cbCGDCONT, &cid))
mazgch 131:965a7cbc1e58 789 return false;
mazgch 131:965a7cbc1e58 790 if (cid == -1)
mazgch 131:965a7cbc1e58 791 return false;
mazgch 131:965a7cbc1e58 792 // we found a context that provides us a valid IP so lets reuse it for the internal IP stack
mazgch 131:965a7cbc1e58 793 sendFormated("AT+UPSD=" PROFILE ",100,%d\r\n", cid);
mazgch 131:965a7cbc1e58 794 if (RESP_OK != waitFinalResp())
mazgch 131:965a7cbc1e58 795 return false;
mazgch 131:965a7cbc1e58 796 // Activate the profile and make connection
mazgch 131:965a7cbc1e58 797 sendFormated("AT+UPSDA=" PROFILE ",3\r\n");
mazgch 131:965a7cbc1e58 798 return (RESP_OK == waitFinalResp(NULL,NULL,150*1000));
mazgch 131:965a7cbc1e58 799 }
mazgch 131:965a7cbc1e58 800
mazgch 128:0415646a9934 801 bool MDMParser::_activateProfileByCid(int cid, const char* apn, const char* username, const char* password, Auth auth)
mazgch 128:0415646a9934 802 {
mazgch 128:0415646a9934 803 sendFormated("AT+CGDCONT=%d,\"IP\",\"%s\"\r\n", cid, apn);
mazgch 128:0415646a9934 804 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 805 return false;
mazgch 128:0415646a9934 806 sendFormated("AT+UAUTHREQ=%d,%d,\"%s\",\"%s\"\r\n", cid, auth, username, password);
mazgch 128:0415646a9934 807 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 808 return false;
mazgch 128:0415646a9934 809 sendFormated("AT+UPSD=" PROFILE ",100,%d\r\n", cid);
mazgch 128:0415646a9934 810 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 811 return false;
mazgch 128:0415646a9934 812 // Activate the profile and make connection
mazgch 128:0415646a9934 813 sendFormated("AT+UPSDA=" PROFILE ",3\r\n");
mazgch 128:0415646a9934 814 return (RESP_OK == waitFinalResp(NULL,NULL,150*1000));
mazgch 128:0415646a9934 815 }
mazgch 128:0415646a9934 816
mazgch 131:965a7cbc1e58 817 int MDMParser::_cbCGDCONT(int type, const char* buf, int len, int* cid)
mazgch 131:965a7cbc1e58 818 {
mazgch 131:965a7cbc1e58 819 // accept with and without leading \r\n in +CGDCONT:
mazgch 131:965a7cbc1e58 820 if ((type == TYPE_PLUS) && (buf[0] == '\r') && (buf[1] == '\n') && (len >= 2))
mazgch 131:965a7cbc1e58 821 buf += 2, len -= 2, type = TYPE_UNKNOWN;
mazgch 131:965a7cbc1e58 822 if (type == TYPE_UNKNOWN) {
mazgch 131:965a7cbc1e58 823 int a,b,c,d,t;
mazgch 131:965a7cbc1e58 824 //+CGDCONT: <cid>,"IP","<apn name>","<ip adr>",0,0,0,0,0,0
mazgch 131:965a7cbc1e58 825 if (sscanf(buf, "+CGDCONT: %d,\"IP\",\"%*[^\"]\",\"" IPSTR "\",%*d,%*d,%*d,%*d,%*d,%*d", &t, &a,&b,&c,&d) == 5) {
mazgch 131:965a7cbc1e58 826 if (IPADR(a,b,c,d) != NOIP)
mazgch 131:965a7cbc1e58 827 *cid = t;
mazgch 131:965a7cbc1e58 828 }
mazgch 131:965a7cbc1e58 829 }
mazgch 131:965a7cbc1e58 830 return WAIT;
mazgch 131:965a7cbc1e58 831 }
mazgch 131:965a7cbc1e58 832
mazgch 79:291df065e345 833 MDMParser::IP MDMParser::join(const char* apn /*= NULL*/, const char* username /*= NULL*/,
mazgch 79:291df065e345 834 const char* password /*= NULL*/, Auth auth /*= AUTH_DETECT*/)
mazgch 21:c4d64830bf02 835 {
mazgch 95:8282dbbe1492 836 LOCK();
mazgch 78:caf0014375cb 837 INFO("Modem::join\r\n");
mazgch 32:8f12ac182bbb 838 _ip = NOIP;
mazgch 125:25a292afbac6 839 if (_dev.dev == DEV_LISA_C2) {
mazgch 76:f7c3dd568dae 840 // make a dumy dns lookup (which will fail, so ignore the result)
mazgch 76:f7c3dd568dae 841 sendFormated("AT+UDNSRN=0,\"u-blox.com\"\r\n");
mazgch 76:f7c3dd568dae 842 waitFinalResp();
mazgch 76:f7c3dd568dae 843 // This fake lookup will enable the IP connection and we
mazgch 76:f7c3dd568dae 844 // should have an IP after this, so we check it
mazgch 76:f7c3dd568dae 845
mazgch 21:c4d64830bf02 846 //Get local IP address
mazgch 21:c4d64830bf02 847 sendFormated("AT+CMIP?\r\n");
mazgch 52:8071747a7cb3 848 if (RESP_OK != waitFinalResp(_cbCMIP, &_ip))
mazgch 95:8282dbbe1492 849 goto failure;
mazgch 125:25a292afbac6 850
mazgch 21:c4d64830bf02 851 } else {
mazgch 21:c4d64830bf02 852 // check gprs attach status
mazgch 72:d1e943ad6558 853 sendFormated("AT+CGATT=1\r\n");
mazgch 74:208e3e32d263 854 if (RESP_OK != waitFinalResp(NULL,NULL,3*60*1000))
mazgch 95:8282dbbe1492 855 goto failure;
mazgch 31:a0bed6c1e05d 856 // Check the profile
mazgch 31:a0bed6c1e05d 857 int a = 0;
mazgch 79:291df065e345 858 bool force = true;
mazgch 31:a0bed6c1e05d 859 sendFormated("AT+UPSND=" PROFILE ",8\r\n");
mazgch 52:8071747a7cb3 860 if (RESP_OK != waitFinalResp(_cbUPSND, &a))
mazgch 95:8282dbbe1492 861 goto failure;
mazgch 79:291df065e345 862 if (a == 1 && force) {
mazgch 31:a0bed6c1e05d 863 // disconnect the profile already if it is connected
mazgch 31:a0bed6c1e05d 864 sendFormated("AT+UPSDA=" PROFILE ",4\r\n");
mazgch 58:e38a2e942fbb 865 if (RESP_OK != waitFinalResp(NULL,NULL,40*1000))
mazgch 95:8282dbbe1492 866 goto failure;
mazgch 79:291df065e345 867 a = 0;
mazgch 31:a0bed6c1e05d 868 }
mazgch 79:291df065e345 869 if (a == 0) {
mazgch 84:a05edb010176 870 bool ok = false;
mazgch 84:a05edb010176 871 // try to lookup the apn settings from our local database by mccmnc
mazgch 84:a05edb010176 872 const char* config = NULL;
mazgch 88:135fb4bb7aac 873 if (!apn && !username && !password)
mazgch 88:135fb4bb7aac 874 config = apnconfig(_dev.imsi);
mazgch 84:a05edb010176 875 do {
mazgch 84:a05edb010176 876 if (config) {
mazgch 85:dd8f4f0d0ca9 877 apn = _APN_GET(config);
mazgch 85:dd8f4f0d0ca9 878 username = _APN_GET(config);
mazgch 85:dd8f4f0d0ca9 879 password = _APN_GET(config);
mazgch 79:291df065e345 880 }
mazgch 125:25a292afbac6 881 // convert pointer to empty strings
mazgch 125:25a292afbac6 882 apn = apn ? apn : "";
mazgch 125:25a292afbac6 883 username = username ? username : "";
mazgch 125:25a292afbac6 884 password = password ? password : "";
mazgch 125:25a292afbac6 885 auth = (*username && *password) ? auth : AUTH_NONE;
mazgch 125:25a292afbac6 886 TRACE("Testing APN Settings(\"%s\",\"%s\",\"%s\",%d)\r\n", apn, username, password, auth);
mazgch 128:0415646a9934 887 if ((_dev.dev != DEV_TOBY_L2) && (_dev.dev != DEV_MPCI_L2))
mazgch 128:0415646a9934 888 ok = _activateProfile(apn, username, password, auth);
mazgch 131:965a7cbc1e58 889 else {
mazgch 131:965a7cbc1e58 890 ok = _activateProfileReuseExternal();
mazgch 131:965a7cbc1e58 891 if (ok)
mazgch 131:965a7cbc1e58 892 TRACE("Reusing External Context\r\n");
mazgch 131:965a7cbc1e58 893 else
mazgch 131:965a7cbc1e58 894 ok = _activateProfileByCid(1, apn, username, password, auth);
mazgch 131:965a7cbc1e58 895 }
mazgch 99:3116d3e900ed 896 } while (!ok && config && *config); // maybe use next setting ?
mazgch 84:a05edb010176 897 if (!ok) {
mazgch 79:291df065e345 898 ERROR("Your modem APN/password/username may be wrong\r\n");
mazgch 95:8282dbbe1492 899 goto failure;
mazgch 79:291df065e345 900 }
mazgch 74:208e3e32d263 901 }
mazgch 21:c4d64830bf02 902 //Get local IP address
mazgch 21:c4d64830bf02 903 sendFormated("AT+UPSND=" PROFILE ",0\r\n");
mazgch 52:8071747a7cb3 904 if (RESP_OK != waitFinalResp(_cbUPSND, &_ip))
mazgch 95:8282dbbe1492 905 goto failure;
mazgch 31:a0bed6c1e05d 906 }
mazgch 95:8282dbbe1492 907 UNLOCK();
mazgch 32:8f12ac182bbb 908 return _ip;
mazgch 95:8282dbbe1492 909 failure:
mazgch 95:8282dbbe1492 910 unlock();
mazgch 95:8282dbbe1492 911 return NOIP;
mazgch 31:a0bed6c1e05d 912 }
mazgch 31:a0bed6c1e05d 913
mazgch 84:a05edb010176 914 int MDMParser::_cbUDOPN(int type, const char* buf, int len, char* mccmnc)
mazgch 84:a05edb010176 915 {
mazgch 84:a05edb010176 916 if ((type == TYPE_PLUS) && mccmnc) {
mazgch 84:a05edb010176 917 if (sscanf(buf, "\r\n+UDOPN: 0,\"%[^\"]\"", mccmnc) == 1)
mazgch 84:a05edb010176 918 ;
mazgch 84:a05edb010176 919 }
mazgch 84:a05edb010176 920 return WAIT;
mazgch 84:a05edb010176 921 }
mazgch 84:a05edb010176 922
mazgch 32:8f12ac182bbb 923 int MDMParser::_cbCMIP(int type, const char* buf, int len, IP* ip)
mazgch 32:8f12ac182bbb 924 {
mazgch 102:fb982ff9da82 925 if ((type == TYPE_UNKNOWN) && ip) {
mazgch 32:8f12ac182bbb 926 int a,b,c,d;
mazgch 102:fb982ff9da82 927 if (sscanf(buf, "\r\n" IPSTR, &a,&b,&c,&d) == 4)
mazgch 32:8f12ac182bbb 928 *ip = IPADR(a,b,c,d);
mazgch 32:8f12ac182bbb 929 }
mazgch 32:8f12ac182bbb 930 return WAIT;
mazgch 32:8f12ac182bbb 931 }
mazgch 32:8f12ac182bbb 932
mazgch 31:a0bed6c1e05d 933 int MDMParser::_cbUPSND(int type, const char* buf, int len, int* act)
mazgch 31:a0bed6c1e05d 934 {
mazgch 31:a0bed6c1e05d 935 if ((type == TYPE_PLUS) && act) {
mazgch 31:a0bed6c1e05d 936 if (sscanf(buf, "\r\n+UPSND: %*d,%*d,%d", act) == 1)
mazgch 31:a0bed6c1e05d 937 /*nothing*/;
mazgch 21:c4d64830bf02 938 }
mazgch 31:a0bed6c1e05d 939 return WAIT;
mazgch 31:a0bed6c1e05d 940 }
mazgch 31:a0bed6c1e05d 941
mazgch 31:a0bed6c1e05d 942 int MDMParser::_cbUPSND(int type, const char* buf, int len, IP* ip)
mazgch 31:a0bed6c1e05d 943 {
mazgch 31:a0bed6c1e05d 944 if ((type == TYPE_PLUS) && ip) {
mazgch 31:a0bed6c1e05d 945 int a,b,c,d;
mazgch 31:a0bed6c1e05d 946 // +UPSND=<profile_id>,<param_tag>[,<dynamic_param_val>]
mazgch 31:a0bed6c1e05d 947 if (sscanf(buf, "\r\n+UPSND: " PROFILE ",0,\"" IPSTR "\"", &a,&b,&c,&d) == 4)
mazgch 31:a0bed6c1e05d 948 *ip = IPADR(a,b,c,d);
mazgch 31:a0bed6c1e05d 949 }
mazgch 31:a0bed6c1e05d 950 return WAIT;
mazgch 31:a0bed6c1e05d 951 }
mazgch 31:a0bed6c1e05d 952
mazgch 31:a0bed6c1e05d 953 int MDMParser::_cbUDNSRN(int type, const char* buf, int len, IP* ip)
mazgch 31:a0bed6c1e05d 954 {
mazgch 31:a0bed6c1e05d 955 if ((type == TYPE_PLUS) && ip) {
mazgch 31:a0bed6c1e05d 956 int a,b,c,d;
mazgch 95:8282dbbe1492 957 if (sscanf(buf, "\r\n+UDNSRN: \"" IPSTR "\"", &a,&b,&c,&d) == 4)
mazgch 31:a0bed6c1e05d 958 *ip = IPADR(a,b,c,d);
mazgch 31:a0bed6c1e05d 959 }
mazgch 31:a0bed6c1e05d 960 return WAIT;
mazgch 21:c4d64830bf02 961 }
mazgch 21:c4d64830bf02 962
mazgch 21:c4d64830bf02 963 bool MDMParser::disconnect(void)
mazgch 21:c4d64830bf02 964 {
mazgch 95:8282dbbe1492 965 bool ok = false;
mazgch 95:8282dbbe1492 966 LOCK();
mazgch 74:208e3e32d263 967 INFO("Modem::disconnect\r\n");
mazgch 95:8282dbbe1492 968 if (_ip != NOIP) {
mazgch 125:25a292afbac6 969 if (_dev.dev == DEV_LISA_C2) {
mazgch 95:8282dbbe1492 970 // There something to do here
mazgch 95:8282dbbe1492 971 _ip = NOIP;
mazgch 95:8282dbbe1492 972 ok = true;
mazgch 95:8282dbbe1492 973 } else {
mazgch 95:8282dbbe1492 974 sendFormated("AT+UPSDA=" PROFILE ",4\r\n");
mazgch 95:8282dbbe1492 975 if (RESP_OK != waitFinalResp()) {
mazgch 95:8282dbbe1492 976 _ip = NOIP;
mazgch 95:8282dbbe1492 977 ok = true;
mazgch 95:8282dbbe1492 978 }
mazgch 95:8282dbbe1492 979 }
mazgch 21:c4d64830bf02 980 }
mazgch 95:8282dbbe1492 981 UNLOCK();
mazgch 95:8282dbbe1492 982 return ok;
mazgch 21:c4d64830bf02 983 }
mazgch 21:c4d64830bf02 984
mazgch 31:a0bed6c1e05d 985 MDMParser::IP MDMParser::gethostbyname(const char* host)
mazgch 21:c4d64830bf02 986 {
mazgch 31:a0bed6c1e05d 987 IP ip = NOIP;
mazgch 31:a0bed6c1e05d 988 int a,b,c,d;
mazgch 31:a0bed6c1e05d 989 if (sscanf(host, IPSTR, &a,&b,&c,&d) == 4)
mazgch 31:a0bed6c1e05d 990 ip = IPADR(a,b,c,d);
mazgch 31:a0bed6c1e05d 991 else {
mazgch 95:8282dbbe1492 992 LOCK();
mazgch 31:a0bed6c1e05d 993 sendFormated("AT+UDNSRN=0,\"%s\"\r\n", host);
mazgch 52:8071747a7cb3 994 if (RESP_OK != waitFinalResp(_cbUDNSRN, &ip))
mazgch 95:8282dbbe1492 995 ip = NOIP;
mazgch 95:8282dbbe1492 996 UNLOCK();
mazgch 21:c4d64830bf02 997 }
mazgch 31:a0bed6c1e05d 998 return ip;
mazgch 21:c4d64830bf02 999 }
mazgch 21:c4d64830bf02 1000
mazgch 21:c4d64830bf02 1001 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 1002 // sockets
mazgch 21:c4d64830bf02 1003
mazgch 103:197fa7920ad8 1004 int MDMParser::_cbUSOCR(int type, const char* buf, int len, int* handle)
mazgch 21:c4d64830bf02 1005 {
mazgch 103:197fa7920ad8 1006 if ((type == TYPE_PLUS) && handle) {
mazgch 108:254bf037f83f 1007 // +USOCR: socket
mazgch 108:254bf037f83f 1008 if (sscanf(buf, "\r\n+USOCR: %d", handle) == 1)
mazgch 108:254bf037f83f 1009 /*nothing*/;
mazgch 21:c4d64830bf02 1010 }
mazgch 21:c4d64830bf02 1011 return WAIT;
mazgch 21:c4d64830bf02 1012 }
mazgch 21:c4d64830bf02 1013
mazgch 63:42cb563a25bc 1014 int MDMParser::socketSocket(IpProtocol ipproto, int port)
mazgch 21:c4d64830bf02 1015 {
mazgch 103:197fa7920ad8 1016 int socket;
mazgch 95:8282dbbe1492 1017 LOCK();
mazgch 103:197fa7920ad8 1018 // find an free socket
mazgch 103:197fa7920ad8 1019 socket = _findSocket();
mazgch 47:9a89e5195721 1020 TRACE("socketSocket(%d)\r\n", ipproto);
mazgch 95:8282dbbe1492 1021 if (socket != SOCKET_ERROR) {
mazgch 106:18aeacdae391 1022 if (ipproto == IPPROTO_UDP) {
mazgch 106:18aeacdae391 1023 // sending port can only be set on 2G/3G modules
mazgch 125:25a292afbac6 1024 if ((port != -1) && (_dev.dev != DEV_LISA_C2)) {
mazgch 106:18aeacdae391 1025 sendFormated("AT+USOCR=17,%d\r\n", port);
mazgch 106:18aeacdae391 1026 } else {
mazgch 106:18aeacdae391 1027 sendFormated("AT+USOCR=17\r\n");
mazgch 106:18aeacdae391 1028 }
mazgch 103:197fa7920ad8 1029 } else /*(ipproto == IPPROTO_TCP)*/ {
mazgch 103:197fa7920ad8 1030 sendFormated("AT+USOCR=6\r\n");
mazgch 103:197fa7920ad8 1031 }
mazgch 103:197fa7920ad8 1032 int handle = SOCKET_ERROR;
mazgch 103:197fa7920ad8 1033 if ((RESP_OK == waitFinalResp(_cbUSOCR, &handle)) &&
mazgch 103:197fa7920ad8 1034 (handle != SOCKET_ERROR)) {
mazgch 103:197fa7920ad8 1035 TRACE("Socket %d: handle %d was created\r\n", socket, handle);
mazgch 103:197fa7920ad8 1036 _sockets[socket].handle = handle;
mazgch 103:197fa7920ad8 1037 _sockets[socket].timeout_ms = TIMEOUT_BLOCKING;
mazgch 103:197fa7920ad8 1038 _sockets[socket].connected = false;
mazgch 103:197fa7920ad8 1039 _sockets[socket].pending = 0;
mazgch 103:197fa7920ad8 1040 }
mazgch 103:197fa7920ad8 1041 else
mazgch 103:197fa7920ad8 1042 socket = SOCKET_ERROR;
mazgch 95:8282dbbe1492 1043 }
mazgch 95:8282dbbe1492 1044 UNLOCK();
mazgch 21:c4d64830bf02 1045 return socket;
mazgch 21:c4d64830bf02 1046 }
mazgch 21:c4d64830bf02 1047
mazgch 21:c4d64830bf02 1048 bool MDMParser::socketConnect(int socket, const char * host, int port)
mazgch 21:c4d64830bf02 1049 {
mazgch 31:a0bed6c1e05d 1050 IP ip = gethostbyname(host);
mazgch 31:a0bed6c1e05d 1051 if (ip == NOIP)
mazgch 21:c4d64830bf02 1052 return false;
mazgch 21:c4d64830bf02 1053 // connect to socket
mazgch 95:8282dbbe1492 1054 bool ok = false;
mazgch 95:8282dbbe1492 1055 LOCK();
mazgch 103:197fa7920ad8 1056 if (ISSOCKET(socket) && (!_sockets[socket].connected)) {
mazgch 95:8282dbbe1492 1057 TRACE("socketConnect(%d,%s,%d)\r\n", socket,host,port);
mazgch 103:197fa7920ad8 1058 sendFormated("AT+USOCO=%d,\"" IPSTR "\",%d\r\n", _sockets[socket].handle, IPNUM(ip), port);
mazgch 95:8282dbbe1492 1059 if (RESP_OK == waitFinalResp())
mazgch 103:197fa7920ad8 1060 ok = _sockets[socket].connected = true;
mazgch 95:8282dbbe1492 1061 }
mazgch 95:8282dbbe1492 1062 UNLOCK();
mazgch 95:8282dbbe1492 1063 return ok;
mazgch 21:c4d64830bf02 1064 }
mazgch 21:c4d64830bf02 1065
mazgch 44:9d12223b78ff 1066 bool MDMParser::socketIsConnected(int socket)
mazgch 44:9d12223b78ff 1067 {
mazgch 95:8282dbbe1492 1068 bool ok = false;
mazgch 95:8282dbbe1492 1069 LOCK();
mazgch 103:197fa7920ad8 1070 ok = ISSOCKET(socket) && _sockets[socket].connected;
mazgch 107:436ee320efd6 1071 TRACE("socketIsConnected(%d) %s\r\n", socket, ok?"yes":"no");
mazgch 95:8282dbbe1492 1072 UNLOCK();
mazgch 95:8282dbbe1492 1073 return ok;
mazgch 44:9d12223b78ff 1074 }
mazgch 44:9d12223b78ff 1075
mazgch 66:69072b3c5bca 1076 bool MDMParser::socketSetBlocking(int socket, int timeout_ms)
mazgch 44:9d12223b78ff 1077 {
mazgch 95:8282dbbe1492 1078 bool ok = false;
mazgch 95:8282dbbe1492 1079 LOCK();
mazgch 103:197fa7920ad8 1080 TRACE("socketSetBlocking(%d,%d)\r\n", socket,timeout_ms);
mazgch 95:8282dbbe1492 1081 if (ISSOCKET(socket)) {
mazgch 95:8282dbbe1492 1082 _sockets[socket].timeout_ms = timeout_ms;
mazgch 95:8282dbbe1492 1083 ok = true;
mazgch 95:8282dbbe1492 1084 }
mazgch 95:8282dbbe1492 1085 UNLOCK();
mazgch 95:8282dbbe1492 1086 return ok;
mazgch 44:9d12223b78ff 1087 }
mazgch 44:9d12223b78ff 1088
mazgch 21:c4d64830bf02 1089 bool MDMParser::socketClose(int socket)
mazgch 21:c4d64830bf02 1090 {
mazgch 95:8282dbbe1492 1091 bool ok = false;
mazgch 95:8282dbbe1492 1092 LOCK();
mazgch 103:197fa7920ad8 1093 if (ISSOCKET(socket) && _sockets[socket].connected) {
mazgch 95:8282dbbe1492 1094 TRACE("socketClose(%d)\r\n", socket);
mazgch 103:197fa7920ad8 1095 sendFormated("AT+USOCL=%d\r\n", _sockets[socket].handle);
mazgch 95:8282dbbe1492 1096 if (RESP_OK == waitFinalResp()) {
mazgch 103:197fa7920ad8 1097 _sockets[socket].connected = false;
mazgch 95:8282dbbe1492 1098 ok = true;
mazgch 95:8282dbbe1492 1099 }
mazgch 95:8282dbbe1492 1100 }
mazgch 95:8282dbbe1492 1101 UNLOCK();
mazgch 95:8282dbbe1492 1102 return ok;
mazgch 21:c4d64830bf02 1103 }
mazgch 21:c4d64830bf02 1104
mazgch 21:c4d64830bf02 1105 bool MDMParser::socketFree(int socket)
mazgch 21:c4d64830bf02 1106 {
mazgch 95:8282dbbe1492 1107 // make sure it is closed
mazgch 21:c4d64830bf02 1108 socketClose(socket);
mazgch 95:8282dbbe1492 1109 bool ok = true;
mazgch 95:8282dbbe1492 1110 LOCK();
mazgch 103:197fa7920ad8 1111 if (ISSOCKET(socket)) {
mazgch 103:197fa7920ad8 1112 TRACE("socketFree(%d)\r\n", socket);
mazgch 103:197fa7920ad8 1113 _sockets[socket].handle = SOCKET_ERROR;
mazgch 103:197fa7920ad8 1114 _sockets[socket].timeout_ms = TIMEOUT_BLOCKING;
mazgch 103:197fa7920ad8 1115 _sockets[socket].connected = false;
mazgch 103:197fa7920ad8 1116 _sockets[socket].pending = 0;
mazgch 95:8282dbbe1492 1117 ok = true;
mazgch 95:8282dbbe1492 1118 }
mazgch 95:8282dbbe1492 1119 UNLOCK();
mazgch 95:8282dbbe1492 1120 return ok;
mazgch 21:c4d64830bf02 1121 }
mazgch 21:c4d64830bf02 1122
mazgch 69:4d6fa520dfca 1123 #define USO_MAX_WRITE 1024 //!< maximum number of bytes to write to socket
mazgch 69:4d6fa520dfca 1124
mazgch 21:c4d64830bf02 1125 int MDMParser::socketSend(int socket, const char * buf, int len)
mazgch 21:c4d64830bf02 1126 {
mazgch 47:9a89e5195721 1127 TRACE("socketSend(%d,,%d)\r\n", socket,len);
mazgch 68:33a96cf64986 1128 int cnt = len;
mazgch 68:33a96cf64986 1129 while (cnt > 0) {
mazgch 69:4d6fa520dfca 1130 int blk = USO_MAX_WRITE;
mazgch 68:33a96cf64986 1131 if (cnt < blk)
mazgch 68:33a96cf64986 1132 blk = cnt;
mazgch 95:8282dbbe1492 1133 bool ok = false;
mazgch 95:8282dbbe1492 1134 LOCK();
mazgch 103:197fa7920ad8 1135 if (ISSOCKET(socket)) {
mazgch 103:197fa7920ad8 1136 sendFormated("AT+USOWR=%d,%d\r\n",_sockets[socket].handle,blk);
mazgch 103:197fa7920ad8 1137 if (RESP_PROMPT == waitFinalResp()) {
mazgch 103:197fa7920ad8 1138 wait_ms(50);
mazgch 103:197fa7920ad8 1139 send(buf, blk);
mazgch 103:197fa7920ad8 1140 if (RESP_OK == waitFinalResp())
mazgch 103:197fa7920ad8 1141 ok = true;
mazgch 103:197fa7920ad8 1142 }
mazgch 95:8282dbbe1492 1143 }
mazgch 95:8282dbbe1492 1144 UNLOCK();
mazgch 95:8282dbbe1492 1145 if (!ok)
mazgch 21:c4d64830bf02 1146 return SOCKET_ERROR;
mazgch 68:33a96cf64986 1147 buf += blk;
mazgch 68:33a96cf64986 1148 cnt -= blk;
mazgch 21:c4d64830bf02 1149 }
mazgch 68:33a96cf64986 1150 return (len - cnt);
mazgch 21:c4d64830bf02 1151 }
mazgch 21:c4d64830bf02 1152
mazgch 21:c4d64830bf02 1153 int MDMParser::socketSendTo(int socket, IP ip, int port, const char * buf, int len)
mazgch 21:c4d64830bf02 1154 {
mazgch 103:197fa7920ad8 1155 TRACE("socketSendTo(%d," IPSTR ",%d,,%d)\r\n", socket,IPNUM(ip),port,len);
mazgch 68:33a96cf64986 1156 int cnt = len;
mazgch 68:33a96cf64986 1157 while (cnt > 0) {
mazgch 69:4d6fa520dfca 1158 int blk = USO_MAX_WRITE;
mazgch 68:33a96cf64986 1159 if (cnt < blk)
mazgch 68:33a96cf64986 1160 blk = cnt;
mazgch 95:8282dbbe1492 1161 bool ok = false;
mazgch 95:8282dbbe1492 1162 LOCK();
mazgch 103:197fa7920ad8 1163 if (ISSOCKET(socket)) {
mazgch 103:197fa7920ad8 1164 sendFormated("AT+USOST=%d,\"" IPSTR "\",%d,%d\r\n",_sockets[socket].handle,IPNUM(ip),port,blk);
mazgch 103:197fa7920ad8 1165 if (RESP_PROMPT == waitFinalResp()) {
mazgch 103:197fa7920ad8 1166 wait_ms(50);
mazgch 103:197fa7920ad8 1167 send(buf, blk);
mazgch 103:197fa7920ad8 1168 if (RESP_OK == waitFinalResp())
mazgch 103:197fa7920ad8 1169 ok = true;
mazgch 103:197fa7920ad8 1170 }
mazgch 95:8282dbbe1492 1171 }
mazgch 95:8282dbbe1492 1172 UNLOCK();
mazgch 95:8282dbbe1492 1173 if (!ok)
mazgch 21:c4d64830bf02 1174 return SOCKET_ERROR;
mazgch 68:33a96cf64986 1175 buf += blk;
mazgch 68:33a96cf64986 1176 cnt -= blk;
mazgch 21:c4d64830bf02 1177 }
mazgch 68:33a96cf64986 1178 return (len - cnt);
mazgch 21:c4d64830bf02 1179 }
mazgch 21:c4d64830bf02 1180
mazgch 21:c4d64830bf02 1181 int MDMParser::socketReadable(int socket)
mazgch 21:c4d64830bf02 1182 {
mazgch 95:8282dbbe1492 1183 int pending = SOCKET_ERROR;
mazgch 95:8282dbbe1492 1184 LOCK();
mazgch 103:197fa7920ad8 1185 if (ISSOCKET(socket) && _sockets[socket].connected) {
mazgch 95:8282dbbe1492 1186 TRACE("socketReadable(%d)\r\n", socket);
mazgch 95:8282dbbe1492 1187 // allow to receive unsolicited commands
mazgch 95:8282dbbe1492 1188 waitFinalResp(NULL, NULL, 0);
mazgch 103:197fa7920ad8 1189 if (_sockets[socket].connected)
mazgch 95:8282dbbe1492 1190 pending = _sockets[socket].pending;
mazgch 95:8282dbbe1492 1191 }
mazgch 95:8282dbbe1492 1192 UNLOCK();
mazgch 95:8282dbbe1492 1193 return pending;
mazgch 21:c4d64830bf02 1194 }
mazgch 21:c4d64830bf02 1195
mazgch 21:c4d64830bf02 1196 int MDMParser::_cbUSORD(int type, const char* buf, int len, char* out)
mazgch 21:c4d64830bf02 1197 {
mazgch 21:c4d64830bf02 1198 if ((type == TYPE_PLUS) && out) {
mazgch 21:c4d64830bf02 1199 int sz, sk;
mazgch 21:c4d64830bf02 1200 if ((sscanf(buf, "\r\n+USORD: %d,%d,", &sk, &sz) == 2) &&
mazgch 21:c4d64830bf02 1201 (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
mazgch 21:c4d64830bf02 1202 memcpy(out, &buf[len-1-sz], sz);
mazgch 21:c4d64830bf02 1203 }
mazgch 21:c4d64830bf02 1204 }
mazgch 21:c4d64830bf02 1205 return WAIT;
mazgch 21:c4d64830bf02 1206 }
mazgch 21:c4d64830bf02 1207
mazgch 21:c4d64830bf02 1208 int MDMParser::socketRecv(int socket, char* buf, int len)
mazgch 21:c4d64830bf02 1209 {
mazgch 21:c4d64830bf02 1210 int cnt = 0;
mazgch 47:9a89e5195721 1211 TRACE("socketRecv(%d,,%d)\r\n", socket, len);
mazgch 95:8282dbbe1492 1212 #ifdef MDM_DEBUG
mazgch 21:c4d64830bf02 1213 memset(buf, '\0', len);
mazgch 95:8282dbbe1492 1214 #endif
mazgch 44:9d12223b78ff 1215 Timer timer;
mazgch 44:9d12223b78ff 1216 timer.start();
mazgch 21:c4d64830bf02 1217 while (len) {
mazgch 69:4d6fa520dfca 1218 int blk = MAX_SIZE; // still need space for headers and unsolicited commands
mazgch 21:c4d64830bf02 1219 if (len < blk) blk = len;
mazgch 95:8282dbbe1492 1220 bool ok = false;
mazgch 95:8282dbbe1492 1221 LOCK();
mazgch 95:8282dbbe1492 1222 if (ISSOCKET(socket)) {
mazgch 103:197fa7920ad8 1223 if (_sockets[socket].connected) {
mazgch 95:8282dbbe1492 1224 if (_sockets[socket].pending < blk)
mazgch 95:8282dbbe1492 1225 blk = _sockets[socket].pending;
mazgch 95:8282dbbe1492 1226 if (blk > 0) {
mazgch 103:197fa7920ad8 1227 sendFormated("AT+USORD=%d,%d\r\n",_sockets[socket].handle, blk);
mazgch 95:8282dbbe1492 1228 if (RESP_OK == waitFinalResp(_cbUSORD, buf)) {
mazgch 95:8282dbbe1492 1229 _sockets[socket].pending -= blk;
mazgch 95:8282dbbe1492 1230 len -= blk;
mazgch 95:8282dbbe1492 1231 cnt += blk;
mazgch 95:8282dbbe1492 1232 buf += blk;
mazgch 95:8282dbbe1492 1233 ok = true;
mazgch 95:8282dbbe1492 1234 }
mazgch 95:8282dbbe1492 1235 } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) {
mazgch 95:8282dbbe1492 1236 ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs
mazgch 95:8282dbbe1492 1237 } else {
mazgch 95:8282dbbe1492 1238 len = 0;
mazgch 95:8282dbbe1492 1239 ok = true;
mazgch 95:8282dbbe1492 1240 }
mazgch 103:197fa7920ad8 1241 } else {
mazgch 95:8282dbbe1492 1242 len = 0;
mazgch 95:8282dbbe1492 1243 ok = true;
mazgch 21:c4d64830bf02 1244 }
mazgch 21:c4d64830bf02 1245 }
mazgch 95:8282dbbe1492 1246 UNLOCK();
mazgch 107:436ee320efd6 1247 if (!ok) {
mazgch 107:436ee320efd6 1248 TRACE("socketRecv: ERROR\r\n");
mazgch 95:8282dbbe1492 1249 return SOCKET_ERROR;
mazgch 107:436ee320efd6 1250 }
mazgch 21:c4d64830bf02 1251 }
mazgch 107:436ee320efd6 1252 TRACE("socketRecv: %d \"%*s\"\r\n", cnt, cnt, buf-cnt);
mazgch 21:c4d64830bf02 1253 return cnt;
mazgch 21:c4d64830bf02 1254 }
mazgch 21:c4d64830bf02 1255
mazgch 21:c4d64830bf02 1256 int MDMParser::_cbUSORF(int type, const char* buf, int len, USORFparam* param)
mazgch 21:c4d64830bf02 1257 {
mazgch 21:c4d64830bf02 1258 if ((type == TYPE_PLUS) && param) {
mazgch 21:c4d64830bf02 1259 int sz, sk, p, a,b,c,d;
mazgch 95:8282dbbe1492 1260 int r = sscanf(buf, "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,",
mazgch 95:8282dbbe1492 1261 &sk,&a,&b,&c,&d,&p,&sz);
mazgch 95:8282dbbe1492 1262 if ((r == 7) && (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
mazgch 21:c4d64830bf02 1263 memcpy(param->buf, &buf[len-1-sz], sz);
mazgch 21:c4d64830bf02 1264 param->ip = IPADR(a,b,c,d);
mazgch 21:c4d64830bf02 1265 param->port = p;
mazgch 21:c4d64830bf02 1266 }
mazgch 21:c4d64830bf02 1267 }
mazgch 21:c4d64830bf02 1268 return WAIT;
mazgch 21:c4d64830bf02 1269 }
mazgch 21:c4d64830bf02 1270
mazgch 63:42cb563a25bc 1271 int MDMParser::socketRecvFrom(int socket, IP* ip, int* port, char* buf, int len)
mazgch 21:c4d64830bf02 1272 {
mazgch 21:c4d64830bf02 1273 int cnt = 0;
mazgch 63:42cb563a25bc 1274 TRACE("socketRecvFrom(%d,,%d)\r\n", socket, len);
mazgch 95:8282dbbe1492 1275 #ifdef MDM_DEBUG
mazgch 21:c4d64830bf02 1276 memset(buf, '\0', len);
mazgch 95:8282dbbe1492 1277 #endif
mazgch 44:9d12223b78ff 1278 Timer timer;
mazgch 44:9d12223b78ff 1279 timer.start();
mazgch 21:c4d64830bf02 1280 while (len) {
mazgch 69:4d6fa520dfca 1281 int blk = MAX_SIZE; // still need space for headers and unsolicited commands
mazgch 21:c4d64830bf02 1282 if (len < blk) blk = len;
mazgch 95:8282dbbe1492 1283 bool ok = false;
mazgch 95:8282dbbe1492 1284 LOCK();
mazgch 95:8282dbbe1492 1285 if (ISSOCKET(socket)) {
mazgch 95:8282dbbe1492 1286 if (_sockets[socket].pending < blk)
mazgch 95:8282dbbe1492 1287 blk = _sockets[socket].pending;
mazgch 95:8282dbbe1492 1288 if (blk > 0) {
mazgch 103:197fa7920ad8 1289 sendFormated("AT+USORF=%d,%d\r\n",_sockets[socket].handle, blk);
mazgch 95:8282dbbe1492 1290 USORFparam param;
mazgch 95:8282dbbe1492 1291 param.buf = buf;
mazgch 95:8282dbbe1492 1292 if (RESP_OK == waitFinalResp(_cbUSORF, &param)) {
mazgch 95:8282dbbe1492 1293 _sockets[socket].pending -= blk;
mazgch 95:8282dbbe1492 1294 *ip = param.ip;
mazgch 95:8282dbbe1492 1295 *port = param.port;
mazgch 95:8282dbbe1492 1296 len -= blk;
mazgch 95:8282dbbe1492 1297 cnt += blk;
mazgch 95:8282dbbe1492 1298 buf += blk;
mazgch 95:8282dbbe1492 1299 len = 0; // done
mazgch 95:8282dbbe1492 1300 ok = true;
mazgch 95:8282dbbe1492 1301 }
mazgch 95:8282dbbe1492 1302 } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) {
mazgch 95:8282dbbe1492 1303 ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs
mazgch 95:8282dbbe1492 1304 } else {
mazgch 95:8282dbbe1492 1305 len = 0; // no more data and socket closed or timed-out
mazgch 95:8282dbbe1492 1306 ok = true;
mazgch 21:c4d64830bf02 1307 }
mazgch 95:8282dbbe1492 1308 }
mazgch 95:8282dbbe1492 1309 UNLOCK();
mazgch 107:436ee320efd6 1310 if (!ok) {
mazgch 107:436ee320efd6 1311 TRACE("socketRecv: ERROR\r\n");
mazgch 95:8282dbbe1492 1312 return SOCKET_ERROR;
mazgch 107:436ee320efd6 1313 }
mazgch 21:c4d64830bf02 1314 }
mazgch 44:9d12223b78ff 1315 timer.stop();
mazgch 44:9d12223b78ff 1316 timer.reset();
mazgch 107:436ee320efd6 1317 TRACE("socketRecv: %d \"%*s\"\r\n", cnt, cnt, buf-cnt);
mazgch 21:c4d64830bf02 1318 return cnt;
mazgch 21:c4d64830bf02 1319 }
mazgch 21:c4d64830bf02 1320
mazgch 103:197fa7920ad8 1321 int MDMParser::_findSocket(int handle) {
mazgch 104:c64ba749a422 1322 for (int socket = 0; socket < NUMSOCKETS; socket ++) {
mazgch 103:197fa7920ad8 1323 if (_sockets[socket].handle == handle)
mazgch 103:197fa7920ad8 1324 return socket;
mazgch 103:197fa7920ad8 1325 }
mazgch 103:197fa7920ad8 1326 return SOCKET_ERROR;
mazgch 103:197fa7920ad8 1327 }
mazgch 103:197fa7920ad8 1328
mazgch 21:c4d64830bf02 1329 // ----------------------------------------------------------------
fdilenarda 135:cbccf4052d45 1330 // HTTP
fdilenarda 135:cbccf4052d45 1331
fdilenarda 135:cbccf4052d45 1332 int MDMParser::httpFindProfile()
fdilenarda 135:cbccf4052d45 1333 {
fdilenarda 135:cbccf4052d45 1334 int profile = HTTP_PROF_ERROR; //default value
fdilenarda 135:cbccf4052d45 1335 LOCK();
fdilenarda 135:cbccf4052d45 1336 // find a free HTTP profile
fdilenarda 135:cbccf4052d45 1337 profile = _findProfile();
fdilenarda 135:cbccf4052d45 1338 TRACE("httpFindProfile: profile is %d\r\n", profile);
fdilenarda 135:cbccf4052d45 1339 if (profile != HTTP_PROF_ERROR) {
fdilenarda 135:cbccf4052d45 1340 _httpProfiles[profile].handle = 1;
fdilenarda 135:cbccf4052d45 1341 _httpProfiles[profile].timeout_ms = TIMEOUT_BLOCKING;
fdilenarda 135:cbccf4052d45 1342 _httpProfiles[profile].pending = false;
fdilenarda 135:cbccf4052d45 1343 _httpProfiles[profile].cmd = -1;
fdilenarda 135:cbccf4052d45 1344 _httpProfiles[profile].result = -1;
fdilenarda 135:cbccf4052d45 1345 }
fdilenarda 135:cbccf4052d45 1346 UNLOCK();
fdilenarda 135:cbccf4052d45 1347 return profile;
fdilenarda 135:cbccf4052d45 1348 }
fdilenarda 135:cbccf4052d45 1349
fdilenarda 135:cbccf4052d45 1350 int MDMParser::_findProfile(int handle) {
fdilenarda 135:cbccf4052d45 1351 for (int profile = 0; profile < NUMPROFILES; profile++) {
fdilenarda 135:cbccf4052d45 1352 if (_httpProfiles[profile].handle == handle)
fdilenarda 135:cbccf4052d45 1353 return profile;
fdilenarda 135:cbccf4052d45 1354 }
fdilenarda 135:cbccf4052d45 1355 return HTTP_PROF_ERROR;
fdilenarda 135:cbccf4052d45 1356 }
fdilenarda 135:cbccf4052d45 1357
fdilenarda 135:cbccf4052d45 1358 bool MDMParser::httpSetBlocking(int profile, int timeout_ms)
fdilenarda 135:cbccf4052d45 1359 {
fdilenarda 135:cbccf4052d45 1360 bool ok = false;
fdilenarda 135:cbccf4052d45 1361 LOCK();
fdilenarda 135:cbccf4052d45 1362 TRACE("httpSetBlocking(%d,%d)\r\n", profile, timeout_ms);
fdilenarda 135:cbccf4052d45 1363 if (ISPROFILE(profile)) {
fdilenarda 135:cbccf4052d45 1364 _httpProfiles[profile].timeout_ms = timeout_ms;
fdilenarda 135:cbccf4052d45 1365 ok = true;
fdilenarda 135:cbccf4052d45 1366 }
fdilenarda 135:cbccf4052d45 1367 UNLOCK();
fdilenarda 135:cbccf4052d45 1368 return ok;
fdilenarda 135:cbccf4052d45 1369 }
fdilenarda 135:cbccf4052d45 1370
fdilenarda 135:cbccf4052d45 1371 bool MDMParser::httpSetProfileForCmdMng(int profile)
fdilenarda 135:cbccf4052d45 1372 {
fdilenarda 135:cbccf4052d45 1373 bool ok = false;
fdilenarda 135:cbccf4052d45 1374 LOCK();
fdilenarda 135:cbccf4052d45 1375 TRACE("httpSetProfileForCmdMng(%d)\r\n", profile);
fdilenarda 135:cbccf4052d45 1376 if (ISPROFILE(profile)) {
fdilenarda 135:cbccf4052d45 1377 _httpProfiles[profile].pending = true;
fdilenarda 135:cbccf4052d45 1378 _httpProfiles[profile].result = -1;
fdilenarda 135:cbccf4052d45 1379 ok = true;
fdilenarda 135:cbccf4052d45 1380 }
fdilenarda 135:cbccf4052d45 1381 UNLOCK();
fdilenarda 135:cbccf4052d45 1382 return ok;
fdilenarda 135:cbccf4052d45 1383 }
fdilenarda 135:cbccf4052d45 1384
fdilenarda 135:cbccf4052d45 1385 bool MDMParser::httpFreeProfile(int profile)
fdilenarda 135:cbccf4052d45 1386 {
fdilenarda 135:cbccf4052d45 1387 bool ok = true;
fdilenarda 135:cbccf4052d45 1388 LOCK();
fdilenarda 135:cbccf4052d45 1389 if (ISPROFILE(profile)) {
fdilenarda 135:cbccf4052d45 1390 TRACE("httpFreeProfile(%d)\r\n", profile);
fdilenarda 135:cbccf4052d45 1391 _httpProfiles[profile].handle = HTTP_PROF_ERROR;
fdilenarda 135:cbccf4052d45 1392 _httpProfiles[profile].timeout_ms = TIMEOUT_BLOCKING;
fdilenarda 135:cbccf4052d45 1393 _httpProfiles[profile].pending = false;
fdilenarda 135:cbccf4052d45 1394 _httpProfiles[profile].cmd = -1;
fdilenarda 135:cbccf4052d45 1395 _httpProfiles[profile].result = -1;
fdilenarda 135:cbccf4052d45 1396 ok = true;
fdilenarda 135:cbccf4052d45 1397 }
fdilenarda 135:cbccf4052d45 1398 UNLOCK();
fdilenarda 135:cbccf4052d45 1399 return ok;
fdilenarda 135:cbccf4052d45 1400 }
fdilenarda 135:cbccf4052d45 1401
fdilenarda 135:cbccf4052d45 1402 bool MDMParser::httpResetProfile(int httpProfile)
fdilenarda 135:cbccf4052d45 1403 {
fdilenarda 135:cbccf4052d45 1404 bool ok = false;
fdilenarda 135:cbccf4052d45 1405
fdilenarda 135:cbccf4052d45 1406 LOCK();
fdilenarda 135:cbccf4052d45 1407 TRACE("httpResetProfile(%d)\r\n", httpProfile);
fdilenarda 135:cbccf4052d45 1408 sendFormated("AT+UHTTP=%d\r\n", httpProfile);
fdilenarda 135:cbccf4052d45 1409 if (RESP_OK == waitFinalResp())
fdilenarda 135:cbccf4052d45 1410 ok = true;
fdilenarda 135:cbccf4052d45 1411 UNLOCK();
fdilenarda 135:cbccf4052d45 1412
fdilenarda 135:cbccf4052d45 1413 return ok;
fdilenarda 135:cbccf4052d45 1414 }
fdilenarda 135:cbccf4052d45 1415
fdilenarda 135:cbccf4052d45 1416 bool MDMParser::httpSetPar(int httpProfile, HttpOpCode httpOpCode, const char * httpInPar)
fdilenarda 135:cbccf4052d45 1417 {
fdilenarda 135:cbccf4052d45 1418 bool ok = false;
fdilenarda 135:cbccf4052d45 1419 IP ip = NOIP;
fdilenarda 135:cbccf4052d45 1420 int httpInParNum = 0;
fdilenarda 135:cbccf4052d45 1421
fdilenarda 135:cbccf4052d45 1422 LOCK();
fdilenarda 135:cbccf4052d45 1423 TRACE("httpSetPar(%d,%d,\"%s\")\r\n", httpProfile, httpOpCode, httpInPar);
fdilenarda 135:cbccf4052d45 1424 switch(httpOpCode){
fdilenarda 135:cbccf4052d45 1425 case HTTP_IP_ADDRESS: //0
fdilenarda 135:cbccf4052d45 1426 ip = gethostbyname(httpInPar);
fdilenarda 135:cbccf4052d45 1427 if (ip == NOIP)
fdilenarda 135:cbccf4052d45 1428 return false;
fdilenarda 135:cbccf4052d45 1429
fdilenarda 135:cbccf4052d45 1430 sendFormated("AT+UHTTP=%d,%d,\"" IPSTR "\"\r\n", httpProfile, httpOpCode, IPNUM(ip));
fdilenarda 135:cbccf4052d45 1431 if (RESP_OK == waitFinalResp())
fdilenarda 135:cbccf4052d45 1432 ok = true;
fdilenarda 135:cbccf4052d45 1433 break;
fdilenarda 135:cbccf4052d45 1434
fdilenarda 135:cbccf4052d45 1435 case HTTP_SERVER_NAME: //1
fdilenarda 135:cbccf4052d45 1436 case HTTP_USER_NAME: //2
fdilenarda 135:cbccf4052d45 1437 case HTTP_PASSWORD: //3
fdilenarda 135:cbccf4052d45 1438 sendFormated("AT+UHTTP=%d,%d,\"%s\"\r\n", httpProfile, httpOpCode, httpInPar);
fdilenarda 135:cbccf4052d45 1439 if (RESP_OK == waitFinalResp())
fdilenarda 135:cbccf4052d45 1440 ok = true;
fdilenarda 135:cbccf4052d45 1441 break;
fdilenarda 135:cbccf4052d45 1442
fdilenarda 135:cbccf4052d45 1443 case HTTP_AUTH_TYPE: //4
fdilenarda 135:cbccf4052d45 1444 case HTTP_PORT: //5
fdilenarda 135:cbccf4052d45 1445 httpInParNum = atoi(httpInPar);
fdilenarda 135:cbccf4052d45 1446 sendFormated("AT+UHTTP=%d,%d,%d\r\n", httpProfile, httpOpCode, httpInParNum);
fdilenarda 135:cbccf4052d45 1447 if (RESP_OK == waitFinalResp())
fdilenarda 135:cbccf4052d45 1448 ok = true;
fdilenarda 135:cbccf4052d45 1449 break;
fdilenarda 135:cbccf4052d45 1450
fdilenarda 135:cbccf4052d45 1451 case HTTP_SECURE: //6
fdilenarda 135:cbccf4052d45 1452 if(_dev.dev != DEV_LISA_C2)
fdilenarda 135:cbccf4052d45 1453 {
fdilenarda 135:cbccf4052d45 1454 httpInParNum = atoi(httpInPar);
fdilenarda 135:cbccf4052d45 1455 sendFormated("AT+UHTTP=%d,%d,%d\r\n", httpProfile, httpOpCode, httpInParNum);
fdilenarda 135:cbccf4052d45 1456 if (RESP_OK == waitFinalResp())
fdilenarda 135:cbccf4052d45 1457 ok = true;
fdilenarda 135:cbccf4052d45 1458 } else {
fdilenarda 135:cbccf4052d45 1459 TRACE("httpSetPar: HTTP secure option not supported by module\r\n");
fdilenarda 135:cbccf4052d45 1460 ok = false;
fdilenarda 135:cbccf4052d45 1461 }
fdilenarda 135:cbccf4052d45 1462 break;
fdilenarda 135:cbccf4052d45 1463
fdilenarda 135:cbccf4052d45 1464 default:
fdilenarda 135:cbccf4052d45 1465 TRACE("httpSetPar: unknown httpOpCode %s\r\n", httpOpCode);
fdilenarda 135:cbccf4052d45 1466 ok = false;
fdilenarda 135:cbccf4052d45 1467 break;
fdilenarda 135:cbccf4052d45 1468 }
fdilenarda 135:cbccf4052d45 1469 UNLOCK();
fdilenarda 135:cbccf4052d45 1470 return ok;
fdilenarda 135:cbccf4052d45 1471 }
fdilenarda 135:cbccf4052d45 1472
fdilenarda 135:cbccf4052d45 1473 bool MDMParser::httpCommand(int httpProfile, HttpCmd httpCmdCode, const char* httpPath, const char* httpOut, \
fdilenarda 135:cbccf4052d45 1474 const char* httpIn, int httpContentType, const char* httpCustomPar, char* buf, int len)
fdilenarda 135:cbccf4052d45 1475 {
fdilenarda 135:cbccf4052d45 1476 bool ok = false;
fdilenarda 135:cbccf4052d45 1477 #ifdef MDM_DEBUG
fdilenarda 135:cbccf4052d45 1478 memset(buf, '\0', len);
fdilenarda 135:cbccf4052d45 1479 #endif
fdilenarda 135:cbccf4052d45 1480 LOCK();
fdilenarda 135:cbccf4052d45 1481 TRACE("%s\r\n", getHTTPcmd(httpCmdCode));
fdilenarda 135:cbccf4052d45 1482 switch (httpCmdCode)
fdilenarda 135:cbccf4052d45 1483 {
fdilenarda 135:cbccf4052d45 1484 case HTTP_HEAD:
fdilenarda 135:cbccf4052d45 1485 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\"\r\n", httpProfile, HTTP_HEAD, httpPath, httpOut);
fdilenarda 135:cbccf4052d45 1486 break;
fdilenarda 135:cbccf4052d45 1487
fdilenarda 135:cbccf4052d45 1488 case HTTP_GET:
fdilenarda 135:cbccf4052d45 1489 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\"\r\n", httpProfile, HTTP_GET, httpPath, httpOut);
fdilenarda 135:cbccf4052d45 1490 break;
fdilenarda 135:cbccf4052d45 1491
fdilenarda 135:cbccf4052d45 1492 case HTTP_DELETE:
fdilenarda 135:cbccf4052d45 1493 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\"\r\n", httpProfile, HTTP_DELETE, httpPath, httpOut);
fdilenarda 135:cbccf4052d45 1494 break;
fdilenarda 135:cbccf4052d45 1495
fdilenarda 135:cbccf4052d45 1496 case HTTP_PUT:
fdilenarda 135:cbccf4052d45 1497 //in this case the parameter httpIn is a filename
fdilenarda 135:cbccf4052d45 1498 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\"\r\n", httpProfile, HTTP_PUT, httpPath, httpOut, httpIn);
fdilenarda 135:cbccf4052d45 1499 break;
fdilenarda 135:cbccf4052d45 1500
fdilenarda 135:cbccf4052d45 1501 case HTTP_POST_FILE:
fdilenarda 135:cbccf4052d45 1502 //in this case the parameter httpIn is a filename
fdilenarda 135:cbccf4052d45 1503 if(_dev.dev != DEV_LISA_C2)
fdilenarda 135:cbccf4052d45 1504 {
fdilenarda 135:cbccf4052d45 1505 if(httpContentType != 6)
fdilenarda 135:cbccf4052d45 1506 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \
fdilenarda 135:cbccf4052d45 1507 httpProfile, HTTP_POST_FILE, httpPath, httpOut, httpIn, httpContentType);
fdilenarda 135:cbccf4052d45 1508 else
fdilenarda 135:cbccf4052d45 1509 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d,%d\r\n", \
fdilenarda 135:cbccf4052d45 1510 httpProfile, HTTP_POST_FILE, httpPath, httpOut, httpIn, httpContentType, httpCustomPar);
fdilenarda 135:cbccf4052d45 1511 }
fdilenarda 135:cbccf4052d45 1512 else{
fdilenarda 135:cbccf4052d45 1513 if((httpContentType != 5) && (httpContentType != 6) && (httpCustomPar == NULL))
fdilenarda 135:cbccf4052d45 1514 {
fdilenarda 135:cbccf4052d45 1515 //parameters values consistent with the AT commands specs of LISA-C200
fdilenarda 135:cbccf4052d45 1516 //(in particular httpCustomPar has to be not defined)
fdilenarda 135:cbccf4052d45 1517 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \
fdilenarda 135:cbccf4052d45 1518 httpProfile, HTTP_POST_FILE, httpPath, httpOut, httpIn, httpContentType);
fdilenarda 135:cbccf4052d45 1519 } else {
fdilenarda 135:cbccf4052d45 1520 TRACE("httpCommand: command not supported by module");
fdilenarda 135:cbccf4052d45 1521 return ok; //error
fdilenarda 135:cbccf4052d45 1522 }
fdilenarda 135:cbccf4052d45 1523 }
fdilenarda 135:cbccf4052d45 1524 break;
fdilenarda 135:cbccf4052d45 1525
fdilenarda 135:cbccf4052d45 1526 case HTTP_POST_DATA:
fdilenarda 135:cbccf4052d45 1527 //in this case the parameter httpIn is a string containing data
fdilenarda 135:cbccf4052d45 1528 if(_dev.dev != DEV_LISA_C2)
fdilenarda 135:cbccf4052d45 1529 {
fdilenarda 135:cbccf4052d45 1530 if(httpContentType != 6)
fdilenarda 135:cbccf4052d45 1531 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \
fdilenarda 135:cbccf4052d45 1532 httpProfile, HTTP_POST_DATA, httpPath, httpOut, httpIn, httpContentType);
fdilenarda 135:cbccf4052d45 1533 else
fdilenarda 135:cbccf4052d45 1534 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d,%d\r\n", \
fdilenarda 135:cbccf4052d45 1535 httpProfile, HTTP_POST_DATA, httpPath, httpOut, httpIn, httpContentType, httpCustomPar);
fdilenarda 135:cbccf4052d45 1536 } else {
fdilenarda 135:cbccf4052d45 1537 if((httpContentType != 5) && (httpContentType != 6) && (httpCustomPar == NULL))
fdilenarda 135:cbccf4052d45 1538 {
fdilenarda 135:cbccf4052d45 1539 //parameters values consistent with the AT commands specs of LISA-C200
fdilenarda 135:cbccf4052d45 1540 //(in particular httpCustomPar has to be not defined)
fdilenarda 135:cbccf4052d45 1541 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \
fdilenarda 135:cbccf4052d45 1542 httpProfile, HTTP_POST_DATA, httpPath, httpOut, httpIn, httpContentType);
fdilenarda 135:cbccf4052d45 1543 } else {
fdilenarda 135:cbccf4052d45 1544 TRACE("httpCommand: command not supported by module");
fdilenarda 135:cbccf4052d45 1545 return ok; //error
fdilenarda 135:cbccf4052d45 1546 }
fdilenarda 135:cbccf4052d45 1547 }
fdilenarda 135:cbccf4052d45 1548 break;
fdilenarda 135:cbccf4052d45 1549
fdilenarda 135:cbccf4052d45 1550 default:
fdilenarda 135:cbccf4052d45 1551 TRACE("HTTP command not recognized\r\n");
fdilenarda 135:cbccf4052d45 1552 return ok; //error
fdilenarda 135:cbccf4052d45 1553 }
fdilenarda 135:cbccf4052d45 1554
fdilenarda 135:cbccf4052d45 1555 if (RESP_OK == waitFinalResp())
fdilenarda 135:cbccf4052d45 1556 {
fdilenarda 135:cbccf4052d45 1557 Timer timer;
fdilenarda 135:cbccf4052d45 1558 timer.start();
fdilenarda 135:cbccf4052d45 1559 httpSetProfileForCmdMng(httpProfile);
fdilenarda 135:cbccf4052d45 1560 while (_httpProfiles[httpProfile].pending) //waiting for unsolicited
fdilenarda 135:cbccf4052d45 1561 {
fdilenarda 135:cbccf4052d45 1562 ok = false; //reset variable
fdilenarda 135:cbccf4052d45 1563 if(_httpProfiles[httpProfile].result != -1)
fdilenarda 135:cbccf4052d45 1564 {
fdilenarda 135:cbccf4052d45 1565 //received unsolicited: starting its analysis
fdilenarda 135:cbccf4052d45 1566 _httpProfiles[httpProfile].pending = false;
fdilenarda 135:cbccf4052d45 1567 if(_httpProfiles[httpProfile].result == 1)
fdilenarda 135:cbccf4052d45 1568 {
fdilenarda 135:cbccf4052d45 1569 //HTTP command successfully executed
fdilenarda 135:cbccf4052d45 1570 if(_dev.dev != DEV_LISA_C2)
fdilenarda 135:cbccf4052d45 1571 {
fdilenarda 135:cbccf4052d45 1572 TRACE("httpCommand: reading files with a dimension " \
fdilenarda 135:cbccf4052d45 1573 "also greater than MAX_SIZE bytes\r\n");
fdilenarda 135:cbccf4052d45 1574 if(readFileNew(httpOut,buf,len) >=0 )
fdilenarda 135:cbccf4052d45 1575 ok = true;
fdilenarda 135:cbccf4052d45 1576 } else {
fdilenarda 135:cbccf4052d45 1577 TRACE("httpCommand: reading files with a dimension " \
fdilenarda 135:cbccf4052d45 1578 "less than MAX_SIZE bytes, otherwise error\r\n");
fdilenarda 135:cbccf4052d45 1579 if(readFile(httpOut,buf,len) >=0 )
fdilenarda 135:cbccf4052d45 1580 ok = true;
fdilenarda 135:cbccf4052d45 1581 }
fdilenarda 135:cbccf4052d45 1582 } else {
fdilenarda 135:cbccf4052d45 1583 //HTTP command not successfully executed
fdilenarda 135:cbccf4052d45 1584 ok = false;
fdilenarda 135:cbccf4052d45 1585 }
fdilenarda 135:cbccf4052d45 1586 } else if (!TIMEOUT(timer, _httpProfiles[httpProfile].timeout_ms)) {
fdilenarda 135:cbccf4052d45 1587 ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs
fdilenarda 135:cbccf4052d45 1588 } else {
fdilenarda 135:cbccf4052d45 1589 //not received unsolicited and expired timer
fdilenarda 135:cbccf4052d45 1590 TRACE("httpCommand: not received unsolicited and expired timer\r\n");
fdilenarda 135:cbccf4052d45 1591 ok = false;
fdilenarda 135:cbccf4052d45 1592 }
fdilenarda 135:cbccf4052d45 1593 if (!ok) {
fdilenarda 135:cbccf4052d45 1594 TRACE("%s: ERROR\r\n", getHTTPcmd(httpCmdCode));
fdilenarda 135:cbccf4052d45 1595 _httpProfiles[httpProfile].pending = false; //no more while loops
fdilenarda 135:cbccf4052d45 1596 }
fdilenarda 135:cbccf4052d45 1597 }
fdilenarda 135:cbccf4052d45 1598 }
fdilenarda 135:cbccf4052d45 1599 UNLOCK();
fdilenarda 135:cbccf4052d45 1600 return ok;
fdilenarda 135:cbccf4052d45 1601 }
fdilenarda 135:cbccf4052d45 1602
fdilenarda 135:cbccf4052d45 1603 const char* MDMParser::getHTTPcmd(int httpCmdCode)
fdilenarda 135:cbccf4052d45 1604 {
fdilenarda 135:cbccf4052d45 1605 switch (httpCmdCode)
fdilenarda 135:cbccf4052d45 1606 {
fdilenarda 135:cbccf4052d45 1607 case HTTP_HEAD:
fdilenarda 135:cbccf4052d45 1608 return "HTTP HEAD command";
fdilenarda 135:cbccf4052d45 1609 case HTTP_GET:
fdilenarda 135:cbccf4052d45 1610 return "HTTP GET command";
fdilenarda 135:cbccf4052d45 1611 case HTTP_DELETE:
fdilenarda 135:cbccf4052d45 1612 return "HTTP DELETE command";
fdilenarda 135:cbccf4052d45 1613 case HTTP_PUT:
fdilenarda 135:cbccf4052d45 1614 return "HTTP PUT command";
fdilenarda 135:cbccf4052d45 1615 case HTTP_POST_FILE:
fdilenarda 135:cbccf4052d45 1616 return "HTTP POST file command";
fdilenarda 135:cbccf4052d45 1617 case HTTP_POST_DATA:
fdilenarda 135:cbccf4052d45 1618 return "HTTP POST data command";
fdilenarda 135:cbccf4052d45 1619 default:
fdilenarda 135:cbccf4052d45 1620 return "HTTP command not recognized";
fdilenarda 135:cbccf4052d45 1621 }
fdilenarda 135:cbccf4052d45 1622 }
fdilenarda 135:cbccf4052d45 1623
fdilenarda 135:cbccf4052d45 1624 // ----------------------------------------------------------------
mazgch 31:a0bed6c1e05d 1625
mazgch 31:a0bed6c1e05d 1626 int MDMParser::_cbCMGL(int type, const char* buf, int len, CMGLparam* param)
mazgch 21:c4d64830bf02 1627 {
mazgch 31:a0bed6c1e05d 1628 if ((type == TYPE_PLUS) && param && param->num) {
mazgch 31:a0bed6c1e05d 1629 // +CMGL: <ix>,...
mazgch 31:a0bed6c1e05d 1630 int ix;
mazgch 31:a0bed6c1e05d 1631 if (sscanf(buf, "\r\n+CMGL: %d,", &ix) == 1)
mazgch 31:a0bed6c1e05d 1632 {
mazgch 31:a0bed6c1e05d 1633 *param->ix++ = ix;
mazgch 31:a0bed6c1e05d 1634 param->num--;
mazgch 31:a0bed6c1e05d 1635 }
mazgch 29:53d346010624 1636 }
mazgch 29:53d346010624 1637 return WAIT;
mazgch 21:c4d64830bf02 1638 }
mazgch 21:c4d64830bf02 1639
mazgch 31:a0bed6c1e05d 1640 int MDMParser::smsList(const char* stat /*= "ALL"*/, int* ix /*=NULL*/, int num /*= 0*/) {
mazgch 95:8282dbbe1492 1641 int ret = -1;
mazgch 95:8282dbbe1492 1642 LOCK();
mazgch 31:a0bed6c1e05d 1643 sendFormated("AT+CMGL=\"%s\"\r\n", stat);
mazgch 31:a0bed6c1e05d 1644 CMGLparam param;
mazgch 31:a0bed6c1e05d 1645 param.ix = ix;
mazgch 31:a0bed6c1e05d 1646 param.num = num;
mazgch 95:8282dbbe1492 1647 if (RESP_OK == waitFinalResp(_cbCMGL, &param))
mazgch 95:8282dbbe1492 1648 ret = num - param.num;
mazgch 95:8282dbbe1492 1649 UNLOCK();
mazgch 95:8282dbbe1492 1650 return ret;
mazgch 21:c4d64830bf02 1651 }
mazgch 21:c4d64830bf02 1652
mazgch 21:c4d64830bf02 1653 bool MDMParser::smsSend(const char* num, const char* buf)
mazgch 21:c4d64830bf02 1654 {
mazgch 95:8282dbbe1492 1655 bool ok = false;
mazgch 95:8282dbbe1492 1656 LOCK();
mazgch 80:34985b4d821e 1657 sendFormated("AT+CMGS=\"%s\"\r\n",num);
mazgch 95:8282dbbe1492 1658 if (RESP_PROMPT == waitFinalResp(NULL,NULL,150*1000)) {
mazgch 95:8282dbbe1492 1659 send(buf, strlen(buf));
mazgch 95:8282dbbe1492 1660 const char ctrlZ = 0x1A;
mazgch 95:8282dbbe1492 1661 send(&ctrlZ, sizeof(ctrlZ));
mazgch 95:8282dbbe1492 1662 ok = (RESP_OK == waitFinalResp());
mazgch 21:c4d64830bf02 1663 }
mazgch 95:8282dbbe1492 1664 UNLOCK();
mazgch 95:8282dbbe1492 1665 return ok;
mazgch 21:c4d64830bf02 1666 }
mazgch 21:c4d64830bf02 1667
mazgch 21:c4d64830bf02 1668 bool MDMParser::smsDelete(int ix)
mazgch 21:c4d64830bf02 1669 {
mazgch 95:8282dbbe1492 1670 bool ok = false;
mazgch 95:8282dbbe1492 1671 LOCK();
mazgch 21:c4d64830bf02 1672 sendFormated("AT+CMGD=%d\r\n",ix);
mazgch 95:8282dbbe1492 1673 ok = (RESP_OK == waitFinalResp());
mazgch 95:8282dbbe1492 1674 UNLOCK();
mazgch 95:8282dbbe1492 1675 return ok;
mazgch 21:c4d64830bf02 1676 }
mazgch 21:c4d64830bf02 1677
mazgch 21:c4d64830bf02 1678 int MDMParser::_cbCMGR(int type, const char* buf, int len, CMGRparam* param)
mazgch 21:c4d64830bf02 1679 {
mazgch 21:c4d64830bf02 1680 if (param) {
mazgch 21:c4d64830bf02 1681 if (type == TYPE_PLUS) {
mazgch 21:c4d64830bf02 1682 if (sscanf(buf, "\r\n+CMGR: \"%*[^\"]\",\"%[^\"]", param->num) == 1) {
mazgch 21:c4d64830bf02 1683 }
mazgch 37:cc3433329d66 1684 } else if ((type == TYPE_UNKNOWN) && (buf[len-2] == '\r') && (buf[len-1] == '\n')) {
mazgch 21:c4d64830bf02 1685 memcpy(param->buf, buf, len-2);
mazgch 21:c4d64830bf02 1686 param->buf[len-2] = '\0';
mazgch 21:c4d64830bf02 1687 }
mazgch 21:c4d64830bf02 1688 }
mazgch 21:c4d64830bf02 1689 return WAIT;
mazgch 21:c4d64830bf02 1690 }
mazgch 21:c4d64830bf02 1691
mazgch 21:c4d64830bf02 1692 bool MDMParser::smsRead(int ix, char* num, char* buf, int len)
mazgch 21:c4d64830bf02 1693 {
mazgch 95:8282dbbe1492 1694 bool ok = false;
mazgch 95:8282dbbe1492 1695 LOCK();
mazgch 21:c4d64830bf02 1696 CMGRparam param;
mazgch 21:c4d64830bf02 1697 param.num = num;
mazgch 21:c4d64830bf02 1698 param.buf = buf;
mazgch 21:c4d64830bf02 1699 sendFormated("AT+CMGR=%d\r\n",ix);
mazgch 95:8282dbbe1492 1700 ok = (RESP_OK == waitFinalResp(_cbCMGR, &param));
mazgch 95:8282dbbe1492 1701 UNLOCK();
mazgch 95:8282dbbe1492 1702 return ok;
mazgch 21:c4d64830bf02 1703 }
mazgch 54:7ba8e4c218e2 1704
mazgch 54:7ba8e4c218e2 1705 // ----------------------------------------------------------------
mazgch 70:0a87d256cd24 1706
mazgch 70:0a87d256cd24 1707 int MDMParser::_cbCUSD(int type, const char* buf, int len, char* resp)
mazgch 70:0a87d256cd24 1708 {
mazgch 70:0a87d256cd24 1709 if ((type == TYPE_PLUS) && resp) {
mazgch 70:0a87d256cd24 1710 // +USD: \"%*[^\"]\",\"%[^\"]\",,\"%*[^\"]\",%d,%d,%d,%d,\"*[^\"]\",%d,%d"..);
mazgch 70:0a87d256cd24 1711 if (sscanf(buf, "\r\n+CUSD: %*d,\"%[^\"]\",%*d", resp) == 1) {
mazgch 70:0a87d256cd24 1712 /*nothing*/
mazgch 70:0a87d256cd24 1713 }
mazgch 70:0a87d256cd24 1714 }
mazgch 70:0a87d256cd24 1715 return WAIT;
mazgch 70:0a87d256cd24 1716 }
mazgch 70:0a87d256cd24 1717
mazgch 70:0a87d256cd24 1718 bool MDMParser::ussdCommand(const char* cmd, char* buf)
mazgch 70:0a87d256cd24 1719 {
mazgch 95:8282dbbe1492 1720 bool ok = false;
mazgch 95:8282dbbe1492 1721 LOCK();
mazgch 70:0a87d256cd24 1722 *buf = '\0';
mazgch 125:25a292afbac6 1723 if (_dev.dev != DEV_LISA_C2) {
mazgch 95:8282dbbe1492 1724 sendFormated("AT+CUSD=1,\"%s\"\r\n",cmd);
mazgch 95:8282dbbe1492 1725 ok = (RESP_OK == waitFinalResp(_cbCUSD, buf));
mazgch 70:0a87d256cd24 1726 }
mazgch 95:8282dbbe1492 1727 UNLOCK();
mazgch 95:8282dbbe1492 1728 return ok;
mazgch 70:0a87d256cd24 1729 }
mazgch 80:34985b4d821e 1730
mazgch 80:34985b4d821e 1731 // ----------------------------------------------------------------
mazgch 70:0a87d256cd24 1732
mazgch 115:d8d94b73c725 1733 int MDMParser::_cbUDELFILE(int type, const char* buf, int len, void*)
mazgch 115:d8d94b73c725 1734 {
mazgch 115:d8d94b73c725 1735 if ((type == TYPE_ERROR) && strstr(buf, "+CME ERROR: FILE NOT FOUND"))
mazgch 115:d8d94b73c725 1736 return RESP_OK; // file does not exist, so all ok...
mazgch 115:d8d94b73c725 1737 return WAIT;
mazgch 115:d8d94b73c725 1738 }
mazgch 115:d8d94b73c725 1739
mazgch 80:34985b4d821e 1740 bool MDMParser::delFile(const char* filename)
mazgch 80:34985b4d821e 1741 {
mazgch 95:8282dbbe1492 1742 bool ok = false;
mazgch 95:8282dbbe1492 1743 LOCK();
mazgch 80:34985b4d821e 1744 sendFormated("AT+UDELFILE=\"%s\"\r\n", filename);
mazgch 115:d8d94b73c725 1745 ok = (RESP_OK == waitFinalResp(_cbUDELFILE));
mazgch 95:8282dbbe1492 1746 UNLOCK();
mazgch 95:8282dbbe1492 1747 return ok;
mazgch 80:34985b4d821e 1748 }
mazgch 80:34985b4d821e 1749
mazgch 80:34985b4d821e 1750 int MDMParser::writeFile(const char* filename, const char* buf, int len)
mazgch 80:34985b4d821e 1751 {
mazgch 95:8282dbbe1492 1752 bool ok = false;
mazgch 95:8282dbbe1492 1753 LOCK();
mazgch 80:34985b4d821e 1754 sendFormated("AT+UDWNFILE=\"%s\",%d\r\n", filename, len);
mazgch 95:8282dbbe1492 1755 if (RESP_PROMPT == waitFinalResp()) {
mazgch 95:8282dbbe1492 1756 send(buf, len);
mazgch 95:8282dbbe1492 1757 ok = (RESP_OK == waitFinalResp());
mazgch 95:8282dbbe1492 1758 }
mazgch 95:8282dbbe1492 1759 UNLOCK();
mazgch 95:8282dbbe1492 1760 return ok ? len : -1;
mazgch 80:34985b4d821e 1761 }
mazgch 80:34985b4d821e 1762
mazgch 80:34985b4d821e 1763 int MDMParser::readFile(const char* filename, char* buf, int len)
mazgch 80:34985b4d821e 1764 {
mazgch 80:34985b4d821e 1765 URDFILEparam param;
mazgch 80:34985b4d821e 1766 param.filename = filename;
mazgch 80:34985b4d821e 1767 param.buf = buf;
mazgch 80:34985b4d821e 1768 param.sz = len;
mazgch 80:34985b4d821e 1769 param.len = 0;
mazgch 95:8282dbbe1492 1770 LOCK();
mazgch 95:8282dbbe1492 1771 sendFormated("AT+URDFILE=\"%s\"\r\n", filename, len);
mazgch 105:f6bb2a20de70 1772 if (RESP_OK != waitFinalResp(_cbURDFILE, &param))
mazgch 95:8282dbbe1492 1773 param.len = -1;
mazgch 95:8282dbbe1492 1774 UNLOCK();
mazgch 80:34985b4d821e 1775 return param.len;
mazgch 80:34985b4d821e 1776 }
mazgch 80:34985b4d821e 1777
mazgch 80:34985b4d821e 1778 int MDMParser::_cbURDFILE(int type, const char* buf, int len, URDFILEparam* param)
mazgch 80:34985b4d821e 1779 {
mazgch 80:34985b4d821e 1780 if ((type == TYPE_PLUS) && param && param->filename && param->buf) {
mazgch 80:34985b4d821e 1781 char filename[48];
mazgch 80:34985b4d821e 1782 int sz;
mazgch 80:34985b4d821e 1783 if ((sscanf(buf, "\r\n+URDFILE: \"%[^\"]\",%d,", filename, &sz) == 2) &&
mazgch 80:34985b4d821e 1784 (0 == strcmp(param->filename, filename)) &&
mazgch 80:34985b4d821e 1785 (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
mazgch 80:34985b4d821e 1786 param->len = (sz < param->sz) ? sz : param->sz;
mazgch 80:34985b4d821e 1787 memcpy(param->buf, &buf[len-1-sz], param->len);
mazgch 80:34985b4d821e 1788 }
mazgch 80:34985b4d821e 1789 }
mazgch 80:34985b4d821e 1790 return WAIT;
mazgch 80:34985b4d821e 1791 }
fdilenarda 135:cbccf4052d45 1792
fdilenarda 135:cbccf4052d45 1793 //The following function is useful for reading files with a dimension greater than MAX_SIZE bytes
fdilenarda 135:cbccf4052d45 1794 int MDMParser::readFileNew(const char* filename, char* buf, int len)
fdilenarda 135:cbccf4052d45 1795 {
fdilenarda 135:cbccf4052d45 1796 int countBytes = -1; //counter for file reading (default value)
fdilenarda 135:cbccf4052d45 1797
fdilenarda 135:cbccf4052d45 1798 if(_dev.dev != DEV_LISA_C2)
fdilenarda 135:cbccf4052d45 1799 {
fdilenarda 135:cbccf4052d45 1800 //retrieve information about the file, in particular its size
fdilenarda 135:cbccf4052d45 1801 int filesize = infoFile(filename);
fdilenarda 135:cbccf4052d45 1802 TRACE("readFileNew: filename is %s; filesize is %d\r\n", filename, filesize);
fdilenarda 135:cbccf4052d45 1803
fdilenarda 135:cbccf4052d45 1804 if (len < filesize)
fdilenarda 135:cbccf4052d45 1805 TRACE("readFileNew: WARNING. Buffer dimension is %d bytes," \
fdilenarda 135:cbccf4052d45 1806 "while file size is %d bytes\r\n", len, filesize);
fdilenarda 135:cbccf4052d45 1807
fdilenarda 135:cbccf4052d45 1808 if (filesize > 0)
fdilenarda 135:cbccf4052d45 1809 {
fdilenarda 135:cbccf4052d45 1810 #ifdef MDM_DEBUG
fdilenarda 135:cbccf4052d45 1811 memset(buf, '\0', len);
fdilenarda 135:cbccf4052d45 1812 #endif
fdilenarda 135:cbccf4052d45 1813 int offset = 0; //start reading from 0
fdilenarda 135:cbccf4052d45 1814 int blockSize = MAX_SIZE; //still need space for headers and unsolicited commands
fdilenarda 135:cbccf4052d45 1815 int bytesToRead = filesize; //bytes to read
fdilenarda 135:cbccf4052d45 1816
fdilenarda 135:cbccf4052d45 1817 while (bytesToRead)
fdilenarda 135:cbccf4052d45 1818 {
fdilenarda 135:cbccf4052d45 1819 bool ok = false;
fdilenarda 135:cbccf4052d45 1820
fdilenarda 135:cbccf4052d45 1821 if (bytesToRead < blockSize)
fdilenarda 135:cbccf4052d45 1822 blockSize = bytesToRead;
fdilenarda 135:cbccf4052d45 1823
fdilenarda 135:cbccf4052d45 1824 LOCK();
fdilenarda 135:cbccf4052d45 1825 if (blockSize > 0) {
fdilenarda 135:cbccf4052d45 1826
fdilenarda 135:cbccf4052d45 1827 sendFormated("AT+URDBLOCK=\"%s\",%d,%d\r\n", filename, offset, blockSize);
fdilenarda 135:cbccf4052d45 1828
fdilenarda 135:cbccf4052d45 1829 if (RESP_OK == waitFinalResp(_cbURDBLOCK, buf)) {
fdilenarda 135:cbccf4052d45 1830 bytesToRead -= blockSize;
fdilenarda 135:cbccf4052d45 1831 offset += blockSize;
fdilenarda 135:cbccf4052d45 1832 buf += blockSize;
fdilenarda 135:cbccf4052d45 1833 ok = true;
fdilenarda 135:cbccf4052d45 1834 } else {
fdilenarda 135:cbccf4052d45 1835 //error condition
fdilenarda 135:cbccf4052d45 1836 countBytes = -1;
fdilenarda 135:cbccf4052d45 1837 ok = false;
fdilenarda 135:cbccf4052d45 1838 }
fdilenarda 135:cbccf4052d45 1839 }
fdilenarda 135:cbccf4052d45 1840 UNLOCK();
fdilenarda 135:cbccf4052d45 1841
fdilenarda 135:cbccf4052d45 1842 if (!ok) {
fdilenarda 135:cbccf4052d45 1843 TRACE("readFileNew: ERROR\r\n");
fdilenarda 135:cbccf4052d45 1844 return countBytes; //in this case countBytes is -1
fdilenarda 135:cbccf4052d45 1845 }
fdilenarda 135:cbccf4052d45 1846 }
fdilenarda 135:cbccf4052d45 1847
fdilenarda 135:cbccf4052d45 1848 countBytes = offset; //total read bytes
fdilenarda 135:cbccf4052d45 1849 return countBytes;
fdilenarda 135:cbccf4052d45 1850 }
fdilenarda 135:cbccf4052d45 1851 } else {
fdilenarda 135:cbccf4052d45 1852 TRACE("httpCommand: command not supported by module");
fdilenarda 135:cbccf4052d45 1853 }
fdilenarda 135:cbccf4052d45 1854 return countBytes; //it could be 0 or -1 (possible error)
fdilenarda 135:cbccf4052d45 1855 }
fdilenarda 135:cbccf4052d45 1856
fdilenarda 135:cbccf4052d45 1857 int MDMParser::_cbURDBLOCK(int type, const char* buf, int len, char* out)
fdilenarda 135:cbccf4052d45 1858 {
fdilenarda 135:cbccf4052d45 1859 char fileNameRes[48];
fdilenarda 135:cbccf4052d45 1860 int sizeRes;
fdilenarda 135:cbccf4052d45 1861
fdilenarda 135:cbccf4052d45 1862 if ((type == TYPE_PLUS) && out) {
fdilenarda 135:cbccf4052d45 1863 if ((sscanf(buf, "\r\n+URDBLOCK: \"%[^\"]\",%d,", fileNameRes, &sizeRes) == 2) &&
fdilenarda 135:cbccf4052d45 1864 (buf[len-sizeRes-2] == '\"') && (buf[len-1] == '\"')) {
fdilenarda 135:cbccf4052d45 1865 memcpy(out, &buf[len-1-sizeRes], sizeRes);
fdilenarda 135:cbccf4052d45 1866 }
fdilenarda 135:cbccf4052d45 1867 }
fdilenarda 135:cbccf4052d45 1868
fdilenarda 135:cbccf4052d45 1869 return WAIT;
fdilenarda 135:cbccf4052d45 1870 }
fdilenarda 135:cbccf4052d45 1871
fdilenarda 135:cbccf4052d45 1872 int MDMParser::infoFile(const char* filename)
fdilenarda 135:cbccf4052d45 1873 {
fdilenarda 135:cbccf4052d45 1874 int infoFile = 0; //default value
fdilenarda 135:cbccf4052d45 1875
fdilenarda 135:cbccf4052d45 1876 LOCK();
fdilenarda 135:cbccf4052d45 1877 sendFormated("AT+ULSTFILE=2,\"%s\"\r\n", filename);
fdilenarda 135:cbccf4052d45 1878 if (RESP_OK != waitFinalResp(_cbULSTFILE, &infoFile))
fdilenarda 135:cbccf4052d45 1879 infoFile = -1; //error condition
fdilenarda 135:cbccf4052d45 1880 UNLOCK();
fdilenarda 135:cbccf4052d45 1881
fdilenarda 135:cbccf4052d45 1882 return infoFile;
fdilenarda 135:cbccf4052d45 1883 }
fdilenarda 135:cbccf4052d45 1884
fdilenarda 135:cbccf4052d45 1885 int MDMParser::_cbULSTFILE(int type, const char* buf, int len, int* infoFile)
fdilenarda 135:cbccf4052d45 1886 {
fdilenarda 135:cbccf4052d45 1887 if (infoFile) {
fdilenarda 135:cbccf4052d45 1888 if (type == TYPE_PLUS) {
fdilenarda 135:cbccf4052d45 1889 if (sscanf(buf, "\r\n+ULSTFILE: %d\r\n", infoFile) == 1) {
fdilenarda 135:cbccf4052d45 1890 }
fdilenarda 135:cbccf4052d45 1891 }
fdilenarda 135:cbccf4052d45 1892 }
fdilenarda 135:cbccf4052d45 1893 return WAIT;
fdilenarda 135:cbccf4052d45 1894 }
fdilenarda 135:cbccf4052d45 1895
msinig 133:57b208dd96fb 1896 // ----------------------------------------------------------------
fdilenarda 135:cbccf4052d45 1897
msinig 133:57b208dd96fb 1898 int MDMParser::cellLocSrvHttp (const char* token, const char* server_1, const char* server_2, int days/* = 14*/, \
msinig 133:57b208dd96fb 1899 int period/* = 4*/, int resolution/* = 1*/)
msinig 133:57b208dd96fb 1900 {
msinig 133:57b208dd96fb 1901 bool ok = false;
msinig 133:57b208dd96fb 1902 LOCK();
msinig 133:57b208dd96fb 1903 if (_dev.dev == DEV_LISA_U2_03S || _dev.dev == DEV_SARA_U2 ){
msinig 133:57b208dd96fb 1904 sendFormated("AT+UGSRV=\"%s\",\"%s\",\"%s\"\r\n", server_1, server_2, token, days, period, resolution);
msinig 133:57b208dd96fb 1905 ok = (RESP_OK == waitFinalResp());
msinig 133:57b208dd96fb 1906 } else
msinig 133:57b208dd96fb 1907 ok = false; //command not supported by module
msinig 133:57b208dd96fb 1908 UNLOCK();
msinig 133:57b208dd96fb 1909 return ok;
msinig 133:57b208dd96fb 1910 }
msinig 133:57b208dd96fb 1911
msinig 133:57b208dd96fb 1912 int MDMParser::cellLocSrvUdp(const char* server_1 /*= "cell-live1.services.u-blox.com"*/, int port /*= 46434*/, \
msinig 133:57b208dd96fb 1913 int latency/* = 1000*/, int mode/* = 0*/)
msinig 133:57b208dd96fb 1914 {
msinig 133:57b208dd96fb 1915 bool ok = false;
msinig 133:57b208dd96fb 1916 LOCK();
msinig 133:57b208dd96fb 1917 if (_dev.dev != DEV_TOBY_L2){
msinig 133:57b208dd96fb 1918 sendFormated("AT+UGAOP=\"%s\",%d,%d,%d\r\n", server_1, port, latency, mode);
msinig 133:57b208dd96fb 1919 ok = (RESP_OK == waitFinalResp());
msinig 133:57b208dd96fb 1920 } else
msinig 133:57b208dd96fb 1921 ok = false; //command not supported by module
msinig 133:57b208dd96fb 1922 UNLOCK();
msinig 133:57b208dd96fb 1923 return ok;
msinig 133:57b208dd96fb 1924 }
msinig 133:57b208dd96fb 1925
msinig 133:57b208dd96fb 1926 int MDMParser::cellLocUnsolIndication(int mode)
msinig 133:57b208dd96fb 1927 {
msinig 133:57b208dd96fb 1928 bool ok = false;
msinig 133:57b208dd96fb 1929 LOCK();
msinig 133:57b208dd96fb 1930 if (_dev.dev == DEV_LISA_U2_03S){
msinig 133:57b208dd96fb 1931 sendFormated("AT+ULOCIND=%d\r\n", mode);
msinig 133:57b208dd96fb 1932 ok = (RESP_OK == waitFinalResp());
msinig 133:57b208dd96fb 1933 } else
msinig 133:57b208dd96fb 1934 ok = false; //command not supported by module
msinig 133:57b208dd96fb 1935 UNLOCK();
msinig 133:57b208dd96fb 1936 return ok;
msinig 133:57b208dd96fb 1937 }
msinig 133:57b208dd96fb 1938
msinig 133:57b208dd96fb 1939 int MDMParser::cellLocConfigSensor(int scanMode)
msinig 133:57b208dd96fb 1940 {
msinig 133:57b208dd96fb 1941 bool ok = false;
msinig 133:57b208dd96fb 1942 LOCK();
msinig 133:57b208dd96fb 1943 if (_dev.dev != DEV_TOBY_L2){
msinig 133:57b208dd96fb 1944 sendFormated("AT+ULOCCELL=%d\r\n", scanMode);
msinig 133:57b208dd96fb 1945 ok = (RESP_OK == waitFinalResp());
msinig 133:57b208dd96fb 1946 }else
msinig 133:57b208dd96fb 1947 ok = false; //command not supported by module
msinig 133:57b208dd96fb 1948 UNLOCK();
msinig 133:57b208dd96fb 1949 return ok;
msinig 133:57b208dd96fb 1950 }
msinig 133:57b208dd96fb 1951
msinig 133:57b208dd96fb 1952 int MDMParser::cellLocRequest(int sensor, int timeout, int accuracy, int numHypotesis /* =1*/)
msinig 133:57b208dd96fb 1953 {
msinig 133:57b208dd96fb 1954 bool ok = false;
msinig 133:57b208dd96fb 1955
msinig 133:57b208dd96fb 1956 LOCK();
msinig 133:57b208dd96fb 1957 _loc.validData = false;
msinig 133:57b208dd96fb 1958 if (_dev.dev == DEV_LISA_U2_03S){
msinig 133:57b208dd96fb 1959 sendFormated("AT+ULOC=2,%d,1,%d,%d,%d\r\n", sensor, timeout, accuracy, numHypotesis);
msinig 133:57b208dd96fb 1960 ok = (RESP_OK == waitFinalResp());
msinig 133:57b208dd96fb 1961 } else if (_dev.dev != DEV_TOBY_L2){
msinig 133:57b208dd96fb 1962 sendFormated("AT+ULOC=2,%d,1,%d,%d\r\n", sensor, timeout, accuracy);
msinig 133:57b208dd96fb 1963 ok = (RESP_OK == waitFinalResp());
msinig 133:57b208dd96fb 1964 }
msinig 133:57b208dd96fb 1965 else ok = false; //command not supported by module
msinig 133:57b208dd96fb 1966
msinig 133:57b208dd96fb 1967
msinig 133:57b208dd96fb 1968 UNLOCK();
msinig 133:57b208dd96fb 1969 return ok;
msinig 133:57b208dd96fb 1970 }
msinig 133:57b208dd96fb 1971
msinig 133:57b208dd96fb 1972 int MDMParser::cellLocGet(CellLocData *data){
msinig 133:57b208dd96fb 1973 waitFinalResp(NULL,NULL,0);
msinig 133:57b208dd96fb 1974 if (_loc.validData){
msinig 133:57b208dd96fb 1975 memcpy(data, &_loc, sizeof(_loc));
msinig 133:57b208dd96fb 1976 _loc.validData = false;
msinig 133:57b208dd96fb 1977 return true;
msinig 133:57b208dd96fb 1978 }
msinig 133:57b208dd96fb 1979 return false;
msinig 133:57b208dd96fb 1980 }
msinig 133:57b208dd96fb 1981
mazgch 70:0a87d256cd24 1982 // ----------------------------------------------------------------
mazgch 74:208e3e32d263 1983 bool MDMParser::setDebug(int level)
mazgch 74:208e3e32d263 1984 {
mazgch 74:208e3e32d263 1985 #ifdef MDM_DEBUG
mazgch 123:66cef6353b13 1986 _debugLevel = (level < -1) ? -1 :
mazgch 123:66cef6353b13 1987 (level > 3) ? 3 :
mazgch 123:66cef6353b13 1988 level;
mazgch 74:208e3e32d263 1989 #endif
mazgch 123:66cef6353b13 1990 return _debugLevel == level;
mazgch 74:208e3e32d263 1991 }
mazgch 74:208e3e32d263 1992
mazgch 73:2b32e0a21df2 1993 void MDMParser::dumpDevStatus(MDMParser::DevStatus* status,
mazgch 73:2b32e0a21df2 1994 _DPRINT dprint, void* param)
mazgch 54:7ba8e4c218e2 1995 {
mazgch 75:ce6e12067d0c 1996 dprint(param, "Modem::devStatus\r\n");
msinig 133:57b208dd96fb 1997 const char* txtDev[] = { "Unknown", "SARA-G35", "LISA-U2", "LISA-U2-03S", "LISA-C2",
mazgch 125:25a292afbac6 1998 "SARA-U2", "LEON-G2", "TOBY-L2", "MPCI-L2" };
mazgch 98:c786461edd40 1999 if (status->dev < sizeof(txtDev)/sizeof(*txtDev) && (status->dev != DEV_UNKNOWN))
mazgch 73:2b32e0a21df2 2000 dprint(param, " Device: %s\r\n", txtDev[status->dev]);
mazgch 54:7ba8e4c218e2 2001 const char* txtLpm[] = { "Disabled", "Enabled", "Active" };
mazgch 54:7ba8e4c218e2 2002 if (status->lpm < sizeof(txtLpm)/sizeof(*txtLpm))
mazgch 73:2b32e0a21df2 2003 dprint(param, " Power Save: %s\r\n", txtLpm[status->lpm]);
mazgch 75:ce6e12067d0c 2004 const char* txtSim[] = { "Unknown", "Missing", "Pin", "Ready" };
mazgch 98:c786461edd40 2005 if (status->sim < sizeof(txtSim)/sizeof(*txtSim) && (status->sim != SIM_UNKNOWN))
mazgch 73:2b32e0a21df2 2006 dprint(param, " SIM: %s\r\n", txtSim[status->sim]);
mazgch 54:7ba8e4c218e2 2007 if (*status->ccid)
mazgch 73:2b32e0a21df2 2008 dprint(param, " CCID: %s\r\n", status->ccid);
mazgch 54:7ba8e4c218e2 2009 if (*status->imei)
mazgch 73:2b32e0a21df2 2010 dprint(param, " IMEI: %s\r\n", status->imei);
mazgch 54:7ba8e4c218e2 2011 if (*status->imsi)
mazgch 73:2b32e0a21df2 2012 dprint(param, " IMSI: %s\r\n", status->imsi);
mazgch 54:7ba8e4c218e2 2013 if (*status->meid)
mazgch 73:2b32e0a21df2 2014 dprint(param, " MEID: %s\r\n", status->meid); // LISA-C
mazgch 54:7ba8e4c218e2 2015 if (*status->manu)
mazgch 73:2b32e0a21df2 2016 dprint(param, " Manufacturer: %s\r\n", status->manu);
mazgch 54:7ba8e4c218e2 2017 if (*status->model)
mazgch 73:2b32e0a21df2 2018 dprint(param, " Model: %s\r\n", status->model);
mazgch 54:7ba8e4c218e2 2019 if (*status->ver)
mazgch 73:2b32e0a21df2 2020 dprint(param, " Version: %s\r\n", status->ver);
mazgch 54:7ba8e4c218e2 2021 }
mazgch 54:7ba8e4c218e2 2022
mazgch 73:2b32e0a21df2 2023 void MDMParser::dumpNetStatus(MDMParser::NetStatus *status,
mazgch 73:2b32e0a21df2 2024 _DPRINT dprint, void* param)
mazgch 54:7ba8e4c218e2 2025 {
mazgch 75:ce6e12067d0c 2026 dprint(param, "Modem::netStatus\r\n");
mazgch 54:7ba8e4c218e2 2027 const char* txtReg[] = { "Unknown", "Denied", "None", "Home", "Roaming" };
mazgch 98:c786461edd40 2028 if (status->csd < sizeof(txtReg)/sizeof(*txtReg) && (status->csd != REG_UNKNOWN))
mazgch 79:291df065e345 2029 dprint(param, " CSD Registration: %s\r\n", txtReg[status->csd]);
mazgch 98:c786461edd40 2030 if (status->psd < sizeof(txtReg)/sizeof(*txtReg) && (status->psd != REG_UNKNOWN))
mazgch 79:291df065e345 2031 dprint(param, " PSD Registration: %s\r\n", txtReg[status->psd]);
mazgch 123:66cef6353b13 2032 if (status->eps < sizeof(txtReg)/sizeof(*txtReg) && (status->eps != REG_UNKNOWN))
mazgch 123:66cef6353b13 2033 dprint(param, " EPS Registration: %s\r\n", txtReg[status->eps]);
mazgch 123:66cef6353b13 2034 const char* txtAct[] = { "Unknown", "GSM", "Edge", "3G", "CDMA", "LTE" };
mazgch 98:c786461edd40 2035 if (status->act < sizeof(txtAct)/sizeof(*txtAct) && (status->act != ACT_UNKNOWN))
mazgch 73:2b32e0a21df2 2036 dprint(param, " Access Technology: %s\r\n", txtAct[status->act]);
mazgch 54:7ba8e4c218e2 2037 if (status->rssi)
mazgch 73:2b32e0a21df2 2038 dprint(param, " Signal Strength: %d dBm\r\n", status->rssi);
mazgch 54:7ba8e4c218e2 2039 if (status->ber)
mazgch 73:2b32e0a21df2 2040 dprint(param, " Bit Error Rate: %d\r\n", status->ber);
mazgch 54:7ba8e4c218e2 2041 if (*status->opr)
mazgch 73:2b32e0a21df2 2042 dprint(param, " Operator: %s\r\n", status->opr);
mazgch 54:7ba8e4c218e2 2043 if (status->lac != 0xFFFF)
mazgch 73:2b32e0a21df2 2044 dprint(param, " Location Area Code: %04X\r\n", status->lac);
mazgch 54:7ba8e4c218e2 2045 if (status->ci != 0xFFFFFFFF)
mazgch 73:2b32e0a21df2 2046 dprint(param, " Cell ID: %08X\r\n", status->ci);
mazgch 54:7ba8e4c218e2 2047 if (*status->num)
mazgch 73:2b32e0a21df2 2048 dprint(param, " Phone Number: %s\r\n", status->num);
mazgch 54:7ba8e4c218e2 2049 }
mazgch 54:7ba8e4c218e2 2050
mazgch 73:2b32e0a21df2 2051 void MDMParser::dumpIp(MDMParser::IP ip,
mazgch 73:2b32e0a21df2 2052 _DPRINT dprint, void* param)
mazgch 54:7ba8e4c218e2 2053 {
mazgch 57:869bd35f44cc 2054 if (ip != NOIP)
mazgch 75:ce6e12067d0c 2055 dprint(param, "Modem:IP " IPSTR "\r\n", IPNUM(ip));
mazgch 54:7ba8e4c218e2 2056 }
mazgch 70:0a87d256cd24 2057
mazgch 21:c4d64830bf02 2058 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 2059 int MDMParser::_parseMatch(Pipe<char>* pipe, int len, const char* sta, const char* end)
mazgch 18:e5697801df29 2060 {
mazgch 18:e5697801df29 2061 int o = 0;
mazgch 21:c4d64830bf02 2062 if (sta) {
mazgch 21:c4d64830bf02 2063 while (*sta) {
mazgch 21:c4d64830bf02 2064 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 2065 char ch = pipe->next();
mazgch 21:c4d64830bf02 2066 if (*sta++ != ch) return NOT_FOUND;
mazgch 21:c4d64830bf02 2067 }
mazgch 21:c4d64830bf02 2068 }
mazgch 21:c4d64830bf02 2069 if (!end) return o; // no termination
mazgch 35:9275215a3a5b 2070 // at least any char
mazgch 35:9275215a3a5b 2071 if (++o > len) return WAIT;
mazgch 35:9275215a3a5b 2072 pipe->next();
mazgch 35:9275215a3a5b 2073 // check the end
mazgch 21:c4d64830bf02 2074 int x = 0;
mazgch 21:c4d64830bf02 2075 while (end[x]) {
mazgch 21:c4d64830bf02 2076 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 2077 char ch = pipe->next();
mazgch 21:c4d64830bf02 2078 x = (end[x] == ch) ? x + 1 :
mazgch 21:c4d64830bf02 2079 (end[0] == ch) ? 1 :
mazgch 21:c4d64830bf02 2080 0;
mazgch 21:c4d64830bf02 2081 }
mazgch 21:c4d64830bf02 2082 return o;
mazgch 21:c4d64830bf02 2083 }
mazgch 21:c4d64830bf02 2084
mazgch 21:c4d64830bf02 2085 int MDMParser::_parseFormated(Pipe<char>* pipe, int len, const char* fmt)
mazgch 21:c4d64830bf02 2086 {
mazgch 21:c4d64830bf02 2087 int o = 0;
mazgch 21:c4d64830bf02 2088 int num = 0;
mazgch 21:c4d64830bf02 2089 if (fmt) {
mazgch 21:c4d64830bf02 2090 while (*fmt) {
mazgch 21:c4d64830bf02 2091 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 2092 char ch = pipe->next();
mazgch 21:c4d64830bf02 2093 if (*fmt == '%') {
mazgch 21:c4d64830bf02 2094 fmt++;
mazgch 21:c4d64830bf02 2095 if (*fmt == 'd') { // numeric
mazgch 21:c4d64830bf02 2096 fmt ++;
mazgch 21:c4d64830bf02 2097 num = 0;
mazgch 21:c4d64830bf02 2098 while (ch >= '0' && ch <= '9') {
mazgch 21:c4d64830bf02 2099 num = num * 10 + (ch - '0');
mazgch 21:c4d64830bf02 2100 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 2101 ch = pipe->next();
mazgch 21:c4d64830bf02 2102 }
mazgch 21:c4d64830bf02 2103 }
mazgch 21:c4d64830bf02 2104 else if (*fmt == 'c') { // char buffer (takes last numeric as length)
mazgch 21:c4d64830bf02 2105 fmt ++;
mazgch 21:c4d64830bf02 2106 while (num --) {
mazgch 21:c4d64830bf02 2107 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 2108 ch = pipe->next();
mazgch 21:c4d64830bf02 2109 }
mazgch 21:c4d64830bf02 2110 }
mazgch 80:34985b4d821e 2111 else if (*fmt == 's') {
mazgch 80:34985b4d821e 2112 fmt ++;
mazgch 80:34985b4d821e 2113 if (ch != '\"') return NOT_FOUND;
mazgch 80:34985b4d821e 2114 do {
mazgch 80:34985b4d821e 2115 if (++o > len) return WAIT;
mazgch 80:34985b4d821e 2116 ch = pipe->next();
mazgch 80:34985b4d821e 2117 } while (ch != '\"');
mazgch 80:34985b4d821e 2118 if (++o > len) return WAIT;
mazgch 80:34985b4d821e 2119 ch = pipe->next();
mazgch 80:34985b4d821e 2120 }
mazgch 21:c4d64830bf02 2121 }
mazgch 21:c4d64830bf02 2122 if (*fmt++ != ch) return NOT_FOUND;
mazgch 18:e5697801df29 2123 }
mazgch 18:e5697801df29 2124 }
mazgch 21:c4d64830bf02 2125 return o;
mazgch 21:c4d64830bf02 2126 }
mazgch 21:c4d64830bf02 2127
mazgch 21:c4d64830bf02 2128 int MDMParser::_getLine(Pipe<char>* pipe, char* buf, int len)
mazgch 21:c4d64830bf02 2129 {
mazgch 21:c4d64830bf02 2130 int unkn = 0;
mazgch 21:c4d64830bf02 2131 int sz = pipe->size();
mazgch 21:c4d64830bf02 2132 int fr = pipe->free();
mazgch 21:c4d64830bf02 2133 if (len > sz)
mazgch 21:c4d64830bf02 2134 len = sz;
mazgch 21:c4d64830bf02 2135 while (len > 0)
mazgch 21:c4d64830bf02 2136 {
mazgch 21:c4d64830bf02 2137 static struct {
mazgch 21:c4d64830bf02 2138 const char* fmt; int type;
mazgch 21:c4d64830bf02 2139 } lutF[] = {
mazgch 21:c4d64830bf02 2140 { "\r\n+USORD: %d,%d,\"%c\"", TYPE_PLUS },
mazgch 95:8282dbbe1492 2141 { "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,\"%c\"", TYPE_PLUS },
mazgch 80:34985b4d821e 2142 { "\r\n+URDFILE: %s,%d,\"%c\"", TYPE_PLUS },
fdilenarda 135:cbccf4052d45 2143 { "\r\n+URDBLOCK: %s,%d,\"%c\"", TYPE_PLUS },
mazgch 21:c4d64830bf02 2144 };
mazgch 21:c4d64830bf02 2145 static struct {
mazgch 21:c4d64830bf02 2146 const char* sta; const char* end; int type;
mazgch 21:c4d64830bf02 2147 } lut[] = {
mazgch 21:c4d64830bf02 2148 { "\r\nOK\r\n", NULL, TYPE_OK },
mazgch 21:c4d64830bf02 2149 { "\r\nERROR\r\n", NULL, TYPE_ERROR },
msinig 134:2fbd5723e063 2150 { "\r\n+CME ERROR:", "\r\n", TYPE_ERROR_CME },
mazgch 21:c4d64830bf02 2151 { "\r\n+CMS ERROR:", "\r\n", TYPE_ERROR },
mazgch 21:c4d64830bf02 2152 { "\r\nRING\r\n", NULL, TYPE_RING },
mazgch 21:c4d64830bf02 2153 { "\r\nCONNECT\r\n", NULL, TYPE_CONNECT },
mazgch 21:c4d64830bf02 2154 { "\r\nNO CARRIER\r\n", NULL, TYPE_NOCARRIER },
mazgch 21:c4d64830bf02 2155 { "\r\nNO DIALTONE\r\n", NULL, TYPE_NODIALTONE },
mazgch 21:c4d64830bf02 2156 { "\r\nBUSY\r\n", NULL, TYPE_BUSY },
mazgch 21:c4d64830bf02 2157 { "\r\nNO ANSWER\r\n", NULL, TYPE_NOANSWER },
mazgch 21:c4d64830bf02 2158 { "\r\n+", "\r\n", TYPE_PLUS },
mazgch 21:c4d64830bf02 2159 { "\r\n@", NULL, TYPE_PROMPT }, // Sockets
mazgch 21:c4d64830bf02 2160 { "\r\n>", NULL, TYPE_PROMPT }, // SMS
mazgch 80:34985b4d821e 2161 { "\n>", NULL, TYPE_PROMPT }, // File
mazgch 21:c4d64830bf02 2162 };
mazgch 21:c4d64830bf02 2163 for (int i = 0; i < sizeof(lutF)/sizeof(*lutF); i ++) {
mazgch 21:c4d64830bf02 2164 pipe->set(unkn);
mazgch 21:c4d64830bf02 2165 int ln = _parseFormated(pipe, len, lutF[i].fmt);
mazgch 21:c4d64830bf02 2166 if (ln == WAIT && fr)
mazgch 21:c4d64830bf02 2167 return WAIT;
mazgch 21:c4d64830bf02 2168 if ((ln != NOT_FOUND) && (unkn > 0))
mazgch 31:a0bed6c1e05d 2169 return TYPE_UNKNOWN | pipe->get(buf, unkn);
mazgch 21:c4d64830bf02 2170 if (ln > 0)
mazgch 21:c4d64830bf02 2171 return lutF[i].type | pipe->get(buf, ln);
mazgch 21:c4d64830bf02 2172 }
mazgch 21:c4d64830bf02 2173 for (int i = 0; i < sizeof(lut)/sizeof(*lut); i ++) {
mazgch 21:c4d64830bf02 2174 pipe->set(unkn);
mazgch 21:c4d64830bf02 2175 int ln = _parseMatch(pipe, len, lut[i].sta, lut[i].end);
mazgch 21:c4d64830bf02 2176 if (ln == WAIT && fr)
mazgch 21:c4d64830bf02 2177 return WAIT;
mazgch 21:c4d64830bf02 2178 if ((ln != NOT_FOUND) && (unkn > 0))
mazgch 31:a0bed6c1e05d 2179 return TYPE_UNKNOWN | pipe->get(buf, unkn);
mazgch 21:c4d64830bf02 2180 if (ln > 0)
mazgch 21:c4d64830bf02 2181 return lut[i].type | pipe->get(buf, ln);
mazgch 21:c4d64830bf02 2182 }
mazgch 21:c4d64830bf02 2183 // UNKNOWN
mazgch 21:c4d64830bf02 2184 unkn ++;
mazgch 21:c4d64830bf02 2185 len--;
mazgch 21:c4d64830bf02 2186 }
mazgch 18:e5697801df29 2187 return WAIT;
mazgch 18:e5697801df29 2188 }
mazgch 18:e5697801df29 2189
mazgch 18:e5697801df29 2190 // ----------------------------------------------------------------
mazgch 18:e5697801df29 2191 // Serial Implementation
mazgch 18:e5697801df29 2192 // ----------------------------------------------------------------
mazgch 18:e5697801df29 2193
mazgch 76:f7c3dd568dae 2194 /*! Helper Dev Null Device
mazgch 76:f7c3dd568dae 2195 Small helper class used to shut off stderr/stdout. Sometimes stdin/stdout
mazgch 76:f7c3dd568dae 2196 is shared with the serial port of the modem. Having printfs inbetween the
mazgch 76:f7c3dd568dae 2197 AT commands you cause a failure of the modem.
mazgch 76:f7c3dd568dae 2198 */
mazgch 76:f7c3dd568dae 2199 class DevNull : public Stream {
mazgch 76:f7c3dd568dae 2200 public:
mazgch 76:f7c3dd568dae 2201 DevNull() : Stream(_name+1) { } //!< Constructor
mazgch 76:f7c3dd568dae 2202 void claim(const char* mode, FILE* file)
mazgch 76:f7c3dd568dae 2203 { freopen(_name, mode, file); } //!< claim a stream
mazgch 76:f7c3dd568dae 2204 protected:
mazgch 76:f7c3dd568dae 2205 virtual int _getc() { return EOF; } //!< Nothing
mazgch 76:f7c3dd568dae 2206 virtual int _putc(int c) { return c; } //!< Discard
mazgch 76:f7c3dd568dae 2207 static const char* _name; //!< File name
mazgch 76:f7c3dd568dae 2208 };
mazgch 76:f7c3dd568dae 2209 const char* DevNull::_name = "/null"; //!< the null device name
mazgch 76:f7c3dd568dae 2210 static DevNull null; //!< the null device
mazgch 76:f7c3dd568dae 2211
mazgch 19:2b5d097ca15d 2212 MDMSerial::MDMSerial(PinName tx /*= MDMTXD*/, PinName rx /*= MDMRXD*/,
mazgch 19:2b5d097ca15d 2213 int baudrate /*= MDMBAUD*/,
mazgch 43:a89a7a505991 2214 #if DEVICE_SERIAL_FC
mazgch 19:2b5d097ca15d 2215 PinName rts /*= MDMRTS*/, PinName cts /*= MDMCTS*/,
mazgch 43:a89a7a505991 2216 #endif
mazgch 18:e5697801df29 2217 int rxSize /*= 256*/, int txSize /*= 128*/) :
mazgch 35:9275215a3a5b 2218 SerialPipe(tx, rx, rxSize, txSize)
mazgch 18:e5697801df29 2219 {
mazgch 76:f7c3dd568dae 2220 if (rx == USBRX)
mazgch 76:f7c3dd568dae 2221 null.claim("r", stdin);
mazgch 76:f7c3dd568dae 2222 if (tx == USBTX) {
mazgch 76:f7c3dd568dae 2223 null.claim("w", stdout);
mazgch 76:f7c3dd568dae 2224 null.claim("w", stderr);
mazgch 74:208e3e32d263 2225 #ifdef MDM_DEBUG
mazgch 76:f7c3dd568dae 2226 _debugLevel = -1;
mazgch 76:f7c3dd568dae 2227 #endif
mazgch 76:f7c3dd568dae 2228 }
mazgch 74:208e3e32d263 2229 #ifdef TARGET_UBLOX_C027
mazgch 74:208e3e32d263 2230 _onboard = (tx == MDMTXD) && (rx == MDMRXD);
mazgch 74:208e3e32d263 2231 if (_onboard)
mazgch 74:208e3e32d263 2232 c027_mdm_powerOn(false);
mazgch 74:208e3e32d263 2233 #endif
mazgch 18:e5697801df29 2234 baud(baudrate);
mazgch 35:9275215a3a5b 2235 #if DEVICE_SERIAL_FC
mazgch 35:9275215a3a5b 2236 if ((rts != NC) || (cts != NC))
mazgch 35:9275215a3a5b 2237 {
mazgch 35:9275215a3a5b 2238 Flow flow = (cts == NC) ? RTS :
mazgch 35:9275215a3a5b 2239 (rts == NC) ? CTS : RTSCTS ;
mazgch 35:9275215a3a5b 2240 set_flow_control(flow, rts, cts);
mazgch 35:9275215a3a5b 2241 if (cts != NC) _dev.lpm = LPM_ENABLED;
mazgch 35:9275215a3a5b 2242 }
mazgch 35:9275215a3a5b 2243 #endif
mazgch 18:e5697801df29 2244 }
mazgch 18:e5697801df29 2245
mazgch 76:f7c3dd568dae 2246 MDMSerial::~MDMSerial(void)
mazgch 76:f7c3dd568dae 2247 {
mazgch 76:f7c3dd568dae 2248 powerOff();
mazgch 76:f7c3dd568dae 2249 #ifdef TARGET_UBLOX_C027
mazgch 76:f7c3dd568dae 2250 if (_onboard)
mazgch 76:f7c3dd568dae 2251 c027_mdm_powerOff();
mazgch 76:f7c3dd568dae 2252 #endif
mazgch 76:f7c3dd568dae 2253 }
mazgch 76:f7c3dd568dae 2254
mazgch 18:e5697801df29 2255 int MDMSerial::_send(const void* buf, int len)
mazgch 18:e5697801df29 2256 {
mazgch 35:9275215a3a5b 2257 return put((const char*)buf, len, true/*=blocking*/);
mazgch 18:e5697801df29 2258 }
mazgch 18:e5697801df29 2259
mazgch 18:e5697801df29 2260 int MDMSerial::getLine(char* buffer, int length)
mazgch 18:e5697801df29 2261 {
mazgch 18:e5697801df29 2262 return _getLine(&_pipeRx, buffer, length);
mazgch 18:e5697801df29 2263 }
mazgch 18:e5697801df29 2264
mazgch 18:e5697801df29 2265 // ----------------------------------------------------------------
mazgch 18:e5697801df29 2266 // USB Implementation
mazgch 18:e5697801df29 2267 // ----------------------------------------------------------------
mazgch 18:e5697801df29 2268
mazgch 18:e5697801df29 2269 #ifdef HAVE_MDMUSB
mazgch 76:f7c3dd568dae 2270 MDMUsb::MDMUsb(void)
mazgch 74:208e3e32d263 2271 {
mazgch 74:208e3e32d263 2272 #ifdef MDM_DEBUG
mazgch 74:208e3e32d263 2273 _debugLevel = 1;
mazgch 74:208e3e32d263 2274 #endif
mazgch 74:208e3e32d263 2275 #ifdef TARGET_UBLOX_C027
mazgch 74:208e3e32d263 2276 _onboard = true;
mazgch 74:208e3e32d263 2277 c027_mdm_powerOn(true);
mazgch 74:208e3e32d263 2278 #endif
mazgch 74:208e3e32d263 2279 }
mazgch 76:f7c3dd568dae 2280
mazgch 76:f7c3dd568dae 2281 MDMUsb::~MDMUsb(void)
mazgch 76:f7c3dd568dae 2282 {
mazgch 76:f7c3dd568dae 2283 powerOff();
mazgch 76:f7c3dd568dae 2284 #ifdef TARGET_UBLOX_C027
mazgch 76:f7c3dd568dae 2285 if (_onboard)
mazgch 76:f7c3dd568dae 2286 c027_mdm_powerOff();
mazgch 76:f7c3dd568dae 2287 #endif
mazgch 76:f7c3dd568dae 2288 }
mazgch 76:f7c3dd568dae 2289
mazgch 76:f7c3dd568dae 2290 int MDMUsb::_send(const void* buf, int len) { return 0; }
mazgch 76:f7c3dd568dae 2291
mazgch 18:e5697801df29 2292 int MDMUsb::getLine(char* buffer, int length) { return NOT_FOUND; }
mazgch 76:f7c3dd568dae 2293
msinig 133:57b208dd96fb 2294 #endif