mirror of https://github.com/ARMmbed/mbed-os.git
Cellular: Added support for the Gemalto/BGS2 cellular module
parent
761e01f55c
commit
a14ac31f68
|
@ -276,10 +276,10 @@ nsapi_size_or_error_t AT_CellularStack::socket_sendto(nsapi_socket_t handle, con
|
|||
|
||||
ret_val = socket_sendto_impl(socket, addr, data, size);
|
||||
|
||||
if (ret_val <= 0) {
|
||||
tr_error("Error sending to: %s error code: %d", addr.get_ip_address(), ret_val);
|
||||
} else {
|
||||
if (ret_val > 0) {
|
||||
tr_info("Success sending %d Bytes to: %s", ret_val, addr.get_ip_address());
|
||||
} else if (ret_val != NSAPI_ERROR_WOULD_BLOCK) {
|
||||
tr_error("Error sending to: %s error code: %d", addr.get_ip_address(), ret_val);
|
||||
}
|
||||
|
||||
_at.unlock();
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "GEMALTO_CINTERION_CellularNetwork.h"
|
||||
#include "GEMALTO_CINTERION_CellularStack.h"
|
||||
#include "GEMALTO_CINTERION_Module.h"
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
|
@ -28,6 +29,7 @@ GEMALTO_CINTERION_CellularNetwork::~GEMALTO_CINTERION_CellularNetwork()
|
|||
{
|
||||
}
|
||||
|
||||
#if !NSAPI_PPP_AVAILABLE
|
||||
NetworkStack *GEMALTO_CINTERION_CellularNetwork::get_stack()
|
||||
{
|
||||
if (!_stack) {
|
||||
|
@ -35,14 +37,21 @@ NetworkStack *GEMALTO_CINTERION_CellularNetwork::get_stack()
|
|||
}
|
||||
return _stack;
|
||||
}
|
||||
#endif // NSAPI_PPP_AVAILABLE
|
||||
|
||||
bool GEMALTO_CINTERION_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
|
||||
return (requested_stack == IPV4_STACK);
|
||||
}
|
||||
return (requested_stack == IPV4_STACK || requested_stack == IPV6_STACK);
|
||||
}
|
||||
|
||||
bool GEMALTO_CINTERION_CellularNetwork::has_registration(RegistrationType reg_type)
|
||||
{
|
||||
if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
|
||||
return (reg_type == C_REG || reg_type == C_GREG);
|
||||
}
|
||||
return (reg_type == C_REG || reg_type == C_GREG || reg_type == C_EREG);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,9 @@ public:
|
|||
virtual ~GEMALTO_CINTERION_CellularNetwork();
|
||||
|
||||
protected:
|
||||
#if !NSAPI_PPP_AVAILABLE
|
||||
virtual NetworkStack *get_stack();
|
||||
#endif // NSAPI_PPP_AVAILABLE
|
||||
|
||||
virtual bool has_registration(RegistrationType reg_type);
|
||||
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include "GEMALTO_CINTERION_CellularStack.h"
|
||||
#include "GEMALTO_CINTERION_Module.h"
|
||||
#include "CellularLog.h"
|
||||
|
||||
// defines as per ELS61-E2_ATC_V01.000
|
||||
// defines as per ELS61-E2_ATC_V01.000 and BGS2-W_ATC_V00.100
|
||||
#define SOCKET_MAX 10
|
||||
#define UDP_PACKET_SIZE 1460
|
||||
#define FAILURE_TIMEOUT (30*1000) // failure timeout in milliseconds on modem side
|
||||
|
@ -84,6 +85,9 @@ void GEMALTO_CINTERION_CellularStack::urc_sisw()
|
|||
if (urc_code == 1) { // ready
|
||||
if (sock->_cb) {
|
||||
sock->tx_ready = true;
|
||||
if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
|
||||
sock->started = true;
|
||||
}
|
||||
sock->_cb(sock->_data);
|
||||
}
|
||||
} else if (urc_code == 2) { // socket closed
|
||||
|
@ -133,6 +137,10 @@ bool GEMALTO_CINTERION_CellularStack::is_protocol_supported(nsapi_protocol_t pro
|
|||
|
||||
nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_close_impl(int sock_id)
|
||||
{
|
||||
CellularSocket *socket = find_socket(sock_id);
|
||||
if (!socket) {
|
||||
return NSAPI_ERROR_NO_SOCKET;
|
||||
}
|
||||
_at.set_at_timeout(FAILURE_TIMEOUT);
|
||||
_at.cmd_start("AT^SISC=");
|
||||
_at.write_int(sock_id);
|
||||
|
@ -140,10 +148,53 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_close_impl(int sock_id)
|
|||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
_at.restore_at_timeout();
|
||||
|
||||
socket->started = false;
|
||||
socket->created = false;
|
||||
socket->tx_ready = false;
|
||||
socket->rx_avail = false;
|
||||
|
||||
tr_debug("Closed socket %d (err %d)", sock_id, _at.get_last_error());
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
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());
|
||||
} else {
|
||||
std::sprintf(sock_addr, "sockudp://%s:%u;port=%u", address->get_ip_address(), address->get_port(), socket->localAddress.get_port());
|
||||
}
|
||||
|
||||
_at.cmd_start("AT^SISS=");
|
||||
_at.write_int(socket->id);
|
||||
_at.write_string("address", false);
|
||||
_at.write_string(sock_addr);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
|
||||
_at.cmd_start("AT^SISO=");
|
||||
_at.write_int(socket->id);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
if (_at.get_last_error()) {
|
||||
tr_error("Socket %d open failed!", socket->id);
|
||||
_at.clear_error();
|
||||
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
|
||||
return NSAPI_ERROR_NO_SOCKET;
|
||||
}
|
||||
|
||||
socket->created = true;
|
||||
tr_debug("Socket %d created (err %d)", socket->id, _at.get_last_error());
|
||||
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
// To open socket:
|
||||
// 1. Select URC mode or polling mode with AT^SCFG
|
||||
// 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
|
|||
|
||||
tr_debug("Internet service %d created (err %d)", internet_service_id, _at.get_last_error());
|
||||
|
||||
char sock_addr[sizeof("sockudp://") + sizeof(":") + sizeof("65535") + 1];
|
||||
std::sprintf(sock_addr, "sockudp://:%u", socket->localAddress.get_port());
|
||||
_at.cmd_start("AT^SISS=");
|
||||
_at.write_int(socket->id);
|
||||
_at.write_string("address", false);
|
||||
_at.write_string(sock_addr);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
|
||||
_at.cmd_start("AT^SISO=");
|
||||
_at.write_int(socket->id);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
if (_at.get_last_error()) {
|
||||
tr_error("Socket %d open failed!", socket->id);
|
||||
_at.clear_error();
|
||||
socket_close_impl(socket->id);
|
||||
return NSAPI_ERROR_NO_SOCKET;
|
||||
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
|
||||
return socket_open_defer(socket);
|
||||
}
|
||||
|
||||
socket->created = true;
|
||||
tr_debug("Socket %d created (err %d)", socket->id, _at.get_last_error());
|
||||
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
|
@ -264,9 +292,33 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul
|
|||
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) {
|
||||
tr_error("Send addr %s, prev addr %s", address.get_ip_address(), socket->remoteAddress.get_ip_address());
|
||||
if (address != socket->remoteAddress) {
|
||||
if (socket->started) {
|
||||
socket_close_impl(socket->id);
|
||||
_at.clear_error();
|
||||
}
|
||||
// socket->started = false;
|
||||
if (socket_open_defer(socket, &address) != NSAPI_ERROR_OK) {
|
||||
tr_error("Failed to open socket %d", socket->id);
|
||||
return NSAPI_ERROR_NO_SOCKET;
|
||||
}
|
||||
socket->remoteAddress = address;
|
||||
// return NSAPI_ERROR_WOULD_BLOCK;
|
||||
_at.resp_start("^SISW:");
|
||||
int sock_id = _at.read_int();
|
||||
int urc_code = _at.read_int();
|
||||
tr_debug("TX ready: socket=%d, urc=%d (err=%d)", sock_id, urc_code, _at.get_last_error());
|
||||
(void)sock_id;
|
||||
(void)urc_code;
|
||||
socket->created = true;
|
||||
socket->started = true;
|
||||
socket->tx_ready = true;
|
||||
}
|
||||
}
|
||||
if (!socket->started || !socket->tx_ready) {
|
||||
tr_debug("Socket %d would block", socket->id);
|
||||
tr_debug("Socket %d would block (started %d, tx %d)", socket->id, socket->started, socket->tx_ready);
|
||||
return NSAPI_ERROR_WOULD_BLOCK;
|
||||
}
|
||||
|
||||
|
@ -279,18 +331,19 @@ 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);
|
||||
_at.write_int(0);
|
||||
char ip_address[sizeof("[1111:2222:3333:4444:5555:6666:7777:8888]:12345") + 1];
|
||||
if (address.get_ip_version() == NSAPI_IPv4) {
|
||||
std::sprintf(ip_address, "%s", address.get_ip_address());
|
||||
} else {
|
||||
std::sprintf(ip_address, "[%s]", address.get_ip_address());
|
||||
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());
|
||||
}
|
||||
_at.write_string(socket_address);
|
||||
}
|
||||
char socket_address[sizeof(ip_address) + sizeof(":") + sizeof("65535") + 1];
|
||||
std::sprintf(socket_address, "%s:%u", ip_address, address.get_port());
|
||||
_at.write_string(socket_address);
|
||||
_at.cmd_stop();
|
||||
|
||||
sisw_retry:
|
||||
_at.resp_start("^SISW:");
|
||||
if (!_at.info_resp()) {
|
||||
tr_error("Socket %d send failure", socket->id);
|
||||
|
@ -311,6 +364,11 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul
|
|||
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.write_bytes((uint8_t *)data, accept_len);
|
||||
|
@ -375,36 +433,41 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
|
|||
socket->rx_avail = true;
|
||||
}
|
||||
}
|
||||
char ip_address[sizeof("[1111:2222:3333:4444:5555:6666:7777:8888]:12345") + 1];
|
||||
int ip_len = _at.read_string(ip_address, sizeof(ip_address));
|
||||
tr_error("ip %s", ip_address);
|
||||
if (ip_len <= 0) {
|
||||
tr_error("Socket %d recvfrom addr!", socket->id);
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
if (address) {
|
||||
char *ip_start = ip_address;
|
||||
char *ip_stop;
|
||||
char *port_start;
|
||||
if (_stack_type == IPV6_STACK) {
|
||||
ip_start++; // skip '['
|
||||
ip_stop = strchr(ip_address, ']');
|
||||
if (ip_stop) {
|
||||
port_start = strchr(ip_stop, ':');
|
||||
}
|
||||
} else {
|
||||
ip_stop = strchr(ip_address, ':');
|
||||
port_start = ip_stop;
|
||||
if (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) {
|
||||
tr_error("Socket %d recvfrom addr!", socket->id);
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
if (ip_stop && port_start) {
|
||||
char tmp_ch = *ip_stop;
|
||||
*ip_stop = '\0'; // split IP and port
|
||||
address->set_ip_address(ip_start);
|
||||
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());
|
||||
*ip_stop = tmp_ch; // restore original IP string
|
||||
if (address) {
|
||||
char *ip_start = ip_address;
|
||||
char *ip_stop;
|
||||
char *port_start;
|
||||
if (_stack_type == IPV6_STACK) {
|
||||
ip_start++; // skip '['
|
||||
ip_stop = strchr(ip_address, ']');
|
||||
if (ip_stop) {
|
||||
port_start = strchr(ip_stop, ':');
|
||||
}
|
||||
} else {
|
||||
ip_stop = strchr(ip_address, ':');
|
||||
port_start = ip_stop;
|
||||
}
|
||||
if (ip_stop && port_start) {
|
||||
char tmp_ch = *ip_stop;
|
||||
*ip_stop = '\0'; // split IP and port
|
||||
address->set_ip_address(ip_start);
|
||||
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());
|
||||
*ip_stop = tmp_ch; // restore original IP string
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (address) {
|
||||
*address = socket->remoteAddress;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,7 +475,7 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
|
|||
|
||||
_at.resp_stop();
|
||||
|
||||
tr_debug("Socket %d, recvfrom %s, %d bytes (err %d)", socket->id, ip_address, len, _at.get_last_error());
|
||||
tr_debug("Socket %d, recvfrom %s, %d bytes (err %d)", socket->id, address, len, _at.get_last_error());
|
||||
|
||||
return (_at.get_last_error() == NSAPI_ERROR_OK) ? recv_len : NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ private:
|
|||
void urc_sisw();
|
||||
void urc_sisr();
|
||||
bool create_connection_profile();
|
||||
nsapi_error_t socket_open_defer(CellularSocket *socket, const SocketAddress *address = NULL);
|
||||
|
||||
const char *_apn;
|
||||
};
|
||||
|
|
|
@ -23,20 +23,29 @@
|
|||
|
||||
using namespace mbed;
|
||||
|
||||
// supported features as per ELS61-E2_ATC_V01.000
|
||||
// unsupported features as per ELS61-E2_ATC_V01.000
|
||||
static const AT_CellularBase::SupportedFeature unsupported_features_els61[] = {
|
||||
AT_CellularBase::AT_CGSN_WITH_TYPE,
|
||||
AT_CellularBase::SUPPORTED_FEATURE_END_MARK
|
||||
};
|
||||
|
||||
// unsupported features as per EMS31-US_ATC_V4.9.5
|
||||
static const AT_CellularBase::SupportedFeature unsupported_features_bgs2[] = {
|
||||
AT_CellularBase::AT_CGSN_WITH_TYPE,
|
||||
AT_CellularBase::SUPPORTED_FEATURE_END_MARK
|
||||
};
|
||||
|
||||
GEMALTO_CINTERION_Module::Model GEMALTO_CINTERION_Module::_model;
|
||||
|
||||
nsapi_error_t GEMALTO_CINTERION_Module::detect_model(const char *model)
|
||||
{
|
||||
static const AT_CellularBase::SupportedFeature *unsupported_features;
|
||||
if (strcmp(model, "ELS61") == 0) {
|
||||
if (memcmp(model, "ELS61", sizeof("ELS61") - 1) == 0) {
|
||||
_model = ModelELS61;
|
||||
unsupported_features = unsupported_features_els61;
|
||||
} else if (memcmp(model, "BGS2", sizeof("BGS2") - 1) == 0) {
|
||||
_model = ModelBGS2;
|
||||
unsupported_features = unsupported_features_bgs2;
|
||||
} else {
|
||||
tr_error("Cinterion model unsupported %s", model);
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
|
|
|
@ -31,7 +31,8 @@ public:
|
|||
*/
|
||||
enum Model {
|
||||
ModelUnknown = 0,
|
||||
ModelELS61
|
||||
ModelELS61,
|
||||
ModelBGS2,
|
||||
};
|
||||
static nsapi_error_t detect_model(const char *model);
|
||||
static Model get_model();
|
||||
|
|
Loading…
Reference in New Issue