Skip to content

Commit e78e1d2

Browse files
author
Teppo Järvelin
committed
Cellular: check plmn against network to verify correct network and don't try to register again if we are are already in correct nw.
1 parent e4c37f2 commit e78e1d2

File tree

5 files changed

+156
-27
lines changed

5 files changed

+156
-27
lines changed

features/cellular/easy_cellular/CellularConnectionFSM.cpp

Lines changed: 102 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ namespace mbed
4343
CellularConnectionFSM::CellularConnectionFSM() :
4444
_serial(0), _state(STATE_INIT), _next_state(_state), _status_callback(0), _event_status_cb(0), _network(0), _power(0), _sim(0),
4545
_queue(8 * EVENTS_EVENT_SIZE), _queue_thread(0), _cellularDevice(0), _retry_count(0), _event_timeout(-1),
46-
_at_queue(8 * EVENTS_EVENT_SIZE), _event_id(0), _plmn(0)
46+
_at_queue(8 * EVENTS_EVENT_SIZE), _event_id(0), _plmn(0), _command_success(false), _plmn_network_found(false)
4747
{
4848
memset(_sim_pin, 0, sizeof(_sim_pin));
4949
#if MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY == 0
@@ -284,7 +284,7 @@ void CellularConnectionFSM::report_failure(const char* msg)
284284
const char* CellularConnectionFSM::get_state_string(CellularState state)
285285
{
286286
#if MBED_CONF_MBED_TRACE_ENABLE
287-
static const char *strings[] = { "Init", "Power", "Device ready", "SIM pin", "Registering network", "Attaching network", "Connecting network", "Connected"};
287+
static const char *strings[] = { "Init", "Power", "Device ready", "SIM pin", "Registering network", "Manual registering", "Attaching network", "Connecting network", "Connected"};
288288
return strings[state];
289289
#else
290290
return NULL;
@@ -302,6 +302,55 @@ nsapi_error_t CellularConnectionFSM::is_automatic_registering(bool& auto_reg)
302302
return err;
303303
}
304304

305+
bool CellularConnectionFSM::is_registered_to_plmn()
306+
{
307+
int format;
308+
CellularNetwork::operator_t op;
309+
310+
nsapi_error_t err = _network->get_operator_params(format, op);
311+
if (err == NSAPI_ERROR_OK) {
312+
if (format == 2) {
313+
// great, numeric format we can do comparison for that
314+
if (strcmp(op.op_num, _plmn) == 0) {
315+
return true;
316+
}
317+
return false;
318+
}
319+
320+
// format was alpha, get operator names to do the comparing
321+
CellularNetwork::operator_names_list names_list;
322+
nsapi_error_t err = _network->get_operator_names(names_list);
323+
if (err == NSAPI_ERROR_OK) {
324+
CellularNetwork::operator_names_t* op_names = names_list.get_head();
325+
bool found_match = false;
326+
while (op_names) {
327+
if (format == 0) {
328+
if (strcmp(op.op_long, op_names->alpha) == 0) {
329+
found_match = true;
330+
}
331+
} else if (format == 1) {
332+
if (strcmp(op.op_short, op_names->alpha) == 0) {
333+
found_match = true;
334+
}
335+
}
336+
337+
if (found_match) {
338+
if (strcmp(_plmn, op_names->numeric)) {
339+
names_list.delete_all();
340+
return true;
341+
} else {
342+
names_list.delete_all();
343+
return false;
344+
}
345+
}
346+
}
347+
}
348+
names_list.delete_all();
349+
}
350+
351+
return false;
352+
}
353+
305354
nsapi_error_t CellularConnectionFSM::continue_from_state(CellularState state)
306355
{
307356
tr_info("Continue state from %s to %s", get_state_string((CellularConnectionFSM::CellularState)_state),
@@ -338,6 +387,7 @@ void CellularConnectionFSM::enter_to_state(CellularState state)
338387
{
339388
_next_state = state;
340389
_retry_count = 0;
390+
_command_success = false;
341391
}
342392

343393
void CellularConnectionFSM::retry_state_or_fail()
@@ -414,7 +464,11 @@ void CellularConnectionFSM::state_sim_pin()
414464
_cellularDevice->set_timeout(TIMEOUT_SIM_PIN);
415465
tr_info("Sim state (timeout %d ms)", TIMEOUT_SIM_PIN);
416466
if (open_sim()) {
417-
enter_to_state(STATE_REGISTERING_NETWORK);
467+
if (_plmn) {
468+
enter_to_state(STATE_MANUAL_REGISTERING_NETWORK);
469+
} else {
470+
enter_to_state(STATE_REGISTERING_NETWORK);
471+
}
418472
} else {
419473
retry_state_or_fail();
420474
}
@@ -424,28 +478,35 @@ void CellularConnectionFSM::state_registering()
424478
{
425479
_cellularDevice->set_timeout(TIMEOUT_NETWORK);
426480
if (is_registered()) {
427-
if (_plmn && _retry_count == 0) {
428-
// we don't know which network we are registered, try to register to specific network
481+
// we are already registered, go to attach
482+
enter_to_state(STATE_ATTACHING_NETWORK);
483+
} else {
484+
bool auto_reg = false;
485+
nsapi_error_t err = is_automatic_registering(auto_reg);
486+
if (err == NSAPI_ERROR_OK && !auto_reg) {
487+
// automatic registering is not on, set registration and retry
429488
_cellularDevice->set_timeout(TIMEOUT_REGISTRATION);
430489
set_network_registration();
431-
retry_state_or_fail();
432-
} else {
433-
// we are already registered, go to attach
434-
enter_to_state(STATE_ATTACHING_NETWORK);
435490
}
436-
} else {
437-
if (_plmn) {
438-
set_network_registration();
491+
retry_state_or_fail();
492+
}
493+
}
494+
495+
// only used when _plmn is set
496+
void CellularConnectionFSM::state_manual_registering_network()
497+
{
498+
_cellularDevice->set_timeout(TIMEOUT_REGISTRATION);
499+
tr_info("state_manual_registering_network");
500+
if (!_plmn_network_found) {
501+
if (is_registered() && is_registered_to_plmn()) {
502+
_plmn_network_found = true;
503+
enter_to_state(STATE_ATTACHING_NETWORK);
439504
} else {
440-
bool auto_reg = false;
441-
nsapi_error_t err = is_automatic_registering(auto_reg);
442-
if (err == NSAPI_ERROR_OK && !auto_reg) {
443-
// automatic registering is not on, set registration and retry
444-
_cellularDevice->set_timeout(TIMEOUT_REGISTRATION);
445-
set_network_registration();
505+
if (!_command_success) {
506+
_command_success = set_network_registration();
446507
}
508+
retry_state_or_fail();
447509
}
448-
retry_state_or_fail();
449510
}
450511
}
451512

@@ -457,7 +518,9 @@ void CellularConnectionFSM::state_attaching()
457518
if (attach_status == CellularNetwork::Attached) {
458519
enter_to_state(STATE_ACTIVATING_PDP_CONTEXT);
459520
} else {
460-
set_attach_network();
521+
if (!_command_success) {
522+
_command_success = set_attach_network();
523+
}
461524
retry_state_or_fail();
462525
}
463526
} else {
@@ -519,6 +582,9 @@ void CellularConnectionFSM::event()
519582
case STATE_REGISTERING_NETWORK:
520583
state_registering();
521584
break;
585+
case STATE_MANUAL_REGISTERING_NETWORK:
586+
state_manual_registering_network();
587+
break;
522588
case STATE_ATTACHING_NETWORK:
523589
state_attaching();
524590
break;
@@ -595,13 +661,23 @@ void CellularConnectionFSM::attach(mbed::Callback<void(nsapi_event_t, intptr_t)>
595661

596662
void CellularConnectionFSM::network_callback(nsapi_event_t ev, intptr_t ptr)
597663
{
598-
599-
tr_info("FSM: network_callback called with event: %d, intptr: %d", ev, ptr);
600-
if ((cellular_connection_status_t)ev == CellularRegistrationStatusChanged && _state == STATE_REGISTERING_NETWORK) {
664+
tr_info("FSM: network_callback called with event: %d, intptr: %d, _state: %s", ev, ptr, get_state_string(_state));
665+
if ((cellular_connection_status_t)ev == CellularRegistrationStatusChanged &&
666+
(_state == STATE_REGISTERING_NETWORK || _state == STATE_MANUAL_REGISTERING_NETWORK)) {
601667
// expect packet data so only these states are valid
602-
if (ptr == CellularNetwork::RegisteredHomeNetwork && CellularNetwork::RegisteredRoaming) {
603-
_queue.cancel(_event_id);
604-
continue_from_state(STATE_ATTACHING_NETWORK);
668+
if (ptr == CellularNetwork::RegisteredHomeNetwork || ptr == CellularNetwork::RegisteredRoaming) {
669+
if (_plmn) {
670+
if (is_registered_to_plmn()) {
671+
if (!_plmn_network_found) {
672+
_plmn_network_found = true;
673+
_queue.cancel(_event_id);
674+
continue_from_state(STATE_ATTACHING_NETWORK);
675+
}
676+
}
677+
} else {
678+
_queue.cancel(_event_id);
679+
continue_from_state(STATE_ATTACHING_NETWORK);
680+
}
605681
}
606682
}
607683

features/cellular/easy_cellular/CellularConnectionFSM.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class CellularConnectionFSM
5858
STATE_DEVICE_READY,
5959
STATE_SIM_PIN,
6060
STATE_REGISTERING_NETWORK,
61+
STATE_MANUAL_REGISTERING_NETWORK,
6162
STATE_ATTACHING_NETWORK,
6263
STATE_ACTIVATING_PDP_CONTEXT,
6364
STATE_CONNECTING_NETWORK,
@@ -169,6 +170,7 @@ class CellularConnectionFSM
169170
void state_device_ready();
170171
void state_sim_pin();
171172
void state_registering();
173+
void state_manual_registering_network();
172174
void state_attaching();
173175
void state_activating_pdp_context();
174176
void state_connect_to_network();
@@ -177,6 +179,7 @@ class CellularConnectionFSM
177179
void retry_state_or_fail();
178180
void network_callback(nsapi_event_t ev, intptr_t ptr);
179181
nsapi_error_t continue_from_state(CellularState state);
182+
bool is_registered_to_plmn();
180183

181184
private:
182185
friend class EasyCellularConnection;
@@ -211,6 +214,8 @@ class CellularConnectionFSM
211214
char _st_string[20];
212215
int _event_id;
213216
const char* _plmn;
217+
bool _command_success;
218+
bool _plmn_network_found;
214219
};
215220

216221
} // namespace

features/cellular/framework/API/CellularNetwork.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,18 @@ class CellularNetwork : public NetworkInterface
199199
};
200200
typedef CellularList<pdpcontext_params_t> pdpContextList_t;
201201

202+
struct operator_names_t {
203+
char numeric[MAX_OPERATOR_NAME_SHORT+1];
204+
char alpha[MAX_OPERATOR_NAME_LONG+1];
205+
operator_names_t* next;
206+
operator_names_t() {
207+
numeric[0] = '\0';
208+
alpha[0] = '\0';
209+
next = NULL;
210+
}
211+
};
212+
typedef CellularList<operator_names_t> operator_names_list;
213+
202214
/* Network registering mode */
203215
enum NWRegisteringMode {
204216
NWModeAutomatic = 0, // automatic registering
@@ -452,6 +464,12 @@ class CellularNetwork : public NetworkInterface
452464
*/
453465
virtual nsapi_error_t set_blocking(bool blocking) = 0;
454466

467+
/** Read operator names
468+
*
469+
* @param op_names on successful return will contain linked list of operator names.
470+
* @return zero on success
471+
*/
472+
virtual nsapi_error_t get_operator_names(operator_names_list &op_names) = 0;
455473
};
456474

457475
} // namespace mbed

features/cellular/framework/AT/AT_CellularNetwork.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,12 @@ nsapi_error_t AT_CellularNetwork::scan_plmn(operList_t &operators, int &opsCount
899899
while (_at.info_elem('(')) {
900900

901901
op = operators.add_new();
902+
if (!op) {
903+
tr_warn("Could not allocate new operator");
904+
_at.resp_stop();
905+
opsCount = idx;
906+
return _at.unlock_return_error();
907+
}
902908

903909
op->op_status = (operator_t::Status)_at.read_int();
904910
_at.read_string(op->op_long, sizeof(op->op_long));
@@ -920,7 +926,6 @@ nsapi_error_t AT_CellularNetwork::scan_plmn(operList_t &operators, int &opsCount
920926
_at.resp_stop();
921927

922928
opsCount = idx;
923-
924929
return _at.unlock_return_error();
925930
}
926931

@@ -1174,3 +1179,27 @@ nsapi_error_t AT_CellularNetwork::get_operator_params(int &format, operator_t &o
11741179

11751180
return _at.unlock_return_error();
11761181
}
1182+
1183+
nsapi_error_t AT_CellularNetwork::get_operator_names(operator_names_list &op_names)
1184+
{
1185+
_at.lock();
1186+
1187+
_at.cmd_start("AT+COPN?");
1188+
_at.cmd_stop();
1189+
1190+
_at.resp_start("+COPN:");
1191+
operator_names_t *names = NULL;
1192+
while (_at.info_resp()) {
1193+
names = op_names.add_new();
1194+
if (!names) {
1195+
tr_warn("Could not allocate new operator_names_t");
1196+
_at.resp_stop();
1197+
return _at.unlock_return_error();
1198+
}
1199+
_at.read_string(names->numeric, sizeof(names->numeric));
1200+
_at.read_string(names->alpha, sizeof(names->alpha));
1201+
}
1202+
1203+
_at.resp_stop();
1204+
return _at.unlock_return_error();
1205+
}

features/cellular/framework/AT/AT_CellularNetwork.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ class AT_CellularNetwork : public CellularNetwork, public AT_CellularBase
139139
*/
140140
virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology op_rat);
141141

142+
virtual nsapi_error_t get_operator_names(operator_names_list &op_names);
142143
private:
143144
// "NO CARRIER" urc
144145
void urc_no_carrier();

0 commit comments

Comments
 (0)