Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of C027_Support by
MDM.cpp
00001 #include "mbed.h" 00002 #include "MDM.h" 00003 #ifdef TARGET_UBLOX_C027 00004 #include "C027_api.h" 00005 #endif 00006 #include "MDMAPN.h" 00007 00008 #define PROFILE "0" //!< this is the psd profile used 00009 #define MAX_SIZE 128 //!< max expected messages 00010 // num sockets 00011 #define NUMSOCKETS (sizeof(_sockets)/sizeof(*_sockets)) 00012 //! test if it is a socket is ok to use 00013 #define ISSOCKET(s) (((s) >= 0) && ((s) < NUMSOCKETS) && (_sockets[s].handle != SOCKET_ERROR)) 00014 //! check for timeout 00015 #define TIMEOUT(t, ms) ((ms != TIMEOUT_BLOCKING) && (ms < t.read_ms())) 00016 //! registration ok check helper 00017 #define REG_OK(r) ((r == REG_HOME) || (r == REG_ROAMING)) 00018 //! registration done check helper (no need to poll further) 00019 #define REG_DONE(r) ((r == REG_HOME) || (r == REG_ROAMING) || (r == REG_DENIED)) 00020 //! helper to make sure that lock unlock pair is always balaced 00021 #define LOCK() { lock() 00022 //! helper to make sure that lock unlock pair is always balaced 00023 #define UNLOCK() } unlock() 00024 00025 #ifdef MDM_DEBUG 00026 #if 1 // colored terminal output using ANSI escape sequences 00027 #define COL(c) "\033[" c 00028 #else 00029 #define COL(c) 00030 #endif 00031 #define DEF COL("39m") 00032 #define BLA COL("30m") 00033 #define RED COL("31m") 00034 #define GRE COL("32m") 00035 #define YEL COL("33m") 00036 #define BLU COL("34m") 00037 #define MAG COL("35m") 00038 #define CYA COL("36m") 00039 #define WHY COL("37m") 00040 00041 void dumpAtCmd(const char* buf, int len) 00042 { 00043 ::printf(" %3d \"", len); 00044 while (len --) { 00045 char ch = *buf++; 00046 if ((ch > 0x1F) && (ch != 0x7F)) { // is printable 00047 if (ch == '%') ::printf("%%"); 00048 else if (ch == '"') ::printf("\\\""); 00049 else if (ch == '\\') ::printf("\\\\"); 00050 else putchar(ch); 00051 } else { 00052 if (ch == '\a') ::printf("\\a"); // BEL (0x07) 00053 else if (ch == '\b') ::printf("\\b"); // Backspace (0x08) 00054 else if (ch == '\t') ::printf("\\t"); // Horizontal Tab (0x09) 00055 else if (ch == '\n') ::printf("\\n"); // Linefeed (0x0A) 00056 else if (ch == '\v') ::printf("\\v"); // Vertical Tab (0x0B) 00057 else if (ch == '\f') ::printf("\\f"); // Formfeed (0x0C) 00058 else if (ch == '\r') ::printf("\\r"); // Carriage Return (0x0D) 00059 else ::printf("\\x%02x", (unsigned char)ch); 00060 } 00061 } 00062 ::printf("\"\r\n"); 00063 } 00064 00065 void MDMParser::_debugPrint(int level, const char* color, const char* format, ...) 00066 { 00067 if (_debugLevel >= level) 00068 { 00069 va_list args; 00070 va_start (args, format); 00071 if (color) ::printf(color); 00072 ::vprintf(format, args); 00073 if (color) ::printf(DEF); 00074 va_end (args); 00075 } 00076 } 00077 00078 #define ERROR(...) _debugPrint(0, RED, __VA_ARGS__) 00079 #define INFO(...) _debugPrint(1, GRE, __VA_ARGS__) 00080 #define TRACE(...) _debugPrint(2, DEF, __VA_ARGS__) 00081 #define TEST(...) _debugPrint(3, CYA, __VA_ARGS__) 00082 00083 #else 00084 00085 #define ERROR(...) (void)0 // no tracing 00086 #define TEST(...) (void)0 // no tracing 00087 #define INFO(...) (void)0 // no tracing 00088 #define TRACE(...) (void)0 // no tracing 00089 00090 #endif 00091 00092 MDMParser* MDMParser::inst; 00093 00094 MDMParser::MDMParser(void) 00095 { 00096 inst = this; 00097 memset(&_dev, 0, sizeof(_dev)); 00098 memset(&_net, 0, sizeof(_net)); 00099 _net.lac = 0xFFFF; 00100 _net.ci = 0xFFFFFFFF; 00101 _ip = NOIP; 00102 _init = false; 00103 memset(_sockets, 0, sizeof(_sockets)); 00104 for (int socket = 0; socket < NUMSOCKETS; socket ++) 00105 _sockets[socket].handle = SOCKET_ERROR; 00106 #ifdef MDM_DEBUG 00107 _debugLevel = 1; 00108 _debugTime.start(); 00109 #endif 00110 } 00111 00112 int MDMParser::send(const char* buf, int len) 00113 { 00114 #ifdef MDM_DEBUG 00115 if (_debugLevel >= 3) { 00116 ::printf("%10.3f AT send ", _debugTime.read_ms()*0.001); 00117 dumpAtCmd(buf,len); 00118 } 00119 #endif 00120 return _send(buf, len); 00121 } 00122 00123 int MDMParser::sendFormated(const char* format, ...) { 00124 char buf[MAX_SIZE]; 00125 va_list args; 00126 va_start(args, format); 00127 int len = vsnprintf(buf,sizeof(buf), format, args); 00128 va_end(args); 00129 return send(buf, len); 00130 } 00131 00132 int MDMParser::waitFinalResp(_CALLBACKPTR cb /* = NULL*/, 00133 void* param /* = NULL*/, 00134 int timeout_ms /*= 5000*/) 00135 { 00136 char buf[MAX_SIZE + 64 /* add some more space for framing */]; 00137 Timer timer; 00138 timer.start(); 00139 do { 00140 int ret = getLine(buf, sizeof(buf)); 00141 #ifdef MDM_DEBUG 00142 if ((_debugLevel >= 3) && (ret != WAIT) && (ret != NOT_FOUND)) 00143 { 00144 int len = LENGTH(ret); 00145 int type = TYPE(ret); 00146 const char* s = (type == TYPE_UNKNOWN)? YEL "UNK" DEF : 00147 (type == TYPE_TEXT) ? MAG "TXT" DEF : 00148 (type == TYPE_OK ) ? GRE "OK " DEF : 00149 (type == TYPE_ERROR) ? RED "ERR" DEF : 00150 (type == TYPE_PLUS) ? CYA " + " DEF : 00151 (type == TYPE_PROMPT) ? BLU " > " DEF : 00152 "..." ; 00153 ::printf("%10.3f AT read %s", _debugTime.read_ms()*0.001, s); 00154 dumpAtCmd(buf, len); 00155 } 00156 #endif 00157 if ((ret != WAIT) && (ret != NOT_FOUND)) 00158 { 00159 int type = TYPE(ret); 00160 // handle unsolicited commands here 00161 if (type == TYPE_PLUS) { 00162 const char* cmd = buf+3; 00163 int a, b, c, d, r; 00164 char s[32]; 00165 00166 // SMS Command --------------------------------- 00167 // +CNMI: <mem>,<index> 00168 if (sscanf(cmd, "CMTI: \"%*[^\"]\",%d", &a) == 1) { 00169 TRACE("New SMS at index %d\r\n", a); 00170 // Socket Specific Command --------------------------------- 00171 // +UUSORD: <socket>,<length> 00172 } else if ((sscanf(cmd, "UUSORD: %d,%d", &a, &b) == 2)) { 00173 int socket = _findSocket(a); 00174 TRACE("Socket %d: handle %d has %d bytes pending\r\n", socket, a, b); 00175 if (socket != SOCKET_ERROR) 00176 _sockets[socket].pending = b; 00177 // +UUSORF: <socket>,<length> 00178 } else if ((sscanf(cmd, "UUSORF: %d,%d", &a, &b) == 2)) { 00179 int socket = _findSocket(a); 00180 TRACE("Socket %d: handle %d has %d bytes pending\r\n", socket, a, b); 00181 if (socket != SOCKET_ERROR) 00182 _sockets[socket].pending = b; 00183 // +UUSOCL: <socket> 00184 } else if ((sscanf(cmd, "UUSOCL: %d", &a) == 1)) { 00185 int socket = _findSocket(a); 00186 TRACE("Socket %d: handle %d closed by remote host\r\n", socket, a); 00187 if ((socket != SOCKET_ERROR) && _sockets[socket].connected) 00188 _sockets[socket].connected = false; 00189 } 00190 if (_dev.dev == DEV_LISA_C2) { 00191 // CDMA Specific ------------------------------------------- 00192 // +CREG: <n><SID>,<NID>,<stat> 00193 if (sscanf(cmd, "CREG: %*d,%d,%d,%d",&a,&b,&c) == 3) { 00194 // _net.sid = a; 00195 // _net.nid = b; 00196 if (c == 0) _net.csd = REG_NONE; // not registered, home network 00197 else if (c == 1) _net.csd = REG_HOME; // registered, home network 00198 else if (c == 2) _net.csd = REG_NONE; // not registered, but MT is currently searching a new operator to register to 00199 else if (c == 3) _net.csd = REG_DENIED; // registration denied 00200 else if (c == 5) _net.csd = REG_ROAMING; // registered, roaming 00201 _net.psd = _net.csd; // fake PSD registration (CDMA is always registered) 00202 _net.act = ACT_CDMA; 00203 // +CSS: <mode>[,<format>,<oper>[,<AcT>]] 00204 } else if (sscanf(cmd, "CSS %*c,%2s,%*d",s) == 1) { 00205 //_net.reg = (strcmp("Z", s) == 0) ? REG_UNKNOWN : REG_HOME; 00206 } 00207 } else { 00208 // GSM/UMTS Specific ------------------------------------------- 00209 // +UUPSDD: <profile_id> 00210 if (sscanf(cmd, "UUPSDD: %d",&a) == 1) { 00211 if (*PROFILE == a) _ip = NOIP; 00212 } else { 00213 // +CREG|CGREG: <n>,<stat>[,<lac>,<ci>[,AcT[,<rac>]]] // reply to AT+CREG|AT+CGREG 00214 // +CREG|CGREG: <stat>[,<lac>,<ci>[,AcT[,<rac>]]] // URC 00215 b = 0xFFFF; c = 0xFFFFFFFF; d = -1; 00216 r = sscanf(cmd, "%s %*d,%d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d); 00217 if (r <= 1) 00218 r = sscanf(cmd, "%s %d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d); 00219 if (r >= 2) { 00220 Reg *reg = !strcmp(s, "CREG:") ? &_net.csd : 00221 !strcmp(s, "CGREG:") ? &_net.psd : 00222 !strcmp(s, "CEREG:") ? &_net.eps : NULL; 00223 if (reg) { 00224 // network status 00225 if (a == 0) *reg = REG_NONE; // 0: not registered, home network 00226 else if (a == 1) *reg = REG_HOME; // 1: registered, home network 00227 else if (a == 2) *reg = REG_NONE; // 2: not registered, but MT is currently searching a new operator to register to 00228 else if (a == 3) *reg = REG_DENIED; // 3: registration denied 00229 else if (a == 4) *reg = REG_UNKNOWN; // 4: unknown 00230 else if (a == 5) *reg = REG_ROAMING; // 5: registered, roaming 00231 else if (a == 6) *reg = REG_HOME; // 6: registered, sms only, home 00232 if ((r >= 3) && (b != 0xFFFF)) _net.lac = b; // location area code 00233 if ((r >= 4) && (c != 0xFFFFFFFF)) _net.ci = c; // cell ID 00234 // access technology 00235 if (r >= 5) { 00236 if (d == 0) _net.act = ACT_GSM; // 0: GSM 00237 else if (d == 1) _net.act = ACT_GSM; // 1: GSM COMPACT 00238 else if (d == 2) _net.act = ACT_UTRAN; // 2: UTRAN 00239 else if (d == 3) _net.act = ACT_EDGE; // 3: GSM with EDGE availability 00240 else if (d == 4) _net.act = ACT_UTRAN; // 4: UTRAN with HSDPA availability 00241 else if (d == 5) _net.act = ACT_UTRAN; // 5: UTRAN with HSUPA availability 00242 else if (d == 6) _net.act = ACT_UTRAN; // 6: UTRAN with HSDPA and HSUPA availability 00243 else if (d == 7) _net.act = ACT_LTE; // 7: LTE 00244 } 00245 } 00246 } 00247 } 00248 } 00249 } 00250 if (cb) { 00251 int len = LENGTH(ret); 00252 int ret = cb(type, buf, len, param); 00253 if (WAIT != ret) 00254 return ret; 00255 } 00256 if (type == TYPE_OK) 00257 return RESP_OK; 00258 if (type == TYPE_ERROR) 00259 return RESP_ERROR; 00260 if (type == TYPE_PROMPT) 00261 return RESP_PROMPT; 00262 } 00263 // relax a bit 00264 wait_ms(10); 00265 } 00266 while (!TIMEOUT(timer, timeout_ms)); 00267 return WAIT; 00268 } 00269 00270 int MDMParser::_cbString(int type, const char* buf, int len, char* str) 00271 { 00272 if (str && (type == TYPE_UNKNOWN)) { 00273 if (sscanf(buf, "\r\n%s\r\n", str) == 1) 00274 /*nothing*/; 00275 } 00276 return WAIT; 00277 } 00278 00279 int MDMParser::_cbInt(int type, const char* buf, int len, int* val) 00280 { 00281 if (val && (type == TYPE_UNKNOWN)) { 00282 if (sscanf(buf, "\r\n%d\r\n", val) == 1) 00283 /*nothing*/; 00284 } 00285 return WAIT; 00286 } 00287 00288 // ---------------------------------------------------------------- 00289 00290 bool MDMParser::connect( 00291 const char* simpin, 00292 const char* apn, const char* username, 00293 const char* password, Auth auth, 00294 PinName pn) 00295 { 00296 bool ok = init(simpin, NULL, pn); 00297 #ifdef MDM_DEBUG 00298 if (_debugLevel >= 1) dumpDevStatus(&_dev); 00299 #endif 00300 if (!ok) 00301 return false; 00302 ok = registerNet(); 00303 #ifdef MDM_DEBUG 00304 if (_debugLevel >= 1) dumpNetStatus(&_net); 00305 #endif 00306 if (!ok) 00307 return false; 00308 IP ip = join(apn,username,password,auth); 00309 #ifdef MDM_DEBUG 00310 if (_debugLevel >= 1) dumpIp(ip); 00311 #endif 00312 if (ip == NOIP) 00313 return false; 00314 return true; 00315 } 00316 00317 bool MDMParser::init(const char* simpin, DevStatus* status, PinName pn) 00318 { 00319 int i = 10; 00320 //printf("MDMParser::init LOCK\n"); 00321 LOCK(); 00322 memset(&_dev, 0, sizeof(_dev)); 00323 if (pn != NC) { 00324 INFO("Modem::wakeup\r\n"); 00325 DigitalOut pin(pn, 1); 00326 while (i--) { 00327 // SARA-U2/LISA-U2 50..80us 00328 pin = 0; ::wait_us(50); 00329 pin = 1; ::wait_ms(10); 00330 00331 // SARA-G35 >5ms, LISA-C2 > 150ms, LEON-G2 >5ms 00332 pin = 0; ::wait_ms(150); 00333 pin = 1; ::wait_ms(100); 00334 00335 // purge any messages 00336 purge(); 00337 00338 // check interface 00339 sendFormated("AT\r\n"); 00340 int r = waitFinalResp(NULL,NULL,1000); 00341 if(RESP_OK == r) break; 00342 } 00343 if (i < 0) { 00344 ERROR("No Reply from Modem\r\n"); 00345 goto failure; 00346 } 00347 } 00348 _init = true; 00349 00350 INFO("Modem::init\r\n"); 00351 // echo off 00352 sendFormated("AT E0\r\n"); 00353 if(RESP_OK != waitFinalResp()) 00354 goto failure; 00355 // enable verbose error messages 00356 sendFormated("AT+CMEE=2\r\n"); 00357 if(RESP_OK != waitFinalResp()) 00358 goto failure; 00359 // set baud rate 00360 sendFormated("AT+IPR=115200\r\n"); 00361 if (RESP_OK != waitFinalResp()) 00362 goto failure; 00363 // wait some time until baudrate is applied 00364 wait_ms(200); // SARA-G > 40ms 00365 // identify the module 00366 sendFormated("ATI\r\n"); 00367 if (RESP_OK != waitFinalResp(_cbATI, &_dev.dev)) 00368 goto failure; 00369 if (_dev.dev == DEV_UNKNOWN) 00370 goto failure; 00371 // device specific init 00372 if (_dev.dev == DEV_LISA_C2) { 00373 // get the manufacturer 00374 sendFormated("AT+GMI\r\n"); 00375 if (RESP_OK != waitFinalResp(_cbString, _dev.manu)) 00376 goto failure; 00377 // get the model identification 00378 sendFormated("AT+GMM\r\n"); 00379 if (RESP_OK != waitFinalResp(_cbString, _dev.model)) 00380 goto failure; 00381 // get the sw version 00382 sendFormated("AT+GMR\r\n"); 00383 if (RESP_OK != waitFinalResp(_cbString, _dev.ver)) 00384 goto failure; 00385 // get the pseudo ESN or MEID 00386 sendFormated("AT+GSN\r\n"); 00387 if (RESP_OK != waitFinalResp(_cbString, _dev.meid)) 00388 goto failure; 00389 #if 0 00390 // enable power saving 00391 if (_dev.lpm != LPM_DISABLED) { 00392 // enable power saving (requires flow control, cts at least) 00393 sendFormated("AT+UPSV=1,1280\r\n"); 00394 if (RESP_OK != waitFinalResp()) 00395 goto failure; 00396 _dev.lpm = LPM_ACTIVE; 00397 } 00398 #endif 00399 } else { 00400 if ((_dev.dev == DEV_LISA_U2) || (_dev.dev == DEV_LEON_G2) || 00401 (_dev.dev == DEV_TOBY_L2)) { 00402 // enable the network identification feature 00403 sendFormated("AT+UGPIOC=20,2\r\n"); 00404 if (RESP_OK != waitFinalResp()) 00405 goto failure; 00406 } else if ((_dev.dev == DEV_SARA_U2) || (_dev.dev == DEV_SARA_G35)) { 00407 // enable the network identification feature 00408 sendFormated("AT+UGPIOC=16,2\r\n"); 00409 if (RESP_OK != waitFinalResp()) 00410 goto failure; 00411 } 00412 // check the sim card 00413 for (int i = 0; (i < 5) && (_dev.sim != SIM_READY); i++) { 00414 sendFormated("AT+CPIN?\r\n"); 00415 int ret = waitFinalResp(_cbCPIN, &_dev.sim); 00416 // having an error here is ok (sim may still be initializing) 00417 if ((RESP_OK != ret) && (RESP_ERROR != ret)) 00418 goto failure; 00419 // Enter PIN if needed 00420 if (_dev.sim == SIM_PIN) { 00421 if (!simpin) { 00422 ERROR("SIM PIN not available\r\n"); 00423 goto failure; 00424 } 00425 sendFormated("AT+CPIN=%s\r\n", simpin); 00426 if (RESP_OK != waitFinalResp(_cbCPIN, &_dev.sim)) 00427 goto failure; 00428 } else if (_dev.sim != SIM_READY) { 00429 wait_ms(1000); 00430 } 00431 } 00432 if (_dev.sim != SIM_READY) { 00433 if (_dev.sim == SIM_MISSING) 00434 ERROR("SIM not inserted\r\n"); 00435 goto failure; 00436 } 00437 // get the manufacturer 00438 sendFormated("AT+CGMI\r\n"); 00439 if (RESP_OK != waitFinalResp(_cbString, _dev.manu)) 00440 goto failure; 00441 // get the model identification 00442 sendFormated("AT+CGMM\r\n"); 00443 if (RESP_OK != waitFinalResp(_cbString, _dev.model)) 00444 goto failure; 00445 // get the version 00446 sendFormated("ATI9\r\n"); 00447 if (RESP_OK != waitFinalResp(_cbString, _dev.ver)) 00448 goto failure; 00449 // Returns the ICCID (Integrated Circuit Card ID) of the SIM-card. 00450 // ICCID is a serial number identifying the SIM. 00451 sendFormated("AT+CCID\r\n"); 00452 if (RESP_OK != waitFinalResp(_cbCCID, _dev.ccid)) 00453 goto failure; 00454 // Returns the product serial number, IMEI (International Mobile Equipment Identity) 00455 sendFormated("AT+CGSN\r\n"); 00456 if (RESP_OK != waitFinalResp(_cbString, _dev.imei)) 00457 goto failure; 00458 // enable power saving 00459 if (_dev.lpm != LPM_DISABLED) { 00460 // enable power saving (requires flow control, cts at least) 00461 sendFormated("AT+UPSV=1\r\n"); 00462 if (RESP_OK != waitFinalResp()) 00463 goto failure; 00464 _dev.lpm = LPM_ACTIVE; 00465 } 00466 // enable the psd registration unsolicited result code 00467 sendFormated("AT+CGREG=2\r\n"); 00468 if (RESP_OK != waitFinalResp()) 00469 goto failure; 00470 } 00471 // enable the network registration unsolicited result code 00472 sendFormated("AT+CREG=%d\r\n", (_dev.dev == DEV_LISA_C2) ? 1 : 2); 00473 if (RESP_OK != waitFinalResp()) 00474 goto failure; 00475 // Setup SMS in text mode 00476 sendFormated("AT+CMGF=1\r\n"); 00477 if (RESP_OK != waitFinalResp()) 00478 goto failure; 00479 // setup new message indication 00480 sendFormated("AT+CNMI=2,1\r\n"); 00481 if (RESP_OK != waitFinalResp()) 00482 goto failure; 00483 // Request IMSI (International Mobile Subscriber Identification) 00484 sendFormated("AT+CIMI\r\n"); 00485 if (RESP_OK != waitFinalResp(_cbString, _dev.imsi)) 00486 goto failure; 00487 if (status) 00488 memcpy(status, &_dev, sizeof(DevStatus)); 00489 UNLOCK(); 00490 //printf("MDMParser::init UNLOCK\n"); 00491 return true; 00492 failure: 00493 unlock(); 00494 //printf("MDMParser::init UNLOCK\n"); 00495 return false; 00496 } 00497 00498 bool MDMParser::powerOff(void) 00499 { 00500 bool ok = false; 00501 if (_init) { 00502 //printf("MDMParser::powerOff LOCK\n"); 00503 LOCK(); 00504 INFO("Modem::powerOff\r\n"); 00505 sendFormated("AT+CPWROFF\r\n"); 00506 if (RESP_OK == waitFinalResp(NULL,NULL,120*1000)) { 00507 _init = false; 00508 ok = true; 00509 } 00510 UNLOCK(); 00511 //printf("MDMParser::powerOff UNLOCK\n"); 00512 } 00513 return ok; 00514 } 00515 00516 int MDMParser::_cbATI(int type, const char* buf, int len, Dev* dev) 00517 { 00518 if ((type == TYPE_UNKNOWN) && dev) { 00519 if (strstr(buf, "SARA-G35")) *dev = DEV_SARA_G35; 00520 else if (strstr(buf, "LISA-U2")) *dev = DEV_LISA_U2; 00521 else if (strstr(buf, "LISA-C2")) *dev = DEV_LISA_C2; 00522 else if (strstr(buf, "SARA-U2")) *dev = DEV_SARA_U2; 00523 else if (strstr(buf, "LEON-G2")) *dev = DEV_LEON_G2; 00524 else if (strstr(buf, "TOBY-L2")) *dev = DEV_TOBY_L2; 00525 else if (strstr(buf, "MPCI-L2")) *dev = DEV_MPCI_L2; 00526 } 00527 return WAIT; 00528 } 00529 00530 int MDMParser::_cbCPIN(int type, const char* buf, int len, Sim* sim) 00531 { 00532 if (sim) { 00533 if (type == TYPE_PLUS){ 00534 char s[16]; 00535 if (sscanf(buf, "\r\n+CPIN: %[^\r]\r\n", s) >= 1) 00536 *sim = (0 == strcmp("READY", s)) ? SIM_READY : SIM_PIN; 00537 } else if (type == TYPE_ERROR) { 00538 if (strstr(buf, "+CME ERROR: SIM not inserted")) 00539 *sim = SIM_MISSING; 00540 } 00541 } 00542 return WAIT; 00543 } 00544 00545 int MDMParser::_cbCCID(int type, const char* buf, int len, char* ccid) 00546 { 00547 if ((type == TYPE_PLUS) && ccid){ 00548 if (sscanf(buf, "\r\n+CCID: %[^\r]\r\n", ccid) == 1) 00549 /*TRACE("Got CCID: %s\r\n", ccid)*/; 00550 } 00551 return WAIT; 00552 } 00553 00554 bool MDMParser::registerNet(NetStatus* status /*= NULL*/, int timeout_ms /*= 180000*/) 00555 { 00556 Timer timer; 00557 timer.start(); 00558 INFO("Modem::register\r\n"); 00559 while (!checkNetStatus(status) && !TIMEOUT(timer, timeout_ms)) 00560 wait_ms(1000); 00561 if (_net.csd == REG_DENIED) ERROR("CSD Registration Denied\r\n"); 00562 if (_net.psd == REG_DENIED) ERROR("PSD Registration Denied\r\n"); 00563 if (_net.eps == REG_DENIED) ERROR("EPS Registration Denied\r\n"); 00564 return REG_OK(_net.csd) || REG_OK(_net.psd) || REG_OK(_net.eps); 00565 } 00566 00567 bool MDMParser::checkNetStatus(NetStatus* status /*= NULL*/) 00568 { 00569 bool ok = false; 00570 //printf("MDMParser::checkNetStatus LOCK\n"); 00571 LOCK(); 00572 memset(&_net, 0, sizeof(_net)); 00573 _net.lac = 0xFFFF; 00574 _net.ci = 0xFFFFFFFF; 00575 // check registration 00576 sendFormated("AT+CREG?\r\n"); 00577 waitFinalResp(); // don't fail as service could be not subscribed 00578 if (_dev.dev != DEV_LISA_C2) { 00579 // check PSD registration 00580 sendFormated("AT+CGREG?\r\n"); 00581 waitFinalResp(); // don't fail as service could be not subscribed 00582 if ((_dev.dev == DEV_TOBY_L2) || (_dev.dev == DEV_MPCI_L2)) { 00583 // check EPS network registration 00584 sendFormated("AT+CEREG?\r\n"); 00585 waitFinalResp(); // don't fail as service could be not subscribed 00586 } 00587 } 00588 if (REG_OK(_net.csd) || REG_OK(_net.psd) || REG_OK(_net.eps)) 00589 { 00590 // check modem specific status messages 00591 if (_dev.dev == DEV_LISA_C2) { 00592 sendFormated("AT+CSS?\r\n"); 00593 if (RESP_OK != waitFinalResp()) 00594 goto failure; 00595 while (1) { 00596 // get the Telephone number 00597 sendFormated("AT$MDN?\r\n"); 00598 if (RESP_OK != waitFinalResp(_cbString, _net.num)) 00599 goto failure; 00600 // check if we have a Mobile Directory Number 00601 if (*_net.num && (memcmp(_net.num, "000000", 6) != 0)) 00602 break; 00603 00604 INFO("Device not yet activated\r\n"); 00605 INFO("Make sure you have a valid contract with the network operator for this device.\r\n"); 00606 // Check if the the version contains a V for Verizon 00607 // Verizon: E0.V.xx.00.xxR, 00608 // Sprint E0.S.xx.00.xxR 00609 if (_dev.ver[3] == 'V') { 00610 int i; 00611 INFO("Start device over-the-air activation (this can take a few minutes)\r\n"); 00612 sendFormated("AT+CDV=*22899\r\n"); 00613 i = 1; 00614 if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) { 00615 ERROR("Device over-the-air activation failed\r\n"); 00616 goto failure; 00617 } 00618 INFO("Device over-the-air activation successful\r\n"); 00619 00620 INFO("Start PRL over-the-air update (this can take a few minutes)\r\n"); 00621 sendFormated("AT+CDV=*22891\r\n"); 00622 i = 1; 00623 if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) { 00624 ERROR("PRL over-the-air update failed\r\n"); 00625 goto failure; 00626 } 00627 INFO("PRL over-the-air update successful\r\n"); 00628 00629 } else { 00630 // Sprint or Aeris 00631 INFO("Wait for OMA-DM over-the-air activation (this can take a few minutes)\r\n"); 00632 wait_ms(120*1000); 00633 } 00634 } 00635 // get the the Network access identifier string 00636 char nai[64]; 00637 sendFormated("AT$QCMIPNAI?\r\n"); 00638 if (RESP_OK != waitFinalResp(_cbString, nai)) 00639 goto failure; 00640 } else { 00641 sendFormated("AT+COPS?\r\n"); 00642 if (RESP_OK != waitFinalResp(_cbCOPS, &_net)) 00643 goto failure; 00644 // get the MSISDNs related to this subscriber 00645 sendFormated("AT+CNUM\r\n"); 00646 if (RESP_OK != waitFinalResp(_cbCNUM, _net.num)) 00647 goto failure; 00648 } 00649 // get the signal strength indication 00650 sendFormated("AT+CSQ\r\n"); 00651 if (RESP_OK != waitFinalResp(_cbCSQ, &_net)) 00652 goto failure; 00653 } 00654 if (status) { 00655 memcpy(status, &_net, sizeof(NetStatus)); 00656 } 00657 ok = REG_DONE(_net.csd) && 00658 (REG_DONE(_net.psd) || REG_DONE(_net.eps)); 00659 UNLOCK(); 00660 //printf("MDMParser::checkNetStatus UNLOCK\n"); 00661 return ok; 00662 failure: 00663 unlock(); 00664 return false; 00665 } 00666 00667 int MDMParser::_cbCOPS(int type, const char* buf, int len, NetStatus* status) 00668 { 00669 if ((type == TYPE_PLUS) && status){ 00670 int act = 99; 00671 // +COPS: <mode>[,<format>,<oper>[,<AcT>]] 00672 if (sscanf(buf, "\r\n+COPS: %*d,%*d,\"%[^\"]\",%d",status->opr,&act) >= 1) { 00673 if (act == 0) status->act = ACT_GSM; // 0: GSM, 00674 else if (act == 2) status->act = ACT_UTRAN; // 2: UTRAN 00675 else if (act == 7) status->act = ACT_LTE; // 2: UTRAN 00676 } 00677 } 00678 return WAIT; 00679 } 00680 00681 int MDMParser::_cbCNUM(int type, const char* buf, int len, char* num) 00682 { 00683 if ((type == TYPE_PLUS) && num){ 00684 int a; 00685 if ((sscanf(buf, "\r\n+CNUM: \"My Number\",\"%31[^\"]\",%d", num, &a) == 2) && 00686 ((a == 129) || (a == 145))) { 00687 } 00688 } 00689 return WAIT; 00690 } 00691 00692 int MDMParser::_cbCSQ(int type, const char* buf, int len, NetStatus* status) 00693 { 00694 if ((type == TYPE_PLUS) && status){ 00695 int a,b; 00696 char _ber[] = { 49, 43, 37, 25, 19, 13, 7, 0 }; // see 3GPP TS 45.008 [20] subclause 8.2.4 00697 // +CSQ: <rssi>,<qual> 00698 if (sscanf(buf, "\r\n+CSQ: %d,%d",&a,&b) == 2) { 00699 if (a != 99) status->rssi = -113 + 2*a; // 0: -113 1: -111 ... 30: -53 dBm with 2 dBm steps, 31: >-51 dBm 00700 if ((b != 99) && (b < sizeof(_ber))) status->ber = _ber[b]; // 00701 } 00702 } 00703 return WAIT; 00704 } 00705 00706 00707 int MDMParser::_cbUACTIND(int type, const char* buf, int len, int* i) 00708 { 00709 if ((type == TYPE_PLUS) && i){ 00710 int a; 00711 if (sscanf(buf, "\r\n+UACTIND: %d", &a) == 1) { 00712 *i = a; 00713 } 00714 } 00715 return WAIT; 00716 } 00717 00718 // ---------------------------------------------------------------- 00719 // internet connection 00720 00721 bool MDMParser::_activateProfile(const char* apn, const char* username, const char* password, Auth auth) 00722 { 00723 // Set up the APN 00724 if (*apn) { 00725 sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn); 00726 if (RESP_OK != waitFinalResp()) 00727 return false; 00728 } 00729 if (*username) { 00730 sendFormated("AT+UPSD=" PROFILE ",2,\"%s\"\r\n", username); 00731 if (RESP_OK != waitFinalResp()) 00732 return false; 00733 } 00734 if (*password) { 00735 sendFormated("AT+UPSD=" PROFILE ",3,\"%s\"\r\n", password); 00736 if (RESP_OK != waitFinalResp()) 00737 return false; 00738 } 00739 // Set up the dynamic IP address assignment. 00740 sendFormated("AT+UPSD=" PROFILE ",7,\"0.0.0.0\"\r\n"); 00741 if (RESP_OK != waitFinalResp()) 00742 return false; 00743 // try different Authentication Protocols 00744 // 0 = none 00745 // 1 = PAP (Password Authentication Protocol) 00746 // 2 = CHAP (Challenge Handshake Authentication Protocol) 00747 for (int i = AUTH_NONE; i <= AUTH_CHAP; i ++) { 00748 if ((auth == AUTH_DETECT) || (auth == i)) { 00749 // Set up the Authentication Protocol 00750 sendFormated("AT+UPSD=" PROFILE ",6,%d\r\n",i); 00751 if (RESP_OK != waitFinalResp()) 00752 return false; 00753 // Activate the profile and make connection 00754 sendFormated("AT+UPSDA=" PROFILE ",3\r\n"); 00755 if (RESP_OK == waitFinalResp(NULL,NULL,150*1000)) 00756 return true; 00757 } 00758 } 00759 return false; 00760 } 00761 00762 bool MDMParser::_activateProfileByCid(int cid, const char* apn, const char* username, const char* password, Auth auth) 00763 { 00764 sendFormated("AT+CGDCONT=%d,\"IP\",\"%s\"\r\n", cid, apn); 00765 if (RESP_OK != waitFinalResp()) 00766 return false; 00767 sendFormated("AT+UAUTHREQ=%d,%d,\"%s\",\"%s\"\r\n", cid, auth, username, password); 00768 if (RESP_OK != waitFinalResp()) 00769 return false; 00770 sendFormated("AT+UPSD=" PROFILE ",100,%d\r\n", cid); 00771 if (RESP_OK != waitFinalResp()) 00772 return false; 00773 // Activate the profile and make connection 00774 sendFormated("AT+UPSDA=" PROFILE ",3\r\n"); 00775 return (RESP_OK == waitFinalResp(NULL,NULL,150*1000)); 00776 } 00777 00778 MDMParser::IP MDMParser::join(const char* apn /*= NULL*/, const char* username /*= NULL*/, 00779 const char* password /*= NULL*/, Auth auth /*= AUTH_DETECT*/) 00780 { 00781 //printf("MDMParser::join LOCK\n"); 00782 LOCK(); 00783 INFO("Modem::join\r\n"); 00784 _ip = NOIP; 00785 if (_dev.dev == DEV_LISA_C2) { 00786 // make a dumy dns lookup (which will fail, so ignore the result) 00787 sendFormated("AT+UDNSRN=0,\"u-blox.com\"\r\n"); 00788 waitFinalResp(); 00789 // This fake lookup will enable the IP connection and we 00790 // should have an IP after this, so we check it 00791 00792 //Get local IP address 00793 sendFormated("AT+CMIP?\r\n"); 00794 if (RESP_OK != waitFinalResp(_cbCMIP, &_ip)) 00795 goto failure; 00796 00797 } else { 00798 // check gprs attach status 00799 sendFormated("AT+CGATT=1\r\n"); 00800 if (RESP_OK != waitFinalResp(NULL,NULL,8*60*1000)){ //-- iazi 00801 goto failure; 00802 } 00803 // Check the profile 00804 int a = 0; 00805 bool force = true; 00806 sendFormated("AT+UPSND=" PROFILE ",8\r\n"); 00807 if (RESP_OK != waitFinalResp(_cbUPSND, &a)) 00808 goto failure; 00809 if (a == 1 && force) { 00810 // disconnect the profile already if it is connected 00811 sendFormated("AT+UPSDA=" PROFILE ",4\r\n"); 00812 if (RESP_OK != waitFinalResp(NULL,NULL,40*1000)) 00813 goto failure; 00814 a = 0; 00815 } 00816 if (a == 0) { 00817 bool ok = false; 00818 // try to lookup the apn settings from our local database by mccmnc 00819 const char* config = NULL; 00820 if (!apn && !username && !password) 00821 config = apnconfig(_dev.imsi); 00822 do { 00823 if (config) { 00824 apn = _APN_GET(config); 00825 username = _APN_GET(config); 00826 password = _APN_GET(config); 00827 } 00828 // convert pointer to empty strings 00829 apn = apn ? apn : ""; 00830 username = username ? username : ""; 00831 password = password ? password : ""; 00832 auth = (*username && *password) ? auth : AUTH_NONE; 00833 TRACE("Testing APN Settings(\"%s\",\"%s\",\"%s\",%d)\r\n", apn, username, password, auth); 00834 if ((_dev.dev != DEV_TOBY_L2) && (_dev.dev != DEV_MPCI_L2)) 00835 ok = _activateProfile(apn, username, password, auth); 00836 else 00837 ok = _activateProfileByCid(1, apn, username, password, auth); 00838 } while (!ok && config && *config); // maybe use next setting ? 00839 if (!ok) { 00840 ERROR("Your modem APN/password/username may be wrong\r\n"); 00841 goto failure; 00842 } 00843 } 00844 //Get local IP address 00845 sendFormated("AT+UPSND=" PROFILE ",0\r\n"); 00846 if (RESP_OK != waitFinalResp(_cbUPSND, &_ip)) 00847 goto failure; 00848 } 00849 UNLOCK(); 00850 //printf("MDMParser::join UNLOCK\n"); 00851 return _ip; 00852 failure: 00853 unlock(); 00854 return NOIP; 00855 } 00856 00857 int MDMParser::_cbUDOPN(int type, const char* buf, int len, char* mccmnc) 00858 { 00859 if ((type == TYPE_PLUS) && mccmnc) { 00860 if (sscanf(buf, "\r\n+UDOPN: 0,\"%[^\"]\"", mccmnc) == 1) 00861 ; 00862 } 00863 return WAIT; 00864 } 00865 00866 int MDMParser::_cbCMIP(int type, const char* buf, int len, IP* ip) 00867 { 00868 if ((type == TYPE_UNKNOWN) && ip) { 00869 int a,b,c,d; 00870 if (sscanf(buf, "\r\n" IPSTR, &a,&b,&c,&d) == 4) 00871 *ip = IPADR(a,b,c,d); 00872 } 00873 return WAIT; 00874 } 00875 00876 int MDMParser::_cbUPSND(int type, const char* buf, int len, int* act) 00877 { 00878 if ((type == TYPE_PLUS) && act) { 00879 if (sscanf(buf, "\r\n+UPSND: %*d,%*d,%d", act) == 1) 00880 /*nothing*/; 00881 } 00882 return WAIT; 00883 } 00884 00885 int MDMParser::_cbUPSND(int type, const char* buf, int len, IP* ip) 00886 { 00887 if ((type == TYPE_PLUS) && ip) { 00888 int a,b,c,d; 00889 // +UPSND=<profile_id>,<param_tag>[,<dynamic_param_val>] 00890 if (sscanf(buf, "\r\n+UPSND: " PROFILE ",0,\"" IPSTR "\"", &a,&b,&c,&d) == 4) 00891 *ip = IPADR(a,b,c,d); 00892 } 00893 return WAIT; 00894 } 00895 00896 int MDMParser::_cbUDNSRN(int type, const char* buf, int len, IP* ip) 00897 { 00898 if ((type == TYPE_PLUS) && ip) { 00899 int a,b,c,d; 00900 if (sscanf(buf, "\r\n+UDNSRN: \"" IPSTR "\"", &a,&b,&c,&d) == 4) 00901 *ip = IPADR(a,b,c,d); 00902 } 00903 return WAIT; 00904 } 00905 00906 bool MDMParser::disconnect(void) 00907 { 00908 bool ok = false; 00909 //printf("MDMParser::disconnect LOCK\n"); 00910 LOCK(); 00911 INFO("Modem::disconnect\r\n"); 00912 if (_ip != NOIP) { 00913 if (_dev.dev == DEV_LISA_C2) { 00914 // There something to do here 00915 _ip = NOIP; 00916 ok = true; 00917 } else { 00918 sendFormated("AT+UPSDA=" PROFILE ",4\r\n"); 00919 if (RESP_OK != waitFinalResp()) { 00920 _ip = NOIP; 00921 ok = true; 00922 } 00923 } 00924 } 00925 UNLOCK(); 00926 //printf("MDMParser::disconnect UNLOCK\n"); 00927 return ok; 00928 } 00929 00930 MDMParser::IP MDMParser::gethostbyname(const char* host) 00931 { 00932 IP ip = NOIP; 00933 int a,b,c,d; 00934 if (sscanf(host, IPSTR, &a,&b,&c,&d) == 4) 00935 ip = IPADR(a,b,c,d); 00936 else { 00937 //printf("MDMParser::gethostbyname LOCK\n"); 00938 LOCK(); 00939 sendFormated("AT+UDNSRN=0,\"%s\"\r\n", host); 00940 if (RESP_OK != waitFinalResp(_cbUDNSRN, &ip)) 00941 ip = NOIP; 00942 UNLOCK(); 00943 //printf("MDMParser::gethostbyname UNLOCK\n"); 00944 } 00945 return ip; 00946 } 00947 00948 // ---------------------------------------------------------------- 00949 // sockets 00950 00951 int MDMParser::_cbUSOCR(int type, const char* buf, int len, int* handle) 00952 { 00953 if ((type == TYPE_PLUS) && handle) { 00954 // +USOCR: socket 00955 if (sscanf(buf, "\r\n+USOCR: %d", handle) == 1) 00956 /*nothing*/; 00957 } 00958 return WAIT; 00959 } 00960 00961 int MDMParser::socketSocket(IpProtocol ipproto, int port) 00962 { 00963 int socket; 00964 //printf("MDMParser::socketSocket LOCK\n"); 00965 LOCK(); 00966 // find an free socket 00967 socket = _findSocket(); 00968 TRACE("socketSocket(%d)\r\n", ipproto); 00969 if (socket != SOCKET_ERROR) { 00970 if (ipproto == IPPROTO_UDP) { 00971 // sending port can only be set on 2G/3G modules 00972 if ((port != -1) && (_dev.dev != DEV_LISA_C2)) { 00973 sendFormated("AT+USOCR=17,%d\r\n", port); 00974 } else { 00975 sendFormated("AT+USOCR=17\r\n"); 00976 } 00977 } else /*(ipproto == IPPROTO_TCP)*/ { 00978 sendFormated("AT+USOCR=6\r\n"); 00979 } 00980 int handle = SOCKET_ERROR; 00981 if ((RESP_OK == waitFinalResp(_cbUSOCR, &handle)) && 00982 (handle != SOCKET_ERROR)) { 00983 TRACE("Socket %d: handle %d was created\r\n", socket, handle); 00984 _sockets[socket].handle = handle; 00985 _sockets[socket].timeout_ms = TIMEOUT_BLOCKING; 00986 _sockets[socket].connected = false; 00987 _sockets[socket].pending = 0; 00988 } 00989 else 00990 socket = SOCKET_ERROR; 00991 } 00992 UNLOCK(); 00993 //printf("MDMParser::socketSocket UNLOCK\n"); 00994 return socket; 00995 } 00996 00997 bool MDMParser::socketConnect(int socket, const char * host, int port) 00998 { 00999 IP ip = gethostbyname(host); 01000 if (ip == NOIP) 01001 return false; 01002 // connect to socket 01003 bool ok = false; 01004 //printf("MDMParser::socketConnect LOCK\n"); 01005 LOCK(); 01006 if (ISSOCKET(socket) && (!_sockets[socket].connected)) { 01007 TRACE("socketConnect(%d,%s,%d)\r\n", socket,host,port); 01008 sendFormated("AT+USOCO=%d,\"" IPSTR "\",%d\r\n", _sockets[socket].handle, IPNUM(ip), port); 01009 if (RESP_OK == waitFinalResp()) 01010 ok = _sockets[socket].connected = true; 01011 } 01012 UNLOCK(); 01013 //printf("MDMParser::socketConnect UNLOCK\n"); 01014 return ok; 01015 } 01016 01017 bool MDMParser::socketIsConnected(int socket) 01018 { 01019 bool ok = false; 01020 //printf("MDMParser::socketIsConnected LOCK\n"); 01021 LOCK(); 01022 ok = ISSOCKET(socket) && _sockets[socket].connected; 01023 TRACE("socketIsConnected(%d) %s\r\n", socket, ok?"yes":"no"); 01024 UNLOCK(); 01025 //printf("MDMParser::socketIsConnected UNLOCK\n"); 01026 return ok; 01027 } 01028 01029 bool MDMParser::socketSetBlocking(int socket, int timeout_ms) 01030 { 01031 bool ok = false; 01032 //printf("MDMParser::socketSetBlocking LOCK\n"); 01033 LOCK(); 01034 TRACE("socketSetBlocking(%d,%d)\r\n", socket,timeout_ms); 01035 if (ISSOCKET(socket)) { 01036 _sockets[socket].timeout_ms = timeout_ms; 01037 ok = true; 01038 } 01039 UNLOCK(); 01040 //printf("MDMParser::socketSetBlocking UNLOCK\n"); 01041 return ok; 01042 } 01043 01044 bool MDMParser::socketClose(int socket) 01045 { 01046 bool ok = false; 01047 //printf("MDMParser::socketClose LOCK\n"); 01048 LOCK(); 01049 if (ISSOCKET(socket) && _sockets[socket].connected) { 01050 TRACE("socketClose(%d)\r\n", socket); 01051 sendFormated("AT+USOCL=%d\r\n", _sockets[socket].handle); 01052 if (RESP_OK == waitFinalResp()) { 01053 _sockets[socket].connected = false; 01054 ok = true; 01055 } 01056 } 01057 UNLOCK(); 01058 //printf("MDMParser::socketClose UNLOCK\n"); 01059 return ok; 01060 } 01061 01062 bool MDMParser::socketFree(int socket) 01063 { 01064 // make sure it is closed 01065 socketClose(socket); 01066 bool ok = true; 01067 //printf("MDMParser::socketFree LOCK\n"); 01068 LOCK(); 01069 if (ISSOCKET(socket)) { 01070 TRACE("socketFree(%d)\r\n", socket); 01071 _sockets[socket].handle = SOCKET_ERROR; 01072 _sockets[socket].timeout_ms = TIMEOUT_BLOCKING; 01073 _sockets[socket].connected = false; 01074 _sockets[socket].pending = 0; 01075 ok = true; 01076 } 01077 UNLOCK(); 01078 //printf("MDMParser::socketFree UNLOCK\n"); 01079 return ok; 01080 } 01081 01082 #define USO_MAX_WRITE 1024 //!< maximum number of bytes to write to socket 01083 01084 int MDMParser::socketSend(int socket, const char * buf, int len) 01085 { 01086 TRACE("socketSend(%d,,%d)\r\n", socket,len); 01087 int cnt = len; 01088 while (cnt > 0) { 01089 int blk = USO_MAX_WRITE; 01090 if (cnt < blk) 01091 blk = cnt; 01092 bool ok = false; 01093 //printf("MDMParser::socketSend LOCK\n"); 01094 LOCK(); 01095 if (ISSOCKET(socket)) { 01096 sendFormated("AT+USOWR=%d,%d\r\n",_sockets[socket].handle,blk); 01097 if (RESP_PROMPT == waitFinalResp()) { 01098 wait_ms(50); 01099 send(buf, blk); 01100 if (RESP_OK == waitFinalResp()) 01101 ok = true; 01102 } 01103 } 01104 UNLOCK(); 01105 //printf("MDMParser::socketSend UNLOCK\n"); 01106 if (!ok) 01107 return SOCKET_ERROR; 01108 buf += blk; 01109 cnt -= blk; 01110 } 01111 return (len - cnt); 01112 } 01113 01114 int MDMParser::socketSendTo(int socket, IP ip, int port, const char * buf, int len) 01115 { 01116 printf("socketSendTo(%d," IPSTR ",%d,,%d)\r\n", socket,IPNUM(ip),port,len); 01117 int cnt = len; 01118 while (cnt > 0) { 01119 int blk = USO_MAX_WRITE; 01120 if (cnt < blk) 01121 blk = cnt; 01122 bool ok = false; 01123 //printf("MDMParser::socketSendTo LOCK\n"); 01124 LOCK(); 01125 if (ISSOCKET(socket)) { 01126 sendFormated("AT+USOST=%d,\"" IPSTR "\",%d,%d\r\n",_sockets[socket].handle,IPNUM(ip),port,blk); 01127 if (RESP_PROMPT == waitFinalResp()) { 01128 wait_ms(50); 01129 send(buf, blk); 01130 if (RESP_OK == waitFinalResp()) 01131 ok = true; 01132 } 01133 } 01134 UNLOCK(); 01135 //printf("MDMParser::socketSendTo UNLOCK\n"); 01136 if (!ok) 01137 return SOCKET_ERROR; 01138 buf += blk; 01139 cnt -= blk; 01140 } 01141 return (len - cnt); 01142 } 01143 01144 int MDMParser::socketReadable(int socket) 01145 { 01146 int pending = SOCKET_ERROR; 01147 //printf("MDMParser::socketReadable LOCK\n"); 01148 LOCK(); 01149 if (ISSOCKET(socket) && _sockets[socket].connected) { 01150 TRACE("socketReadable(%d)\r\n", socket); 01151 // allow to receive unsolicited commands 01152 waitFinalResp(NULL, NULL, 0); 01153 if (_sockets[socket].connected) 01154 pending = _sockets[socket].pending; 01155 } 01156 UNLOCK(); 01157 //printf("MDMParser::socketReadable UNLOCK\n"); 01158 return pending; 01159 } 01160 01161 int MDMParser::_cbUSORD(int type, const char* buf, int len, char* out) 01162 { 01163 if ((type == TYPE_PLUS) && out) { 01164 int sz, sk; 01165 if ((sscanf(buf, "\r\n+USORD: %d,%d,", &sk, &sz) == 2) && 01166 (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) { 01167 memcpy(out, &buf[len-1-sz], sz); 01168 } 01169 } 01170 return WAIT; 01171 } 01172 01173 int MDMParser::socketRecv(int socket, char* buf, int len) 01174 { 01175 int cnt = 0; 01176 TRACE("socketRecv(%d,,%d)\r\n", socket, len); 01177 #ifdef MDM_DEBUG 01178 memset(buf, '\0', len); 01179 #endif 01180 Timer timer; 01181 timer.start(); 01182 while (len) { 01183 int blk = MAX_SIZE; // still need space for headers and unsolicited commands 01184 if (len < blk) blk = len; 01185 bool ok = false; 01186 //printf("MDMParser::socketRecv LOCK\n"); 01187 LOCK(); 01188 if (ISSOCKET(socket)) { 01189 if (_sockets[socket].connected) { 01190 if (_sockets[socket].pending < blk) 01191 blk = _sockets[socket].pending; 01192 if (blk > 0) { 01193 sendFormated("AT+USORD=%d,%d\r\n",_sockets[socket].handle, blk); 01194 if (RESP_OK == waitFinalResp(_cbUSORD, buf)) { 01195 _sockets[socket].pending -= blk; 01196 len -= blk; 01197 cnt += blk; 01198 buf += blk; 01199 ok = true; 01200 } 01201 } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) { 01202 ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs 01203 } else { 01204 len = 0; 01205 ok = true; 01206 } 01207 } else { 01208 len = 0; 01209 ok = true; 01210 } 01211 } 01212 UNLOCK(); 01213 //printf("MDMParser::socketRecv UNLOCK\n"); 01214 if (!ok) { 01215 TRACE("socketRecv: ERROR\r\n"); 01216 return SOCKET_ERROR; 01217 } 01218 } 01219 TRACE("socketRecv: %d \"%*s\"\r\n", cnt, cnt, buf-cnt); 01220 return cnt; 01221 } 01222 01223 int MDMParser::_cbUSORF(int type, const char* buf, int len, USORFparam* param) 01224 { 01225 if ((type == TYPE_PLUS) && param) { 01226 int sz, sk, p, a,b,c,d; 01227 int r = sscanf(buf, "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,", 01228 &sk,&a,&b,&c,&d,&p,&sz); 01229 if ((r == 7) && (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) { 01230 memcpy(param->buf, &buf[len-1-sz], sz); 01231 param->ip = IPADR(a,b,c,d); 01232 param->port = p; 01233 } 01234 } 01235 return WAIT; 01236 } 01237 01238 int MDMParser::socketRecvFrom(int socket, IP* ip, int* port, char* buf, int len) 01239 { 01240 int cnt = 0; 01241 TRACE("socketRecvFrom(%d,,%d)\r\n", socket, len); 01242 #ifdef MDM_DEBUG 01243 memset(buf, '\0', len); 01244 #endif 01245 Timer timer; 01246 timer.start(); 01247 while (len) { 01248 int blk = MAX_SIZE; // still need space for headers and unsolicited commands 01249 if (len < blk) blk = len; 01250 bool ok = false; 01251 //printf("MDMParser::socketRecvFrom LOCK\n"); 01252 LOCK(); 01253 if (ISSOCKET(socket)) { 01254 if (_sockets[socket].pending < blk) 01255 blk = _sockets[socket].pending; 01256 if (blk > 0) { 01257 sendFormated("AT+USORF=%d,%d\r\n",_sockets[socket].handle, blk); 01258 USORFparam param; 01259 param.buf = buf; 01260 if (RESP_OK == waitFinalResp(_cbUSORF, ¶m)) { 01261 _sockets[socket].pending -= blk; 01262 *ip = param.ip; 01263 *port = param.port; 01264 len -= blk; 01265 cnt += blk; 01266 buf += blk; 01267 len = 0; // done 01268 ok = true; 01269 } 01270 } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) { 01271 ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs 01272 } else { 01273 len = 0; // no more data and socket closed or timed-out 01274 ok = true; 01275 } 01276 } 01277 UNLOCK(); 01278 //printf("MDMParser::socketRecvFrom UNLOCK\n"); 01279 if (!ok) { 01280 TRACE("socketRecv: ERROR\r\n"); 01281 return SOCKET_ERROR; 01282 } 01283 } 01284 timer.stop(); 01285 timer.reset(); 01286 TRACE("socketRecv: %d \"%*s\"\r\n", cnt, cnt, buf-cnt); 01287 return cnt; 01288 } 01289 01290 int MDMParser::_findSocket(int handle) { 01291 for (int socket = 0; socket < NUMSOCKETS; socket ++) { 01292 if (_sockets[socket].handle == handle) 01293 return socket; 01294 } 01295 return SOCKET_ERROR; 01296 } 01297 01298 // ---------------------------------------------------------------- 01299 01300 int MDMParser::_cbCMGL(int type, const char* buf, int len, CMGLparam* param) 01301 { 01302 if ((type == TYPE_PLUS) && param && param->num) { 01303 // +CMGL: <ix>,... 01304 int ix; 01305 if (sscanf(buf, "\r\n+CMGL: %d,", &ix) == 1) 01306 { 01307 *param->ix++ = ix; 01308 param->num--; 01309 } 01310 } 01311 return WAIT; 01312 } 01313 01314 int MDMParser::smsList(const char* stat /*= "ALL"*/, int* ix /*=NULL*/, int num /*= 0*/) { 01315 int ret = -1; 01316 //printf("MDMParser::smsList LOCK\n"); 01317 LOCK(); 01318 sendFormated("AT+CMGL=\"%s\"\r\n", stat); 01319 CMGLparam param; 01320 param.ix = ix; 01321 param.num = num; 01322 if (RESP_OK == waitFinalResp(_cbCMGL, ¶m)) 01323 ret = num - param.num; 01324 UNLOCK(); 01325 //printf("MDMParser::smsList UNLOCK\n"); 01326 return ret; 01327 } 01328 01329 bool MDMParser::smsSend(const char* num, const char* buf) 01330 { 01331 bool ok = false; 01332 //printf("MDMParser::smsSend LOCK\n"); 01333 LOCK(); 01334 sendFormated("AT+CMGS=\"%s\"\r\n",num); 01335 if (RESP_PROMPT == waitFinalResp(NULL,NULL,150*1000)) { 01336 send(buf, strlen(buf)); 01337 const char ctrlZ = 0x1A; 01338 send(&ctrlZ, sizeof(ctrlZ)); 01339 ok = (RESP_OK == waitFinalResp()); 01340 } 01341 UNLOCK(); 01342 //printf("MDMParser::smsSend UNLOCK\n"); 01343 return ok; 01344 } 01345 01346 bool MDMParser::smsDelete(int ix) 01347 { 01348 bool ok = false; 01349 //printf("MDMParser::smsDelete LOCK\n"); 01350 LOCK(); 01351 sendFormated("AT+CMGD=%d\r\n",ix); 01352 ok = (RESP_OK == waitFinalResp()); 01353 UNLOCK(); 01354 //printf("MDMParser::smsDelete UNLOCK\n"); 01355 return ok; 01356 } 01357 01358 int MDMParser::_cbCMGR(int type, const char* buf, int len, CMGRparam* param) 01359 { 01360 if (param) { 01361 if (type == TYPE_PLUS) { 01362 if (sscanf(buf, "\r\n+CMGR: \"%*[^\"]\",\"%[^\"]", param->num) == 1) { 01363 } 01364 } else if ((type == TYPE_UNKNOWN) && (buf[len-2] == '\r') && (buf[len-1] == '\n')) { 01365 memcpy(param->buf, buf, len-2); 01366 param->buf[len-2] = '\0'; 01367 } 01368 } 01369 return WAIT; 01370 } 01371 01372 bool MDMParser::smsRead(int ix, char* num, char* buf, int len) 01373 { 01374 bool ok = false; 01375 //printf("MDMParser::smsRead LOCK\n"); 01376 LOCK(); 01377 CMGRparam param; 01378 param.num = num; 01379 param.buf = buf; 01380 sendFormated("AT+CMGR=%d\r\n",ix); 01381 ok = (RESP_OK == waitFinalResp(_cbCMGR, ¶m)); 01382 UNLOCK(); 01383 //printf("MDMParser::smsRead UNLOCK\n"); 01384 return ok; 01385 } 01386 01387 // ---------------------------------------------------------------- 01388 01389 int MDMParser::_cbCUSD(int type, const char* buf, int len, char* resp) 01390 { 01391 if ((type == TYPE_PLUS) && resp) { 01392 // +USD: \"%*[^\"]\",\"%[^\"]\",,\"%*[^\"]\",%d,%d,%d,%d,\"*[^\"]\",%d,%d"..); 01393 if (sscanf(buf, "\r\n+CUSD: %*d,\"%[^\"]\",%*d", resp) == 1) { 01394 /*nothing*/ 01395 } 01396 } 01397 return WAIT; 01398 } 01399 01400 bool MDMParser::ussdCommand(const char* cmd, char* buf) 01401 { 01402 bool ok = false; 01403 //printf("MDMParser::ussdCommand LOCK\n"); 01404 LOCK(); 01405 *buf = '\0'; 01406 if (_dev.dev != DEV_LISA_C2) { 01407 sendFormated("AT+CUSD=1,\"%s\"\r\n",cmd); 01408 ok = (RESP_OK == waitFinalResp(_cbCUSD, buf)); 01409 } 01410 UNLOCK(); 01411 //printf("MDMParser::ussdCommand UNLOCK\n"); 01412 return ok; 01413 } 01414 01415 // ---------------------------------------------------------------- 01416 01417 int MDMParser::_cbUDELFILE(int type, const char* buf, int len, void*) 01418 { 01419 if ((type == TYPE_ERROR) && strstr(buf, "+CME ERROR: FILE NOT FOUND")) 01420 return RESP_OK; // file does not exist, so all ok... 01421 return WAIT; 01422 } 01423 01424 bool MDMParser::delFile(const char* filename) 01425 { 01426 bool ok = false; 01427 //printf("MDMParser::delFile LOCK\n"); 01428 LOCK(); 01429 sendFormated("AT+UDELFILE=\"%s\"\r\n", filename); 01430 ok = (RESP_OK == waitFinalResp(_cbUDELFILE)); 01431 UNLOCK(); 01432 //printf("MDMParser::delFile UNLOCK\n"); 01433 return ok; 01434 } 01435 01436 int MDMParser::writeFile(const char* filename, const char* buf, int len) 01437 { 01438 bool ok = false; 01439 //printf("MDMParser::writeFile LOCK\n"); 01440 LOCK(); 01441 sendFormated("AT+UDWNFILE=\"%s\",%d\r\n", filename, len); 01442 if (RESP_PROMPT == waitFinalResp()) { 01443 send(buf, len); 01444 ok = (RESP_OK == waitFinalResp()); 01445 } 01446 UNLOCK(); 01447 //printf("MDMParser::writeFile UNLOCK\n"); 01448 return ok ? len : -1; 01449 } 01450 01451 int MDMParser::readFile(const char* filename, char* buf, int len) 01452 { 01453 URDFILEparam param; 01454 param.filename = filename; 01455 param.buf = buf; 01456 param.sz = len; 01457 param.len = 0; 01458 //printf("MDMParser::readFile LOCK\n"); 01459 LOCK(); 01460 sendFormated("AT+URDFILE=\"%s\"\r\n", filename, len); 01461 if (RESP_OK != waitFinalResp(_cbURDFILE, ¶m)) 01462 param.len = -1; 01463 UNLOCK(); 01464 return param.len; 01465 } 01466 01467 int MDMParser::_cbURDFILE(int type, const char* buf, int len, URDFILEparam* param) 01468 { 01469 if ((type == TYPE_PLUS) && param && param->filename && param->buf) { 01470 char filename[48]; 01471 int sz; 01472 if ((sscanf(buf, "\r\n+URDFILE: \"%[^\"]\",%d,", filename, &sz) == 2) && 01473 (0 == strcmp(param->filename, filename)) && 01474 (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) { 01475 param->len = (sz < param->sz) ? sz : param->sz; 01476 memcpy(param->buf, &buf[len-1-sz], param->len); 01477 } 01478 } 01479 return WAIT; 01480 } 01481 01482 // ---------------------------------------------------------------- 01483 bool MDMParser::setDebug (int level) 01484 { 01485 #ifdef MDM_DEBUG 01486 _debugLevel = (level < -1) ? -1 : 01487 (level > 3) ? 3 : 01488 level; 01489 #endif 01490 return _debugLevel == level; 01491 } 01492 01493 void MDMParser::dumpDevStatus(MDMParser::DevStatus* status, 01494 _DPRINT dprint, void* param) 01495 { 01496 dprint(param, "Modem::devStatus\r\n"); 01497 const char* txtDev[] = { "Unknown", "SARA-G35", "LISA-U2", "LISA-C2", 01498 "SARA-U2", "LEON-G2", "TOBY-L2", "MPCI-L2" }; 01499 if (status->dev < sizeof(txtDev)/sizeof(*txtDev) && (status->dev != DEV_UNKNOWN)) 01500 dprint(param, " Device: %s\r\n", txtDev[status->dev]); 01501 const char* txtLpm[] = { "Disabled", "Enabled", "Active" }; 01502 if (status->lpm < sizeof(txtLpm)/sizeof(*txtLpm)) 01503 dprint(param, " Power Save: %s\r\n", txtLpm[status->lpm]); 01504 const char* txtSim[] = { "Unknown", "Missing", "Pin", "Ready" }; 01505 if (status->sim < sizeof(txtSim)/sizeof(*txtSim) && (status->sim != SIM_UNKNOWN)) 01506 dprint(param, " SIM: %s\r\n", txtSim[status->sim]); 01507 if (*status->ccid) 01508 dprint(param, " CCID: %s\r\n", status->ccid); 01509 if (*status->imei) 01510 dprint(param, " IMEI: %s\r\n", status->imei); 01511 if (*status->imsi) 01512 dprint(param, " IMSI: %s\r\n", status->imsi); 01513 if (*status->meid) 01514 dprint(param, " MEID: %s\r\n", status->meid); // LISA-C 01515 if (*status->manu) 01516 dprint(param, " Manufacturer: %s\r\n", status->manu); 01517 if (*status->model) 01518 dprint(param, " Model: %s\r\n", status->model); 01519 if (*status->ver) 01520 dprint(param, " Version: %s\r\n", status->ver); 01521 } 01522 01523 void MDMParser::dumpNetStatus(MDMParser::NetStatus *status, 01524 _DPRINT dprint, void* param) 01525 { 01526 dprint(param, "Modem::netStatus\r\n"); 01527 const char* txtReg[] = { "Unknown", "Denied", "None", "Home", "Roaming" }; 01528 if (status->csd < sizeof(txtReg)/sizeof(*txtReg) && (status->csd != REG_UNKNOWN)) 01529 dprint(param, " CSD Registration: %s\r\n", txtReg[status->csd]); 01530 if (status->psd < sizeof(txtReg)/sizeof(*txtReg) && (status->psd != REG_UNKNOWN)) 01531 dprint(param, " PSD Registration: %s\r\n", txtReg[status->psd]); 01532 if (status->eps < sizeof(txtReg)/sizeof(*txtReg) && (status->eps != REG_UNKNOWN)) 01533 dprint(param, " EPS Registration: %s\r\n", txtReg[status->eps]); 01534 const char* txtAct[] = { "Unknown", "GSM", "Edge", "3G", "CDMA", "LTE" }; 01535 if (status->act < sizeof(txtAct)/sizeof(*txtAct) && (status->act != ACT_UNKNOWN)) 01536 dprint(param, " Access Technology: %s\r\n", txtAct[status->act]); 01537 if (status->rssi) 01538 dprint(param, " Signal Strength: %d dBm\r\n", status->rssi); 01539 if (status->ber) 01540 dprint(param, " Bit Error Rate: %d\r\n", status->ber); 01541 if (*status->opr) 01542 dprint(param, " Operator: %s\r\n", status->opr); 01543 if (status->lac != 0xFFFF) 01544 dprint(param, " Location Area Code: %04X\r\n", status->lac); 01545 if (status->ci != 0xFFFFFFFF) 01546 dprint(param, " Cell ID: %08X\r\n", status->ci); 01547 if (*status->num) 01548 dprint(param, " Phone Number: %s\r\n", status->num); 01549 } 01550 01551 void MDMParser::dumpIp(MDMParser::IP ip, 01552 _DPRINT dprint, void* param) 01553 { 01554 if (ip != NOIP) 01555 dprint(param, "Modem:IP " IPSTR "\r\n", IPNUM(ip)); 01556 } 01557 01558 // ---------------------------------------------------------------- 01559 int MDMParser::_parseMatch(Pipe<char> * pipe, int len, const char* sta, const char* end) 01560 { 01561 int o = 0; 01562 if (sta) { 01563 while (*sta) { 01564 if (++o > len) return WAIT; 01565 char ch = pipe->next(); 01566 if (*sta++ != ch) return NOT_FOUND; 01567 } 01568 } 01569 if (!end) return o; // no termination 01570 // at least any char 01571 if (++o > len) return WAIT; 01572 pipe->next(); 01573 // check the end 01574 int x = 0; 01575 while (end[x]) { 01576 if (++o > len) return WAIT; 01577 char ch = pipe->next(); 01578 x = (end[x] == ch) ? x + 1 : 01579 (end[0] == ch) ? 1 : 01580 0; 01581 } 01582 return o; 01583 } 01584 01585 int MDMParser::_parseFormated(Pipe<char> * pipe, int len, const char* fmt) 01586 { 01587 int o = 0; 01588 int num = 0; 01589 if (fmt) { 01590 while (*fmt) { 01591 if (++o > len) return WAIT; 01592 char ch = pipe->next(); 01593 if (*fmt == '%') { 01594 fmt++; 01595 if (*fmt == 'd') { // numeric 01596 fmt ++; 01597 num = 0; 01598 while (ch >= '0' && ch <= '9') { 01599 num = num * 10 + (ch - '0'); 01600 if (++o > len) return WAIT; 01601 ch = pipe->next(); 01602 } 01603 } 01604 else if (*fmt == 'c') { // char buffer (takes last numeric as length) 01605 fmt ++; 01606 while (num --) { 01607 if (++o > len) return WAIT; 01608 ch = pipe->next(); 01609 } 01610 } 01611 else if (*fmt == 's') { 01612 fmt ++; 01613 if (ch != '\"') return NOT_FOUND; 01614 do { 01615 if (++o > len) return WAIT; 01616 ch = pipe->next(); 01617 } while (ch != '\"'); 01618 if (++o > len) return WAIT; 01619 ch = pipe->next(); 01620 } 01621 } 01622 if (*fmt++ != ch) return NOT_FOUND; 01623 } 01624 } 01625 return o; 01626 } 01627 01628 int MDMParser::_getLine(Pipe<char> * pipe, char* buf, int len) 01629 { 01630 int unkn = 0; 01631 int sz = pipe->size(); 01632 int fr = pipe->free(); 01633 if (len > sz) 01634 len = sz; 01635 while (len > 0) 01636 { 01637 static struct { 01638 const char* fmt; int type; 01639 } lutF[] = { 01640 { "\r\n+USORD: %d,%d,\"%c\"", TYPE_PLUS }, 01641 { "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,\"%c\"", TYPE_PLUS }, 01642 { "\r\n+URDFILE: %s,%d,\"%c\"", TYPE_PLUS }, 01643 }; 01644 static struct { 01645 const char* sta; const char* end; int type; 01646 } lut[] = { 01647 { "\r\nOK\r\n", NULL, TYPE_OK }, 01648 { "\r\nERROR\r\n", NULL, TYPE_ERROR }, 01649 { "\r\n+CME ERROR:", "\r\n", TYPE_ERROR }, 01650 { "\r\n+CMS ERROR:", "\r\n", TYPE_ERROR }, 01651 { "\r\nRING\r\n", NULL, TYPE_RING }, 01652 { "\r\nCONNECT\r\n", NULL, TYPE_CONNECT }, 01653 { "\r\nNO CARRIER\r\n", NULL, TYPE_NOCARRIER }, 01654 { "\r\nNO DIALTONE\r\n", NULL, TYPE_NODIALTONE }, 01655 { "\r\nBUSY\r\n", NULL, TYPE_BUSY }, 01656 { "\r\nNO ANSWER\r\n", NULL, TYPE_NOANSWER }, 01657 { "\r\n+", "\r\n", TYPE_PLUS }, 01658 { "\r\n@", NULL, TYPE_PROMPT }, // Sockets 01659 { "\r\n>", NULL, TYPE_PROMPT }, // SMS 01660 { "\n>", NULL, TYPE_PROMPT }, // File 01661 }; 01662 for (int i = 0; i < sizeof(lutF)/sizeof(*lutF); i ++) { 01663 pipe->set(unkn); 01664 int ln = _parseFormated(pipe, len, lutF[i].fmt); 01665 if (ln == WAIT && fr) 01666 return WAIT; 01667 if ((ln != NOT_FOUND) && (unkn > 0)) 01668 return TYPE_UNKNOWN | pipe->get (buf, unkn); 01669 if (ln > 0) 01670 return lutF[i].type | pipe->get (buf, ln); 01671 } 01672 for (int i = 0; i < sizeof(lut)/sizeof(*lut); i ++) { 01673 pipe->set(unkn); 01674 int ln = _parseMatch(pipe, len, lut[i].sta, lut[i].end); 01675 if (ln == WAIT && fr) 01676 return WAIT; 01677 if ((ln != NOT_FOUND) && (unkn > 0)) 01678 return TYPE_UNKNOWN | pipe->get (buf, unkn); 01679 if (ln > 0) 01680 return lut[i].type | pipe->get (buf, ln); 01681 } 01682 // UNKNOWN 01683 unkn ++; 01684 len--; 01685 } 01686 return WAIT; 01687 } 01688 01689 // ---------------------------------------------------------------- 01690 // Serial Implementation 01691 // ---------------------------------------------------------------- 01692 01693 /*! Helper Dev Null Device 01694 Small helper class used to shut off stderr/stdout. Sometimes stdin/stdout 01695 is shared with the serial port of the modem. Having printfs inbetween the 01696 AT commands you cause a failure of the modem. 01697 */ 01698 class DevNull : public Stream { 01699 public: 01700 DevNull() : Stream(_name+1) { } //!< Constructor 01701 void claim(const char* mode, FILE* file) 01702 { freopen(_name, mode, file); } //!< claim a stream 01703 protected: 01704 virtual int _getc() { return EOF; } //!< Nothing 01705 virtual int _putc(int c) { return c; } //!< Discard 01706 static const char* _name; //!< File name 01707 }; 01708 const char* DevNull::_name = "/null"; //!< the null device name 01709 static DevNull null; //!< the null device 01710 01711 MDMSerial::MDMSerial(PinName tx /*= MDMTXD*/, PinName rx /*= MDMRXD*/, 01712 int baudrate /*= MDMBAUD*/, 01713 #if DEVICE_SERIAL_FC 01714 PinName rts /*= MDMRTS*/, PinName cts /*= MDMCTS*/, 01715 #endif 01716 int rxSize /*= 256*/, int txSize /*= 128*/) : 01717 SerialPipe(tx, rx, rxSize, txSize) 01718 { 01719 if (rx == USBRX) 01720 null.claim("r", stdin); 01721 if (tx == USBTX) { 01722 null.claim("w", stdout); 01723 null.claim("w", stderr); 01724 #ifdef MDM_DEBUG 01725 _debugLevel = -1; 01726 #endif 01727 } 01728 #ifdef TARGET_UBLOX_C027 01729 _onboard = (tx == MDMTXD) && (rx == MDMRXD); 01730 if (_onboard) 01731 c027_mdm_powerOn(false); 01732 #endif 01733 baud(baudrate); 01734 #if DEVICE_SERIAL_FC 01735 if ((rts != NC) || (cts != NC)) 01736 { 01737 Flow flow = (cts == NC) ? RTS : 01738 (rts == NC) ? CTS : RTSCTS ; 01739 set_flow_control(flow, rts, cts); 01740 if (cts != NC) _dev.lpm = LPM_ENABLED; 01741 } 01742 #endif 01743 } 01744 01745 MDMSerial::~MDMSerial(void) 01746 { 01747 powerOff(); 01748 #ifdef TARGET_UBLOX_C027 01749 if (_onboard) 01750 c027_mdm_powerOff(); 01751 #endif 01752 } 01753 01754 int MDMSerial::_send(const void* buf, int len) 01755 { 01756 return put((const char*)buf, len, true/*=blocking*/); 01757 } 01758 01759 int MDMSerial::getLine(char* buffer, int length) 01760 { 01761 return _getLine(&_pipeRx, buffer, length); 01762 } 01763 01764 // ---------------------------------------------------------------- 01765 // USB Implementation 01766 // ---------------------------------------------------------------- 01767 01768 #ifdef HAVE_MDMUSB 01769 MDMUsb::MDMUsb(void) 01770 { 01771 #ifdef MDM_DEBUG 01772 _debugLevel = 1; 01773 #endif 01774 #ifdef TARGET_UBLOX_C027 01775 _onboard = true; 01776 c027_mdm_powerOn(true); 01777 #endif 01778 } 01779 01780 MDMUsb::~MDMUsb(void) 01781 { 01782 powerOff(); 01783 #ifdef TARGET_UBLOX_C027 01784 if (_onboard) 01785 c027_mdm_powerOff(); 01786 #endif 01787 } 01788 01789 int MDMUsb::_send(const void* buf, int len) { return 0; } 01790 01791 int MDMUsb::getLine(char* buffer, int length) { return NOT_FOUND; } 01792 01793 #endif
Generated on Mon Jul 18 2022 11:00:33 by
1.7.2
