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 Mar 12 17:27:42 2015 +0000
Revision:
121:8da935c2c08c
Parent:
117:74e4e0109a9e
Child:
122:5f6804915d77
comments

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