Merge pull request #8440 from kivaisan/gemalto_tcp_socket_support

Cellular: Gemalto TCP Socket support
pull/12790/head^2
Cruz Monrreal 2018-10-27 09:17:31 -05:00 committed by GitHub
commit 737b36f106
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 105 additions and 34 deletions

View File

@ -65,8 +65,6 @@ void GEMALTO_CINTERION_CellularStack::urc_sis()
int urc_code = _at.read_int();
CellularSocket *sock = find_socket(sock_id);
if (sock) {
// Currently only UDP is supported so there is need to handle only some error codes here,
// and others are detected on sendto/recvfrom responses.
if (urc_code == 5) { // The service is ready to use (ELS61 and EMS31).
if (sock->_cb) {
sock->started = true;
@ -81,12 +79,17 @@ void GEMALTO_CINTERION_CellularStack::urc_sisw()
{
int sock_id = _at.read_int();
int urc_code = _at.read_int();
sisw_urc_handler(sock_id, urc_code);
}
void GEMALTO_CINTERION_CellularStack::sisw_urc_handler(int sock_id, int urc_code)
{
CellularSocket *sock = find_socket(sock_id);
if (sock) {
if (urc_code == 1) { // ready
if (sock->_cb) {
sock->tx_ready = true;
if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
if (sock->proto == NSAPI_TCP || GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
sock->started = true;
}
sock->_cb(sock->_data);
@ -99,6 +102,11 @@ void GEMALTO_CINTERION_CellularStack::urc_sisr()
{
int sock_id = _at.read_int();
int urc_code = _at.read_int();
sisr_urc_handler(sock_id, urc_code);
}
void GEMALTO_CINTERION_CellularStack::sisr_urc_handler(int sock_id, int urc_code)
{
CellularSocket *sock = find_socket(sock_id);
if (sock) {
if (urc_code == 1) { // data available
@ -139,7 +147,7 @@ int GEMALTO_CINTERION_CellularStack::get_max_socket_count()
bool GEMALTO_CINTERION_CellularStack::is_protocol_supported(nsapi_protocol_t protocol)
{
return (protocol == NSAPI_UDP);
return (protocol == NSAPI_UDP || protocol == NSAPI_TCP);
}
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)
nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_open_defer(CellularSocket *socket, const SocketAddress *address)
{
// host address (IPv4) and local+remote port is needed only for BGS2 which does not support UDP server socket
char sock_addr[sizeof("sockudp://") - 1 + NSAPI_IPv4_SIZE + sizeof(":12345;port=12345") - 1 + 1];
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
std::sprintf(sock_addr, "sockudp://%s:%u", address ? address->get_ip_address() : "", socket->localAddress.get_port());
char sock_addr[sizeof("sockudp://") - 1 + NSAPI_IPv6_SIZE + sizeof("[]:12345;port=12345") - 1 + 1];
if (socket->proto == NSAPI_UDP) {
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
std::sprintf(sock_addr, "sockudp://%s:%u", address ? address->get_ip_address() : "", socket->localAddress.get_port());
} else {
std::sprintf(sock_addr, "sockudp://%s:%u;port=%u", address->get_ip_address(), address->get_port(), socket->localAddress.get_port());
}
} else {
std::sprintf(sock_addr, "sockudp://%s:%u;port=%u", address->get_ip_address(), address->get_port(), socket->localAddress.get_port());
if (address->get_ip_version() == NSAPI_IPv4) {
std::sprintf(sock_addr, "socktcp://%s:%u", address->get_ip_address(), address->get_port());
} else {
std::sprintf(sock_addr, "socktcp://[%s]:%u", address->get_ip_address(), address->get_port());
}
}
_at.cmd_start("AT^SISS=");
@ -272,9 +289,12 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::create_socket_impl(CellularSocket
tr_debug("Internet service %d (err %d)", internet_service_id, _at.get_last_error());
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
return socket_open_defer(socket);
if (socket->proto == NSAPI_UDP) {
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
return socket_open_defer(socket);
}
}
return _at.get_last_error();
}
@ -283,13 +303,16 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul
{
tr_debug("Socket %d, sendto %s, len %d", socket->id, address.get_ip_address(), size);
int ip_version = address.get_ip_version();
if ((ip_version == NSAPI_IPv4 && _stack_type != IPV4_STACK) ||
(ip_version == NSAPI_IPv6 && _stack_type != IPV6_STACK)) {
tr_warn("No IP route for %s", address.get_ip_address());
return NSAPI_ERROR_NO_SOCKET;
if (socket->proto == NSAPI_UDP) {
const int ip_version = address.get_ip_version();
if ((ip_version == NSAPI_IPv4 && _stack_type != IPV4_STACK) ||
(ip_version == NSAPI_IPv6 && _stack_type != IPV6_STACK)) {
tr_warn("No IP route for %s", address.get_ip_address());
return NSAPI_ERROR_NO_SOCKET;
}
}
if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
if (socket->proto == NSAPI_UDP && GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
tr_debug("Send addr %s, prev addr %s", address.get_ip_address(), socket->remoteAddress.get_ip_address());
if (address != socket->remoteAddress) {
if (socket->started) {
@ -331,16 +354,22 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul
_at.cmd_start("AT^SISW=");
_at.write_int(socket->id);
_at.write_int(size);
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
_at.write_int(0);
char socket_address[NSAPI_IPv6_SIZE + sizeof("[]:12345") - 1 + 1];
if (address.get_ip_version() == NSAPI_IPv4) {
std::sprintf(socket_address, "%s:%u", address.get_ip_address(), address.get_port());
} else {
std::sprintf(socket_address, "[%s]:%u", address.get_ip_address(), address.get_port());
// UDP requires Udp_RemClient
if (socket->proto == NSAPI_UDP) {
char socket_address[NSAPI_IPv6_SIZE + sizeof("[]:12345") - 1 + 1];
if (address.get_ip_version() == NSAPI_IPv4) {
std::sprintf(socket_address, "%s:%u", address.get_ip_address(), address.get_port());
} else {
std::sprintf(socket_address, "[%s]:%u", address.get_ip_address(), address.get_port());
}
_at.write_string(socket_address);
}
_at.write_string(socket_address);
}
_at.cmd_stop();
sisw_retry:
@ -350,29 +379,30 @@ sisw_retry:
_at.restore_at_timeout();
return NSAPI_ERROR_DEVICE_ERROR;
}
_at.restore_at_timeout();
int socket_id = _at.read_int();
if (socket_id != socket->id) {
// We might have read the SISW URC so let's try to handle it
const int urc_code = _at.read_int();
const int extra = _at.read_int();
if (urc_code != -1 && extra == -1) {
sisw_urc_handler(socket_id, urc_code);
goto sisw_retry;
}
_at.restore_at_timeout();
tr_error("Socket id %d != %d", socket_id, socket->id);
return NSAPI_ERROR_DEVICE_ERROR;
}
int accept_len = _at.read_int();
if (accept_len == -1) {
tr_error("Socket %d send failed", socket->id);
_at.restore_at_timeout();
return NSAPI_ERROR_DEVICE_ERROR;
}
int unack_len = _at.read_int();
if (unack_len != 0) {
tr_warn("Socket %d unack_len %d", socket->id, unack_len);
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
// assume that an URC was received when unackData is not received
_at.resp_stop();
goto sisw_retry;
}
}
_at.skip_param(); // unackData
_at.write_bytes((uint8_t *)data, accept_len);
_at.resp_stop();
_at.restore_at_timeout();
tr_debug("Socket %d sendto %s, %d bytes (err %d)", socket->id, address.get_ip_address(), accept_len, _at.get_last_error());
@ -408,16 +438,25 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
_at.write_int(size);
_at.cmd_stop();
sisr_retry:
_at.resp_start("^SISR:");
if (!_at.info_resp()) {
tr_error("Socket %d not responding", socket->id);
return NSAPI_ERROR_DEVICE_ERROR;
}
int socket_id = _at.read_int();
if (socket_id != socket->id) {
const int urc_code = _at.read_int();
const int extra = _at.read_int(); // should be -1 if URC
if (urc_code != -1 && extra == -1) {
sisr_urc_handler(socket_id, urc_code);
goto sisr_retry;
}
tr_error("Socket recvfrom id %d != %d", socket_id, socket->id);
return NSAPI_ERROR_DEVICE_ERROR;
}
nsapi_size_or_error_t len = _at.read_int();
if (len == 0) {
tr_warn("Socket %d no data", socket->id);
@ -435,7 +474,9 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
socket->rx_avail = true;
}
}
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
// UDP Udp_RemClient
if (socket->proto == NSAPI_UDP && GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
char ip_address[NSAPI_IPv6_SIZE + sizeof("[]:12345") - 1 + 1];
int ip_len = _at.read_string(ip_address, sizeof(ip_address));
if (ip_len <= 0) {
@ -463,7 +504,7 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
port_start++; // skip ':'
int port = std::strtol(port_start, NULL, 10);
address->set_port(port);
tr_debug("IP address %s:%d", address->get_ip_address(), address->get_port());
tr_debug("IP address %s, port %d", address->get_ip_address(), address->get_port());
*ip_stop = tmp_ch; // restore original IP string
}
}
@ -571,3 +612,29 @@ void GEMALTO_CINTERION_CellularStack::close_connection_profile(int connection_pr
_at.clear_error();
}
nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_connect(nsapi_socket_t handle, const SocketAddress &address)
{
int err = NSAPI_ERROR_DEVICE_ERROR;
struct CellularSocket *socket = (struct CellularSocket *)handle;
if (!socket) {
return err;
}
_at.lock();
err = create_socket_impl(socket);
if (err != NSAPI_ERROR_OK) {
_at.unlock();
return err;
}
err = socket_open_defer(socket, &address);
_at.unlock();
if (err == NSAPI_ERROR_OK) {
socket->remoteAddress = address;
socket->connected = true;
}
return err;
}

View File

@ -45,6 +45,8 @@ protected:
virtual nsapi_size_or_error_t socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
void *buffer, nsapi_size_t size);
virtual nsapi_error_t socket_connect(nsapi_socket_t handle, const SocketAddress &address);
private:
// find the socket handle based on socket identifier
CellularSocket *find_socket(int sock_id);
@ -52,7 +54,9 @@ private:
// socket URC handlers as per Cinterion AT manuals
void urc_sis();
void urc_sisw();
void sisw_urc_handler(int sock_id, int urc_code);
void urc_sisr();
void sisr_urc_handler(int sock_id, int urc_code);
// sockets need a connection profile, one profile is enough to support single stack sockets
nsapi_error_t create_connection_profile(int connection_profile_id);