Skip to content

Commit d7e0716

Browse files
author
Kimmo Vaisanen
committed
Cellular: Gemalto TCP Socket support
1 parent a6651b8 commit d7e0716

File tree

2 files changed

+105
-34
lines changed

2 files changed

+105
-34
lines changed

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

Lines changed: 101 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,6 @@ void GEMALTO_CINTERION_CellularStack::urc_sis()
6565
int urc_code = _at.read_int();
6666
CellularSocket *sock = find_socket(sock_id);
6767
if (sock) {
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.
7068
if (urc_code == 5) { // The service is ready to use (ELS61 and EMS31).
7169
if (sock->_cb) {
7270
sock->started = true;
@@ -81,12 +79,17 @@ void GEMALTO_CINTERION_CellularStack::urc_sisw()
8179
{
8280
int sock_id = _at.read_int();
8381
int urc_code = _at.read_int();
82+
sisw_urc_handler(sock_id, urc_code);
83+
}
84+
85+
void GEMALTO_CINTERION_CellularStack::sisw_urc_handler(int sock_id, int urc_code)
86+
{
8487
CellularSocket *sock = find_socket(sock_id);
8588
if (sock) {
8689
if (urc_code == 1) { // ready
8790
if (sock->_cb) {
8891
sock->tx_ready = true;
89-
if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
92+
if (sock->proto == NSAPI_TCP || GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
9093
sock->started = true;
9194
}
9295
sock->_cb(sock->_data);
@@ -99,6 +102,11 @@ void GEMALTO_CINTERION_CellularStack::urc_sisr()
99102
{
100103
int sock_id = _at.read_int();
101104
int urc_code = _at.read_int();
105+
sisr_urc_handler(sock_id, urc_code);
106+
}
107+
108+
void GEMALTO_CINTERION_CellularStack::sisr_urc_handler(int sock_id, int urc_code)
109+
{
102110
CellularSocket *sock = find_socket(sock_id);
103111
if (sock) {
104112
if (urc_code == 1) { // data available
@@ -139,7 +147,7 @@ int GEMALTO_CINTERION_CellularStack::get_max_socket_count()
139147

140148
bool GEMALTO_CINTERION_CellularStack::is_protocol_supported(nsapi_protocol_t protocol)
141149
{
142-
return (protocol == NSAPI_UDP);
150+
return (protocol == NSAPI_UDP || protocol == NSAPI_TCP);
143151
}
144152

145153
nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_close_impl(int sock_id)
@@ -170,11 +178,20 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_close_impl(int sock_id)
170178
nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_open_defer(CellularSocket *socket, const SocketAddress *address)
171179
{
172180
// host address (IPv4) and local+remote port is needed only for BGS2 which does not support UDP server socket
173-
char sock_addr[sizeof("sockudp://") - 1 + NSAPI_IPv4_SIZE + sizeof(":12345;port=12345") - 1 + 1];
174-
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
175-
std::sprintf(sock_addr, "sockudp://%s:%u", address ? address->get_ip_address() : "", socket->localAddress.get_port());
181+
char sock_addr[sizeof("sockudp://") - 1 + NSAPI_IPv6_SIZE + sizeof("[]:12345;port=12345") - 1 + 1];
182+
183+
if (socket->proto == NSAPI_UDP) {
184+
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
185+
std::sprintf(sock_addr, "sockudp://%s:%u", address ? address->get_ip_address() : "", socket->localAddress.get_port());
186+
} else {
187+
std::sprintf(sock_addr, "sockudp://%s:%u;port=%u", address->get_ip_address(), address->get_port(), socket->localAddress.get_port());
188+
}
176189
} else {
177-
std::sprintf(sock_addr, "sockudp://%s:%u;port=%u", address->get_ip_address(), address->get_port(), socket->localAddress.get_port());
190+
if (address->get_ip_version() == NSAPI_IPv4) {
191+
std::sprintf(sock_addr, "socktcp://%s:%u", address->get_ip_address(), address->get_port());
192+
} else {
193+
std::sprintf(sock_addr, "socktcp://[%s]:%u", address->get_ip_address(), address->get_port());
194+
}
178195
}
179196

180197
_at.cmd_start("AT^SISS=");
@@ -281,9 +298,12 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::create_socket_impl(CellularSocket
281298

282299
tr_debug("Internet service %d (err %d)", internet_service_id, _at.get_last_error());
283300

284-
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
285-
return socket_open_defer(socket);
301+
if (socket->proto == NSAPI_UDP) {
302+
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
303+
return socket_open_defer(socket);
304+
}
286305
}
306+
287307
return _at.get_last_error();
288308
}
289309

@@ -292,13 +312,16 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul
292312
{
293313
tr_debug("Socket %d, sendto %s, len %d", socket->id, address.get_ip_address(), size);
294314

295-
int ip_version = address.get_ip_version();
296-
if ((ip_version == NSAPI_IPv4 && _stack_type != IPV4_STACK) ||
297-
(ip_version == NSAPI_IPv6 && _stack_type != IPV6_STACK)) {
298-
tr_warn("No IP route for %s", address.get_ip_address());
299-
return NSAPI_ERROR_NO_SOCKET;
315+
if (socket->proto == NSAPI_UDP) {
316+
const int ip_version = address.get_ip_version();
317+
if ((ip_version == NSAPI_IPv4 && _stack_type != IPV4_STACK) ||
318+
(ip_version == NSAPI_IPv6 && _stack_type != IPV6_STACK)) {
319+
tr_warn("No IP route for %s", address.get_ip_address());
320+
return NSAPI_ERROR_NO_SOCKET;
321+
}
300322
}
301-
if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
323+
324+
if (socket->proto == NSAPI_UDP && GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
302325
tr_debug("Send addr %s, prev addr %s", address.get_ip_address(), socket->remoteAddress.get_ip_address());
303326
if (address != socket->remoteAddress) {
304327
if (socket->started) {
@@ -340,16 +363,22 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul
340363
_at.cmd_start("AT^SISW=");
341364
_at.write_int(socket->id);
342365
_at.write_int(size);
366+
343367
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
344368
_at.write_int(0);
345-
char socket_address[NSAPI_IPv6_SIZE + sizeof("[]:12345") - 1 + 1];
346-
if (address.get_ip_version() == NSAPI_IPv4) {
347-
std::sprintf(socket_address, "%s:%u", address.get_ip_address(), address.get_port());
348-
} else {
349-
std::sprintf(socket_address, "[%s]:%u", address.get_ip_address(), address.get_port());
369+
370+
// UDP requires Udp_RemClient
371+
if (socket->proto == NSAPI_UDP) {
372+
char socket_address[NSAPI_IPv6_SIZE + sizeof("[]:12345") - 1 + 1];
373+
if (address.get_ip_version() == NSAPI_IPv4) {
374+
std::sprintf(socket_address, "%s:%u", address.get_ip_address(), address.get_port());
375+
} else {
376+
std::sprintf(socket_address, "[%s]:%u", address.get_ip_address(), address.get_port());
377+
}
378+
_at.write_string(socket_address);
350379
}
351-
_at.write_string(socket_address);
352380
}
381+
353382
_at.cmd_stop();
354383

355384
sisw_retry:
@@ -359,29 +388,30 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul
359388
_at.restore_at_timeout();
360389
return NSAPI_ERROR_DEVICE_ERROR;
361390
}
362-
_at.restore_at_timeout();
363391
int socket_id = _at.read_int();
364392
if (socket_id != socket->id) {
393+
// We might have read the SISW URC so let's try to handle it
394+
const int urc_code = _at.read_int();
395+
const int extra = _at.read_int();
396+
if (urc_code != -1 && extra == -1) {
397+
sisw_urc_handler(socket_id, urc_code);
398+
goto sisw_retry;
399+
}
400+
_at.restore_at_timeout();
365401
tr_error("Socket id %d != %d", socket_id, socket->id);
366402
return NSAPI_ERROR_DEVICE_ERROR;
367403
}
368404
int accept_len = _at.read_int();
369405
if (accept_len == -1) {
370406
tr_error("Socket %d send failed", socket->id);
407+
_at.restore_at_timeout();
371408
return NSAPI_ERROR_DEVICE_ERROR;
372409
}
373-
int unack_len = _at.read_int();
374-
if (unack_len != 0) {
375-
tr_warn("Socket %d unack_len %d", socket->id, unack_len);
376-
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
377-
// assume that an URC was received when unackData is not received
378-
_at.resp_stop();
379-
goto sisw_retry;
380-
}
381-
}
410+
_at.skip_param(); // unackData
382411

383412
_at.write_bytes((uint8_t *)data, accept_len);
384413
_at.resp_stop();
414+
_at.restore_at_timeout();
385415

386416
tr_debug("Socket %d sendto %s, %d bytes (err %d)", socket->id, address.get_ip_address(), accept_len, _at.get_last_error());
387417

@@ -417,16 +447,25 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
417447
_at.write_int(size);
418448
_at.cmd_stop();
419449

450+
sisr_retry:
420451
_at.resp_start("^SISR:");
421452
if (!_at.info_resp()) {
422453
tr_error("Socket %d not responding", socket->id);
423454
return NSAPI_ERROR_DEVICE_ERROR;
424455
}
456+
425457
int socket_id = _at.read_int();
426458
if (socket_id != socket->id) {
459+
const int urc_code = _at.read_int();
460+
const int extra = _at.read_int(); // should be -1 if URC
461+
if (urc_code != -1 && extra == -1) {
462+
sisr_urc_handler(socket_id, urc_code);
463+
goto sisr_retry;
464+
}
427465
tr_error("Socket recvfrom id %d != %d", socket_id, socket->id);
428466
return NSAPI_ERROR_DEVICE_ERROR;
429467
}
468+
430469
nsapi_size_or_error_t len = _at.read_int();
431470
if (len == 0) {
432471
tr_warn("Socket %d no data", socket->id);
@@ -444,7 +483,9 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
444483
socket->rx_avail = true;
445484
}
446485
}
447-
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
486+
487+
// UDP Udp_RemClient
488+
if (socket->proto == NSAPI_UDP && GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
448489
char ip_address[NSAPI_IPv6_SIZE + sizeof("[]:12345") - 1 + 1];
449490
int ip_len = _at.read_string(ip_address, sizeof(ip_address));
450491
if (ip_len <= 0) {
@@ -472,7 +513,7 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
472513
port_start++; // skip ':'
473514
int port = std::strtol(port_start, NULL, 10);
474515
address->set_port(port);
475-
tr_debug("IP address %s:%d", address->get_ip_address(), address->get_port());
516+
tr_debug("IP address %s, port %d", address->get_ip_address(), address->get_port());
476517
*ip_stop = tmp_ch; // restore original IP string
477518
}
478519
}
@@ -592,3 +633,29 @@ void GEMALTO_CINTERION_CellularStack::close_connection_profile(int connection_pr
592633

593634
_at.clear_error();
594635
}
636+
637+
nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_connect(nsapi_socket_t handle, const SocketAddress &address)
638+
{
639+
int err = NSAPI_ERROR_DEVICE_ERROR;
640+
641+
struct CellularSocket *socket = (struct CellularSocket *)handle;
642+
if (!socket) {
643+
return err;
644+
}
645+
646+
_at.lock();
647+
err = create_socket_impl(socket);
648+
if (err != NSAPI_ERROR_OK) {
649+
_at.unlock();
650+
return err;
651+
}
652+
err = socket_open_defer(socket, &address);
653+
_at.unlock();
654+
655+
if (err == NSAPI_ERROR_OK) {
656+
socket->remoteAddress = address;
657+
socket->connected = true;
658+
}
659+
660+
return err;
661+
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,18 @@ class GEMALTO_CINTERION_CellularStack : public AT_CellularStack {
4545
virtual nsapi_size_or_error_t socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
4646
void *buffer, nsapi_size_t size);
4747

48+
virtual nsapi_error_t socket_connect(nsapi_socket_t handle, const SocketAddress &address);
49+
4850
private:
4951
// find the socket handle based on socket identifier
5052
CellularSocket *find_socket(int sock_id);
5153

5254
// socket URC handlers as per Cinterion AT manuals
5355
void urc_sis();
5456
void urc_sisw();
57+
void sisw_urc_handler(int sock_id, int urc_code);
5558
void urc_sisr();
59+
void sisr_urc_handler(int sock_id, int urc_code);
5660

5761
// sockets need a connection profile, one profile is enough to support single stack sockets
5862
nsapi_error_t create_connection_profile(int connection_profile_id);

0 commit comments

Comments
 (0)