mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #6629 from jarvte/add_select_plmn_to_cellularfsm
Cellular: add plmn for CellularConnectionFSMpull/6682/head
commit
9cc4302c51
|
@ -43,7 +43,7 @@ namespace mbed
|
|||
CellularConnectionFSM::CellularConnectionFSM() :
|
||||
_serial(0), _state(STATE_INIT), _next_state(_state), _status_callback(0), _event_status_cb(0), _network(0), _power(0), _sim(0),
|
||||
_queue(8 * EVENTS_EVENT_SIZE), _queue_thread(0), _cellularDevice(0), _retry_count(0), _event_timeout(-1),
|
||||
_at_queue(8 * EVENTS_EVENT_SIZE), _event_id(0)
|
||||
_at_queue(8 * EVENTS_EVENT_SIZE), _event_id(0), _plmn(0), _command_success(false), _plmn_network_found(false)
|
||||
{
|
||||
memset(_sim_pin, 0, sizeof(_sim_pin));
|
||||
#if MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY == 0
|
||||
|
@ -146,6 +146,11 @@ void CellularConnectionFSM::set_sim_pin(const char * sim_pin)
|
|||
_sim_pin[sizeof(_sim_pin)-1] = '\0';
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::set_plmn(const char* plmn)
|
||||
{
|
||||
_plmn = plmn;
|
||||
}
|
||||
|
||||
bool CellularConnectionFSM::open_sim()
|
||||
{
|
||||
CellularSIM::SimState state = CellularSIM::SimStateUnknown;
|
||||
|
@ -162,7 +167,7 @@ bool CellularConnectionFSM::open_sim()
|
|||
nsapi_error_t err = _sim->set_pin(_sim_pin);
|
||||
if (err) {
|
||||
tr_error("SIM pin set failed with: %d, bailing out...", err);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tr_warn("PIN required but No SIM pin provided.");
|
||||
}
|
||||
|
@ -175,11 +180,10 @@ bool CellularConnectionFSM::open_sim()
|
|||
return state == CellularSIM::SimStateReady;
|
||||
}
|
||||
|
||||
bool CellularConnectionFSM::set_network_registration(char *plmn)
|
||||
bool CellularConnectionFSM::set_network_registration()
|
||||
{
|
||||
nsapi_error_t error = _network->set_registration(plmn);
|
||||
if (error != NSAPI_ERROR_OK) {
|
||||
tr_error("Set network registration mode failing (%d)", error);
|
||||
if (_network->set_registration(_plmn) != NSAPI_ERROR_OK) {
|
||||
tr_error("Failed to set network registration.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -279,8 +283,12 @@ void CellularConnectionFSM::report_failure(const char* msg)
|
|||
|
||||
const char* CellularConnectionFSM::get_state_string(CellularState state)
|
||||
{
|
||||
static const char *strings[] = { "Init", "Power", "Device ready", "SIM pin", "Registering network", "Attaching network", "Activating PDP Context", "Connecting network", "Connected"};
|
||||
#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"};
|
||||
return strings[state];
|
||||
#else
|
||||
return NULL;
|
||||
#endif // #if MBED_CONF_MBED_TRACE_ENABLE
|
||||
}
|
||||
|
||||
nsapi_error_t CellularConnectionFSM::is_automatic_registering(bool& auto_reg)
|
||||
|
@ -294,6 +302,54 @@ nsapi_error_t CellularConnectionFSM::is_automatic_registering(bool& auto_reg)
|
|||
return err;
|
||||
}
|
||||
|
||||
bool CellularConnectionFSM::is_registered_to_plmn()
|
||||
{
|
||||
int format;
|
||||
CellularNetwork::operator_t op;
|
||||
|
||||
nsapi_error_t err = _network->get_operator_params(format, op);
|
||||
if (err == NSAPI_ERROR_OK) {
|
||||
if (format == 2) {
|
||||
// great, numeric format we can do comparison for that
|
||||
if (strcmp(op.op_num, _plmn) == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// format was alpha, get operator names to do the comparing
|
||||
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();
|
||||
bool found_match = false;
|
||||
while (op_names) {
|
||||
if (format == 0) {
|
||||
if (strcmp(op.op_long, op_names->alpha) == 0) {
|
||||
found_match = true;
|
||||
}
|
||||
} else if (format == 1) {
|
||||
if (strcmp(op.op_short, op_names->alpha) == 0) {
|
||||
found_match = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_match) {
|
||||
if (strcmp(_plmn, op_names->numeric)) {
|
||||
names_list.delete_all();
|
||||
return true;
|
||||
}
|
||||
names_list.delete_all();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
names_list.delete_all();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nsapi_error_t CellularConnectionFSM::continue_from_state(CellularState state)
|
||||
{
|
||||
tr_info("Continue state from %s to %s", get_state_string((CellularConnectionFSM::CellularState)_state),
|
||||
|
@ -330,6 +386,7 @@ void CellularConnectionFSM::enter_to_state(CellularState state)
|
|||
{
|
||||
_next_state = state;
|
||||
_retry_count = 0;
|
||||
_command_success = false;
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::retry_state_or_fail()
|
||||
|
@ -406,7 +463,11 @@ void CellularConnectionFSM::state_sim_pin()
|
|||
_cellularDevice->set_timeout(TIMEOUT_SIM_PIN);
|
||||
tr_info("Sim state (timeout %d ms)", TIMEOUT_SIM_PIN);
|
||||
if (open_sim()) {
|
||||
enter_to_state(STATE_REGISTERING_NETWORK);
|
||||
if (_plmn) {
|
||||
enter_to_state(STATE_MANUAL_REGISTERING_NETWORK);
|
||||
} else {
|
||||
enter_to_state(STATE_REGISTERING_NETWORK);
|
||||
}
|
||||
} else {
|
||||
retry_state_or_fail();
|
||||
}
|
||||
|
@ -421,7 +482,7 @@ void CellularConnectionFSM::state_registering()
|
|||
} else {
|
||||
bool auto_reg = false;
|
||||
nsapi_error_t err = is_automatic_registering(auto_reg);
|
||||
if (err == NSAPI_ERROR_OK && !auto_reg) { // when we support plmn add this : || plmn
|
||||
if (err == NSAPI_ERROR_OK && !auto_reg) {
|
||||
// automatic registering is not on, set registration and retry
|
||||
_cellularDevice->set_timeout(TIMEOUT_REGISTRATION);
|
||||
set_network_registration();
|
||||
|
@ -430,6 +491,24 @@ void CellularConnectionFSM::state_registering()
|
|||
}
|
||||
}
|
||||
|
||||
// only used when _plmn is set
|
||||
void CellularConnectionFSM::state_manual_registering_network()
|
||||
{
|
||||
_cellularDevice->set_timeout(TIMEOUT_REGISTRATION);
|
||||
tr_info("state_manual_registering_network");
|
||||
if (!_plmn_network_found) {
|
||||
if (is_registered() && is_registered_to_plmn()) {
|
||||
_plmn_network_found = true;
|
||||
enter_to_state(STATE_ATTACHING_NETWORK);
|
||||
} else {
|
||||
if (!_command_success) {
|
||||
_command_success = set_network_registration();
|
||||
}
|
||||
retry_state_or_fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::state_attaching()
|
||||
{
|
||||
_cellularDevice->set_timeout(TIMEOUT_CONNECT);
|
||||
|
@ -438,7 +517,9 @@ void CellularConnectionFSM::state_attaching()
|
|||
if (attach_status == CellularNetwork::Attached) {
|
||||
enter_to_state(STATE_ACTIVATING_PDP_CONTEXT);
|
||||
} else {
|
||||
set_attach_network();
|
||||
if (!_command_success) {
|
||||
_command_success = set_attach_network();
|
||||
}
|
||||
retry_state_or_fail();
|
||||
}
|
||||
} else {
|
||||
|
@ -500,6 +581,9 @@ void CellularConnectionFSM::event()
|
|||
case STATE_REGISTERING_NETWORK:
|
||||
state_registering();
|
||||
break;
|
||||
case STATE_MANUAL_REGISTERING_NETWORK:
|
||||
state_manual_registering_network();
|
||||
break;
|
||||
case STATE_ATTACHING_NETWORK:
|
||||
state_attaching();
|
||||
break;
|
||||
|
@ -576,13 +660,23 @@ void CellularConnectionFSM::attach(mbed::Callback<void(nsapi_event_t, intptr_t)>
|
|||
|
||||
void CellularConnectionFSM::network_callback(nsapi_event_t ev, intptr_t ptr)
|
||||
{
|
||||
|
||||
tr_info("FSM: network_callback called with event: %d, intptr: %d", ev, ptr);
|
||||
if ((cellular_connection_status_t)ev == CellularRegistrationStatusChanged && _state == STATE_REGISTERING_NETWORK) {
|
||||
tr_info("FSM: network_callback called with event: %d, intptr: %d, _state: %s", ev, ptr, get_state_string(_state));
|
||||
if ((cellular_connection_status_t)ev == CellularRegistrationStatusChanged &&
|
||||
(_state == STATE_REGISTERING_NETWORK || _state == STATE_MANUAL_REGISTERING_NETWORK)) {
|
||||
// expect packet data so only these states are valid
|
||||
if (ptr == CellularNetwork::RegisteredHomeNetwork && CellularNetwork::RegisteredRoaming) {
|
||||
_queue.cancel(_event_id);
|
||||
continue_from_state(STATE_ATTACHING_NETWORK);
|
||||
if (ptr == CellularNetwork::RegisteredHomeNetwork || ptr == CellularNetwork::RegisteredRoaming) {
|
||||
if (_plmn) {
|
||||
if (is_registered_to_plmn()) {
|
||||
if (!_plmn_network_found) {
|
||||
_plmn_network_found = true;
|
||||
_queue.cancel(_event_id);
|
||||
continue_from_state(STATE_ATTACHING_NETWORK);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_queue.cancel(_event_id);
|
||||
continue_from_state(STATE_ATTACHING_NETWORK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ public:
|
|||
STATE_DEVICE_READY,
|
||||
STATE_SIM_PIN,
|
||||
STATE_REGISTERING_NETWORK,
|
||||
STATE_MANUAL_REGISTERING_NETWORK,
|
||||
STATE_ATTACHING_NETWORK,
|
||||
STATE_ACTIVATING_PDP_CONTEXT,
|
||||
STATE_CONNECTING_NETWORK,
|
||||
|
@ -139,12 +140,24 @@ public:
|
|||
*/
|
||||
void set_retry_timeout_array(uint16_t timeout[], int array_len);
|
||||
|
||||
/** Sets the operator plmn which is used when registering to a network specified by plmn. If plmn is not set then automatic
|
||||
* registering is used when registering to a cellular network. Does not start any operations.
|
||||
*
|
||||
* @param plmn operator in numeric format. See more from 3GPP TS 27.007 chapter 7.3.
|
||||
*/
|
||||
void set_plmn(const char* plmn);
|
||||
|
||||
/** returns readable format of the given state. Used for printing states while debugging.
|
||||
*
|
||||
* @param state state which is returned in string format
|
||||
* @return string format of the given 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(char *plmn = 0);
|
||||
bool set_network_registration();
|
||||
bool get_attach_network(CellularNetwork::AttachStatus &status);
|
||||
bool set_attach_network();
|
||||
bool is_registered();
|
||||
|
@ -157,6 +170,7 @@ private:
|
|||
void state_device_ready();
|
||||
void state_sim_pin();
|
||||
void state_registering();
|
||||
void state_manual_registering_network();
|
||||
void state_attaching();
|
||||
void state_activating_pdp_context();
|
||||
void state_connect_to_network();
|
||||
|
@ -165,6 +179,7 @@ private:
|
|||
void retry_state_or_fail();
|
||||
void network_callback(nsapi_event_t ev, intptr_t ptr);
|
||||
nsapi_error_t continue_from_state(CellularState state);
|
||||
bool is_registered_to_plmn();
|
||||
|
||||
private:
|
||||
friend class EasyCellularConnection;
|
||||
|
@ -198,6 +213,9 @@ private:
|
|||
events::EventQueue _at_queue;
|
||||
char _st_string[20];
|
||||
int _event_id;
|
||||
const char* _plmn;
|
||||
bool _command_success;
|
||||
bool _plmn_network_found;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -280,6 +280,11 @@ void EasyCellularConnection::modem_debug_on(bool on)
|
|||
}
|
||||
}
|
||||
|
||||
void EasyCellularConnection::set_plmn(const char* plmn)
|
||||
{
|
||||
_cellularConnectionFSM.set_plmn(plmn);
|
||||
}
|
||||
|
||||
NetworkStack *EasyCellularConnection::get_stack()
|
||||
{
|
||||
return _cellularConnectionFSM.get_stack();
|
||||
|
|
|
@ -131,6 +131,12 @@ public:
|
|||
*/
|
||||
void modem_debug_on(bool on);
|
||||
|
||||
/** Sets the operator plmn which is used when registering to a network specified by plmn. If plmn is not set then automatic
|
||||
* registering is used when registering to a cellular network.
|
||||
*
|
||||
* @param plmn operator in numeric format. See more from 3GPP TS 27.007 chapter 7.3.
|
||||
*/
|
||||
void set_plmn(const char* plmn);
|
||||
protected:
|
||||
|
||||
/** Provide access to the NetworkStack object
|
||||
|
|
|
@ -199,6 +199,18 @@ public:
|
|||
};
|
||||
typedef CellularList<pdpcontext_params_t> pdpContextList_t;
|
||||
|
||||
struct operator_names_t {
|
||||
char numeric[MAX_OPERATOR_NAME_SHORT+1];
|
||||
char alpha[MAX_OPERATOR_NAME_LONG+1];
|
||||
operator_names_t* next;
|
||||
operator_names_t() {
|
||||
numeric[0] = '\0';
|
||||
alpha[0] = '\0';
|
||||
next = NULL;
|
||||
}
|
||||
};
|
||||
typedef CellularList<operator_names_t> operator_names_list;
|
||||
|
||||
/* Network registering mode */
|
||||
enum NWRegisteringMode {
|
||||
NWModeAutomatic = 0, // automatic registering
|
||||
|
@ -460,6 +472,12 @@ public:
|
|||
*/
|
||||
virtual nsapi_error_t set_blocking(bool blocking) = 0;
|
||||
|
||||
/** Read operator names
|
||||
*
|
||||
* @param op_names on successful return will contain linked list of operator names.
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t get_operator_names(operator_names_list &op_names) = 0;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
|
|
@ -656,7 +656,7 @@ nsapi_error_t AT_CellularNetwork::set_registration(const char *plmn)
|
|||
tr_debug("Automatic network registration");
|
||||
_at.cmd_start("AT+COPS?");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("AT+COPS:");
|
||||
_at.resp_start("+COPS:");
|
||||
int mode = _at.read_int();
|
||||
_at.resp_stop();
|
||||
if (mode != 0) {
|
||||
|
@ -912,6 +912,14 @@ nsapi_error_t AT_CellularNetwork::scan_plmn(operList_t &operators, int &opsCount
|
|||
while (_at.info_elem('(')) {
|
||||
|
||||
op = operators.add_new();
|
||||
if (!op) {
|
||||
tr_warn("Could not allocate new operator");
|
||||
_at.resp_stop();
|
||||
_at.unlock();
|
||||
operators.delete_all();
|
||||
opsCount = 0;
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
op->op_status = (operator_t::Status)_at.read_int();
|
||||
_at.read_string(op->op_long, sizeof(op->op_long));
|
||||
|
@ -933,7 +941,6 @@ nsapi_error_t AT_CellularNetwork::scan_plmn(operList_t &operators, int &opsCount
|
|||
_at.resp_stop();
|
||||
|
||||
opsCount = idx;
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
|
@ -1045,8 +1052,9 @@ nsapi_error_t AT_CellularNetwork::get_pdpcontext_params(pdpContextList_t& params
|
|||
params = params_list.add_new();
|
||||
if (!params) {
|
||||
tr_warn("Could not allocate new pdpcontext_params_t");
|
||||
params_list.delete_all();
|
||||
_at.resp_stop();
|
||||
_at.unlock();
|
||||
params_list.delete_all();
|
||||
free(temp);
|
||||
free(ipv6_and_subnetmask);
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
|
@ -1187,3 +1195,29 @@ nsapi_error_t AT_CellularNetwork::get_operator_params(int &format, operator_t &o
|
|||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_operator_names(operator_names_list &op_names)
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+COPN?");
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+COPN:");
|
||||
operator_names_t *names = NULL;
|
||||
while (_at.info_resp()) {
|
||||
names = op_names.add_new();
|
||||
if (!names) {
|
||||
tr_warn("Could not allocate new operator_names_t");
|
||||
_at.resp_stop();
|
||||
_at.unlock();
|
||||
op_names.delete_all();
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
_at.read_string(names->numeric, sizeof(names->numeric));
|
||||
_at.read_string(names->alpha, sizeof(names->alpha));
|
||||
}
|
||||
|
||||
_at.resp_stop();
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
|
|
@ -141,6 +141,7 @@ protected:
|
|||
*/
|
||||
virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology op_rat);
|
||||
|
||||
virtual nsapi_error_t get_operator_names(operator_names_list &op_names);
|
||||
private:
|
||||
// "NO CARRIER" urc
|
||||
void urc_no_carrier();
|
||||
|
|
Loading…
Reference in New Issue