@@ -39,7 +39,7 @@ static const at_reg_t at_reg[] = {
39
39
AT_CellularNetwork::AT_CellularNetwork (ATHandler &atHandler) : AT_CellularBase(atHandler),
40
40
_stack(NULL ), _apn(NULL ), _uname(NULL ), _pwd(NULL ), _ip_stack_type_requested(DEFAULT_STACK), _ip_stack_type(DEFAULT_STACK), _cid(-1 ),
41
41
_connection_status_cb(NULL ), _op_act(operator_t ::RAT_UNKNOWN), _authentication_type(CHAP), _last_reg_type(C_REG),
42
- _connect_status(NSAPI_STATUS_DISCONNECTED)
42
+ _connect_status(NSAPI_STATUS_DISCONNECTED), _new_context_set( false )
43
43
{
44
44
45
45
_at.set_urc_handler (" NO CARRIER" , callback (this , &AT_CellularNetwork::urc_no_carrier));
@@ -131,6 +131,23 @@ nsapi_error_t AT_CellularNetwork::connect(const char *apn,
131
131
return connect ();
132
132
}
133
133
134
+ nsapi_error_t AT_CellularNetwork::delete_current_context ()
135
+ {
136
+ _at.clear_error ();
137
+ _at.cmd_start (" AT+CGDCONT=" );
138
+ _at.write_int (_cid);
139
+ _at.cmd_stop ();
140
+ _at.resp_start ();
141
+ _at.resp_stop ();
142
+
143
+ if (_at.get_last_error () == NSAPI_ERROR_OK) {
144
+ _cid = -1 ;
145
+ _new_context_set = false ;
146
+ }
147
+
148
+ return _at.get_last_error ();
149
+ }
150
+
134
151
nsapi_error_t AT_CellularNetwork::connect ()
135
152
{
136
153
_at.lock ();
@@ -155,7 +172,14 @@ nsapi_error_t AT_CellularNetwork::connect()
155
172
156
173
err = open_data_channel ();
157
174
if (err != NSAPI_ERROR_OK) {
175
+
176
+ // If new PDP context was created and failed to activate, delete it
177
+ if (_new_context_set) {
178
+ delete_current_context ();
179
+ }
180
+
158
181
_at.unlock ();
182
+
159
183
tr_error (" Failed to open data channel!" );
160
184
161
185
_connect_status = NSAPI_STATUS_DISCONNECTED;
@@ -294,7 +318,7 @@ void AT_CellularNetwork::ppp_status_cb(nsapi_event_t event, intptr_t parameter)
294
318
nsapi_error_t AT_CellularNetwork::set_context_to_be_activated ()
295
319
{
296
320
// try to find or create context with suitable stack
297
- if (!get_context (_ip_stack_type_requested )) {
321
+ if (!get_context ()) {
298
322
return NSAPI_ERROR_NO_CONNECTION;
299
323
}
300
324
@@ -316,12 +340,26 @@ nsapi_error_t AT_CellularNetwork::set_context_to_be_activated()
316
340
return _at.get_last_error ();
317
341
}
318
342
319
- bool AT_CellularNetwork::set_new_context (nsapi_ip_stack_t stack, int cid)
343
+ bool AT_CellularNetwork::set_new_context (int cid)
320
344
{
321
- nsapi_ip_stack_t tmp_stack = stack;
345
+ nsapi_ip_stack_t tmp_stack = _ip_stack_type_requested;
346
+
347
+ if (tmp_stack == DEFAULT_STACK) {
348
+ bool modem_supports_ipv6 = get_modem_stack_type (IPV6_STACK);
349
+ bool modem_supports_ipv4 = get_modem_stack_type (IPV4_STACK);
350
+
351
+ if (modem_supports_ipv6 && modem_supports_ipv4) {
352
+ tmp_stack = IPV4V6_STACK;
353
+ } else if (modem_supports_ipv6) {
354
+ tmp_stack = IPV6_STACK;
355
+ } else if (modem_supports_ipv4) {
356
+ tmp_stack = IPV4_STACK;
357
+ }
358
+ }
359
+
322
360
char pdp_type[8 +1 ] = {0 };
323
361
324
- switch (stack ) {
362
+ switch (tmp_stack ) {
325
363
case IPV4_STACK:
326
364
strncpy (pdp_type, " IP" , sizeof (pdp_type));
327
365
break ;
@@ -332,7 +370,6 @@ bool AT_CellularNetwork::set_new_context(nsapi_ip_stack_t stack, int cid)
332
370
strncpy (pdp_type, " IPV4V6" , sizeof (pdp_type));
333
371
break ;
334
372
default :
335
- strncpy (pdp_type, " " , sizeof (pdp_type));
336
373
break ;
337
374
}
338
375
@@ -363,12 +400,13 @@ bool AT_CellularNetwork::set_new_context(nsapi_ip_stack_t stack, int cid)
363
400
if (success) {
364
401
_ip_stack_type = tmp_stack;
365
402
_cid = cid;
403
+ _new_context_set = true ;
366
404
}
367
405
368
406
return success;
369
407
}
370
408
371
- bool AT_CellularNetwork::get_context (nsapi_ip_stack_t requested_stack )
409
+ bool AT_CellularNetwork::get_context ()
372
410
{
373
411
_at.cmd_start (" AT+CGDCONT?" );
374
412
_at.cmd_stop ();
@@ -378,6 +416,9 @@ bool AT_CellularNetwork::get_context(nsapi_ip_stack_t requested_stack)
378
416
char apn[MAX_ACCESSPOINT_NAME_LENGTH];
379
417
int apn_len = 0 ;
380
418
419
+ bool modem_supports_ipv6 = get_modem_stack_type (IPV6_STACK);
420
+ bool modem_supports_ipv4 = get_modem_stack_type (IPV4_STACK);
421
+
381
422
while (_at.info_resp ()) {
382
423
int cid = _at.read_int ();
383
424
if (cid > cid_max) {
@@ -392,29 +433,42 @@ bool AT_CellularNetwork::get_context(nsapi_ip_stack_t requested_stack)
392
433
continue ;
393
434
}
394
435
nsapi_ip_stack_t pdp_stack = string_to_stack_type (pdp_type_from_context);
395
- if (pdp_stack != DEFAULT_STACK) {
396
- if (get_modem_stack_type (pdp_stack)) {
397
- if (requested_stack == IPV4_STACK) {
398
- if (pdp_stack == IPV4_STACK || pdp_stack == IPV4V6_STACK) {
399
- _ip_stack_type = requested_stack;
436
+ // Accept dual PDP context for IPv4/IPv6 only modems
437
+ if (pdp_stack != DEFAULT_STACK && (get_modem_stack_type (pdp_stack) || pdp_stack == IPV4V6_STACK)) {
438
+ if (_ip_stack_type_requested == IPV4_STACK) {
439
+ if (pdp_stack == IPV4_STACK || pdp_stack == IPV4V6_STACK) {
440
+ _ip_stack_type = _ip_stack_type_requested;
441
+ _cid = cid;
442
+ break ;
443
+ }
444
+ } else if (_ip_stack_type_requested == IPV6_STACK) {
445
+ if (pdp_stack == IPV6_STACK || pdp_stack == IPV4V6_STACK) {
446
+ _ip_stack_type = _ip_stack_type_requested;
447
+ _cid = cid;
448
+ break ;
449
+ }
450
+ } else {
451
+ // If dual PDP need to check for IPV4 or IPV6 modem support. Prefer IPv6.
452
+ if (pdp_stack == IPV4V6_STACK) {
453
+ if (modem_supports_ipv6) {
454
+ _ip_stack_type = IPV6_STACK;
400
455
_cid = cid;
401
456
break ;
402
- }
403
- } else if (requested_stack == IPV6_STACK) {
404
- if (pdp_stack == IPV6_STACK || pdp_stack == IPV4V6_STACK) {
405
- _ip_stack_type = requested_stack;
457
+ } else if (modem_supports_ipv4) {
458
+ _ip_stack_type = IPV4_STACK;
406
459
_cid = cid;
407
460
break ;
408
461
}
409
- } else { // accept any but prefer to IPv6
410
- if (pdp_stack == IPV6_STACK || pdp_stack == IPV4V6_STACK) {
411
- _ip_stack_type = requested_stack;
412
- _cid = cid;
462
+ // If PDP is IPV4 or IPV6 they are already checked if supported
463
+ } else {
464
+ _ip_stack_type = pdp_stack;
465
+ _cid = cid;
466
+
467
+ if (pdp_stack == IPV6_STACK) {
413
468
break ;
414
469
}
415
- if (_ip_stack_type == DEFAULT_STACK) {
416
- _ip_stack_type = pdp_stack;
417
- _cid = cid;
470
+ if (pdp_stack == IPV4_STACK && !modem_supports_ipv6) {
471
+ break ;
418
472
}
419
473
}
420
474
}
@@ -424,7 +478,7 @@ bool AT_CellularNetwork::get_context(nsapi_ip_stack_t requested_stack)
424
478
}
425
479
_at.resp_stop ();
426
480
if (_cid == -1 ) { // no suitable context was found so create a new one
427
- if (!set_new_context (requested_stack, cid_max+1 )) {
481
+ if (!set_new_context (cid_max+1 )) {
428
482
return false ;
429
483
}
430
484
}
0 commit comments