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:
Fri Jun 20 12:07:09 2014 +0000
Revision:
96:2aa03444fee3
Parent:
95:8282dbbe1492
Child:
98:c786461edd40
added china apn settings to LUT

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