17
17
18
18
#include < stdlib.h>
19
19
#include " GEMALTO_CINTERION_CellularStack.h"
20
+ #include " GEMALTO_CINTERION_Module.h"
20
21
#include " CellularLog.h"
21
22
22
- // defines as per ELS61-E2_ATC_V01.000
23
+ // defines as per ELS61-E2_ATC_V01.000 and BGS2-W_ATC_V00.100
23
24
#define SOCKET_MAX 10
24
25
#define UDP_PACKET_SIZE 1460
25
26
#define FAILURE_TIMEOUT (30 *1000 ) // failure timeout in milliseconds on modem side
@@ -84,6 +85,9 @@ void GEMALTO_CINTERION_CellularStack::urc_sisw()
84
85
if (urc_code == 1 ) { // ready
85
86
if (sock->_cb ) {
86
87
sock->tx_ready = true ;
88
+ if (GEMALTO_CINTERION_Module::get_model () == GEMALTO_CINTERION_Module::ModelBGS2) {
89
+ sock->started = true ;
90
+ }
87
91
sock->_cb (sock->_data );
88
92
}
89
93
} else if (urc_code == 2 ) { // socket closed
@@ -133,17 +137,64 @@ bool GEMALTO_CINTERION_CellularStack::is_protocol_supported(nsapi_protocol_t pro
133
137
134
138
nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_close_impl (int sock_id)
135
139
{
140
+ CellularSocket *socket = find_socket (sock_id);
141
+ if (!socket) {
142
+ return NSAPI_ERROR_NO_SOCKET;
143
+ }
136
144
_at.set_at_timeout (FAILURE_TIMEOUT);
137
145
_at.cmd_start (" AT^SISC=" );
138
146
_at.write_int (sock_id);
139
147
_at.cmd_stop ();
140
148
_at.resp_start ();
141
149
_at.resp_stop ();
142
150
_at.restore_at_timeout ();
151
+
152
+ socket->started = false ;
153
+ socket->created = false ;
154
+ socket->tx_ready = false ;
155
+ socket->rx_avail = false ;
156
+
143
157
tr_debug (" Closed socket %d (err %d)" , sock_id, _at.get_last_error ());
144
158
return _at.get_last_error ();
145
159
}
146
160
161
+ nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_open_defer (CellularSocket *socket, const SocketAddress *address)
162
+ {
163
+ // host address (IPv4) and local+remote port is needed only for BGS2 which does not support UDP server socket
164
+ char sock_addr[sizeof (" sockudp://" ) - 1 + NSAPI_IPv4_SIZE + sizeof (" :12345;port=12345" ) - 1 + 1 ];
165
+ if (GEMALTO_CINTERION_Module::get_model () != GEMALTO_CINTERION_Module::ModelBGS2) {
166
+ std::sprintf (sock_addr, " sockudp://%s:%u" , address ? address->get_ip_address () : " " , socket->localAddress .get_port ());
167
+ } else {
168
+ std::sprintf (sock_addr, " sockudp://%s:%u;port=%u" , address->get_ip_address (), address->get_port (), socket->localAddress .get_port ());
169
+ }
170
+
171
+ _at.cmd_start (" AT^SISS=" );
172
+ _at.write_int (socket->id );
173
+ _at.write_string (" address" , false );
174
+ _at.write_string (sock_addr);
175
+ _at.cmd_stop ();
176
+ _at.resp_start ();
177
+ _at.resp_stop ();
178
+
179
+
180
+ _at.cmd_start (" AT^SISO=" );
181
+ _at.write_int (socket->id );
182
+ _at.cmd_stop ();
183
+ _at.resp_start ();
184
+ _at.resp_stop ();
185
+ if (_at.get_last_error ()) {
186
+ tr_error (" Socket %d open failed!" , socket->id );
187
+ _at.clear_error ();
188
+ socket_close_impl (socket->id ); // socket may already be open on modem if app and modem are not in sync, as a recovery, try to close the socket so open succeeds the next time
189
+ return NSAPI_ERROR_NO_SOCKET;
190
+ }
191
+
192
+ socket->created = true ;
193
+ tr_debug (" Socket %d created (err %d)" , socket->id , _at.get_last_error ());
194
+
195
+ return _at.get_last_error ();
196
+ }
197
+
147
198
// To open socket:
148
199
// 1. Select URC mode or polling mode with AT^SCFG
149
200
// 2. create a GPRS connection profile with AT^SICS (must have PDP)
@@ -224,32 +275,9 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::create_socket_impl(CellularSocket
224
275
225
276
tr_debug (" Internet service %d created (err %d)" , internet_service_id, _at.get_last_error ());
226
277
227
- char sock_addr[sizeof (" sockudp://" ) + sizeof (" :" ) + sizeof (" 65535" ) + 1 ];
228
- std::sprintf (sock_addr, " sockudp://:%u" , socket->localAddress .get_port ());
229
- _at.cmd_start (" AT^SISS=" );
230
- _at.write_int (socket->id );
231
- _at.write_string (" address" , false );
232
- _at.write_string (sock_addr);
233
- _at.cmd_stop ();
234
- _at.resp_start ();
235
- _at.resp_stop ();
236
-
237
-
238
- _at.cmd_start (" AT^SISO=" );
239
- _at.write_int (socket->id );
240
- _at.cmd_stop ();
241
- _at.resp_start ();
242
- _at.resp_stop ();
243
- if (_at.get_last_error ()) {
244
- tr_error (" Socket %d open failed!" , socket->id );
245
- _at.clear_error ();
246
- socket_close_impl (socket->id );
247
- return NSAPI_ERROR_NO_SOCKET;
278
+ if (GEMALTO_CINTERION_Module::get_model () != GEMALTO_CINTERION_Module::ModelBGS2) {
279
+ return socket_open_defer (socket);
248
280
}
249
-
250
- socket->created = true ;
251
- tr_debug (" Socket %d created (err %d)" , socket->id , _at.get_last_error ());
252
-
253
281
return _at.get_last_error ();
254
282
}
255
283
@@ -264,9 +292,33 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul
264
292
tr_warn (" No IP route for %s" , address.get_ip_address ());
265
293
return NSAPI_ERROR_NO_SOCKET;
266
294
}
267
-
295
+ if (GEMALTO_CINTERION_Module::get_model () == GEMALTO_CINTERION_Module::ModelBGS2) {
296
+ tr_error (" Send addr %s, prev addr %s" , address.get_ip_address (), socket->remoteAddress .get_ip_address ());
297
+ if (address != socket->remoteAddress ) {
298
+ if (socket->started ) {
299
+ socket_close_impl (socket->id );
300
+ _at.clear_error ();
301
+ }
302
+ // socket->started = false;
303
+ if (socket_open_defer (socket, &address) != NSAPI_ERROR_OK) {
304
+ tr_error (" Failed to open socket %d" , socket->id );
305
+ return NSAPI_ERROR_NO_SOCKET;
306
+ }
307
+ socket->remoteAddress = address;
308
+ // return NSAPI_ERROR_WOULD_BLOCK;
309
+ _at.resp_start (" ^SISW:" );
310
+ int sock_id = _at.read_int ();
311
+ int urc_code = _at.read_int ();
312
+ tr_debug (" TX ready: socket=%d, urc=%d (err=%d)" , sock_id, urc_code, _at.get_last_error ());
313
+ (void )sock_id;
314
+ (void )urc_code;
315
+ socket->created = true ;
316
+ socket->started = true ;
317
+ socket->tx_ready = true ;
318
+ }
319
+ }
268
320
if (!socket->started || !socket->tx_ready ) {
269
- tr_debug (" Socket %d would block" , socket->id );
321
+ tr_debug (" Socket %d would block (started %d, tx %d) " , socket->id , socket-> started , socket-> tx_ready );
270
322
return NSAPI_ERROR_WOULD_BLOCK;
271
323
}
272
324
@@ -279,18 +331,19 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul
279
331
_at.cmd_start (" AT^SISW=" );
280
332
_at.write_int (socket->id );
281
333
_at.write_int (size);
282
- _at.write_int (0 );
283
- char ip_address[sizeof (" [1111:2222:3333:4444:5555:6666:7777:8888]:12345" ) + 1 ];
284
- if (address.get_ip_version () == NSAPI_IPv4) {
285
- std::sprintf (ip_address, " %s" , address.get_ip_address ());
286
- } else {
287
- std::sprintf (ip_address, " [%s]" , address.get_ip_address ());
334
+ if (GEMALTO_CINTERION_Module::get_model () != GEMALTO_CINTERION_Module::ModelBGS2) {
335
+ _at.write_int (0 );
336
+ char socket_address[NSAPI_IPv6_SIZE + sizeof (" []:12345" ) - 1 + 1 ];
337
+ if (address.get_ip_version () == NSAPI_IPv4) {
338
+ std::sprintf (socket_address, " %s:%u" , address.get_ip_address (), address.get_port ());
339
+ } else {
340
+ std::sprintf (socket_address, " [%s]:%u" , address.get_ip_address (), address.get_port ());
341
+ }
342
+ _at.write_string (socket_address);
288
343
}
289
- char socket_address[sizeof (ip_address) + sizeof (" :" ) + sizeof (" 65535" ) + 1 ];
290
- std::sprintf (socket_address, " %s:%u" , ip_address, address.get_port ());
291
- _at.write_string (socket_address);
292
344
_at.cmd_stop ();
293
345
346
+ sisw_retry:
294
347
_at.resp_start (" ^SISW:" );
295
348
if (!_at.info_resp ()) {
296
349
tr_error (" Socket %d send failure" , socket->id );
@@ -311,6 +364,11 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul
311
364
int unack_len = _at.read_int ();
312
365
if (unack_len != 0 ) {
313
366
tr_warn (" Socket %d unack_len %d" , socket->id , unack_len);
367
+ if (GEMALTO_CINTERION_Module::get_model () != GEMALTO_CINTERION_Module::ModelBGS2) {
368
+ // assume that an URC was received when unackData is not received
369
+ _at.resp_stop ();
370
+ goto sisw_retry;
371
+ }
314
372
}
315
373
316
374
_at.write_bytes ((uint8_t *)data, accept_len);
@@ -375,44 +433,49 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
375
433
socket->rx_avail = true ;
376
434
}
377
435
}
378
- char ip_address[sizeof (" [1111:2222:3333:4444:5555:6666:7777:8888]:12345" ) + 1 ];
379
- int ip_len = _at.read_string (ip_address, sizeof (ip_address));
380
- tr_error (" ip %s" , ip_address);
381
- if (ip_len <= 0 ) {
382
- tr_error (" Socket %d recvfrom addr!" , socket->id );
383
- return NSAPI_ERROR_DEVICE_ERROR;
384
- }
385
- if (address) {
386
- char *ip_start = ip_address;
387
- char *ip_stop;
388
- char *port_start;
389
- if (_stack_type == IPV6_STACK) {
390
- ip_start++; // skip '['
391
- ip_stop = strchr (ip_address, ' ]' );
392
- if (ip_stop) {
393
- port_start = strchr (ip_stop, ' :' );
436
+ if (GEMALTO_CINTERION_Module::get_model () != GEMALTO_CINTERION_Module::ModelBGS2) {
437
+ char ip_address[NSAPI_IPv6_SIZE + sizeof (" []:12345" ) - 1 + 1 ];
438
+ int ip_len = _at.read_string (ip_address, sizeof (ip_address));
439
+ if (ip_len <= 0 ) {
440
+ tr_error (" Socket %d recvfrom addr!" , socket->id );
441
+ return NSAPI_ERROR_DEVICE_ERROR;
442
+ }
443
+ if (address) {
444
+ char *ip_start = ip_address;
445
+ char *ip_stop;
446
+ char *port_start;
447
+ if (_stack_type == IPV6_STACK) {
448
+ ip_start++; // skip '['
449
+ ip_stop = strchr (ip_address, ' ]' );
450
+ if (ip_stop) {
451
+ port_start = strchr (ip_stop, ' :' );
452
+ }
453
+ } else {
454
+ ip_stop = strchr (ip_address, ' :' );
455
+ port_start = ip_stop;
456
+ }
457
+ if (ip_stop && port_start) {
458
+ char tmp_ch = *ip_stop;
459
+ *ip_stop = ' \0 ' ; // split IP and port
460
+ address->set_ip_address (ip_start);
461
+ port_start++; // skip ':'
462
+ int port = std::strtol (port_start, NULL , 10 );
463
+ address->set_port (port);
464
+ tr_debug (" IP address %s:%d" , address->get_ip_address (), address->get_port ());
465
+ *ip_stop = tmp_ch; // restore original IP string
394
466
}
395
- } else {
396
- ip_stop = strchr (ip_address, ' :' );
397
- port_start = ip_stop;
398
467
}
399
- if (ip_stop && port_start) {
400
- char tmp_ch = *ip_stop;
401
- *ip_stop = ' \0 ' ; // split IP and port
402
- address->set_ip_address (ip_start);
403
- port_start++; // skip ':'
404
- int port = std::strtol (port_start, NULL , 10 );
405
- address->set_port (port);
406
- tr_debug (" IP address %s:%d" , address->get_ip_address (), address->get_port ());
407
- *ip_stop = tmp_ch; // restore original IP string
468
+ } else {
469
+ if (address) {
470
+ *address = socket->remoteAddress ;
408
471
}
409
472
}
410
473
411
474
nsapi_size_or_error_t recv_len = _at.read_bytes ((uint8_t *)buffer, len);
412
475
413
476
_at.resp_stop ();
414
477
415
- tr_debug (" Socket %d, recvfrom %s, %d bytes (err %d)" , socket->id , ip_address , len, _at.get_last_error ());
478
+ tr_debug (" Socket %d, recvfrom %s, %d bytes (err %d)" , socket->id , address , len, _at.get_last_error ());
416
479
417
480
return (_at.get_last_error () == NSAPI_ERROR_OK) ? recv_len : NSAPI_ERROR_DEVICE_ERROR;
418
481
}
0 commit comments