Skip to content

Commit aaa2dcb

Browse files
Finish integrating Arduino cellular patches
1 parent 7145fd6 commit aaa2dcb

File tree

8 files changed

+205
-22
lines changed

8 files changed

+205
-22
lines changed

connectivity/cellular/include/cellular/framework/API/CellularDevice.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,14 @@ class CellularDevice {
424424
*/
425425
void set_retry_timeout_array(const uint16_t timeout[], int array_len);
426426

427+
/**
428+
* @brief Enable serial multiplexing according to <a href="https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=1516">3GPP TS 27.010</a>, if implemented
429+
* on this modem.
430+
*
431+
* @return Error code or success
432+
*/
433+
virtual nsapi_error_t enable_cmux() { return NSAPI_ERROR_UNSUPPORTED;};
434+
427435
protected: //Common functions
428436
friend class AT_CellularNetwork;
429437
friend class AT_CellularContext;
@@ -453,6 +461,8 @@ class CellularDevice {
453461
CellularStateMachine *_state_machine;
454462
Callback<void(nsapi_event_t, intptr_t)> _status_cb;
455463

464+
bool _cmux_enabled = false;
465+
456466
private: //Member variables
457467
CellularNetwork *_nw;
458468
char _sim_pin[MAX_PIN_SIZE + 1];

connectivity/cellular/include/cellular/framework/AT/AT_CellularDevice.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ class AT_CellularDevice : public CellularDevice {
130130

131131
virtual nsapi_error_t set_baud_rate(int baud_rate);
132132

133+
nsapi_error_t enable_cmux() override;
134+
133135
#if MBED_CONF_CELLULAR_USE_SMS
134136
virtual CellularSMS *open_sms();
135137

connectivity/cellular/source/framework/AT/AT_CellularDevice.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,29 @@ nsapi_error_t AT_CellularDevice::set_baud_rate(int baud_rate)
624624
return error;
625625
}
626626

627+
nsapi_error_t AT_CellularDevice::enable_cmux()
628+
{
629+
setup_at_handler();
630+
631+
_at.lock();
632+
for (int retry = 1; retry <= 3; retry++) {
633+
_at.clear_error();
634+
_at.flush();
635+
_at.at_cmd_discard("E0", "");
636+
if (_at.get_last_error() == NSAPI_ERROR_OK) {
637+
_at.at_cmd_discard("+CMUX", "=0");
638+
if (_at.get_last_error() == NSAPI_ERROR_OK) {
639+
_cmux_enabled = true;
640+
break;
641+
}
642+
}
643+
tr_debug("Wait 100ms to init modem");
644+
rtos::ThisThread::sleep_for(100ms); // let modem have time to get ready
645+
}
646+
647+
return _at.unlock_return_error();
648+
}
649+
627650
nsapi_error_t AT_CellularDevice::set_baud_rate_impl(int baud_rate)
628651
{
629652
return _at.at_cmd_discard("+IPR", "=", "%d", baud_rate);

connectivity/cellular/source/framework/AT/AT_CellularStack.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ nsapi_size_or_error_t AT_CellularStack::socket_recvfrom(nsapi_socket_t handle, S
332332

333333
if (socket->closed) {
334334
tr_info("recvfrom socket %d closed", socket->id);
335-
return 0;
335+
return NSAPI_ERROR_NO_CONNECTION;
336336
}
337337

338338
nsapi_size_or_error_t ret_val = NSAPI_ERROR_OK;

connectivity/drivers/cellular/GEMALTO/COMPONENT_GEMALTO_CINTERION/GEMALTO_CINTERION.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@ time_t GEMALTO_CINTERION::get_time()
3535
{
3636
tr_info("GEMALTO_CINTERION::get_time\n");
3737

38-
//Enable automatic time zone update:
39-
set_automatic_time_zone_update();
40-
4138
_at.lock();
4239

4340
//"+CCLK: \"%y/%m/%d,%H:%M:%S+ZZ"
@@ -299,20 +296,23 @@ void GEMALTO_CINTERION::init_module_tx62()
299296
1, // AT_CNMI
300297
1, // AT_CSMP
301298
1, // AT_CMGF
302-
0, // AT_CSDH
299+
1, // AT_CSDH
303300
1, // PROPERTY_IPV4_STACK
304301
0, // PROPERTY_IPV6_STACK
305302
0, // PROPERTY_IPV4V6_STACK
306303
0, // PROPERTY_NON_IP_PDP_TYPE
307-
0, // PROPERTY_AT_CGEREP
308-
0, // PROPERTY_AT_COPS_FALLBACK_AUTO
304+
1, // PROPERTY_AT_CGEREP
305+
1, // PROPERTY_AT_COPS_FALLBACK_AUTO
309306
7, // PROPERTY_SOCKET_COUNT
310307
1, // PROPERTY_IP_TCP
311308
1, // PROPERTY_IP_UDP
312-
100, // PROPERTY_AT_SEND_DELAY
309+
0, // PROPERTY_AT_SEND_DELAY
313310
};
314311
set_cellular_properties(cellular_properties);
315312
_module = ModuleTX62;
313+
314+
// Enable network time zone updates
315+
_at.at_cmd_discard("+CTZU", "=", "%d", 1);
316316
}
317317

318318
time_t GEMALTO_CINTERION::parse_time(char const *time_str) {

connectivity/drivers/cellular/GEMALTO/COMPONENT_GEMALTO_CINTERION/GEMALTO_CINTERION.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ class GEMALTO_CINTERION : public AT_CellularDevice {
7474
virtual AT_CellularInformation *open_information_impl(ATHandler &at);
7575
AT_CellularNetwork *open_network_impl(ATHandler &at) override;
7676

77-
protected:
78-
virtual nsapi_error_t init();
77+
public:
78+
nsapi_error_t init() override;
7979

8080
private:
8181
static Module _module;

connectivity/drivers/cellular/GEMALTO/COMPONENT_GEMALTO_CINTERION/GEMALTO_CINTERION_CellularStack.cpp

Lines changed: 140 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,18 @@ void GEMALTO_CINTERION_CellularStack::urc_sisr()
100100
sisr_urc_handler(sock_id, urc_code);
101101
}
102102

103+
void GEMALTO_CINTERION_CellularStack::urc_sysstart()
104+
{
105+
// close sockets if open
106+
_at.lock();
107+
for (int i = 0; i < _device.get_property(AT_CellularDevice::PROPERTY_SOCKET_COUNT); i++) {
108+
_at.clear_error();
109+
socket_close_impl(i);
110+
}
111+
_at.clear_error();
112+
_at.unlock();
113+
}
114+
103115
void GEMALTO_CINTERION_CellularStack::sisr_urc_handler(int sock_id, int urc_code)
104116
{
105117
CellularSocket *sock = find_socket(sock_id);
@@ -113,6 +125,86 @@ void GEMALTO_CINTERION_CellularStack::sisr_urc_handler(int sock_id, int urc_code
113125
}
114126
}
115127

128+
void GEMALTO_CINTERION_CellularStack::urc_gnss() {
129+
char gnss_string[100] = {'$', 'G'};
130+
if (_gnss_cb) {
131+
_at.set_delimiter('\n');
132+
_at.read_string(&gnss_string[2], 98);
133+
_at.set_default_delimiter();
134+
_gnss_cb(gnss_string);
135+
}
136+
}
137+
138+
void GEMALTO_CINTERION_CellularStack::beginGNSS(mbed::Callback<void(char*)> gnss_cb) {
139+
_at.lock();
140+
_gnss_cb = gnss_cb;
141+
_at.at_cmd_discard("^SGPSC", "=", "%s%d", "Engine/StartMode", 0);
142+
_at.at_cmd_discard("^SGPSC", "=", "%s%d", "Engine", 0);
143+
_at.at_cmd_discard("^SGPSC", "=", "%s%s", "Nmea/Urc", "off");
144+
145+
// Set up LNA_ENABLE GPIO
146+
_at.at_cmd_discard("^SPIO", "=", "%d", 1);
147+
_at.at_cmd_discard("^SCPIN", "=", "%d%d%d%d", 1, 7, 1, 0);
148+
_at.clear_error();
149+
_at.unlock();
150+
}
151+
152+
void GEMALTO_CINTERION_CellularStack::endGNSS() {
153+
_at.lock();
154+
_at.at_cmd_discard("^SSIO", "=", "%d%d", 7, 0);
155+
_gnss_cb = nullptr;
156+
_at.clear_error();
157+
_at.unlock();
158+
}
159+
160+
void GEMALTO_CINTERION_CellularStack::enableCmux()
161+
{
162+
_at.at_cmd_discard("+CMUX", "=0");
163+
}
164+
165+
int GEMALTO_CINTERION_CellularStack::startGNSS() {
166+
_at.lock();
167+
_engine = false;
168+
_at.at_cmd_discard("^SSIO", "=", "%d%d", 7, 1);
169+
_at.cmd_start_stop("^SGPSC", "=", "%s%d", "Engine", 3);
170+
_at.resp_start("^SGPSC: \"Engine\",");
171+
172+
char respEng[2];
173+
int resp_len = _at.read_string(respEng, sizeof(respEng));
174+
if (strcmp(respEng, "3") != 0) {
175+
_engine = false;
176+
_at.at_cmd_discard("^SGPSC", "=", "%s%d", "Engine", 0);
177+
_at.at_cmd_discard("^SGPSC", "=", "%s%s", "Nmea/Urc", "off");
178+
return 0;
179+
}
180+
_engine = true;
181+
_at.at_cmd_discard("^SGPSC", "=", "%s%s", "Nmea/Urc", "on");
182+
_at.clear_error();
183+
_at.unlock();
184+
185+
return 1;
186+
}
187+
188+
void GEMALTO_CINTERION_CellularStack::stopGNSS() {
189+
if(_engine) {
190+
_at.lock();
191+
_at.at_cmd_discard("^SGPSC", "=", "%s%s", "Nmea/Urc", "off");
192+
_at.at_cmd_discard("^SGPSC", "=", "%s%d", "Engine", 0);
193+
_at.clear_error();
194+
_at.unlock();
195+
_engine = false;
196+
}
197+
}
198+
199+
void GEMALTO_CINTERION_CellularStack::setGNSS_PSM(bool const enable) {
200+
if(_engine) {
201+
_at.lock();
202+
_at.at_cmd_discard("^SGPSC", "=", "%s%d", "Power/Psm", enable);
203+
_at.clear_error();
204+
_at.unlock();
205+
}
206+
}
207+
116208
nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_stack_init()
117209
{
118210
_at.lock();
@@ -121,6 +213,9 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_stack_init()
121213
_at.set_urc_handler("^SIS:", mbed::Callback<void()>(this, &GEMALTO_CINTERION_CellularStack::urc_sis));
122214
_at.set_urc_handler("^SISW:", mbed::Callback<void()>(this, &GEMALTO_CINTERION_CellularStack::urc_sisw));
123215
_at.set_urc_handler("^SISR:", mbed::Callback<void()>(this, &GEMALTO_CINTERION_CellularStack::urc_sisr));
216+
_at.set_urc_handler("^SYSSTART", mbed::Callback<void()>(this, &GEMALTO_CINTERION_CellularStack::urc_sysstart));
217+
_at.set_urc_handler("^SGPSE", mbed::Callback<void()>(this, &GEMALTO_CINTERION_CellularStack::urc_gnss));
218+
_at.set_urc_handler("$G", mbed::Callback<void()>(this, &GEMALTO_CINTERION_CellularStack::urc_gnss));
124219
} else { // recovery cleanup
125220
// close all Internet and connection profiles
126221
for (int i = 0; i < _device.get_property(AT_CellularDevice::PROPERTY_SOCKET_COUNT); i++) {
@@ -172,7 +267,7 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::gethostbyname(const char *host, S
172267
_at.resp_start("^SISX: \"HostByName\",");
173268
char ipAddress[NSAPI_IP_SIZE];
174269
int size = _at.read_string(ipAddress, sizeof(ipAddress));
175-
if (size) {
270+
if (size > 0) {
176271
//Valid string received
177272
tr_info("Read %d bytes. Valid string: %s\n", size, ipAddress);
178273
_at.restore_at_timeout();
@@ -200,10 +295,6 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_open_defer(CellularSocket
200295
bool foundSrvType = false;
201296
bool foundConIdType = false;
202297

203-
if (GEMALTO_CINTERION::get_module() == GEMALTO_CINTERION::ModuleTX62) {
204-
_at.cmd_start_stop("^SICA", "=", "%d%d", 1, _cid);
205-
}
206-
207298
_at.cmd_start_stop("^SISS", "?");
208299
_at.resp_start("^SISS:");
209300
/*
@@ -438,6 +529,7 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
438529
size = UDP_PACKET_SIZE;
439530
}
440531

532+
tr_info("requesting %d bytes\n", size);
441533
_at.cmd_start_stop("^SISR", "=", "%d%d", socket->id, size);
442534

443535
sisr_retry:
@@ -467,26 +559,62 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell
467559
}
468560
if (len == -1) {
469561
if (GEMALTO_CINTERION::get_module() == GEMALTO_CINTERION::ModuleTX62 && _at.get_last_read_error() == -2) {
562+
_at.process_oob();
470563
tr_error("Socket %d recvfrom finished!", socket->id);
471564
socket->pending_bytes = 0;
472565
return NSAPI_ERROR_OK;
473566
}
474567
tr_error("Socket %d recvfrom failed!", socket->id);
475568
return NSAPI_ERROR_DEVICE_ERROR;
476569
}
477-
socket->pending_bytes = 1;
478570
if (len >= (nsapi_size_or_error_t)size) {
479571
len = (nsapi_size_or_error_t)size;
480572
}
481573

482574
// UDP Udp_RemClient
483575
if (socket->proto == NSAPI_UDP && GEMALTO_CINTERION::get_module() != GEMALTO_CINTERION::ModuleBGS2) {
484-
char ip_address[NSAPI_IPv6_SIZE + sizeof("[]:12345") - 1 + 1];
485-
int ip_len = _at.read_string(ip_address, sizeof(ip_address));
486-
if (ip_len <= 0) {
487-
tr_error("Socket %d recvfrom addr (len %d)", socket->id, ip_len);
488-
return NSAPI_ERROR_DEVICE_ERROR;
489-
}
576+
size_t ip_address_len = NSAPI_IPv6_SIZE + sizeof("[]:12345") - 1 + 1;
577+
char ip_address[ip_address_len];
578+
579+
if (GEMALTO_CINTERION::get_module() == GEMALTO_CINTERION::ModuleTX62) {
580+
// Local buffer for parsing Udp_RemClient for TX62
581+
uint8_t at_buf[ip_address_len];
582+
size_t ip_len = 0;
583+
584+
// Skip <remainUdpPacketLength>
585+
nsapi_size_or_error_t rem_len = _at.read_int();
586+
587+
// Wait for full <Udp_RemClient> in the _at buffer
588+
do {
589+
int len = _at.read_bytes(at_buf + ip_len, 1);
590+
if (len <= 0) {
591+
tr_error("Socket %d recvfrom addr (len %d)", socket->id, ip_len);
592+
return NSAPI_ERROR_DEVICE_ERROR;
593+
}
594+
ip_len += len;
595+
} while (ip_len < ip_address_len && at_buf[ip_len - 2] != '\r' && at_buf[ip_len - 1] != '\n');
596+
597+
// if (ip_len < sizeof("0.0.0.0:0")) {
598+
if (ip_len < sizeof("[]:0")) {
599+
tr_error("Socket %d has no address", socket->id);
600+
goto sisr_retry;
601+
}
602+
603+
// at_buf contains remote client IP information
604+
// in the format "<ip address>:<port>"\r\n.
605+
606+
// Terminate the C string at the closing quotation mark
607+
at_buf[ip_len - 3] = '\0';
608+
// Skip the opening quotation mark
609+
memcpy(ip_address, at_buf + 1, ip_len - 4);
610+
tr_info("ip_address %s (%d)", ip_address, ip_len - 4);
611+
} else {
612+
int ip_len = _at.read_string(ip_address, sizeof(ip_address));
613+
if (ip_len <= 0) {
614+
tr_error("Socket %d recvfrom addr (len %d)", socket->id, ip_len);
615+
return NSAPI_ERROR_DEVICE_ERROR;
616+
}
617+
}
490618
if (address) {
491619
char *ip_start = ip_address;
492620
char *ip_stop;

connectivity/drivers/cellular/GEMALTO/COMPONENT_GEMALTO_CINTERION/GEMALTO_CINTERION_CellularStack.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,21 @@ class GEMALTO_CINTERION_CellularStack : public AT_CellularStack {
3434
*/
3535
nsapi_error_t socket_stack_init();
3636

37+
/**
38+
* @brief Enable GNSS output, if supported by the Cinterion module
39+
*
40+
* @param gnss_cb Callback which will be called when a new GNSS sentence is received
41+
*/
42+
void beginGNSS(mbed::Callback<void(char*)> gnss_cb);
43+
44+
void enableCmux();
45+
void endGNSS();
46+
int startGNSS();
47+
void stopGNSS();
48+
49+
/// Set whether Power Save Mode is enabled for the GNSS in the Cinterion module
50+
void setGNSS_PSM(bool enable);
51+
3752
protected:
3853

3954
virtual nsapi_error_t socket_close_impl(int sock_id);
@@ -56,9 +71,11 @@ class GEMALTO_CINTERION_CellularStack : public AT_CellularStack {
5671
// socket URC handlers as per Cinterion AT manuals
5772
void urc_sis();
5873
void urc_sisw();
74+
void urc_sysstart();
5975
void sisw_urc_handler(int sock_id, int urc_code);
6076
void urc_sisr();
6177
void sisr_urc_handler(int sock_id, int urc_code);
78+
void urc_gnss();
6279

6380
// sockets need a connection profile, one profile is enough to support single stack sockets
6481
nsapi_error_t create_connection_profile(int connection_profile_id);
@@ -71,6 +88,9 @@ class GEMALTO_CINTERION_CellularStack : public AT_CellularStack {
7188
const char *_apn;
7289
const char *_user;
7390
const char *_password;
91+
bool _engine;
92+
93+
mbed::Callback<void(char*)> _gnss_cb;
7494

7595
#ifdef MBED_CONF_CELLULAR_OFFLOAD_DNS_QUERIES
7696
hostbyname_cb_t _dns_callback;

0 commit comments

Comments
 (0)