Skip to content

Commit a14ac31

Browse files
author
Ari Parkkila
committed
Cellular: Added support for the Gemalto/BGS2 cellular module
1 parent 761e01f commit a14ac31

File tree

7 files changed

+157
-72
lines changed

7 files changed

+157
-72
lines changed

features/cellular/framework/AT/AT_CellularStack.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,10 +276,10 @@ nsapi_size_or_error_t AT_CellularStack::socket_sendto(nsapi_socket_t handle, con
276276

277277
ret_val = socket_sendto_impl(socket, addr, data, size);
278278

279-
if (ret_val <= 0) {
280-
tr_error("Error sending to: %s error code: %d", addr.get_ip_address(), ret_val);
281-
} else {
279+
if (ret_val > 0) {
282280
tr_info("Success sending %d Bytes to: %s", ret_val, addr.get_ip_address());
281+
} else if (ret_val != NSAPI_ERROR_WOULD_BLOCK) {
282+
tr_error("Error sending to: %s error code: %d", addr.get_ip_address(), ret_val);
283283
}
284284

285285
_at.unlock();

features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularNetwork.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "GEMALTO_CINTERION_CellularNetwork.h"
1919
#include "GEMALTO_CINTERION_CellularStack.h"
20+
#include "GEMALTO_CINTERION_Module.h"
2021

2122
using namespace mbed;
2223

@@ -28,21 +29,29 @@ GEMALTO_CINTERION_CellularNetwork::~GEMALTO_CINTERION_CellularNetwork()
2829
{
2930
}
3031

32+
#if !NSAPI_PPP_AVAILABLE
3133
NetworkStack *GEMALTO_CINTERION_CellularNetwork::get_stack()
3234
{
3335
if (!_stack) {
3436
_stack = new GEMALTO_CINTERION_CellularStack(_at, _apn, _cid, _ip_stack_type);
3537
}
3638
return _stack;
3739
}
40+
#endif // NSAPI_PPP_AVAILABLE
3841

3942
bool GEMALTO_CINTERION_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
4043
{
44+
if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
45+
return (requested_stack == IPV4_STACK);
46+
}
4147
return (requested_stack == IPV4_STACK || requested_stack == IPV6_STACK);
4248
}
4349

4450
bool GEMALTO_CINTERION_CellularNetwork::has_registration(RegistrationType reg_type)
4551
{
52+
if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
53+
return (reg_type == C_REG || reg_type == C_GREG);
54+
}
4655
return (reg_type == C_REG || reg_type == C_GREG || reg_type == C_EREG);
4756
}
4857

features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularNetwork.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ class GEMALTO_CINTERION_CellularNetwork : public AT_CellularNetwork {
2828
virtual ~GEMALTO_CINTERION_CellularNetwork();
2929

3030
protected:
31+
#if !NSAPI_PPP_AVAILABLE
3132
virtual NetworkStack *get_stack();
33+
#endif // NSAPI_PPP_AVAILABLE
3234

3335
virtual bool has_registration(RegistrationType reg_type);
3436

features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp

Lines changed: 129 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@
1717

1818
#include <stdlib.h>
1919
#include "GEMALTO_CINTERION_CellularStack.h"
20+
#include "GEMALTO_CINTERION_Module.h"
2021
#include "CellularLog.h"
2122

22-
// defines as per ELS61-E2_ATC_V01.000
23+
// defines as per ELS61-E2_ATC_V01.000 and BGS2-W_ATC_V00.100
2324
#define SOCKET_MAX 10
2425
#define UDP_PACKET_SIZE 1460
2526
#define FAILURE_TIMEOUT (30*1000) // failure timeout in milliseconds on modem side
@@ -84,6 +85,9 @@ void GEMALTO_CINTERION_CellularStack::urc_sisw()
8485
if (urc_code == 1) { // ready
8586
if (sock->_cb) {
8687
sock->tx_ready = true;
88+
if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
89+
sock->started = true;
90+
}
8791
sock->_cb(sock->_data);
8892
}
8993
} else if (urc_code == 2) { // socket closed
@@ -133,17 +137,64 @@ bool GEMALTO_CINTERION_CellularStack::is_protocol_supported(nsapi_protocol_t pro
133137

134138
nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_close_impl(int sock_id)
135139
{
140+
CellularSocket *socket = find_socket(sock_id);
141+
if (!socket) {
142+
return NSAPI_ERROR_NO_SOCKET;
143+
}
136144
_at.set_at_timeout(FAILURE_TIMEOUT);
137145
_at.cmd_start("AT^SISC=");
138146
_at.write_int(sock_id);
139147
_at.cmd_stop();
140148
_at.resp_start();
141149
_at.resp_stop();
142150
_at.restore_at_timeout();
151+
152+
socket->started = false;
153+
socket->created = false;
154+
socket->tx_ready = false;
155+
socket->rx_avail = false;
156+
143157
tr_debug("Closed socket %d (err %d)", sock_id, _at.get_last_error());
144158
return _at.get_last_error();
145159
}
146160

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+
147198
// To open socket:
148199
// 1. Select URC mode or polling mode with AT^SCFG
149200
// 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
224275

225276
tr_debug("Internet service %d created (err %d)", internet_service_id, _at.get_last_error());
226277

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);
248280
}
249-
250-
socket->created = true;
251-
tr_debug("Socket %d created (err %d)", socket->id, _at.get_last_error());
252-
253281
return _at.get_last_error();
254282
}
255283

