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+
2836enum 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
123137static 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
300375static bool modem_cellular_is_registered (struct modem_cellular_data * data )
@@ -346,6 +421,11 @@ MODEM_CHAT_MATCHES_DEFINE(allow_match,
346421
347422MODEM_CHAT_MATCH_DEFINE (imei_match , "" , "" , modem_cellular_chat_on_imei );
348423MODEM_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
350430MODEM_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
13411429MODEM_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
13551443MODEM_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
13601449MODEM_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
13821486MODEM_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
13961500MODEM_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
14011506MODEM_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
19462060DT_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