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:
Mon May 26 11:55:16 2014 +0000
Revision:
79:291df065e345
Parent:
78:caf0014375cb
Child:
80:34985b4d821e
added different Authentication protocols handle gprs registration

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