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:
Fri Jun 06 10:33:13 2014 +0000
Revision:
88:135fb4bb7aac
Parent:
85:dd8f4f0d0ca9
Child:
90:3915192f6d7e
improve apn lookup

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