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:
Thu Aug 20 08:07:37 2015 +0000
Revision:
124:65eb7d58f2da
Parent:
123:66cef6353b13
Child:
125:25a292afbac6
updated toby handling

Who changed what in which revision?

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