Skip to content

Commit d1ba79a

Browse files
ldeneflecarlescufi
authored andcommitted
drivers: cellular: add signal and modem_info API
Implement modem info pulling using the init and periodic chat scripts Signed-off-by: Lucas Denefle <[email protected]>
1 parent ad01169 commit d1ba79a

File tree

2 files changed

+259
-25
lines changed

2 files changed

+259
-25
lines changed

drivers/modem/modem_cellular.c

Lines changed: 206 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <zephyr/kernel.h>
88
#include <zephyr/device.h>
99
#include <zephyr/drivers/gpio.h>
10+
#include <zephyr/drivers/cellular.h>
1011
#include <zephyr/modem/chat.h>
1112
#include <zephyr/modem/cmux.h>
1213
#include <zephyr/modem/pipe.h>
@@ -25,6 +26,13 @@ LOG_MODULE_REGISTER(modem_cellular, CONFIG_MODEM_LOG_LEVEL);
2526
#define MODEM_CELLULAR_PERIODIC_SCRIPT_TIMEOUT \
2627
K_MSEC(CONFIG_MODEM_CELLULAR_PERIODIC_SCRIPT_MS)
2728

29+
#define MODEM_CELLULAR_DATA_IMEI_LEN (15)
30+
#define MODEM_CELLULAR_DATA_MODEL_ID_LEN (64)
31+
#define MODEM_CELLULAR_DATA_IMSI_LEN (22)
32+
#define MODEM_CELLULAR_DATA_ICCID_LEN (22)
33+
#define MODEM_CELLULAR_DATA_MANUFACTURER_LEN (64)
34+
#define MODEM_CELLULAR_DATA_FW_VERSION_LEN (64)
35+
2836
enum modem_cellular_state {
2937
MODEM_CELLULAR_STATE_IDLE = 0,
3038
MODEM_CELLULAR_STATE_RESET_PULSE,
@@ -83,11 +91,16 @@ struct modem_cellular_data {
8391
uint8_t *chat_argv[32];
8492

8593
/* Status */
86-
uint8_t imei[15];
87-
uint8_t hwinfo[64];
8894
uint8_t registration_status_gsm;
8995
uint8_t registration_status_gprs;
9096
uint8_t registration_status_lte;
97+
int8_t rssi;
98+
uint8_t imei[MODEM_CELLULAR_DATA_IMEI_LEN];
99+
uint8_t model_id[MODEM_CELLULAR_DATA_MODEL_ID_LEN];
100+
uint8_t imsi[MODEM_CELLULAR_DATA_IMSI_LEN];
101+
uint8_t iccid[MODEM_CELLULAR_DATA_ICCID_LEN];
102+
uint8_t manufacturer[MODEM_CELLULAR_DATA_MANUFACTURER_LEN];
103+
uint8_t fw_version[MODEM_CELLULAR_DATA_FW_VERSION_LEN];
91104

92105
/* PPP */
93106
struct modem_ppp *ppp;
@@ -118,6 +131,7 @@ struct modem_cellular_config {
118131
const struct modem_chat_script *init_chat_script;
119132
const struct modem_chat_script *dial_chat_script;
120133
const struct modem_chat_script *periodic_chat_script;
134+
const struct modem_chat_script *get_signal_chat_script;
121135
};
122136

123137
static const char *modem_cellular_state_str(enum modem_cellular_state state)
@@ -276,16 +290,34 @@ static void modem_cellular_chat_on_imei(struct modem_chat *chat, char **argv, ui
276290
return;
277291
}
278292

279-
if (strlen(argv[1]) != 15) {
293+
strncpy(data->imei, argv[1], sizeof(data->imei));
294+
}
295+
296+
static void modem_cellular_chat_on_cgmm(struct modem_chat *chat, char **argv, uint16_t argc,
297+
void *user_data)
298+
{
299+
struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
300+
301+
if (argc != 2) {
280302
return;
281303
}
282304

283-
for (uint8_t i = 0; i < 15; i++) {
284-
data->imei[i] = argv[1][i] - '0';
305+
strncpy(data->model_id, argv[1], sizeof(data->model_id));
306+
}
307+
308+
static void modem_cellular_chat_on_cgmi(struct modem_chat *chat, char **argv, uint16_t argc,
309+
void *user_data)
310+
{
311+
struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
312+
313+
if (argc != 2) {
314+
return;
285315
}
316+
317+
strncpy(data->manufacturer, argv[1], sizeof(data->manufacturer));
286318
}
287319

288-
static void modem_cellular_chat_on_cgmm(struct modem_chat *chat, char **argv, uint16_t argc,
320+
static void modem_cellular_chat_on_cgmr(struct modem_chat *chat, char **argv, uint16_t argc,
289321
void *user_data)
290322
{
291323
struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
@@ -294,7 +326,50 @@ static void modem_cellular_chat_on_cgmm(struct modem_chat *chat, char **argv, ui
294326
return;
295327
}
296328

297-
strncpy(data->hwinfo, argv[1], sizeof(data->hwinfo) - 1);
329+
strncpy(data->fw_version, argv[1], sizeof(data->fw_version));
330+
}
331+
332+
static void modem_cellular_chat_on_csq(struct modem_chat *chat, char **argv, uint16_t argc,
333+
void *user_data)
334+
{
335+
uint8_t rssi;
336+
337+
/* AT+CSQ returns a response +CSQ: <rssi>,<ber> where:
338+
* - rssi is a integer from 0 to 31 whose values describes a signal strength
339+
* between -113 dBm for 0 and -51dbM for 31 or unknown for 99
340+
* - ber is an integer from 0 to 7 that describes the error rate, it can also
341+
* be 99 for an unknown error rate
342+
*/
343+
struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
344+
345+
if (argc != 3) {
346+
return;
347+
}
348+
349+
/* Read rssi */
350+
rssi = atoi(argv[1]);
351+
352+
if (rssi == 99) {
353+
return;
354+
}
355+
356+
data->rssi = (-113 + (2 * rssi));
357+
}
358+
359+
static void modem_cellular_chat_on_imsi(struct modem_chat *chat, char **argv, uint16_t argc,
360+
void *user_data)
361+
{
362+
struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
363+
364+
strncpy(data->imsi, (char *)argv[1], sizeof(data->imsi));
365+
}
366+
367+
static void modem_cellular_chat_on_iccid(struct modem_chat *chat, char **argv, uint16_t argc,
368+
void *user_data)
369+
{
370+
struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;
371+
372+
strncpy(data->iccid, (char *)argv[1], sizeof(data->iccid));
298373
}
299374

300375
static bool modem_cellular_is_registered(struct modem_cellular_data *data)
@@ -346,6 +421,11 @@ MODEM_CHAT_MATCHES_DEFINE(allow_match,
346421

347422
MODEM_CHAT_MATCH_DEFINE(imei_match, "", "", modem_cellular_chat_on_imei);
348423
MODEM_CHAT_MATCH_DEFINE(cgmm_match, "", "", modem_cellular_chat_on_cgmm);
424+
MODEM_CHAT_MATCH_DEFINE(csq_match, "+CSQ: ", ",", modem_cellular_chat_on_csq);
425+
MODEM_CHAT_MATCH_DEFINE(cimi_match, "", "", modem_cellular_chat_on_imsi);
426+
MODEM_CHAT_MATCH_DEFINE(ccid_match, "+QCCID: ", "", modem_cellular_chat_on_iccid);
427+
MODEM_CHAT_MATCH_DEFINE(cgmi_match, "", "", modem_cellular_chat_on_cgmi);
428+
MODEM_CHAT_MATCH_DEFINE(cgmr_match, "", "", modem_cellular_chat_on_cgmr);
349429

350430
MODEM_CHAT_MATCHES_DEFINE(unsol_matches,
351431
MODEM_CHAT_MATCH("+CREG: ", ",", modem_cellular_chat_on_cxreg),
@@ -1336,6 +1416,14 @@ MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_bg95_init_chat_script_cmds,
13361416
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
13371417
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
13381418
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1419+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMI", cgmi_match),
1420+
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1421+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMR", cgmr_match),
1422+
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1423+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CIMI", cimi_match),
1424+
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1425+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+QCCID", ccid_match),
1426+
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
13391427
MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127", 300));
13401428

13411429
MODEM_CHAT_SCRIPT_DEFINE(quectel_bg95_init_chat_script, quectel_bg95_init_chat_script_cmds,
@@ -1355,29 +1443,45 @@ MODEM_CHAT_SCRIPT_DEFINE(quectel_bg95_dial_chat_script, quectel_bg95_dial_chat_s
13551443
MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_bg95_periodic_chat_script_cmds,
13561444
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
13571445
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
1358-
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match));
1446+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
1447+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CSQ", csq_match));
13591448

13601449
MODEM_CHAT_SCRIPT_DEFINE(quectel_bg95_periodic_chat_script,
13611450
quectel_bg95_periodic_chat_script_cmds, abort_matches,
13621451
modem_cellular_chat_callback_handler, 4);
1452+
1453+
MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_bg95_get_signal_chat_script_cmds,
1454+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CSQ", csq_match));
1455+
1456+
MODEM_CHAT_SCRIPT_DEFINE(quectel_bg95_get_signal_chat_script,
1457+
quectel_bg95_get_signal_chat_script_cmds, abort_matches,
1458+
modem_cellular_chat_callback_handler, 4);
13631459
#endif
13641460

13651461
#if DT_HAS_COMPAT_STATUS_OKAY(quectel_eg25_g)
1366-
MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_eg25_g_init_chat_script_cmds,
1367-
MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match),
1368-
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match),
1369-
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match),
1370-
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match),
1371-
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG=1", ok_match),
1372-
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match),
1373-
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
1374-
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
1375-
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
1376-
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match),
1377-
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1378-
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
1379-
MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127,10,3,30,10,2",
1380-
100));
1462+
MODEM_CHAT_SCRIPT_CMDS_DEFINE(
1463+
quectel_eg25_g_init_chat_script_cmds, MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match),
1464+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match),
1465+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match),
1466+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match),
1467+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG=1", ok_match),
1468+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match),
1469+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
1470+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
1471+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
1472+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match),
1473+
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1474+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
1475+
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1476+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMI", cgmi_match),
1477+
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1478+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMR", cgmr_match),
1479+
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1480+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CIMI", cimi_match),
1481+
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1482+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+QCCID", ccid_match),
1483+
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
1484+
MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127,10,3,30,10,2", 100));
13811485

