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