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 06 07:51:23 2014 +0000
Revision:
85:dd8f4f0d0ca9
Parent:
84:a05edb010176
Child:
88:135fb4bb7aac
adding simple apn lookup table ... that can be to be extended for other networks

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