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