13821486
MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_init_chat_script, quectel_eg25_g_init_chat_script_cmds,
13831487
abort_matches, modem_cellular_chat_callback_handler, 10);
@@ -1396,11 +1500,19 @@ MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_dial_chat_script, quectel_eg25_g_dial_ch
13961500
MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_eg25_g_periodic_chat_script_cmds,
13971501
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match),
13981502
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match),
1399-
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match));
1503+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match),
1504+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CSQ", csq_match));
14001505

14011506
MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_periodic_chat_script,
14021507
quectel_eg25_g_periodic_chat_script_cmds, abort_matches,
14031508
modem_cellular_chat_callback_handler, 4);
1509+
1510+
MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_eg25_g_get_signal_chat_script_cmds,
1511+
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CSQ", csq_match));
1512+
1513+
MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_get_signal_chat_script,
1514+
quectel_eg25_g_get_signal_chat_script_cmds, abort_matches,
1515+
modem_cellular_chat_callback_handler, 4);
14041516
#endif
14051517

14061518
#if DT_HAS_COMPAT_STATUS_OKAY(zephyr_gsm_ppp)
@@ -1708,7 +1820,8 @@ MODEM_CHAT_SCRIPT_DEFINE(telit_me910g1_periodic_chat_script,
17081820
.shutdown_time_ms = 5000, \
17091821
.init_chat_script = &quectel_bg95_init_chat_script, \
17101822
.dial_chat_script = &quectel_bg95_dial_chat_script, \
1711-
.periodic_chat_script = &quectel_bg95_periodic_chat_script, \
1823+
.periodic_chat_script = &_CONCAT(DT_DRV_COMPAT, _periodic_chat_script), \
1824+
.get_signal_chat_script = &_CONCAT(DT_DRV_COMPAT, _get_signal_chat_script), \
17121825
}; \
17131826
\
17141827
PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \
@@ -1737,6 +1850,7 @@ MODEM_CHAT_SCRIPT_DEFINE(telit_me910g1_periodic_chat_script,
17371850
.init_chat_script = &quectel_eg25_g_init_chat_script, \
17381851
.dial_chat_script = &quectel_eg25_g_dial_chat_script, \
17391852
.periodic_chat_script = &_CONCAT(DT_DRV_COMPAT, _periodic_chat_script), \
1853+
.get_signal_chat_script = &_CONCAT(DT_DRV_COMPAT, _get_signal_chat_script), \
17401854
}; \
17411855
\
17421856
PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \
@@ -1945,3 +2059,70 @@ DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_SWIR_HL7800)
19452059
#define DT_DRV_COMPAT telit_me910g1
19462060
DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_TELIT_ME910G1)
19472061
#undef DT_DRV_COMPAT
2062+
2063+
int cellular_get_modem_info(const struct device *dev, enum cellular_modem_info_type type,
2064+
char *info, size_t size)
2065+
{
2066+
int ret = 0;
2067+
struct modem_cellular_data *data = (struct modem_cellular_data *)dev->data;
2068+
2069+
switch (type) {
2070+
case CELLULAR_MODEM_INFO_IMEI:
2071+
strncpy(info, &data->imei[0], MIN(size, sizeof(data->imei)));
2072+
break;
2073+
case CELLULAR_MODEM_INFO_SIM_IMSI:
2074+
strncpy(info, &data->imsi[0], MIN(size, sizeof(data->imsi)));
2075+
break;
2076+
case CELLULAR_MODEM_INFO_SIM_ICCID:
2077+
strncpy(info, &data->iccid[0], MIN(size, sizeof(data->iccid)));
2078+
break;
2079+
case CELLULAR_MODEM_INFO_MANUFACTURER:
2080+
strncpy(info, &data->manufacturer[0], MIN(size, sizeof(data->manufacturer)));
2081+
break;
2082+
case CELLULAR_MODEM_INFO_FW_VERSION:
2083+
strncpy(info, &data->fw_version[0], MIN(size, sizeof(data->fw_version)));
2084+
break;
2085+
case CELLULAR_MODEM_INFO_MODEL_ID:
2086+
strncpy(info, &data->model_id[0], MIN(size, sizeof(data->model_id)));
2087+
break;
2088+
default:
2089+
ret = -ENODATA;
2090+
break;
2091+
}
2092+
2093+
return ret;
2094+
}
2095+
2096+
int cellular_get_signal(const struct device *dev, const enum cellular_signal_type type,
2097+
int16_t *value)
2098+
{
2099+
int ret;
2100+
struct modem_cellular_data *data = (struct modem_cellular_data *)dev->data;
2101+
const struct modem_cellular_config *config = (struct modem_cellular_config *)dev->config;
2102+
2103+
if (config->get_signal_chat_script == NULL) {
2104+
return -ENOTSUP;
2105+
}
2106+
2107+
if ((data->state != MODEM_CELLULAR_STATE_AWAIT_REGISTERED) &&
2108+
(data->state != MODEM_CELLULAR_STATE_CARRIER_ON)) {
2109+
return -ENODATA;
2110+
}
2111+
2112+
ret = modem_chat_run_script(&data->chat, config->get_signal_chat_script);
2113+
if (ret != 0) {
2114+
return ret;
2115+
}
2116+
2117+
switch (type) {
2118+
case CELLULAR_SIGNAL_RSSI: {
2119+
*value = data->rssi;
2120+
} break;
2121+
case CELLULAR_SIGNAL_RSRP:
2122+
return -ENOTSUP;
2123+
case CELLULAR_SIGNAL_RSRQ:
2124+
return -ENOTSUP;
2125+
}
2126+
2127+
return ret;
2128+
}

0 commit comments

Comments
 (0)