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 Jul 03 21:00:22 2014 +0000
Revision:
103:197fa7920ad8
Parent:
102:fb982ff9da82
Child:
104:c64ba749a422
do not use socket handle from modem as index directly

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