Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AT_CellularDevice.cpp Source File

AT_CellularDevice.cpp

00001 /*
00002  * Copyright (c) 2017, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "rtos/ThisThread.h"
00019 #include "CellularUtil.h"
00020 #include "AT_CellularDevice.h"
00021 #include "AT_CellularInformation.h"
00022 #include "AT_CellularNetwork.h"
00023 #include "AT_CellularSMS.h"
00024 #include "AT_CellularContext.h"
00025 #include "AT_CellularStack.h"
00026 #include "CellularLog.h"
00027 #include "ATHandler.h"
00028 #if (DEVICE_SERIAL && DEVICE_INTERRUPTIN) || defined(DOXYGEN_ONLY)
00029 #include "UARTSerial.h"
00030 #endif // #if DEVICE_SERIAL
00031 #include "FileHandle.h"
00032 #include <ctype.h>
00033 
00034 using namespace mbed_cellular_util;
00035 using namespace events;
00036 using namespace mbed;
00037 
00038 #define DEFAULT_AT_TIMEOUT 1000 // at default timeout in milliseconds
00039 const int MAX_SIM_RESPONSE_LENGTH = 16;
00040 
00041 AT_CellularDevice::AT_CellularDevice(FileHandle *fh) : CellularDevice(fh),
00042 #if MBED_CONF_CELLULAR_USE_SMS
00043     _sms(0),
00044 #endif // MBED_CONF_CELLULAR_USE_SMS
00045     _network(0), _information(0), _context_list(0), _default_timeout(DEFAULT_AT_TIMEOUT),
00046     _modem_debug_on(false), _property_array(NULL)
00047 {
00048     MBED_ASSERT(fh);
00049     _at = get_at_handler(fh);
00050     MBED_ASSERT(_at);
00051 }
00052 
00053 AT_CellularDevice::~AT_CellularDevice()
00054 {
00055     if (get_property(PROPERTY_AT_CGEREP)) {
00056         _at->set_urc_handler("+CGEV: NW DEACT", 0);
00057         _at->set_urc_handler("+CGEV: ME DEACT", 0);
00058         _at->set_urc_handler("+CGEV: NW PDN D", 0);
00059         _at->set_urc_handler("+CGEV: ME PDN D", 0);
00060     }
00061 
00062     // make sure that all is deleted even if somewhere close was not called and reference counting is messed up.
00063     _network_ref_count = 1;
00064 #if MBED_CONF_CELLULAR_USE_SMS
00065     _sms_ref_count = 1;
00066 #endif // MBED_CONF_CELLULAR_USE_SMS
00067     _info_ref_count = 1;
00068 
00069     close_network();
00070 
00071 #if MBED_CONF_CELLULAR_USE_SMS
00072     close_sms();
00073 #endif //MBED_CONF_CELLULAR_USE_SMS
00074 
00075     close_information();
00076 
00077     AT_CellularContext *curr = _context_list;
00078     AT_CellularContext *next;
00079     while (curr) {
00080         next = (AT_CellularContext *)curr->_next;
00081         ATHandler *at = &curr->get_at_handler();
00082         delete curr;
00083         curr = next;
00084         release_at_handler(at);
00085     }
00086 
00087     release_at_handler(_at);
00088 }
00089 
00090 void AT_CellularDevice::set_at_urcs_impl()
00091 {
00092 }
00093 
00094 void AT_CellularDevice::set_at_urcs()
00095 {
00096     if (get_property(PROPERTY_AT_CGEREP)) {
00097         _at->set_urc_handler("+CGEV: NW DEACT", callback(this, &AT_CellularDevice::urc_nw_deact));
00098         _at->set_urc_handler("+CGEV: ME DEACT", callback(this, &AT_CellularDevice::urc_nw_deact));
00099         _at->set_urc_handler("+CGEV: NW PDN D", callback(this, &AT_CellularDevice::urc_pdn_deact));
00100         _at->set_urc_handler("+CGEV: ME PDN D", callback(this, &AT_CellularDevice::urc_pdn_deact));
00101     }
00102 
00103     set_at_urcs_impl();
00104 }
00105 
00106 void AT_CellularDevice::setup_at_handler()
00107 {
00108     set_at_urcs();
00109 
00110     _at->set_send_delay(get_send_delay());
00111 }
00112 
00113 void AT_CellularDevice::urc_nw_deact()
00114 {
00115     // The network has forced a context deactivation
00116     char buf[10];
00117     _at->read_string(buf, 10);
00118     int cid;
00119     if (isalpha(buf[0])) {
00120         // this is +CGEV: NW DEACT <PDP_type>, <PDP_addr>, [<cid>]
00121         // or      +CGEV: ME DEACT <PDP_type>, <PDP_addr>, [<cid>]
00122         _at->skip_param(); // skip <PDP_addr>
00123         cid = _at->read_int();
00124     } else {
00125         // this is +CGEV: NW DEACT <p_cid>, <cid>, <event_type>[,<WLAN_Offload>]
00126         // or      +CGEV: ME DEACT <p_cid>, <cid>, <event_type
00127         cid = _at->read_int();
00128     }
00129     send_disconnect_to_context(cid);
00130 }
00131 
00132 void AT_CellularDevice::urc_pdn_deact()
00133 {
00134     // The network has deactivated a context
00135     // The mobile termination has deactivated a context.
00136     // +CGEV: NW PDN DEACT <cid>[,<WLAN_Offload>]
00137     // +CGEV: ME PDN DEACT <cid>
00138     _at->set_delimiter(' ');
00139     _at->skip_param();
00140     _at->set_delimiter(',');
00141 
00142     int cid = _at->read_int();
00143     send_disconnect_to_context(cid);
00144 }
00145 
00146 void AT_CellularDevice::send_disconnect_to_context(int cid)
00147 {
00148     tr_debug("send_disconnect_to_context, cid: %d", cid);
00149     AT_CellularContext *curr = _context_list;
00150     while (curr) {
00151         if (cid >= 0) {
00152             if (curr->get_cid() == cid) {
00153                 CellularDevice::cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_DISCONNECTED , curr);
00154                 break;
00155             }
00156         } else {
00157             CellularDevice::cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_DISCONNECTED );
00158         }
00159         curr = (AT_CellularContext *)curr->_next;
00160     }
00161 }
00162 
00163 nsapi_error_t AT_CellularDevice::hard_power_on()
00164 {
00165     return NSAPI_ERROR_OK ;
00166 }
00167 
00168 nsapi_error_t AT_CellularDevice::hard_power_off()
00169 {
00170     return NSAPI_ERROR_OK ;
00171 }
00172 
00173 nsapi_error_t AT_CellularDevice::soft_power_on()
00174 {
00175     return NSAPI_ERROR_OK ;
00176 }
00177 
00178 nsapi_error_t AT_CellularDevice::soft_power_off()
00179 {
00180     return NSAPI_ERROR_OK ;
00181 }
00182 
00183 // each parser is associated with one filehandle (that is UART)
00184 ATHandler *AT_CellularDevice::get_at_handler(FileHandle *fileHandle)
00185 {
00186     if (!fileHandle) {
00187         fileHandle = _fh;
00188     }
00189 
00190     return ATHandler::get_instance(fileHandle, _queue, _default_timeout,
00191                                    "\r", get_send_delay(), _modem_debug_on);
00192 }
00193 
00194 ATHandler *AT_CellularDevice::get_at_handler()
00195 {
00196     return get_at_handler(NULL);
00197 }
00198 
00199 nsapi_error_t AT_CellularDevice::release_at_handler(ATHandler *at_handler)
00200 {
00201     if (at_handler) {
00202         return at_handler->close();
00203     } else {
00204         return NSAPI_ERROR_PARAMETER ;
00205     }
00206 }
00207 
00208 nsapi_error_t AT_CellularDevice::get_sim_state(SimState &state)
00209 {
00210     char simstr[MAX_SIM_RESPONSE_LENGTH];
00211     _at->lock();
00212     _at->flush();
00213     nsapi_error_t error = _at->at_cmd_str("+CPIN", "?", simstr, sizeof(simstr));
00214     ssize_t len = strlen(simstr);
00215 #if MBED_CONF_MBED_TRACE_ENABLE
00216     device_err_t err = _at->get_last_device_error();
00217 #endif
00218     _at->unlock();
00219 
00220     if (len != -1) {
00221         if (len >= 5 && memcmp(simstr, "READY", 5) == 0) {
00222             state = SimStateReady;
00223         } else if (len >= 7 && memcmp(simstr, "SIM PIN", 7) == 0) {
00224             state = SimStatePinNeeded;
00225         } else if (len >= 7 && memcmp(simstr, "SIM PUK", 7) == 0) {
00226             state = SimStatePukNeeded;
00227         } else {
00228             simstr[len] = '\0';
00229             state = SimStateUnknown;
00230         }
00231     } else {
00232         tr_warn("SIM not readable.");
00233         state = SimStateUnknown; // SIM may not be ready yet or +CPIN may be unsupported command
00234     }
00235 #if MBED_CONF_MBED_TRACE_ENABLE
00236     switch (state) {
00237         case SimStatePinNeeded:
00238             tr_info("SIM PIN required");
00239             break;
00240         case SimStatePukNeeded:
00241             tr_error("SIM PUK required");
00242             break;
00243         case SimStateUnknown:
00244             if (err.errType == DeviceErrorTypeErrorCME && err.errCode == 14) {
00245                 tr_info("SIM busy");
00246             } else {
00247                 tr_warn("SIM state unknown");
00248             }
00249             break;
00250         default:
00251             tr_info("SIM is ready");
00252             break;
00253     }
00254 #endif
00255     return error;
00256 }
00257 
00258 nsapi_error_t AT_CellularDevice::set_pin(const char *sim_pin)
00259 {
00260     // if SIM is already in ready state then settings the PIN
00261     // will return error so let's check the state before settings the pin.
00262     SimState state = SimStateUnknown;
00263     if (get_sim_state(state) == NSAPI_ERROR_OK  && state == SimStateReady) {
00264         return NSAPI_ERROR_OK ;
00265     }
00266 
00267     if (sim_pin == NULL) {
00268         return NSAPI_ERROR_PARAMETER ;
00269     }
00270 
00271     _at->lock();
00272 
00273     const bool stored_debug_state = _at->get_debug();
00274     _at->set_debug(false);
00275 
00276     _at->at_cmd_discard("+CPIN", "=", "%s", sim_pin);
00277 
00278     _at->set_debug(stored_debug_state);
00279 
00280     return _at->unlock_return_error();
00281 }
00282 
00283 CellularContext *AT_CellularDevice::get_context_list() const
00284 {
00285     return _context_list;
00286 }
00287 
00288 #if (DEVICE_SERIAL && DEVICE_INTERRUPTIN) || defined(DOXYGEN_ONLY)
00289 CellularContext *AT_CellularDevice::create_context(UARTSerial *serial, const char *const apn, PinName dcd_pin,
00290                                                    bool active_high, bool cp_req, bool nonip_req)
00291 {
00292     // Call FileHandle base version - explict upcast to avoid recursing into ourselves
00293     CellularContext *ctx = create_context(static_cast<FileHandle *>(serial), apn, cp_req, nonip_req);
00294     if (serial) {
00295         ctx->set_file_handle(serial, dcd_pin, active_high);
00296     }
00297     return ctx;
00298 }
00299 #endif // #if DEVICE_SERIAL
00300 
00301 CellularContext *AT_CellularDevice::create_context(FileHandle *fh, const char *apn, bool cp_req, bool nonip_req)
00302 {
00303     AT_CellularContext *ctx = create_context_impl(*get_at_handler(fh), apn, cp_req, nonip_req);
00304     AT_CellularContext *curr = _context_list;
00305 
00306     if (_context_list == NULL) {
00307         _context_list = ctx;
00308         return ctx;
00309     }
00310 
00311     AT_CellularContext *prev = NULL;
00312     while (curr) {
00313         prev = curr;
00314         curr = (AT_CellularContext *)curr->_next;
00315     }
00316 
00317     prev->_next = ctx;
00318     return ctx;
00319 }
00320 
00321 AT_CellularContext *AT_CellularDevice::create_context_impl(ATHandler &at, const char *apn, bool cp_req, bool nonip_req)
00322 {
00323     if (cp_req) {
00324 
00325     }
00326     return new AT_CellularContext(at, this, apn, cp_req, nonip_req);
00327 }
00328 
00329 void AT_CellularDevice::delete_context(CellularContext *context)
00330 {
00331     AT_CellularContext *curr = _context_list;
00332     AT_CellularContext *prev = NULL;
00333     while (curr) {
00334         if (curr == context) {
00335             if (prev == NULL) {
00336                 _context_list = (AT_CellularContext *)curr->_next;
00337             } else {
00338                 prev->_next = curr->_next;
00339             }
00340         }
00341         prev = curr;
00342         curr = (AT_CellularContext *)curr->_next;
00343     }
00344     curr = (AT_CellularContext *)context;
00345     ATHandler *at = NULL;
00346     if (curr) {
00347         at = &curr->get_at_handler();
00348     }
00349     delete (AT_CellularContext *)context;
00350     release_at_handler(at);
00351 }
00352 
00353 CellularNetwork *AT_CellularDevice::open_network(FileHandle *fh)
00354 {
00355     if (!_network) {
00356         _network = open_network_impl(*get_at_handler(fh));
00357     }
00358     _network_ref_count++;
00359     return _network;
00360 }
00361 
00362 CellularInformation *AT_CellularDevice::open_information(FileHandle *fh)
00363 {
00364     if (!_information) {
00365         _information = open_information_impl(*get_at_handler(fh));
00366     }
00367     _info_ref_count++;
00368     return _information;
00369 }
00370 
00371 AT_CellularNetwork *AT_CellularDevice::open_network_impl(ATHandler &at)
00372 {
00373     return new AT_CellularNetwork(at, *this);
00374 }
00375 
00376 #if MBED_CONF_CELLULAR_USE_SMS
00377 
00378 CellularSMS *AT_CellularDevice::open_sms(FileHandle *fh)
00379 {
00380     if (!_sms) {
00381         _sms = open_sms_impl(*get_at_handler(fh));
00382     }
00383     _sms_ref_count++;
00384     return _sms;
00385 }
00386 
00387 void AT_CellularDevice::close_sms()
00388 {
00389     if (_sms) {
00390         _sms_ref_count--;
00391         if (_sms_ref_count == 0) {
00392             ATHandler *atHandler = &_sms->get_at_handler();
00393             delete _sms;
00394             _sms = NULL;
00395             release_at_handler(atHandler);
00396         }
00397     }
00398 }
00399 
00400 AT_CellularSMS *AT_CellularDevice::open_sms_impl(ATHandler &at)
00401 {
00402     return new AT_CellularSMS(at, *this);
00403 }
00404 #endif // MBED_CONF_CELLULAR_USE_SMS
00405 
00406 AT_CellularInformation *AT_CellularDevice::open_information_impl(ATHandler &at)
00407 {
00408     return new AT_CellularInformation(at, *this);
00409 }
00410 
00411 void AT_CellularDevice::close_network()
00412 {
00413     if (_network) {
00414         _network_ref_count--;
00415         if (_network_ref_count == 0) {
00416             ATHandler *atHandler = &_network->get_at_handler();
00417             delete _network;
00418             _network = NULL;
00419             release_at_handler(atHandler);
00420         }
00421     }
00422 }
00423 
00424 void AT_CellularDevice::close_information()
00425 {
00426     if (_information) {
00427         _info_ref_count--;
00428         if (_info_ref_count == 0) {
00429             ATHandler *atHandler = &_information->get_at_handler();
00430             delete _information;
00431             _information = NULL;
00432             release_at_handler(atHandler);
00433         }
00434     }
00435 }
00436 
00437 void AT_CellularDevice::set_timeout(int timeout)
00438 {
00439     _default_timeout = timeout;
00440 
00441     ATHandler::set_at_timeout_list(_default_timeout, true);
00442 
00443     if (_state_machine) {
00444         _state_machine->set_timeout(_default_timeout);
00445     }
00446 }
00447 
00448 uint16_t AT_CellularDevice::get_send_delay() const
00449 {
00450     return 0;
00451 }
00452 
00453 void AT_CellularDevice::modem_debug_on(bool on)
00454 {
00455     _modem_debug_on = on;
00456 
00457     ATHandler::set_debug_list(_modem_debug_on);
00458 }
00459 
00460 nsapi_error_t AT_CellularDevice::init()
00461 {
00462     setup_at_handler();
00463 
00464     _at->lock();
00465     for (int retry = 1; retry <= 3; retry++) {
00466         _at->clear_error();
00467         _at->flush();
00468         _at->at_cmd_discard("E0", "");
00469         if (_at->get_last_error() == NSAPI_ERROR_OK ) {
00470             _at->at_cmd_discard("+CMEE", "=1");
00471             _at->at_cmd_discard("+CFUN", "=1");
00472             if (_at->get_last_error() == NSAPI_ERROR_OK ) {
00473                 break;
00474             }
00475         }
00476         tr_debug("Wait 100ms to init modem");
00477         rtos::ThisThread::sleep_for(100); // let modem have time to get ready
00478     }
00479 
00480     return _at->unlock_return_error();
00481 }
00482 
00483 nsapi_error_t AT_CellularDevice::shutdown()
00484 {
00485     CellularDevice::shutdown();
00486 
00487     return _at->at_cmd_discard("+CFUN", "=0");
00488 }
00489 
00490 nsapi_error_t AT_CellularDevice::is_ready()
00491 {
00492     _at->lock();
00493     _at->at_cmd_discard("", "");
00494 
00495     // we need to do this twice because for example after data mode the first 'AT' command will give modem a
00496     // stimulus that we are back to command mode.
00497     _at->clear_error();
00498     _at->at_cmd_discard("", "");
00499 
00500     return _at->unlock_return_error();
00501 }
00502 
00503 void AT_CellularDevice::set_ready_cb(Callback<void()> callback)
00504 {
00505 }
00506 
00507 nsapi_error_t AT_CellularDevice::set_power_save_mode(int periodic_time, int active_time)
00508 {
00509     _at->lock();
00510 
00511     if (periodic_time == 0 && active_time == 0) {
00512         // disable PSM
00513         _at->at_cmd_discard("+CPSMS", "=0");
00514     } else {
00515         const int PSMTimerBits = 5;
00516 
00517         /**
00518             Table 10.5.163a/3GPP TS 24.008: GPRS Timer 3 information element
00519 
00520             Bits 5 to 1 represent the binary coded timer value.
00521 
00522             Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
00523             8 7 6
00524             0 0 0 value is incremented in multiples of 10 minutes
00525             0 0 1 value is incremented in multiples of 1 hour
00526             0 1 0 value is incremented in multiples of 10 hours
00527             0 1 1 value is incremented in multiples of 2 seconds
00528             1 0 0 value is incremented in multiples of 30 seconds
00529             1 0 1 value is incremented in multiples of 1 minute
00530             1 1 0 value is incremented in multiples of 320 hours (NOTE 1)
00531             1 1 1 value indicates that the timer is deactivated (NOTE 2).
00532          */
00533         char pt[8 + 1]; // timer value encoded as 3GPP IE
00534         const int ie_value_max = 0x1f;
00535         uint32_t periodic_timer = 0;
00536         if (periodic_time <= 2 * ie_value_max) { // multiples of 2 seconds
00537             periodic_timer = periodic_time / 2;
00538             strcpy(pt, "01100000");
00539         } else {
00540             if (periodic_time <= 30 * ie_value_max) { // multiples of 30 seconds
00541                 periodic_timer = periodic_time / 30;
00542                 strcpy(pt, "10000000");
00543             } else {
00544                 if (periodic_time <= 60 * ie_value_max) { // multiples of 1 minute
00545                     periodic_timer = periodic_time / 60;
00546                     strcpy(pt, "10100000");
00547                 } else {
00548                     if (periodic_time <= 10 * 60 * ie_value_max) { // multiples of 10 minutes
00549                         periodic_timer = periodic_time / (10 * 60);
00550                         strcpy(pt, "00000000");
00551                     } else {
00552                         if (periodic_time <= 60 * 60 * ie_value_max) { // multiples of 1 hour
00553                             periodic_timer = periodic_time / (60 * 60);
00554                             strcpy(pt, "00100000");
00555                         } else {
00556                             if (periodic_time <= 10 * 60 * 60 * ie_value_max) { // multiples of 10 hours
00557                                 periodic_timer = periodic_time / (10 * 60 * 60);
00558                                 strcpy(pt, "01000000");
00559                             } else { // multiples of 320 hours
00560                                 int t = periodic_time / (320 * 60 * 60);
00561                                 if (t > ie_value_max) {
00562                                     t = ie_value_max;
00563                                 }
00564                                 periodic_timer = t;
00565                                 strcpy(pt, "11000000");
00566                             }
00567                         }
00568                     }
00569                 }
00570             }
00571         }
00572 
00573         uint_to_binary_str(periodic_timer, &pt[3], sizeof(pt) - 3, PSMTimerBits);
00574         pt[8] = '\0';
00575 
00576         /**
00577             Table 10.5.172/3GPP TS 24.008: GPRS Timer information element
00578 
00579             Bits 5 to 1 represent the binary coded timer value.
00580 
00581             Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
00582 
00583             8 7 6
00584             0 0 0  value is incremented in multiples of 2 seconds
00585             0 0 1  value is incremented in multiples of 1 minute
00586             0 1 0  value is incremented in multiples of decihours
00587             1 1 1  value indicates that the timer is deactivated.
00588 
00589             Other values shall be interpreted as multiples of 1 minute in this version of the protocol.
00590         */
00591         char at[8 + 1];
00592         uint32_t active_timer; // timer value encoded as 3GPP IE
00593         if (active_time <= 2 * ie_value_max) { // multiples of 2 seconds
00594             active_timer = active_time / 2;
00595             strcpy(at, "00000000");
00596         } else {
00597             if (active_time <= 60 * ie_value_max) { // multiples of 1 minute
00598                 active_timer = (1 << 5) | (active_time / 60);
00599                 strcpy(at, "00100000");
00600             } else { // multiples of decihours
00601                 int t = active_time / (6 * 60);
00602                 if (t > ie_value_max) {
00603                     t = ie_value_max;
00604                 }
00605                 active_timer = t;
00606                 strcpy(at, "01000000");
00607             }
00608         }
00609 
00610         uint_to_binary_str(active_timer, &at[3], sizeof(at) - 3, PSMTimerBits);
00611         at[8] = '\0';
00612 
00613         // request for both GPRS and LTE
00614 
00615         _at->at_cmd_discard("+CPSMS", "=1,", "%s%s%s%s", pt, at, pt, at);
00616 
00617         if (_at->get_last_error() != NSAPI_ERROR_OK ) {
00618             tr_warn("Power save mode not enabled!");
00619         } else {
00620             // network may not agree with power save options but
00621             // that should be fine as timeout is not longer than requested
00622         }
00623     }
00624 
00625     return _at->unlock_return_error();
00626 }
00627 
00628 void AT_CellularDevice::cellular_callback(nsapi_event_t ev, intptr_t ptr, CellularContext *ctx)
00629 {
00630     if (ev >= NSAPI_EVENT_CELLULAR_STATUS_BASE  && ev <= NSAPI_EVENT_CELLULAR_STATUS_END ) {
00631         cellular_connection_status_t cell_ev = (cellular_connection_status_t)ev;
00632         if (cell_ev == CellularDeviceTimeout) {
00633             cell_callback_data_t *data = (cell_callback_data_t *)ptr;
00634             int timeout = *(int *)data->data;
00635             if (_default_timeout != timeout) {
00636                 _default_timeout = timeout;
00637                 ATHandler::set_at_timeout_list(_default_timeout, true);
00638             }
00639         }
00640     }
00641     CellularDevice::cellular_callback(ev, ptr, ctx);
00642 }
00643 
00644 nsapi_error_t AT_CellularDevice::clear()
00645 {
00646     AT_CellularNetwork *net = static_cast<AT_CellularNetwork *>(open_network());
00647     nsapi_error_t err = net->clear();
00648     close_network();
00649 
00650     return err;
00651 }
00652 
00653 nsapi_error_t AT_CellularDevice::set_baud_rate(int baud_rate)
00654 {
00655     nsapi_error_t error = set_baud_rate_impl(baud_rate);
00656 
00657     if (error) {
00658         tr_warning("Baudrate was not changed to desired value: %d", baud_rate);
00659         return error;
00660     }
00661 
00662     _at->set_baud(baud_rate);
00663 
00664     // Give some time before starting using the UART with the new baud rate
00665     rtos::ThisThread::sleep_for(3000);
00666 
00667     return error;
00668 }
00669 
00670 nsapi_error_t AT_CellularDevice::set_baud_rate_impl(int baud_rate)
00671 {
00672     return _at->at_cmd_discard("+IPR", "=", "%d", baud_rate);
00673 }
00674 
00675 void AT_CellularDevice::set_cellular_properties(const intptr_t *property_array)
00676 {
00677     if (!property_array) {
00678         tr_warning("trying to set an empty cellular property array");
00679         return;
00680     }
00681 
00682     _property_array = property_array;
00683 }
00684 
00685 intptr_t AT_CellularDevice::get_property(CellularProperty key)
00686 {
00687     if (_property_array) {
00688         return _property_array[key];
00689     } else {
00690         return 0;
00691     }
00692 }