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

Dependents:   HTTPClient_Cellular_HelloWorld Cellular_HelloMQTT MbedSmartRestMain Car_Bon_car_module ... more

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

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

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

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

Committer:
mazgch
Date:
Mon Dec 15 08:33:54 2014 +0000
Revision:
115:d8d94b73c725
Parent:
112:89b5b21db71e
Child:
117:74e4e0109a9e
delete to a non-existing file returns true now

Who changed what in which revision?

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