Skip to content

Commit a9f4323

Browse files
author
Cruz Monrreal
authored
Merge pull request #8295 from AriParkkila/cell-cinterion
Cellular: Update Cinterion AT drivers
2 parents ec03df4 + 3784dd0 commit a9f4323

File tree

6 files changed

+109
-60
lines changed

6 files changed

+109
-60
lines changed

features/cellular/framework/AT/AT_CellularNetwork.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,7 @@ bool AT_CellularNetwork::set_new_context(int cid)
581581
// Fall back to ipv4
582582
if (!success && tmp_stack == IPV4V6_STACK) {
583583
tmp_stack = IPV4_STACK;
584+
_at.clear_error();
584585
_at.cmd_start("AT+FCLASS=0;+CGDCONT=");
585586
_at.write_int(cid);
586587
_at.write_string("IP");

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
using namespace mbed;
2525
using namespace events;
2626

27+
const uint16_t RESPONSE_TO_SEND_DELAY = 100; // response-to-send delay in milliseconds at bit-rate over 9600
28+
2729
GEMALTO_CINTERION::GEMALTO_CINTERION(EventQueue &queue) : AT_CellularDevice(queue)
2830
{
2931
}
@@ -52,3 +54,8 @@ nsapi_error_t GEMALTO_CINTERION::init_module(FileHandle *fh)
5254
}
5355
return GEMALTO_CINTERION_Module::detect_model(model);
5456
}
57+
58+
uint16_t GEMALTO_CINTERION::get_send_delay()
59+
{
60+
return RESPONSE_TO_SEND_DELAY;
61+
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ class GEMALTO_CINTERION : public AT_CellularDevice {
3030

3131
protected: // AT_CellularDevice
3232
virtual AT_CellularNetwork *open_network_impl(ATHandler &at);
33-
public:
33+
34+
public: // CellularDevice
3435
virtual nsapi_error_t init_module(FileHandle *fh);
36+
virtual uint16_t get_send_delay();
3537
};
3638

3739
} // namespace mbed

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,10 @@ NetworkStack *GEMALTO_CINTERION_CellularNetwork::get_stack()
4141

4242
bool GEMALTO_CINTERION_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
4343
{
44-
#if NSAPI_PPP_AVAILABLE
45-
return (requested_stack == IPV4_STACK || requested_stack == IPV6_STACK);
46-
#else
4744
if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
4845
return (requested_stack == IPV4_STACK);
4946
}
5047
return (requested_stack == IPV4_STACK || requested_stack == IPV6_STACK);
51-
#endif
5248
}
5349

5450
AT_CellularNetwork::RegistrationMode GEMALTO_CINTERION_CellularNetwork::has_registration(RegistrationType reg_type)

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

Lines changed: 96 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ GEMALTO_CINTERION_CellularStack::GEMALTO_CINTERION_CellularStack(ATHandler &atHa
3939

4040
GEMALTO_CINTERION_CellularStack::~GEMALTO_CINTERION_CellularStack()
4141
{
42+
_at.remove_urc_handler("^SIS:", mbed::Callback<void()>(this, &GEMALTO_CINTERION_CellularStack::urc_sis));
43+
_at.remove_urc_handler("^SISW:", mbed::Callback<void()>(this, &GEMALTO_CINTERION_CellularStack::urc_sisw));
44+
_at.remove_urc_handler("^SISR:", mbed::Callback<void()>(this, &GEMALTO_CINTERION_CellularStack::urc_sisr));
4245
}
4346

4447
GEMALTO_CINTERION_CellularStack::CellularSocket *GEMALTO_CINTERION_CellularStack::find_socket(int sock_id)
@@ -62,14 +65,14 @@ void GEMALTO_CINTERION_CellularStack::urc_sis()
6265
int urc_code = _at.read_int();
6366
CellularSocket *sock = find_socket(sock_id);
6467
if (sock) {
65-
if (urc_code == 5) { // data available
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.
70+
if (urc_code == 5) { // The service is ready to use (ELS61 and EMS31).
6671
if (sock->_cb) {
6772
sock->started = true;
6873
sock->tx_ready = true;
6974
sock->_cb(sock->_data);
7075
}
71-
} else if (urc_code == 2) { // socket closed
72-
sock->created = false;
7376
}
7477
}
7578
}
@@ -88,8 +91,6 @@ void GEMALTO_CINTERION_CellularStack::urc_sisw()
8891
}
8992
sock->_cb(sock->_data);
9093
}
91-
} else if (urc_code == 2) { // socket closed
92-
sock->created = false;
9394
}
9495
}
9596
}
@@ -105,21 +106,30 @@ void GEMALTO_CINTERION_CellularStack::urc_sisr()
105106
sock->rx_avail = true;
106107
sock->_cb(sock->_data);
107108
}
108-
} else if (urc_code == 2) { // socket closed
109-
sock->created = false;
110109
}
111110
}
112111
}
113112

