Skip to content

Commit 9cc4302

Browse files
authored
Merge pull request #6629 from jarvte/add_select_plmn_to_cellularfsm
Cellular: add plmn for CellularConnectionFSM
2 parents 15cac12 + 55f4360 commit 9cc4302

File tree

7 files changed

+196
-20
lines changed

7 files changed

+196
-20
lines changed

features/cellular/easy_cellular/CellularConnectionFSM.cpp

Lines changed: 110 additions & 16 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)
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
@@ -146,6 +146,11 @@ void CellularConnectionFSM::set_sim_pin(const char * sim_pin)
146146
_sim_pin[sizeof(_sim_pin)-1] = '\0';
147147
}
148148

149+
void CellularConnectionFSM::set_plmn(const char* plmn)
150+
{
151+
_plmn = plmn;
152+
}
153+
149154
bool CellularConnectionFSM::open_sim()
150155
{
151156
CellularSIM::SimState state = CellularSIM::SimStateUnknown;
@@ -162,7 +167,7 @@ bool CellularConnectionFSM::open_sim()
162167
nsapi_error_t err = _sim->set_pin(_sim_pin);
163168
if (err) {
164169
tr_error("SIM pin set failed with: %d, bailing out...", err);
165-
}
170+
}
166171
} else {
167172
tr_warn("PIN required but No SIM pin provided.");
168173
}
@@ -175,11 +180,10 @@ bool CellularConnectionFSM::open_sim()
175180
return state == CellularSIM::SimStateReady;
176181
}
177182

178-
bool CellularConnectionFSM::set_network_registration(char *plmn)
183+
bool CellularConnectionFSM::set_network_registration()
179184
{
180-
nsapi_error_t error = _network->set_registration(plmn);
181-
if (error != NSAPI_ERROR_OK) {
182-
tr_error("Set network registration mode failing (%d)", error);
185+
if (_network->set_registration(_plmn) != NSAPI_ERROR_OK) {
186+
tr_error("Failed to set network registration.");
183187
return false;
184188
}
185189
return true;
@@ -279,8 +283,12 @@ void CellularConnectionFSM::report_failure(const char* msg)
279283

280284
const char* CellularConnectionFSM::get_state_string(CellularState state)
281285
{
282-
static const char *strings[] = { "Init", "Power", "Device ready", "SIM pin", "Registering network", "Attaching network", "Activating PDP Context", "Connecting network", "Connected"};
286+
#if MBED_CONF_MBED_TRACE_ENABLE
287+
static const char *strings[] = { "Init", "Power", "Device ready", "SIM pin", "Registering network", "Manual registering", "Attaching network", "Activating PDP Context", "Connecting network", "Connected"};
283288
return strings[state];
289+
#else
290+
return NULL;
291+
#endif // #if MBED_CONF_MBED_TRACE_ENABLE
284292
}
285293

286294
nsapi_error_t CellularConnectionFSM::is_automatic_registering(bool& auto_reg)
@@ -294,6 +302,54 @@ nsapi_error_t CellularConnectionFSM::is_automatic_registering(bool& auto_reg)
294302
return err;
295303
}
296304

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+
}
342+
names_list.delete_all();
343+
return false;
344+
}
345+
}
346+
}
347+
names_list.delete_all();
348+
}
349+
350+
return false;
351+
}
352+
297353
nsapi_error_t CellularConnectionFSM::continue_from_state(CellularState state)
298354
{
299355
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)
330386
{
331387
_next_state = state;
332388
_retry_count = 0;
389+
_command_success = false;
333390
}
334391

