Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
PPPCellularInterface.cpp
00001 /* Copyright (c) 2017 ARM Limited 00002 * 00003 * Licensed under the Apache License, Version 2.0 (the "License"); 00004 * you may not use this file except in compliance with the License. 00005 * You may obtain a copy of the License at 00006 * 00007 * http://www.apache.org/licenses/LICENSE-2.0 00008 * 00009 * Unless required by applicable law or agreed to in writing, software 00010 * distributed under the License is distributed on an "AS IS" BASIS, 00011 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 * See the License for the specific language governing permissions and 00013 * limitations under the License. 00014 */ 00015 #include "PPPCellularInterface.h" 00016 00017 #if NSAPI_PPP_AVAILABLE 00018 00019 #include <string.h> 00020 #include "nsapi_ppp.h" 00021 #if MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP 00022 #include "utils/APN_db.h" 00023 #endif //MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP 00024 #if defined(FEATURE_COMMON_PAL) 00025 #include "mbed_trace.h" 00026 #define TRACE_GROUP "UCID" 00027 #else 00028 #define tr_debug(...) (void(0)) //dummies if feature common pal is not added 00029 #define tr_info(...) (void(0)) //dummies if feature common pal is not added 00030 #define tr_error(...) (void(0)) //dummies if feature common pal is not added 00031 #endif //defined(FEATURE_COMMON_PAL) 00032 00033 /** 00034 * PDP (packet data profile) Context 00035 */ 00036 #define CTX "1" 00037 00038 /** 00039 * Output Enter sequence for the modem , default CR 00040 */ 00041 #define OUTPUT_ENTER_KEY "\r" 00042 00043 #if MBED_CONF_PPP_CELL_IFACE_AT_PARSER_BUFFER_SIZE 00044 #define AT_PARSER_BUFFER_SIZE MBED_CONF_PPP_CELL_IFACE_AT_PARSER_BUFFER_SIZE //bytes 00045 #else 00046 #define AT_PARSER_BUFFER_SIZE 256 //bytes 00047 #endif //MBED_CONF_PPP_CELL_IFACE_AT_PARSER_BUFFER_SIZE 00048 00049 #if MBED_CONF_PPP_CELL_IFACE_AT_PARSER_TIMEOUT 00050 #define AT_PARSER_TIMEOUT MBED_CONF_PPP_CELL_IFACE_AT_PARSER_TIMEOUT 00051 #else 00052 #define AT_PARSER_TIMEOUT 8*1000 //miliseconds 00053 #endif //MBED_CONF_PPP_CELL_IFACE_AT_PARSER_TIMEOUT 00054 00055 static bool initialized; 00056 static bool set_credentials_api_used; 00057 static bool set_sim_pin_check_request; 00058 static bool change_pin; 00059 static device_info dev_info; 00060 00061 static void parser_abort(ATCmdParser *at) 00062 { 00063 at->abort(); 00064 } 00065 00066 static bool get_CCID(ATCmdParser *at) 00067 { 00068 // Returns the ICCID (Integrated Circuit Card ID) of the SIM-card. 00069 // ICCID is a serial number identifying the SIM. 00070 bool success = at->send("AT+CCID") && at->recv("+CCID: %20[^\n]\nOK\n", dev_info.ccid); 00071 tr_debug("DevInfo: CCID=%s", dev_info.ccid); 00072 return success; 00073 } 00074 00075 static bool get_IMSI(ATCmdParser *at) 00076 { 00077 // International mobile subscriber identification 00078 bool success = at->send("AT+CIMI") && at->recv("%15[^\n]\nOK\n", dev_info.imsi); 00079 tr_debug("DevInfo: IMSI=%s", dev_info.imsi); 00080 return success; 00081 } 00082 00083 static bool get_IMEI(ATCmdParser *at) 00084 { 00085 // International mobile equipment identifier 00086 bool success = at->send("AT+CGSN") && at->recv("%15[^\n]\nOK\n", dev_info.imei); 00087 tr_debug("DevInfo: IMEI=%s", dev_info.imei); 00088 return success; 00089 } 00090 00091 static bool get_MEID(ATCmdParser *at) 00092 { 00093 // Mobile equipment identifier 00094 bool success = at->send("AT+GSN") 00095 && at->recv("%18[^\n]\nOK\n", dev_info.meid); 00096 tr_debug("DevInfo: MEID=%s", dev_info.meid); 00097 return success; 00098 } 00099 00100 static bool set_CMGF(ATCmdParser *at) 00101 { 00102 // Preferred message format 00103 // set AT+CMGF=[mode] , 0 PDU mode, 1 text mode 00104 bool success = at->send("AT+CMGF=1") && at->recv("OK"); 00105 return success; 00106 } 00107 00108 static bool set_CNMI(ATCmdParser *at) 00109 { 00110 // New SMS indication configuration 00111 // set AT+CMTI=[mode, index] , 0 PDU mode, 1 text mode 00112 // Multiple URCs for SMS, i.e., CMT, CMTI, UCMT, CBMI, CDSI as DTE could be following any of these SMS formats 00113 bool success = at->send("AT+CNMI=2," CTX) && at->recv("OK"); 00114 return success; 00115 } 00116 00117 static void CMTI_URC(ATCmdParser *at) 00118 { 00119 // our CMGF = 1, i.e., text mode. So we expect response in this format: 00120 //+CMTI: <mem>,<index>, 00121 at->recv(": %*u,%*u"); 00122 tr_info("New SMS received"); 00123 00124 } 00125 00126 static void CMT_URC(ATCmdParser *at) 00127 { 00128 // our CMGF = 1, i.e., text mode. So we expect response in this format: 00129 //+CMT: <oa>,[<alpha>],<scts>[,<tooa>, 00130 //<fo>,<pid>,<dcs>,<sca>,<tosca>, 00131 //<length>]<CR><LF><data> 00132 // By default detailed SMS header CSDH=0 , so we are not expecting [,<tooa>, 00133 //<fo>,<pid>,<dcs>,<sca>,<tosca> 00134 char sms[50]; 00135 char service_timestamp[15]; 00136 at->recv(": %49[^\"]\",,%14[^\"]\"\n", sms, service_timestamp); 00137 00138 tr_info("SMS:%s, %s", service_timestamp, sms); 00139 00140 } 00141 00142 static bool set_atd(ATCmdParser *at) 00143 { 00144 bool success = at->send("ATD*99***" CTX "#") && at->recv("CONNECT"); 00145 00146 return success; 00147 } 00148 00149 /** 00150 * Enables or disables SIM pin check lock 00151 */ 00152 static nsapi_error_t do_sim_pin_check(ATCmdParser *at, const char *pin) 00153 { 00154 bool success; 00155 if (set_sim_pin_check_request) { 00156 /* use the SIM locked */ 00157 success = at->send("AT+CLCK=\"SC\",1,\"%s\"", pin) && at->recv("OK"); 00158 } else { 00159 /* use the SIM unlocked */ 00160 success = at->send("AT+CLCK=\"SC\",0,\"%s\"",pin) && at->recv("OK"); 00161 } 00162 00163 if (success) return NSAPI_ERROR_OK ; 00164 00165 return NSAPI_ERROR_AUTH_FAILURE ; 00166 } 00167 00168 /** 00169 * Change the pin code for the SIM card 00170 */ 00171 static nsapi_error_t do_change_sim_pin(ATCmdParser *at, const char *old_pin, const char *new_pin) 00172 { 00173 /* changes the SIM pin */ 00174 bool success = at->send("AT+CPWD=\"SC\",\"%s\",\"%s\"", old_pin, new_pin) && at->recv("OK"); 00175 if (success) { 00176 return NSAPI_ERROR_OK ; 00177 } 00178 00179 return NSAPI_ERROR_AUTH_FAILURE ; 00180 } 00181 00182 static void set_nwk_reg_status_csd(unsigned int status) 00183 { 00184 switch (status) { 00185 case CSD_NOT_REGISTERED_NOT_SEARCHING: 00186 case CSD_NOT_REGISTERED_SEARCHING: 00187 break; 00188 case CSD_REGISTERED: 00189 case CSD_REGISTERED_ROAMING: 00190 tr_debug("Registered for circuit switched service"); 00191 break; 00192 case CSD_REGISTRATION_DENIED: 00193 tr_debug("Circuit switched service denied"); 00194 break; 00195 case CSD_UNKNOWN_COVERAGE: 00196 tr_debug("Out of circuit switched service coverage"); 00197 break; 00198 case CSD_SMS_ONLY: 00199 tr_debug("SMS service only"); 00200 break; 00201 case CSD_SMS_ONLY_ROAMING: 00202 tr_debug("SMS service only"); 00203 break; 00204 case CSD_CSFB_NOT_PREFERRED: 00205 tr_debug("Registered for circuit switched service with CSFB not preferred"); 00206 break; 00207 default: 00208 tr_debug("Unknown circuit switched service registration status. %u", status); 00209 break; 00210 } 00211 00212 dev_info.reg_status_csd = static_cast<nwk_registration_status_csd>(status); 00213 } 00214 00215 static void set_nwk_reg_status_psd(unsigned int status) 00216 { 00217 switch (status) { 00218 case PSD_NOT_REGISTERED_NOT_SEARCHING: 00219 case PSD_NOT_REGISTERED_SEARCHING: 00220 break; 00221 case PSD_REGISTERED: 00222 case PSD_REGISTERED_ROAMING: 00223 tr_debug("Registered for packet switched service"); 00224 break; 00225 case PSD_REGISTRATION_DENIED: 00226 tr_debug("Packet switched service denied"); 00227 break; 00228 case PSD_UNKNOWN_COVERAGE: 00229 tr_debug("Out of packet switched service coverage"); 00230 break; 00231 case PSD_EMERGENCY_SERVICES_ONLY: 00232 tr_debug("Limited access for packet switched service. Emergency use only."); 00233 break; 00234 default: 00235 tr_debug("Unknown packet switched service registration status. %u", status); 00236 break; 00237 } 00238 00239 dev_info.reg_status_psd = static_cast<nwk_registration_status_psd>(status); 00240 } 00241 00242 static bool is_registered_csd() 00243 { 00244 return (dev_info.reg_status_csd == CSD_REGISTERED) || 00245 (dev_info.reg_status_csd == CSD_REGISTERED_ROAMING) || 00246 (dev_info.reg_status_csd == CSD_CSFB_NOT_PREFERRED); 00247 } 00248 00249 static bool is_registered_psd() 00250 { 00251 return (dev_info.reg_status_psd == PSD_REGISTERED) || 00252 (dev_info.reg_status_psd == PSD_REGISTERED_ROAMING); 00253 } 00254 00255 PPPCellularInterface::PPPCellularInterface(FileHandle *fh, bool debug) 00256 { 00257 _new_pin = NULL; 00258 _pin = NULL; 00259 _at = NULL; 00260 _apn = "internet"; 00261 _uname = NULL; 00262 _pwd = NULL; 00263 _fh = fh; 00264 _debug_trace_on = debug; 00265 _stack = DEFAULT_STACK; 00266 dev_info.reg_status_csd = CSD_NOT_REGISTERED_NOT_SEARCHING; 00267 dev_info.reg_status_psd = PSD_NOT_REGISTERED_NOT_SEARCHING; 00268 dev_info.ppp_connection_up = false; 00269 } 00270 00271 00272 PPPCellularInterface::~PPPCellularInterface() 00273 { 00274 delete _at; 00275 } 00276 00277 void PPPCellularInterface::enable_hup(bool) 00278 { 00279 //meant to be overridden 00280 } 00281 00282 void PPPCellularInterface::modem_init() 00283 { 00284 //meant to be overridden 00285 } 00286 00287 void PPPCellularInterface::modem_deinit() 00288 { 00289 //meant to be overridden 00290 } 00291 00292 void PPPCellularInterface::modem_power_up() 00293 { 00294 //meant to be overridden 00295 } 00296 00297 void PPPCellularInterface::modem_power_down() 00298 { 00299 //meant to be overridden 00300 } 00301 00302 void PPPCellularInterface::modem_debug_on(bool on) 00303 { 00304 _debug_trace_on = on; 00305 } 00306 00307 void PPPCellularInterface::connection_status_cb(Callback<void(nsapi_error_t)> cb) 00308 { 00309 _connection_status_cb = cb; 00310 } 00311 00312 /** 00313 * Public API. Sets up the flag for the driver to enable or disable SIM pin check 00314 * at the next boot. 00315 */ 00316 void PPPCellularInterface::set_sim_pin_check(bool check) 00317 { 00318 set_sim_pin_check_request = check; 00319 } 00320 00321 /** 00322 * Public API. Sets up the flag for the driver to change pin code for SIM card 00323 */ 00324 void PPPCellularInterface::set_new_sim_pin(const char *new_pin) 00325 { 00326 change_pin = true; 00327 _new_pin = new_pin; 00328 } 00329 00330 bool PPPCellularInterface::nwk_registration(uint8_t nwk_type) 00331 { 00332 bool success = false; 00333 bool registered = false; 00334 00335 char str[35]; 00336 int retcode; 00337 int retry_counter = 0; 00338 unsigned int reg_status; 00339 00340 success = nwk_type == PACKET_SWITCHED ? 00341 _at->send("AT+CGREG=0") : 00342 _at->send("AT+CREG=0") && _at->recv("OK\n"); 00343 00344 success = _at->send("AT+COPS=0") //initiate auto-registration 00345 && _at->recv("OK"); 00346 if (!success) { 00347 tr_error("Modem not responding."); 00348 return false; 00349 } 00350 00351 //Network search 00352 //If not registered after 60 attempts, i.e., 30 seconds wait, give up 00353 tr_debug("Searching Network ..."); 00354 00355 while (!registered) { 00356 00357 if (retry_counter > 60) { 00358 success = false; 00359 goto give_up; 00360 } 00361 00362 success = nwk_type == PACKET_SWITCHED ? 00363 _at->send("AT+CGREG?") 00364 && _at->recv("+CGREG: %34[^\n]\n", str) 00365 && _at->recv("OK\n") : 00366 _at->send("AT+CREG?") 00367 && _at->recv("+CREG: %34[^\n]\n", str) 00368 && _at->recv("OK\n"); 00369 00370 retcode = sscanf(str, "%*u,%u", ®_status); 00371 00372 if (retcode >= 1) { 00373 if (nwk_type == PACKET_SWITCHED) { 00374 set_nwk_reg_status_psd(reg_status); 00375 if (is_registered_psd()) { 00376 registered = true; 00377 } 00378 } else if (nwk_type == CIRCUIT_SWITCHED) { 00379 set_nwk_reg_status_csd(reg_status); 00380 if (is_registered_csd()) { 00381 registered = true; 00382 } 00383 } 00384 } 00385 00386 if (registered) { 00387 break; 00388 } else { 00389 wait_ms(500); 00390 } 00391 00392 retry_counter++; 00393 } 00394 00395 give_up: 00396 return registered; 00397 } 00398 00399 bool PPPCellularInterface::is_connected() 00400 { 00401 return dev_info.ppp_connection_up; 00402 } 00403 00404 // Get the SIM card going. 00405 nsapi_error_t PPPCellularInterface::initialize_sim_card() 00406 { 00407 nsapi_error_t nsapi_error = NSAPI_ERROR_AUTH_FAILURE ; 00408 int retry_count = 0; 00409 bool done = false; 00410 00411 /* SIM initialization may take a significant amount, so an error is 00412 * kind of expected. We should retry 10 times until we succeed or timeout. */ 00413 for (retry_count = 0; !done && (retry_count < 10); retry_count++) { 00414 char pinstr[16]; 00415 00416 if (_at->send("AT+CPIN?") && _at->recv("+CPIN: %15[^\n]\nOK\n", pinstr)) { 00417 if (strcmp(pinstr, "SIM PIN") == 0) { 00418 if (!_at->send("AT+CPIN=\"%s\"", _pin) || !_at->recv("OK")) { 00419 tr_debug("PIN correct"); 00420 nsapi_error = NSAPI_ERROR_OK ; 00421 } 00422 } else if (strcmp(pinstr, "READY") == 0) { 00423 tr_debug("SIM Ready"); 00424 nsapi_error = NSAPI_ERROR_OK ; 00425 done = true; 00426 } else { 00427 tr_debug("Unexpected response from SIM: \"%s\"", pinstr); 00428 } 00429 } 00430 00431 /* wait for a second before retry */ 00432 wait_ms(1000); 00433 } 00434 00435 if (!done) { 00436 tr_error("SIM not ready."); 00437 } 00438 00439 return nsapi_error; 00440 } 00441 00442 void PPPCellularInterface::set_sim_pin(const char *pin) { 00443 /* overwrite the default pin by user provided pin */ 00444 _pin = pin; 00445 } 00446 00447 nsapi_error_t PPPCellularInterface::setup_context_and_credentials() 00448 { 00449 bool success; 00450 00451 if (!_apn) { 00452 return NSAPI_ERROR_PARAMETER ; 00453 } 00454 00455 #if NSAPI_PPP_IPV4_AVAILABLE && NSAPI_PPP_IPV6_AVAILABLE 00456 const char ipv4v6_pdp_type[] = {"IPV4V6"}; 00457 const char ipv4_pdp_type[] = {"IP"}; 00458 const char *pdp_type = ipv4v6_pdp_type; 00459 _stack = IPV4V6_STACK; 00460 #elif NSAPI_PPP_IPV6_AVAILABLE 00461 const char pdp_type[] = {"IPV6"}; 00462 #elif NSAPI_PPP_IPV4_AVAILABLE 00463 const char pdp_type[] = {"IP"}; 00464 #endif 00465 const char *auth = _uname && _pwd ? "CHAP:" : ""; 00466 00467 #if NSAPI_PPP_IPV4_AVAILABLE && NSAPI_PPP_IPV6_AVAILABLE 00468 retry_without_dual_stack: 00469 #endif 00470 success = _at->send("AT" 00471 "+FCLASS=0;" // set to connection (ATD) to data mode 00472 "+CGDCONT=" CTX ",\"%s\",\"%s%s\"", 00473 pdp_type, auth, _apn 00474 ) 00475 && _at->recv("OK"); 00476 00477 #if NSAPI_PPP_IPV4_AVAILABLE && NSAPI_PPP_IPV6_AVAILABLE 00478 if (_stack == IPV4V6_STACK) { 00479 if (!success) { 00480 // fallback to ipv4 00481 pdp_type = ipv4_pdp_type; 00482 _stack = IPV4_STACK; 00483 goto retry_without_dual_stack; 00484 } 00485 } 00486 #endif 00487 00488 if (!success) { 00489 _at->recv("OK"); 00490 } 00491 00492 return success ? NSAPI_ERROR_OK : NSAPI_ERROR_PARAMETER ; 00493 00494 } 00495 00496 void PPPCellularInterface::set_credentials(const char *apn, const char *uname, 00497 const char *pwd) 00498 { 00499 _apn = apn; 00500 _uname = uname; 00501 _pwd = pwd; 00502 set_credentials_api_used = true; 00503 } 00504 00505 00506 00507 void PPPCellularInterface::setup_at_parser() 00508 { 00509 if (_at) { 00510 return; 00511 } 00512 00513 _at = new ATCmdParser(_fh, OUTPUT_ENTER_KEY, AT_PARSER_BUFFER_SIZE, AT_PARSER_TIMEOUT, 00514 _debug_trace_on ? true : false); 00515 00516 /* Error cases, out of band handling */ 00517 _at->oob("ERROR", callback(parser_abort, _at)); 00518 _at->oob("+CME ERROR", callback(parser_abort, _at)); 00519 _at->oob("+CMS ERROR", callback(parser_abort, _at)); 00520 _at->oob("NO CARRIER", callback(parser_abort, _at)); 00521 00522 /* URCs, handled out of band */ 00523 _at->oob("+CMT", callback(CMT_URC, _at)); 00524 _at->oob("+CMTI", callback(CMTI_URC, _at)); 00525 } 00526 00527 void PPPCellularInterface::shutdown_at_parser() 00528 { 00529 delete _at; 00530 _at = NULL; 00531 } 00532 00533 nsapi_error_t PPPCellularInterface::connect(const char *sim_pin, const char *apn, const char *uname, const char *pwd) 00534 { 00535 if (!sim_pin) { 00536 return NSAPI_ERROR_PARAMETER ; 00537 } 00538 00539 if (apn) { 00540 _apn = apn; 00541 } 00542 00543 if (uname && pwd) { 00544 _uname = uname; 00545 _pwd = pwd; 00546 } else { 00547 _uname = NULL; 00548 _pwd = NULL; 00549 } 00550 00551 _pin = sim_pin; 00552 00553 return connect(); 00554 } 00555 00556 nsapi_error_t PPPCellularInterface::connect() 00557 { 00558 nsapi_error_t retcode; 00559 bool success; 00560 bool did_init = false; 00561 const char *apn_config = NULL; 00562 00563 if (dev_info.ppp_connection_up) { 00564 return NSAPI_ERROR_IS_CONNECTED ; 00565 } 00566 00567 do { 00568 retry_init: 00569 00570 /* setup AT parser */ 00571 setup_at_parser(); 00572 00573 if (!initialized) { 00574 00575 /* If we have hangup (eg DCD) detection, we don't want it active 00576 * as long as we are using ATCmdParser. 00577 * As soon as we get into data mode, we will turn it back on. */ 00578 enable_hup(false); 00579 00580 if (!power_up()) { 00581 return NSAPI_ERROR_DEVICE_ERROR ; 00582 } 00583 00584 retcode = initialize_sim_card(); 00585 if (retcode != NSAPI_ERROR_OK ) { 00586 return retcode; 00587 } 00588 00589 success = nwk_registration(PACKET_SWITCHED) //perform network registration 00590 && get_CCID(_at)//get integrated circuit ID of the SIM 00591 && get_IMSI(_at)//get international mobile subscriber information 00592 && get_IMEI(_at)//get international mobile equipment identifier 00593 && get_MEID(_at)//its same as IMEI 00594 && set_CMGF(_at)//set message format for SMS 00595 && set_CNMI(_at);//set new SMS indication 00596 00597 if (!success) { 00598 return NSAPI_ERROR_NO_CONNECTION ; 00599 } 00600 00601 #if MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP 00602 if (!apn_config) { 00603 apn_config = apnconfig(dev_info.imsi); 00604 } 00605 #endif 00606 00607 /* Check if user want skip SIM pin checking on boot up */ 00608 if (set_sim_pin_check_request) { 00609 retcode = do_sim_pin_check(_at, _pin); 00610 if (retcode != NSAPI_ERROR_OK ) { 00611 return retcode; 00612 } 00613 /* set this request to false, as it is unnecessary to repeat in case of retry */ 00614 set_sim_pin_check_request = false; 00615 } 00616 00617 /* check if the user requested a sim pin change */ 00618 if (change_pin) { 00619 retcode = do_change_sim_pin(_at, _pin, _new_pin); 00620 if (retcode != NSAPI_ERROR_OK ) { 00621 return retcode; 00622 } 00623 /* set this request to false, as it is unnecessary to repeat in case of retry */ 00624 change_pin = false; 00625 } 00626 00627 #if MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP 00628 if (apn_config) { 00629 _apn = _APN_GET(apn_config); 00630 _uname = _APN_GET(apn_config); 00631 _pwd = _APN_GET(apn_config); 00632 tr_info("Looked up APN %s.", _apn); 00633 } 00634 #endif 00635 00636 //sets up APN and IP protocol for external PDP context 00637 retcode = setup_context_and_credentials(); 00638 if (retcode != NSAPI_ERROR_OK ) { 00639 return retcode; 00640 } 00641 00642 if (!success) { 00643 shutdown_at_parser(); 00644 return NSAPI_ERROR_NO_CONNECTION ; 00645 } 00646 00647 initialized = true; 00648 did_init = true; 00649 } else { 00650 /* If we were already initialized, we expect to receive NO_CARRIER response 00651 * from the modem as we were kicked out of Data mode */ 00652 _at->recv("NO CARRIER"); 00653 success = _at->send("AT") && _at->recv("OK"); 00654 } 00655 00656 /* Attempt to enter data mode */ 00657 success = set_atd(_at); //enter into Data mode with the modem 00658 if (!success) { 00659 power_down(); 00660 initialized = false; 00661 00662 /* if we were previously initialized , i.e., not in this particular attempt, 00663 * we want to re-initialize */ 00664 if (!did_init) { 00665 goto retry_init; 00666 } 00667 00668 /* shutdown AT parser before notifying application of the failure */ 00669 shutdown_at_parser(); 00670 00671 return NSAPI_ERROR_NO_CONNECTION ; 00672 } 00673 00674 /* This is the success case. 00675 * Save RAM, discard AT Parser as we have entered Data mode. */ 00676 shutdown_at_parser(); 00677 00678 /* We now want hangup (e.g., DCD) detection if available */ 00679 enable_hup(true); 00680 00681 /* Initialize PPP 00682 * mbed_ppp_init() is a blocking call, it will block until 00683 * connected, or timeout after 30 seconds*/ 00684 retcode = nsapi_ppp_connect(_fh, _connection_status_cb, _uname, _pwd, _stack); 00685 if (retcode == NSAPI_ERROR_OK ) { 00686 dev_info.ppp_connection_up = true; 00687 } 00688 00689 }while(!dev_info.ppp_connection_up && apn_config && *apn_config); 00690 00691 return retcode; 00692 } 00693 00694 /** 00695 * User initiated disconnect 00696 * 00697 * Disconnects from PPP connection only and brings down the underlying network 00698 * interface 00699 */ 00700 nsapi_error_t PPPCellularInterface::disconnect() 00701 { 00702 nsapi_error_t ret = nsapi_ppp_disconnect(_fh); 00703 if (ret == NSAPI_ERROR_OK ) { 00704 dev_info.ppp_connection_up = false; 00705 return NSAPI_ERROR_OK ; 00706 } 00707 00708 return ret; 00709 } 00710 00711 const char *PPPCellularInterface::get_ip_address() 00712 { 00713 return nsapi_ppp_get_ip_addr(_fh); 00714 } 00715 00716 const char *PPPCellularInterface::get_netmask() 00717 { 00718 return nsapi_ppp_get_netmask(_fh); 00719 } 00720 00721 const char *PPPCellularInterface::get_gateway() 00722 { 00723 return nsapi_ppp_get_ip_addr(_fh); 00724 } 00725 00726 /** Power down modem 00727 * Uses AT command to do it */ 00728 void PPPCellularInterface::power_down() 00729 { 00730 modem_power_down(); 00731 modem_deinit(); 00732 } 00733 00734 /** 00735 * Powers up the modem 00736 * 00737 * Enables the GPIO lines to the modem and then wriggles the power line in short pulses. 00738 */ 00739 bool PPPCellularInterface::power_up() 00740 { 00741 /* Initialize GPIO lines */ 00742 modem_init(); 00743 /* Give modem a little time to settle down */ 00744 wait(0.25); 00745 00746 bool success = false; 00747 00748 int retry_count = 0; 00749 while (true) { 00750 modem_power_up(); 00751 /* Modem tends to spit out noise during power up - don't confuse the parser */ 00752 _at->flush(); 00753 /* It is mandatory to avoid sending data to the serial port during the first 200 ms 00754 * of the module startup. Telit_xE910 Global form factor App note. 00755 * Not necessary for all types of modems however. Let's wait just to be on the safe side */ 00756 wait_ms(200); 00757 _at->set_timeout(1000); 00758 if (_at->send("AT") && _at->recv("OK")) { 00759 tr_info("Modem Ready."); 00760 break; 00761 } 00762 00763 if (++retry_count > 10) { 00764 goto failure; 00765 } 00766 } 00767 00768 _at->set_timeout(8000); 00769 00770 /*For more details regarding DCD and DTR circuitry, please refer to Modem AT manual */ 00771 success = _at->send("AT" 00772 "E0;" //turn off modem echoing 00773 "+CMEE=2;"//turn on verbose responses 00774 "&K0"//turn off RTC/CTS handshaking 00775 "+IPR=115200;"//setup baud rate 00776 "&C1;"//set DCD circuit(109), changes in accordance with the carrier detect status 00777 "&D0")//set DTR circuit, we ignore the state change of DTR 00778 && _at->recv("OK"); 00779 00780 if (!success) { 00781 goto failure; 00782 } 00783 00784 /* If everything alright, return from here with success*/ 00785 return success; 00786 00787 failure: 00788 tr_error("Preliminary modem setup failed."); 00789 return false; 00790 } 00791 00792 /** 00793 * Get a pointer to the underlying network stack 00794 */ 00795 NetworkStack *PPPCellularInterface::get_stack() 00796 { 00797 return nsapi_ppp_get_stack(); 00798 } 00799 00800 #endif // NSAPI_PPP_AVAILABLE
Generated on Sun Jul 17 2022 08:25:29 by 1.7.2