Own fork of C027_Support

Dependents:   MbedSmartRestMain MbedSmartRestMain

Fork of C027_Support by u-blox

Committer:
xinlei
Date:
Fri Sep 15 10:12:03 2017 +0000
Revision:
134:d84232916eac
new apns

Who changed what in which revision?

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