335392
void CellularConnectionFSM::retry_state_or_fail()
@@ -406,7 +463,11 @@ void CellularConnectionFSM::state_sim_pin()
406463
_cellularDevice->set_timeout(TIMEOUT_SIM_PIN);
407464
tr_info("Sim state (timeout %d ms)", TIMEOUT_SIM_PIN);
408465
if (open_sim()) {
409-
enter_to_state(STATE_REGISTERING_NETWORK);
466+
if (_plmn) {
467+
enter_to_state(STATE_MANUAL_REGISTERING_NETWORK);
468+
} else {
469+
enter_to_state(STATE_REGISTERING_NETWORK);
470+
}
410471
} else {
411472
retry_state_or_fail();
412473
}
@@ -421,7 +482,7 @@ void CellularConnectionFSM::state_registering()
421482
} else {
422483
bool auto_reg = false;
423484
nsapi_error_t err = is_automatic_registering(auto_reg);
424-
if (err == NSAPI_ERROR_OK && !auto_reg) { // when we support plmn add this : || plmn
485+
if (err == NSAPI_ERROR_OK && !auto_reg) {
425486
// automatic registering is not on, set registration and retry
426487
_cellularDevice->set_timeout(TIMEOUT_REGISTRATION);
427488
set_network_registration();
@@ -430,6 +491,24 @@ void CellularConnectionFSM::state_registering()
430491
}
431492
}
432493

494+
// only used when _plmn is set
495+
void CellularConnectionFSM::state_manual_registering_network()
496+
{
497+
_cellularDevice->set_timeout(TIMEOUT_REGISTRATION);
498+
tr_info("state_manual_registering_network");
499+
if (!_plmn_network_found) {
500+
if (is_registered() && is_registered_to_plmn()) {
501+
_plmn_network_found = true;
502+
enter_to_state(STATE_ATTACHING_NETWORK);
503+
} else {
504+
if (!_command_success) {
505+
_command_success = set_network_registration();
506+
}
507+
retry_state_or_fail();
508+
}
509+
}
510+
}
511+
433512
void CellularConnectionFSM::state_attaching()
434513
{
435514
_cellularDevice->set_timeout(TIMEOUT_CONNECT);
@@ -438,7 +517,9 @@ void CellularConnectionFSM::state_attaching()
438517
if (attach_status == CellularNetwork::Attached) {
439518
enter_to_state(STATE_ACTIVATING_PDP_CONTEXT);
440519
} else {
441-
set_attach_network();
520+
if (!_command_success) {
521+
_command_success = set_attach_network();
522+
}
442523
retry_state_or_fail();
443524
}
444525
} else {
@@ -500,6 +581,9 @@ void CellularConnectionFSM::event()
500581
case STATE_REGISTERING_NETWORK:
501582
state_registering();
502583
break;
584+
case STATE_MANUAL_REGISTERING_NETWORK:
585+
state_manual_registering_network();
586+
break;
503587
case STATE_ATTACHING_NETWORK:
504588
state_attaching();
505589
break;
@@ -576,13 +660,23 @@ void CellularConnectionFSM::attach(mbed::Callback<void(nsapi_event_t, intptr_t)>
576660

577661
void CellularConnectionFSM::network_callback(nsapi_event_t ev, intptr_t ptr)
578662
{
579-
580-
tr_info("FSM: network_callback called with event: %d, intptr: %d", ev, ptr);
581-
if ((cellular_connection_status_t)ev == CellularRegistrationStatusChanged && _state == STATE_REGISTERING_NETWORK) {
663+
tr_info("FSM: network_callback called with event: %d, intptr: %d, _state: %s", ev, ptr, get_state_string(_state));
664+
if ((cellular_connection_status_t)ev == CellularRegistrationStatusChanged &&
665+
(_state == STATE_REGISTERING_NETWORK || _state == STATE_MANUAL_REGISTERING_NETWORK)) {
582666
// expect packet data so only these states are valid
583-
if (ptr == CellularNetwork::RegisteredHomeNetwork && CellularNetwork::RegisteredRoaming) {
584-
_queue.cancel(_event_id);
585-
continue_from_state(STATE_ATTACHING_NETWORK);
667+
if (ptr == CellularNetwork::RegisteredHomeNetwork || ptr == CellularNetwork::RegisteredRoaming) {
668+
if (_plmn) {
669+
if (is_registered_to_plmn()) {
670+
if (!_plmn_network_found) {
671+
_plmn_network_found = true;
672+
_queue.cancel(_event_id);
673+
continue_from_state(STATE_ATTACHING_NETWORK);
674+
}
675+
}
676+
} else {
677+
_queue.cancel(_event_id);
678+
continue_from_state(STATE_ATTACHING_NETWORK);
679+
}
586680
}
587681
}
588682

features/cellular/easy_cellular/CellularConnectionFSM.h

Lines changed: 19 additions & 1 deletion
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,
@@ -139,12 +140,24 @@ class CellularConnectionFSM
139140
*/
140141
void set_retry_timeout_array(uint16_t timeout[], int array_len);
141142

143+
/** Sets the operator plmn which is used when registering to a network specified by plmn. If plmn is not set then automatic
144+
* registering is used when registering to a cellular network. Does not start any operations.
145+
*
146+
* @param plmn operator in numeric format. See more from 3GPP TS 27.007 chapter 7.3.
147+
*/
148+
void set_plmn(const char* plmn);
149+
150+
/** returns readable format of the given state. Used for printing states while debugging.
151+
*
152+
* @param state state which is returned in string format
153+
* @return string format of the given state
154+
*/
142155
const char* get_state_string(CellularState state);
143156
private:
144157
bool power_on();
145158
bool open_sim();
146159
bool get_network_registration(CellularNetwork::RegistrationType type, CellularNetwork::RegistrationStatus &status, bool &is_registered);
147-
bool set_network_registration(char *plmn = 0);
160+
bool set_network_registration();
148161
bool get_attach_network(CellularNetwork::AttachStatus &status);
149162
bool set_attach_network();
150163
bool is_registered();
@@ -157,6 +170,7 @@ class CellularConnectionFSM
157170
void state_device_ready();
158171
void state_sim_pin();
159172
void state_registering();
173+
void state_manual_registering_network();
160174
void state_attaching();
161175
void state_activating_pdp_context();
162176
void state_connect_to_network();
@@ -165,6 +179,7 @@ class CellularConnectionFSM
165179
void retry_state_or_fail();
166180
void network_callback(nsapi_event_t ev, intptr_t ptr);
167181
nsapi_error_t continue_from_state(CellularState state);
182+
bool is_registered_to_plmn();
168183

169184
private:
170185
friend class EasyCellularConnection;
@@ -198,6 +213,9 @@ class CellularConnectionFSM
198213
events::EventQueue _at_queue;
199214
char _st_string[20];
200215
int _event_id;
216+
const char* _plmn;
217+
bool _command_success;
218+
bool _plmn_network_found;
201219
};
202220

203221
} // namespace

features/cellular/easy_cellular/EasyCellularConnection.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,11 @@ void EasyCellularConnection::modem_debug_on(bool on)
280280
}
281281
}
282282

283+
void EasyCellularConnection::set_plmn(const char* plmn)
284+
{
285+
_cellularConnectionFSM.set_plmn(plmn);
286+
}
287+
283288
NetworkStack *EasyCellularConnection::get_stack()
284289
{
285290
return _cellularConnectionFSM.get_stack();

features/cellular/easy_cellular/EasyCellularConnection.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ class EasyCellularConnection: public CellularBase
131131
*/
132132
void modem_debug_on(bool on);
133133

134+
/** Sets the operator plmn which is used when registering to a network specified by plmn. If plmn is not set then automatic
135+
* registering is used when registering to a cellular network.
136+
*
137+
* @param plmn operator in numeric format. See more from 3GPP TS 27.007 chapter 7.3.
138+
*/
139+
void set_plmn(const char* plmn);
134140
protected:
135141

136142
/** Provide access to the NetworkStack object

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
@@ -460,6 +472,12 @@ class CellularNetwork : public NetworkInterface
460472
*/
461473
virtual nsapi_error_t set_blocking(bool blocking) = 0;
462474

475+
/** Read operator names
476+
*
477+
* @param op_names on successful return will contain linked list of operator names.
478+
* @return zero on success
479+
*/
480+
virtual nsapi_error_t get_operator_names(operator_names_list &op_names) = 0;
463481
};
464482

465483
} // namespace mbed

0 commit comments

Comments
 (0)