uqmi: Add basic 5G NR support
authorJean Thomas <jeantho@gmail.com>
Wed, 10 Apr 2024 11:29:20 +0000 (13:29 +0200)
committerAlexander Couzens <lynxis@fe80.eu>
Sat, 13 Apr 2024 20:07:06 +0000 (22:07 +0200)
* 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>
uqmi/commands-dms.c
uqmi/commands-nas.c
uqmi/commands-nas.h

index 59648fb9e8a94d3499648cc6c6c14cb520593c28..b86fae2780ad628d884fa88d9be835555624ab64 100644 (file)
@@ -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",
index eebc2a6ac02cefd842048354e6734d4a9694e4a8..f59bc7d51a0232ee7750db12d8a33eb2aa54932e 100644 (file)
 
 #include <libubox/blobmsg.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  {
@@ -131,6 +135,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;
@@ -266,10 +271,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");
@@ -308,7 +329,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
@@ -502,6 +546,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);
 }
 
@@ -598,11 +673,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);
        }
@@ -679,7 +757,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;
@@ -900,6 +980,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);
 }
 
@@ -1015,6 +1114,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;
index 2426caafff226f85546e9e88c84dab23c3919251..6b29d33e2e0a5a258be9749bb690131fe6be6d65 100644 (file)
@@ -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" \