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