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:
Wed May 28 07:14:21 2014 +0000
Revision:
82:055dcfcf9dcc
Parent:
81:3966a5c17037
Child:
84:a05edb010176
more safe

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