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.
MDM.cpp
00001 #include "mbed.h" 00002 #include "MDM.h" 00003 #ifdef TARGET_UBLOX_C027 00004 #include "C027_api.h" 00005 #endif 00006 #include "MDMAPN.h" 00007 00008 #define PROFILE "0" //!< this is the psd profile used 00009 #define MAX_SIZE 128 //!< max expected messages 00010 // num sockets 00011 #define NUMSOCKETS (sizeof(_sockets)/sizeof(*_sockets)) 00012 //! test if it is a socket is ok to use 00013 #define ISSOCKET(s) (((s) >= 0) && ((s) < NUMSOCKETS) && (_sockets[s].handle != SOCKET_ERROR)) 00014 //! check for timeout 00015 #define TIMEOUT(t, ms) ((ms != TIMEOUT_BLOCKING) && (ms < t.read_ms())) 00016 // num HTTP profiles 00017 #define NUMPROFILES (sizeof(_httpProfiles)/sizeof(*_httpProfiles)) 00018 //! test if it is an HTTP profile is ok to use 00019 #define ISPROFILE(p) (((p) >= 0) && ((p) < NUMPROFILES) && (_httpProfiles[p].handle != HTTP_PROF_ERROR)) 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 memset(_httpProfiles, 0, sizeof(_httpProfiles)); 00111 for (int profile = 0; profile < NUMPROFILES; profile ++) 00112 _httpProfiles[profile].handle = HTTP_PROF_ERROR; 00113 #ifdef MDM_DEBUG 00114 _debugLevel = 1; 00115 _debugTime.start(); 00116 #endif 00117 } 00118 00119 int MDMParser::send(const char* buf, int len) 00120 { 00121 #ifdef MDM_DEBUG 00122 if (_debugLevel >= 3) { 00123 ::printf("%10.3f AT send ", _debugTime.read_ms()*0.001); 00124 dumpAtCmd(buf,len); 00125 } 00126 #endif 00127 return _send(buf, len); 00128 } 00129 00130 int MDMParser::sendFormated(const char* format, ...) { 00131 char buf[MAX_SIZE]; 00132 va_list args; 00133 va_start(args, format); 00134 int len = vsnprintf(buf,sizeof(buf), format, args); 00135 va_end(args); 00136 return send(buf, len); 00137 } 00138 00139 int MDMParser::waitFinalResp(_CALLBACKPTR cb /* = NULL*/, 00140 void* param /* = NULL*/, 00141 int timeout_ms /*= 5000*/) 00142 { 00143 char buf[MAX_SIZE + 64 /* add some more space for framing */]; 00144 Timer timer; 00145 timer.start(); 00146 do { 00147 int ret = getLine(buf, sizeof(buf)); 00148 #ifdef MDM_DEBUG 00149 if ((_debugLevel >= 3) && (ret != WAIT) && (ret != NOT_FOUND)) 00150 { 00151 int len = LENGTH(ret); 00152 int type = TYPE(ret); 00153 const char* s = (type == TYPE_UNKNOWN)? YEL "UNK" DEF : 00154 (type == TYPE_TEXT) ? MAG "TXT" DEF : 00155 (type == TYPE_OK ) ? GRE "OK " DEF : 00156 (type == TYPE_ERROR) ? RED "ERR" DEF : 00157 (type == TYPE_PLUS) ? CYA " + " DEF : 00158 (type == TYPE_PROMPT) ? BLU " > " DEF : 00159 "..." ; 00160 ::printf("%10.3f AT read %s", _debugTime.read_ms()*0.001, s); 00161 dumpAtCmd(buf, len); 00162 } 00163 #endif 00164 if ((ret != WAIT) && (ret != NOT_FOUND)) 00165 { 00166 int type = TYPE(ret); 00167 // handle unsolicited commands here 00168 if (type == TYPE_PLUS) { 00169 const char* cmd = buf+3; 00170 int a, b, c, d, r; 00171 char s[32]; 00172 00173 // SMS Command --------------------------------- 00174 // +CNMI: <mem>,<index> 00175 if (sscanf(cmd, "CMTI: \"%*[^\"]\",%d", &a) == 1) { 00176 TRACE("New SMS at index %d\r\n", a); 00177 // Socket Specific Command --------------------------------- 00178 // +UUSORD: <socket>,<length> 00179 } else if ((sscanf(cmd, "UUSORD: %d,%d", &a, &b) == 2)) { 00180 int socket = _findSocket(a); 00181 TRACE("Socket %d: handle %d has %d bytes pending\r\n", socket, a, b); 00182 if (socket != SOCKET_ERROR) 00183 _sockets[socket].pending = b; 00184 // +UUSORF: <socket>,<length> 00185 } else if ((sscanf(cmd, "UUSORF: %d,%d", &a, &b) == 2)) { 00186 int socket = _findSocket(a); 00187 TRACE("Socket %d: handle %d has %d bytes pending\r\n", socket, a, b); 00188 if (socket != SOCKET_ERROR) 00189 _sockets[socket].pending = b; 00190 // +UUSOCL: <socket> 00191 } else if ((sscanf(cmd, "UUSOCL: %d", &a) == 1)) { 00192 int socket = _findSocket(a); 00193 TRACE("Socket %d: handle %d closed by remote host\r\n", socket, a); 00194 if ((socket != SOCKET_ERROR) && _sockets[socket].connected) 00195 _sockets[socket].connected = false; 00196 // +UULOC: <date>,<time>,<lat>,<long>,<alt>,<uncertainty>,<speed>, <direction>,<vertical_acc>,<sensor_used>,<SV_used>,<antenna_status>, <jamming_status> 00197 }else if (sscanf(cmd, "UULOC: %d/%d/%d,%d:%d:%d.%*d,%f,%f,%d,%d,%d,%d,%d,%d,%d,%*d,%*d",\ 00198 &_loc[0].time.tm_mday, &_loc[0].time.tm_mon, &_loc[0].time.tm_year, &_loc[0].time.tm_hour, &_loc[0].time.tm_min, &_loc[0].time.tm_sec,\ 00199 &_loc[0].latitude, &_loc[0].longitude, &_loc[0].altitutude, &_loc[0].uncertainty, &_loc[0].speed, &_loc[0].direction, &_loc[0].verticalAcc, \ 00200 &b, &_loc[0].svUsed) == 15) { 00201 TRACE("Parsed UULOC position at index 0\r\n"); 00202 _loc[0].sensor = (b==0)? CELL_LAST : (b==1)? CELL_GNSS : (b==2)? CELL_LOCATE : (b==3)? CELL_HYBRID : CELL_LAST; 00203 _loc[0].time.tm_mon -= 1; 00204 _loc[0].time.tm_wday=0; 00205 _loc[0].time.tm_yday=0; 00206 _loc[0].validData = true; 00207 _locExpPos=1; 00208 _locRcvPos++; 00209 // +UULOC: <sol>,<num>,<sensor_used>,<date>,<time>,<lat>,<long>,<alt>,<uncertainty>,<speed>, <direction>,<vertical_acc>,,<SV_used>,<antenna_status>, <jamming_status> 00210 }else if (sscanf(cmd, "UULOC: %d,%d,%d,%d/%d/%d,%d:%d:%d.%*d,%f,%f,%d,%d,%d,%d,%d,%d,%*d,%*d",\ 00211 &a,&_locExpPos,&b, \ 00212 &_loc[CELL_MAX_HYP-1].time.tm_mday, &_loc[CELL_MAX_HYP-1].time.tm_mon, &_loc[CELL_MAX_HYP-1].time.tm_year, &_loc[CELL_MAX_HYP-1].time.tm_hour, &_loc[CELL_MAX_HYP-1].time.tm_min, &_loc[CELL_MAX_HYP-1].time.tm_sec,\ 00213 &_loc[CELL_MAX_HYP-1].latitude, &_loc[CELL_MAX_HYP-1].longitude, &_loc[CELL_MAX_HYP-1].altitutude, &_loc[CELL_MAX_HYP-1].uncertainty, &_loc[CELL_MAX_HYP-1].speed, &_loc[CELL_MAX_HYP-1].direction, &_loc[CELL_MAX_HYP-1].verticalAcc, \ 00214 &_loc[CELL_MAX_HYP-1].svUsed) == 17) { 00215 if (--a>=0){ 00216 TRACE("Parsed UULOC position at index %d\r\n",a); 00217 memcpy(&_loc[a], &_loc[CELL_MAX_HYP-1], sizeof(*_loc)); 00218 _loc[a].sensor = (b==0)? CELL_LAST : (b==1)? CELL_GNSS : (b==2)? CELL_LOCATE : (b==3)? CELL_HYBRID : CELL_LAST; 00219 _loc[a].time.tm_mon -= 1; 00220 _loc[a].time.tm_wday=0; 00221 _loc[a].time.tm_yday=0; 00222 _loc[a].validData = true; 00223 _locRcvPos++; 00224 } 00225 //+UULOC: <sol>,<num>,<sensor_used>,<date>,<time>,<lat>,<long>,<alt>,<lat50>,<long50>,<major50>,<minor50>,<orientation50>,<confidence50>[,<lat95>,<long95>,<major95>,<minor95>,<orientation95>,<confidence95>] 00226 }else if (sscanf(cmd, "UULOC: %d,%d,%d,%d/%d/%d,%d:%d:%d.%*d,%f,%f,%d,%*f,%*f,%d,%*d,%*d,%*d",\ 00227 &a,&_locExpPos,&b, \ 00228 &_loc[CELL_MAX_HYP-1].time.tm_mday, &_loc[CELL_MAX_HYP-1].time.tm_mon, &_loc[CELL_MAX_HYP-1].time.tm_year, &_loc[CELL_MAX_HYP-1].time.tm_hour, &_loc[CELL_MAX_HYP-1].time.tm_min, &_loc[CELL_MAX_HYP-1].time.tm_sec,\ 00229 &_loc[CELL_MAX_HYP-1].latitude, &_loc[CELL_MAX_HYP-1].longitude, &_loc[CELL_MAX_HYP-1].altitutude, &_loc[CELL_MAX_HYP-1].uncertainty) == 13) { 00230 if (--a>=0){ 00231 TRACE("Parsed UULOC position at index %d\r\n",a); 00232 memcpy(&_loc[a], &_loc[CELL_MAX_HYP-1], sizeof(*_loc)); 00233 _loc[a].sensor = (b==0)? CELL_LAST : (b==1)? CELL_GNSS : (b==2)? CELL_LOCATE : (b==3)? CELL_HYBRID : CELL_LAST; 00234 _loc[a].time.tm_mon -= 1; 00235 _loc[a].time.tm_wday=0; 00236 _loc[a].time.tm_yday=0; 00237 _loc[a].validData = true; 00238 _locRcvPos++; 00239 } 00240 // +UHTTPCR: <profile_id>,<op_code>,<param_val> 00241 } else if ((sscanf(cmd, "UUHTTPCR: %d,%d,%d", &a, &b, &c) == 3)) { 00242 _httpProfiles[a].cmd = b; //command 00243 _httpProfiles[a].result = c; //result 00244 TRACE("%s for profile %d: result code is %d\r\n", getHTTPcmd(b), a, c); 00245 } 00246 if (_dev.dev == DEV_LISA_C2) { 00247 // CDMA Specific ------------------------------------------- 00248 // +CREG: <n><SID>,<NID>,<stat> 00249 if (sscanf(cmd, "CREG: %*d,%d,%d,%d",&a,&b,&c) == 3) { 00250 // _net.sid = a; 00251 // _net.nid = b; 00252 if (c == 0) _net.csd = REG_NONE; // not registered, home network 00253 else if (c == 1) _net.csd = REG_HOME; // registered, home network 00254 else if (c == 2) _net.csd = REG_NONE; // not registered, but MT is currently searching a new operator to register to 00255 else if (c == 3) _net.csd = REG_DENIED; // registration denied 00256 else if (c == 5) _net.csd = REG_ROAMING; // registered, roaming 00257 _net.psd = _net.csd; // fake PSD registration (CDMA is always registered) 00258 _net.act = ACT_CDMA; 00259 // +CSS: <mode>[,<format>,<oper>[,<AcT>]] 00260 } else if (sscanf(cmd, "CSS %*c,%2s,%*d",s) == 1) { 00261 //_net.reg = (strcmp("Z", s) == 0) ? REG_UNKNOWN : REG_HOME; 00262 } 00263 } else { 00264 // GSM/UMTS Specific ------------------------------------------- 00265 // +UUPSDD: <profile_id> 00266 if (sscanf(cmd, "UUPSDD: %d",&a) == 1) { 00267 if (*PROFILE == a) _ip = NOIP; 00268 } else { 00269 // +CREG|CGREG: <n>,<stat>[,<lac>,<ci>[,AcT[,<rac>]]] // reply to AT+CREG|AT+CGREG 00270 // +CREG|CGREG: <stat>[,<lac>,<ci>[,AcT[,<rac>]]] // URC 00271 b = 0xFFFF; c = 0xFFFFFFFF; d = -1; 00272 r = sscanf(cmd, "%s %*d,%d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d); 00273 if (r <= 1) 00274 r = sscanf(cmd, "%s %d,\"%X\",\"%X\",%d",s,&a,&b,&c,&d); 00275 if (r >= 2) { 00276 Reg *reg = !strcmp(s, "CREG:") ? &_net.csd : 00277 !strcmp(s, "CGREG:") ? &_net.psd : 00278 !strcmp(s, "CEREG:") ? &_net.eps : NULL; 00279 if (reg) { 00280 // network status 00281 if (a == 0) *reg = REG_NONE; // 0: not registered, home network 00282 else if (a == 1) *reg = REG_HOME; // 1: registered, home network 00283 else if (a == 2) *reg = REG_NONE; // 2: not registered, but MT is currently searching a new operator to register to 00284 else if (a == 3) *reg = REG_DENIED; // 3: registration denied 00285 else if (a == 4) *reg = REG_UNKNOWN; // 4: unknown 00286 else if (a == 5) *reg = REG_ROAMING; // 5: registered, roaming 00287 else if (a == 6) *reg = REG_HOME; // 6: registered, sms only, home 00288 if ((r >= 3) && (b != 0xFFFF)) _net.lac = b; // location area code 00289 if ((r >= 4) && (c != 0xFFFFFFFF)) _net.ci = c; // cell ID 00290 // access technology 00291 if (r >= 5) { 00292 if (d == 0) _net.act = ACT_GSM; // 0: GSM 00293 else if (d == 1) _net.act = ACT_GSM; // 1: GSM COMPACT 00294 else if (d == 2) _net.act = ACT_UTRAN; // 2: UTRAN 00295 else if (d == 3) _net.act = ACT_EDGE; // 3: GSM with EDGE availability 00296 else if (d == 4) _net.act = ACT_UTRAN; // 4: UTRAN with HSDPA availability 00297 else if (d == 5) _net.act = ACT_UTRAN; // 5: UTRAN with HSUPA availability 00298 else if (d == 6) _net.act = ACT_UTRAN; // 6: UTRAN with HSDPA and HSUPA availability 00299 else if (d == 7) _net.act = ACT_LTE; // 7: LTE 00300 } 00301 } 00302 } 00303 } 00304 } 00305 } 00306 if (cb) { 00307 int len = LENGTH(ret); 00308 int ret = cb(type, buf, len, param); 00309 if (WAIT != ret) 00310 return ret; 00311 } 00312 if (type == TYPE_OK) 00313 return RESP_OK; 00314 if (type == TYPE_ERROR) 00315 return RESP_ERROR; 00316 if (type == TYPE_ERROR_CME) 00317 return RESP_ERROR_CME; 00318 if (type == TYPE_PROMPT) 00319 return RESP_PROMPT; 00320 } 00321 // relax a bit 00322 wait_ms(10); 00323 } 00324 while (!TIMEOUT(timer, timeout_ms)); 00325 return WAIT; 00326 } 00327 00328 int MDMParser::_cbString(int type, const char* buf, int len, char* str) 00329 { 00330 if (str && (type == TYPE_UNKNOWN)) { 00331 if (sscanf(buf, "\r\n%s\r\n", str) == 1) 00332 /*nothing*/; 00333 } 00334 return WAIT; 00335 } 00336 00337 int MDMParser::_cbInt(int type, const char* buf, int len, int* val) 00338 { 00339 if (val && (type == TYPE_UNKNOWN)) { 00340 if (sscanf(buf, "\r\n%d\r\n", val) == 1) 00341 /*nothing*/; 00342 } 00343 return WAIT; 00344 } 00345 00346 // ---------------------------------------------------------------- 00347 00348 bool MDMParser::connect( 00349 const char* simpin, 00350 const char* apn, const char* username, 00351 const char* password, Auth auth, 00352 PinName pn) 00353 { 00354 bool ok = init(simpin, NULL, pn); 00355 #ifdef MDM_DEBUG 00356 if (_debugLevel >= 1) dumpDevStatus(&_dev); 00357 #endif 00358 if (!ok) 00359 return false; 00360 ok = registerNet(); 00361 #ifdef MDM_DEBUG 00362 if (_debugLevel >= 1) dumpNetStatus(&_net); 00363 #endif 00364 if (!ok) 00365 return false; 00366 IP ip = join(apn,username,password,auth); 00367 #ifdef MDM_DEBUG 00368 if (_debugLevel >= 1) dumpIp(ip); 00369 #endif 00370 if (ip == NOIP) 00371 return false; 00372 return true; 00373 } 00374 00375 bool MDMParser::init(const char* simpin, DevStatus* status, PinName pn) 00376 { 00377 int i = 10; 00378 LOCK(); 00379 memset(&_dev, 0, sizeof(_dev)); 00380 if (pn != NC) { 00381 INFO("Modem::wakeup\r\n"); 00382 DigitalOut pin(pn, 1); 00383 while (i--) { 00384 // SARA-U2/LISA-U2 50..80us 00385 pin = 0; ::wait_us(50); 00386 pin = 1; ::wait_ms(10); 00387 00388 // SARA-G35 >5ms, LISA-C2 > 150ms, LEON-G2 >5ms 00389 pin = 0; ::wait_ms(150); 00390 pin = 1; ::wait_ms(100); 00391 00392 // purge any messages 00393 purge(); 00394 00395 // check interface 00396 sendFormated("AT\r\n"); 00397 int r = waitFinalResp(NULL,NULL,1000); 00398 if(RESP_OK == r) break; 00399 } 00400 if (i < 0) { 00401 ERROR("No Reply from Modem\r\n"); 00402 goto failure; 00403 } 00404 } 00405 _init = true; 00406 00407 INFO("Modem::init\r\n"); 00408 // echo off 00409 sendFormated("AT E0\r\n"); 00410 if(RESP_OK != waitFinalResp()) 00411 goto failure; 00412 // enable verbose error messages 00413 sendFormated("AT+CMEE=2\r\n"); 00414 if(RESP_OK != waitFinalResp()) 00415 goto failure; 00416 // set baud rate 00417 sendFormated("AT+IPR=115200\r\n"); 00418 if (RESP_OK != waitFinalResp()) 00419 goto failure; 00420 // wait some time until baudrate is applied 00421 wait_ms(200); // SARA-G > 40ms 00422 // identify the module 00423 sendFormated("ATI\r\n"); 00424 if (RESP_OK != waitFinalResp(_cbATI, &_dev.dev)) 00425 goto failure; 00426 if (_dev.dev == DEV_UNKNOWN) 00427 goto failure; 00428 // device specific init 00429 if (_dev.dev == DEV_LISA_C2) { 00430 // get the manufacturer 00431 sendFormated("AT+GMI\r\n"); 00432 if (RESP_OK != waitFinalResp(_cbString, _dev.manu)) 00433 goto failure; 00434 // get the model identification 00435 sendFormated("AT+GMM\r\n"); 00436 if (RESP_OK != waitFinalResp(_cbString, _dev.model)) 00437 goto failure; 00438 // get the sw version 00439 sendFormated("AT+GMR\r\n"); 00440 if (RESP_OK != waitFinalResp(_cbString, _dev.ver)) 00441 goto failure; 00442 // get the pseudo ESN or MEID 00443 sendFormated("AT+GSN\r\n"); 00444 if (RESP_OK != waitFinalResp(_cbString, _dev.meid)) 00445 goto failure; 00446 #if 0 00447 // enable power saving 00448 if (_dev.lpm != LPM_DISABLED) { 00449 // enable power saving (requires flow control, cts at least) 00450 sendFormated("AT+UPSV=1,1280\r\n"); 00451 if (RESP_OK != waitFinalResp()) 00452 goto failure; 00453 _dev.lpm = LPM_ACTIVE; 00454 } 00455 #endif 00456 } else { 00457 if ((_dev.dev == DEV_LISA_U2) || (_dev.dev == DEV_LEON_G2) || 00458 (_dev.dev == DEV_TOBY_L2)) { 00459 // enable the network identification feature 00460 sendFormated("AT+UGPIOC=20,2\r\n"); 00461 if (RESP_OK != waitFinalResp()) 00462 goto failure; 00463 } else if ((_dev.dev == DEV_SARA_U2) || (_dev.dev == DEV_SARA_G35)) { 00464 // enable the network identification feature 00465 sendFormated("AT+UGPIOC=16,2\r\n"); 00466 if (RESP_OK != waitFinalResp()) 00467 goto failure; 00468 } 00469 // check the sim card 00470 for (int i = 0; (i < 5) && (_dev.sim != SIM_READY); i++) { 00471 sendFormated("AT+CPIN?\r\n"); 00472 int ret = waitFinalResp(_cbCPIN, &_dev.sim); 00473 // having an error here is ok (sim may still be initializing) 00474 if ((RESP_OK != ret) && (RESP_ERROR != ret)) 00475 goto failure; 00476 // Enter PIN if needed 00477 if (_dev.sim == SIM_PIN) { 00478 if (!simpin) { 00479 ERROR("SIM PIN not available\r\n"); 00480 goto failure; 00481 } 00482 sendFormated("AT+CPIN=\"%s\"\r\n", simpin); 00483 if (RESP_OK != waitFinalResp(_cbCPIN, &_dev.sim)) 00484 goto failure; 00485 } else if (_dev.sim != SIM_READY) { 00486 wait_ms(1000); 00487 } 00488 } 00489 if (_dev.sim != SIM_READY) { 00490 if (_dev.sim == SIM_MISSING) 00491 ERROR("SIM not inserted\r\n"); 00492 goto failure; 00493 } 00494 // get the manufacturer 00495 sendFormated("AT+CGMI\r\n"); 00496 if (RESP_OK != waitFinalResp(_cbString, _dev.manu)) 00497 goto failure; 00498 // get the model identification 00499 sendFormated("AT+CGMM\r\n"); 00500 if (RESP_OK != waitFinalResp(_cbString, _dev.model)) 00501 goto failure; 00502 // get the version 00503 sendFormated("ATI9\r\n"); 00504 if (RESP_OK != waitFinalResp(_cbString, _dev.ver)) 00505 goto failure; 00506 // Returns the ICCID (Integrated Circuit Card ID) of the SIM-card. 00507 // ICCID is a serial number identifying the SIM. 00508 sendFormated("AT+CCID\r\n"); 00509 if (RESP_OK != waitFinalResp(_cbCCID, _dev.ccid)) 00510 goto failure; 00511 // Returns the product serial number, IMEI (International Mobile Equipment Identity) 00512 sendFormated("AT+CGSN\r\n"); 00513 if (RESP_OK != waitFinalResp(_cbString, _dev.imei)) 00514 goto failure; 00515 // enable power saving 00516 if (_dev.lpm != LPM_DISABLED) { 00517 // enable power saving (requires flow control, cts at least) 00518 sendFormated("AT+UPSV=1\r\n"); 00519 if (RESP_OK != waitFinalResp()) 00520 goto failure; 00521 _dev.lpm = LPM_ACTIVE; 00522 } 00523 // enable the psd registration unsolicited result code 00524 sendFormated("AT+CGREG=2\r\n"); 00525 if (RESP_OK != waitFinalResp()) 00526 goto failure; 00527 } 00528 // enable the network registration unsolicited result code 00529 sendFormated("AT+CREG=%d\r\n", (_dev.dev == DEV_LISA_C2) ? 1 : 2); 00530 if (RESP_OK != waitFinalResp()) 00531 goto failure; 00532 // Setup SMS in text mode 00533 sendFormated("AT+CMGF=1\r\n"); 00534 if (RESP_OK != waitFinalResp()) 00535 goto failure; 00536 // setup new message indication 00537 sendFormated("AT+CNMI=2,1\r\n"); 00538 if (RESP_OK != waitFinalResp()) 00539 goto failure; 00540 // Request IMSI (International Mobile Subscriber Identification) 00541 sendFormated("AT+CIMI\r\n"); 00542 if (RESP_OK != waitFinalResp(_cbString, _dev.imsi)) 00543 goto failure; 00544 if (status) 00545 memcpy(status, &_dev, sizeof(DevStatus)); 00546 UNLOCK(); 00547 return true; 00548 failure: 00549 unlock(); 00550 return false; 00551 } 00552 00553 bool MDMParser::powerOff(void) 00554 { 00555 bool ok = false; 00556 if (_init) { 00557 LOCK(); 00558 INFO("Modem::powerOff\r\n"); 00559 sendFormated("AT+CPWROFF\r\n"); 00560 if (RESP_OK == waitFinalResp(NULL,NULL,120*1000)) { 00561 _init = false; 00562 ok = true; 00563 } 00564 UNLOCK(); 00565 } 00566 return ok; 00567 } 00568 00569 int MDMParser::_cbATI(int type, const char* buf, int len, Dev* dev) 00570 { 00571 if ((type == TYPE_UNKNOWN) && dev) { 00572 if (strstr(buf, "SARA-G35")) *dev = DEV_SARA_G35; 00573 else if (strstr(buf, "LISA-U200-03S")) *dev = DEV_LISA_U2_03S; 00574 else if (strstr(buf, "LISA-U2")) *dev = DEV_LISA_U2; 00575 else if (strstr(buf, "LISA-C2")) *dev = DEV_LISA_C2; 00576 else if (strstr(buf, "SARA-U2")) *dev = DEV_SARA_U2; 00577 else if (strstr(buf, "LEON-G2")) *dev = DEV_LEON_G2; 00578 else if (strstr(buf, "TOBY-L2")) *dev = DEV_TOBY_L2; 00579 else if (strstr(buf, "MPCI-L2")) *dev = DEV_MPCI_L2; 00580 } 00581 return WAIT; 00582 } 00583 00584 int MDMParser::_cbCPIN(int type, const char* buf, int len, Sim* sim) 00585 { 00586 if (sim) { 00587 if (type == TYPE_PLUS){ 00588 char s[16]; 00589 if (sscanf(buf, "\r\n+CPIN: %[^\r]\r\n", s) >= 1) 00590 *sim = (0 == strcmp("READY", s)) ? SIM_READY : SIM_PIN; 00591 } else if (type == TYPE_ERROR) { 00592 if (strstr(buf, "+CME ERROR: SIM not inserted")) 00593 *sim = SIM_MISSING; 00594 } 00595 } 00596 return WAIT; 00597 } 00598 00599 int MDMParser::_cbCCID(int type, const char* buf, int len, char* ccid) 00600 { 00601 if ((type == TYPE_PLUS) && ccid){ 00602 if (sscanf(buf, "\r\n+CCID: %[^\r]\r\n", ccid) == 1) 00603 /*TRACE("Got CCID: %s\r\n", ccid)*/; 00604 } 00605 return WAIT; 00606 } 00607 00608 bool MDMParser::registerNet(NetStatus* status /*= NULL*/, int timeout_ms /*= 180000*/) 00609 { 00610 Timer timer; 00611 timer.start(); 00612 INFO("Modem::register\r\n"); 00613 while (!checkNetStatus(status) && !TIMEOUT(timer, timeout_ms)) 00614 wait_ms(1000); 00615 if (_net.csd == REG_DENIED) ERROR("CSD Registration Denied\r\n"); 00616 if (_net.psd == REG_DENIED) ERROR("PSD Registration Denied\r\n"); 00617 if (_net.eps == REG_DENIED) ERROR("EPS Registration Denied\r\n"); 00618 return REG_OK(_net.csd) || REG_OK(_net.psd) || REG_OK(_net.eps); 00619 } 00620 00621 bool MDMParser::checkNetStatus(NetStatus* status /*= NULL*/) 00622 { 00623 bool ok = false; 00624 LOCK(); 00625 memset(&_net, 0, sizeof(_net)); 00626 _net.lac = 0xFFFF; 00627 _net.ci = 0xFFFFFFFF; 00628 // check registration 00629 sendFormated("AT+CREG?\r\n"); 00630 waitFinalResp(); // don't fail as service could be not subscribed 00631 if (_dev.dev != DEV_LISA_C2) { 00632 // check PSD registration 00633 sendFormated("AT+CGREG?\r\n"); 00634 waitFinalResp(); // don't fail as service could be not subscribed 00635 if ((_dev.dev == DEV_TOBY_L2) || (_dev.dev == DEV_MPCI_L2)) { 00636 // check EPS network registration 00637 sendFormated("AT+CEREG?\r\n"); 00638 waitFinalResp(); // don't fail as service could be not subscribed 00639 } 00640 } 00641 if (REG_OK(_net.csd) || REG_OK(_net.psd) || REG_OK(_net.eps)) 00642 { 00643 // check modem specific status messages 00644 if (_dev.dev == DEV_LISA_C2) { 00645 sendFormated("AT+CSS?\r\n"); 00646 if (RESP_OK != waitFinalResp()) 00647 goto failure; 00648 while (1) { 00649 // get the Telephone number 00650 sendFormated("AT$MDN?\r\n"); 00651 if (RESP_OK != waitFinalResp(_cbString, _net.num)) 00652 goto failure; 00653 // check if we have a Mobile Directory Number 00654 if (*_net.num && (memcmp(_net.num, "000000", 6) != 0)) 00655 break; 00656 00657 INFO("Device not yet activated\r\n"); 00658 INFO("Make sure you have a valid contract with the network operator for this device.\r\n"); 00659 // Check if the the version contains a V for Verizon 00660 // Verizon: E0.V.xx.00.xxR, 00661 // Sprint E0.S.xx.00.xxR 00662 if (_dev.ver[3] == 'V') { 00663 int i; 00664 INFO("Start device over-the-air activation (this can take a few minutes)\r\n"); 00665 sendFormated("AT+CDV=*22899\r\n"); 00666 i = 1; 00667 if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) { 00668 ERROR("Device over-the-air activation failed\r\n"); 00669 goto failure; 00670 } 00671 INFO("Device over-the-air activation successful\r\n"); 00672 00673 INFO("Start PRL over-the-air update (this can take a few minutes)\r\n"); 00674 sendFormated("AT+CDV=*22891\r\n"); 00675 i = 1; 00676 if ((RESP_OK != waitFinalResp(_cbUACTIND, &i, 120*1000)) || (i == 1)) { 00677 ERROR("PRL over-the-air update failed\r\n"); 00678 goto failure; 00679 } 00680 INFO("PRL over-the-air update successful\r\n"); 00681 00682 } else { 00683 // Sprint or Aeris 00684 INFO("Wait for OMA-DM over-the-air activation (this can take a few minutes)\r\n"); 00685 wait_ms(120*1000); 00686 } 00687 } 00688 // get the the Network access identifier string 00689 char nai[64]; 00690 sendFormated("AT$QCMIPNAI?\r\n"); 00691 if (RESP_OK != waitFinalResp(_cbString, nai)) 00692 goto failure; 00693 } else { 00694 sendFormated("AT+COPS?\r\n"); 00695 if (RESP_OK != waitFinalResp(_cbCOPS, &_net)) 00696 goto failure; 00697 // get the MSISDNs related to this subscriber 00698 sendFormated("AT+CNUM\r\n"); 00699 if (RESP_OK != waitFinalResp(_cbCNUM, _net.num)) 00700 goto failure; 00701 } 00702 // get the signal strength indication 00703 sendFormated("AT+CSQ\r\n"); 00704 if (RESP_OK != waitFinalResp(_cbCSQ, &_net)) 00705 goto failure; 00706 } 00707 if (status) { 00708 memcpy(status, &_net, sizeof(NetStatus)); 00709 } 00710 ok = REG_DONE(_net.csd) && 00711 (REG_DONE(_net.psd) || REG_DONE(_net.eps)); 00712 UNLOCK(); 00713 return ok; 00714 failure: 00715 unlock(); 00716 return false; 00717 } 00718 00719 int MDMParser::_cbCOPS(int type, const char* buf, int len, NetStatus* status) 00720 { 00721 if ((type == TYPE_PLUS) && status){ 00722 int act = 99; 00723 int mode = 99; 00724 // +COPS: <mode>[,<format>,<oper>[,<AcT>]] 00725 if (sscanf(buf, "\r\n+COPS: %d,%*d,\"%[^\"]\",%d",&mode,status->opr,&act) >= 1) { 00726 if (act == 0) status->act = ACT_GSM; // 0: GSM, 00727 else if (act == 2) status->act = ACT_UTRAN; // 2: UTRAN 00728 else if (act == 7) status->act = ACT_LTE; // 2: UTRAN 00729 if (mode == 0) status->regStatus = COPS_AUTOMATIC_REG; 00730 else if (mode == 1) status->regStatus = COPS_MANUAL_REG; 00731 else if (mode == 2) status->regStatus = COPS_DISABLED_REG; 00732 } 00733 } 00734 return WAIT; 00735 } 00736 00737 int MDMParser::_cbCNUM(int type, const char* buf, int len, char* num) 00738 { 00739 if ((type == TYPE_PLUS) && num){ 00740 int a; 00741 if ((sscanf(buf, "\r\n+CNUM: \"My Number\",\"%31[^\"]\",%d", num, &a) == 2) && 00742 ((a == 129) || (a == 145))) { 00743 } 00744 } 00745 return WAIT; 00746 } 00747 00748 int MDMParser::_cbCSQ(int type, const char* buf, int len, NetStatus* status) 00749 { 00750 if ((type == TYPE_PLUS) && status){ 00751 int a,b; 00752 char _ber[] = { 49, 43, 37, 25, 19, 13, 7, 0 }; // see 3GPP TS 45.008 [20] subclause 8.2.4 00753 // +CSQ: <rssi>,<qual> 00754 if (sscanf(buf, "\r\n+CSQ: %d,%d",&a,&b) == 2) { 00755 if (a != 99) status->rssi = -113 + 2*a; // 0: -113 1: -111 ... 30: -53 dBm with 2 dBm steps, 31: >-51 dBm 00756 if ((b != 99) && (b < sizeof(_ber))) status->ber = _ber[b]; // 00757 } 00758 } 00759 return WAIT; 00760 } 00761 00762 00763 int MDMParser::_cbUACTIND(int type, const char* buf, int len, int* i) 00764 { 00765 if ((type == TYPE_PLUS) && i){ 00766 int a; 00767 if (sscanf(buf, "\r\n+UACTIND: %d", &a) == 1) { 00768 *i = a; 00769 } 00770 } 00771 return WAIT; 00772 } 00773 00774 // ---------------------------------------------------------------- 00775 // internet connection 00776 00777 bool MDMParser::_activateProfile(const char* apn, const char* username, const char* password, Auth auth) 00778 { 00779 // Set up the APN 00780 if (*apn) { 00781 sendFormated("AT+UPSD=" PROFILE ",1,\"%s\"\r\n", apn); 00782 if (RESP_OK != waitFinalResp()) 00783 return false; 00784 } 00785 if (*username) { 00786 sendFormated("AT+UPSD=" PROFILE ",2,\"%s\"\r\n", username); 00787 if (RESP_OK != waitFinalResp()) 00788 return false; 00789 } 00790 if (*password) { 00791 sendFormated("AT+UPSD=" PROFILE ",3,\"%s\"\r\n", password); 00792 if (RESP_OK != waitFinalResp()) 00793 return false; 00794 } 00795 // Set up the dynamic IP address assignment. 00796 sendFormated("AT+UPSD=" PROFILE ",7,\"0.0.0.0\"\r\n"); 00797 if (RESP_OK != waitFinalResp()) 00798 return false; 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; 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 return false; 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 return true; 00813 } 00814 } 00815 return false; 00816 } 00817 00818 bool MDMParser::_activateProfileReuseExternal(void) 00819 { 00820 int cid = -1; 00821 sendFormated("AT+CGDCONT?\r\n"); 00822 if (RESP_OK != waitFinalResp(_cbCGDCONT, &cid)) 00823 return false; 00824 if (cid == -1) 00825 return false; 00826 // we found a context that provides us a valid IP so lets reuse it for the internal IP stack 00827 sendFormated("AT+UPSD=" PROFILE ",100,%d\r\n", cid); 00828 if (RESP_OK != waitFinalResp()) 00829 return false; 00830 // Activate the profile and make connection 00831 sendFormated("AT+UPSDA=" PROFILE ",3\r\n"); 00832 return (RESP_OK == waitFinalResp(NULL,NULL,150*1000)); 00833 } 00834 00835 bool MDMParser::_activateProfileByCid(int cid, const char* apn, const char* username, const char* password, Auth auth) 00836 { 00837 sendFormated("AT+CGDCONT=%d,\"IP\",\"%s\"\r\n", cid, apn); 00838 if (RESP_OK != waitFinalResp()) 00839 return false; 00840 sendFormated("AT+UAUTHREQ=%d,%d,\"%s\",\"%s\"\r\n", cid, auth, username, password); 00841 if (RESP_OK != waitFinalResp()) 00842 return false; 00843 sendFormated("AT+UPSD=" PROFILE ",100,%d\r\n", cid); 00844 if (RESP_OK != waitFinalResp()) 00845 return false; 00846 // Activate the profile and make connection 00847 sendFormated("AT+UPSDA=" PROFILE ",3\r\n"); 00848 return (RESP_OK == waitFinalResp(NULL,NULL,150*1000)); 00849 } 00850 00851 int MDMParser::_cbCGDCONT(int type, const char* buf, int len, int* cid) 00852 { 00853 // accept with and without leading \r\n in +CGDCONT: 00854 if ((type == TYPE_PLUS) && (buf[0] == '\r') && (buf[1] == '\n') && (len >= 2)) 00855 buf += 2, len -= 2, type = TYPE_UNKNOWN; 00856 if (type == TYPE_UNKNOWN) { 00857 int a,b,c,d,t; 00858 //+CGDCONT: <cid>,"IP","<apn name>","<ip adr>",0,0,0,0,0,0 00859 if (sscanf(buf, "+CGDCONT: %d,\"IP\",\"%*[^\"]\",\"" IPSTR "\",%*d,%*d,%*d,%*d,%*d,%*d", &t, &a,&b,&c,&d) == 5) { 00860 if (IPADR(a,b,c,d) != NOIP) 00861 *cid = t; 00862 } 00863 } 00864 return WAIT; 00865 } 00866 00867 MDMParser::IP MDMParser::join(const char* apn /*= NULL*/, const char* username /*= NULL*/, 00868 const char* password /*= NULL*/, Auth auth /*= AUTH_DETECT*/) 00869 { 00870 LOCK(); 00871 INFO("Modem::join\r\n"); 00872 _ip = NOIP; 00873 if (_dev.dev == DEV_LISA_C2) { 00874 // make a dumy dns lookup (which will fail, so ignore the result) 00875 sendFormated("AT+UDNSRN=0,\"u-blox.com\"\r\n"); 00876 waitFinalResp(); 00877 // This fake lookup will enable the IP connection and we 00878 // should have an IP after this, so we check it 00879 00880 //Get local IP address 00881 sendFormated("AT+CMIP?\r\n"); 00882 if (RESP_OK != waitFinalResp(_cbCMIP, &_ip)) 00883 goto failure; 00884 00885 } else { 00886 // check gprs attach status 00887 sendFormated("AT+CGATT=1\r\n"); 00888 if (RESP_OK != waitFinalResp(NULL,NULL,3*60*1000)) 00889 goto failure; 00890 // Check the profile 00891 int a = 0; 00892 bool force = true; 00893 sendFormated("AT+UPSND=" PROFILE ",8\r\n"); 00894 if (RESP_OK != waitFinalResp(_cbUPSND, &a)) 00895 goto failure; 00896 if (a == 1 && force) { 00897 // disconnect the profile already if it is connected 00898 sendFormated("AT+UPSDA=" PROFILE ",4\r\n"); 00899 if (RESP_OK != waitFinalResp(NULL,NULL,40*1000)) 00900 goto failure; 00901 a = 0; 00902 } 00903 if (a == 0) { 00904 bool ok = false; 00905 // try to lookup the apn settings from our local database by mccmnc 00906 const char* config = NULL; 00907 if (!apn && !username && !password) 00908 config = apnconfig(_dev.imsi); 00909 do { 00910 if (config) { 00911 apn = _APN_GET(config); 00912 username = _APN_GET(config); 00913 password = _APN_GET(config); 00914 } 00915 // convert pointer to empty strings 00916 apn = apn ? apn : ""; 00917 username = username ? username : ""; 00918 password = password ? password : ""; 00919 auth = (*username && *password) ? auth : AUTH_NONE; 00920 TRACE("Testing APN Settings(\"%s\",\"%s\",\"%s\",%d)\r\n", apn, username, password, auth); 00921 if ((_dev.dev != DEV_TOBY_L2) && (_dev.dev != DEV_MPCI_L2)) 00922 ok = _activateProfile(apn, username, password, auth); 00923 else { 00924 ok = _activateProfileReuseExternal(); 00925 if (ok) 00926 TRACE("Reusing External Context\r\n"); 00927 else 00928 ok = _activateProfileByCid(1, apn, username, password, auth); 00929 } 00930 } while (!ok && config && *config); // maybe use next setting ? 00931 if (!ok) { 00932 ERROR("Your modem APN/password/username may be wrong\r\n"); 00933 goto failure; 00934 } 00935 } 00936 //Get local IP address 00937 sendFormated("AT+UPSND=" PROFILE ",0\r\n"); 00938 if (RESP_OK != waitFinalResp(_cbUPSND, &_ip)) 00939 goto failure; 00940 } 00941 UNLOCK(); 00942 return _ip; 00943 failure: 00944 unlock(); 00945 return NOIP; 00946 } 00947 00948 int MDMParser::_cbUDOPN(int type, const char* buf, int len, char* mccmnc) 00949 { 00950 if ((type == TYPE_PLUS) && mccmnc) { 00951 if (sscanf(buf, "\r\n+UDOPN: 0,\"%[^\"]\"", mccmnc) == 1) 00952 ; 00953 } 00954 return WAIT; 00955 } 00956 00957 int MDMParser::_cbCMIP(int type, const char* buf, int len, IP* ip) 00958 { 00959 if ((type == TYPE_UNKNOWN) && ip) { 00960 int a,b,c,d; 00961 if (sscanf(buf, "\r\n" IPSTR, &a,&b,&c,&d) == 4) 00962 *ip = IPADR(a,b,c,d); 00963 } 00964 return WAIT; 00965 } 00966 00967 int MDMParser::_cbUPSND(int type, const char* buf, int len, int* act) 00968 { 00969 if ((type == TYPE_PLUS) && act) { 00970 if (sscanf(buf, "\r\n+UPSND: %*d,%*d,%d", act) == 1) 00971 /*nothing*/; 00972 } 00973 return WAIT; 00974 } 00975 00976 int MDMParser::_cbUPSND(int type, const char* buf, int len, IP* ip) 00977 { 00978 if ((type == TYPE_PLUS) && ip) { 00979 int a,b,c,d; 00980 // +UPSND=<profile_id>,<param_tag>[,<dynamic_param_val>] 00981 if (sscanf(buf, "\r\n+UPSND: " PROFILE ",0,\"" IPSTR "\"", &a,&b,&c,&d) == 4) 00982 *ip = IPADR(a,b,c,d); 00983 } 00984 return WAIT; 00985 } 00986 00987 int MDMParser::_cbUDNSRN(int type, const char* buf, int len, IP* ip) 00988 { 00989 if ((type == TYPE_PLUS) && ip) { 00990 int a,b,c,d; 00991 if (sscanf(buf, "\r\n+UDNSRN: \"" IPSTR "\"", &a,&b,&c,&d) == 4) 00992 *ip = IPADR(a,b,c,d); 00993 } 00994 return WAIT; 00995 } 00996 00997 bool MDMParser::disconnect(void) 00998 { 00999 bool ok = false; 01000 LOCK(); 01001 INFO("Modem::disconnect\r\n"); 01002 if (_ip != NOIP) { 01003 if (_dev.dev == DEV_LISA_C2) { 01004 // There something to do here 01005 _ip = NOIP; 01006 ok = true; 01007 } else { 01008 sendFormated("AT+UPSDA=" PROFILE ",4\r\n"); 01009 if (RESP_OK != waitFinalResp()) { 01010 _ip = NOIP; 01011 ok = true; 01012 } 01013 } 01014 } 01015 UNLOCK(); 01016 return ok; 01017 } 01018 01019 MDMParser::IP MDMParser::gethostbyname(const char* host) 01020 { 01021 IP ip = NOIP; 01022 int a,b,c,d; 01023 if (sscanf(host, IPSTR, &a,&b,&c,&d) == 4) 01024 ip = IPADR(a,b,c,d); 01025 else { 01026 LOCK(); 01027 sendFormated("AT+UDNSRN=0,\"%s\"\r\n", host); 01028 if (RESP_OK != waitFinalResp(_cbUDNSRN, &ip)) 01029 ip = NOIP; 01030 UNLOCK(); 01031 } 01032 return ip; 01033 } 01034 01035 // ---------------------------------------------------------------- 01036 // sockets 01037 01038 int MDMParser::_cbUSOCR(int type, const char* buf, int len, int* handle) 01039 { 01040 if ((type == TYPE_PLUS) && handle) { 01041 // +USOCR: socket 01042 if (sscanf(buf, "\r\n+USOCR: %d", handle) == 1) 01043 /*nothing*/; 01044 } 01045 return WAIT; 01046 } 01047 01048 int MDMParser::socketSocket(IpProtocol ipproto, int port) 01049 { 01050 int socket; 01051 LOCK(); 01052 // find an free socket 01053 socket = _findSocket(); 01054 TRACE("socketSocket(%d)\r\n", ipproto); 01055 if (socket != SOCKET_ERROR) { 01056 if (ipproto == IPPROTO_UDP) { 01057 // sending port can only be set on 2G/3G modules 01058 if ((port != -1) && (_dev.dev != DEV_LISA_C2)) { 01059 sendFormated("AT+USOCR=17,%d\r\n", port); 01060 } else { 01061 sendFormated("AT+USOCR=17\r\n"); 01062 } 01063 } else /*(ipproto == IPPROTO_TCP)*/ { 01064 sendFormated("AT+USOCR=6\r\n"); 01065 } 01066 int handle = SOCKET_ERROR; 01067 if ((RESP_OK == waitFinalResp(_cbUSOCR, &handle)) && 01068 (handle != SOCKET_ERROR)) { 01069 TRACE("Socket %d: handle %d was created\r\n", socket, handle); 01070 _sockets[socket].handle = handle; 01071 _sockets[socket].timeout_ms = TIMEOUT_BLOCKING; 01072 _sockets[socket].connected = false; 01073 _sockets[socket].pending = 0; 01074 } 01075 else 01076 socket = SOCKET_ERROR; 01077 } 01078 UNLOCK(); 01079 return socket; 01080 } 01081 01082 bool MDMParser::socketConnect(int socket, const char * host, int port) 01083 { 01084 IP ip = gethostbyname(host); 01085 if (ip == NOIP) 01086 return false; 01087 // connect to socket 01088 bool ok = false; 01089 LOCK(); 01090 if (ISSOCKET(socket) && (!_sockets[socket].connected)) { 01091 TRACE("socketConnect(%d,%s,%d)\r\n", socket,host,port); 01092 sendFormated("AT+USOCO=%d,\"" IPSTR "\",%d\r\n", _sockets[socket].handle, IPNUM(ip), port); 01093 if (RESP_OK == waitFinalResp()) 01094 ok = _sockets[socket].connected = true; 01095 } 01096 UNLOCK(); 01097 return ok; 01098 } 01099 01100 bool MDMParser::socketIsConnected(int socket) 01101 { 01102 bool ok = false; 01103 LOCK(); 01104 ok = ISSOCKET(socket) && _sockets[socket].connected; 01105 TRACE("socketIsConnected(%d) %s\r\n", socket, ok?"yes":"no"); 01106 UNLOCK(); 01107 return ok; 01108 } 01109 01110 bool MDMParser::socketSetBlocking(int socket, int timeout_ms) 01111 { 01112 bool ok = false; 01113 LOCK(); 01114 TRACE("socketSetBlocking(%d,%d)\r\n", socket,timeout_ms); 01115 if (ISSOCKET(socket)) { 01116 _sockets[socket].timeout_ms = timeout_ms; 01117 ok = true; 01118 } 01119 UNLOCK(); 01120 return ok; 01121 } 01122 01123 bool MDMParser::socketClose(int socket) 01124 { 01125 bool ok = false; 01126 LOCK(); 01127 if (ISSOCKET(socket) && _sockets[socket].connected) { 01128 TRACE("socketClose(%d)\r\n", socket); 01129 sendFormated("AT+USOCL=%d\r\n", _sockets[socket].handle); 01130 if (RESP_OK == waitFinalResp()) { 01131 _sockets[socket].connected = false; 01132 ok = true; 01133 } 01134 } 01135 UNLOCK(); 01136 return ok; 01137 } 01138 01139 bool MDMParser::socketFree(int socket) 01140 { 01141 // make sure it is closed 01142 socketClose(socket); 01143 bool ok = true; 01144 LOCK(); 01145 if (ISSOCKET(socket)) { 01146 TRACE("socketFree(%d)\r\n", socket); 01147 _sockets[socket].handle = SOCKET_ERROR; 01148 _sockets[socket].timeout_ms = TIMEOUT_BLOCKING; 01149 _sockets[socket].connected = false; 01150 _sockets[socket].pending = 0; 01151 ok = true; 01152 } 01153 UNLOCK(); 01154 return ok; 01155 } 01156 01157 #define USO_MAX_WRITE 1024 //!< maximum number of bytes to write to socket 01158 01159 int MDMParser::socketSend(int socket, const char * buf, int len) 01160 { 01161 TRACE("socketSend(%d,,%d)\r\n", socket,len); 01162 int cnt = len; 01163 while (cnt > 0) { 01164 int blk = USO_MAX_WRITE; 01165 if (cnt < blk) 01166 blk = cnt; 01167 bool ok = false; 01168 LOCK(); 01169 if (ISSOCKET(socket)) { 01170 sendFormated("AT+USOWR=%d,%d\r\n",_sockets[socket].handle,blk); 01171 if (RESP_PROMPT == waitFinalResp()) { 01172 wait_ms(50); 01173 send(buf, blk); 01174 if (RESP_OK == waitFinalResp()) 01175 ok = true; 01176 } 01177 } 01178 UNLOCK(); 01179 if (!ok) 01180 return SOCKET_ERROR; 01181 buf += blk; 01182 cnt -= blk; 01183 } 01184 return (len - cnt); 01185 } 01186 01187 int MDMParser::socketSendTo(int socket, IP ip, int port, const char * buf, int len) 01188 { 01189 TRACE("socketSendTo(%d," IPSTR ",%d,,%d)\r\n", socket,IPNUM(ip),port,len); 01190 int cnt = len; 01191 while (cnt > 0) { 01192 int blk = USO_MAX_WRITE; 01193 if (cnt < blk) 01194 blk = cnt; 01195 bool ok = false; 01196 LOCK(); 01197 if (ISSOCKET(socket)) { 01198 sendFormated("AT+USOST=%d,\"" IPSTR "\",%d,%d\r\n",_sockets[socket].handle,IPNUM(ip),port,blk); 01199 if (RESP_PROMPT == waitFinalResp()) { 01200 wait_ms(50); 01201 send(buf, blk); 01202 if (RESP_OK == waitFinalResp()) 01203 ok = true; 01204 } 01205 } 01206 UNLOCK(); 01207 if (!ok) 01208 return SOCKET_ERROR; 01209 buf += blk; 01210 cnt -= blk; 01211 } 01212 return (len - cnt); 01213 } 01214 01215 int MDMParser::socketReadable(int socket) 01216 { 01217 int pending = SOCKET_ERROR; 01218 LOCK(); 01219 if (ISSOCKET(socket) && _sockets[socket].connected) { 01220 TRACE("socketReadable(%d)\r\n", socket); 01221 // allow to receive unsolicited commands 01222 waitFinalResp(NULL, NULL, 0); 01223 if (_sockets[socket].connected) 01224 pending = _sockets[socket].pending; 01225 } 01226 UNLOCK(); 01227 return pending; 01228 } 01229 01230 int MDMParser::_cbUSORD(int type, const char* buf, int len, char* out) 01231 { 01232 if ((type == TYPE_PLUS) && out) { 01233 int sz, sk; 01234 if ((sscanf(buf, "\r\n+USORD: %d,%d,", &sk, &sz) == 2) && 01235 (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) { 01236 memcpy(out, &buf[len-1-sz], sz); 01237 } 01238 } 01239 return WAIT; 01240 } 01241 01242 int MDMParser::socketRecv(int socket, char* buf, int len) 01243 { 01244 int cnt = 0; 01245 TRACE("socketRecv(%d,,%d)\r\n", socket, len); 01246 #ifdef MDM_DEBUG 01247 memset(buf, '\0', len); 01248 #endif 01249 Timer timer; 01250 timer.start(); 01251 while (len) { 01252 int blk = MAX_SIZE; // still need space for headers and unsolicited commands 01253 if (len < blk) blk = len; 01254 bool ok = false; 01255 LOCK(); 01256 if (ISSOCKET(socket)) { 01257 if (_sockets[socket].connected) { 01258 if (_sockets[socket].pending < blk) 01259 blk = _sockets[socket].pending; 01260 if (blk > 0) { 01261 sendFormated("AT+USORD=%d,%d\r\n",_sockets[socket].handle, blk); 01262 if (RESP_OK == waitFinalResp(_cbUSORD, buf)) { 01263 _sockets[socket].pending -= blk; 01264 len -= blk; 01265 cnt += blk; 01266 buf += blk; 01267 ok = true; 01268 } 01269 } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) { 01270 ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs 01271 } else { 01272 len = 0; 01273 ok = true; 01274 } 01275 } else { 01276 len = 0; 01277 ok = true; 01278 } 01279 } 01280 UNLOCK(); 01281 if (!ok) { 01282 TRACE("socketRecv: ERROR\r\n"); 01283 return SOCKET_ERROR; 01284 } 01285 } 01286 TRACE("socketRecv: %d \"%*s\"\r\n", cnt, cnt, buf-cnt); 01287 return cnt; 01288 } 01289 01290 int MDMParser::_cbUSORF(int type, const char* buf, int len, USORFparam* param) 01291 { 01292 if ((type == TYPE_PLUS) && param) { 01293 int sz, sk, p, a,b,c,d; 01294 int r = sscanf(buf, "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,", 01295 &sk,&a,&b,&c,&d,&p,&sz); 01296 if ((r == 7) && (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) { 01297 memcpy(param->buf, &buf[len-1-sz], sz); 01298 param->ip = IPADR(a,b,c,d); 01299 param->port = p; 01300 } 01301 } 01302 return WAIT; 01303 } 01304 01305 int MDMParser::socketRecvFrom(int socket, IP* ip, int* port, char* buf, int len) 01306 { 01307 int cnt = 0; 01308 TRACE("socketRecvFrom(%d,,%d)\r\n", socket, len); 01309 #ifdef MDM_DEBUG 01310 memset(buf, '\0', len); 01311 #endif 01312 Timer timer; 01313 timer.start(); 01314 while (len) { 01315 int blk = MAX_SIZE; // still need space for headers and unsolicited commands 01316 if (len < blk) blk = len; 01317 bool ok = false; 01318 LOCK(); 01319 if (ISSOCKET(socket)) { 01320 if (_sockets[socket].pending < blk) 01321 blk = _sockets[socket].pending; 01322 if (blk > 0) { 01323 sendFormated("AT+USORF=%d,%d\r\n",_sockets[socket].handle, blk); 01324 USORFparam param; 01325 param.buf = buf; 01326 if (RESP_OK == waitFinalResp(_cbUSORF, ¶m)) { 01327 _sockets[socket].pending -= blk; 01328 *ip = param.ip; 01329 *port = param.port; 01330 len -= blk; 01331 cnt += blk; 01332 buf += blk; 01333 len = 0; // done 01334 ok = true; 01335 } 01336 } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) { 01337 ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs 01338 } else { 01339 len = 0; // no more data and socket closed or timed-out 01340 ok = true; 01341 } 01342 } 01343 UNLOCK(); 01344 if (!ok) { 01345 TRACE("socketRecv: ERROR\r\n"); 01346 return SOCKET_ERROR; 01347 } 01348 } 01349 timer.stop(); 01350 timer.reset(); 01351 TRACE("socketRecv: %d \"%*s\"\r\n", cnt, cnt, buf-cnt); 01352 return cnt; 01353 } 01354 01355 int MDMParser::_findSocket(int handle) { 01356 for (int socket = 0; socket < NUMSOCKETS; socket ++) { 01357 if (_sockets[socket].handle == handle) 01358 return socket; 01359 } 01360 return SOCKET_ERROR; 01361 } 01362 01363 // ---------------------------------------------------------------- 01364 // HTTP 01365 01366 int MDMParser::httpFindProfile() 01367 { 01368 int profile = HTTP_PROF_ERROR; //default value 01369 LOCK(); 01370 // find a free HTTP profile 01371 profile = _findProfile(); 01372 TRACE("httpFindProfile: profile is %d\r\n", profile); 01373 if (profile != HTTP_PROF_ERROR) { 01374 _httpProfiles[profile].handle = 1; 01375 _httpProfiles[profile].timeout_ms = TIMEOUT_BLOCKING; 01376 _httpProfiles[profile].pending = false; 01377 _httpProfiles[profile].cmd = -1; 01378 _httpProfiles[profile].result = -1; 01379 } 01380 UNLOCK(); 01381 return profile; 01382 } 01383 01384 int MDMParser::_findProfile(int handle) { 01385 for (int profile = 0; profile < NUMPROFILES; profile++) { 01386 if (_httpProfiles[profile].handle == handle) 01387 return profile; 01388 } 01389 return HTTP_PROF_ERROR; 01390 } 01391 01392 bool MDMParser::httpSetBlocking(int profile, int timeout_ms) 01393 { 01394 bool ok = false; 01395 LOCK(); 01396 TRACE("httpSetBlocking(%d,%d)\r\n", profile, timeout_ms); 01397 if (ISPROFILE(profile)) { 01398 _httpProfiles[profile].timeout_ms = timeout_ms; 01399 ok = true; 01400 } 01401 UNLOCK(); 01402 return ok; 01403 } 01404 01405 bool MDMParser::httpSetProfileForCmdMng(int profile) 01406 { 01407 bool ok = false; 01408 LOCK(); 01409 TRACE("httpSetProfileForCmdMng(%d)\r\n", profile); 01410 if (ISPROFILE(profile)) { 01411 _httpProfiles[profile].pending = true; 01412 _httpProfiles[profile].result = -1; 01413 ok = true; 01414 } 01415 UNLOCK(); 01416 return ok; 01417 } 01418 01419 bool MDMParser::httpFreeProfile(int profile) 01420 { 01421 bool ok = true; 01422 LOCK(); 01423 if (ISPROFILE(profile)) { 01424 TRACE("httpFreeProfile(%d)\r\n", profile); 01425 _httpProfiles[profile].handle = HTTP_PROF_ERROR; 01426 _httpProfiles[profile].timeout_ms = TIMEOUT_BLOCKING; 01427 _httpProfiles[profile].pending = false; 01428 _httpProfiles[profile].cmd = -1; 01429 _httpProfiles[profile].result = -1; 01430 ok = true; 01431 } 01432 UNLOCK(); 01433 return ok; 01434 } 01435 01436 bool MDMParser::httpResetProfile(int httpProfile) 01437 { 01438 bool ok = false; 01439 01440 LOCK(); 01441 TRACE("httpResetProfile(%d)\r\n", httpProfile); 01442 sendFormated("AT+UHTTP=%d\r\n", httpProfile); 01443 if (RESP_OK == waitFinalResp()) 01444 ok = true; 01445 UNLOCK(); 01446 01447 return ok; 01448 } 01449 01450 bool MDMParser::httpSetPar(int httpProfile, HttpOpCode httpOpCode, const char * httpInPar) 01451 { 01452 bool ok = false; 01453 IP ip = NOIP; 01454 int httpInParNum = 0; 01455 01456 LOCK(); 01457 TRACE("httpSetPar(%d,%d,\"%s\")\r\n", httpProfile, httpOpCode, httpInPar); 01458 switch(httpOpCode){ 01459 case HTTP_IP_ADDRESS: //0 01460 ip = gethostbyname(httpInPar); 01461 if (ip == NOIP) 01462 return false; 01463 01464 sendFormated("AT+UHTTP=%d,%d,\"" IPSTR "\"\r\n", httpProfile, httpOpCode, IPNUM(ip)); 01465 if (RESP_OK == waitFinalResp()) 01466 ok = true; 01467 break; 01468 01469 case HTTP_SERVER_NAME: //1 01470 case HTTP_USER_NAME: //2 01471 case HTTP_PASSWORD: //3 01472 sendFormated("AT+UHTTP=%d,%d,\"%s\"\r\n", httpProfile, httpOpCode, httpInPar); 01473 if (RESP_OK == waitFinalResp()) 01474 ok = true; 01475 break; 01476 01477 case HTTP_AUTH_TYPE: //4 01478 case HTTP_SERVER_PORT: //5 01479 httpInParNum = atoi(httpInPar); 01480 sendFormated("AT+UHTTP=%d,%d,%d\r\n", httpProfile, httpOpCode, httpInParNum); 01481 if (RESP_OK == waitFinalResp()) 01482 ok = true; 01483 break; 01484 01485 case HTTP_SECURE: //6 01486 if(_dev.dev != DEV_LISA_C2) 01487 { 01488 httpInParNum = atoi(httpInPar); 01489 sendFormated("AT+UHTTP=%d,%d,%d\r\n", httpProfile, httpOpCode, httpInParNum); 01490 if (RESP_OK == waitFinalResp()) 01491 ok = true; 01492 } else { 01493 TRACE("httpSetPar: HTTP secure option not supported by module\r\n"); 01494 ok = false; 01495 } 01496 break; 01497 01498 default: 01499 TRACE("httpSetPar: unknown httpOpCode %s\r\n", httpOpCode); 01500 ok = false; 01501 break; 01502 } 01503 UNLOCK(); 01504 return ok; 01505 } 01506 01507 bool MDMParser::httpCommand(int httpProfile, HttpCmd httpCmdCode, const char* httpPath, const char* httpOut, \ 01508 const char* httpIn, int httpContentType, const char* httpCustomPar, char* buf, int len) 01509 { 01510 bool ok = false; 01511 #ifdef MDM_DEBUG 01512 memset(buf, '\0', len); 01513 #endif 01514 LOCK(); 01515 TRACE("%s\r\n", getHTTPcmd(httpCmdCode)); 01516 switch (httpCmdCode) 01517 { 01518 case HTTP_HEAD: 01519 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\"\r\n", httpProfile, HTTP_HEAD, httpPath, httpOut); 01520 break; 01521 01522 case HTTP_GET: 01523 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\"\r\n", httpProfile, HTTP_GET, httpPath, httpOut); 01524 break; 01525 01526 case HTTP_DELETE: 01527 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\"\r\n", httpProfile, HTTP_DELETE, httpPath, httpOut); 01528 break; 01529 01530 case HTTP_PUT: 01531 //in this case the parameter httpIn is a filename 01532 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\"\r\n", httpProfile, HTTP_PUT, httpPath, httpOut, httpIn); 01533 break; 01534 01535 case HTTP_POST_FILE: 01536 //in this case the parameter httpIn is a filename 01537 if(_dev.dev != DEV_LISA_C2) 01538 { 01539 if(httpContentType != 6) 01540 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \ 01541 httpProfile, HTTP_POST_FILE, httpPath, httpOut, httpIn, httpContentType); 01542 else 01543 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d,%d\r\n", \ 01544 httpProfile, HTTP_POST_FILE, httpPath, httpOut, httpIn, httpContentType, httpCustomPar); 01545 } 01546 else{ 01547 if((httpContentType != 5) && (httpContentType != 6) && (httpCustomPar == NULL)) 01548 { 01549 //parameters values consistent with the AT commands specs of LISA-C200 01550 //(in particular httpCustomPar has to be not defined) 01551 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \ 01552 httpProfile, HTTP_POST_FILE, httpPath, httpOut, httpIn, httpContentType); 01553 } else { 01554 TRACE("httpCommand: command not supported by module"); 01555 return ok; //error 01556 } 01557 } 01558 break; 01559 01560 case HTTP_POST_DATA: 01561 //in this case the parameter httpIn is a string containing data 01562 if(_dev.dev != DEV_LISA_C2) 01563 { 01564 if(httpContentType != 6) 01565 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \ 01566 httpProfile, HTTP_POST_DATA, httpPath, httpOut, httpIn, httpContentType); 01567 else 01568 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d,%d\r\n", \ 01569 httpProfile, HTTP_POST_DATA, httpPath, httpOut, httpIn, httpContentType, httpCustomPar); 01570 } else { 01571 if((httpContentType != 5) && (httpContentType != 6) && (httpCustomPar == NULL)) 01572 { 01573 //parameters values consistent with the AT commands specs of LISA-C200 01574 //(in particular httpCustomPar has to be not defined) 01575 sendFormated("AT+UHTTPC=%d,%d,\"%s\",\"%s\",\"%s\",%d\r\n", \ 01576 httpProfile, HTTP_POST_DATA, httpPath, httpOut, httpIn, httpContentType); 01577 } else { 01578 TRACE("httpCommand: command not supported by module"); 01579 return ok; //error 01580 } 01581 } 01582 break; 01583 01584 default: 01585 TRACE("HTTP command not recognized\r\n"); 01586 return ok; //error 01587 } 01588 01589 if (RESP_OK == waitFinalResp()) 01590 { 01591 Timer timer; 01592 timer.start(); 01593 httpSetProfileForCmdMng(httpProfile); 01594 while (_httpProfiles[httpProfile].pending) //waiting for unsolicited 01595 { 01596 ok = false; //reset variable 01597 if(_httpProfiles[httpProfile].result != -1) 01598 { 01599 //received unsolicited: starting its analysis 01600 _httpProfiles[httpProfile].pending = false; 01601 if(_httpProfiles[httpProfile].result == 1) 01602 { 01603 //HTTP command successfully executed 01604 if(_dev.dev != DEV_LISA_C2) 01605 { 01606 TRACE("httpCommand: reading files with a dimension " \ 01607 "also greater than MAX_SIZE bytes\r\n"); 01608 if(readFileNew(httpOut,buf,len) >=0 ) 01609 ok = true; 01610 } else { 01611 TRACE("httpCommand: reading files with a dimension " \ 01612 "less than MAX_SIZE bytes, otherwise error\r\n"); 01613 if(readFile(httpOut,buf,len) >=0 ) 01614 ok = true; 01615 } 01616 } else { 01617 //HTTP command not successfully executed 01618 ok = false; 01619 } 01620 } else if (!TIMEOUT(timer, _httpProfiles[httpProfile].timeout_ms)) { 01621 ok = (WAIT == waitFinalResp(NULL,NULL,0)); // wait for URCs 01622 } else { 01623 //not received unsolicited and expired timer 01624 TRACE("httpCommand: not received unsolicited and expired timer\r\n"); 01625 ok = false; 01626 } 01627 if (!ok) { 01628 TRACE("%s: ERROR\r\n", getHTTPcmd(httpCmdCode)); 01629 _httpProfiles[httpProfile].pending = false; //no more while loops 01630 } 01631 } 01632 } 01633 UNLOCK(); 01634 return ok; 01635 } 01636 01637 const char* MDMParser::getHTTPcmd(int httpCmdCode) 01638 { 01639 switch (httpCmdCode) 01640 { 01641 case HTTP_HEAD: 01642 return "HTTP HEAD command"; 01643 case HTTP_GET: 01644 return "HTTP GET command"; 01645 case HTTP_DELETE: 01646 return "HTTP DELETE command"; 01647 case HTTP_PUT: 01648 return "HTTP PUT command"; 01649 case HTTP_POST_FILE: 01650 return "HTTP POST file command"; 01651 case HTTP_POST_DATA: 01652 return "HTTP POST data command"; 01653 default: 01654 return "HTTP command not recognized"; 01655 } 01656 } 01657 01658 // ---------------------------------------------------------------- 01659 01660 int MDMParser::_cbCMGL(int type, const char* buf, int len, CMGLparam* param) 01661 { 01662 if ((type == TYPE_PLUS) && param && param->num) { 01663 // +CMGL: <ix>,... 01664 int ix; 01665 if (sscanf(buf, "\r\n+CMGL: %d,", &ix) == 1) 01666 { 01667 *param->ix++ = ix; 01668 param->num--; 01669 } 01670 } 01671 return WAIT; 01672 } 01673 01674 int MDMParser::smsList(const char* stat /*= "ALL"*/, int* ix /*=NULL*/, int num /*= 0*/) { 01675 int ret = -1; 01676 LOCK(); 01677 sendFormated("AT+CMGL=\"%s\"\r\n", stat); 01678 CMGLparam param; 01679 param.ix = ix; 01680 param.num = num; 01681 if (RESP_OK == waitFinalResp(_cbCMGL, ¶m)) 01682 ret = num - param.num; 01683 UNLOCK(); 01684 return ret; 01685 } 01686 01687 bool MDMParser::smsSend(const char* num, const char* buf) 01688 { 01689 bool ok = false; 01690 LOCK(); 01691 sendFormated("AT+CMGS=\"%s\"\r\n",num); 01692 if (RESP_PROMPT == waitFinalResp(NULL,NULL,150*1000)) { 01693 send(buf, strlen(buf)); 01694 const char ctrlZ = 0x1A; 01695 send(&ctrlZ, sizeof(ctrlZ)); 01696 ok = (RESP_OK == waitFinalResp()); 01697 } 01698 UNLOCK(); 01699 return ok; 01700 } 01701 01702 bool MDMParser::smsDelete(int ix) 01703 { 01704 bool ok = false; 01705 LOCK(); 01706 sendFormated("AT+CMGD=%d\r\n",ix); 01707 ok = (RESP_OK == waitFinalResp()); 01708 UNLOCK(); 01709 return ok; 01710 } 01711 01712 int MDMParser::_cbCMGR(int type, const char* buf, int len, CMGRparam* param) 01713 { 01714 if (param) { 01715 if (type == TYPE_PLUS) { 01716 if (sscanf(buf, "\r\n+CMGR: \"%*[^\"]\",\"%[^\"]", param->num) == 1) { 01717 } 01718 } else if ((type == TYPE_UNKNOWN) && (buf[len-2] == '\r') && (buf[len-1] == '\n')) { 01719 memcpy(param->buf, buf, len-2); 01720 param->buf[len-2] = '\0'; 01721 } 01722 } 01723 return WAIT; 01724 } 01725 01726 bool MDMParser::smsRead(int ix, char* num, char* buf, int len) 01727 { 01728 bool ok = false; 01729 LOCK(); 01730 CMGRparam param; 01731 param.num = num; 01732 param.buf = buf; 01733 sendFormated("AT+CMGR=%d\r\n",ix); 01734 ok = (RESP_OK == waitFinalResp(_cbCMGR, ¶m)); 01735 UNLOCK(); 01736 return ok; 01737 } 01738 01739 // ---------------------------------------------------------------- 01740 01741 int MDMParser::_cbCUSD(int type, const char* buf, int len, char* resp) 01742 { 01743 if ((type == TYPE_PLUS) && resp) { 01744 // +USD: \"%*[^\"]\",\"%[^\"]\",,\"%*[^\"]\",%d,%d,%d,%d,\"*[^\"]\",%d,%d"..); 01745 if (sscanf(buf, "\r\n+CUSD: %*d,\"%[^\"]\",%*d", resp) == 1) { 01746 /*nothing*/ 01747 } 01748 } 01749 return WAIT; 01750 } 01751 01752 bool MDMParser::ussdCommand(const char* cmd, char* buf) 01753 { 01754 bool ok = false; 01755 LOCK(); 01756 *buf = '\0'; 01757 if (_dev.dev != DEV_LISA_C2) { 01758 sendFormated("AT+CUSD=1,\"%s\"\r\n",cmd); 01759 ok = (RESP_OK == waitFinalResp(_cbCUSD, buf)); 01760 } 01761 UNLOCK(); 01762 return ok; 01763 } 01764 01765 // ---------------------------------------------------------------- 01766 01767 int MDMParser::_cbUDELFILE(int type, const char* buf, int len, void*) 01768 { 01769 if ((type == TYPE_ERROR) && strstr(buf, "+CME ERROR: FILE NOT FOUND")) 01770 return RESP_OK; // file does not exist, so all ok... 01771 return WAIT; 01772 } 01773 01774 bool MDMParser::delFile(const char* filename) 01775 { 01776 bool ok = false; 01777 LOCK(); 01778 sendFormated("AT+UDELFILE=\"%s\"\r\n", filename); 01779 ok = (RESP_OK == waitFinalResp(_cbUDELFILE)); 01780 UNLOCK(); 01781 return ok; 01782 } 01783 01784 int MDMParser::writeFile(const char* filename, const char* buf, int len) 01785 { 01786 bool ok = false; 01787 LOCK(); 01788 sendFormated("AT+UDWNFILE=\"%s\",%d\r\n", filename, len); 01789 if (RESP_PROMPT == waitFinalResp()) { 01790 send(buf, len); 01791 ok = (RESP_OK == waitFinalResp()); 01792 } 01793 UNLOCK(); 01794 return ok ? len : -1; 01795 } 01796 01797 int MDMParser::readFile(const char* filename, char* buf, int len) 01798 { 01799 URDFILEparam param; 01800 param.filename = filename; 01801 param.buf = buf; 01802 param.sz = len; 01803 param.len = 0; 01804 LOCK(); 01805 sendFormated("AT+URDFILE=\"%s\"\r\n", filename, len); 01806 if (RESP_OK != waitFinalResp(_cbURDFILE, ¶m)) 01807 param.len = -1; 01808 UNLOCK(); 01809 return param.len; 01810 } 01811 01812 int MDMParser::_cbURDFILE(int type, const char* buf, int len, URDFILEparam* param) 01813 { 01814 if ((type == TYPE_PLUS) && param && param->filename && param->buf) { 01815 char filename[48]; 01816 int sz; 01817 if ((sscanf(buf, "\r\n+URDFILE: \"%[^\"]\",%d,", filename, &sz) == 2) && 01818 (0 == strcmp(param->filename, filename)) && 01819 (buf[len-sz-2] == '\"') && (buf[len-1] == '\"')) { 01820 param->len = (sz < param->sz) ? sz : param->sz; 01821 memcpy(param->buf, &buf[len-1-sz], param->len); 01822 } 01823 } 01824 return WAIT; 01825 } 01826 01827 //The following function is useful for reading files with a dimension greater than MAX_SIZE bytes 01828 int MDMParser::readFileNew(const char* filename, char* buf, int len) 01829 { 01830 int countBytes = -1; //counter for file reading (default value) 01831 01832 if(_dev.dev != DEV_LISA_C2) 01833 { 01834 //retrieve information about the file, in particular its size 01835 int filesize = infoFile(filename); 01836 TRACE("readFileNew: filename is %s; filesize is %d\r\n", filename, filesize); 01837 01838 if (len < filesize) 01839 TRACE("readFileNew: WARNING. Buffer dimension is %d bytes," \ 01840 "while file size is %d bytes\r\n", len, filesize); 01841 01842 if (filesize > 0) 01843 { 01844 #ifdef MDM_DEBUG 01845 memset(buf, '\0', len); 01846 #endif 01847 int offset = 0; //start reading from 0 01848 int blockSize = MAX_SIZE; //still need space for headers and unsolicited commands 01849 int bytesToRead = filesize; //bytes to read 01850 01851 while (bytesToRead) 01852 { 01853 bool ok = false; 01854 01855 if (bytesToRead < blockSize) 01856 blockSize = bytesToRead; 01857 01858 LOCK(); 01859 if (blockSize > 0) { 01860 01861 sendFormated("AT+URDBLOCK=\"%s\",%d,%d\r\n", filename, offset, blockSize); 01862 01863 if (RESP_OK == waitFinalResp(_cbURDBLOCK, buf)) { 01864 bytesToRead -= blockSize; 01865 offset += blockSize; 01866 buf += blockSize; 01867 ok = true; 01868 } else { 01869 //error condition 01870 countBytes = -1; 01871 ok = false; 01872 } 01873 } 01874 UNLOCK(); 01875 01876 if (!ok) { 01877 TRACE("readFileNew: ERROR\r\n"); 01878 return countBytes; //in this case countBytes is -1 01879 } 01880 } 01881 01882 countBytes = offset; //total read bytes 01883 return countBytes; 01884 } 01885 } else { 01886 TRACE("httpCommand: command not supported by module"); 01887 } 01888 return countBytes; //it could be 0 or -1 (possible error) 01889 } 01890 01891 int MDMParser::_cbURDBLOCK(int type, const char* buf, int len, char* out) 01892 { 01893 char fileNameRes[48]; 01894 int sizeRes; 01895 01896 if ((type == TYPE_PLUS) && out) { 01897 if ((sscanf(buf, "\r\n+URDBLOCK: \"%[^\"]\",%d,", fileNameRes, &sizeRes) == 2) && 01898 (buf[len-sizeRes-2] == '\"') && (buf[len-1] == '\"')) { 01899 memcpy(out, &buf[len-1-sizeRes], sizeRes); 01900 } 01901 } 01902 01903 return WAIT; 01904 } 01905 01906 int MDMParser::infoFile(const char* filename) 01907 { 01908 int infoFile = 0; //default value 01909 01910 LOCK(); 01911 sendFormated("AT+ULSTFILE=2,\"%s\"\r\n", filename); 01912 if (RESP_OK != waitFinalResp(_cbULSTFILE, &infoFile)) 01913 infoFile = -1; //error condition 01914 UNLOCK(); 01915 01916 return infoFile; 01917 } 01918 01919 int MDMParser::_cbULSTFILE(int type, const char* buf, int len, int* infoFile) 01920 { 01921 if (infoFile) { 01922 if (type == TYPE_PLUS) { 01923 if (sscanf(buf, "\r\n+ULSTFILE: %d\r\n", infoFile) == 1) { 01924 } 01925 } 01926 } 01927 return WAIT; 01928 } 01929 01930 // ---------------------------------------------------------------- 01931 int MDMParser::cellLocSrvTcp(const char* token, const char* server_1, const char* server_2, int days/* = 14*/, \ 01932 int period/* = 4*/, int resolution/* = 1*/) 01933 { 01934 bool ok = false; 01935 LOCK(); 01936 if (_dev.dev == DEV_LISA_U2_03S || _dev.dev == DEV_SARA_U2 ){ 01937 sendFormated("AT+UGSRV=\"%s\",\"%s\",\"%s\"\r\n", server_1, server_2, token, days, period, resolution); 01938 ok = (RESP_OK == waitFinalResp()); 01939 } else 01940 ERROR("Command not supported\r\n"); 01941 UNLOCK(); 01942 return ok; 01943 } 01944 01945 int MDMParser::cellLocSrvUdp(const char* server_1 /*= "cell-live1.services.u-blox.com"*/, int port /*= 46434*/, \ 01946 int latency/* = 1000*/, int mode/* = 0*/) 01947 { 01948 bool ok = false; 01949 LOCK(); 01950 if (_dev.dev != DEV_TOBY_L2){ 01951 sendFormated("AT+UGAOP=\"%s\",%d,%d,%d\r\n", server_1, port, latency, mode); 01952 ok = (RESP_OK == waitFinalResp()); 01953 } else 01954 ERROR("Command not supported\r\n"); 01955 UNLOCK(); 01956 return ok; 01957 } 01958 01959 int MDMParser::cellLocUnsol(int mode) 01960 { 01961 bool ok = false; 01962 LOCK(); 01963 if (_dev.dev == DEV_LISA_U2_03S){ 01964 sendFormated("AT+ULOCIND=%d\r\n", mode); 01965 ok = (RESP_OK == waitFinalResp()); 01966 } else 01967 ERROR("Command not supported\r\n"); 01968 UNLOCK(); 01969 return ok; 01970 } 01971 01972 int MDMParser::cellLocConfig(int scanMode) 01973 { 01974 bool ok = false; 01975 LOCK(); 01976 if (_dev.dev != DEV_TOBY_L2){ 01977 sendFormated("AT+ULOCCELL=%d\r\n", scanMode); 01978 ok = (RESP_OK == waitFinalResp()); 01979 }else 01980 ERROR("Command not supported\r\n"); 01981 UNLOCK(); 01982 return ok; 01983 } 01984 01985 int MDMParser::cellLocRequest(CellSensType sensor, int timeout, int accuracy, CellRespType type/* =1*/, int hypotesis/* =1*/) 01986 { 01987 bool ok = false; 01988 01989 if (hypotesis > 1 && type != CELL_MULTIHYP){ 01990 ERROR("Num hypotesis is not set accordelying to CellRespType\r\n"); 01991 return false; 01992 } 01993 if (hypotesis > CELL_MAX_HYP){ 01994 ERROR("Number of hypotesis is too big\r\n"); 01995 return false; 01996 } 01997 LOCK(); 01998 _locRcvPos=0; 01999 _locExpPos=0; 02000 for (int i=0; i < hypotesis; i++) 02001 _loc[i].validData = false; 02002 if (_dev.dev == DEV_LISA_U2_03S){ 02003 sendFormated("AT+ULOC=2,%d,%d,%d,%d,%d\r\n", sensor, type, timeout, accuracy, hypotesis); 02004 ok = (RESP_OK == waitFinalResp()); 02005 } else if (_dev.dev != DEV_TOBY_L2){ 02006 sendFormated("AT+ULOC=2,%d,1,%d,%d\r\n", sensor, timeout, accuracy); 02007 ok = (RESP_OK == waitFinalResp()); 02008 } else 02009 ERROR("Command not supported\r\n"); 02010 UNLOCK(); 02011 return ok; 02012 } 02013 int MDMParser::cellLocGetRes() 02014 { 02015 return _locRcvPos; 02016 } 02017 int MDMParser::cellLocGetExpRes() 02018 { 02019 int res=0; 02020 waitFinalResp(NULL,NULL,0); 02021 LOCK(); 02022 if (_locRcvPos>0) 02023 res = _locExpPos; 02024 UNLOCK(); 02025 return res; 02026 } 02027 02028 int MDMParser::cellLocGetData(CellLocData *data, int index/*=0*/){ 02029 02030 if (!_loc[index].validData) 02031 return false; 02032 LOCK(); 02033 memcpy(data, &_loc[index], sizeof(*_loc)); 02034 UNLOCK(); 02035 return true; 02036 } 02037 02038 // ---------------------------------------------------------------- 02039 bool MDMParser::setDebug (int level) 02040 { 02041 #ifdef MDM_DEBUG 02042 _debugLevel = (level < -1) ? -1 : 02043 (level > 3) ? 3 : 02044 level; 02045 #endif 02046 return _debugLevel == level; 02047 } 02048 02049 void MDMParser::dumpDevStatus(MDMParser::DevStatus* status, 02050 _DPRINT dprint, void* param) 02051 { 02052 dprint(param, "Modem::devStatus\r\n"); 02053 const char* txtDev[] = { "Unknown", "SARA-G35", "LISA-U2", "LISA-U2-03S", "LISA-C2", 02054 "SARA-U2", "LEON-G2", "TOBY-L2", "MPCI-L2" }; 02055 if (status->dev < sizeof(txtDev)/sizeof(*txtDev) && (status->dev != DEV_UNKNOWN)) 02056 dprint(param, " Device: %s\r\n", txtDev[status->dev]); 02057 const char* txtLpm[] = { "Disabled", "Enabled", "Active" }; 02058 if (status->lpm < sizeof(txtLpm)/sizeof(*txtLpm)) 02059 dprint(param, " Power Save: %s\r\n", txtLpm[status->lpm]); 02060 const char* txtSim[] = { "Unknown", "Missing", "Pin", "Ready" }; 02061 if (status->sim < sizeof(txtSim)/sizeof(*txtSim) && (status->sim != SIM_UNKNOWN)) 02062 dprint(param, " SIM: %s\r\n", txtSim[status->sim]); 02063 if (*status->ccid) 02064 dprint(param, " CCID: %s\r\n", status->ccid); 02065 if (*status->imei) 02066 dprint(param, " IMEI: %s\r\n", status->imei); 02067 if (*status->imsi) 02068 dprint(param, " IMSI: %s\r\n", status->imsi); 02069 if (*status->meid) 02070 dprint(param, " MEID: %s\r\n", status->meid); // LISA-C 02071 if (*status->manu) 02072 dprint(param, " Manufacturer: %s\r\n", status->manu); 02073 if (*status->model) 02074 dprint(param, " Model: %s\r\n", status->model); 02075 if (*status->ver) 02076 dprint(param, " Version: %s\r\n", status->ver); 02077 } 02078 02079 void MDMParser::dumpNetStatus(MDMParser::NetStatus *status, 02080 _DPRINT dprint, void* param) 02081 { 02082 dprint(param, "Modem::netStatus\r\n"); 02083 const char* txtReg[] = { "Unknown", "Denied", "None", "Home", "Roaming" }; 02084 if (status->csd < sizeof(txtReg)/sizeof(*txtReg) && (status->csd != REG_UNKNOWN)) 02085 dprint(param, " CSD Registration: %s\r\n", txtReg[status->csd]); 02086 if (status->psd < sizeof(txtReg)/sizeof(*txtReg) && (status->psd != REG_UNKNOWN)) 02087 dprint(param, " PSD Registration: %s\r\n", txtReg[status->psd]); 02088 if (status->eps < sizeof(txtReg)/sizeof(*txtReg) && (status->eps != REG_UNKNOWN)) 02089 dprint(param, " EPS Registration: %s\r\n", txtReg[status->eps]); 02090 const char* txtAct[] = { "Unknown", "GSM", "Edge", "3G", "CDMA", "LTE" }; 02091 if (status->act < sizeof(txtAct)/sizeof(*txtAct) && (status->act != ACT_UNKNOWN)) 02092 dprint(param, " Access Technology: %s\r\n", txtAct[status->act]); 02093 if (status->rssi) 02094 dprint(param, " Signal Strength: %d dBm\r\n", status->rssi); 02095 if (status->ber) 02096 dprint(param, " Bit Error Rate: %d\r\n", status->ber); 02097 if (*status->opr) 02098 dprint(param, " Operator: %s\r\n", status->opr); 02099 if (status->lac != 0xFFFF) 02100 dprint(param, " Location Area Code: %04X\r\n", status->lac); 02101 if (status->ci != 0xFFFFFFFF) 02102 dprint(param, " Cell ID: %08X\r\n", status->ci); 02103 if (*status->num) 02104 dprint(param, " Phone Number: %s\r\n", status->num); 02105 } 02106 02107 void MDMParser::dumpIp(MDMParser::IP ip, 02108 _DPRINT dprint, void* param) 02109 { 02110 if (ip != NOIP) 02111 dprint(param, "Modem:IP " IPSTR "\r\n", IPNUM(ip)); 02112 } 02113 02114 // ---------------------------------------------------------------- 02115 int MDMParser::_parseMatch(Pipe<char> * pipe, int len, const char* sta, const char* end) 02116 { 02117 int o = 0; 02118 if (sta) { 02119 while (*sta) { 02120 if (++o > len) return WAIT; 02121 char ch = pipe->next(); 02122 if (*sta++ != ch) return NOT_FOUND; 02123 } 02124 } 02125 if (!end) return o; // no termination 02126 // at least any char 02127 if (++o > len) return WAIT; 02128 pipe->next(); 02129 // check the end 02130 int x = 0; 02131 while (end[x]) { 02132 if (++o > len) return WAIT; 02133 char ch = pipe->next(); 02134 x = (end[x] == ch) ? x + 1 : 02135 (end[0] == ch) ? 1 : 02136 0; 02137 } 02138 return o; 02139 } 02140 02141 int MDMParser::_parseFormated(Pipe<char> * pipe, int len, const char* fmt) 02142 { 02143 int o = 0; 02144 int num = 0; 02145 if (fmt) { 02146 while (*fmt) { 02147 if (++o > len) return WAIT; 02148 char ch = pipe->next(); 02149 if (*fmt == '%') { 02150 fmt++; 02151 if (*fmt == 'd') { // numeric 02152 fmt ++; 02153 num = 0; 02154 while (ch >= '0' && ch <= '9') { 02155 num = num * 10 + (ch - '0'); 02156 if (++o > len) return WAIT; 02157 ch = pipe->next(); 02158 } 02159 } 02160 else if (*fmt == 'c') { // char buffer (takes last numeric as length) 02161 fmt ++; 02162 while (num --) { 02163 if (++o > len) return WAIT; 02164 ch = pipe->next(); 02165 } 02166 } 02167 else if (*fmt == 's') { 02168 fmt ++; 02169 if (ch != '\"') return NOT_FOUND; 02170 do { 02171 if (++o > len) return WAIT; 02172 ch = pipe->next(); 02173 } while (ch != '\"'); 02174 if (++o > len) return WAIT; 02175 ch = pipe->next(); 02176 } 02177 } 02178 if (*fmt++ != ch) return NOT_FOUND; 02179 } 02180 } 02181 return o; 02182 } 02183 02184 int MDMParser::_getLine(Pipe<char> * pipe, char* buf, int len) 02185 { 02186 int unkn = 0; 02187 int sz = pipe->size(); 02188 int fr = pipe->free(); 02189 if (len > sz) 02190 len = sz; 02191 while (len > 0) 02192 { 02193 static struct { 02194 const char* fmt; int type; 02195 } lutF[] = { 02196 { "\r\n+USORD: %d,%d,\"%c\"", TYPE_PLUS }, 02197 { "\r\n+USORF: %d,\"" IPSTR "\",%d,%d,\"%c\"", TYPE_PLUS }, 02198 { "\r\n+URDFILE: %s,%d,\"%c\"", TYPE_PLUS }, 02199 { "\r\n+URDBLOCK: %s,%d,\"%c\"", TYPE_PLUS }, 02200 }; 02201 static struct { 02202 const char* sta; const char* end; int type; 02203 } lut[] = { 02204 { "\r\nOK\r\n", NULL, TYPE_OK }, 02205 { "\r\nERROR\r\n", NULL, TYPE_ERROR }, 02206 { "\r\n+CME ERROR:", "\r\n", TYPE_ERROR_CME }, 02207 { "\r\n+CMS ERROR:", "\r\n", TYPE_ERROR }, 02208 { "\r\nRING\r\n", NULL, TYPE_RING }, 02209 { "\r\nCONNECT\r\n", NULL, TYPE_CONNECT }, 02210 { "\r\nNO CARRIER\r\n", NULL, TYPE_NOCARRIER }, 02211 { "\r\nNO DIALTONE\r\n", NULL, TYPE_NODIALTONE }, 02212 { "\r\nBUSY\r\n", NULL, TYPE_BUSY }, 02213 { "\r\nNO ANSWER\r\n", NULL, TYPE_NOANSWER }, 02214 { "\r\n+", "\r\n", TYPE_PLUS }, 02215 { "\r\n@", NULL, TYPE_PROMPT }, // Sockets 02216 { "\r\n>", NULL, TYPE_PROMPT }, // SMS 02217 { "\n>", NULL, TYPE_PROMPT }, // File 02218 }; 02219 for (int i = 0; i < sizeof(lutF)/sizeof(*lutF); i ++) { 02220 pipe->set(unkn); 02221 int ln = _parseFormated(pipe, len, lutF[i].fmt); 02222 if (ln == WAIT && fr) 02223 return WAIT; 02224 if ((ln != NOT_FOUND) && (unkn > 0)) 02225 return TYPE_UNKNOWN | pipe->get (buf, unkn); 02226 if (ln > 0) 02227 return lutF[i].type | pipe->get (buf, ln); 02228 } 02229 for (int i = 0; i < sizeof(lut)/sizeof(*lut); i ++) { 02230 pipe->set(unkn); 02231 int ln = _parseMatch(pipe, len, lut[i].sta, lut[i].end); 02232 if (ln == WAIT && fr) 02233 return WAIT; 02234 if ((ln != NOT_FOUND) && (unkn > 0)) 02235 return TYPE_UNKNOWN | pipe->get (buf, unkn); 02236 if (ln > 0) 02237 return lut[i].type | pipe->get (buf, ln); 02238 } 02239 // UNKNOWN 02240 unkn ++; 02241 len--; 02242 } 02243 return WAIT; 02244 } 02245 02246 // ---------------------------------------------------------------- 02247 // Serial Implementation 02248 // ---------------------------------------------------------------- 02249 02250 /*! Helper Dev Null Device 02251 Small helper class used to shut off stderr/stdout. Sometimes stdin/stdout 02252 is shared with the serial port of the modem. Having printfs inbetween the 02253 AT commands you cause a failure of the modem. 02254 */ 02255 class DevNull : public Stream { 02256 public: 02257 DevNull() : Stream(_name+1) { } //!< Constructor 02258 void claim(const char* mode, FILE* file) 02259 { freopen(_name, mode, file); } //!< claim a stream 02260 protected: 02261 virtual int _getc() { return EOF; } //!< Nothing 02262 virtual int _putc(int c) { return c; } //!< Discard 02263 static const char* _name; //!< File name 02264 }; 02265 const char* DevNull::_name = "/null"; //!< the null device name 02266 static DevNull null; //!< the null device 02267 02268 MDMSerial::MDMSerial(PinName tx /*= MDMTXD*/, PinName rx /*= MDMRXD*/, 02269 int baudrate /*= MDMBAUD*/, 02270 #if DEVICE_SERIAL_FC 02271 PinName rts /*= MDMRTS*/, PinName cts /*= MDMCTS*/, 02272 #endif 02273 int rxSize /*= 256*/, int txSize /*= 128*/) : 02274 SerialPipe(tx, rx, baudrate, rxSize, txSize) 02275 { 02276 if (rx == USBRX) 02277 null.claim("r", stdin); 02278 if (tx == USBTX) { 02279 null.claim("w", stdout); 02280 null.claim("w", stderr); 02281 #ifdef MDM_DEBUG 02282 _debugLevel = -1; 02283 #endif 02284 } 02285 #ifdef TARGET_UBLOX_C027 02286 _onboard = (tx == MDMTXD) && (rx == MDMRXD); 02287 if (_onboard) 02288 c027_mdm_powerOn(false); 02289 #endif 02290 baud(baudrate); 02291 #if DEVICE_SERIAL_FC 02292 if ((rts != NC) || (cts != NC)) 02293 { 02294 Flow flow = (cts == NC) ? RTS : 02295 (rts == NC) ? CTS : RTSCTS ; 02296 set_flow_control(flow, rts, cts); 02297 if (cts != NC) _dev.lpm = LPM_ENABLED; 02298 } 02299 #endif 02300 } 02301 02302 MDMSerial::~MDMSerial(void) 02303 { 02304 powerOff(); 02305 #ifdef TARGET_UBLOX_C027 02306 if (_onboard) 02307 c027_mdm_powerOff(); 02308 #endif 02309 } 02310 02311 int MDMSerial::_send(const void* buf, int len) 02312 { 02313 return put((const char*)buf, len, true/*=blocking*/); 02314 } 02315 02316 int MDMSerial::getLine(char* buffer, int length) 02317 { 02318 return _getLine(&_pipeRx, buffer, length); 02319 } 02320 02321 // ---------------------------------------------------------------- 02322 // USB Implementation 02323 // ---------------------------------------------------------------- 02324 02325 #ifdef HAVE_MDMUSB 02326 MDMUsb::MDMUsb(void) 02327 { 02328 #ifdef MDM_DEBUG 02329 _debugLevel = 1; 02330 #endif 02331 #ifdef TARGET_UBLOX_C027 02332 _onboard = true; 02333 c027_mdm_powerOn(true); 02334 #endif 02335 } 02336 02337 MDMUsb::~MDMUsb(void) 02338 { 02339 powerOff(); 02340 #ifdef TARGET_UBLOX_C027 02341 if (_onboard) 02342 c027_mdm_powerOff(); 02343 #endif 02344 } 02345 02346 int MDMUsb::_send(const void* buf, int len) { return 0; } 02347 02348 int MDMUsb::getLine(char* buffer, int length) { return NOT_FOUND; } 02349 02350 #endif
Generated on Thu Jul 14 2022 07:24:04 by
1.7.2