Skip to content

Commit 737b36f

Browse files
author
Cruz Monrreal
authored
Merge pull request #8440 from kivaisan/gemalto_tcp_socket_support
Cellular: Gemalto TCP Socket support
2 parents 4798a91 + d7e0716 commit 737b36f

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)
@@ -168,11 +176,20 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_close_impl(int sock_id)
168176
nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_open_defer(CellularSocket *socket, const SocketAddress *address)
169177
{
170178
// host address (IPv4) and local+remote port is needed only for BGS2 which does not support UDP server socket
171-
char sock_addr[sizeof("sockudp://") - 1 + NSAPI_IPv4_SIZE + sizeof(":12345;port=12345") - 1 + 1];
172-
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
173-
std::sprintf(sock_addr, "sockudp://%s:%u", address ? address->get_ip_address() : "", socket->localAddress.get_port());
179+
char sock_addr[sizeof("sockudp://") - 1 + NSAPI_IPv6_SIZE + sizeof("[]:12345;port=12345") - 1 + 1];
180+
181+
if (socket->proto == NSAPI_UDP) {
182+
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
183+
std::sprintf(sock_addr, "sockudp://%s:%u", address ? address->get_ip_address() : "", socket->localAddress.get_port());
184+
} else {
185+
std::sprintf(sock_addr, "sockudp://%s:%u;port=%u", address->get_ip_address(), address->get_port(), socket->localAddress.get_port());
186+
}
174187
} else {
175-
std::sprintf(sock_addr, "sockudp://%s:%u;port=%u", address->get_ip_address(), address->get_port(), socket->localAddress.get_port());
188+
if (address->get_ip_version() == NSAPI_IPv4) {
189+
std::sprintf(sock_addr, "socktcp://%s:%u", address->get_ip_address(), address->get_port());
190+
} else {
191+
std::sprintf(sock_addr, "socktcp://[%s]:%u", address->get_ip_address(), address->get_port());
192+
}
176193
}
177194

178195
_at.cmd_start("AT^SISS=");
@@ -272,9 +289,12 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::create_socket_impl(CellularSocket
272289

273290
tr_debug("Internet service %d (err %d)", internet_service_id, _at.get_last_error());
274291

275-
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
276-
return socket_open_defer(socket);
292+
if (socket->proto == NSAPI_UDP) {
293+
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
294+
return socket_open_defer(socket);
295+
}
277296
}
297+
278298
return _at.get_last_error();
279299
}
280300