114113
nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_stack_init()
115114
{
116115
_at.lock();
117-
if (create_connection_profile()) {
116+
int connection_profile_id = CONNECTION_PROFILE_ID;
117+
nsapi_error_t err = create_connection_profile(connection_profile_id);
118+
if (!err) {
118119
_at.set_urc_handler("^SIS:", mbed::Callback<void()>(this, &GEMALTO_CINTERION_CellularStack::urc_sis));
119120
_at.set_urc_handler("^SISW:", mbed::Callback<void()>(this, &GEMALTO_CINTERION_CellularStack::urc_sisw));
120121
_at.set_urc_handler("^SISR:", mbed::Callback<void()>(this, &GEMALTO_CINTERION_CellularStack::urc_sisr));
122+
} else { // recovery cleanup
123+
// close all Internet and connection profiles
124+
for (int i = 0; i < SOCKET_MAX; i++) {
125+
_at.clear_error();
126+
socket_close_impl(i);
127+
}
128+
_at.clear_error();
129+
close_connection_profile(connection_profile_id);
121130
}
122-
return _at.unlock_return_error();
131+
_at.unlock();
132+
return err;
123133
}
124134

125135
int GEMALTO_CINTERION_CellularStack::get_max_socket_count()
@@ -134,22 +144,24 @@ bool GEMALTO_CINTERION_CellularStack::is_protocol_supported(nsapi_protocol_t pro
134144

135145
nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_close_impl(int sock_id)
136146
{
137-
CellularSocket *socket = find_socket(sock_id);
138-
if (!socket) {
139-
return NSAPI_ERROR_NO_SOCKET;
140-
}
141147
_at.set_at_timeout(FAILURE_TIMEOUT);
148+
142149
_at.cmd_start("AT^SISC=");
143150
_at.write_int(sock_id);
144151
_at.cmd_stop();
145152
_at.resp_start();
146153
_at.resp_stop();
147-
_at.restore_at_timeout();
148154

149-
socket->started = false;
150-
socket->created = false;
151-
socket->tx_ready = false;
152-
socket->rx_avail = false;
155+
_at.clear_error(); // clear SISS even though SISC fails
156+
_at.cmd_start("AT^SISS=");
157+
_at.write_int(sock_id);
158+
_at.write_string("srvType");
159+
_at.write_string("none");
160+
_at.cmd_stop();
161+
_at.resp_start();
162+
_at.resp_stop();
163+
164+
_at.restore_at_timeout();
153165

154166
tr_debug("Closed socket %d (err %d)", sock_id, _at.get_last_error());
155167
return _at.get_last_error();
@@ -267,7 +279,7 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::create_socket_impl(CellularSocket
267279
_at.resp_stop();
268280
}
269281

270-
tr_debug("Internet service %d created (err %d)", internet_service_id, _at.get_last_error());
282+
tr_debug("Internet service %d (err %d)", internet_service_id, _at.get_last_error());
271283

272284
if (GEMALTO_CINTERION_Module::get_model() != GEMALTO_CINTERION_Module::ModelBGS2) {
273285
return socket_open_defer(socket);
@@ -287,13 +299,17 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul
287299
return NSAPI_ERROR_NO_SOCKET;
288300
}
289301
if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
290-
tr_error("Send addr %s, prev addr %s", address.get_ip_address(), socket->remoteAddress.get_ip_address());
302+
tr_debug("Send addr %s, prev addr %s", address.get_ip_address(), socket->remoteAddress.get_ip_address());
291303
if (address != socket->remoteAddress) {
292304
if (socket->started) {
293305
socket_close_impl(socket->id);
294306
_at.clear_error();
295307
}
296308

309+
if (create_socket_impl(socket) != NSAPI_ERROR_OK) {
310+
tr_error("Failed to create socket %d", socket->id);
311+
return NSAPI_ERROR_NO_SOCKET;
312+
}
297313
if (socket_open_defer(socket, &address) != NSAPI_ERROR_OK) {
298314
tr_error("Failed to open socket %d", socket->id);
299315
return NSAPI_ERROR_NO_SOCKET;
@@ -381,11 +397,8 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
381397
{
382398
tr_debug("Socket %d recvfrom %d bytes", socket->id, size);
383399

384-
if (size > UDP_PACKET_SIZE) {
385-
tr_debug("Socket recvfrom size %d > %d", size, UDP_PACKET_SIZE);
386-
size = UDP_PACKET_SIZE;
387-
}
388-
400+
// we must use this flag, otherwise ^SISR URC can come while we are reading response and there is
401+
// no way to detect if that is really an URC or response
389402
if (!socket->rx_avail) {
390403
_at.process_oob(); // check for ^SISR URC
391404
if (!socket->rx_avail) {
@@ -394,6 +407,11 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
394407
}
395408
}
396409

410+
if (size > UDP_PACKET_SIZE) {
411+
tr_debug("Socket recvfrom size %d > %d", size, UDP_PACKET_SIZE);
412+
size = UDP_PACKET_SIZE;
413+
}
414+
397415
_at.cmd_start("AT^SISR=");
398416
_at.write_int(socket->id);
399417
_at.write_int(size);
@@ -468,30 +486,27 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
468486

469487
_at.resp_stop();
470488

471-
tr_debug("Socket %d, recvfrom %s, %d bytes (err %d)", socket->id, address, len, _at.get_last_error());
489+
tr_debug("Socket %d, recvfrom %s, %d bytes (err %d)", socket->id, socket->remoteAddress.get_ip_address(), len, _at.get_last_error());
472490

473-
return (_at.get_last_error() == NSAPI_ERROR_OK) ? recv_len : NSAPI_ERROR_DEVICE_ERROR;
491+
return (_at.get_last_error() == NSAPI_ERROR_OK) ? ( recv_len ? recv_len : NSAPI_ERROR_WOULD_BLOCK ) : NSAPI_ERROR_DEVICE_ERROR;
474492
}
475493

476494
// setup internet connection profile for sockets
477-
bool GEMALTO_CINTERION_CellularStack::create_connection_profile()
495+
nsapi_error_t GEMALTO_CINTERION_CellularStack::create_connection_profile(int connection_profile_id)
478496
{
479497
if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelEMS31) {
480498
// EMS31 connection has only DNS settings and there is no need to modify those here for now
481-
return true;
499+
return NSAPI_ERROR_OK;
482500
}
483501

484-
char conParamType[12];
502+
char conParamType[sizeof("GPRS0") + 1];
485503
std::sprintf(conParamType, "GPRS%d", (_stack_type == IPV4_STACK) ? 0 : 6);
486504
_at.cmd_start("AT^SICS?");
487505
_at.cmd_stop();
488-
bool foundConnection = false;
489-
bool foundAPN = false;
490-
int connection_profile_id = CONNECTION_PROFILE_ID;
506+
bool found_connection = false;
491507
_at.resp_start("^SICS:");
492508
while (_at.info_resp()) {
493509
int id = _at.read_int();
494-
tr_debug("SICS %d", id);
495510
if (id == connection_profile_id) {
496511
char paramTag[16];
497512
int paramTagLen = _at.read_string(paramTag, sizeof(paramTag));
@@ -500,17 +515,10 @@ bool GEMALTO_CINTERION_CellularStack::create_connection_profile()
500515
char paramValue[100 + 1]; // APN may be up to 100 chars
501516
int paramValueLen = _at.read_string(paramValue, sizeof(paramValue));
502517
if (paramValueLen >= 0) {
503-
tr_debug("paramValue %s", paramValue);
504518
if (strcmp(paramTag, "conType") == 0) {
505-
tr_debug("conType %s", paramValue);
506519
if (strcmp(paramValue, conParamType) == 0) {
507-
foundConnection = true;
508-
}
509-
}
510-
if (strcmp(paramTag, "apn") == 0) {
511-
tr_debug("apn %s", paramValue);
512-
if (strcmp(paramValue, _apn ? _apn : "") == 0) {
513-
foundAPN = true;
520+
found_connection = true;
521+
break;
514522
}
515523
}
516524
}
@@ -519,34 +527,68 @@ bool GEMALTO_CINTERION_CellularStack::create_connection_profile()
519527
}
520528
_at.resp_stop();
521529

522-
if (!foundConnection) {
523-
tr_debug("Socket conType %s", conParamType);
530+
// connection profile is bound to a PDP context and it can not be changed
531+
if (!found_connection) {
524532
_at.cmd_start("AT^SICS=");
525533
_at.write_int(connection_profile_id);
526534
_at.write_string("conType");
527535
_at.write_string(conParamType);
528536
_at.cmd_stop();
529537
_at.resp_start();
530538
_at.resp_stop();
531-
}
532539

533-
if (!foundAPN && _apn) {
534-
tr_debug("Socket APN %s", _apn ? _apn : "");
540+
if (_apn && strlen(_apn) > 0) {
541+
_at.cmd_start("AT^SICS=");
542+
_at.write_int(connection_profile_id);
543+
_at.write_string("apn");
544+
_at.write_string(_apn);
545+
_at.cmd_stop();
546+
_at.resp_start();
547+
_at.resp_stop();
548+
}
549+
550+
// set maximum inactivity timeout
535551
_at.cmd_start("AT^SICS=");
536552
_at.write_int(connection_profile_id);
537-
_at.write_string("apn");
538-
_at.write_string(_apn);
553+
_at.write_string("inactTO");
554+
_at.write_int(0xffff); // 2^16-1
555+
_at.cmd_stop();
556+
_at.resp_start();
557+
_at.resp_stop();
558+
559+
// use URC mode ON
560+
_at.cmd_start("AT^SCFG=\"Tcp/withURCs\",\"on\"");
539561
_at.cmd_stop();
540562
_at.resp_start();
541563
_at.resp_stop();
542564
}
543565

544-
// use URC mode
545-
_at.cmd_start("AT^SCFG=\"Tcp/withURCs\",\"on\"");
566+
tr_debug("Connection profile %d, stack_type %d (err %d)", connection_profile_id, _stack_type, _at.get_last_error());
567+
return _at.get_last_error();
568+
}
569+
570+
void GEMALTO_CINTERION_CellularStack::close_connection_profile(int connection_profile_id)
571+
{
572+
if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelEMS31) {
573+
return;
574+
}
575+
576+
// To clear connection profile need to detach from packet data.
577+
// After detach modem sends PDP disconnected event to network class,
578+
// which propagates network disconnected to upper layer to start reconnecting.
579+
_at.cmd_start("AT+CGATT=0");
580+
_at.cmd_stop();
581+
_at.resp_start();
582+
_at.resp_stop();
583+
_at.clear_error();
584+
585+
_at.cmd_start("AT^SICS=");
586+
_at.write_int(connection_profile_id);
587+
_at.write_string("conType");
588+
_at.write_string("none");
546589
_at.cmd_stop();
547590
_at.resp_start();
548591
_at.resp_stop();
549592

550-
tr_debug("Connection profile %d created, stack_type %d (err %d)", connection_profile_id, _stack_type, _at.get_last_error());
551-
return _at.get_last_error() == NSAPI_ERROR_OK;
593+
_at.clear_error();
552594
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ class GEMALTO_CINTERION_CellularStack : public AT_CellularStack {
5555
void urc_sisr();
5656

5757
// sockets need a connection profile, one profile is enough to support single stack sockets
58-
bool create_connection_profile();
58+
nsapi_error_t create_connection_profile(int connection_profile_id);
59+
void close_connection_profile(int connection_profile_id);
5960

6061
// socket open need to be deferred until sendto due to BGS2 does not support UDP server endpoint
6162
nsapi_error_t socket_open_defer(CellularSocket *socket, const SocketAddress *address = NULL);

0 commit comments

Comments
 (0)