diff mbox series

[3/5] uqmi: Add basic 5G NR support

Message ID 20240410112922.3945627-1-jean.thomas@wifirst.fr
State Accepted
Delegated to: Alexander Couzens
Headers show
Series None | expand

Commit Message

Jean Thomas April 10, 2024, 11:29 a.m. UTC
* Add 5G NR to supported networks in DMS --get-capabilities.
* Add 5G NR to supported mode in NAS --set-network-modes.
* Add 5G NR signal information to NAS --get-signal-info.
* Add 5G NR system information to NAS --get-system-info.
* Add 5G NR to supported radios in NAS --get-tx-rx-info.
* Add 5G NR cell information to NAS --get-cell-location-info.

Signed-off-by: Jean Thomas <jean.thomas@wifirst.fr>
---
 commands-dms.c |   1 +
 commands-nas.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++--
 commands-nas.h |   4 +-
 3 files changed, 107 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/commands-dms.c b/commands-dms.c
index 59648fb..b86fae2 100644
--- a/commands-dms.c
+++ b/commands-dms.c
@@ -49,6 +49,7 @@  static void cmd_dms_get_capabilities_cb(struct qmi_dev *qmi, struct qmi_request
 		[QMI_DMS_RADIO_INTERFACE_GSM] = "gsm",
 		[QMI_DMS_RADIO_INTERFACE_UMTS] = "umts",
 		[QMI_DMS_RADIO_INTERFACE_LTE] = "lte",
+		[QMI_DMS_RADIO_INTERFACE_5GNR] = "5gnr",
 	};
 	const char *service_cap[] = {
 		[QMI_DMS_DATA_SERVICE_CAPABILITY_NONE] = "none",
diff --git a/commands-nas.c b/commands-nas.c
index 476cd61..d791fee 100644
--- a/commands-nas.c
+++ b/commands-nas.c
@@ -21,6 +21,10 @@ 
 
 #include "qmi-message.h"
 
+/* According to libqmi, a value of -32768 in 5G
+ * indicates that the modem is not connected. */
+#define _5GNR_NOT_CONNECTED_VALUE	-32768
+
 static struct qmi_nas_get_tx_rx_info_request tx_rx_req;
 static struct qmi_nas_set_system_selection_preference_request sel_req;
 static struct	{
@@ -127,6 +131,7 @@  cmd_nas_set_network_modes_prepare(struct qmi_dev *qmi, struct qmi_request *req,
 		{ "gsm", QMI_NAS_RAT_MODE_PREFERENCE_GSM },
 		{ "umts", QMI_NAS_RAT_MODE_PREFERENCE_UMTS },
 		{ "lte", QMI_NAS_RAT_MODE_PREFERENCE_LTE },
+		{ "5gnr", QMI_NAS_RAT_MODE_PREFERENCE_5GNR },
 	};
 	QmiNasRatModePreference val = 0;
 	char *word;
@@ -262,10 +267,26 @@  static void
 cmd_nas_get_signal_info_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
 {
 	struct qmi_nas_get_signal_info_response res;
-	void *c;
+	void *c, *a;
+	bool is_5gnr_connected = false;
+	bool is_5gnr_endc = false;
 
 	qmi_parse_nas_get_signal_info_response(msg, &res);
 
+	/* If 5G NR EN-DC (dual connectivity) is enabled, the mobile device has two connections,
+	 * one with the LTE base station, and one with the NR base station.
+	 * Therefore an array of signals has to be reported in this case. */
+	is_5gnr_connected = ((res.set._5g_signal_strength &&
+		((res.data._5g_signal_strength.rsrp != _5GNR_NOT_CONNECTED_VALUE) ||
+		 (res.data._5g_signal_strength.snr != _5GNR_NOT_CONNECTED_VALUE))) ||
+		(res.set._5g_signal_strength_extended &&
+		(res.data._5g_signal_strength_extended != _5GNR_NOT_CONNECTED_VALUE)));
+	is_5gnr_endc = (res.set.lte_signal_strength && is_5gnr_connected);
+
+	if (is_5gnr_endc) {
+		a = blobmsg_open_array(&status, NULL);
+	}
+
 	c = blobmsg_open_table(&status, NULL);
 	if (res.set.cdma_signal_strength) {
 		blobmsg_add_string(&status, "type", "cdma");
@@ -304,7 +325,30 @@  cmd_nas_get_signal_info_cb(struct qmi_dev *qmi, struct qmi_request *req, struct
 		blobmsg_add_u32(&status, "signal", (int32_t) res.data.tdma_signal_strength);
 	}
 
+	if (is_5gnr_connected) {
+		if (is_5gnr_endc) {
+			blobmsg_close_table(&status, c);
+			c = blobmsg_open_table(&status, NULL);
+		}
+		blobmsg_add_string(&status, "type", "5gnr");
+		if (res.set._5g_signal_strength) {
+			if (res.data._5g_signal_strength.rsrp != _5GNR_NOT_CONNECTED_VALUE)
+				blobmsg_add_u32(&status, "rsrp", (int32_t) res.data._5g_signal_strength.rsrp);
+			if (res.data._5g_signal_strength.snr != _5GNR_NOT_CONNECTED_VALUE)
+				blobmsg_add_double(&status, "snr", (double) res.data._5g_signal_strength.snr*0.1);
+		}
+
+		if (res.set._5g_signal_strength_extended &&
+			(res.data._5g_signal_strength_extended != _5GNR_NOT_CONNECTED_VALUE)) {
+			blobmsg_add_u32(&status, "rsrq", (int32_t) res.data._5g_signal_strength_extended);
+		}
+	}
+
 	blobmsg_close_table(&status, c);
+
+	if (is_5gnr_endc) {
+		blobmsg_close_array(&status, a);
+	}
 }
 
 static void
@@ -498,6 +542,37 @@  cmd_nas_get_system_info_cb(struct qmi_dev *qmi, struct qmi_request *req, struct
 
 		blobmsg_close_table(&status, c);
 	}
+
+	if (res.set.nr5g_service_status_info) {
+		c = blobmsg_open_table(&status, "5gnr");
+		print_system_info(res.data.nr5g_service_status_info.service_status,
+				  res.data.nr5g_service_status_info.true_service_status,
+				  res.data.nr5g_service_status_info.preferred_data_path,
+				  res.set.nr5g_system_info,
+				  res.data.nr5g_system_info.domain_valid,
+				  res.data.nr5g_system_info.domain,
+				  res.data.nr5g_system_info.service_capability_valid,
+				  res.data.nr5g_system_info.service_capability,
+				  res.data.nr5g_system_info.roaming_status_valid,
+				  res.data.nr5g_system_info.roaming_status,
+				  res.data.nr5g_system_info.forbidden_valid,
+				  res.data.nr5g_system_info.forbidden,
+				  res.data.nr5g_system_info.network_id_valid,
+				  res.data.nr5g_system_info.mcc,
+				  res.data.nr5g_system_info.mnc,
+				  res.data.nr5g_system_info.lac_valid,
+				  res.data.nr5g_system_info.lac);
+		if (res.set.nr5g_system_info && res.data.nr5g_system_info.tac_valid)
+			blobmsg_add_u32(&status, "tracking_area_code",
+					res.data.nr5g_system_info.tac);
+		if (res.set.nr5g_system_info && res.data.nr5g_system_info.cid_valid) {
+			blobmsg_add_u32(&status, "enodeb_id",res.data.nr5g_system_info.cid/256);
+			blobmsg_add_u32(&status, "cell_id",res.data.nr5g_system_info.cid%256);
+		}
+
+		blobmsg_close_table(&status, c);
+	}
+
 	blobmsg_close_table(&status, t);
 }
 
@@ -594,11 +669,14 @@  print_chain_info(int8_t radio, bool tuned, int32_t rssi, int32_t ecio, int32_t r
 {
 	blobmsg_add_u8(&status, "tuned", tuned);
 	blobmsg_add_double(&status, "rssi", (double) rssi*0.1);
-	if (radio == QMI_NAS_RADIO_INTERFACE_LTE) {
+	if (radio == QMI_NAS_RADIO_INTERFACE_5GNR) {
+		blobmsg_add_double(&status, "rsrp", (double) rsrp*-0.1);
+	}
+	else if (radio == QMI_NAS_RADIO_INTERFACE_LTE) {
 		blobmsg_add_double(&status, "rsrq", (double) ecio*-0.1);
 		blobmsg_add_double(&status, "rsrp", (double) rsrp*-0.1);
 	}
-	if (radio == QMI_NAS_RADIO_INTERFACE_UMTS) {
+	else if (radio == QMI_NAS_RADIO_INTERFACE_UMTS) {
 		blobmsg_add_double(&status, "ecio", (double) ecio*-0.1);
 		blobmsg_add_double(&status, "rscp", (double) rscp*-0.1);
 	}
@@ -675,7 +753,9 @@  cmd_nas_get_tx_rx_info_prepare(struct qmi_dev *qmi, struct qmi_request *req, str
 {
 	int radio = 0;
 
-	if (!strcmp(arg, "lte"))
+	if (!strcmp(arg, "5gnr"))
+		radio = QMI_NAS_RADIO_INTERFACE_5GNR;
+	else if (!strcmp(arg, "lte"))
 		radio = QMI_NAS_RADIO_INTERFACE_LTE;
 	else if (!strcmp(arg, "umts"))
 		radio = QMI_NAS_RADIO_INTERFACE_UMTS;
@@ -896,6 +976,25 @@  cmd_nas_get_cell_location_info_cb(struct qmi_dev *qmi, struct qmi_request *req,
 		if (res.data.umts_info_neighboring_lte.frequency_n > 0)
 			blobmsg_close_table(&status, c);
 	}
+	if (res.set.nr5g_cell_information) {
+		c = blobmsg_open_table(&status, "nr5g_cell_information");
+		blobmsg_add_u32(&status, "enodeb_id",
+				res.data.nr5g_cell_information.global_cell_id/256);
+		blobmsg_add_u32(&status, "cell_id",
+				res.data.nr5g_cell_information.global_cell_id%256);
+		blobmsg_add_u32(&status, "physical_cell_id",
+				res.data.nr5g_cell_information.physical_cell_id);
+		blobmsg_add_double(&status, "rsrq", ((double)res.data.nr5g_cell_information.rsrq)/10);
+		blobmsg_add_double(&status, "rsrp", ((double)res.data.nr5g_cell_information.rsrp)/10);
+		blobmsg_add_double(&status, "snr", ((double)res.data.nr5g_cell_information.snr)/10);
+		blobmsg_close_table(&status, c);
+	}
+	if (res.set.nr5g_arfcn) {
+		c = blobmsg_open_table(&status, "nr5g_arfcn");
+		blobmsg_add_u32(&status, "arfcn",
+				res.data.nr5g_arfcn);
+		blobmsg_close_table(&status, c);
+	}
 	blobmsg_close_table(&status, t);
 }
 
@@ -1011,6 +1110,7 @@  cmd_nas_network_scan_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi
 		[QMI_NAS_RADIO_INTERFACE_UMTS] = "umts",
 		[QMI_NAS_RADIO_INTERFACE_LTE] = "lte",
 		[QMI_NAS_RADIO_INTERFACE_TD_SCDMA] = "td-scdma",
+		[QMI_NAS_RADIO_INTERFACE_5GNR] = "5gnr",
 	};
 	void *t, *c, *info, *stat;
 	int i, j;
diff --git a/commands-nas.h b/commands-nas.h
index 2426caa..6b29d33 100644
--- a/commands-nas.h
+++ b/commands-nas.h
@@ -39,7 +39,7 @@ 
 
 #define nas_helptext \
 		"  --set-network-modes <modes>:      Set usable network modes (Syntax: <mode1>[,<mode2>,...])\n" \
-		"                                    Available modes: all, lte, umts, gsm, cdma, td-scdma\n" \
+		"                                    Available modes: all, lte, umts, gsm, cdma, td-scdma, 5gnr\n" \
 		"  --set-network-preference <mode>:  Set preferred network mode to <mode>\n" \
 		"                                    Available modes: auto, gsm, wcdma\n" \
 		"  --set-network-roaming <mode>:     Set roaming preference:\n" \
@@ -55,5 +55,5 @@ 
 		"  --get-system-info:                Get system info\n" \
 		"  --get-lte-cphy-ca-info:           Get LTE Cphy CA Info\n" \
 		"  --get-cell-location-info:         Get Cell Location Info\n" \
-		"  --get-tx-rx-info <radio>:         Get TX/RX Info (gsm, umts, lte)\n" \
+		"  --get-tx-rx-info <radio>:         Get TX/RX Info (gsm, umts, lte, 5gnr)\n" \