Skip to content

Cellular: add plmn for CellularConnectionFSM #6629

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 110 additions & 16 deletions features/cellular/easy_cellular/CellularConnectionFSM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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.");
}
Expand All @@ -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;
Expand Down Expand Up @@ -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)
Expand All @@ -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),
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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();
}
Expand All @@ -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();
Expand All @@ -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);
Expand All @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}
}

Expand Down
20 changes: 19 additions & 1 deletion features/cellular/easy_cellular/CellularConnectionFSM.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class CellularConnectionFSM
STATE_DEVICE_READY,
STATE_SIM_PIN,
STATE_REGISTERING_NETWORK,
STATE_MANUAL_REGISTERING_NETWORK,
STATE_ATTACHING_NETWORK,
STATE_ACTIVATING_PDP_CONTEXT,
STATE_CONNECTING_NETWORK,
Expand Down Expand Up @@ -139,12 +140,24 @@ class CellularConnectionFSM
*/
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();
Expand All @@ -157,6 +170,7 @@ class CellularConnectionFSM
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();
Expand All @@ -165,6 +179,7 @@ class CellularConnectionFSM
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;
Expand Down Expand Up @@ -198,6 +213,9 @@ class CellularConnectionFSM
events::EventQueue _at_queue;
char _st_string[20];
int _event_id;
const char* _plmn;
bool _command_success;
bool _plmn_network_found;
};

} // namespace
Expand Down
5 changes: 5 additions & 0 deletions features/cellular/easy_cellular/EasyCellularConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
6 changes: 6 additions & 0 deletions features/cellular/easy_cellular/EasyCellularConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ class EasyCellularConnection: public CellularBase
*/
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
Expand Down
18 changes: 18 additions & 0 deletions features/cellular/framework/API/CellularNetwork.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,18 @@ class CellularNetwork : public NetworkInterface
};
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
Expand Down Expand Up @@ -452,6 +464,12 @@ class CellularNetwork : public NetworkInterface
*/
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
Expand Down
Loading