@@ -283,13 +303,16 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul
283303
{
284304
tr_debug("Socket %d, sendto %s, len %d", socket->id, address.get_ip_address(), size);
285305

286-
int ip_version = address.get_ip_version();
287-
if ((ip_version == NSAPI_IPv4 && _stack_type != IPV4_STACK) ||
288-
(ip_version == NSAPI_IPv6 && _stack_type != IPV6_STACK)) {
289-
tr_warn("No IP route for %s", address.get_ip_address());
290-
return NSAPI_ERROR_NO_SOCKET;
306+
if (socket->proto == NSAPI_UDP) {
307+
const int ip_version = address.get_ip_version();
308+
if ((ip_version == NSAPI_IPv4 && _stack_type != IPV4_STACK) ||
309+
(ip_version == NSAPI_IPv6 && _stack_type != IPV6_STACK)) {
310+
tr_warn("No IP route for %s", address.get_ip_address());
311+
return NSAPI_ERROR_NO_SOCKET;
312+
}
291313
}
292-
if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
314+
315+
if (socket->proto == NSAPI_UDP && GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
293316
tr_debug("Send addr %s, prev addr %s", address.get_ip_address(), socket->remoteAddress.get_ip_address());
294317
if (address != socket->remoteAddress) {
295318
if (socket->started) {
@@ -331,16 +354,22 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul
331354
_at.cmd_start("AT^SISW=");
332355
_at.write_int(socket->id);
333356
_at.write_int(size);
357+
334358
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
335359
_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());
360+
361+
// UDP requires Udp_RemClient
362+
if (socket->proto == NSAPI_UDP) {
363+
char socket_address[NSAPI_IPv6_SIZE + sizeof("[]:12345") - 1 + 1];
364+
if (address.get_ip_version() == NSAPI_IPv4) {
365+
std::sprintf(socket_address, "%s:%u", address.get_ip_address(), address.get_port());
366+
} else {
367+
std::sprintf(socket_address, "[%s]:%u", address.get_ip_address(), address.get_port());
368+
}
369+
_at.write_string(socket_address);
341370
}
342-
_at.write_string(socket_address);
343371
}
372+
344373
_at.cmd_stop();
345374

346375
sisw_retry:
@@ -350,29 +379,30 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul
350379
_at.restore_at_timeout();
351380
return NSAPI_ERROR_DEVICE_ERROR;
352381
}
353-
_at.restore_at_timeout();
354382
int socket_id = _at.read_int();
355383
if (socket_id != socket->id) {
384+
// We might have read the SISW URC so let's try to handle it
385+
const int urc_code = _at.read_int();
386+
const int extra = _at.read_int();
387+
if (urc_code != -1 && extra == -1) {
388+
sisw_urc_handler(socket_id, urc_code);
389+
goto sisw_retry;
390+
}
391+
_at.restore_at_timeout();
356392
tr_error("Socket id %d != %d", socket_id, socket->id);
357393
return NSAPI_ERROR_DEVICE_ERROR;
358394
}
359395
int accept_len = _at.read_int();
360396
if (accept_len == -1) {
361397
tr_error("Socket %d send failed", socket->id);
398+
_at.restore_at_timeout();
362399
return NSAPI_ERROR_DEVICE_ERROR;
363400
}
364-
int unack_len = _at.read_int();
365-
if (unack_len != 0) {
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-
}
372-
}
401+
_at.skip_param(); // unackData
373402

374403
_at.write_bytes((uint8_t *)data, accept_len);
375404
_at.resp_stop();
405+
_at.restore_at_timeout();
376406

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

@@ -408,16 +438,25 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
408438
_at.write_int(size);
409439
_at.cmd_stop();
410440

441+
sisr_retry:
411442
_at.resp_start("^SISR:");
412443
if (!_at.info_resp()) {
413444
tr_error("Socket %d not responding", socket->id);
414445
return NSAPI_ERROR_DEVICE_ERROR;
415446
}
447+
416448
int socket_id = _at.read_int();
417449
if (socket_id != socket->id) {
450+
const int urc_code = _at.read_int();
451+
const int extra = _at.read_int(); // should be -1 if URC
452+
if (urc_code != -1 && extra == -1) {
453+
sisr_urc_handler(socket_id, urc_code);
454+
goto sisr_retry;
455+
}
418456
tr_error("Socket recvfrom id %d != %d", socket_id, socket->id);
419457
return NSAPI_ERROR_DEVICE_ERROR;
420458
}
459+
421460
nsapi_size_or_error_t len = _at.read_int();
422461
if (len == 0) {
423462
tr_warn("Socket %d no data", socket->id);
@@ -435,7 +474,9 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
435474
socket->rx_avail = true;
436475
}
437476
}
438-
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
477+
478+
// UDP Udp_RemClient
479+
if (socket->proto == NSAPI_UDP && GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
439480
char ip_address[NSAPI_IPv6_SIZE + sizeof("[]:12345") - 1 + 1];
440481
int ip_len = _at.read_string(ip_address, sizeof(ip_address));
441482
if (ip_len <= 0) {
@@ -463,7 +504,7 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
463504
port_start++; // skip ':'
464505
int port = std::strtol(port_start, NULL, 10);
465506
address->set_port(port);
466-
tr_debug("IP address %s:%d", address->get_ip_address(), address->get_port());
507+
tr_debug("IP address %s, port %d", address->get_ip_address(), address->get_port());
467508
*ip_stop = tmp_ch; // restore original IP string
468509
}
469510
}
@@ -571,3 +612,29 @@ void GEMALTO_CINTERION_CellularStack::close_connection_profile(int connection_pr
571612

572613
_at.clear_error();
573614
}
615+
616+
nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_connect(nsapi_socket_t handle, const SocketAddress &address)
617+
{
618+
int err = NSAPI_ERROR_DEVICE_ERROR;
619+
620+
struct CellularSocket *socket = (struct CellularSocket *)handle;
621+
if (!socket) {
622+
return err;
623+
}
624+
625+
_at.lock();
626+
err = create_socket_impl(socket);
627+
if (err != NSAPI_ERROR_OK) {
628+
_at.unlock();
629+
return err;
630+
}
631+
err = socket_open_defer(socket, &address);
632+
_at.unlock();
633+
634+
if (err == NSAPI_ERROR_OK) {
635+
socket->remoteAddress = address;
636+
socket->connected = true;
637+
}
638+
639+
return err;
640+
}

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)