support library for C027 helper functions for Buffer Pipes, Buffered Serial Port (rtos capable) and GPS parsing. It includes modem APIs for USSD, SMS and Sockets.

Dependents:   HTTPClient_Cellular_HelloWorld Cellular_HelloMQTT MbedSmartRestMain Car_Bon_car_module ... more

This library is intended to be used with u-blox products such as the C027 or a shield with u-blox cellular and GPS modules like the cellular and positioning shield from Embedded Artist.

For 2G/GSM and 3G/UMTS you need to:

  • have a SIM card and know its PIN number
  • need to know you network operators APN setting These setting should be passed to the connect or init and join functions. You can also extend the APN database in MDMAPN.h.

For CDMA products you need to make sure that you have provisioned and activated the modem with either Sprint or Verizon.

Committer:
mazgch
Date:
Mon Sep 15 11:51:49 2014 +0000
Revision:
108:254bf037f83f
Parent:
106:18aeacdae391
Child:
109:327d209a8ab9
better parsing

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