Cellular: Fixed connect-disconnect sequence can now be called multiple times.

pull/7228/head
Teppo Järvelin 2018-05-16 14:25:35 +03:00 committed by adbridge
parent 866850acc1
commit 0c23935cae
8 changed files with 143 additions and 125 deletions

View File

@ -184,15 +184,6 @@ bool CellularConnectionFSM::open_sim()
return state == CellularSIM::SimStateReady; 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() bool CellularConnectionFSM::is_registered()
{ {
CellularNetwork::RegistrationStatus status; CellularNetwork::RegistrationStatus status;
@ -259,24 +250,6 @@ bool CellularConnectionFSM::get_network_registration(CellularNetwork::Registrati
return true; 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); tr_error("Cellular network failed: %s", msg);
@ -295,17 +268,6 @@ const char* CellularConnectionFSM::get_state_string(CellularState state)
#endif // #if MBED_CONF_MBED_TRACE_ENABLE #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() bool CellularConnectionFSM::is_registered_to_plmn()
{ {
int format; int format;
@ -407,9 +369,18 @@ void CellularConnectionFSM::retry_state_or_fail()
void CellularConnectionFSM::state_init() void CellularConnectionFSM::state_init()
{ {
// 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; _event_timeout = _start_time;
tr_info("Init state, waiting %d ms before POWER state)", _start_time); tr_info("Init state, waiting %d ms before POWER state)", _start_time);
enter_to_state(STATE_POWER_ON); 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() 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"); tr_info("Cellular device ready");
if (_event_status_cb) { if (_event_status_cb) {
_event_status_cb((nsapi_event_t)CellularDeviceReady, 0); _event_status_cb((nsapi_event_t)CellularDeviceReady, 0);
} }
_power->remove_device_ready_urc_cb(mbed::callback(this, &CellularConnectionFSM::ready_urc_cb)); _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() void CellularConnectionFSM::state_device_ready()
{ {
_cellularDevice->set_timeout(TIMEOUT_POWER_ON); _cellularDevice->set_timeout(TIMEOUT_POWER_ON);
if (_power->set_at_mode() == NSAPI_ERROR_OK) { if (_power->set_at_mode() == NSAPI_ERROR_OK) {
if (device_ready()) { device_ready();
enter_to_state(STATE_SIM_PIN); enter_to_state(STATE_SIM_PIN);
}
} else { } else {
if (_retry_count == 0) { if (_retry_count == 0) {
(void)_power->set_device_ready_urc_cb(mbed::callback(this, &CellularConnectionFSM::ready_urc_cb)); (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); _cellularDevice->set_timeout(TIMEOUT_SIM_PIN);
tr_info("Sim state (timeout %d ms)", TIMEOUT_SIM_PIN); tr_info("Sim state (timeout %d ms)", TIMEOUT_SIM_PIN);
if (open_sim()) { 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_warning("Failed to set any URC's for registration");
retry_state_or_fail();
return;
}
if (_plmn) { if (_plmn) {
enter_to_state(STATE_MANUAL_REGISTERING_NETWORK); enter_to_state(STATE_MANUAL_REGISTERING_NETWORK);
} else { } else {
@ -485,12 +452,9 @@ void CellularConnectionFSM::state_registering()
// we are already registered, go to attach // we are already registered, go to attach
enter_to_state(STATE_ATTACHING_NETWORK); enter_to_state(STATE_ATTACHING_NETWORK);
} else { } 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); _cellularDevice->set_timeout(TIMEOUT_REGISTRATION);
set_network_registration(); if (!_command_success) {
_command_success = (_network->set_registration() == NSAPI_ERROR_OK);
} }
retry_state_or_fail(); retry_state_or_fail();
} }
@ -507,7 +471,7 @@ void CellularConnectionFSM::state_manual_registering_network()
enter_to_state(STATE_ATTACHING_NETWORK); enter_to_state(STATE_ATTACHING_NETWORK);
} else { } else {
if (!_command_success) { if (!_command_success) {
_command_success = set_network_registration(); _command_success = (_network->set_registration(_plmn) == NSAPI_ERROR_OK);
} }
retry_state_or_fail(); retry_state_or_fail();
} }
@ -517,16 +481,8 @@ void CellularConnectionFSM::state_manual_registering_network()
void CellularConnectionFSM::state_attaching() void CellularConnectionFSM::state_attaching()
{ {
_cellularDevice->set_timeout(TIMEOUT_CONNECT); _cellularDevice->set_timeout(TIMEOUT_CONNECT);
CellularNetwork::AttachStatus attach_status; if (_network->set_attach() == NSAPI_ERROR_OK) {
if (get_attach_network(attach_status)) {
if (attach_status == CellularNetwork::Attached) {
enter_to_state(STATE_ACTIVATING_PDP_CONTEXT); enter_to_state(STATE_ACTIVATING_PDP_CONTEXT);
} else {
if (!_command_success) {
_command_success = set_attach_network();
}
retry_state_or_fail();
}
} else { } else {
retry_state_or_fail(); retry_state_or_fail();
} }
@ -701,11 +657,10 @@ void CellularConnectionFSM::ready_urc_cb()
if (_state == STATE_DEVICE_READY && _power->set_at_mode() == NSAPI_ERROR_OK) { 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"); tr_debug("State was STATE_DEVICE_READY and at mode ready, cancel state and move to next");
_queue.cancel(_event_id); _queue.cancel(_event_id);
if (device_ready()) { device_ready();
continue_from_state(STATE_SIM_PIN); continue_from_state(STATE_SIM_PIN);
} }
} }
}
events::EventQueue *CellularConnectionFSM::get_queue() events::EventQueue *CellularConnectionFSM::get_queue()
{ {

View File

@ -159,12 +159,8 @@ private:
bool power_on(); bool power_on();
bool open_sim(); bool open_sim();
bool get_network_registration(CellularNetwork::RegistrationType type, CellularNetwork::RegistrationStatus &status, bool &is_registered); 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 is_registered();
bool device_ready(); void device_ready();
nsapi_error_t is_automatic_registering(bool& auto_reg);
// state functions to keep state machine simple // state functions to keep state machine simple
void state_init(); void state_init();

View File

@ -37,11 +37,11 @@ namespace mbed {
bool EasyCellularConnection::cellular_status(int state, int next_state) bool EasyCellularConnection::cellular_status(int state, int next_state)
{ {
tr_info("cellular_status: %s ==> %s", _cellularConnectionFSM.get_state_string((CellularConnectionFSM::CellularState)state), tr_info("cellular_status: %s ==> %s", _cellularConnectionFSM->get_state_string((CellularConnectionFSM::CellularState)state),
_cellularConnectionFSM.get_state_string((CellularConnectionFSM::CellularState)next_state)); _cellularConnectionFSM->get_state_string((CellularConnectionFSM::CellularState)next_state));
if (_target_state == 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); MBED_ASSERT(_cellularSemaphore.release() == osOK);
return false; // return false -> state machine is halted 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) : EasyCellularConnection::EasyCellularConnection(bool debug) :
_is_connected(false), _is_initialized(false), _target_state(CellularConnectionFSM::STATE_POWER_ON), _cellularSerial( _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) NSAPI_ERROR_OK), _status_cb(0)
{ {
tr_info("EasyCellularConnection()"); tr_info("EasyCellularConnection()");
@ -76,8 +76,11 @@ EasyCellularConnection::EasyCellularConnection(bool debug) :
EasyCellularConnection::~EasyCellularConnection() EasyCellularConnection::~EasyCellularConnection()
{ {
_cellularConnectionFSM.set_callback(NULL); if (_cellularConnectionFSM) {
_cellularConnectionFSM.attach(NULL); _cellularConnectionFSM->set_callback(NULL);
_cellularConnectionFSM->attach(NULL);
delete _cellularConnectionFSM;
}
} }
nsapi_error_t EasyCellularConnection::init() nsapi_error_t EasyCellularConnection::init()
@ -87,14 +90,15 @@ nsapi_error_t EasyCellularConnection::init()
#if defined (MDMRTS) && defined (MDMCTS) #if defined (MDMRTS) && defined (MDMCTS)
_cellularSerial.set_flow_control(SerialBase::RTSCTS, MDMRTS, MDMCTS); _cellularSerial.set_flow_control(SerialBase::RTSCTS, MDMRTS, MDMCTS);
#endif #endif
_cellularConnectionFSM.set_serial(&_cellularSerial); _cellularConnectionFSM = new CellularConnectionFSM();
_cellularConnectionFSM.set_callback(callback(this, &EasyCellularConnection::cellular_status)); _cellularConnectionFSM->set_serial(&_cellularSerial);
_cellularConnectionFSM->set_callback(callback(this, &EasyCellularConnection::cellular_status));
err = _cellularConnectionFSM.init(); err = _cellularConnectionFSM->init();
if (err == NSAPI_ERROR_OK) { if (err == NSAPI_ERROR_OK) {
err = _cellularConnectionFSM.start_dispatch(); err = _cellularConnectionFSM->start_dispatch();
_cellularConnectionFSM.attach(callback(this, &EasyCellularConnection::network_callback)); _cellularConnectionFSM->attach(callback(this, &EasyCellularConnection::network_callback));
} }
_is_initialized = true; _is_initialized = true;
} }
@ -110,7 +114,7 @@ void EasyCellularConnection::set_credentials(const char *apn, const char *uname,
if (_credentials_err) { if (_credentials_err) {
return; return;
} }
CellularNetwork * network = _cellularConnectionFSM.get_network(); CellularNetwork * network = _cellularConnectionFSM->get_network();
if (network) { if (network) {
_credentials_err = network->set_credentials(apn, uname, pwd); _credentials_err = network->set_credentials(apn, uname, pwd);
#if USE_APN_LOOKUP #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) void EasyCellularConnection::set_sim_pin(const char *sim_pin)
{ {
if (sim_pin) { if (sim_pin && strlen(sim_pin) > 0) {
_cellularConnectionFSM.set_sim_pin(sim_pin); 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) { if (sim_pin) {
_cellularConnectionFSM.set_sim_pin(sim_pin); _cellularConnectionFSM->set_sim_pin(sim_pin);
} }
return connect(); return connect();
@ -179,7 +190,7 @@ nsapi_error_t EasyCellularConnection::connect()
#if USE_APN_LOOKUP #if USE_APN_LOOKUP
if (!_credentials_set) { if (!_credentials_set) {
_target_state = CellularConnectionFSM::STATE_SIM_PIN; _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) { 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) { if (sim_wait != 1) {
@ -188,7 +199,7 @@ nsapi_error_t EasyCellularConnection::connect()
} else { } else {
char imsi[MAX_IMSI_LENGTH+1]; char imsi[MAX_IMSI_LENGTH+1];
wait(1); // need to wait to access SIM in some modems 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) { if (err == NSAPI_ERROR_OK) {
const char *apn_config = apnconfig(imsi); const char *apn_config = apnconfig(imsi);
if (apn_config) { if (apn_config) {
@ -196,7 +207,7 @@ nsapi_error_t EasyCellularConnection::connect()
const char* uname = _APN_GET(apn_config); const char* uname = _APN_GET(apn_config);
const char* pwd = _APN_GET(apn_config); const char* pwd = _APN_GET(apn_config);
tr_info("Looked up APN %s", apn); 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 #endif // USE_APN_LOOKUP
_target_state = CellularConnectionFSM::STATE_CONNECTED; _target_state = CellularConnectionFSM::STATE_CONNECTED;
err = _cellularConnectionFSM.continue_to_state(_target_state); err = _cellularConnectionFSM->continue_to_state(_target_state);
if (err == NSAPI_ERROR_OK) { if (err == NSAPI_ERROR_OK) {
int ret_wait = _cellularSemaphore.wait(10 * 60 * 1000); // cellular network searching may take several minutes int ret_wait = _cellularSemaphore.wait(10 * 60 * 1000); // cellular network searching may take several minutes
if (ret_wait != 1) { if (ret_wait != 1) {
@ -231,11 +242,14 @@ nsapi_error_t EasyCellularConnection::disconnect()
#endif // #if USE_APN_LOOKUP #endif // #if USE_APN_LOOKUP
nsapi_error_t err = NSAPI_ERROR_OK; nsapi_error_t err = NSAPI_ERROR_OK;
if (_cellularConnectionFSM.get_network()) { if (_cellularConnectionFSM && _cellularConnectionFSM->get_network()) {
err = _cellularConnectionFSM.get_network()->disconnect(); err = _cellularConnectionFSM->get_network()->disconnect();
} }
_cellularConnectionFSM.stop(); if (err == NSAPI_ERROR_OK) {
delete _cellularConnectionFSM;
_cellularConnectionFSM = NULL;
}
return err; return err;
} }
@ -247,31 +261,41 @@ bool EasyCellularConnection::is_connected()
const char *EasyCellularConnection::get_ip_address() const char *EasyCellularConnection::get_ip_address()
{ {
CellularNetwork *network = _cellularConnectionFSM.get_network(); if (_cellularConnectionFSM) {
CellularNetwork *network = _cellularConnectionFSM->get_network();
if (!network) { if (!network) {
return NULL; return NULL;
} }
return _cellularConnectionFSM.get_network()->get_ip_address(); return _cellularConnectionFSM->get_network()->get_ip_address();
} else {
return NULL;
}
} }
const char *EasyCellularConnection::get_netmask() const char *EasyCellularConnection::get_netmask()
{ {
CellularNetwork *network = _cellularConnectionFSM.get_network(); if (_cellularConnectionFSM) {
CellularNetwork *network = _cellularConnectionFSM->get_network();
if (!network) { if (!network) {
return NULL; return NULL;
} }
return network->get_netmask(); return network->get_netmask();
} else {
return NULL;
}
} }
const char *EasyCellularConnection::get_gateway() const char *EasyCellularConnection::get_gateway()
{ {
CellularNetwork *network = _cellularConnectionFSM.get_network(); if (_cellularConnectionFSM) {
CellularNetwork *network = _cellularConnectionFSM->get_network();
if (!network) { if (!network) {
return NULL; return NULL;
} }
return network->get_gateway(); return network->get_gateway();
} else {
return NULL;
}
} }
void EasyCellularConnection::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb) void EasyCellularConnection::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
@ -281,20 +305,28 @@ void EasyCellularConnection::attach(mbed::Callback<void(nsapi_event_t, intptr_t)
void EasyCellularConnection::modem_debug_on(bool on) void EasyCellularConnection::modem_debug_on(bool on)
{ {
CellularDevice *dev = _cellularConnectionFSM.get_device(); if (_cellularConnectionFSM) {
CellularDevice *dev = _cellularConnectionFSM->get_device();
if (dev) { if (dev) {
dev->modem_debug_on(on); dev->modem_debug_on(on);
} }
} }
}
void EasyCellularConnection::set_plmn(const char* plmn) void EasyCellularConnection::set_plmn(const char* plmn)
{ {
_cellularConnectionFSM.set_plmn(plmn); if (_cellularConnectionFSM) {
_cellularConnectionFSM->set_plmn(plmn);
}
} }
NetworkStack *EasyCellularConnection::get_stack() NetworkStack *EasyCellularConnection::get_stack()
{ {
return _cellularConnectionFSM.get_stack(); if (_cellularConnectionFSM) {
return _cellularConnectionFSM->get_stack();
} else {
return NULL;
}
} }
} // namespace } // namespace

View File

@ -164,7 +164,7 @@ private:
UARTSerial _cellularSerial; UARTSerial _cellularSerial;
rtos::Semaphore _cellularSemaphore; rtos::Semaphore _cellularSemaphore;
CellularConnectionFSM _cellularConnectionFSM; CellularConnectionFSM *_cellularConnectionFSM;
nsapi_error_t _credentials_err; nsapi_error_t _credentials_err;
Callback<void(nsapi_event_t, intptr_t)> _status_cb; Callback<void(nsapi_event_t, intptr_t)> _status_cb;
}; };

View File

@ -121,6 +121,12 @@ public:
*/ */
virtual nsapi_error_t opt_receive_period(int mode, EDRXAccessTechnology act_type, uint8_t edrx_value) = 0; 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 /** 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 * power API. Used in startup sequence to listen when device is ready
* for using at commands and possible sim. * for using at commands and possible sim.

View File

@ -371,7 +371,15 @@ nsapi_error_t AT_CellularNetwork::open_data_channel()
nsapi_error_t AT_CellularNetwork::disconnect() nsapi_error_t AT_CellularNetwork::disconnect()
{ {
#if NSAPI_PPP_AVAILABLE #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 #else
_at.lock(); _at.lock();
_at.cmd_start("AT+CGACT=0,"); _at.cmd_start("AT+CGACT=0,");

View File

@ -233,6 +233,25 @@ nsapi_error_t AT_CellularPower::opt_receive_period(int mode, EDRXAccessTechnolog
return _at.unlock_return_error(); 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<void()> callback) nsapi_error_t AT_CellularPower::set_device_ready_urc_cb(mbed::Callback<void()> callback)
{ {
return NSAPI_ERROR_UNSUPPORTED; return NSAPI_ERROR_UNSUPPORTED;

View File

@ -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 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<void()> callback); virtual nsapi_error_t set_device_ready_urc_cb(mbed::Callback<void()> callback);
virtual void remove_device_ready_urc_cb(mbed::Callback<void()> callback); virtual void remove_device_ready_urc_cb(mbed::Callback<void()> callback);