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 05:42:10 2014 +0000
Revision:
99:3116d3e900ed
Parent:
98:c786461edd40
Child:
101:edfeb8af206e
fixed the early abort of the APN settings test loop

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