@@ -39,6 +39,9 @@ GEMALTO_CINTERION_CellularStack::GEMALTO_CINTERION_CellularStack(ATHandler &atHa
39
39
40
40
GEMALTO_CINTERION_CellularStack::~GEMALTO_CINTERION_CellularStack ()
41
41
{
42
+ _at.remove_urc_handler (" ^SIS:" , mbed::Callback<void ()>(this , &GEMALTO_CINTERION_CellularStack::urc_sis));
43
+ _at.remove_urc_handler (" ^SISW:" , mbed::Callback<void ()>(this , &GEMALTO_CINTERION_CellularStack::urc_sisw));
44
+ _at.remove_urc_handler (" ^SISR:" , mbed::Callback<void ()>(this , &GEMALTO_CINTERION_CellularStack::urc_sisr));
42
45
}
43
46
44
47
GEMALTO_CINTERION_CellularStack::CellularSocket *GEMALTO_CINTERION_CellularStack::find_socket (int sock_id)
@@ -62,14 +65,14 @@ void GEMALTO_CINTERION_CellularStack::urc_sis()
62
65
int urc_code = _at.read_int ();
63
66
CellularSocket *sock = find_socket (sock_id);
64
67
if (sock) {
65
- if (urc_code == 5 ) { // data available
68
+ // Currently only UDP is supported so there is need to handle only some error codes here,
69
+ // and others are detected on sendto/recvfrom responses.
70
+ if (urc_code == 5 ) { // The service is ready to use (ELS61 and EMS31).
66
71
if (sock->_cb ) {
67
72
sock->started = true ;
68
73
sock->tx_ready = true ;
69
74
sock->_cb (sock->_data );
70
75
}
71
- } else if (urc_code == 2 ) { // socket closed
72
- sock->created = false ;
73
76
}
74
77
}
75
78
}
@@ -88,8 +91,6 @@ void GEMALTO_CINTERION_CellularStack::urc_sisw()
88
91
}
89
92
sock->_cb (sock->_data );
90
93
}
91
- } else if (urc_code == 2 ) { // socket closed
92
- sock->created = false ;
93
94
}
94
95
}
95
96
}
@@ -105,21 +106,30 @@ void GEMALTO_CINTERION_CellularStack::urc_sisr()
105
106
sock->rx_avail = true ;
106
107
sock->_cb (sock->_data );
107
108
}
108
- } else if (urc_code == 2 ) { // socket closed
109
- sock->created = false ;
110
109
}
111
110
}
112
111
}
113
112
114
113
nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_stack_init ()
115
114
{
116
115
_at.lock ();
117
- if (create_connection_profile ()) {
116
+ int connection_profile_id = CONNECTION_PROFILE_ID;
117
+ nsapi_error_t err = create_connection_profile (connection_profile_id);
118
+ if (!err) {
118
119
_at.set_urc_handler (" ^SIS:" , mbed::Callback<void ()>(this , &GEMALTO_CINTERION_CellularStack::urc_sis));
119
120
_at.set_urc_handler (" ^SISW:" , mbed::Callback<void ()>(this , &GEMALTO_CINTERION_CellularStack::urc_sisw));
120
121
_at.set_urc_handler (" ^SISR:" , mbed::Callback<void ()>(this , &GEMALTO_CINTERION_CellularStack::urc_sisr));
122
+ } else { // recovery cleanup
123
+ // close all Internet and connection profiles
124
+ for (int i = 0 ; i < SOCKET_MAX; i++) {
125
+ _at.clear_error ();
126
+ socket_close_impl (i);
127
+ }
128
+ _at.clear_error ();
129
+ close_connection_profile (connection_profile_id);
121
130
}
122
- return _at.unlock_return_error ();
131
+ _at.unlock ();
132
+ return err;
123
133
}
124
134
125
135
int GEMALTO_CINTERION_CellularStack::get_max_socket_count ()
@@ -134,22 +144,24 @@ bool GEMALTO_CINTERION_CellularStack::is_protocol_supported(nsapi_protocol_t pro
134
144
135
145
nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_close_impl (int sock_id)
136
146
{
137
- CellularSocket *socket = find_socket (sock_id);
138
- if (!socket) {
139
- return NSAPI_ERROR_NO_SOCKET;
140
- }
141
147
_at.set_at_timeout (FAILURE_TIMEOUT);
148
+
142
149
_at.cmd_start (" AT^SISC=" );
143
150
_at.write_int (sock_id);
144
151
_at.cmd_stop ();
145
152
_at.resp_start ();
146
153
_at.resp_stop ();
147
- _at.restore_at_timeout ();
148
154
149
- socket->started = false ;
150
- socket->created = false ;
151
- socket->tx_ready = false ;
152
- socket->rx_avail = false ;
155
+ _at.clear_error (); // clear SISS even though SISC fails
156
+ _at.cmd_start (" AT^SISS=" );
157
+ _at.write_int (sock_id);
158
+ _at.write_string (" srvType" );
159
+ _at.write_string (" none" );
160
+ _at.cmd_stop ();
161
+ _at.resp_start ();
162
+ _at.resp_stop ();
163
+
164
+ _at.restore_at_timeout ();
153
165
154
166
tr_debug (" Closed socket %d (err %d)" , sock_id, _at.get_last_error ());
155
167
return _at.get_last_error ();
@@ -267,7 +279,7 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::create_socket_impl(CellularSocket
267
279
_at.resp_stop ();
268
280
}
269
281
270
- tr_debug (" Internet service %d created (err %d)" , internet_service_id, _at.get_last_error ());
282
+ tr_debug (" Internet service %d (err %d)" , internet_service_id, _at.get_last_error ());
271
283
272
284
if (GEMALTO_CINTERION_Module::get_model () != GEMALTO_CINTERION_Module::ModelBGS2) {
273
285
return socket_open_defer (socket);
@@ -287,13 +299,17 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul
287
299
return NSAPI_ERROR_NO_SOCKET;
288
300
}
289
301
if (GEMALTO_CINTERION_Module::get_model () == GEMALTO_CINTERION_Module::ModelBGS2) {
290
- tr_error (" Send addr %s, prev addr %s" , address.get_ip_address (), socket->remoteAddress .get_ip_address ());
302
+ tr_debug (" Send addr %s, prev addr %s" , address.get_ip_address (), socket->remoteAddress .get_ip_address ());
291
303
if (address != socket->remoteAddress ) {
292
304
if (socket->started ) {
293
305
socket_close_impl (socket->id );
294
306
_at.clear_error ();
295
307
}
296
308
309
+ if (create_socket_impl (socket) != NSAPI_ERROR_OK) {
310
+ tr_error (" Failed to create socket %d" , socket->id );
311
+ return NSAPI_ERROR_NO_SOCKET;
312
+ }
297
313
if (socket_open_defer (socket, &address) != NSAPI_ERROR_OK) {
298
314
tr_error (" Failed to open socket %d" , socket->id );
299
315
return NSAPI_ERROR_NO_SOCKET;
@@ -381,11 +397,8 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
381
397
{
382
398
tr_debug (" Socket %d recvfrom %d bytes" , socket->id , size);
383
399
384
- if (size > UDP_PACKET_SIZE) {
385
- tr_debug (" Socket recvfrom size %d > %d" , size, UDP_PACKET_SIZE);
386
- size = UDP_PACKET_SIZE;
387
- }
388
-
400
+ // we must use this flag, otherwise ^SISR URC can come while we are reading response and there is
401
+ // no way to detect if that is really an URC or response
389
402
if (!socket->rx_avail ) {
390
403
_at.process_oob (); // check for ^SISR URC
391
404
if (!socket->rx_avail ) {
@@ -394,6 +407,11 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
394
407
}
395
408
}
396
409
410
+ if (size > UDP_PACKET_SIZE) {
411
+ tr_debug (" Socket recvfrom size %d > %d" , size, UDP_PACKET_SIZE);
412
+ size = UDP_PACKET_SIZE;
413
+ }
414
+
397
415
_at.cmd_start (" AT^SISR=" );
398
416
_at.write_int (socket->id );
399
417
_at.write_int (size);
@@ -468,30 +486,27 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
468
486
469
487
_at.resp_stop ();
470
488
471
- tr_debug (" Socket %d, recvfrom %s, %d bytes (err %d)" , socket->id , address , len, _at.get_last_error ());
489
+ tr_debug (" Socket %d, recvfrom %s, %d bytes (err %d)" , socket->id , socket-> remoteAddress . get_ip_address () , len, _at.get_last_error ());
472
490
473
- return (_at.get_last_error () == NSAPI_ERROR_OK) ? recv_len : NSAPI_ERROR_DEVICE_ERROR;
491
+ return (_at.get_last_error () == NSAPI_ERROR_OK) ? ( recv_len ? recv_len : NSAPI_ERROR_WOULD_BLOCK ) : NSAPI_ERROR_DEVICE_ERROR;
474
492
}
475
493
476
494
// setup internet connection profile for sockets
477
- bool GEMALTO_CINTERION_CellularStack::create_connection_profile ()
495
+ nsapi_error_t GEMALTO_CINTERION_CellularStack::create_connection_profile (int connection_profile_id )
478
496
{
479
497
if (GEMALTO_CINTERION_Module::get_model () == GEMALTO_CINTERION_Module::ModelEMS31) {
480
498
// EMS31 connection has only DNS settings and there is no need to modify those here for now
481
- return true ;
499
+ return NSAPI_ERROR_OK ;
482
500
}
483
501
484
- char conParamType[12 ];
502
+ char conParamType[sizeof ( " GPRS0 " ) + 1 ];
485
503
std::sprintf (conParamType, " GPRS%d" , (_stack_type == IPV4_STACK) ? 0 : 6 );
486
504
_at.cmd_start (" AT^SICS?" );
487
505
_at.cmd_stop ();
488
- bool foundConnection = false ;
489
- bool foundAPN = false ;
490
- int connection_profile_id = CONNECTION_PROFILE_ID;
506
+ bool found_connection = false ;
491
507
_at.resp_start (" ^SICS:" );
492
508
while (_at.info_resp ()) {
493
509
int id = _at.read_int ();
494
- tr_debug (" SICS %d" , id);
495
510
if (id == connection_profile_id) {
496
511
char paramTag[16 ];
497
512
int paramTagLen = _at.read_string (paramTag, sizeof (paramTag));
@@ -500,17 +515,10 @@ bool GEMALTO_CINTERION_CellularStack::create_connection_profile()
500
515
char paramValue[100 + 1 ]; // APN may be up to 100 chars
501
516
int paramValueLen = _at.read_string (paramValue, sizeof (paramValue));
502
517
if (paramValueLen >= 0 ) {
503
- tr_debug (" paramValue %s" , paramValue);
504
518
if (strcmp (paramTag, " conType" ) == 0 ) {
505
- tr_debug (" conType %s" , paramValue);
506
519
if (strcmp (paramValue, conParamType) == 0 ) {
507
- foundConnection = true ;
508
- }
509
- }
510
- if (strcmp (paramTag, " apn" ) == 0 ) {
511
- tr_debug (" apn %s" , paramValue);
512
- if (strcmp (paramValue, _apn ? _apn : " " ) == 0 ) {
513
- foundAPN = true ;
520
+ found_connection = true ;
521
+ break ;
514
522
}
515
523
}
516
524
}
@@ -519,34 +527,68 @@ bool GEMALTO_CINTERION_CellularStack::create_connection_profile()
519
527
}
520
528
_at.resp_stop ();
521
529
522
- if (!foundConnection) {
523
- tr_debug ( " Socket conType %s " , conParamType);
530
+ // connection profile is bound to a PDP context and it can not be changed
531
+ if (!found_connection) {
524
532
_at.cmd_start (" AT^SICS=" );
525
533
_at.write_int (connection_profile_id);
526
534
_at.write_string (" conType" );
527
535
_at.write_string (conParamType);
528
536
_at.cmd_stop ();
529
537
_at.resp_start ();
530
538
_at.resp_stop ();
531
- }
532
539
533
- if (!foundAPN && _apn) {
534
- tr_debug (" Socket APN %s" , _apn ? _apn : " " );
540
+ if (_apn && strlen (_apn) > 0 ) {
541
+ _at.cmd_start (" AT^SICS=" );
542
+ _at.write_int (connection_profile_id);
543
+ _at.write_string (" apn" );
544
+ _at.write_string (_apn);
545
+ _at.cmd_stop ();
546
+ _at.resp_start ();
547
+ _at.resp_stop ();
548
+ }
549
+
550
+ // set maximum inactivity timeout
535
551
_at.cmd_start (" AT^SICS=" );
536
552
_at.write_int (connection_profile_id);
537
- _at.write_string (" apn" );
538
- _at.write_string (_apn);
553
+ _at.write_string (" inactTO" );
554
+ _at.write_int (0xffff ); // 2^16-1
555
+ _at.cmd_stop ();
556
+ _at.resp_start ();
557
+ _at.resp_stop ();
558
+
559
+ // use URC mode ON
560
+ _at.cmd_start (" AT^SCFG=\" Tcp/withURCs\" ,\" on\" " );
539
561
_at.cmd_stop ();
540
562
_at.resp_start ();
541
563
_at.resp_stop ();
542
564
}
543
565
544
- // use URC mode
545
- _at.cmd_start (" AT^SCFG=\" Tcp/withURCs\" ,\" on\" " );
566
+ tr_debug (" Connection profile %d, stack_type %d (err %d)" , connection_profile_id, _stack_type, _at.get_last_error ());
567
+ return _at.get_last_error ();
568
+ }
569
+
570
+ void GEMALTO_CINTERION_CellularStack::close_connection_profile (int connection_profile_id)
571
+ {
572
+ if (GEMALTO_CINTERION_Module::get_model () == GEMALTO_CINTERION_Module::ModelEMS31) {
573
+ return ;
574
+ }
575
+
576
+ // To clear connection profile need to detach from packet data.
577
+ // After detach modem sends PDP disconnected event to network class,
578
+ // which propagates network disconnected to upper layer to start reconnecting.
579
+ _at.cmd_start (" AT+CGATT=0" );
580
+ _at.cmd_stop ();
581
+ _at.resp_start ();
582
+ _at.resp_stop ();
583
+ _at.clear_error ();
584
+
585
+ _at.cmd_start (" AT^SICS=" );
586
+ _at.write_int (connection_profile_id);
587
+ _at.write_string (" conType" );
588
+ _at.write_string (" none" );
546
589
_at.cmd_stop ();
547
590
_at.resp_start ();
548
591
_at.resp_stop ();
549
592
550
- tr_debug (" Connection profile %d created, stack_type %d (err %d)" , connection_profile_id, _stack_type, _at.get_last_error ());
551
- return _at.get_last_error () == NSAPI_ERROR_OK;
593
+ _at.clear_error ();
552
594
}
0 commit comments