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:
Tue Jul 01 06:41:26 2014 +0000
Revision:
101:edfeb8af206e
Parent:
99:3116d3e900ed
Child:
102:fb982ff9da82
improve purge at wakeup

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