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> 
@@ -84,11 +85,16 @@ struct modem_cellular_data {
8485	uint8_t  * chat_argv [32 ];
8586
8687	/* Status */ 
87- 	uint8_t  imei [15 ];
88- 	uint8_t  hwinfo [64 ];
8988	uint8_t  registration_status_gsm ;
9089	uint8_t  registration_status_gprs ;
9190	uint8_t  registration_status_lte ;
91+ 	int8_t  rssi ;
92+ 	uint8_t  imei [15 ];
93+ 	uint8_t  model_id [64 ];
94+ 	uint8_t  imsi [15 ];
95+ 	uint8_t  iccid [22 ];
96+ 	uint8_t  manufacturer [64 ];
97+ 	uint8_t  fw_version [64 ];
9298
9399	/* PPP */ 
94100	struct  modem_ppp  * ppp ;
@@ -120,6 +126,7 @@ struct modem_cellular_config {
120126	const  struct  modem_chat_script  * dial_chat_script ;
121127	const  struct  modem_chat_script  * periodic_chat_script ;
122128	const  struct  modem_chat_script  * power_down_script ;
129+ 	const  struct  modem_chat_script  * get_signal_chat_script ;
123130};
124131
125132static  const  char  * modem_cellular_state_str (enum  modem_cellular_state  state )
@@ -280,16 +287,34 @@ static void modem_cellular_chat_on_imei(struct modem_chat *chat, char **argv, ui
280287		return ;
281288	}
282289
283- 	if  (strlen (argv [1 ]) !=  15 ) {
290+ 	strncpy (data -> imei , argv [1 ], sizeof (data -> imei ));
291+ }
292+ 
293+ static  void  modem_cellular_chat_on_cgmm (struct  modem_chat  * chat , char  * * argv , uint16_t  argc ,
294+ 					void  * user_data )
295+ {
296+ 	struct  modem_cellular_data  * data  =  (struct  modem_cellular_data  * )user_data ;
297+ 
298+ 	if  (argc  !=  2 ) {
284299		return ;
285300	}
286301
287- 	for  (uint8_t  i  =  0 ; i  <  15 ; i ++ ) {
288- 		data -> imei [i ] =  argv [1 ][i ] -  '0' ;
302+ 	strncpy (data -> model_id , argv [1 ], sizeof (data -> model_id ));
303+ }
304+ 
305+ static  void  modem_cellular_chat_on_cgmi (struct  modem_chat  * chat , char  * * argv , uint16_t  argc ,
306+ 					void  * user_data )
307+ {
308+ 	struct  modem_cellular_data  * data  =  (struct  modem_cellular_data  * )user_data ;
309+ 
310+ 	if  (argc  !=  2 ) {
311+ 		return ;
289312	}
313+ 
314+ 	strncpy (data -> manufacturer , argv [1 ], sizeof (data -> manufacturer ));
290315}
291316
292- static  void  modem_cellular_chat_on_cgmm (struct  modem_chat  * chat , char  * * argv , uint16_t  argc ,
317+ static  void  modem_cellular_chat_on_cgmr (struct  modem_chat  * chat , char  * * argv , uint16_t  argc ,
293318					void  * user_data )
294319{
295320	struct  modem_cellular_data  * data  =  (struct  modem_cellular_data  * )user_data ;
@@ -298,7 +323,48 @@ static void modem_cellular_chat_on_cgmm(struct modem_chat *chat, char **argv, ui
298323		return ;
299324	}
300325
301- 	strncpy (data -> hwinfo , argv [1 ], sizeof (data -> hwinfo ) -  1 );
326+ 	strncpy (data -> fw_version , argv [1 ], sizeof (data -> fw_version ));
327+ }
328+ 
329+ static  void  modem_cellular_chat_on_csq (struct  modem_chat  * chat , char  * * argv , uint16_t  argc ,
330+ 				       void  * user_data )
331+ {
332+ 	/* AT+CSQ returns a response +CSQ: <rssi>,<ber> where: 
333+ 	 * - rssi is a integer from 0 to 31 whose values describes a signal strength 
334+ 	 *   between -113 dBm for 0 and -51dbM for 31 or unknown for 99 
335+ 	 * - ber is an integer from 0 to 7 that describes the error rate, it can also 
336+ 	 *   be 99 for an unknown error rate 
337+ 	 */ 
338+ 	struct  modem_cellular_data  * data  =  (struct  modem_cellular_data  * )user_data ;
339+ 
340+ 	if  (argc  !=  3 ) {
341+ 		return ;
342+ 	}
343+ 
344+ 	/* Read rssi */ 
345+ 	uint8_t  rssi  =  atoi (argv [1 ]);
346+ 
347+ 	if  (rssi  ==  99 ) {
348+ 		return ;
349+ 	}
350+ 
351+ 	data -> rssi  =  (-113  +  (2  *  rssi ));
352+ }
353+ 
354+ static  void  modem_cellular_chat_on_imsi (struct  modem_chat  * chat , char  * * argv , uint16_t  argc ,
355+ 					void  * user_data )
356+ {
357+ 	struct  modem_cellular_data  * data  =  (struct  modem_cellular_data  * )user_data ;
358+ 
359+ 	strncpy (data -> imsi , (char  * )argv [1 ], sizeof (data -> imsi ));
360+ }
361+ 
362+ static  void  modem_cellular_chat_on_iccid (struct  modem_chat  * chat , char  * * argv , uint16_t  argc ,
363+ 					 void  * user_data )
364+ {
365+ 	struct  modem_cellular_data  * data  =  (struct  modem_cellular_data  * )user_data ;
366+ 
367+ 	strncpy (data -> iccid , (char  * )argv [1 ], sizeof (data -> iccid ));
302368}
303369
304370static  bool  modem_cellular_is_registered (struct  modem_cellular_data  * data )
@@ -350,6 +416,11 @@ MODEM_CHAT_MATCHES_DEFINE(allow_match,
350416
351417MODEM_CHAT_MATCH_DEFINE (imei_match , "" , "" , modem_cellular_chat_on_imei );
352418MODEM_CHAT_MATCH_DEFINE (cgmm_match , "" , "" , modem_cellular_chat_on_cgmm );
419+ MODEM_CHAT_MATCH_DEFINE (csq_match , "+CSQ: " , "," , modem_cellular_chat_on_csq );
420+ MODEM_CHAT_MATCH_DEFINE (cimi_match , "" , "" , modem_cellular_chat_on_imsi );
421+ MODEM_CHAT_MATCH_DEFINE (ccid_match , "+QCCID: " , "" , modem_cellular_chat_on_iccid );
422+ MODEM_CHAT_MATCH_DEFINE (cgmi_match , "" , "" , modem_cellular_chat_on_cgmi );
423+ MODEM_CHAT_MATCH_DEFINE (cgmr_match , "" , "" , modem_cellular_chat_on_cgmr );
353424
354425MODEM_CHAT_MATCHES_DEFINE (unsol_matches ,
355426			  MODEM_CHAT_MATCH ("+CREG: " , "," , modem_cellular_chat_on_cxreg ),
@@ -1371,6 +1442,14 @@ MODEM_CHAT_SCRIPT_CMDS_DEFINE(quectel_bg95_init_chat_script_cmds,
13711442			      MODEM_CHAT_SCRIPT_CMD_RESP ("" , ok_match ),
13721443			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGMM" , cgmm_match ),
13731444			      MODEM_CHAT_SCRIPT_CMD_RESP ("" , ok_match ),
1445+ 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGMI" , cgmi_match ),
1446+ 			      MODEM_CHAT_SCRIPT_CMD_RESP ("" , ok_match ),
1447+ 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGMR" , cgmr_match ),
1448+ 			      MODEM_CHAT_SCRIPT_CMD_RESP ("" , ok_match ),
1449+ 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CIMI" , cimi_match ),
1450+ 			      MODEM_CHAT_SCRIPT_CMD_RESP ("" , ok_match ),
1451+ 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+QCCID" , ccid_match ),
1452+ 			      MODEM_CHAT_SCRIPT_CMD_RESP ("" , ok_match ),
13741453			      MODEM_CHAT_SCRIPT_CMD_RESP_NONE ("AT+CMUX=0,0,5,127" , 300 ));
13751454
13761455MODEM_CHAT_SCRIPT_DEFINE (quectel_bg95_init_chat_script , quectel_bg95_init_chat_script_cmds ,
@@ -1390,29 +1469,38 @@ MODEM_CHAT_SCRIPT_DEFINE(quectel_bg95_dial_chat_script, quectel_bg95_dial_chat_s
13901469MODEM_CHAT_SCRIPT_CMDS_DEFINE (quectel_bg95_periodic_chat_script_cmds ,
13911470			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CREG?" , ok_match ),
13921471			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CEREG?" , ok_match ),
1393- 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGREG?" , ok_match ));
1472+ 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGREG?" , ok_match ),
1473+ 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CSQ" , csq_match ));
13941474
13951475MODEM_CHAT_SCRIPT_DEFINE (quectel_bg95_periodic_chat_script ,
13961476			 quectel_bg95_periodic_chat_script_cmds , abort_matches ,
13971477			 modem_cellular_chat_callback_handler , 4 );
13981478#endif 
13991479
14001480#if  DT_HAS_COMPAT_STATUS_OKAY (quectel_eg25_g )
1401- MODEM_CHAT_SCRIPT_CMDS_DEFINE (quectel_eg25_g_init_chat_script_cmds ,
1402- 			      MODEM_CHAT_SCRIPT_CMD_RESP ("ATE0" , ok_match ),
1403- 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CFUN=4" , ok_match ),
1404- 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CMEE=1" , ok_match ),
1405- 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CREG=1" , ok_match ),
1406- 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGREG=1" , ok_match ),
1407- 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CEREG=1" , ok_match ),
1408- 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CREG?" , ok_match ),
1409- 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CEREG?" , ok_match ),
1410- 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGREG?" , ok_match ),
1411- 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGSN" , imei_match ),
1412- 			      MODEM_CHAT_SCRIPT_CMD_RESP ("" , ok_match ),
1413- 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGMM" , cgmm_match ),
1414- 			      MODEM_CHAT_SCRIPT_CMD_RESP_NONE ("AT+CMUX=0,0,5,127,10,3,30,10,2" ,
1415- 							      100 ));
1481+ MODEM_CHAT_SCRIPT_CMDS_DEFINE (
1482+ 	quectel_eg25_g_init_chat_script_cmds , MODEM_CHAT_SCRIPT_CMD_RESP ("ATE0" , ok_match ),
1483+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CFUN=4" , ok_match ),
1484+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CMEE=1" , ok_match ),
1485+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CREG=1" , ok_match ),
1486+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGREG=1" , ok_match ),
1487+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CEREG=1" , ok_match ),
1488+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CREG?" , ok_match ),
1489+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CEREG?" , ok_match ),
1490+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGREG?" , ok_match ),
1491+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGSN" , imei_match ),
1492+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("" , ok_match ),
1493+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGMM" , cgmm_match ),
1494+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("" , ok_match ),
1495+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGMI" , cgmi_match ),
1496+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("" , ok_match ),
1497+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGMR" , cgmr_match ),
1498+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("" , ok_match ),
1499+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CIMI" , cimi_match ),
1500+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("" , ok_match ),
1501+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("AT+QCCID" , ccid_match ),
1502+ 	MODEM_CHAT_SCRIPT_CMD_RESP ("" , ok_match ),
1503+ 	MODEM_CHAT_SCRIPT_CMD_RESP_NONE ("AT+CMUX=0,0,5,127,10,3,30,10,2" , 100 ));
14161504
14171505MODEM_CHAT_SCRIPT_DEFINE (quectel_eg25_g_init_chat_script , quectel_eg25_g_init_chat_script_cmds ,
14181506			 abort_matches , modem_cellular_chat_callback_handler , 10 );
@@ -1429,7 +1517,7 @@ MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_dial_chat_script, quectel_eg25_g_dial_ch
14291517			 dial_abort_matches , modem_cellular_chat_callback_handler , 10 );
14301518
14311519MODEM_CHAT_SCRIPT_CMDS_DEFINE (quectel_eg25_g_power_down_script_cmds ,
1432- 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CFUN=1 " , ok_match ),
1520+ 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CFUN=0 " , ok_match ),
14331521			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+QSCLK=1" , ok_match ), );
14341522
14351523MODEM_CHAT_SCRIPT_DEFINE (quectel_eg25_g_power_down_script , quectel_eg25_g_power_down_script_cmds ,
@@ -1438,11 +1526,19 @@ MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_power_down_script, quectel_eg25_g_power_
14381526MODEM_CHAT_SCRIPT_CMDS_DEFINE (quectel_eg25_g_periodic_chat_script_cmds ,
14391527			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CREG?" , ok_match ),
14401528			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CEREG?" , ok_match ),
1441- 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGREG?" , ok_match ));
1529+ 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGREG?" , ok_match ),
1530+ 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CSQ" , csq_match ));
14421531
14431532MODEM_CHAT_SCRIPT_DEFINE (quectel_eg25_g_periodic_chat_script ,
14441533			 quectel_eg25_g_periodic_chat_script_cmds , abort_matches ,
14451534			 modem_cellular_chat_callback_handler , 4 );
1535+ 
1536+ MODEM_CHAT_SCRIPT_CMDS_DEFINE (quectel_eg25_g_get_signal_chat_script_cmds ,
1537+ 			      MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CSQ" , csq_match ));
1538+ 
1539+ MODEM_CHAT_SCRIPT_DEFINE (quectel_eg25_g_get_signal_chat_script ,
1540+ 			 quectel_eg25_g_get_signal_chat_script_cmds , abort_matches ,
1541+ 			 modem_cellular_chat_callback_handler , 4 );
14461542#endif 
14471543
14481544#if  DT_HAS_COMPAT_STATUS_OKAY (zephyr_gsm_ppp )
@@ -1697,6 +1793,7 @@ MODEM_CHAT_SCRIPT_DEFINE(telit_me910g1_dial_chat_script, telit_me910g1_dial_chat
16971793		.init_chat_script = &quectel_bg95_init_chat_script,                                \
16981794		.dial_chat_script = &quectel_bg95_dial_chat_script,                                \
16991795		.periodic_chat_script = &_CONCAT(DT_DRV_COMPAT, _periodic_chat_script),            \
1796+ 		.get_signal_chat_script = &_CONCAT(DT_DRV_COMPAT, _get_signal_chat_script),        \
17001797	};                                                                                         \
17011798                                                                                                   \
17021799	PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action);                                  \
@@ -1727,6 +1824,7 @@ MODEM_CHAT_SCRIPT_DEFINE(telit_me910g1_dial_chat_script, telit_me910g1_dial_chat
17271824		.dial_chat_script = &quectel_eg25_g_dial_chat_script,                              \
17281825		.periodic_chat_script = &_CONCAT(DT_DRV_COMPAT, _periodic_chat_script),            \
17291826		.power_down_script = &quectel_eg25_g_power_down_script,                            \
1827+ 		.get_signal_chat_script = &_CONCAT(DT_DRV_COMPAT, _get_signal_chat_script),        \
17301828	};                                                                                         \
17311829                                                                                                   \
17321830	PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action);                                  \
@@ -1903,3 +2001,72 @@ DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_SWIR_HL7800)
19032001#define  DT_DRV_COMPAT  telit_me910g1
19042002DT_INST_FOREACH_STATUS_OKAY (MODEM_CELLULAR_DEVICE_TELIT_ME910G1 )
19052003#undef  DT_DRV_COMPAT
2004+ 
2005+ int  cellular_get_modem_info (const  struct  device  * dev , enum  cellular_modem_info_type  type ,
2006+ 			    char  * info , size_t  size )
2007+ {
2008+ 	int  ret  =  0 ;
2009+ 
2010+ 	struct  modem_cellular_data  * data  =  (struct  modem_cellular_data  * )dev -> data ;
2011+ 
2012+ 	switch  (type ) {
2013+ 	case  CELLULAR_MODEM_INFO_IMEI :
2014+ 		strncpy (info , & data -> imei [0 ], MIN (size , sizeof (data -> imei )));
2015+ 		break ;
2016+ 	case  CELLULAR_MODEM_INFO_SIM_IMSI :
2017+ 		strncpy (info , & data -> imsi [0 ], MIN (size , sizeof (data -> imsi )));
2018+ 		break ;
2019+ 	case  CELLULAR_MODEM_INFO_SIM_ICCID :
2020+ 		strncpy (info , & data -> iccid [0 ], MIN (size , sizeof (data -> iccid )));
2021+ 		break ;
2022+ 	case  CELLULAR_MODEM_INFO_MANUFACTURER :
2023+ 		strncpy (info , & data -> manufacturer [0 ], MIN (size , sizeof (data -> manufacturer )));
2024+ 		break ;
2025+ 	case  CELLULAR_MODEM_INFO_FW_VERSION :
2026+ 		strncpy (info , & data -> fw_version [0 ], MIN (size , sizeof (data -> fw_version )));
2027+ 		break ;
2028+ 	case  CELLULAR_MODEM_INFO_MODEL_ID :
2029+ 		strncpy (info , & data -> model_id [0 ], MIN (size , sizeof (data -> model_id )));
2030+ 		break ;
2031+ 	default :
2032+ 		ret  =  - ENODATA ;
2033+ 		break ;
2034+ 	}
2035+ 
2036+ 	return  ret ;
2037+ }
2038+ 
2039+ int  cellular_get_signal (const  struct  device  * dev , const  enum  cellular_signal_type  type ,
2040+ 			int16_t  * value )
2041+ {
2042+ 	int  ret  =  0 ;
2043+ 
2044+ 	struct  modem_cellular_data  * data  =  (struct  modem_cellular_data  * )dev -> data ;
2045+ 	const  struct  modem_cellular_config  * config  =  (struct  modem_cellular_config  * )dev -> config ;
2046+ 
2047+ 	if  (config -> get_signal_chat_script  ==  NULL ) {
2048+ 		return  - ENOTSUP ;
2049+ 	}
2050+ 
2051+ 	if  ((data -> state  !=  MODEM_CELLULAR_STATE_AWAIT_REGISTERED ) && 
2052+ 	    (data -> state  !=  MODEM_CELLULAR_STATE_CARRIER_ON )) {
2053+ 		return  - ENODATA ;
2054+ 	}
2055+ 
2056+ 	ret  =  modem_chat_run_script (& data -> chat , config -> get_signal_chat_script );
2057+ 	if  (ret  !=  0 ) {
2058+ 		return  ret ;
2059+ 	}
2060+ 
2061+ 	switch  (type ) {
2062+ 	case  CELLULAR_SIGNAL_RSSI : {
2063+ 		* value  =  data -> rssi ;
2064+ 	} break ;
2065+ 	case  CELLULAR_SIGNAL_RSRP :
2066+ 		return  - ENOTSUP ;
2067+ 	case  CELLULAR_SIGNAL_RSRQ :
2068+ 		return  - ENOTSUP ;
2069+ 	}
2070+ 
2071+ 	return  ret ;
2072+ }
0 commit comments