@@ -264,9 +292,33 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul
264292
tr_warn("No IP route for %s", address.get_ip_address());
265293
return NSAPI_ERROR_NO_SOCKET;
266294
}
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+
}
268320
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);
270322
return NSAPI_ERROR_WOULD_BLOCK;
271323
}
272324

@@ -279,18 +331,19 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul
279331
_at.cmd_start("AT^SISW=");
280332
_at.write_int(socket->id);
281333
_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);
288343
}
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);
292344
_at.cmd_stop();
293345

346+
sisw_retry:
294347
_at.resp_start("^SISW:");
295348
if (!_at.info_resp()) {
296349
tr_error("Socket %d send failure", socket->id);
@@ -311,6 +364,11 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul
311364
int unack_len = _at.read_int();
312365
if (unack_len != 0) {
313366
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+
}
314372
}
315373

316374
_at.write_bytes((uint8_t *)data, accept_len);
@@ -375,44 +433,49 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
375433
socket->rx_avail = true;
376434
}
377435
}
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
394466
}
395-
} else {
396-
ip_stop = strchr(ip_address, ':');
397-
port_start = ip_stop;
398467
}
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;
408471
}
409472
}
410473

411474
nsapi_size_or_error_t recv_len = _at.read_bytes((uint8_t *)buffer, len);
412475

413476
_at.resp_stop();
414477

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());
416479

417480
return (_at.get_last_error() == NSAPI_ERROR_OK) ? recv_len : NSAPI_ERROR_DEVICE_ERROR;
418481
}

features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class GEMALTO_CINTERION_CellularStack : public AT_CellularStack {
5151
void urc_sisw();
5252
void urc_sisr();
5353
bool create_connection_profile();
54+
nsapi_error_t socket_open_defer(CellularSocket *socket, const SocketAddress *address = NULL);
5455

5556
const char *_apn;
5657
};

features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_Module.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,29 @@
2323

2424
using namespace mbed;
2525

26-
// supported features as per ELS61-E2_ATC_V01.000
26+
// unsupported features as per ELS61-E2_ATC_V01.000
2727
static const AT_CellularBase::SupportedFeature unsupported_features_els61[] = {
2828
AT_CellularBase::AT_CGSN_WITH_TYPE,
2929
AT_CellularBase::SUPPORTED_FEATURE_END_MARK
3030
};
3131

32+
// unsupported features as per EMS31-US_ATC_V4.9.5
33+
static const AT_CellularBase::SupportedFeature unsupported_features_bgs2[] = {
34+
AT_CellularBase::AT_CGSN_WITH_TYPE,
35+
AT_CellularBase::SUPPORTED_FEATURE_END_MARK
36+
};
37+
3238
GEMALTO_CINTERION_Module::Model GEMALTO_CINTERION_Module::_model;
3339

3440
nsapi_error_t GEMALTO_CINTERION_Module::detect_model(const char *model)
3541
{
3642
static const AT_CellularBase::SupportedFeature *unsupported_features;
37-
if (strcmp(model, "ELS61") == 0) {
43+
if (memcmp(model, "ELS61", sizeof("ELS61") - 1) == 0) {
3844
_model = ModelELS61;
3945
unsupported_features = unsupported_features_els61;
46+
} else if (memcmp(model, "BGS2", sizeof("BGS2") - 1) == 0) {
47+
_model = ModelBGS2;
48+
unsupported_features = unsupported_features_bgs2;
4049
} else {
4150
tr_error("Cinterion model unsupported %s", model);
4251
return NSAPI_ERROR_UNSUPPORTED;

features/cellular/framework/targets/GEMALTO/CINTERION/GEMALTO_CINTERION_Module.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ class GEMALTO_CINTERION_Module {
3131
*/
3232
enum Model {
3333
ModelUnknown = 0,
34-
ModelELS61
34+
ModelELS61,
35+
ModelBGS2,
3536
};
3637
static nsapi_error_t detect_model(const char *model);
3738
static Model get_model();

0 commit comments

Comments
 (0)