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:
mazgch
Date:
Tue Sep 01 15:50:06 2015 +0000
Revision:
131:965a7cbc1e58
Parent:
130:3189949981ec
Child:
133:57b208dd96fb
re-use context in LTE

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()))
mazgch 80:34985b4d821e 16 //! registration ok check helper
mazgch 79:291df065e345 17 #define REG_OK(r) ((r == REG_HOME) || (r == REG_ROAMING))
mazgch 80:34985b4d821e 18 //! registration done check helper (no need to poll further)
mazgch 79:291df065e345 19 #define REG_DONE(r) ((r == REG_HOME) || (r == REG_ROAMING) || (r == REG_DENIED))
mazgch 95:8282dbbe1492 20 //! helper to make sure that lock unlock pair is always balaced
mazgch 95:8282dbbe1492 21 #define LOCK() { lock()
mazgch 95:8282dbbe1492 22 //! helper to make sure that lock unlock pair is always balaced
mazgch 95:8282dbbe1492 23 #define UNLOCK() } unlock()
mazgch 79:291df065e345 24
mazgch 74:208e3e32d263 25 #ifdef MDM_DEBUG
mazgch 95:8282dbbe1492 26 #if 1 // colored terminal output using ANSI escape sequences
mazgch 95:8282dbbe1492 27 #define COL(c) "\033[" c
mazgch 95:8282dbbe1492 28 #else
mazgch 95:8282dbbe1492 29 #define COL(c)
mazgch 95:8282dbbe1492 30 #endif
mazgch 95:8282dbbe1492 31 #define DEF COL("39m")
mazgch 95:8282dbbe1492 32 #define BLA COL("30m")
mazgch 95:8282dbbe1492 33 #define RED COL("31m")
mazgch 95:8282dbbe1492 34 #define GRE COL("32m")
mazgch 95:8282dbbe1492 35 #define YEL COL("33m")
mazgch 95:8282dbbe1492 36 #define BLU COL("34m")
mazgch 95:8282dbbe1492 37 #define MAG COL("35m")
mazgch 95:8282dbbe1492 38 #define CYA COL("36m")
mazgch 95:8282dbbe1492 39 #define WHY COL("37m")
mazgch 95:8282dbbe1492 40
mazgch 74:208e3e32d263 41 void dumpAtCmd(const char* buf, int len)
mazgch 21:c4d64830bf02 42 {
mazgch 75:ce6e12067d0c 43 ::printf(" %3d \"", len);
mazgch 21:c4d64830bf02 44 while (len --) {
mazgch 21:c4d64830bf02 45 char ch = *buf++;
mazgch 75:ce6e12067d0c 46 if ((ch > 0x1F) && (ch != 0x7F)) { // is printable
mazgch 75:ce6e12067d0c 47 if (ch == '%') ::printf("%%");
mazgch 75:ce6e12067d0c 48 else if (ch == '"') ::printf("\\\"");
mazgch 75:ce6e12067d0c 49 else if (ch == '\\') ::printf("\\\\");
mazgch 75:ce6e12067d0c 50 else putchar(ch);
mazgch 75:ce6e12067d0c 51 } else {
mazgch 75:ce6e12067d0c 52 if (ch == '\a') ::printf("\\a"); // BEL (0x07)
mazgch 75:ce6e12067d0c 53 else if (ch == '\b') ::printf("\\b"); // Backspace (0x08)
mazgch 75:ce6e12067d0c 54 else if (ch == '\t') ::printf("\\t"); // Horizontal Tab (0x09)
mazgch 75:ce6e12067d0c 55 else if (ch == '\n') ::printf("\\n"); // Linefeed (0x0A)
mazgch 75:ce6e12067d0c 56 else if (ch == '\v') ::printf("\\v"); // Vertical Tab (0x0B)
mazgch 75:ce6e12067d0c 57 else if (ch == '\f') ::printf("\\f"); // Formfeed (0x0C)
mazgch 75:ce6e12067d0c 58 else if (ch == '\r') ::printf("\\r"); // Carriage Return (0x0D)
mazgch 76:f7c3dd568dae 59 else ::printf("\\x%02x", (unsigned char)ch);
mazgch 75:ce6e12067d0c 60 }
mazgch 21:c4d64830bf02 61 }
mazgch 75:ce6e12067d0c 62 ::printf("\"\r\n");
mazgch 21:c4d64830bf02 63 }
mazgch 74:208e3e32d263 64
mazgch 117:74e4e0109a9e 65 void MDMParser::_debugPrint(int level, const char* color, const char* format, ...)
mazgch 117:74e4e0109a9e 66 {
mazgch 117:74e4e0109a9e 67 if (_debugLevel >= level)
mazgch 117:74e4e0109a9e 68 {
mazgch 117:74e4e0109a9e 69 va_list args;
mazgch 117:74e4e0109a9e 70 va_start (args, format);
mazgch 117:74e4e0109a9e 71 if (color) ::printf(color);
mazgch 117:74e4e0109a9e 72 ::vprintf(format, args);
mazgch 117:74e4e0109a9e 73 if (color) ::printf(DEF);
mazgch 117:74e4e0109a9e 74 va_end (args);
mazgch 117:74e4e0109a9e 75 }
mazgch 117:74e4e0109a9e 76 }
mazgch 117:74e4e0109a9e 77
mazgch 117:74e4e0109a9e 78 #define ERROR(...) _debugPrint(0, RED, __VA_ARGS__)
mazgch 117:74e4e0109a9e 79 #define INFO(...) _debugPrint(1, GRE, __VA_ARGS__)
mazgch 117:74e4e0109a9e 80 #define TRACE(...) _debugPrint(2, DEF, __VA_ARGS__)
mazgch 117:74e4e0109a9e 81 #define TEST(...) _debugPrint(3, CYA, __VA_ARGS__)
mazgch 74:208e3e32d263 82
mazgch 74:208e3e32d263 83 #else
mazgch 74:208e3e32d263 84
mazgch 75:ce6e12067d0c 85 #define ERROR(...) (void)0 // no tracing
mazgch 95:8282dbbe1492 86 #define TEST(...) (void)0 // no tracing
mazgch 74:208e3e32d263 87 #define INFO(...) (void)0 // no tracing
mazgch 74:208e3e32d263 88 #define TRACE(...) (void)0 // no tracing
mazgch 74:208e3e32d263 89
mazgch 31:a0bed6c1e05d 90 #endif
mazgch 21:c4d64830bf02 91
mazgch 44:9d12223b78ff 92 MDMParser* MDMParser::inst;
mazgch 44:9d12223b78ff 93
mazgch 21:c4d64830bf02 94 MDMParser::MDMParser(void)
mazgch 21:c4d64830bf02 95 {
mazgch 44:9d12223b78ff 96 inst = this;
mazgch 31:a0bed6c1e05d 97 memset(&_dev, 0, sizeof(_dev));
mazgch 31:a0bed6c1e05d 98 memset(&_net, 0, sizeof(_net));
mazgch 54:7ba8e4c218e2 99 _net.lac = 0xFFFF;
mazgch 54:7ba8e4c218e2 100 _net.ci = 0xFFFFFFFF;
mazgch 35:9275215a3a5b 101 _ip = NOIP;
mazgch 76:f7c3dd568dae 102 _init = false;
mazgch 31:a0bed6c1e05d 103 memset(_sockets, 0, sizeof(_sockets));
mazgch 104:c64ba749a422 104 for (int socket = 0; socket < NUMSOCKETS; socket ++)
mazgch 103:197fa7920ad8 105 _sockets[socket].handle = SOCKET_ERROR;
mazgch 74:208e3e32d263 106 #ifdef MDM_DEBUG
mazgch 76:f7c3dd568dae 107 _debugLevel = 1;
mazgch 74:208e3e32d263 108 _debugTime.start();
mazgch 74:208e3e32d263 109 #endif
mazgch 74:208e3e32d263 110 }
mazgch 74:208e3e32d263 111
mazgch 18:e5697801df29 112 int MDMParser::send(const char* buf, int len)
mazgch 18:e5697801df29 113 {
mazgch 74:208e3e32d263 114 #ifdef MDM_DEBUG
mazgch 74:208e3e32d263 115 if (_debugLevel >= 3) {
mazgch 75:ce6e12067d0c 116 ::printf("%10.3f AT send ", _debugTime.read_ms()*0.001);
mazgch 74:208e3e32d263 117 dumpAtCmd(buf,len);
mazgch 74:208e3e32d263 118 }
mazgch 21:c4d64830bf02 119 #endif
mazgch 18:e5697801df29 120 return _send(buf, len);
mazgch 18:e5697801df29 121 }
mazgch 18:e5697801df29 122
mazgch 21:c4d64830bf02 123 int MDMParser::sendFormated(const char* format, ...) {
mazgch 21:c4d64830bf02 124 char buf[MAX_SIZE];
mazgch 21:c4d64830bf02 125 va_list args;
mazgch 21:c4d64830bf02 126 va_start(args, format);
mazgch 21:c4d64830bf02 127 int len = vsnprintf(buf,sizeof(buf), format, args);
mazgch 21:c4d64830bf02 128 va_end(args);
mazgch 21:c4d64830bf02 129 return send(buf, len);
mazgch 21:c4d64830bf02 130 }
mazgch 21:c4d64830bf02 131
mazgch 26:07be5faf8925 132 int MDMParser::waitFinalResp(_CALLBACKPTR cb /* = NULL*/,
mazgch 26:07be5faf8925 133 void* param /* = NULL*/,
mazgch 26:07be5faf8925 134 int timeout_ms /*= 5000*/)
mazgch 26:07be5faf8925 135 {
mazgch 69:4d6fa520dfca 136 char buf[MAX_SIZE + 64 /* add some more space for framing */];
mazgch 21:c4d64830bf02 137 Timer timer;
mazgch 21:c4d64830bf02 138 timer.start();
mazgch 21:c4d64830bf02 139 do {
mazgch 21:c4d64830bf02 140 int ret = getLine(buf, sizeof(buf));
mazgch 74:208e3e32d263 141 #ifdef MDM_DEBUG
mazgch 74:208e3e32d263 142 if ((_debugLevel >= 3) && (ret != WAIT) && (ret != NOT_FOUND))
mazgch 21:c4d64830bf02 143 {
mazgch 31:a0bed6c1e05d 144 int len = LENGTH(ret);
mazgch 31:a0bed6c1e05d 145 int type = TYPE(ret);
mazgch 95:8282dbbe1492 146 const char* s = (type == TYPE_UNKNOWN)? YEL "UNK" DEF :
mazgch 95:8282dbbe1492 147 (type == TYPE_TEXT) ? MAG "TXT" DEF :
mazgch 95:8282dbbe1492 148 (type == TYPE_OK ) ? GRE "OK " DEF :
mazgch 95:8282dbbe1492 149 (type == TYPE_ERROR) ? RED "ERR" DEF :
mazgch 95:8282dbbe1492 150 (type == TYPE_PLUS) ? CYA " + " DEF :
mazgch 95:8282dbbe1492 151 (type == TYPE_PROMPT) ? BLU " > " DEF :
mazgch 95:8282dbbe1492 152 "..." ;
mazgch 75:ce6e12067d0c 153 ::printf("%10.3f AT read %s", _debugTime.read_ms()*0.001, s);
mazgch 74:208e3e32d263 154 dumpAtCmd(buf, len);
mazgch 21:c4d64830bf02 155 }
mazgch 21:c4d64830bf02 156 #endif
mazgch 21:c4d64830bf02 157 if ((ret != WAIT) && (ret != NOT_FOUND))
mazgch 18:e5697801df29 158 {
mazgch 21:c4d64830bf02 159 int type = TYPE(ret);
mazgch 21:c4d64830bf02 160 // handle unsolicited commands here
mazgch 21:c4d64830bf02 161 if (type == TYPE_PLUS) {
mazgch 21:c4d64830bf02 162 const char* cmd = buf+3;
mazgch 54:7ba8e4c218e2 163 int a, b, c, d, r;
mazgch 23:05a1aeeb5fd9 164 char s[32];
mazgch 21:c4d64830bf02 165
mazgch 31:a0bed6c1e05d 166 // SMS Command ---------------------------------
mazgch 31:a0bed6c1e05d 167 // +CNMI: <mem>,<index>
mazgch 31:a0bed6c1e05d 168 if (sscanf(cmd, "CMTI: \"%*[^\"]\",%d", &a) == 1) {
mazgch 31:a0bed6c1e05d 169 TRACE("New SMS at index %d\r\n", a);
mazgch 21:c4d64830bf02 170 // Socket Specific Command ---------------------------------
mazgch 21:c4d64830bf02 171 // +UUSORD: <socket>,<length>
mazgch 103:197fa7920ad8 172 } else if ((sscanf(cmd, "UUSORD: %d,%d", &a, &b) == 2)) {
mazgch 103:197fa7920ad8 173 int socket = _findSocket(a);
mazgch 103:197fa7920ad8 174 TRACE("Socket %d: handle %d has %d bytes pending\r\n", socket, a, b);
mazgch 103:197fa7920ad8 175 if (socket != SOCKET_ERROR)
mazgch 103:197fa7920ad8 176 _sockets[socket].pending = b;
mazgch 69:4d6fa520dfca 177 // +UUSORF: <socket>,<length>
mazgch 103:197fa7920ad8 178 } else if ((sscanf(cmd, "UUSORF: %d,%d", &a, &b) == 2)) {
mazgch 103:197fa7920ad8 179 int socket = _findSocket(a);
mazgch 103:197fa7920ad8 180 TRACE("Socket %d: handle %d has %d bytes pending\r\n", socket, a, b);
mazgch 103:197fa7920ad8 181 if (socket != SOCKET_ERROR)
mazgch 103:197fa7920ad8 182 _sockets[socket].pending = b;
mazgch 21:c4d64830bf02 183 // +UUSOCL: <socket>
mazgch 103:197fa7920ad8 184 } else if ((sscanf(cmd, "UUSOCL: %d", &a) == 1)) {
mazgch 103:197fa7920ad8 185 int socket = _findSocket(a);
mazgch 103:197fa7920ad8 186 TRACE("Socket %d: handle %d closed by remote host\r\n", socket, a);
mazgch 103:197fa7920ad8 187 if ((socket != SOCKET_ERROR) && _sockets[socket].connected)
mazgch 103:197fa7920ad8 188 _sockets[socket].connected = false;
mazgch 103:197fa7920ad8 189 }
mazgch 125:25a292afbac6 190 if (_dev.dev == DEV_LISA_C2) {
mazgch 21:c4d64830bf02 191 // CDMA Specific -------------------------------------------
mazgch 21:c4d64830bf02 192 // +CREG: <n><SID>,<NID>,<stat>
mazgch 54:7ba8e4c218e2 193 if (sscanf(cmd, "CREG: %*d,%d,%d,%d",&a,&b,&c) == 3) {
mazgch 54:7ba8e4c218e2 194 // _net.sid = a;
mazgch 54:7ba8e4c218e2 195 // _net.nid = b;
mazgch 79:291df065e345 196 if (c == 0) _net.csd = REG_NONE; // not registered, home network
mazgch 79:291df065e345 197 else if (c == 1) _net.csd = REG_HOME; // registered, home network
mazgch 79:291df065e345 198 else if (c == 2) _net.csd = REG_NONE; // not registered, but MT is currently searching a new operator to register to
mazgch 79:291df065e345 199 else if (c == 3) _net.csd = REG_DENIED; // registration denied
mazgch 79:291df065e345 200 else if (c == 5) _net.csd = REG_ROAMING; // registered, roaming
mazgch 79:291df065e345 201 _net.psd = _net.csd; // fake PSD registration (CDMA is always registered)
mazgch 31:a0bed6c1e05d 202 _net.act = ACT_CDMA;
mazgch 84:a05edb010176 203 // +CSS: <mode>[,<format>,<oper>[,<AcT>]]
mazgch 21:c4d64830bf02 204 } else if (sscanf(cmd, "CSS %*c,%2s,%*d",s) == 1) {
mazgch 31:a0bed6c1e05d 205 //_net.reg = (strcmp("Z", s) == 0) ? REG_UNKNOWN : REG_HOME;
mazgch 21:c4d64830bf02 206 }
mazgch 21:c4d64830bf02 207 } else {
mazgch 21:c4d64830bf02 208 // GSM/UMTS Specific -------------------------------------------
mazgch 79:291df065e345 209 // +UUPSDD: <profile_id>
mazgch 79:291df065e345 210 if (sscanf(cmd, "UUPSDD: %d",&a) == 1) {
mazgch 79:291df065e345 211 if (*PROFILE == a) _ip = NOIP;
mazgch 79:291df065e345 212 } else {
mazgch 79:291df065e345 213 // +CREG|CGREG: <n>,<stat>[,<lac>,<ci>[,AcT[,<rac>]]] // reply to AT+CREG|AT+CGREG
mazgch 79:291df065e345 214 // +CREG|CGREG: <stat>[,<lac>,<ci>[,AcT[,<rac>]]] // URC
mazgch 79:291df065e345 215 b = 0xFFFF; c = 0xFFFFFFFF; d = -1;
mazgch 79:291df065e345 216 r = sscanf(cmd, "%s %*d,%d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d);
mazgch 79:291df065e345 217 if (r <= 1)
mazgch 79:291df065e345 218 r = sscanf(cmd, "%s %d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d);
mazgch 79:291df065e345 219 if (r >= 2) {
mazgch 79:291df065e345 220 Reg *reg = !strcmp(s, "CREG:") ? &_net.csd :
mazgch 123:66cef6353b13 221 !strcmp(s, "CGREG:") ? &_net.psd :
mazgch 123:66cef6353b13 222 !strcmp(s, "CEREG:") ? &_net.eps : NULL;
mazgch 79:291df065e345 223 if (reg) {
mazgch 79:291df065e345 224 // network status
mazgch 79:291df065e345 225 if (a == 0) *reg = REG_NONE; // 0: not registered, home network
mazgch 79:291df065e345 226 else if (a == 1) *reg = REG_HOME; // 1: registered, home network
mazgch 79:291df065e345 227 else if (a == 2) *reg = REG_NONE; // 2: not registered, but MT is currently searching a new operator to register to
mazgch 79:291df065e345 228 else if (a == 3) *reg = REG_DENIED; // 3: registration denied
mazgch 79:291df065e345 229 else if (a == 4) *reg = REG_UNKNOWN; // 4: unknown
mazgch 79:291df065e345 230 else if (a == 5) *reg = REG_ROAMING; // 5: registered, roaming
mazgch 123:66cef6353b13 231 else if (a == 6) *reg = REG_HOME; // 6: registered, sms only, home
mazgch 79:291df065e345 232 if ((r >= 3) && (b != 0xFFFF)) _net.lac = b; // location area code
mazgch 79:291df065e345 233 if ((r >= 4) && (c != 0xFFFFFFFF)) _net.ci = c; // cell ID
mazgch 79:291df065e345 234 // access technology
mazgch 79:291df065e345 235 if (r >= 5) {
mazgch 79:291df065e345 236 if (d == 0) _net.act = ACT_GSM; // 0: GSM
mazgch 79:291df065e345 237 else if (d == 1) _net.act = ACT_GSM; // 1: GSM COMPACT
mazgch 79:291df065e345 238 else if (d == 2) _net.act = ACT_UTRAN; // 2: UTRAN
mazgch 79:291df065e345 239 else if (d == 3) _net.act = ACT_EDGE; // 3: GSM with EDGE availability
mazgch 79:291df065e345 240 else if (d == 4) _net.act = ACT_UTRAN; // 4: UTRAN with HSDPA availability
mazgch 79:291df065e345 241 else if (d == 5) _net.act = ACT_UTRAN; // 5: UTRAN with HSUPA availability
mazgch 79:291df065e345 242 else if (d == 6) _net.act = ACT_UTRAN; // 6: UTRAN with HSDPA and HSUPA availability
mazgch 123:66cef6353b13 243 else if (d == 7) _net.act = ACT_LTE; // 7: LTE
mazgch 79:291df065e345 244 }
mazgch 79:291df065e345 245 }
mazgch 54:7ba8e4c218e2 246 }
mazgch 21:c4d64830bf02 247 }
mazgch 21:c4d64830bf02 248 }
mazgch 21:c4d64830bf02 249 }
mazgch 21:c4d64830bf02 250 if (cb) {
mazgch 21:c4d64830bf02 251 int len = LENGTH(ret);
mazgch 21:c4d64830bf02 252 int ret = cb(type, buf, len, param);
mazgch 21:c4d64830bf02 253 if (WAIT != ret)
mazgch 21:c4d64830bf02 254 return ret;
mazgch 21:c4d64830bf02 255 }
mazgch 95:8282dbbe1492 256 if (type == TYPE_OK)
mazgch 95:8282dbbe1492 257 return RESP_OK;
mazgch 95:8282dbbe1492 258 if (type == TYPE_ERROR)
mazgch 95:8282dbbe1492 259 return RESP_ERROR;
mazgch 95:8282dbbe1492 260 if (type == TYPE_PROMPT)
mazgch 95:8282dbbe1492 261 return RESP_PROMPT;
mazgch 21:c4d64830bf02 262 }
mazgch 21:c4d64830bf02 263 // relax a bit
mazgch 95:8282dbbe1492 264 wait_ms(10);
mazgch 21:c4d64830bf02 265 }
mazgch 75:ce6e12067d0c 266 while (!TIMEOUT(timer, timeout_ms));
mazgch 21:c4d64830bf02 267 return WAIT;
mazgch 21:c4d64830bf02 268 }
mazgch 21:c4d64830bf02 269
mazgch 31:a0bed6c1e05d 270 int MDMParser::_cbString(int type, const char* buf, int len, char* str)
mazgch 21:c4d64830bf02 271 {
mazgch 37:cc3433329d66 272 if (str && (type == TYPE_UNKNOWN)) {
mazgch 31:a0bed6c1e05d 273 if (sscanf(buf, "\r\n%s\r\n", str) == 1)
mazgch 31:a0bed6c1e05d 274 /*nothing*/;
mazgch 21:c4d64830bf02 275 }
mazgch 21:c4d64830bf02 276 return WAIT;
mazgch 21:c4d64830bf02 277 }
mazgch 21:c4d64830bf02 278
mazgch 31:a0bed6c1e05d 279 int MDMParser::_cbInt(int type, const char* buf, int len, int* val)
mazgch 31:a0bed6c1e05d 280 {
mazgch 37:cc3433329d66 281 if (val && (type == TYPE_UNKNOWN)) {
mazgch 31:a0bed6c1e05d 282 if (sscanf(buf, "\r\n%d\r\n", val) == 1)
mazgch 31:a0bed6c1e05d 283 /*nothing*/;
mazgch 31:a0bed6c1e05d 284 }
mazgch 31:a0bed6c1e05d 285 return WAIT;
mazgch 31:a0bed6c1e05d 286 }
mazgch 31:a0bed6c1e05d 287
mazgch 31:a0bed6c1e05d 288 // ----------------------------------------------------------------
mazgch 31:a0bed6c1e05d 289
mazgch 57:869bd35f44cc 290 bool MDMParser::connect(
mazgch 57:869bd35f44cc 291 const char* simpin,
mazgch 80:34985b4d821e 292 const char* apn, const char* username,
mazgch 80:34985b4d821e 293 const char* password, Auth auth,
mazgch 74:208e3e32d263 294 PinName pn)
mazgch 57:869bd35f44cc 295 {
mazgch 75:ce6e12067d0c 296 bool ok = init(simpin, NULL, pn);
mazgch 74:208e3e32d263 297 #ifdef MDM_DEBUG
mazgch 75:ce6e12067d0c 298 if (_debugLevel >= 1) dumpDevStatus(&_dev);
mazgch 74:208e3e32d263 299 #endif
mazgch 75:ce6e12067d0c 300 if (!ok)
mazgch 57:869bd35f44cc 301 return false;
mazgch 75:ce6e12067d0c 302 ok = registerNet();
mazgch 74:208e3e32d263 303 #ifdef MDM_DEBUG
mazgch 75:ce6e12067d0c 304 if (_debugLevel >= 1) dumpNetStatus(&_net);
mazgch 74:208e3e32d263 305 #endif
mazgch 75:ce6e12067d0c 306 if (!ok)
mazgch 57:869bd35f44cc 307 return false;
mazgch 80:34985b4d821e 308 IP ip = join(apn,username,password,auth);
mazgch 74:208e3e32d263 309 #ifdef MDM_DEBUG
mazgch 74:208e3e32d263 310 if (_debugLevel >= 1) dumpIp(ip);
mazgch 74:208e3e32d263 311 #endif
mazgch 57:869bd35f44cc 312 if (ip == NOIP)
mazgch 57:869bd35f44cc 313 return false;
mazgch 57:869bd35f44cc 314 return true;
mazgch 57:869bd35f44cc 315 }
mazgch 57:869bd35f44cc 316
mazgch 74:208e3e32d263 317 bool MDMParser::init(const char* simpin, DevStatus* status, PinName pn)
mazgch 21:c4d64830bf02 318 {
mazgch 74:208e3e32d263 319 int i = 10;
mazgch 95:8282dbbe1492 320 LOCK();
mazgch 76:f7c3dd568dae 321 memset(&_dev, 0, sizeof(_dev));
mazgch 74:208e3e32d263 322 if (pn != NC) {
mazgch 74:208e3e32d263 323 INFO("Modem::wakeup\r\n");
mazgch 74:208e3e32d263 324 DigitalOut pin(pn, 1);
mazgch 74:208e3e32d263 325 while (i--) {
mazgch 79:291df065e345 326 // SARA-U2/LISA-U2 50..80us
mazgch 95:8282dbbe1492 327 pin = 0; ::wait_us(50);
mazgch 95:8282dbbe1492 328 pin = 1; ::wait_ms(10);
mazgch 79:291df065e345 329
mazgch 98:c786461edd40 330 // SARA-G35 >5ms, LISA-C2 > 150ms, LEON-G2 >5ms
mazgch 95:8282dbbe1492 331 pin = 0; ::wait_ms(150);
mazgch 95:8282dbbe1492 332 pin = 1; ::wait_ms(100);
mazgch 79:291df065e345 333
mazgch 79:291df065e345 334 // purge any messages
mazgch 101:edfeb8af206e 335 purge();
mazgch 95:8282dbbe1492 336
mazgch 101:edfeb8af206e 337 // check interface
mazgch 74:208e3e32d263 338 sendFormated("AT\r\n");
mazgch 101:edfeb8af206e 339 int r = waitFinalResp(NULL,NULL,1000);
mazgch 95:8282dbbe1492 340 if(RESP_OK == r) break;
mazgch 74:208e3e32d263 341 }
mazgch 75:ce6e12067d0c 342 if (i < 0) {
mazgch 95:8282dbbe1492 343 ERROR("No Reply from Modem\r\n");
mazgch 95:8282dbbe1492 344 goto failure;
mazgch 75:ce6e12067d0c 345 }
mazgch 21:c4d64830bf02 346 }
mazgch 76:f7c3dd568dae 347 _init = true;
mazgch 75:ce6e12067d0c 348
mazgch 74:208e3e32d263 349 INFO("Modem::init\r\n");
mazgch 21:c4d64830bf02 350 // echo off
mazgch 21:c4d64830bf02 351 sendFormated("AT E0\r\n");
mazgch 52:8071747a7cb3 352 if(RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 353 goto failure;
mazgch 21:c4d64830bf02 354 // enable verbose error messages
mazgch 21:c4d64830bf02 355 sendFormated("AT+CMEE=2\r\n");
mazgch 52:8071747a7cb3 356 if(RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 357 goto failure;
mazgch 21:c4d64830bf02 358 // set baud rate
mazgch 21:c4d64830bf02 359 sendFormated("AT+IPR=115200\r\n");
mazgch 52:8071747a7cb3 360 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 361 goto failure;
mazgch 112:89b5b21db71e 362 // wait some time until baudrate is applied
mazgch 112:89b5b21db71e 363 wait_ms(200); // SARA-G > 40ms
mazgch 21:c4d64830bf02 364 // identify the module
mazgch 21:c4d64830bf02 365 sendFormated("ATI\r\n");
mazgch 52:8071747a7cb3 366 if (RESP_OK != waitFinalResp(_cbATI, &_dev.dev))
mazgch 95:8282dbbe1492 367 goto failure;
mazgch 32:8f12ac182bbb 368 if (_dev.dev == DEV_UNKNOWN)
mazgch 95:8282dbbe1492 369 goto failure;
mazgch 32:8f12ac182bbb 370 // device specific init
mazgch 125:25a292afbac6 371 if (_dev.dev == DEV_LISA_C2) {
mazgch 32:8f12ac182bbb 372 // get the manufacturer
mazgch 32:8f12ac182bbb 373 sendFormated("AT+GMI\r\n");
mazgch 52:8071747a7cb3 374 if (RESP_OK != waitFinalResp(_cbString, _dev.manu))
mazgch 95:8282dbbe1492 375 goto failure;
mazgch 32:8f12ac182bbb 376 // get the model identification
mazgch 32:8f12ac182bbb 377 sendFormated("AT+GMM\r\n");
mazgch 52:8071747a7cb3 378 if (RESP_OK != waitFinalResp(_cbString, _dev.model))
mazgch 95:8282dbbe1492 379 goto failure;
mazgch 32:8f12ac182bbb 380 // get the sw version
mazgch 32:8f12ac182bbb 381 sendFormated("AT+GMR\r\n");
mazgch 52:8071747a7cb3 382 if (RESP_OK != waitFinalResp(_cbString, _dev.ver))
mazgch 95:8282dbbe1492 383 goto failure;
mazgch 95:8282dbbe1492 384 // get the pseudo ESN or MEID
mazgch 21:c4d64830bf02 385 sendFormated("AT+GSN\r\n");
mazgch 52:8071747a7cb3 386 if (RESP_OK != waitFinalResp(_cbString, _dev.meid))
mazgch 95:8282dbbe1492 387 goto failure;
mazgch 50:d76aece8038f 388 #if 0
mazgch 50:d76aece8038f 389 // enable power saving
mazgch 50:d76aece8038f 390 if (_dev.lpm != LPM_DISABLED) {
mazgch 50:d76aece8038f 391 // enable power saving (requires flow control, cts at least)
mazgch 50:d76aece8038f 392 sendFormated("AT+UPSV=1,1280\r\n");
mazgch 52:8071747a7cb3 393 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 394 goto failure;
mazgch 50:d76aece8038f 395 _dev.lpm = LPM_ACTIVE;
mazgch 50:d76aece8038f 396 }
mazgch 50:d76aece8038f 397 #endif
mazgch 26:07be5faf8925 398 } else {
mazgch 125:25a292afbac6 399 if ((_dev.dev == DEV_LISA_U2) || (_dev.dev == DEV_LEON_G2) ||
mazgch 125:25a292afbac6 400 (_dev.dev == DEV_TOBY_L2)) {
mazgch 35:9275215a3a5b 401 // enable the network identification feature
mazgch 21:c4d64830bf02 402 sendFormated("AT+UGPIOC=20,2\r\n");
mazgch 52:8071747a7cb3 403 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 404 goto failure;
mazgch 125:25a292afbac6 405 } else if ((_dev.dev == DEV_SARA_U2) || (_dev.dev == DEV_SARA_G35)) {
mazgch 35:9275215a3a5b 406 // enable the network identification feature
mazgch 21:c4d64830bf02 407 sendFormated("AT+UGPIOC=16,2\r\n");
mazgch 52:8071747a7cb3 408 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 409 goto failure;
mazgch 21:c4d64830bf02 410 }
mazgch 21:c4d64830bf02 411 // check the sim card
mazgch 31:a0bed6c1e05d 412 for (int i = 0; (i < 5) && (_dev.sim != SIM_READY); i++) {
mazgch 21:c4d64830bf02 413 sendFormated("AT+CPIN?\r\n");
mazgch 31:a0bed6c1e05d 414 int ret = waitFinalResp(_cbCPIN, &_dev.sim);
mazgch 62:a02f026bdd7c 415 // having an error here is ok (sim may still be initializing)
mazgch 52:8071747a7cb3 416 if ((RESP_OK != ret) && (RESP_ERROR != ret))
mazgch 95:8282dbbe1492 417 goto failure;
mazgch 31:a0bed6c1e05d 418 // Enter PIN if needed
mazgch 77:55788e619858 419 if (_dev.sim == SIM_PIN) {
mazgch 57:869bd35f44cc 420 if (!simpin) {
mazgch 75:ce6e12067d0c 421 ERROR("SIM PIN not available\r\n");
mazgch 95:8282dbbe1492 422 goto failure;
mazgch 31:a0bed6c1e05d 423 }
mazgch 130:3189949981ec 424 sendFormated("AT+CPIN=\"%s\"\r\n", simpin);
mazgch 52:8071747a7cb3 425 if (RESP_OK != waitFinalResp(_cbCPIN, &_dev.sim))
mazgch 95:8282dbbe1492 426 goto failure;
mazgch 62:a02f026bdd7c 427 } else if (_dev.sim != SIM_READY) {
mazgch 95:8282dbbe1492 428 wait_ms(1000);
mazgch 62:a02f026bdd7c 429 }
mazgch 21:c4d64830bf02 430 }
mazgch 77:55788e619858 431 if (_dev.sim != SIM_READY) {
mazgch 77:55788e619858 432 if (_dev.sim == SIM_MISSING)
mazgch 77:55788e619858 433 ERROR("SIM not inserted\r\n");
mazgch 95:8282dbbe1492 434 goto failure;
mazgch 77:55788e619858 435 }
mazgch 32:8f12ac182bbb 436 // get the manufacturer
mazgch 32:8f12ac182bbb 437 sendFormated("AT+CGMI\r\n");
mazgch 52:8071747a7cb3 438 if (RESP_OK != waitFinalResp(_cbString, _dev.manu))
mazgch 95:8282dbbe1492 439 goto failure;
mazgch 32:8f12ac182bbb 440 // get the model identification
mazgch 32:8f12ac182bbb 441 sendFormated("AT+CGMM\r\n");
mazgch 52:8071747a7cb3 442 if (RESP_OK != waitFinalResp(_cbString, _dev.model))
mazgch 95:8282dbbe1492 443 goto failure;
mazgch 126:bfbb9e19f6e0 444 // get the version
mazgch 126:bfbb9e19f6e0 445 sendFormated("ATI9\r\n");
mazgch 52:8071747a7cb3 446 if (RESP_OK != waitFinalResp(_cbString, _dev.ver))
mazgch 126:bfbb9e19f6e0 447 goto failure;
mazgch 21:c4d64830bf02 448 // Returns the ICCID (Integrated Circuit Card ID) of the SIM-card.
mazgch 21:c4d64830bf02 449 // ICCID is a serial number identifying the SIM.
mazgch 21:c4d64830bf02 450 sendFormated("AT+CCID\r\n");
mazgch 52:8071747a7cb3 451 if (RESP_OK != waitFinalResp(_cbCCID, _dev.ccid))
mazgch 95:8282dbbe1492 452 goto failure;
mazgch 21:c4d64830bf02 453 // Returns the product serial number, IMEI (International Mobile Equipment Identity)
mazgch 21:c4d64830bf02 454 sendFormated("AT+CGSN\r\n");
mazgch 52:8071747a7cb3 455 if (RESP_OK != waitFinalResp(_cbString, _dev.imei))
mazgch 95:8282dbbe1492 456 goto failure;
mazgch 50:d76aece8038f 457 // enable power saving
mazgch 50:d76aece8038f 458 if (_dev.lpm != LPM_DISABLED) {
mazgch 50:d76aece8038f 459 // enable power saving (requires flow control, cts at least)
mazgch 50:d76aece8038f 460 sendFormated("AT+UPSV=1\r\n");
mazgch 52:8071747a7cb3 461 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 462 goto failure;
mazgch 50:d76aece8038f 463 _dev.lpm = LPM_ACTIVE;
mazgch 50:d76aece8038f 464 }
mazgch 79:291df065e345 465 // enable the psd registration unsolicited result code
mazgch 79:291df065e345 466 sendFormated("AT+CGREG=2\r\n");
mazgch 79:291df065e345 467 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 468 goto failure;
mazgch 21:c4d64830bf02 469 }
mazgch 79:291df065e345 470 // enable the network registration unsolicited result code
mazgch 125:25a292afbac6 471 sendFormated("AT+CREG=%d\r\n", (_dev.dev == DEV_LISA_C2) ? 1 : 2);
mazgch 79:291df065e345 472 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 473 goto failure;
mazgch 31:a0bed6c1e05d 474 // Setup SMS in text mode
mazgch 31:a0bed6c1e05d 475 sendFormated("AT+CMGF=1\r\n");
mazgch 52:8071747a7cb3 476 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 477 goto failure;
mazgch 31:a0bed6c1e05d 478 // setup new message indication
mazgch 75:ce6e12067d0c 479 sendFormated("AT+CNMI=2,1\r\n");
mazgch 52:8071747a7cb3 480 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 481 goto failure;
mazgch 21:c4d64830bf02 482 // Request IMSI (International Mobile Subscriber Identification)
mazgch 21:c4d64830bf02 483 sendFormated("AT+CIMI\r\n");
mazgch 52:8071747a7cb3 484 if (RESP_OK != waitFinalResp(_cbString, _dev.imsi))
mazgch 95:8282dbbe1492 485 goto failure;
mazgch 28:4d9509e3b1cf 486 if (status)
mazgch 31:a0bed6c1e05d 487 memcpy(status, &_dev, sizeof(DevStatus));
mazgch 95:8282dbbe1492 488 UNLOCK();
mazgch 31:a0bed6c1e05d 489 return true;
mazgch 95:8282dbbe1492 490 failure:
mazgch 95:8282dbbe1492 491 unlock();
mazgch 95:8282dbbe1492 492 return false;
mazgch 31:a0bed6c1e05d 493 }
mazgch 31:a0bed6c1e05d 494
mazgch 74:208e3e32d263 495 bool MDMParser::powerOff(void)
mazgch 74:208e3e32d263 496 {
mazgch 95:8282dbbe1492 497 bool ok = false;
mazgch 76:f7c3dd568dae 498 if (_init) {
mazgch 95:8282dbbe1492 499 LOCK();
mazgch 76:f7c3dd568dae 500 INFO("Modem::powerOff\r\n");
mazgch 76:f7c3dd568dae 501 sendFormated("AT+CPWROFF\r\n");
mazgch 95:8282dbbe1492 502 if (RESP_OK == waitFinalResp(NULL,NULL,120*1000)) {
mazgch 95:8282dbbe1492 503 _init = false;
mazgch 95:8282dbbe1492 504 ok = true;
mazgch 95:8282dbbe1492 505 }
mazgch 95:8282dbbe1492 506 UNLOCK();
mazgch 76:f7c3dd568dae 507 }
mazgch 95:8282dbbe1492 508 return ok;
mazgch 74:208e3e32d263 509 }
mazgch 74:208e3e32d263 510
mazgch 32:8f12ac182bbb 511 int MDMParser::_cbATI(int type, const char* buf, int len, Dev* dev)
mazgch 31:a0bed6c1e05d 512 {
mazgch 37:cc3433329d66 513 if ((type == TYPE_UNKNOWN) && dev) {
mazgch 125:25a292afbac6 514 if (strstr(buf, "SARA-G35")) *dev = DEV_SARA_G35;
mazgch 125:25a292afbac6 515 else if (strstr(buf, "LISA-U2")) *dev = DEV_LISA_U2;
mazgch 125:25a292afbac6 516 else if (strstr(buf, "LISA-C2")) *dev = DEV_LISA_C2;
mazgch 125:25a292afbac6 517 else if (strstr(buf, "SARA-U2")) *dev = DEV_SARA_U2;
mazgch 125:25a292afbac6 518 else if (strstr(buf, "LEON-G2")) *dev = DEV_LEON_G2;
mazgch 125:25a292afbac6 519 else if (strstr(buf, "TOBY-L2")) *dev = DEV_TOBY_L2;
mazgch 125:25a292afbac6 520 else if (strstr(buf, "MPCI-L2")) *dev = DEV_MPCI_L2;
mazgch 28:4d9509e3b1cf 521 }
mazgch 31:a0bed6c1e05d 522 return WAIT;
mazgch 31:a0bed6c1e05d 523 }
mazgch 31:a0bed6c1e05d 524
mazgch 31:a0bed6c1e05d 525 int MDMParser::_cbCPIN(int type, const char* buf, int len, Sim* sim)
mazgch 31:a0bed6c1e05d 526 {
mazgch 75:ce6e12067d0c 527 if (sim) {
mazgch 75:ce6e12067d0c 528 if (type == TYPE_PLUS){
mazgch 75:ce6e12067d0c 529 char s[16];
mazgch 75:ce6e12067d0c 530 if (sscanf(buf, "\r\n+CPIN: %[^\r]\r\n", s) >= 1)
mazgch 75:ce6e12067d0c 531 *sim = (0 == strcmp("READY", s)) ? SIM_READY : SIM_PIN;
mazgch 75:ce6e12067d0c 532 } else if (type == TYPE_ERROR) {
mazgch 75:ce6e12067d0c 533 if (strstr(buf, "+CME ERROR: SIM not inserted"))
mazgch 75:ce6e12067d0c 534 *sim = SIM_MISSING;
mazgch 31:a0bed6c1e05d 535 }
mazgch 31:a0bed6c1e05d 536 }
mazgch 31:a0bed6c1e05d 537 return WAIT;
mazgch 21:c4d64830bf02 538 }
mazgch 21:c4d64830bf02 539
mazgch 26:07be5faf8925 540 int MDMParser::_cbCCID(int type, const char* buf, int len, char* ccid)
mazgch 26:07be5faf8925 541 {
mazgch 26:07be5faf8925 542 if ((type == TYPE_PLUS) && ccid){
mazgch 26:07be5faf8925 543 if (sscanf(buf, "\r\n+CCID: %[^\r]\r\n", ccid) == 1)
mazgch 31:a0bed6c1e05d 544 /*TRACE("Got CCID: %s\r\n", ccid)*/;
mazgch 26:07be5faf8925 545 }
mazgch 26:07be5faf8925 546 return WAIT;
mazgch 26:07be5faf8925 547 }
mazgch 26:07be5faf8925 548
mazgch 75:ce6e12067d0c 549 bool MDMParser::registerNet(NetStatus* status /*= NULL*/, int timeout_ms /*= 180000*/)
mazgch 75:ce6e12067d0c 550 {
mazgch 75:ce6e12067d0c 551 Timer timer;
mazgch 75:ce6e12067d0c 552 timer.start();
mazgch 75:ce6e12067d0c 553 INFO("Modem::register\r\n");
mazgch 75:ce6e12067d0c 554 while (!checkNetStatus(status) && !TIMEOUT(timer, timeout_ms))
mazgch 95:8282dbbe1492 555 wait_ms(1000);
mazgch 79:291df065e345 556 if (_net.csd == REG_DENIED) ERROR("CSD Registration Denied\r\n");
mazgch 79:291df065e345 557 if (_net.psd == REG_DENIED) ERROR("PSD Registration Denied\r\n");
mazgch 123:66cef6353b13 558 if (_net.eps == REG_DENIED) ERROR("EPS Registration Denied\r\n");
mazgch 123:66cef6353b13 559 return REG_OK(_net.csd) || REG_OK(_net.psd) || REG_OK(_net.eps);
mazgch 75:ce6e12067d0c 560 }
mazgch 75:ce6e12067d0c 561
mazgch 28:4d9509e3b1cf 562 bool MDMParser::checkNetStatus(NetStatus* status /*= NULL*/)
mazgch 21:c4d64830bf02 563 {
mazgch 95:8282dbbe1492 564 bool ok = false;
mazgch 95:8282dbbe1492 565 LOCK();
mazgch 75:ce6e12067d0c 566 memset(&_net, 0, sizeof(_net));
mazgch 75:ce6e12067d0c 567 _net.lac = 0xFFFF;
mazgch 75:ce6e12067d0c 568 _net.ci = 0xFFFFFFFF;
mazgch 21:c4d64830bf02 569 // check registration
mazgch 21:c4d64830bf02 570 sendFormated("AT+CREG?\r\n");
mazgch 88:135fb4bb7aac 571 waitFinalResp(); // don't fail as service could be not subscribed
mazgch 125:25a292afbac6 572 if (_dev.dev != DEV_LISA_C2) {
mazgch 79:291df065e345 573 // check PSD registration
mazgch 79:291df065e345 574 sendFormated("AT+CGREG?\r\n");
mazgch 88:135fb4bb7aac 575 waitFinalResp(); // don't fail as service could be not subscribed
mazgch 125:25a292afbac6 576 if ((_dev.dev == DEV_TOBY_L2) || (_dev.dev == DEV_MPCI_L2)) {
mazgch 125:25a292afbac6 577 // check EPS network registration
mazgch 125:25a292afbac6 578 sendFormated("AT+CEREG?\r\n");
mazgch 125:25a292afbac6 579 waitFinalResp(); // don't fail as service could be not subscribed
mazgch 125:25a292afbac6 580 }
mazgch 79:291df065e345 581 }
mazgch 123:66cef6353b13 582 if (REG_OK(_net.csd) || REG_OK(_net.psd) || REG_OK(_net.eps))
mazgch 75:ce6e12067d0c 583 {
mazgch 75:ce6e12067d0c 584 // check modem specific status messages
mazgch 125:25a292afbac6 585 if (_dev.dev == DEV_LISA_C2) {
mazgch 75:ce6e12067d0c 586 sendFormated("AT+CSS?\r\n");
mazgch 75:ce6e12067d0c 587 if (RESP_OK != waitFinalResp())
mazgch 95:8282dbbe1492 588 goto failure;
mazgch 81:3966a5c17037 589 while (1) {
mazgch 81:3966a5c17037 590 // get the Telephone number
mazgch 81:3966a5c17037 591 sendFormated("AT$MDN?\r\n");
mazgch 81:3966a5c17037 592 if (RESP_OK != waitFinalResp(_cbString, _net.num))
mazgch 95:8282dbbe1492 593 goto failure;
mazgch 81:3966a5c17037 594 // check if we have a Mobile Directory Number
mazgch 81:3966a5c17037 595 if (*_net.num && (memcmp(_net.num, "000000", 6) != 0))
mazgch 81:3966a5c17037 596 break;
mazgch 81:3966a5c17037 597
mazgch 81:3966a5c17037 598 INFO("Device not yet activated\r\n");
mazgch 81:3966a5c17037 599 INFO("Make sure you have a valid contract with the network operator for this device.\r\n");
mazgch 81:3966a5c17037 600 // Check if the the version contains a V for Verizon
mazgch 81:3966a5c17037 601 // Verizon: E0.V.xx.00.xxR,
mazgch 81:3966a5c17037 602 // Sprint E0.S.xx.00.xxR
mazgch 81:3966a5c17037 603 if (_dev.ver[3] == 'V') {
mazgch 81:3966a5c17037 604 int i;
mazgch 81:3966a5c17037 605 INFO("Start device over-the-air activation (this can take a few minutes)\r\n");
mazgch 81:3966a5c17037 606 sendFormated("AT+CDV=*22899\r\n");
mazgch 81:3966a5c17037 607 i = 1;
mazgch 82:055dcfcf9dcc 608 if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) {
mazgch 81:3966a5c17037 609 ERROR("Device over-the-air activation failed\r\n");
mazgch 95:8282dbbe1492 610 goto failure;
mazgch 81:3966a5c17037 611 }
mazgch 81:3966a5c17037 612 INFO("Device over-the-air activation successful\r\n");
mazgch 81:3966a5c17037 613
mazgch 81:3966a5c17037 614 INFO("Start PRL over-the-air update (this can take a few minutes)\r\n");
mazgch 81:3966a5c17037 615 sendFormated("AT+CDV=*22891\r\n");
mazgch 81:3966a5c17037 616 i = 1;
mazgch 82:055dcfcf9dcc 617 if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) {
mazgch 81:3966a5c17037 618 ERROR("PRL over-the-air update failed\r\n");
mazgch 95:8282dbbe1492 619 goto failure;
mazgch 81:3966a5c17037 620 }
mazgch 81:3966a5c17037 621 INFO("PRL over-the-air update successful\r\n");
mazgch 81:3966a5c17037 622
mazgch 81:3966a5c17037 623 } else {
mazgch 81:3966a5c17037 624 // Sprint or Aeris
mazgch 81:3966a5c17037 625 INFO("Wait for OMA-DM over-the-air activation (this can take a few minutes)\r\n");
mazgch 95:8282dbbe1492 626 wait_ms(120*1000);
mazgch 81:3966a5c17037 627 }
mazgch 81:3966a5c17037 628 }
mazgch 75:ce6e12067d0c 629 // get the the Network access identifier string
mazgch 75:ce6e12067d0c 630 char nai[64];
mazgch 75:ce6e12067d0c 631 sendFormated("AT$QCMIPNAI?\r\n");
mazgch 75:ce6e12067d0c 632 if (RESP_OK != waitFinalResp(_cbString, nai))
mazgch 95:8282dbbe1492 633 goto failure;
mazgch 75:ce6e12067d0c 634 } else {
mazgch 75:ce6e12067d0c 635 sendFormated("AT+COPS?\r\n");
mazgch 75:ce6e12067d0c 636 if (RESP_OK != waitFinalResp(_cbCOPS, &_net))
mazgch 95:8282dbbe1492 637 goto failure;
mazgch 95:8282dbbe1492 638 // get the MSISDNs related to this subscriber
mazgch 75:ce6e12067d0c 639 sendFormated("AT+CNUM\r\n");
mazgch 75:ce6e12067d0c 640 if (RESP_OK != waitFinalResp(_cbCNUM, _net.num))
mazgch 95:8282dbbe1492 641 goto failure;
mazgch 75:ce6e12067d0c 642 }
mazgch 95:8282dbbe1492 643 // get the signal strength indication
mazgch 75:ce6e12067d0c 644 sendFormated("AT+CSQ\r\n");
mazgch 75:ce6e12067d0c 645 if (RESP_OK != waitFinalResp(_cbCSQ, &_net))
mazgch 95:8282dbbe1492 646 goto failure;
mazgch 75:ce6e12067d0c 647 }
mazgch 28:4d9509e3b1cf 648 if (status) {
mazgch 31:a0bed6c1e05d 649 memcpy(status, &_net, sizeof(NetStatus));
mazgch 25:4045d02e44f1 650 }
mazgch 123:66cef6353b13 651 ok = REG_DONE(_net.csd) &&
mazgch 123:66cef6353b13 652 (REG_DONE(_net.psd) || REG_DONE(_net.eps));
mazgch 95:8282dbbe1492 653 UNLOCK();
mazgch 95:8282dbbe1492 654 return ok;
mazgch 95:8282dbbe1492 655 failure:
mazgch 95:8282dbbe1492 656 unlock();
mazgch 95:8282dbbe1492 657 return false;
mazgch 31:a0bed6c1e05d 658 }
mazgch 31:a0bed6c1e05d 659
mazgch 31:a0bed6c1e05d 660 int MDMParser::_cbCOPS(int type, const char* buf, int len, NetStatus* status)
mazgch 31:a0bed6c1e05d 661 {
mazgch 31:a0bed6c1e05d 662 if ((type == TYPE_PLUS) && status){
mazgch 31:a0bed6c1e05d 663 int act = 99;
mazgch 31:a0bed6c1e05d 664 // +COPS: <mode>[,<format>,<oper>[,<AcT>]]
mazgch 31:a0bed6c1e05d 665 if (sscanf(buf, "\r\n+COPS: %*d,%*d,\"%[^\"]\",%d",status->opr,&act) >= 1) {
mazgch 31:a0bed6c1e05d 666 if (act == 0) status->act = ACT_GSM; // 0: GSM,
mazgch 31:a0bed6c1e05d 667 else if (act == 2) status->act = ACT_UTRAN; // 2: UTRAN
mazgch 123:66cef6353b13 668 else if (act == 7) status->act = ACT_LTE; // 2: UTRAN
mazgch 31:a0bed6c1e05d 669 }
mazgch 31:a0bed6c1e05d 670 }
mazgch 31:a0bed6c1e05d 671 return WAIT;
mazgch 31:a0bed6c1e05d 672 }
mazgch 31:a0bed6c1e05d 673
mazgch 31:a0bed6c1e05d 674 int MDMParser::_cbCNUM(int type, const char* buf, int len, char* num)
mazgch 31:a0bed6c1e05d 675 {
mazgch 31:a0bed6c1e05d 676 if ((type == TYPE_PLUS) && num){
mazgch 31:a0bed6c1e05d 677 int a;
mazgch 31:a0bed6c1e05d 678 if ((sscanf(buf, "\r\n+CNUM: \"My Number\",\"%31[^\"]\",%d", num, &a) == 2) &&
mazgch 31:a0bed6c1e05d 679 ((a == 129) || (a == 145))) {
mazgch 31:a0bed6c1e05d 680 }
mazgch 31:a0bed6c1e05d 681 }
mazgch 31:a0bed6c1e05d 682 return WAIT;
mazgch 31:a0bed6c1e05d 683 }
mazgch 31:a0bed6c1e05d 684
mazgch 54:7ba8e4c218e2 685 int MDMParser::_cbCSQ(int type, const char* buf, int len, NetStatus* status)
mazgch 31:a0bed6c1e05d 686 {
mazgch 54:7ba8e4c218e2 687 if ((type == TYPE_PLUS) && status){
mazgch 54:7ba8e4c218e2 688 int a,b;
mazgch 54:7ba8e4c218e2 689 char _ber[] = { 49, 43, 37, 25, 19, 13, 7, 0 }; // see 3GPP TS 45.008 [20] subclause 8.2.4
mazgch 31:a0bed6c1e05d 690 // +CSQ: <rssi>,<qual>
mazgch 54:7ba8e4c218e2 691 if (sscanf(buf, "\r\n+CSQ: %d,%d",&a,&b) == 2) {
mazgch 121:8da935c2c08c 692 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 693 if ((b != 99) && (b < sizeof(_ber))) status->ber = _ber[b]; //
mazgch 31:a0bed6c1e05d 694 }
mazgch 31:a0bed6c1e05d 695 }
mazgch 31:a0bed6c1e05d 696 return WAIT;
mazgch 31:a0bed6c1e05d 697 }
mazgch 21:c4d64830bf02 698
mazgch 124:65eb7d58f2da 699
mazgch 124:65eb7d58f2da 700 int MDMParser::_cbUACTIND(int type, const char* buf, int len, int* i)
mazgch 124:65eb7d58f2da 701 {
mazgch 124:65eb7d58f2da 702 if ((type == TYPE_PLUS) && i){
mazgch 124:65eb7d58f2da 703 int a;
mazgch 124:65eb7d58f2da 704 if (sscanf(buf, "\r\n+UACTIND: %d", &a) == 1) {
mazgch 124:65eb7d58f2da 705 *i = a;
mazgch 124:65eb7d58f2da 706 }
mazgch 124:65eb7d58f2da 707 }
mazgch 124:65eb7d58f2da 708 return WAIT;
mazgch 124:65eb7d58f2da 709 }
mazgch 124:65eb7d58f2da 710
mazgch 21:c4d64830bf02 711 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 712 // internet connection
mazgch 21:c4d64830bf02 713
mazgch 128:0415646a9934 714 bool MDMParser::_activateProfile(const char* apn, const char* username, const char* password, Auth auth)
mazgch 128:0415646a9934 715 {
mazgch 128:0415646a9934 716 // Set up the APN
mazgch 128:0415646a9934 717 if (*apn) {
mazgch 128:0415646a9934 718 sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn);
mazgch 128:0415646a9934 719 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 720 return false;
mazgch 128:0415646a9934 721 }
mazgch 128:0415646a9934 722 if (*username) {
mazgch 128:0415646a9934 723 sendFormated("AT+UPSD=" PROFILE ",2,\"%s\"\r\n", username);
mazgch 128:0415646a9934 724 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 725 return false;
mazgch 128:0415646a9934 726 }
mazgch 128:0415646a9934 727 if (*password) {
mazgch 128:0415646a9934 728 sendFormated("AT+UPSD=" PROFILE ",3,\"%s\"\r\n", password);
mazgch 128:0415646a9934 729 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 730 return false;
mazgch 128:0415646a9934 731 }
mazgch 128:0415646a9934 732 // Set up the dynamic IP address assignment.
mazgch 128:0415646a9934 733 sendFormated("AT+UPSD=" PROFILE ",7,\"0.0.0.0\"\r\n");
mazgch 128:0415646a9934 734 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 735 return false;
mazgch 128:0415646a9934 736 // try different Authentication Protocols
mazgch 128:0415646a9934 737 // 0 = none
mazgch 128:0415646a9934 738 // 1 = PAP (Password Authentication Protocol)
mazgch 128:0415646a9934 739 // 2 = CHAP (Challenge Handshake Authentication Protocol)
mazgch 128:0415646a9934 740 for (int i = AUTH_NONE; i <= AUTH_CHAP; i ++) {
mazgch 128:0415646a9934 741 if ((auth == AUTH_DETECT) || (auth == i)) {
mazgch 128:0415646a9934 742 // Set up the Authentication Protocol
mazgch 128:0415646a9934 743 sendFormated("AT+UPSD=" PROFILE ",6,%d\r\n",i);
mazgch 128:0415646a9934 744 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 745 return false;
mazgch 128:0415646a9934 746 // Activate the profile and make connection
mazgch 128:0415646a9934 747 sendFormated("AT+UPSDA=" PROFILE ",3\r\n");
mazgch 128:0415646a9934 748 if (RESP_OK == waitFinalResp(NULL,NULL,150*1000))
mazgch 128:0415646a9934 749 return true;
mazgch 128:0415646a9934 750 }
mazgch 128:0415646a9934 751 }
mazgch 128:0415646a9934 752 return false;
mazgch 128:0415646a9934 753 }
mazgch 128:0415646a9934 754
mazgch 131:965a7cbc1e58 755 bool MDMParser::_activateProfileReuseExternal(void)
mazgch 131:965a7cbc1e58 756 {
mazgch 131:965a7cbc1e58 757 int cid = -1;
mazgch 131:965a7cbc1e58 758 sendFormated("AT+CGDCONT?\r\n");
mazgch 131:965a7cbc1e58 759 if (RESP_OK != waitFinalResp(_cbCGDCONT, &cid))
mazgch 131:965a7cbc1e58 760 return false;
mazgch 131:965a7cbc1e58 761 if (cid == -1)
mazgch 131:965a7cbc1e58 762 return false;
mazgch 131:965a7cbc1e58 763 // we found a context that provides us a valid IP so lets reuse it for the internal IP stack
mazgch 131:965a7cbc1e58 764 sendFormated("AT+UPSD=" PROFILE ",100,%d\r\n", cid);
mazgch 131:965a7cbc1e58 765 if (RESP_OK != waitFinalResp())
mazgch 131:965a7cbc1e58 766 return false;
mazgch 131:965a7cbc1e58 767 // Activate the profile and make connection
mazgch 131:965a7cbc1e58 768 sendFormated("AT+UPSDA=" PROFILE ",3\r\n");
mazgch 131:965a7cbc1e58 769 return (RESP_OK == waitFinalResp(NULL,NULL,150*1000));
mazgch 131:965a7cbc1e58 770 }
mazgch 131:965a7cbc1e58 771
mazgch 128:0415646a9934 772 bool MDMParser::_activateProfileByCid(int cid, const char* apn, const char* username, const char* password, Auth auth)
mazgch 128:0415646a9934 773 {
mazgch 128:0415646a9934 774 sendFormated("AT+CGDCONT=%d,\"IP\",\"%s\"\r\n", cid, apn);
mazgch 128:0415646a9934 775 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 776 return false;
mazgch 128:0415646a9934 777 sendFormated("AT+UAUTHREQ=%d,%d,\"%s\",\"%s\"\r\n", cid, auth, username, password);
mazgch 128:0415646a9934 778 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 779 return false;
mazgch 128:0415646a9934 780 sendFormated("AT+UPSD=" PROFILE ",100,%d\r\n", cid);
mazgch 128:0415646a9934 781 if (RESP_OK != waitFinalResp())
mazgch 128:0415646a9934 782 return false;
mazgch 128:0415646a9934 783 // Activate the profile and make connection
mazgch 128:0415646a9934 784 sendFormated("AT+UPSDA=" PROFILE ",3\r\n");
mazgch 128:0415646a9934 785 return (RESP_OK == waitFinalResp(NULL,NULL,150*1000));
mazgch 128:0415646a9934 786 }
mazgch 128:0415646a9934 787
mazgch 131:965a7cbc1e58 788 int MDMParser::_cbCGDCONT(int type, const char* buf, int len, int* cid)
mazgch 131:965a7cbc1e58 789 {
mazgch 131:965a7cbc1e58 790 // accept with and without leading \r\n in +CGDCONT:
mazgch 131:965a7cbc1e58 791 if ((type == TYPE_PLUS) && (buf[0] == '\r') && (buf[1] == '\n') && (len >= 2))
mazgch 131:965a7cbc1e58 792 buf += 2, len -= 2, type = TYPE_UNKNOWN;
mazgch 131:965a7cbc1e58 793 if (type == TYPE_UNKNOWN) {
mazgch 131:965a7cbc1e58 794 int a,b,c,d,t;
mazgch 131:965a7cbc1e58 795 //+CGDCONT: <cid>,"IP","<apn name>","<ip adr>",0,0,0,0,0,0
mazgch 131:965a7cbc1e58 796 if (sscanf(buf, "+CGDCONT: %d,\"IP\",\"%*[^\"]\",\"" IPSTR "\",%*d,%*d,%*d,%*d,%*d,%*d", &t, &a,&b,&c,&d) == 5) {
mazgch 131:965a7cbc1e58 797 if (IPADR(a,b,c,d) != NOIP)
mazgch 131:965a7cbc1e58 798 *cid = t;
mazgch 131:965a7cbc1e58 799 }
mazgch 131:965a7cbc1e58 800 }
mazgch 131:965a7cbc1e58 801 return WAIT;
mazgch 131:965a7cbc1e58 802 }
mazgch 131:965a7cbc1e58 803
mazgch 79:291df065e345 804 MDMParser::IP MDMParser::join(const char* apn /*= NULL*/, const char* username /*= NULL*/,
mazgch 79:291df065e345 805 const char* password /*= NULL*/, Auth auth /*= AUTH_DETECT*/)
mazgch 21:c4d64830bf02 806 {
mazgch 95:8282dbbe1492 807 LOCK();
mazgch 78:caf0014375cb 808 INFO("Modem::join\r\n");
mazgch 32:8f12ac182bbb 809 _ip = NOIP;
mazgch 125:25a292afbac6 810 if (_dev.dev == DEV_LISA_C2) {
mazgch 76:f7c3dd568dae 811 // make a dumy dns lookup (which will fail, so ignore the result)
mazgch 76:f7c3dd568dae 812 sendFormated("AT+UDNSRN=0,\"u-blox.com\"\r\n");
mazgch 76:f7c3dd568dae 813 waitFinalResp();
mazgch 76:f7c3dd568dae 814 // This fake lookup will enable the IP connection and we
mazgch 76:f7c3dd568dae 815 // should have an IP after this, so we check it
mazgch 76:f7c3dd568dae 816
mazgch 21:c4d64830bf02 817 //Get local IP address
mazgch 21:c4d64830bf02 818 sendFormated("AT+CMIP?\r\n");
mazgch 52:8071747a7cb3 819 if (RESP_OK != waitFinalResp(_cbCMIP, &_ip))
mazgch 95:8282dbbe1492 820 goto failure;
mazgch 125:25a292afbac6 821
mazgch 21:c4d64830bf02 822 } else {
mazgch 21:c4d64830bf02 823 // check gprs attach status
mazgch 72:d1e943ad6558 824 sendFormated("AT+CGATT=1\r\n");
mazgch 74:208e3e32d263 825 if (RESP_OK != waitFinalResp(NULL,NULL,3*60*1000))
mazgch 95:8282dbbe1492 826 goto failure;
mazgch 31:a0bed6c1e05d 827 // Check the profile
mazgch 31:a0bed6c1e05d 828 int a = 0;
mazgch 79:291df065e345 829 bool force = true;
mazgch 31:a0bed6c1e05d 830 sendFormated("AT+UPSND=" PROFILE ",8\r\n");
mazgch 52:8071747a7cb3 831 if (RESP_OK != waitFinalResp(_cbUPSND, &a))
mazgch 95:8282dbbe1492 832 goto failure;
mazgch 79:291df065e345 833 if (a == 1 && force) {
mazgch 31:a0bed6c1e05d 834 // disconnect the profile already if it is connected
mazgch 31:a0bed6c1e05d 835 sendFormated("AT+UPSDA=" PROFILE ",4\r\n");
mazgch 58:e38a2e942fbb 836 if (RESP_OK != waitFinalResp(NULL,NULL,40*1000))
mazgch 95:8282dbbe1492 837 goto failure;
mazgch 79:291df065e345 838 a = 0;
mazgch 31:a0bed6c1e05d 839 }
mazgch 79:291df065e345 840 if (a == 0) {
mazgch 84:a05edb010176 841 bool ok = false;
mazgch 84:a05edb010176 842 // try to lookup the apn settings from our local database by mccmnc
mazgch 84:a05edb010176 843 const char* config = NULL;
mazgch 88:135fb4bb7aac 844 if (!apn && !username && !password)
mazgch 88:135fb4bb7aac 845 config = apnconfig(_dev.imsi);
mazgch 84:a05edb010176 846 do {
mazgch 84:a05edb010176 847 if (config) {
mazgch 85:dd8f4f0d0ca9 848 apn = _APN_GET(config);
mazgch 85:dd8f4f0d0ca9 849 username = _APN_GET(config);
mazgch 85:dd8f4f0d0ca9 850 password = _APN_GET(config);
mazgch 79:291df065e345 851 }
mazgch 125:25a292afbac6 852 // convert pointer to empty strings
mazgch 125:25a292afbac6 853 apn = apn ? apn : "";
mazgch 125:25a292afbac6 854 username = username ? username : "";
mazgch 125:25a292afbac6 855 password = password ? password : "";
mazgch 125:25a292afbac6 856 auth = (*username && *password) ? auth : AUTH_NONE;
mazgch 125:25a292afbac6 857 TRACE("Testing APN Settings(\"%s\",\"%s\",\"%s\",%d)\r\n", apn, username, password, auth);
mazgch 128:0415646a9934 858 if ((_dev.dev != DEV_TOBY_L2) && (_dev.dev != DEV_MPCI_L2))
mazgch 128:0415646a9934 859 ok = _activateProfile(apn, username, password, auth);
mazgch 131:965a7cbc1e58 860 else {
mazgch 131:965a7cbc1e58 861 ok = _activateProfileReuseExternal();
mazgch 131:965a7cbc1e58 862 if (ok)
mazgch 131:965a7cbc1e58 863 TRACE("Reusing External Context\r\n");
mazgch 131:965a7cbc1e58 864 else
mazgch 131:965a7cbc1e58 865 ok = _activateProfileByCid(1, apn, username, password, auth);
mazgch 131:965a7cbc1e58 866 }
mazgch 99:3116d3e900ed 867 } while (!ok && config && *config); // maybe use next setting ?
mazgch 84:a05edb010176 868 if (!ok) {
mazgch 79:291df065e345 869 ERROR("Your modem APN/password/username may be wrong\r\n");
mazgch 95:8282dbbe1492 870 goto failure;
mazgch 79:291df065e345 871 }
mazgch 74:208e3e32d263 872 }
mazgch 21:c4d64830bf02 873 //Get local IP address
mazgch 21:c4d64830bf02 874 sendFormated("AT+UPSND=" PROFILE ",0\r\n");
mazgch 52:8071747a7cb3 875 if (RESP_OK != waitFinalResp(_cbUPSND, &_ip))
mazgch 95:8282dbbe1492 876 goto failure;
mazgch 31:a0bed6c1e05d 877 }
mazgch 95:8282dbbe1492 878 UNLOCK();
mazgch 32:8f12ac182bbb 879 return _ip;
mazgch 95:8282dbbe1492 880 failure:
mazgch 95:8282dbbe1492 881 unlock();
mazgch 95:8282dbbe1492 882 return NOIP;
mazgch 31:a0bed6c1e05d 883 }
mazgch 31:a0bed6c1e05d 884
mazgch 84:a05edb010176 885 int MDMParser::_cbUDOPN(int type, const char* buf, int len, char* mccmnc)
mazgch 84:a05edb010176 886 {
mazgch 84:a05edb010176 887 if ((type == TYPE_PLUS) && mccmnc) {
mazgch 84:a05edb010176 888 if (sscanf(buf, "\r\n+UDOPN: 0,\"%[^\"]\"", mccmnc) == 1)
mazgch 84:a05edb010176 889 ;
mazgch 84:a05edb010176 890 }
mazgch 84:a05edb010176 891 return WAIT;
mazgch 84:a05edb010176 892 }
mazgch 84:a05edb010176 893
mazgch 32:8f12ac182bbb 894 int MDMParser::_cbCMIP(int type, const char* buf, int len, IP* ip)
mazgch 32:8f12ac182bbb 895 {
mazgch 102:fb982ff9da82 896 if ((type == TYPE_UNKNOWN) && ip) {
mazgch 32:8f12ac182bbb 897 int a,b,c,d;
mazgch 102:fb982ff9da82 898 if (sscanf(buf, "\r\n" IPSTR, &a,&b,&c,&d) == 4)
mazgch 32:8f12ac182bbb 899 *ip = IPADR(a,b,c,d);
mazgch 32:8f12ac182bbb 900 }
mazgch 32:8f12ac182bbb 901 return WAIT;
mazgch 32:8f12ac182bbb 902 }
mazgch 32:8f12ac182bbb 903
mazgch 31:a0bed6c1e05d 904 int MDMParser::_cbUPSND(int type, const char* buf, int len, int* act)
mazgch 31:a0bed6c1e05d 905 {
mazgch 31:a0bed6c1e05d 906 if ((type == TYPE_PLUS) && act) {
mazgch 31:a0bed6c1e05d 907 if (sscanf(buf, "\r\n+UPSND: %*d,%*d,%d", act) == 1)
mazgch 31:a0bed6c1e05d 908 /*nothing*/;
mazgch 21:c4d64830bf02 909 }
mazgch 31:a0bed6c1e05d 910 return WAIT;
mazgch 31:a0bed6c1e05d 911 }
mazgch 31:a0bed6c1e05d 912
mazgch 31:a0bed6c1e05d 913 int MDMParser::_cbUPSND(int type, const char* buf, int len, IP* ip)
mazgch 31:a0bed6c1e05d 914 {
mazgch 31:a0bed6c1e05d 915 if ((type == TYPE_PLUS) && ip) {
mazgch 31:a0bed6c1e05d 916 int a,b,c,d;
mazgch 31:a0bed6c1e05d 917 // +UPSND=<profile_id>,<param_tag>[,<dynamic_param_val>]
mazgch 31:a0bed6c1e05d 918 if (sscanf(buf, "\r\n+UPSND: " PROFILE ",0,\"" IPSTR "\"", &a,&b,&c,&d) == 4)
mazgch 31:a0bed6c1e05d 919 *ip = IPADR(a,b,c,d);
mazgch 31:a0bed6c1e05d 920 }
mazgch 31:a0bed6c1e05d 921 return WAIT;
mazgch 31:a0bed6c1e05d 922 }
mazgch 31:a0bed6c1e05d 923
mazgch 31:a0bed6c1e05d 924 int MDMParser::_cbUDNSRN(int type, const char* buf, int len, IP* ip)
mazgch 31:a0bed6c1e05d 925 {
mazgch 31:a0bed6c1e05d 926 if ((type == TYPE_PLUS) && ip) {
mazgch 31:a0bed6c1e05d 927 int a,b,c,d;
mazgch 95:8282dbbe1492 928 if (sscanf(buf, "\r\n+UDNSRN: \"" IPSTR "\"", &a,&b,&c,&d) == 4)
mazgch 31:a0bed6c1e05d 929 *ip = IPADR(a,b,c,d);
mazgch 31:a0bed6c1e05d 930 }
mazgch 31:a0bed6c1e05d 931 return WAIT;
mazgch 21:c4d64830bf02 932 }
mazgch 21:c4d64830bf02 933
mazgch 21:c4d64830bf02 934 bool MDMParser::disconnect(void)
mazgch 21:c4d64830bf02 935 {
mazgch 95:8282dbbe1492 936 bool ok = false;
mazgch 95:8282dbbe1492 937 LOCK();
mazgch 74:208e3e32d263 938 INFO("Modem::disconnect\r\n");
mazgch 95:8282dbbe1492 939 if (_ip != NOIP) {
mazgch 125:25a292afbac6 940 if (_dev.dev == DEV_LISA_C2) {
mazgch 95:8282dbbe1492 941 // There something to do here
mazgch 95:8282dbbe1492 942 _ip = NOIP;
mazgch 95:8282dbbe1492 943 ok = true;
mazgch 95:8282dbbe1492 944 } else {
mazgch 95:8282dbbe1492 945 sendFormated("AT+UPSDA=" PROFILE ",4\r\n");
mazgch 95:8282dbbe1492 946 if (RESP_OK != waitFinalResp()) {
mazgch 95:8282dbbe1492 947 _ip = NOIP;
mazgch 95:8282dbbe1492 948 ok = true;
mazgch 95:8282dbbe1492 949 }
mazgch 95:8282dbbe1492 950 }
mazgch 21:c4d64830bf02 951 }
mazgch 95:8282dbbe1492 952 UNLOCK();
mazgch 95:8282dbbe1492 953 return ok;
mazgch 21:c4d64830bf02 954 }
mazgch 21:c4d64830bf02 955
mazgch 31:a0bed6c1e05d 956 MDMParser::IP MDMParser::gethostbyname(const char* host)
mazgch 21:c4d64830bf02 957 {
mazgch 31:a0bed6c1e05d 958 IP ip = NOIP;
mazgch 31:a0bed6c1e05d 959 int a,b,c,d;
mazgch 31:a0bed6c1e05d 960 if (sscanf(host, IPSTR, &a,&b,&c,&d) == 4)
mazgch 31:a0bed6c1e05d 961 ip = IPADR(a,b,c,d);
mazgch 31:a0bed6c1e05d 962 else {
mazgch 95:8282dbbe1492 963 LOCK();
mazgch 31:a0bed6c1e05d 964 sendFormated("AT+UDNSRN=0,\"%s\"\r\n", host);
mazgch 52:8071747a7cb3 965 if (RESP_OK != waitFinalResp(_cbUDNSRN, &ip))
mazgch 95:8282dbbe1492 966 ip = NOIP;
mazgch 95:8282dbbe1492 967 UNLOCK();
mazgch 21:c4d64830bf02 968 }
mazgch 31:a0bed6c1e05d 969 return ip;
mazgch 21:c4d64830bf02 970 }
mazgch 21:c4d64830bf02 971
mazgch 21:c4d64830bf02 972 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 973 // sockets
mazgch 21:c4d64830bf02 974
mazgch 103:197fa7920ad8 975 int MDMParser::_cbUSOCR(int type, const char* buf, int len, int* handle)
mazgch 21:c4d64830bf02 976 {
mazgch 103:197fa7920ad8 977 if ((type == TYPE_PLUS) && handle) {
mazgch 108:254bf037f83f 978 // +USOCR: socket
mazgch 108:254bf037f83f 979 if (sscanf(buf, "\r\n+USOCR: %d", handle) == 1)
mazgch 108:254bf037f83f 980 /*nothing*/;
mazgch 21:c4d64830bf02 981 }
mazgch 21:c4d64830bf02 982 return WAIT;
mazgch 21:c4d64830bf02 983 }
mazgch 21:c4d64830bf02 984
mazgch 63:42cb563a25bc 985 int MDMParser::socketSocket(IpProtocol ipproto, int port)
mazgch 21:c4d64830bf02 986 {
mazgch 103:197fa7920ad8 987 int socket;
mazgch 95:8282dbbe1492 988 LOCK();
mazgch 103:197fa7920ad8 989 // find an free socket
mazgch 103:197fa7920ad8 990 socket = _findSocket();
mazgch 47:9a89e5195721 991 TRACE("socketSocket(%d)\r\n", ipproto);
mazgch 95:8282dbbe1492 992 if (socket != SOCKET_ERROR) {
mazgch 106:18aeacdae391 993 if (ipproto == IPPROTO_UDP) {
mazgch 106:18aeacdae391 994 // sending port can only be set on 2G/3G modules
mazgch 125:25a292afbac6 995 if ((port != -1) && (_dev.dev != DEV_LISA_C2)) {
mazgch 106:18aeacdae391 996 sendFormated("AT+USOCR=17,%d\r\n", port);
mazgch 106:18aeacdae391 997 } else {
mazgch 106:18aeacdae391 998 sendFormated("AT+USOCR=17\r\n");
mazgch 106:18aeacdae391 999 }
mazgch 103:197fa7920ad8 1000 } else /*(ipproto == IPPROTO_TCP)*/ {
mazgch 103:197fa7920ad8 1001 sendFormated("AT+USOCR=6\r\n");
mazgch 103:197fa7920ad8 1002 }
mazgch 103:197fa7920ad8 1003 int handle = SOCKET_ERROR;
mazgch 103:197fa7920ad8 1004 if ((RESP_OK == waitFinalResp(_cbUSOCR, &handle)) &&
mazgch 103:197fa7920ad8 1005 (handle != SOCKET_ERROR)) {
mazgch 103:197fa7920ad8 1006 TRACE("Socket %d: handle %d was created\r\n", socket, handle);
mazgch 103:197fa7920ad8 1007 _sockets[socket].handle = handle;
mazgch 103:197fa7920ad8 1008 _sockets[socket].timeout_ms = TIMEOUT_BLOCKING;
mazgch 103:197fa7920ad8 1009 _sockets[socket].connected = false;
mazgch 103:197fa7920ad8 1010 _sockets[socket].pending = 0;
mazgch 103:197fa7920ad8 1011 }
mazgch 103:197fa7920ad8 1012 else
mazgch 103:197fa7920ad8 1013 socket = SOCKET_ERROR;
mazgch 95:8282dbbe1492 1014 }
mazgch 95:8282dbbe1492 1015 UNLOCK();
mazgch 21:c4d64830bf02 1016 return socket;
mazgch 21:c4d64830bf02 1017 }
mazgch 21:c4d64830bf02 1018
mazgch 21:c4d64830bf02 1019 bool MDMParser::socketConnect(int socket, const char * host, int port)
mazgch 21:c4d64830bf02 1020 {
mazgch 31:a0bed6c1e05d 1021 IP ip = gethostbyname(host);
mazgch 31:a0bed6c1e05d 1022 if (ip == NOIP)
mazgch 21:c4d64830bf02 1023 return false;
mazgch 21:c4d64830bf02 1024 // connect to socket
mazgch 95:8282dbbe1492 1025 bool ok = false;
mazgch 95:8282dbbe1492 1026 LOCK();
mazgch 103:197fa7920ad8 1027 if (ISSOCKET(socket) && (!_sockets[socket].connected)) {
mazgch 95:8282dbbe1492 1028 TRACE("socketConnect(%d,%s,%d)\r\n", socket,host,port);
mazgch 103:197fa7920ad8 1029 sendFormated("AT+USOCO=%d,\"" IPSTR "\",%d\r\n", _sockets[socket].handle, IPNUM(ip), port);
mazgch 95:8282dbbe1492 1030 if (RESP_OK == waitFinalResp())
mazgch 103:197fa7920ad8 1031 ok = _sockets[socket].connected = true;
mazgch 95:8282dbbe1492 1032 }
mazgch 95:8282dbbe1492 1033 UNLOCK();
mazgch 95:8282dbbe1492 1034 return ok;
mazgch 21:c4d64830bf02 1035 }
mazgch 21:c4d64830bf02 1036
mazgch 44:9d12223b78ff 1037 bool MDMParser::socketIsConnected(int socket)
mazgch 44:9d12223b78ff 1038 {
mazgch 95:8282dbbe1492 1039 bool ok = false;
mazgch 95:8282dbbe1492 1040 LOCK();
mazgch 103:197fa7920ad8 1041 ok = ISSOCKET(socket) && _sockets[socket].connected;
mazgch 107:436ee320efd6 1042 TRACE("socketIsConnected(%d) %s\r\n", socket, ok?"yes":"no");
mazgch 95:8282dbbe1492 1043 UNLOCK();
mazgch 95:8282dbbe1492 1044 return ok;
mazgch 44:9d12223b78ff 1045 }
mazgch 44:9d12223b78ff 1046
mazgch 66:69072b3c5bca 1047 bool MDMParser::socketSetBlocking(int socket, int timeout_ms)
mazgch 44:9d12223b78ff 1048 {
mazgch 95:8282dbbe1492 1049 bool ok = false;
mazgch 95:8282dbbe1492 1050 LOCK();
mazgch 103:197fa7920ad8 1051 TRACE("socketSetBlocking(%d,%d)\r\n", socket,timeout_ms);
mazgch 95:8282dbbe1492 1052 if (ISSOCKET(socket)) {
mazgch 95:8282dbbe1492 1053 _sockets[socket].timeout_ms = timeout_ms;
mazgch 95:8282dbbe1492 1054 ok = true;
mazgch 95:8282dbbe1492 1055 }
mazgch 95:8282dbbe1492 1056 UNLOCK();
mazgch 95:8282dbbe1492 1057 return ok;
mazgch 44:9d12223b78ff 1058 }
mazgch 44:9d12223b78ff 1059
mazgch 21:c4d64830bf02 1060 bool MDMParser::socketClose(int socket)
mazgch 21:c4d64830bf02 1061 {
mazgch 95:8282dbbe1492 1062 bool ok = false;
mazgch 95:8282dbbe1492 1063 LOCK();
mazgch 103:197fa7920ad8 1064 if (ISSOCKET(socket) && _sockets[socket].connected) {
mazgch 95:8282dbbe1492 1065 TRACE("socketClose(%d)\r\n", socket);
mazgch 103:197fa7920ad8 1066 sendFormated("AT+USOCL=%d\r\n", _sockets[socket].handle);
mazgch 95:8282dbbe1492 1067 if (RESP_OK == waitFinalResp()) {
mazgch 103:197fa7920ad8 1068 _sockets[socket].connected = false;
mazgch 95:8282dbbe1492 1069 ok = true;
mazgch 95:8282dbbe1492 1070 }
mazgch 95:8282dbbe1492 1071 }
mazgch 95:8282dbbe1492 1072 UNLOCK();
mazgch 95:8282dbbe1492 1073 return ok;
mazgch 21:c4d64830bf02 1074 }
mazgch 21:c4d64830bf02 1075
mazgch 21:c4d64830bf02 1076 bool MDMParser::socketFree(int socket)
mazgch 21:c4d64830bf02 1077 {
mazgch 95:8282dbbe1492 1078 // make sure it is closed
mazgch 21:c4d64830bf02 1079 socketClose(socket);
mazgch 95:8282dbbe1492 1080 bool ok = true;
mazgch 95:8282dbbe1492 1081 LOCK();
mazgch 103:197fa7920ad8 1082 if (ISSOCKET(socket)) {
mazgch 103:197fa7920ad8 1083 TRACE("socketFree(%d)\r\n", socket);
mazgch 103:197fa7920ad8 1084 _sockets[socket].handle = SOCKET_ERROR;
mazgch 103:197fa7920ad8 1085 _sockets[socket].timeout_ms = TIMEOUT_BLOCKING;
mazgch 103:197fa7920ad8 1086 _sockets[socket].connected = false;
mazgch 103:197fa7920ad8 1087 _sockets[socket].pending = 0;
mazgch 95:8282dbbe1492 1088 ok = true;
mazgch 95:8282dbbe1492 1089 }
mazgch 95:8282dbbe1492 1090 UNLOCK();
mazgch 95:8282dbbe1492 1091 return ok;
mazgch 21:c4d64830bf02 1092 }
mazgch 21:c4d64830bf02 1093
mazgch 69:4d6fa520dfca 1094 #define USO_MAX_WRITE 1024 //!< maximum number of bytes to write to socket
mazgch 69:4d6fa520dfca 1095
mazgch 21:c4d64830bf02 1096 int MDMParser::socketSend(int socket, const char * buf, int len)
mazgch 21:c4d64830bf02 1097 {
mazgch 47:9a89e5195721 1098 TRACE("socketSend(%d,,%d)\r\n", socket,len);
mazgch 68:33a96cf64986 1099 int cnt = len;
mazgch 68:33a96cf64986 1100 while (cnt > 0) {
mazgch 69:4d6fa520dfca 1101 int blk = USO_MAX_WRITE;
mazgch 68:33a96cf64986 1102 if (cnt < blk)
mazgch 68:33a96cf64986 1103 blk = cnt;
mazgch 95:8282dbbe1492 1104 bool ok = false;
mazgch 95:8282dbbe1492 1105 LOCK();
mazgch 103:197fa7920ad8 1106 if (ISSOCKET(socket)) {
mazgch 103:197fa7920ad8 1107 sendFormated("AT+USOWR=%d,%d\r\n",_sockets[socket].handle,blk);
mazgch 103:197fa7920ad8 1108 if (RESP_PROMPT == waitFinalResp()) {
mazgch 103:197fa7920ad8 1109 wait_ms(50);
mazgch 103:197fa7920ad8 1110 send(buf, blk);
mazgch 103:197fa7920ad8 1111 if (RESP_OK == waitFinalResp())
mazgch 103:197fa7920ad8 1112 ok = true;
mazgch 103:197fa7920ad8 1113 }
mazgch 95:8282dbbe1492 1114 }
mazgch 95:8282dbbe1492 1115 UNLOCK();
mazgch 95:8282dbbe1492 1116 if (!ok)
mazgch 21:c4d64830bf02 1117 return SOCKET_ERROR;
mazgch 68:33a96cf64986 1118 buf += blk;
mazgch 68:33a96cf64986 1119 cnt -= blk;
mazgch 21:c4d64830bf02 1120 }
mazgch 68:33a96cf64986 1121 return (len - cnt);
mazgch 21:c4d64830bf02 1122 }
mazgch 21:c4d64830bf02 1123
mazgch 21:c4d64830bf02 1124 int MDMParser::socketSendTo(int socket, IP ip, int port, const char * buf, int len)
mazgch 21:c4d64830bf02 1125 {
mazgch 103:197fa7920ad8 1126 TRACE("socketSendTo(%d," IPSTR ",%d,,%d)\r\n", socket,IPNUM(ip),port,len);
mazgch 68:33a96cf64986 1127 int cnt = len;
mazgch 68:33a96cf64986 1128 while (cnt > 0) {
mazgch 69:4d6fa520dfca 1129 int blk = USO_MAX_WRITE;
mazgch 68:33a96cf64986 1130 if (cnt < blk)
mazgch 68:33a96cf64986 1131 blk = cnt;
mazgch 95:8282dbbe1492 1132 bool ok = false;
mazgch 95:8282dbbe1492 1133 LOCK();
mazgch 103:197fa7920ad8 1134 if (ISSOCKET(socket)) {
mazgch 103:197fa7920ad8 1135 sendFormated("AT+USOST=%d,\"" IPSTR "\",%d,%d\r\n",_sockets[socket].handle,IPNUM(ip),port,blk);
mazgch 103:197fa7920ad8 1136 if (RESP_PROMPT == waitFinalResp()) {
mazgch 103:197fa7920ad8 1137 wait_ms(50);
mazgch 103:197fa7920ad8 1138 send(buf, blk);
mazgch 103:197fa7920ad8 1139 if (RESP_OK == waitFinalResp())
mazgch 103:197fa7920ad8 1140 ok = true;
mazgch 103:197fa7920ad8 1141 }
mazgch 95:8282dbbe1492 1142 }
mazgch 95:8282dbbe1492 1143 UNLOCK();
mazgch 95:8282dbbe1492 1144 if (!ok)
mazgch 21:c4d64830bf02 1145 return SOCKET_ERROR;
mazgch 68:33a96cf64986 1146 buf += blk;
mazgch 68:33a96cf64986 1147 cnt -= blk;
mazgch 21:c4d64830bf02 1148 }
mazgch 68:33a96cf64986 1149 return (len - cnt);
mazgch 21:c4d64830bf02 1150 }
mazgch 21:c4d64830bf02 1151
mazgch 21:c4d64830bf02 1152 int MDMParser::socketReadable(int socket)
mazgch 21:c4d64830bf02 1153 {
mazgch 95:8282dbbe1492 1154 int pending = SOCKET_ERROR;
mazgch 95:8282dbbe1492 1155 LOCK();
mazgch 103:197fa7920ad8 1156 if (ISSOCKET(socket) && _sockets[socket].connected) {
mazgch 95:8282dbbe1492 1157 TRACE("socketReadable(%d)\r\n", socket);
mazgch 95:8282dbbe1492 1158 // allow to receive unsolicited commands
mazgch 95:8282dbbe1492 1159 waitFinalResp(NULL, NULL, 0);
mazgch 103:197fa7920ad8 1160 if (_sockets[socket].connected)
mazgch 95:8282dbbe1492 1161 pending = _sockets[socket].pending;
mazgch 95:8282dbbe1492 1162 }
mazgch 95:8282dbbe1492 1163 UNLOCK();
mazgch 95:8282dbbe1492 1164 return pending;
mazgch 21:c4d64830bf02 1165 }
mazgch 21:c4d64830bf02 1166
mazgch 21:c4d64830bf02 1167 int MDMParser::_cbUSORD(int type, const char* buf, int len, char* out)
mazgch 21:c4d64830bf02 1168 {
mazgch 21:c4d64830bf02 1169 if ((type == TYPE_PLUS) && out) {
mazgch 21:c4d64830bf02 1170 int sz, sk;
mazgch 21:c4d64830bf02 1171 if ((sscanf(buf, "\r\n+USORD: %d,%d,", &sk, &sz) == 2) &&
mazgch 21:c4d64830bf02 1172 (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
mazgch 21:c4d64830bf02 1173 memcpy(out, &buf[len-1-sz], sz);
mazgch 21:c4d64830bf02 1174 }
mazgch 21:c4d64830bf02 1175 }
mazgch 21:c4d64830bf02 1176 return WAIT;
mazgch 21:c4d64830bf02 1177 }
mazgch 21:c4d64830bf02 1178
mazgch 21:c4d64830bf02 1179 int MDMParser::socketRecv(int socket, char* buf, int len)
mazgch 21:c4d64830bf02 1180 {
mazgch 21:c4d64830bf02 1181 int cnt = 0;
mazgch 47:9a89e5195721 1182 TRACE("socketRecv(%d,,%d)\r\n", socket, len);
mazgch 95:8282dbbe1492 1183 #ifdef MDM_DEBUG
mazgch 21:c4d64830bf02 1184 memset(buf, '\0', len);
mazgch 95:8282dbbe1492 1185 #endif
mazgch 44:9d12223b78ff 1186 Timer timer;
mazgch 44:9d12223b78ff 1187 timer.start();
mazgch 21:c4d64830bf02 1188 while (len) {
mazgch 69:4d6fa520dfca 1189 int blk = MAX_SIZE; // still need space for headers and unsolicited commands
mazgch 21:c4d64830bf02 1190 if (len < blk) blk = len;
mazgch 95:8282dbbe1492 1191 bool ok = false;
mazgch 95:8282dbbe1492 1192 LOCK();
mazgch 95:8282dbbe1492 1193 if (ISSOCKET(socket)) {
mazgch 103:197fa7920ad8 1194 if (_sockets[socket].connected) {
mazgch 95:8282dbbe1492 1195 if (_sockets[socket].pending < blk)
mazgch 95:8282dbbe1492 1196 blk = _sockets[socket].pending;
mazgch 95:8282dbbe1492 1197 if (blk > 0) {
mazgch 103:197fa7920ad8 1198 sendFormated("AT+USORD=%d,%d\r\n",_sockets[socket].handle, blk);
mazgch 95:8282dbbe1492 1199 if (RESP_OK == waitFinalResp(_cbUSORD, buf)) {
mazgch 95:8282dbbe1492 1200 _sockets[socket].pending -= blk;
mazgch 95:8282dbbe1492 1201 len -= blk;
mazgch 95:8282dbbe1492 1202 cnt += blk;
mazgch 95:8282dbbe1492 1203 buf += blk;
mazgch 95:8282dbbe1492 1204 ok = true;
mazgch 95:8282dbbe1492 1205 }
mazgch 95:8282dbbe1492 1206 } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) {
mazgch 95:8282dbbe1492 1207 ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs
mazgch 95:8282dbbe1492 1208 } else {
mazgch 95:8282dbbe1492 1209 len = 0;
mazgch 95:8282dbbe1492 1210 ok = true;
mazgch 95:8282dbbe1492 1211 }
mazgch 103:197fa7920ad8 1212 } else {
mazgch 95:8282dbbe1492 1213 len = 0;
mazgch 95:8282dbbe1492 1214 ok = true;
mazgch 21:c4d64830bf02 1215 }
mazgch 21:c4d64830bf02 1216 }
mazgch 95:8282dbbe1492 1217 UNLOCK();
mazgch 107:436ee320efd6 1218 if (!ok) {
mazgch 107:436ee320efd6 1219 TRACE("socketRecv: ERROR\r\n");
mazgch 95:8282dbbe1492 1220 return SOCKET_ERROR;
mazgch 107:436ee320efd6 1221 }
mazgch 21:c4d64830bf02 1222 }
mazgch 107:436ee320efd6 1223 TRACE("socketRecv: %d \"%*s\"\r\n", cnt, cnt, buf-cnt);
mazgch 21:c4d64830bf02 1224 return cnt;
mazgch 21:c4d64830bf02 1225 }
mazgch 21:c4d64830bf02 1226
mazgch 21:c4d64830bf02 1227 int MDMParser::_cbUSORF(int type, const char* buf, int len, USORFparam* param)
mazgch 21:c4d64830bf02 1228 {
mazgch 21:c4d64830bf02 1229 if ((type == TYPE_PLUS) && param) {
mazgch 21:c4d64830bf02 1230 int sz, sk, p, a,b,c,d;
mazgch 95:8282dbbe1492 1231 int r = sscanf(buf, "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,",
mazgch 95:8282dbbe1492 1232 &sk,&a,&b,&c,&d,&p,&sz);
mazgch 95:8282dbbe1492 1233 if ((r == 7) && (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
mazgch 21:c4d64830bf02 1234 memcpy(param->buf, &buf[len-1-sz], sz);
mazgch 21:c4d64830bf02 1235 param->ip = IPADR(a,b,c,d);
mazgch 21:c4d64830bf02 1236 param->port = p;
mazgch 21:c4d64830bf02 1237 }
mazgch 21:c4d64830bf02 1238 }
mazgch 21:c4d64830bf02 1239 return WAIT;
mazgch 21:c4d64830bf02 1240 }
mazgch 21:c4d64830bf02 1241
mazgch 63:42cb563a25bc 1242 int MDMParser::socketRecvFrom(int socket, IP* ip, int* port, char* buf, int len)
mazgch 21:c4d64830bf02 1243 {
mazgch 21:c4d64830bf02 1244 int cnt = 0;
mazgch 63:42cb563a25bc 1245 TRACE("socketRecvFrom(%d,,%d)\r\n", socket, len);
mazgch 95:8282dbbe1492 1246 #ifdef MDM_DEBUG
mazgch 21:c4d64830bf02 1247 memset(buf, '\0', len);
mazgch 95:8282dbbe1492 1248 #endif
mazgch 44:9d12223b78ff 1249 Timer timer;
mazgch 44:9d12223b78ff 1250 timer.start();
mazgch 21:c4d64830bf02 1251 while (len) {
mazgch 69:4d6fa520dfca 1252 int blk = MAX_SIZE; // still need space for headers and unsolicited commands
mazgch 21:c4d64830bf02 1253 if (len < blk) blk = len;
mazgch 95:8282dbbe1492 1254 bool ok = false;
mazgch 95:8282dbbe1492 1255 LOCK();
mazgch 95:8282dbbe1492 1256 if (ISSOCKET(socket)) {
mazgch 95:8282dbbe1492 1257 if (_sockets[socket].pending < blk)
mazgch 95:8282dbbe1492 1258 blk = _sockets[socket].pending;
mazgch 95:8282dbbe1492 1259 if (blk > 0) {
mazgch 103:197fa7920ad8 1260 sendFormated("AT+USORF=%d,%d\r\n",_sockets[socket].handle, blk);
mazgch 95:8282dbbe1492 1261 USORFparam param;
mazgch 95:8282dbbe1492 1262 param.buf = buf;
mazgch 95:8282dbbe1492 1263 if (RESP_OK == waitFinalResp(_cbUSORF, &param)) {
mazgch 95:8282dbbe1492 1264 _sockets[socket].pending -= blk;
mazgch 95:8282dbbe1492 1265 *ip = param.ip;
mazgch 95:8282dbbe1492 1266 *port = param.port;
mazgch 95:8282dbbe1492 1267 len -= blk;
mazgch 95:8282dbbe1492 1268 cnt += blk;
mazgch 95:8282dbbe1492 1269 buf += blk;
mazgch 95:8282dbbe1492 1270 len = 0; // done
mazgch 95:8282dbbe1492 1271 ok = true;
mazgch 95:8282dbbe1492 1272 }
mazgch 95:8282dbbe1492 1273 } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) {
mazgch 95:8282dbbe1492 1274 ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs
mazgch 95:8282dbbe1492 1275 } else {
mazgch 95:8282dbbe1492 1276 len = 0; // no more data and socket closed or timed-out
mazgch 95:8282dbbe1492 1277 ok = true;
mazgch 21:c4d64830bf02 1278 }
mazgch 95:8282dbbe1492 1279 }
mazgch 95:8282dbbe1492 1280 UNLOCK();
mazgch 107:436ee320efd6 1281 if (!ok) {
mazgch 107:436ee320efd6 1282 TRACE("socketRecv: ERROR\r\n");
mazgch 95:8282dbbe1492 1283 return SOCKET_ERROR;
mazgch 107:436ee320efd6 1284 }
mazgch 21:c4d64830bf02 1285 }
mazgch 44:9d12223b78ff 1286 timer.stop();
mazgch 44:9d12223b78ff 1287 timer.reset();
mazgch 107:436ee320efd6 1288 TRACE("socketRecv: %d \"%*s\"\r\n", cnt, cnt, buf-cnt);
mazgch 21:c4d64830bf02 1289 return cnt;
mazgch 21:c4d64830bf02 1290 }
mazgch 21:c4d64830bf02 1291
mazgch 103:197fa7920ad8 1292 int MDMParser::_findSocket(int handle) {
mazgch 104:c64ba749a422 1293 for (int socket = 0; socket < NUMSOCKETS; socket ++) {
mazgch 103:197fa7920ad8 1294 if (_sockets[socket].handle == handle)
mazgch 103:197fa7920ad8 1295 return socket;
mazgch 103:197fa7920ad8 1296 }
mazgch 103:197fa7920ad8 1297 return SOCKET_ERROR;
mazgch 103:197fa7920ad8 1298 }
mazgch 103:197fa7920ad8 1299
mazgch 21:c4d64830bf02 1300 // ----------------------------------------------------------------
mazgch 31:a0bed6c1e05d 1301
mazgch 31:a0bed6c1e05d 1302 int MDMParser::_cbCMGL(int type, const char* buf, int len, CMGLparam* param)
mazgch 21:c4d64830bf02 1303 {
mazgch 31:a0bed6c1e05d 1304 if ((type == TYPE_PLUS) && param && param->num) {
mazgch 31:a0bed6c1e05d 1305 // +CMGL: <ix>,...
mazgch 31:a0bed6c1e05d 1306 int ix;
mazgch 31:a0bed6c1e05d 1307 if (sscanf(buf, "\r\n+CMGL: %d,", &ix) == 1)
mazgch 31:a0bed6c1e05d 1308 {
mazgch 31:a0bed6c1e05d 1309 *param->ix++ = ix;
mazgch 31:a0bed6c1e05d 1310 param->num--;
mazgch 31:a0bed6c1e05d 1311 }
mazgch 29:53d346010624 1312 }
mazgch 29:53d346010624 1313 return WAIT;
mazgch 21:c4d64830bf02 1314 }
mazgch 21:c4d64830bf02 1315
mazgch 31:a0bed6c1e05d 1316 int MDMParser::smsList(const char* stat /*= "ALL"*/, int* ix /*=NULL*/, int num /*= 0*/) {
mazgch 95:8282dbbe1492 1317 int ret = -1;
mazgch 95:8282dbbe1492 1318 LOCK();
mazgch 31:a0bed6c1e05d 1319 sendFormated("AT+CMGL=\"%s\"\r\n", stat);
mazgch 31:a0bed6c1e05d 1320 CMGLparam param;
mazgch 31:a0bed6c1e05d 1321 param.ix = ix;
mazgch 31:a0bed6c1e05d 1322 param.num = num;
mazgch 95:8282dbbe1492 1323 if (RESP_OK == waitFinalResp(_cbCMGL, &param))
mazgch 95:8282dbbe1492 1324 ret = num - param.num;
mazgch 95:8282dbbe1492 1325 UNLOCK();
mazgch 95:8282dbbe1492 1326 return ret;
mazgch 21:c4d64830bf02 1327 }
mazgch 21:c4d64830bf02 1328
mazgch 21:c4d64830bf02 1329 bool MDMParser::smsSend(const char* num, const char* buf)
mazgch 21:c4d64830bf02 1330 {
mazgch 95:8282dbbe1492 1331 bool ok = false;
mazgch 95:8282dbbe1492 1332 LOCK();
mazgch 80:34985b4d821e 1333 sendFormated("AT+CMGS=\"%s\"\r\n",num);
mazgch 95:8282dbbe1492 1334 if (RESP_PROMPT == waitFinalResp(NULL,NULL,150*1000)) {
mazgch 95:8282dbbe1492 1335 send(buf, strlen(buf));
mazgch 95:8282dbbe1492 1336 const char ctrlZ = 0x1A;
mazgch 95:8282dbbe1492 1337 send(&ctrlZ, sizeof(ctrlZ));
mazgch 95:8282dbbe1492 1338 ok = (RESP_OK == waitFinalResp());
mazgch 21:c4d64830bf02 1339 }
mazgch 95:8282dbbe1492 1340 UNLOCK();
mazgch 95:8282dbbe1492 1341 return ok;
mazgch 21:c4d64830bf02 1342 }
mazgch 21:c4d64830bf02 1343
mazgch 21:c4d64830bf02 1344 bool MDMParser::smsDelete(int ix)
mazgch 21:c4d64830bf02 1345 {
mazgch 95:8282dbbe1492 1346 bool ok = false;
mazgch 95:8282dbbe1492 1347 LOCK();
mazgch 21:c4d64830bf02 1348 sendFormated("AT+CMGD=%d\r\n",ix);
mazgch 95:8282dbbe1492 1349 ok = (RESP_OK == waitFinalResp());
mazgch 95:8282dbbe1492 1350 UNLOCK();
mazgch 95:8282dbbe1492 1351 return ok;
mazgch 21:c4d64830bf02 1352 }
mazgch 21:c4d64830bf02 1353
mazgch 21:c4d64830bf02 1354 int MDMParser::_cbCMGR(int type, const char* buf, int len, CMGRparam* param)
mazgch 21:c4d64830bf02 1355 {
mazgch 21:c4d64830bf02 1356 if (param) {
mazgch 21:c4d64830bf02 1357 if (type == TYPE_PLUS) {
mazgch 21:c4d64830bf02 1358 if (sscanf(buf, "\r\n+CMGR: \"%*[^\"]\",\"%[^\"]", param->num) == 1) {
mazgch 21:c4d64830bf02 1359 }
mazgch 37:cc3433329d66 1360 } else if ((type == TYPE_UNKNOWN) && (buf[len-2] == '\r') && (buf[len-1] == '\n')) {
mazgch 21:c4d64830bf02 1361 memcpy(param->buf, buf, len-2);
mazgch 21:c4d64830bf02 1362 param->buf[len-2] = '\0';
mazgch 21:c4d64830bf02 1363 }
mazgch 21:c4d64830bf02 1364 }
mazgch 21:c4d64830bf02 1365 return WAIT;
mazgch 21:c4d64830bf02 1366 }
mazgch 21:c4d64830bf02 1367
mazgch 21:c4d64830bf02 1368 bool MDMParser::smsRead(int ix, char* num, char* buf, int len)
mazgch 21:c4d64830bf02 1369 {
mazgch 95:8282dbbe1492 1370 bool ok = false;
mazgch 95:8282dbbe1492 1371 LOCK();
mazgch 21:c4d64830bf02 1372 CMGRparam param;
mazgch 21:c4d64830bf02 1373 param.num = num;
mazgch 21:c4d64830bf02 1374 param.buf = buf;
mazgch 21:c4d64830bf02 1375 sendFormated("AT+CMGR=%d\r\n",ix);
mazgch 95:8282dbbe1492 1376 ok = (RESP_OK == waitFinalResp(_cbCMGR, &param));
mazgch 95:8282dbbe1492 1377 UNLOCK();
mazgch 95:8282dbbe1492 1378 return ok;
mazgch 21:c4d64830bf02 1379 }
mazgch 54:7ba8e4c218e2 1380
mazgch 54:7ba8e4c218e2 1381 // ----------------------------------------------------------------
mazgch 70:0a87d256cd24 1382
mazgch 70:0a87d256cd24 1383 int MDMParser::_cbCUSD(int type, const char* buf, int len, char* resp)
mazgch 70:0a87d256cd24 1384 {
mazgch 70:0a87d256cd24 1385 if ((type == TYPE_PLUS) && resp) {
mazgch 70:0a87d256cd24 1386 // +USD: \"%*[^\"]\",\"%[^\"]\",,\"%*[^\"]\",%d,%d,%d,%d,\"*[^\"]\",%d,%d"..);
mazgch 70:0a87d256cd24 1387 if (sscanf(buf, "\r\n+CUSD: %*d,\"%[^\"]\",%*d", resp) == 1) {
mazgch 70:0a87d256cd24 1388 /*nothing*/
mazgch 70:0a87d256cd24 1389 }
mazgch 70:0a87d256cd24 1390 }
mazgch 70:0a87d256cd24 1391 return WAIT;
mazgch 70:0a87d256cd24 1392 }
mazgch 70:0a87d256cd24 1393
mazgch 70:0a87d256cd24 1394 bool MDMParser::ussdCommand(const char* cmd, char* buf)
mazgch 70:0a87d256cd24 1395 {
mazgch 95:8282dbbe1492 1396 bool ok = false;
mazgch 95:8282dbbe1492 1397 LOCK();
mazgch 70:0a87d256cd24 1398 *buf = '\0';
mazgch 125:25a292afbac6 1399 if (_dev.dev != DEV_LISA_C2) {
mazgch 95:8282dbbe1492 1400 sendFormated("AT+CUSD=1,\"%s\"\r\n",cmd);
mazgch 95:8282dbbe1492 1401 ok = (RESP_OK == waitFinalResp(_cbCUSD, buf));
mazgch 70:0a87d256cd24 1402 }
mazgch 95:8282dbbe1492 1403 UNLOCK();
mazgch 95:8282dbbe1492 1404 return ok;
mazgch 70:0a87d256cd24 1405 }
mazgch 80:34985b4d821e 1406
mazgch 80:34985b4d821e 1407 // ----------------------------------------------------------------
mazgch 70:0a87d256cd24 1408
mazgch 115:d8d94b73c725 1409 int MDMParser::_cbUDELFILE(int type, const char* buf, int len, void*)
mazgch 115:d8d94b73c725 1410 {
mazgch 115:d8d94b73c725 1411 if ((type == TYPE_ERROR) && strstr(buf, "+CME ERROR: FILE NOT FOUND"))
mazgch 115:d8d94b73c725 1412 return RESP_OK; // file does not exist, so all ok...
mazgch 115:d8d94b73c725 1413 return WAIT;
mazgch 115:d8d94b73c725 1414 }
mazgch 115:d8d94b73c725 1415
mazgch 80:34985b4d821e 1416 bool MDMParser::delFile(const char* filename)
mazgch 80:34985b4d821e 1417 {
mazgch 95:8282dbbe1492 1418 bool ok = false;
mazgch 95:8282dbbe1492 1419 LOCK();
mazgch 80:34985b4d821e 1420 sendFormated("AT+UDELFILE=\"%s\"\r\n", filename);
mazgch 115:d8d94b73c725 1421 ok = (RESP_OK == waitFinalResp(_cbUDELFILE));
mazgch 95:8282dbbe1492 1422 UNLOCK();
mazgch 95:8282dbbe1492 1423 return ok;
mazgch 80:34985b4d821e 1424 }
mazgch 80:34985b4d821e 1425
mazgch 80:34985b4d821e 1426 int MDMParser::writeFile(const char* filename, const char* buf, int len)
mazgch 80:34985b4d821e 1427 {
mazgch 95:8282dbbe1492 1428 bool ok = false;
mazgch 95:8282dbbe1492 1429 LOCK();
mazgch 80:34985b4d821e 1430 sendFormated("AT+UDWNFILE=\"%s\",%d\r\n", filename, len);
mazgch 95:8282dbbe1492 1431 if (RESP_PROMPT == waitFinalResp()) {
mazgch 95:8282dbbe1492 1432 send(buf, len);
mazgch 95:8282dbbe1492 1433 ok = (RESP_OK == waitFinalResp());
mazgch 95:8282dbbe1492 1434 }
mazgch 95:8282dbbe1492 1435 UNLOCK();
mazgch 95:8282dbbe1492 1436 return ok ? len : -1;
mazgch 80:34985b4d821e 1437 }
mazgch 80:34985b4d821e 1438
mazgch 80:34985b4d821e 1439 int MDMParser::readFile(const char* filename, char* buf, int len)
mazgch 80:34985b4d821e 1440 {
mazgch 80:34985b4d821e 1441 URDFILEparam param;
mazgch 80:34985b4d821e 1442 param.filename = filename;
mazgch 80:34985b4d821e 1443 param.buf = buf;
mazgch 80:34985b4d821e 1444 param.sz = len;
mazgch 80:34985b4d821e 1445 param.len = 0;
mazgch 95:8282dbbe1492 1446 LOCK();
mazgch 95:8282dbbe1492 1447 sendFormated("AT+URDFILE=\"%s\"\r\n", filename, len);
mazgch 105:f6bb2a20de70 1448 if (RESP_OK != waitFinalResp(_cbURDFILE, &param))
mazgch 95:8282dbbe1492 1449 param.len = -1;
mazgch 95:8282dbbe1492 1450 UNLOCK();
mazgch 80:34985b4d821e 1451 return param.len;
mazgch 80:34985b4d821e 1452 }
mazgch 80:34985b4d821e 1453
mazgch 80:34985b4d821e 1454 int MDMParser::_cbURDFILE(int type, const char* buf, int len, URDFILEparam* param)
mazgch 80:34985b4d821e 1455 {
mazgch 80:34985b4d821e 1456 if ((type == TYPE_PLUS) && param && param->filename && param->buf) {
mazgch 80:34985b4d821e 1457 char filename[48];
mazgch 80:34985b4d821e 1458 int sz;
mazgch 80:34985b4d821e 1459 if ((sscanf(buf, "\r\n+URDFILE: \"%[^\"]\",%d,", filename, &sz) == 2) &&
mazgch 80:34985b4d821e 1460 (0 == strcmp(param->filename, filename)) &&
mazgch 80:34985b4d821e 1461 (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) {
mazgch 80:34985b4d821e 1462 param->len = (sz < param->sz) ? sz : param->sz;
mazgch 80:34985b4d821e 1463 memcpy(param->buf, &buf[len-1-sz], param->len);
mazgch 80:34985b4d821e 1464 }
mazgch 80:34985b4d821e 1465 }
mazgch 80:34985b4d821e 1466 return WAIT;
mazgch 80:34985b4d821e 1467 }
mazgch 80:34985b4d821e 1468
mazgch 70:0a87d256cd24 1469 // ----------------------------------------------------------------
mazgch 74:208e3e32d263 1470 bool MDMParser::setDebug(int level)
mazgch 74:208e3e32d263 1471 {
mazgch 74:208e3e32d263 1472 #ifdef MDM_DEBUG
mazgch 123:66cef6353b13 1473 _debugLevel = (level < -1) ? -1 :
mazgch 123:66cef6353b13 1474 (level > 3) ? 3 :
mazgch 123:66cef6353b13 1475 level;
mazgch 74:208e3e32d263 1476 #endif
mazgch 123:66cef6353b13 1477 return _debugLevel == level;
mazgch 74:208e3e32d263 1478 }
mazgch 74:208e3e32d263 1479
mazgch 73:2b32e0a21df2 1480 void MDMParser::dumpDevStatus(MDMParser::DevStatus* status,
mazgch 73:2b32e0a21df2 1481 _DPRINT dprint, void* param)
mazgch 54:7ba8e4c218e2 1482 {
mazgch 75:ce6e12067d0c 1483 dprint(param, "Modem::devStatus\r\n");
mazgch 125:25a292afbac6 1484 const char* txtDev[] = { "Unknown", "SARA-G35", "LISA-U2", "LISA-C2",
mazgch 125:25a292afbac6 1485 "SARA-U2", "LEON-G2", "TOBY-L2", "MPCI-L2" };
mazgch 98:c786461edd40 1486 if (status->dev < sizeof(txtDev)/sizeof(*txtDev) && (status->dev != DEV_UNKNOWN))
mazgch 73:2b32e0a21df2 1487 dprint(param, " Device: %s\r\n", txtDev[status->dev]);
mazgch 54:7ba8e4c218e2 1488 const char* txtLpm[] = { "Disabled", "Enabled", "Active" };
mazgch 54:7ba8e4c218e2 1489 if (status->lpm < sizeof(txtLpm)/sizeof(*txtLpm))
mazgch 73:2b32e0a21df2 1490 dprint(param, " Power Save: %s\r\n", txtLpm[status->lpm]);
mazgch 75:ce6e12067d0c 1491 const char* txtSim[] = { "Unknown", "Missing", "Pin", "Ready" };
mazgch 98:c786461edd40 1492 if (status->sim < sizeof(txtSim)/sizeof(*txtSim) && (status->sim != SIM_UNKNOWN))
mazgch 73:2b32e0a21df2 1493 dprint(param, " SIM: %s\r\n", txtSim[status->sim]);
mazgch 54:7ba8e4c218e2 1494 if (*status->ccid)
mazgch 73:2b32e0a21df2 1495 dprint(param, " CCID: %s\r\n", status->ccid);
mazgch 54:7ba8e4c218e2 1496 if (*status->imei)
mazgch 73:2b32e0a21df2 1497 dprint(param, " IMEI: %s\r\n", status->imei);
mazgch 54:7ba8e4c218e2 1498 if (*status->imsi)
mazgch 73:2b32e0a21df2 1499 dprint(param, " IMSI: %s\r\n", status->imsi);
mazgch 54:7ba8e4c218e2 1500 if (*status->meid)
mazgch 73:2b32e0a21df2 1501 dprint(param, " MEID: %s\r\n", status->meid); // LISA-C
mazgch 54:7ba8e4c218e2 1502 if (*status->manu)
mazgch 73:2b32e0a21df2 1503 dprint(param, " Manufacturer: %s\r\n", status->manu);
mazgch 54:7ba8e4c218e2 1504 if (*status->model)
mazgch 73:2b32e0a21df2 1505 dprint(param, " Model: %s\r\n", status->model);
mazgch 54:7ba8e4c218e2 1506 if (*status->ver)
mazgch 73:2b32e0a21df2 1507 dprint(param, " Version: %s\r\n", status->ver);
mazgch 54:7ba8e4c218e2 1508 }
mazgch 54:7ba8e4c218e2 1509
mazgch 73:2b32e0a21df2 1510 void MDMParser::dumpNetStatus(MDMParser::NetStatus *status,
mazgch 73:2b32e0a21df2 1511 _DPRINT dprint, void* param)
mazgch 54:7ba8e4c218e2 1512 {
mazgch 75:ce6e12067d0c 1513 dprint(param, "Modem::netStatus\r\n");
mazgch 54:7ba8e4c218e2 1514 const char* txtReg[] = { "Unknown", "Denied", "None", "Home", "Roaming" };
mazgch 98:c786461edd40 1515 if (status->csd < sizeof(txtReg)/sizeof(*txtReg) && (status->csd != REG_UNKNOWN))
mazgch 79:291df065e345 1516 dprint(param, " CSD Registration: %s\r\n", txtReg[status->csd]);
mazgch 98:c786461edd40 1517 if (status->psd < sizeof(txtReg)/sizeof(*txtReg) && (status->psd != REG_UNKNOWN))
mazgch 79:291df065e345 1518 dprint(param, " PSD Registration: %s\r\n", txtReg[status->psd]);
mazgch 123:66cef6353b13 1519 if (status->eps < sizeof(txtReg)/sizeof(*txtReg) && (status->eps != REG_UNKNOWN))
mazgch 123:66cef6353b13 1520 dprint(param, " EPS Registration: %s\r\n", txtReg[status->eps]);
mazgch 123:66cef6353b13 1521 const char* txtAct[] = { "Unknown", "GSM", "Edge", "3G", "CDMA", "LTE" };
mazgch 98:c786461edd40 1522 if (status->act < sizeof(txtAct)/sizeof(*txtAct) && (status->act != ACT_UNKNOWN))
mazgch 73:2b32e0a21df2 1523 dprint(param, " Access Technology: %s\r\n", txtAct[status->act]);
mazgch 54:7ba8e4c218e2 1524 if (status->rssi)
mazgch 73:2b32e0a21df2 1525 dprint(param, " Signal Strength: %d dBm\r\n", status->rssi);
mazgch 54:7ba8e4c218e2 1526 if (status->ber)
mazgch 73:2b32e0a21df2 1527 dprint(param, " Bit Error Rate: %d\r\n", status->ber);
mazgch 54:7ba8e4c218e2 1528 if (*status->opr)
mazgch 73:2b32e0a21df2 1529 dprint(param, " Operator: %s\r\n", status->opr);
mazgch 54:7ba8e4c218e2 1530 if (status->lac != 0xFFFF)
mazgch 73:2b32e0a21df2 1531 dprint(param, " Location Area Code: %04X\r\n", status->lac);
mazgch 54:7ba8e4c218e2 1532 if (status->ci != 0xFFFFFFFF)
mazgch 73:2b32e0a21df2 1533 dprint(param, " Cell ID: %08X\r\n", status->ci);
mazgch 54:7ba8e4c218e2 1534 if (*status->num)
mazgch 73:2b32e0a21df2 1535 dprint(param, " Phone Number: %s\r\n", status->num);
mazgch 54:7ba8e4c218e2 1536 }
mazgch 54:7ba8e4c218e2 1537
mazgch 73:2b32e0a21df2 1538 void MDMParser::dumpIp(MDMParser::IP ip,
mazgch 73:2b32e0a21df2 1539 _DPRINT dprint, void* param)
mazgch 54:7ba8e4c218e2 1540 {
mazgch 57:869bd35f44cc 1541 if (ip != NOIP)
mazgch 75:ce6e12067d0c 1542 dprint(param, "Modem:IP " IPSTR "\r\n", IPNUM(ip));
mazgch 54:7ba8e4c218e2 1543 }
mazgch 70:0a87d256cd24 1544
mazgch 21:c4d64830bf02 1545 // ----------------------------------------------------------------
mazgch 21:c4d64830bf02 1546 int MDMParser::_parseMatch(Pipe<char>* pipe, int len, const char* sta, const char* end)
mazgch 18:e5697801df29 1547 {
mazgch 18:e5697801df29 1548 int o = 0;
mazgch 21:c4d64830bf02 1549 if (sta) {
mazgch 21:c4d64830bf02 1550 while (*sta) {
mazgch 21:c4d64830bf02 1551 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 1552 char ch = pipe->next();
mazgch 21:c4d64830bf02 1553 if (*sta++ != ch) return NOT_FOUND;
mazgch 21:c4d64830bf02 1554 }
mazgch 21:c4d64830bf02 1555 }
mazgch 21:c4d64830bf02 1556 if (!end) return o; // no termination
mazgch 35:9275215a3a5b 1557 // at least any char
mazgch 35:9275215a3a5b 1558 if (++o > len) return WAIT;
mazgch 35:9275215a3a5b 1559 pipe->next();
mazgch 35:9275215a3a5b 1560 // check the end
mazgch 21:c4d64830bf02 1561 int x = 0;
mazgch 21:c4d64830bf02 1562 while (end[x]) {
mazgch 21:c4d64830bf02 1563 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 1564 char ch = pipe->next();
mazgch 21:c4d64830bf02 1565 x = (end[x] == ch) ? x + 1 :
mazgch 21:c4d64830bf02 1566 (end[0] == ch) ? 1 :
mazgch 21:c4d64830bf02 1567 0;
mazgch 21:c4d64830bf02 1568 }
mazgch 21:c4d64830bf02 1569 return o;
mazgch 21:c4d64830bf02 1570 }
mazgch 21:c4d64830bf02 1571
mazgch 21:c4d64830bf02 1572 int MDMParser::_parseFormated(Pipe<char>* pipe, int len, const char* fmt)
mazgch 21:c4d64830bf02 1573 {
mazgch 21:c4d64830bf02 1574 int o = 0;
mazgch 21:c4d64830bf02 1575 int num = 0;
mazgch 21:c4d64830bf02 1576 if (fmt) {
mazgch 21:c4d64830bf02 1577 while (*fmt) {
mazgch 21:c4d64830bf02 1578 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 1579 char ch = pipe->next();
mazgch 21:c4d64830bf02 1580 if (*fmt == '%') {
mazgch 21:c4d64830bf02 1581 fmt++;
mazgch 21:c4d64830bf02 1582 if (*fmt == 'd') { // numeric
mazgch 21:c4d64830bf02 1583 fmt ++;
mazgch 21:c4d64830bf02 1584 num = 0;
mazgch 21:c4d64830bf02 1585 while (ch >= '0' && ch <= '9') {
mazgch 21:c4d64830bf02 1586 num = num * 10 + (ch - '0');
mazgch 21:c4d64830bf02 1587 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 1588 ch = pipe->next();
mazgch 21:c4d64830bf02 1589 }
mazgch 21:c4d64830bf02 1590 }
mazgch 21:c4d64830bf02 1591 else if (*fmt == 'c') { // char buffer (takes last numeric as length)
mazgch 21:c4d64830bf02 1592 fmt ++;
mazgch 21:c4d64830bf02 1593 while (num --) {
mazgch 21:c4d64830bf02 1594 if (++o > len) return WAIT;
mazgch 21:c4d64830bf02 1595 ch = pipe->next();
mazgch 21:c4d64830bf02 1596 }
mazgch 21:c4d64830bf02 1597 }
mazgch 80:34985b4d821e 1598 else if (*fmt == 's') {
mazgch 80:34985b4d821e 1599 fmt ++;
mazgch 80:34985b4d821e 1600 if (ch != '\"') return NOT_FOUND;
mazgch 80:34985b4d821e 1601 do {
mazgch 80:34985b4d821e 1602 if (++o > len) return WAIT;
mazgch 80:34985b4d821e 1603 ch = pipe->next();
mazgch 80:34985b4d821e 1604 } while (ch != '\"');
mazgch 80:34985b4d821e 1605 if (++o > len) return WAIT;
mazgch 80:34985b4d821e 1606 ch = pipe->next();
mazgch 80:34985b4d821e 1607 }
mazgch 21:c4d64830bf02 1608 }
mazgch 21:c4d64830bf02 1609 if (*fmt++ != ch) return NOT_FOUND;
mazgch 18:e5697801df29 1610 }
mazgch 18:e5697801df29 1611 }
mazgch 21:c4d64830bf02 1612 return o;
mazgch 21:c4d64830bf02 1613 }
mazgch 21:c4d64830bf02 1614
mazgch 21:c4d64830bf02 1615 int MDMParser::_getLine(Pipe<char>* pipe, char* buf, int len)
mazgch 21:c4d64830bf02 1616 {
mazgch 21:c4d64830bf02 1617 int unkn = 0;
mazgch 21:c4d64830bf02 1618 int sz = pipe->size();
mazgch 21:c4d64830bf02 1619 int fr = pipe->free();
mazgch 21:c4d64830bf02 1620 if (len > sz)
mazgch 21:c4d64830bf02 1621 len = sz;
mazgch 21:c4d64830bf02 1622 while (len > 0)
mazgch 21:c4d64830bf02 1623 {
mazgch 21:c4d64830bf02 1624 static struct {
mazgch 21:c4d64830bf02 1625 const char* fmt; int type;
mazgch 21:c4d64830bf02 1626 } lutF[] = {
mazgch 21:c4d64830bf02 1627 { "\r\n+USORD: %d,%d,\"%c\"", TYPE_PLUS },
mazgch 95:8282dbbe1492 1628 { "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,\"%c\"", TYPE_PLUS },
mazgch 80:34985b4d821e 1629 { "\r\n+URDFILE: %s,%d,\"%c\"", TYPE_PLUS },
mazgch 21:c4d64830bf02 1630 };
mazgch 21:c4d64830bf02 1631 static struct {
mazgch 21:c4d64830bf02 1632 const char* sta; const char* end; int type;
mazgch 21:c4d64830bf02 1633 } lut[] = {
mazgch 21:c4d64830bf02 1634 { "\r\nOK\r\n", NULL, TYPE_OK },
mazgch 21:c4d64830bf02 1635 { "\r\nERROR\r\n", NULL, TYPE_ERROR },
mazgch 31:a0bed6c1e05d 1636 { "\r\n+CME ERROR:", "\r\n", TYPE_ERROR },
mazgch 21:c4d64830bf02 1637 { "\r\n+CMS ERROR:", "\r\n", TYPE_ERROR },
mazgch 21:c4d64830bf02 1638 { "\r\nRING\r\n", NULL, TYPE_RING },
mazgch 21:c4d64830bf02 1639 { "\r\nCONNECT\r\n", NULL, TYPE_CONNECT },
mazgch 21:c4d64830bf02 1640 { "\r\nNO CARRIER\r\n", NULL, TYPE_NOCARRIER },
mazgch 21:c4d64830bf02 1641 { "\r\nNO DIALTONE\r\n", NULL, TYPE_NODIALTONE },
mazgch 21:c4d64830bf02 1642 { "\r\nBUSY\r\n", NULL, TYPE_BUSY },
mazgch 21:c4d64830bf02 1643 { "\r\nNO ANSWER\r\n", NULL, TYPE_NOANSWER },
mazgch 21:c4d64830bf02 1644 { "\r\n+", "\r\n", TYPE_PLUS },
mazgch 21:c4d64830bf02 1645 { "\r\n@", NULL, TYPE_PROMPT }, // Sockets
mazgch 21:c4d64830bf02 1646 { "\r\n>", NULL, TYPE_PROMPT }, // SMS
mazgch 80:34985b4d821e 1647 { "\n>", NULL, TYPE_PROMPT }, // File
mazgch 21:c4d64830bf02 1648 };
mazgch 21:c4d64830bf02 1649 for (int i = 0; i < sizeof(lutF)/sizeof(*lutF); i ++) {
mazgch 21:c4d64830bf02 1650 pipe->set(unkn);
mazgch 21:c4d64830bf02 1651 int ln = _parseFormated(pipe, len, lutF[i].fmt);
mazgch 21:c4d64830bf02 1652 if (ln == WAIT && fr)
mazgch 21:c4d64830bf02 1653 return WAIT;
mazgch 21:c4d64830bf02 1654 if ((ln != NOT_FOUND) && (unkn > 0))
mazgch 31:a0bed6c1e05d 1655 return TYPE_UNKNOWN | pipe->get(buf, unkn);
mazgch 21:c4d64830bf02 1656 if (ln > 0)
mazgch 21:c4d64830bf02 1657 return lutF[i].type | pipe->get(buf, ln);
mazgch 21:c4d64830bf02 1658 }
mazgch 21:c4d64830bf02 1659 for (int i = 0; i < sizeof(lut)/sizeof(*lut); i ++) {
mazgch 21:c4d64830bf02 1660 pipe->set(unkn);
mazgch 21:c4d64830bf02 1661 int ln = _parseMatch(pipe, len, lut[i].sta, lut[i].end);
mazgch 21:c4d64830bf02 1662 if (ln == WAIT && fr)
mazgch 21:c4d64830bf02 1663 return WAIT;
mazgch 21:c4d64830bf02 1664 if ((ln != NOT_FOUND) && (unkn > 0))
mazgch 31:a0bed6c1e05d 1665 return TYPE_UNKNOWN | pipe->get(buf, unkn);
mazgch 21:c4d64830bf02 1666 if (ln > 0)
mazgch 21:c4d64830bf02 1667 return lut[i].type | pipe->get(buf, ln);
mazgch 21:c4d64830bf02 1668 }
mazgch 21:c4d64830bf02 1669 // UNKNOWN
mazgch 21:c4d64830bf02 1670 unkn ++;
mazgch 21:c4d64830bf02 1671 len--;
mazgch 21:c4d64830bf02 1672 }
mazgch 18:e5697801df29 1673 return WAIT;
mazgch 18:e5697801df29 1674 }
mazgch 18:e5697801df29 1675
mazgch 18:e5697801df29 1676 // ----------------------------------------------------------------
mazgch 18:e5697801df29 1677 // Serial Implementation
mazgch 18:e5697801df29 1678 // ----------------------------------------------------------------
mazgch 18:e5697801df29 1679
mazgch 76:f7c3dd568dae 1680 /*! Helper Dev Null Device
mazgch 76:f7c3dd568dae 1681 Small helper class used to shut off stderr/stdout. Sometimes stdin/stdout
mazgch 76:f7c3dd568dae 1682 is shared with the serial port of the modem. Having printfs inbetween the
mazgch 76:f7c3dd568dae 1683 AT commands you cause a failure of the modem.
mazgch 76:f7c3dd568dae 1684 */
mazgch 76:f7c3dd568dae 1685 class DevNull : public Stream {
mazgch 76:f7c3dd568dae 1686 public:
mazgch 76:f7c3dd568dae 1687 DevNull() : Stream(_name+1) { } //!< Constructor
mazgch 76:f7c3dd568dae 1688 void claim(const char* mode, FILE* file)
mazgch 76:f7c3dd568dae 1689 { freopen(_name, mode, file); } //!< claim a stream
mazgch 76:f7c3dd568dae 1690 protected:
mazgch 76:f7c3dd568dae 1691 virtual int _getc() { return EOF; } //!< Nothing
mazgch 76:f7c3dd568dae 1692 virtual int _putc(int c) { return c; } //!< Discard
mazgch 76:f7c3dd568dae 1693 static const char* _name; //!< File name
mazgch 76:f7c3dd568dae 1694 };
mazgch 76:f7c3dd568dae 1695 const char* DevNull::_name = "/null"; //!< the null device name
mazgch 76:f7c3dd568dae 1696 static DevNull null; //!< the null device
mazgch 76:f7c3dd568dae 1697
mazgch 19:2b5d097ca15d 1698 MDMSerial::MDMSerial(PinName tx /*= MDMTXD*/, PinName rx /*= MDMRXD*/,
mazgch 19:2b5d097ca15d 1699 int baudrate /*= MDMBAUD*/,
mazgch 43:a89a7a505991 1700 #if DEVICE_SERIAL_FC
mazgch 19:2b5d097ca15d 1701 PinName rts /*= MDMRTS*/, PinName cts /*= MDMCTS*/,
mazgch 43:a89a7a505991 1702 #endif
mazgch 18:e5697801df29 1703 int rxSize /*= 256*/, int txSize /*= 128*/) :
mazgch 35:9275215a3a5b 1704 SerialPipe(tx, rx, rxSize, txSize)
mazgch 18:e5697801df29 1705 {
mazgch 76:f7c3dd568dae 1706 if (rx == USBRX)
mazgch 76:f7c3dd568dae 1707 null.claim("r", stdin);
mazgch 76:f7c3dd568dae 1708 if (tx == USBTX) {
mazgch 76:f7c3dd568dae 1709 null.claim("w", stdout);
mazgch 76:f7c3dd568dae 1710 null.claim("w", stderr);
mazgch 74:208e3e32d263 1711 #ifdef MDM_DEBUG
mazgch 76:f7c3dd568dae 1712 _debugLevel = -1;
mazgch 76:f7c3dd568dae 1713 #endif
mazgch 76:f7c3dd568dae 1714 }
mazgch 74:208e3e32d263 1715 #ifdef TARGET_UBLOX_C027
mazgch 74:208e3e32d263 1716 _onboard = (tx == MDMTXD) && (rx == MDMRXD);
mazgch 74:208e3e32d263 1717 if (_onboard)
mazgch 74:208e3e32d263 1718 c027_mdm_powerOn(false);
mazgch 74:208e3e32d263 1719 #endif
mazgch 18:e5697801df29 1720 baud(baudrate);
mazgch 35:9275215a3a5b 1721 #if DEVICE_SERIAL_FC
mazgch 35:9275215a3a5b 1722 if ((rts != NC) || (cts != NC))
mazgch 35:9275215a3a5b 1723 {
mazgch 35:9275215a3a5b 1724 Flow flow = (cts == NC) ? RTS :
mazgch 35:9275215a3a5b 1725 (rts == NC) ? CTS : RTSCTS ;
mazgch 35:9275215a3a5b 1726 set_flow_control(flow, rts, cts);
mazgch 35:9275215a3a5b 1727 if (cts != NC) _dev.lpm = LPM_ENABLED;
mazgch 35:9275215a3a5b 1728 }
mazgch 35:9275215a3a5b 1729 #endif
mazgch 18:e5697801df29 1730 }
mazgch 18:e5697801df29 1731
mazgch 76:f7c3dd568dae 1732 MDMSerial::~MDMSerial(void)
mazgch 76:f7c3dd568dae 1733 {
mazgch 76:f7c3dd568dae 1734 powerOff();
mazgch 76:f7c3dd568dae 1735 #ifdef TARGET_UBLOX_C027
mazgch 76:f7c3dd568dae 1736 if (_onboard)
mazgch 76:f7c3dd568dae 1737 c027_mdm_powerOff();
mazgch 76:f7c3dd568dae 1738 #endif
mazgch 76:f7c3dd568dae 1739 }
mazgch 76:f7c3dd568dae 1740
mazgch 18:e5697801df29 1741 int MDMSerial::_send(const void* buf, int len)
mazgch 18:e5697801df29 1742 {
mazgch 35:9275215a3a5b 1743 return put((const char*)buf, len, true/*=blocking*/);
mazgch 18:e5697801df29 1744 }
mazgch 18:e5697801df29 1745
mazgch 18:e5697801df29 1746 int MDMSerial::getLine(char* buffer, int length)
mazgch 18:e5697801df29 1747 {
mazgch 18:e5697801df29 1748 return _getLine(&_pipeRx, buffer, length);
mazgch 18:e5697801df29 1749 }
mazgch 18:e5697801df29 1750
mazgch 18:e5697801df29 1751 // ----------------------------------------------------------------
mazgch 18:e5697801df29 1752 // USB Implementation
mazgch 18:e5697801df29 1753 // ----------------------------------------------------------------
mazgch 18:e5697801df29 1754
mazgch 18:e5697801df29 1755 #ifdef HAVE_MDMUSB
mazgch 76:f7c3dd568dae 1756 MDMUsb::MDMUsb(void)
mazgch 74:208e3e32d263 1757 {
mazgch 74:208e3e32d263 1758 #ifdef MDM_DEBUG
mazgch 74:208e3e32d263 1759 _debugLevel = 1;
mazgch 74:208e3e32d263 1760 #endif
mazgch 74:208e3e32d263 1761 #ifdef TARGET_UBLOX_C027
mazgch 74:208e3e32d263 1762 _onboard = true;
mazgch 74:208e3e32d263 1763 c027_mdm_powerOn(true);
mazgch 74:208e3e32d263 1764 #endif
mazgch 74:208e3e32d263 1765 }
mazgch 76:f7c3dd568dae 1766
mazgch 76:f7c3dd568dae 1767 MDMUsb::~MDMUsb(void)
mazgch 76:f7c3dd568dae 1768 {
mazgch 76:f7c3dd568dae 1769 powerOff();
mazgch 76:f7c3dd568dae 1770 #ifdef TARGET_UBLOX_C027
mazgch 76:f7c3dd568dae 1771 if (_onboard)
mazgch 76:f7c3dd568dae 1772 c027_mdm_powerOff();
mazgch 76:f7c3dd568dae 1773 #endif
mazgch 76:f7c3dd568dae 1774 }
mazgch 76:f7c3dd568dae 1775
mazgch 76:f7c3dd568dae 1776 int MDMUsb::_send(const void* buf, int len) { return 0; }
mazgch 76:f7c3dd568dae 1777
mazgch 18:e5697801df29 1778 int MDMUsb::getLine(char* buffer, int length) { return NOT_FOUND; }
mazgch 76:f7c3dd568dae 1779
mazgch 35:9275215a3a5b 1780 #endif