diff --git a/features/cellular/easy_cellular/CellularConnectionFSM.cpp b/features/cellular/easy_cellular/CellularConnectionFSM.cpp index 75867683c1..cb5e08eea1 100644 --- a/features/cellular/easy_cellular/CellularConnectionFSM.cpp +++ b/features/cellular/easy_cellular/CellularConnectionFSM.cpp @@ -144,13 +144,13 @@ bool CellularConnectionFSM::power_on() return true; } -void CellularConnectionFSM::set_sim_pin(const char * sim_pin) +void CellularConnectionFSM::set_sim_pin(const char *sim_pin) { strncpy(_sim_pin, sim_pin, sizeof(_sim_pin)); _sim_pin[sizeof(_sim_pin)-1] = '\0'; } -void CellularConnectionFSM::set_plmn(const char* plmn) +void CellularConnectionFSM::set_plmn(const char *plmn) { _plmn = plmn; } @@ -184,15 +184,6 @@ bool CellularConnectionFSM::open_sim() return state == CellularSIM::SimStateReady; } -bool CellularConnectionFSM::set_network_registration() -{ - if (_network->set_registration(_plmn) != NSAPI_ERROR_OK) { - tr_error("Failed to set network registration."); - return false; - } - return true; -} - bool CellularConnectionFSM::is_registered() { CellularNetwork::RegistrationStatus status; @@ -259,25 +250,7 @@ bool CellularConnectionFSM::get_network_registration(CellularNetwork::Registrati return true; } -bool CellularConnectionFSM::get_attach_network(CellularNetwork::AttachStatus &status) -{ - nsapi_error_t err = _network->get_attach(status); - if (err != NSAPI_ERROR_OK) { - return false; - } - return true; -} - -bool CellularConnectionFSM::set_attach_network() -{ - nsapi_error_t attach_err = _network->set_attach(); - if (attach_err != NSAPI_ERROR_OK) { - return false; - } - return true; -} - -void CellularConnectionFSM::report_failure(const char* msg) +void CellularConnectionFSM::report_failure(const char *msg) { tr_error("Cellular network failed: %s", msg); if (_status_callback) { @@ -285,7 +258,7 @@ void CellularConnectionFSM::report_failure(const char* msg) } } -const char* CellularConnectionFSM::get_state_string(CellularState state) +const char *CellularConnectionFSM::get_state_string(CellularState state) { #if MBED_CONF_MBED_TRACE_ENABLE static const char *strings[] = { "Init", "Power", "Device ready", "SIM pin", "Registering network", "Manual registering", "Attaching network", "Activating PDP Context", "Connecting network", "Connected"}; @@ -295,17 +268,6 @@ const char* CellularConnectionFSM::get_state_string(CellularState state) #endif // #if MBED_CONF_MBED_TRACE_ENABLE } -nsapi_error_t CellularConnectionFSM::is_automatic_registering(bool& auto_reg) -{ - CellularNetwork::NWRegisteringMode mode; - nsapi_error_t err = _network->get_network_registering_mode(mode); - if (err == NSAPI_ERROR_OK) { - tr_debug("automatic registering mode: %d", mode); - auto_reg = (mode == CellularNetwork::NWModeAutomatic); - } - return err; -} - bool CellularConnectionFSM::is_registered_to_plmn() { int format; @@ -325,7 +287,7 @@ bool CellularConnectionFSM::is_registered_to_plmn() CellularNetwork::operator_names_list names_list; nsapi_error_t err = _network->get_operator_names(names_list); if (err == NSAPI_ERROR_OK) { - CellularNetwork::operator_names_t* op_names = names_list.get_head(); + CellularNetwork::operator_names_t *op_names = names_list.get_head(); bool found_match = false; while (op_names) { if (format == 0) { @@ -407,9 +369,18 @@ void CellularConnectionFSM::retry_state_or_fail() void CellularConnectionFSM::state_init() { - _event_timeout = _start_time; - tr_info("Init state, waiting %d ms before POWER state)", _start_time); - enter_to_state(STATE_POWER_ON); + // we should check that if power is already on then we can jump to device ready state + _cellularDevice->set_timeout(TIMEOUT_POWER_ON); + tr_info("Cellular state init (timeout %d ms)", TIMEOUT_POWER_ON); + nsapi_error_t err = _power->is_device_ready(); + if (err != NSAPI_ERROR_OK) { + _event_timeout = _start_time; + tr_info("Init state, waiting %d ms before POWER state)", _start_time); + enter_to_state(STATE_POWER_ON); + } else { + tr_info("Device was ready to accept commands, jump to device ready"); + enter_to_state(STATE_DEVICE_READY); + } } void CellularConnectionFSM::state_power_on() @@ -424,37 +395,21 @@ void CellularConnectionFSM::state_power_on() } } -bool CellularConnectionFSM::device_ready() +void CellularConnectionFSM::device_ready() { tr_info("Cellular device ready"); if (_event_status_cb) { _event_status_cb((nsapi_event_t)CellularDeviceReady, 0); } - _power->remove_device_ready_urc_cb(mbed::callback(this, &CellularConnectionFSM::ready_urc_cb)); - - bool success = false; - for (int type = 0; type < CellularNetwork::C_MAX; type++) { - if (!_network->set_registration_urc((CellularNetwork::RegistrationType)type, true)) { - success = true; - } - } - if (!success) { - tr_error("Failed to set any URC's for registration"); - report_failure(get_state_string(_state)); - return false; - } - - return true; } void CellularConnectionFSM::state_device_ready() { _cellularDevice->set_timeout(TIMEOUT_POWER_ON); if (_power->set_at_mode() == NSAPI_ERROR_OK) { - if (device_ready()) { - enter_to_state(STATE_SIM_PIN); - } + device_ready(); + enter_to_state(STATE_SIM_PIN); } else { if (_retry_count == 0) { (void)_power->set_device_ready_urc_cb(mbed::callback(this, &CellularConnectionFSM::ready_urc_cb)); @@ -468,6 +423,18 @@ void CellularConnectionFSM::state_sim_pin() _cellularDevice->set_timeout(TIMEOUT_SIM_PIN); tr_info("Sim state (timeout %d ms)", TIMEOUT_SIM_PIN); if (open_sim()) { + bool success = false; + for (int type = 0; type < CellularNetwork::C_MAX; type++) { + if (!_network->set_registration_urc((CellularNetwork::RegistrationType)type, true)) { + success = true; + } + } + if (!success) { + tr_warn("Failed to set any URC's for registration"); + retry_state_or_fail(); + return; + } + if (_plmn) { enter_to_state(STATE_MANUAL_REGISTERING_NETWORK); } else { @@ -485,12 +452,9 @@ void CellularConnectionFSM::state_registering() // we are already registered, go to attach enter_to_state(STATE_ATTACHING_NETWORK); } else { - bool auto_reg = false; - nsapi_error_t err = is_automatic_registering(auto_reg); - if (err == NSAPI_ERROR_OK && !auto_reg) { - // automatic registering is not on, set registration and retry - _cellularDevice->set_timeout(TIMEOUT_REGISTRATION); - set_network_registration(); + _cellularDevice->set_timeout(TIMEOUT_REGISTRATION); + if (!_command_success) { + _command_success = (_network->set_registration() == NSAPI_ERROR_OK); } retry_state_or_fail(); } @@ -507,7 +471,7 @@ void CellularConnectionFSM::state_manual_registering_network() enter_to_state(STATE_ATTACHING_NETWORK); } else { if (!_command_success) { - _command_success = set_network_registration(); + _command_success = (_network->set_registration(_plmn) == NSAPI_ERROR_OK); } retry_state_or_fail(); } @@ -517,16 +481,8 @@ void CellularConnectionFSM::state_manual_registering_network() void CellularConnectionFSM::state_attaching() { _cellularDevice->set_timeout(TIMEOUT_CONNECT); - CellularNetwork::AttachStatus attach_status; - if (get_attach_network(attach_status)) { - if (attach_status == CellularNetwork::Attached) { - enter_to_state(STATE_ACTIVATING_PDP_CONTEXT); - } else { - if (!_command_success) { - _command_success = set_attach_network(); - } - retry_state_or_fail(); - } + if (_network->set_attach() == NSAPI_ERROR_OK) { + enter_to_state(STATE_ACTIVATING_PDP_CONTEXT); } else { retry_state_or_fail(); } @@ -701,9 +657,8 @@ void CellularConnectionFSM::ready_urc_cb() if (_state == STATE_DEVICE_READY && _power->set_at_mode() == NSAPI_ERROR_OK) { tr_debug("State was STATE_DEVICE_READY and at mode ready, cancel state and move to next"); _queue.cancel(_event_id); - if (device_ready()) { - continue_from_state(STATE_SIM_PIN); - } + device_ready(); + continue_from_state(STATE_SIM_PIN); } } @@ -712,17 +667,17 @@ events::EventQueue *CellularConnectionFSM::get_queue() return &_queue; } -CellularNetwork* CellularConnectionFSM::get_network() +CellularNetwork *CellularConnectionFSM::get_network() { return _network; } -CellularDevice* CellularConnectionFSM::get_device() +CellularDevice *CellularConnectionFSM::get_device() { return _cellularDevice; } -CellularSIM* CellularConnectionFSM::get_sim() +CellularSIM *CellularConnectionFSM::get_sim() { return _sim; } diff --git a/features/cellular/easy_cellular/CellularConnectionFSM.h b/features/cellular/easy_cellular/CellularConnectionFSM.h index 2ed9cd36cb..78dc1f232a 100644 --- a/features/cellular/easy_cellular/CellularConnectionFSM.h +++ b/features/cellular/easy_cellular/CellularConnectionFSM.h @@ -95,7 +95,7 @@ public: /** Get event queue that can be chained to main event queue (or use start_dispatch) * @return event queue */ - events::EventQueue* get_queue(); + events::EventQueue *get_queue(); /** Start event queue dispatching * @return see nsapi_error_t, 0 on success @@ -110,17 +110,17 @@ public: /** Get cellular network interface * @return network interface, NULL on failure */ - CellularNetwork* get_network(); + CellularNetwork *get_network(); /** Get cellular device interface * @return device interface, NULL on failure */ - CellularDevice* get_device(); + CellularDevice *get_device(); /** Get cellular sim interface * @return sim interface, NULL on failure */ - CellularSIM* get_sim(); + CellularSIM *get_sim(); /** Change cellular connection to the target state * @param state to continue. Default is to connect. @@ -153,18 +153,14 @@ public: * @param state state which is returned in string format * @return string format of the given state */ - const char* get_state_string(CellularState state); + const char *get_state_string(CellularState state); private: bool power_on(); bool open_sim(); bool get_network_registration(CellularNetwork::RegistrationType type, CellularNetwork::RegistrationStatus &status, bool &is_registered); - bool set_network_registration(); - bool get_attach_network(CellularNetwork::AttachStatus &status); - bool set_attach_network(); bool is_registered(); - bool device_ready(); - nsapi_error_t is_automatic_registering(bool& auto_reg); + void device_ready(); // state functions to keep state machine simple void state_init(); @@ -215,7 +211,7 @@ private: events::EventQueue _at_queue; char _st_string[20]; int _event_id; - const char* _plmn; + const char *_plmn; bool _command_success; bool _plmn_network_found; }; diff --git a/features/cellular/easy_cellular/EasyCellularConnection.cpp b/features/cellular/easy_cellular/EasyCellularConnection.cpp index 6543c524de..fb7c0498cf 100644 --- a/features/cellular/easy_cellular/EasyCellularConnection.cpp +++ b/features/cellular/easy_cellular/EasyCellularConnection.cpp @@ -37,11 +37,11 @@ namespace mbed { bool EasyCellularConnection::cellular_status(int state, int next_state) { - tr_info("cellular_status: %s ==> %s", _cellularConnectionFSM.get_state_string((CellularConnectionFSM::CellularState)state), - _cellularConnectionFSM.get_state_string((CellularConnectionFSM::CellularState)next_state)); + tr_info("cellular_status: %s ==> %s", _cellularConnectionFSM->get_state_string((CellularConnectionFSM::CellularState)state), + _cellularConnectionFSM->get_state_string((CellularConnectionFSM::CellularState)next_state)); if (_target_state == state) { - tr_info("Target state reached: %s", _cellularConnectionFSM.get_state_string(_target_state)); + tr_info("Target state reached: %s", _cellularConnectionFSM->get_state_string(_target_state)); MBED_ASSERT(_cellularSemaphore.release() == osOK); return false; // return false -> state machine is halted } @@ -64,7 +64,7 @@ void EasyCellularConnection::network_callback(nsapi_event_t ev, intptr_t ptr) EasyCellularConnection::EasyCellularConnection(bool debug) : _is_connected(false), _is_initialized(false), _target_state(CellularConnectionFSM::STATE_POWER_ON), _cellularSerial( - MDMTXD, MDMRXD, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE), _cellularSemaphore(0), _cellularConnectionFSM(), _credentials_err( + MDMTXD, MDMRXD, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE), _cellularSemaphore(0), _cellularConnectionFSM(0), _credentials_err( NSAPI_ERROR_OK), _status_cb(0) { tr_info("EasyCellularConnection()"); @@ -76,8 +76,11 @@ EasyCellularConnection::EasyCellularConnection(bool debug) : EasyCellularConnection::~EasyCellularConnection() { - _cellularConnectionFSM.set_callback(NULL); - _cellularConnectionFSM.attach(NULL); + if (_cellularConnectionFSM) { + _cellularConnectionFSM->set_callback(NULL); + _cellularConnectionFSM->attach(NULL); + delete _cellularConnectionFSM; + } } nsapi_error_t EasyCellularConnection::init() @@ -87,14 +90,15 @@ nsapi_error_t EasyCellularConnection::init() #if defined (MDMRTS) && defined (MDMCTS) _cellularSerial.set_flow_control(SerialBase::RTSCTS, MDMRTS, MDMCTS); #endif - _cellularConnectionFSM.set_serial(&_cellularSerial); - _cellularConnectionFSM.set_callback(callback(this, &EasyCellularConnection::cellular_status)); + _cellularConnectionFSM = new CellularConnectionFSM(); + _cellularConnectionFSM->set_serial(&_cellularSerial); + _cellularConnectionFSM->set_callback(callback(this, &EasyCellularConnection::cellular_status)); - err = _cellularConnectionFSM.init(); + err = _cellularConnectionFSM->init(); if (err == NSAPI_ERROR_OK) { - err = _cellularConnectionFSM.start_dispatch(); - _cellularConnectionFSM.attach(callback(this, &EasyCellularConnection::network_callback)); + err = _cellularConnectionFSM->start_dispatch(); + _cellularConnectionFSM->attach(callback(this, &EasyCellularConnection::network_callback)); } _is_initialized = true; } @@ -110,7 +114,7 @@ void EasyCellularConnection::set_credentials(const char *apn, const char *uname, if (_credentials_err) { return; } - CellularNetwork * network = _cellularConnectionFSM.get_network(); + CellularNetwork *network = _cellularConnectionFSM->get_network(); if (network) { _credentials_err = network->set_credentials(apn, uname, pwd); #if USE_APN_LOOKUP @@ -128,8 +132,15 @@ void EasyCellularConnection::set_credentials(const char *apn, const char *uname, void EasyCellularConnection::set_sim_pin(const char *sim_pin) { - if (sim_pin) { - _cellularConnectionFSM.set_sim_pin(sim_pin); + if (sim_pin && strlen(sim_pin) > 0) { + if (!_cellularConnectionFSM) { + _credentials_err = init(); + + if (_credentials_err) { + return; + } + } + _cellularConnectionFSM->set_sim_pin(sim_pin); } } @@ -145,7 +156,7 @@ nsapi_error_t EasyCellularConnection::connect(const char *sim_pin, const char *a } if (sim_pin) { - _cellularConnectionFSM.set_sim_pin(sim_pin); + _cellularConnectionFSM->set_sim_pin(sim_pin); } return connect(); @@ -179,16 +190,16 @@ nsapi_error_t EasyCellularConnection::connect() #if USE_APN_LOOKUP if (!_credentials_set) { _target_state = CellularConnectionFSM::STATE_SIM_PIN; - err = _cellularConnectionFSM.continue_to_state(_target_state); + err = _cellularConnectionFSM->continue_to_state(_target_state); if (err == NSAPI_ERROR_OK) { - int sim_wait = _cellularSemaphore.wait(60*1000); // reserve 60 seconds to access to SIM + int sim_wait = _cellularSemaphore.wait(60 * 1000); // reserve 60 seconds to access to SIM if (sim_wait != 1) { tr_error("NO SIM ACCESS"); err = NSAPI_ERROR_NO_CONNECTION; } else { - char imsi[MAX_IMSI_LENGTH+1]; + char imsi[MAX_IMSI_LENGTH + 1]; wait(1); // need to wait to access SIM in some modems - err = _cellularConnectionFSM.get_sim()->get_imsi(imsi); + err = _cellularConnectionFSM->get_sim()->get_imsi(imsi); if (err == NSAPI_ERROR_OK) { const char *apn_config = apnconfig(imsi); if (apn_config) { @@ -196,7 +207,7 @@ nsapi_error_t EasyCellularConnection::connect() const char* uname = _APN_GET(apn_config); const char* pwd = _APN_GET(apn_config); tr_info("Looked up APN %s", apn); - err = _cellularConnectionFSM.get_network()->set_credentials(apn, uname, pwd); + err = _cellularConnectionFSM->get_network()->set_credentials(apn, uname, pwd); } } } @@ -209,7 +220,7 @@ nsapi_error_t EasyCellularConnection::connect() #endif // USE_APN_LOOKUP _target_state = CellularConnectionFSM::STATE_CONNECTED; - err = _cellularConnectionFSM.continue_to_state(_target_state); + err = _cellularConnectionFSM->continue_to_state(_target_state); if (err == NSAPI_ERROR_OK) { int ret_wait = _cellularSemaphore.wait(10 * 60 * 1000); // cellular network searching may take several minutes if (ret_wait != 1) { @@ -231,11 +242,14 @@ nsapi_error_t EasyCellularConnection::disconnect() #endif // #if USE_APN_LOOKUP nsapi_error_t err = NSAPI_ERROR_OK; - if (_cellularConnectionFSM.get_network()) { - err = _cellularConnectionFSM.get_network()->disconnect(); + if (_cellularConnectionFSM && _cellularConnectionFSM->get_network()) { + err = _cellularConnectionFSM->get_network()->disconnect(); } - _cellularConnectionFSM.stop(); + if (err == NSAPI_ERROR_OK) { + delete _cellularConnectionFSM; + _cellularConnectionFSM = NULL; + } return err; } @@ -247,31 +261,41 @@ bool EasyCellularConnection::is_connected() const char *EasyCellularConnection::get_ip_address() { - CellularNetwork *network = _cellularConnectionFSM.get_network(); - if (!network) { + if (_cellularConnectionFSM) { + CellularNetwork *network = _cellularConnectionFSM->get_network(); + if (!network) { + return NULL; + } + return _cellularConnectionFSM->get_network()->get_ip_address(); + } else { return NULL; } - return _cellularConnectionFSM.get_network()->get_ip_address(); } const char *EasyCellularConnection::get_netmask() { - CellularNetwork *network = _cellularConnectionFSM.get_network(); - if (!network) { + if (_cellularConnectionFSM) { + CellularNetwork *network = _cellularConnectionFSM->get_network(); + if (!network) { + return NULL; + } + return network->get_netmask(); + } else { return NULL; } - - return network->get_netmask(); } const char *EasyCellularConnection::get_gateway() { - CellularNetwork *network = _cellularConnectionFSM.get_network(); - if (!network) { + if (_cellularConnectionFSM) { + CellularNetwork *network = _cellularConnectionFSM->get_network(); + if (!network) { + return NULL; + } + return network->get_gateway(); + } else { return NULL; } - - return network->get_gateway(); } void EasyCellularConnection::attach(mbed::Callback status_cb) @@ -281,20 +305,35 @@ void EasyCellularConnection::attach(mbed::Callbackmodem_debug_on(on); + if (_cellularConnectionFSM) { + CellularDevice *dev = _cellularConnectionFSM->get_device(); + if (dev) { + dev->modem_debug_on(on); + } } } -void EasyCellularConnection::set_plmn(const char* plmn) +void EasyCellularConnection::set_plmn(const char *plmn) { - _cellularConnectionFSM.set_plmn(plmn); + if (plmn && strlen(plmn) > 0) { + if (!_cellularConnectionFSM) { + _credentials_err = init(); + + if (_credentials_err) { + return; + } + } + _cellularConnectionFSM->set_plmn(plmn); + } } NetworkStack *EasyCellularConnection::get_stack() { - return _cellularConnectionFSM.get_stack(); + if (_cellularConnectionFSM) { + return _cellularConnectionFSM->get_stack(); + } else { + return NULL; + } } } // namespace diff --git a/features/cellular/easy_cellular/EasyCellularConnection.h b/features/cellular/easy_cellular/EasyCellularConnection.h index defd1dd752..52c6a681bb 100644 --- a/features/cellular/easy_cellular/EasyCellularConnection.h +++ b/features/cellular/easy_cellular/EasyCellularConnection.h @@ -164,7 +164,7 @@ private: UARTSerial _cellularSerial; rtos::Semaphore _cellularSemaphore; - CellularConnectionFSM _cellularConnectionFSM; + CellularConnectionFSM *_cellularConnectionFSM; nsapi_error_t _credentials_err; Callback _status_cb; }; diff --git a/features/cellular/framework/API/CellularPower.h b/features/cellular/framework/API/CellularPower.h index 3be6cb3969..b5b4a54639 100644 --- a/features/cellular/framework/API/CellularPower.h +++ b/features/cellular/framework/API/CellularPower.h @@ -121,6 +121,12 @@ public: */ virtual nsapi_error_t opt_receive_period(int mode, EDRXAccessTechnology act_type, uint8_t edrx_value) = 0; + /** Check whether the device is ready to accept commands. + * + * @return zero on success + */ + virtual nsapi_error_t is_device_ready() = 0; + /** Set URC callback function for device specific ready urc. URC is defined in device specific * power API. Used in startup sequence to listen when device is ready * for using at commands and possible sim. diff --git a/features/cellular/framework/AT/AT_CellularNetwork.cpp b/features/cellular/framework/AT/AT_CellularNetwork.cpp index 9eb5226031..ff0d9876f6 100644 --- a/features/cellular/framework/AT/AT_CellularNetwork.cpp +++ b/features/cellular/framework/AT/AT_CellularNetwork.cpp @@ -371,7 +371,15 @@ nsapi_error_t AT_CellularNetwork::open_data_channel() nsapi_error_t AT_CellularNetwork::disconnect() { #if NSAPI_PPP_AVAILABLE - return nsapi_ppp_disconnect(_at.get_file_handle()); + nsapi_error_t err = nsapi_ppp_disconnect(_at.get_file_handle()); + // after ppp disconnect if we wan't to use same at handler we need to set filehandle again to athandler so it + // will set the correct sigio and nonblocking + if (err == NSAPI_ERROR_OK) { + _at.lock(); + _at.set_file_handle(_at.get_file_handle()); + _at.unlock(); + } + return err; #else _at.lock(); _at.cmd_start("AT+CGACT=0,"); diff --git a/features/cellular/framework/AT/AT_CellularPower.cpp b/features/cellular/framework/AT/AT_CellularPower.cpp index 76c7ef699c..ba2c3c92b8 100644 --- a/features/cellular/framework/AT/AT_CellularPower.cpp +++ b/features/cellular/framework/AT/AT_CellularPower.cpp @@ -233,6 +233,25 @@ nsapi_error_t AT_CellularPower::opt_receive_period(int mode, EDRXAccessTechnolog return _at.unlock_return_error(); } +nsapi_error_t AT_CellularPower::is_device_ready() +{ + _at.lock(); + _at.cmd_start("AT"); + _at.cmd_stop(); + _at.resp_start(); + _at.resp_stop(); + + // we need to do this twice because for example after data mode the first 'AT' command will give modem a + // stimulus that we are back to command mode. + _at.clear_error(); + _at.cmd_start("AT"); + _at.cmd_stop(); + _at.resp_start(); + _at.resp_stop(); + + return _at.unlock_return_error(); +} + nsapi_error_t AT_CellularPower::set_device_ready_urc_cb(mbed::Callback callback) { return NSAPI_ERROR_UNSUPPORTED; diff --git a/features/cellular/framework/AT/AT_CellularPower.h b/features/cellular/framework/AT/AT_CellularPower.h index e29c02a17e..daf4698386 100644 --- a/features/cellular/framework/AT/AT_CellularPower.h +++ b/features/cellular/framework/AT/AT_CellularPower.h @@ -49,6 +49,8 @@ public: virtual nsapi_error_t opt_receive_period(int mode, EDRXAccessTechnology act_type, uint8_t edrx_value); + virtual nsapi_error_t is_device_ready(); + virtual nsapi_error_t set_device_ready_urc_cb(mbed::Callback callback); virtual void remove_device_ready_urc_cb(mbed::Callback callback);