diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2022-01-07 18:46:41 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2022-01-18 09:00:10 +0000 |
commit | af0665c573a96f475b02d074144a136371ff473c (patch) | |
tree | 39d6a49c895c92688f92fdc9ae6e448a4ba4f9f5 | |
parent | 3c49e04377db5a61280da83f2c1f371219cf277f (diff) |
broadband-modem-mbim: implement support for GetCellInfo()
-rw-r--r-- | src/mm-broadband-modem-mbim.c | 400 |
1 files changed, 400 insertions, 0 deletions
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c index 2aab75f5..d8ef5311 100644 --- a/src/mm-broadband-modem-mbim.c +++ b/src/mm-broadband-modem-mbim.c @@ -121,6 +121,7 @@ struct _MMBroadbandModemMbimPrivate { gboolean is_pco_supported; gboolean is_lte_attach_info_supported; gboolean is_nr5g_registration_settings_supported; + gboolean is_base_stations_info_supported; gboolean is_ussd_supported; gboolean is_atds_location_supported; gboolean is_atds_signal_supported; @@ -2234,6 +2235,400 @@ modem_reset (MMIfaceModem *_self, } /*****************************************************************************/ +/* Cell info retrieval */ + +static GList * +modem_get_cell_info_finish (MMIfaceModem *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_pointer (G_TASK (res), error); +} + +static void +cell_info_list_free (GList *list) +{ + g_list_free_full (list, (GDestroyNotify)g_object_unref); +} + +static void +base_stations_info_query_ready (MbimDevice *device, + GAsyncResult *res, + GTask *task) +{ + MMBroadbandModemMbim *self; + g_autoptr(MbimMessage) response = NULL; + GError *error = NULL; + GList *list = NULL; + MMCellInfo *info = NULL; + g_autoptr(MbimCellInfoServingGsm) gsm_serving_cell = NULL; + g_autoptr(MbimCellInfoServingUmts) umts_serving_cell = NULL; + g_autoptr(MbimCellInfoServingTdscdma) tdscdma_serving_cell = NULL; + g_autoptr(MbimCellInfoServingLte) lte_serving_cell = NULL; + guint32 gsm_neighboring_cells_count = 0; + g_autoptr(MbimCellInfoNeighboringGsmArray) gsm_neighboring_cells = NULL; + guint32 umts_neighboring_cells_count = 0; + g_autoptr(MbimCellInfoNeighboringUmtsArray) umts_neighboring_cells = NULL; + guint32 tdscdma_neighboring_cells_count = 0; + g_autoptr(MbimCellInfoNeighboringTdscdmaArray) tdscdma_neighboring_cells = NULL; + guint32 lte_neighboring_cells_count = 0; + g_autoptr(MbimCellInfoNeighboringLteArray) lte_neighboring_cells = NULL; + guint32 cdma_cells_count = 0; + g_autoptr(MbimCellInfoCdmaArray) cdma_cells = NULL; + guint32 nr_serving_cells_count = 0; + g_autoptr(MbimCellInfoServingNrArray) nr_serving_cells = NULL; + guint32 nr_neighboring_cells_count = 0; + g_autoptr(MbimCellInfoNeighboringNrArray) nr_neighboring_cells = NULL; + + self = g_task_get_source_object (task); + + response = mbim_device_command_finish (device, res, &error); + if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + /* MBIMEx 3.0 support */ + if (mbim_device_check_ms_mbimex_version (device, 3, 0)) { + if (!mbim_message_ms_basic_connect_extensions_v3_base_stations_info_response_parse ( + response, + NULL, /* system_type_v3 */ + NULL, /* system_subtype */ + &gsm_serving_cell, + &umts_serving_cell, + &tdscdma_serving_cell, + <e_serving_cell, + &gsm_neighboring_cells_count, + &gsm_neighboring_cells, + &umts_neighboring_cells_count, + &umts_neighboring_cells, + &tdscdma_neighboring_cells_count, + &tdscdma_neighboring_cells, + <e_neighboring_cells_count, + <e_neighboring_cells, + &cdma_cells_count, + &cdma_cells, + &nr_serving_cells_count, + &nr_serving_cells, + &nr_neighboring_cells_count, + &nr_neighboring_cells, + &error)) + g_prefix_error (&error, "Failed processing MBIMEx v3.0 base stations info response: "); + else + mm_obj_dbg (self, "processed MBIMEx v3.0 base stations info response"); + } + /* MBIMEx 1.0 support */ + else { + if (!mbim_message_ms_basic_connect_extensions_base_stations_info_response_parse ( + response, + NULL, /* system_type */ + &gsm_serving_cell, + &umts_serving_cell, + &tdscdma_serving_cell, + <e_serving_cell, + &gsm_neighboring_cells_count, + &gsm_neighboring_cells, + &umts_neighboring_cells_count, + &umts_neighboring_cells, + &tdscdma_neighboring_cells_count, + &tdscdma_neighboring_cells, + <e_neighboring_cells_count, + <e_neighboring_cells, + &cdma_cells_count, + &cdma_cells, + &error)) + g_prefix_error (&error, "Failed processing MBIMEx v1.0 base stations info response: "); + else + mm_obj_dbg (self, "processed MBIMEx v1.0 base stations info response"); + } + + if (error) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + +#define CELL_INFO_SET_STR(VALUE, SETTER, CELL_TYPE) do { \ + if (VALUE) { \ + mm_cell_info_##SETTER (CELL_TYPE (info), VALUE); \ + } \ + } while (0) + +#define CELL_INFO_SET_HEXSTR(VALUE, UNKNOWN, MODIFIER, SETTER, CELL_TYPE) do { \ + if (VALUE != UNKNOWN) { \ + g_autofree gchar *str = NULL; \ + \ + str = g_strdup_printf ("%" MODIFIER "X", VALUE); \ + mm_cell_info_##SETTER (CELL_TYPE (info), str); \ + } \ + } while (0) + +#define CELL_INFO_SET_UINT(VALUE, UNKNOWN, SETTER, CELL_TYPE) do { \ + if (VALUE != UNKNOWN) { \ + mm_cell_info_##SETTER (CELL_TYPE (info), VALUE); \ + } \ + } while (0) + +#define CELL_INFO_SET_INT_DOUBLE(VALUE, UNKNOWN, SETTER, CELL_TYPE) do { \ + if (VALUE != (gint)UNKNOWN) { \ + mm_cell_info_##SETTER (CELL_TYPE (info), (gdouble)VALUE); \ + } \ + } while (0) + +#define CELL_INFO_SET_UINT_DOUBLE_SCALED(VALUE, UNKNOWN, SCALE, SETTER, CELL_TYPE) do { \ + if (VALUE != UNKNOWN) { \ + mm_cell_info_##SETTER (CELL_TYPE (info), (gdouble)(VALUE + SCALE)); \ + } \ + } while (0) + + if (gsm_serving_cell) { + info = mm_cell_info_gsm_new_from_dictionary (NULL); + mm_cell_info_set_serving (info, TRUE); + + CELL_INFO_SET_STR (gsm_serving_cell->provider_id, gsm_set_operator_id, MM_CELL_INFO_GSM); + CELL_INFO_SET_HEXSTR (gsm_serving_cell->location_area_code, 0xFFFFFFFF, "", gsm_set_lac, MM_CELL_INFO_GSM); + CELL_INFO_SET_HEXSTR (gsm_serving_cell->cell_id, 0xFFFFFFFF, "", gsm_set_ci, MM_CELL_INFO_GSM); + CELL_INFO_SET_UINT (gsm_serving_cell->timing_advance, 0xFFFFFFFF, gsm_set_timing_advance, MM_CELL_INFO_GSM); + CELL_INFO_SET_UINT (gsm_serving_cell->arfcn, 0xFFFFFFFF, gsm_set_arfcn, MM_CELL_INFO_GSM); + CELL_INFO_SET_HEXSTR (gsm_serving_cell->base_station_id, 0xFFFFFFFF, "", gsm_set_base_station_id, MM_CELL_INFO_GSM); + CELL_INFO_SET_UINT (gsm_serving_cell->rx_level, 0xFFFFFFFF, gsm_set_rx_level, MM_CELL_INFO_GSM); + + list = g_list_append (list, g_steal_pointer (&info)); + } + + if (gsm_neighboring_cells_count && gsm_neighboring_cells) { + guint i; + + for (i = 0; i < gsm_neighboring_cells_count; i++) { + info = mm_cell_info_gsm_new_from_dictionary (NULL); + mm_cell_info_set_serving (info, FALSE); + + CELL_INFO_SET_STR (gsm_neighboring_cells[i]->provider_id, gsm_set_operator_id, MM_CELL_INFO_GSM); + CELL_INFO_SET_HEXSTR (gsm_neighboring_cells[i]->location_area_code, 0xFFFFFFFF, "", gsm_set_lac, MM_CELL_INFO_GSM); + CELL_INFO_SET_HEXSTR (gsm_neighboring_cells[i]->cell_id, 0xFFFFFFFF, "", gsm_set_ci, MM_CELL_INFO_GSM); + CELL_INFO_SET_UINT (gsm_neighboring_cells[i]->arfcn, 0xFFFFFFFF, gsm_set_arfcn, MM_CELL_INFO_GSM); + CELL_INFO_SET_HEXSTR (gsm_neighboring_cells[i]->base_station_id, 0xFFFFFFFF, "", gsm_set_base_station_id, MM_CELL_INFO_GSM); + CELL_INFO_SET_UINT (gsm_neighboring_cells[i]->rx_level, 0xFFFFFFFF, gsm_set_rx_level, MM_CELL_INFO_GSM); + + list = g_list_append (list, g_steal_pointer (&info)); + } + } + + if (umts_serving_cell) { + info = mm_cell_info_umts_new_from_dictionary (NULL); + mm_cell_info_set_serving (info, TRUE); + + CELL_INFO_SET_STR (umts_serving_cell->provider_id, umts_set_operator_id, MM_CELL_INFO_UMTS); + CELL_INFO_SET_HEXSTR (umts_serving_cell->location_area_code, 0xFFFFFFFF, "", umts_set_lac, MM_CELL_INFO_UMTS); + CELL_INFO_SET_HEXSTR (umts_serving_cell->cell_id, 0xFFFFFFFF, "", umts_set_ci, MM_CELL_INFO_UMTS); + CELL_INFO_SET_UINT (umts_serving_cell->frequency_info_ul, 0xFFFFFFFF, umts_set_frequency_fdd_ul, MM_CELL_INFO_UMTS); + CELL_INFO_SET_UINT (umts_serving_cell->frequency_info_dl, 0xFFFFFFFF, umts_set_frequency_fdd_dl, MM_CELL_INFO_UMTS); + CELL_INFO_SET_UINT (umts_serving_cell->frequency_info_nt, 0xFFFFFFFF, umts_set_frequency_tdd, MM_CELL_INFO_UMTS); + CELL_INFO_SET_UINT (umts_serving_cell->uarfcn, 0xFFFFFFFF, umts_set_uarfcn, MM_CELL_INFO_UMTS); + CELL_INFO_SET_UINT (umts_serving_cell->primary_scrambling_code, 0xFFFFFFFF, umts_set_psc, MM_CELL_INFO_UMTS); + CELL_INFO_SET_INT_DOUBLE (umts_serving_cell->rscp, 0, umts_set_rscp, MM_CELL_INFO_UMTS); + CELL_INFO_SET_INT_DOUBLE (umts_serving_cell->ecno, 1, umts_set_ecio, MM_CELL_INFO_UMTS); + CELL_INFO_SET_UINT (umts_serving_cell->path_loss, 0xFFFFFFFF, umts_set_path_loss, MM_CELL_INFO_UMTS); + + list = g_list_append (list, g_steal_pointer (&info)); + } + + if (umts_neighboring_cells_count && umts_neighboring_cells) { + guint i; + + for (i = 0; i < umts_neighboring_cells_count; i++) { + info = mm_cell_info_umts_new_from_dictionary (NULL); + mm_cell_info_set_serving (info, FALSE); + + CELL_INFO_SET_STR (umts_neighboring_cells[i]->provider_id, umts_set_operator_id, MM_CELL_INFO_UMTS); + CELL_INFO_SET_HEXSTR (umts_neighboring_cells[i]->location_area_code, 0xFFFFFFFF, "", umts_set_lac, MM_CELL_INFO_UMTS); + CELL_INFO_SET_HEXSTR (umts_neighboring_cells[i]->cell_id, 0xFFFFFFFF, "", umts_set_ci, MM_CELL_INFO_UMTS); + CELL_INFO_SET_UINT (umts_neighboring_cells[i]->uarfcn, 0xFFFFFFFF, umts_set_uarfcn, MM_CELL_INFO_UMTS); + CELL_INFO_SET_UINT (umts_neighboring_cells[i]->primary_scrambling_code, 0xFFFFFFFF, umts_set_psc, MM_CELL_INFO_UMTS); + CELL_INFO_SET_INT_DOUBLE (umts_neighboring_cells[i]->rscp, 0, umts_set_rscp, MM_CELL_INFO_UMTS); + CELL_INFO_SET_INT_DOUBLE (umts_neighboring_cells[i]->ecno, 1, umts_set_ecio, MM_CELL_INFO_UMTS); + CELL_INFO_SET_UINT (umts_neighboring_cells[i]->path_loss, 0xFFFFFFFF, umts_set_path_loss, MM_CELL_INFO_UMTS); + + list = g_list_append (list, g_steal_pointer (&info)); + } + } + + if (tdscdma_serving_cell) { + info = mm_cell_info_tdscdma_new_from_dictionary (NULL); + mm_cell_info_set_serving (info, TRUE); + + CELL_INFO_SET_STR (tdscdma_serving_cell->provider_id, tdscdma_set_operator_id, MM_CELL_INFO_TDSCDMA); + CELL_INFO_SET_HEXSTR (tdscdma_serving_cell->location_area_code, 0xFFFFFFFF, "", tdscdma_set_lac, MM_CELL_INFO_TDSCDMA); + CELL_INFO_SET_HEXSTR (tdscdma_serving_cell->cell_id, 0xFFFFFFFF, "", tdscdma_set_ci, MM_CELL_INFO_TDSCDMA); + CELL_INFO_SET_UINT (tdscdma_serving_cell->uarfcn, 0xFFFFFFFF, tdscdma_set_uarfcn, MM_CELL_INFO_TDSCDMA); + CELL_INFO_SET_UINT (tdscdma_serving_cell->cell_parameter_id, 0xFFFFFFFF, tdscdma_set_cell_parameter_id, MM_CELL_INFO_TDSCDMA); + CELL_INFO_SET_UINT (tdscdma_serving_cell->timing_advance, 0xFFFFFFFF, tdscdma_set_timing_advance, MM_CELL_INFO_TDSCDMA); + CELL_INFO_SET_INT_DOUBLE (tdscdma_serving_cell->rscp, 0xFFFFFFFF, tdscdma_set_rscp, MM_CELL_INFO_TDSCDMA); + CELL_INFO_SET_UINT (tdscdma_serving_cell->path_loss, 0xFFFFFFFF, tdscdma_set_path_loss, MM_CELL_INFO_TDSCDMA); + + list = g_list_append (list, g_steal_pointer (&info)); + } + + if (tdscdma_neighboring_cells_count && tdscdma_neighboring_cells) { + guint i; + + for (i = 0; i < tdscdma_neighboring_cells_count; i++) { + info = mm_cell_info_tdscdma_new_from_dictionary (NULL); + mm_cell_info_set_serving (info, FALSE); + + CELL_INFO_SET_STR (tdscdma_neighboring_cells[i]->provider_id, tdscdma_set_operator_id, MM_CELL_INFO_TDSCDMA); + CELL_INFO_SET_HEXSTR (tdscdma_neighboring_cells[i]->location_area_code, 0xFFFFFFFF, "", tdscdma_set_lac, MM_CELL_INFO_TDSCDMA); + CELL_INFO_SET_HEXSTR (tdscdma_neighboring_cells[i]->cell_id, 0xFFFFFFFF, "", tdscdma_set_ci, MM_CELL_INFO_TDSCDMA); + CELL_INFO_SET_UINT (tdscdma_neighboring_cells[i]->uarfcn, 0xFFFFFFFF, tdscdma_set_uarfcn, MM_CELL_INFO_TDSCDMA); + CELL_INFO_SET_UINT (tdscdma_neighboring_cells[i]->cell_parameter_id, 0xFFFFFFFF, tdscdma_set_cell_parameter_id, MM_CELL_INFO_TDSCDMA); + CELL_INFO_SET_UINT (tdscdma_neighboring_cells[i]->timing_advance, 0xFFFFFFFF, tdscdma_set_timing_advance, MM_CELL_INFO_TDSCDMA); + CELL_INFO_SET_INT_DOUBLE (tdscdma_neighboring_cells[i]->rscp, 0xFFFFFFFF, tdscdma_set_rscp, MM_CELL_INFO_TDSCDMA); + CELL_INFO_SET_UINT (tdscdma_neighboring_cells[i]->path_loss, 0xFFFFFFFF, tdscdma_set_path_loss, MM_CELL_INFO_TDSCDMA); + + list = g_list_append (list, g_steal_pointer (&info)); + } + } + + if (lte_serving_cell) { + info = mm_cell_info_lte_new_from_dictionary (NULL); + mm_cell_info_set_serving (info, TRUE); + + CELL_INFO_SET_STR (lte_serving_cell->provider_id, lte_set_operator_id, MM_CELL_INFO_LTE); + CELL_INFO_SET_HEXSTR (lte_serving_cell->tac, 0xFFFFFFFF, "", lte_set_tac, MM_CELL_INFO_LTE); + CELL_INFO_SET_HEXSTR (lte_serving_cell->cell_id, 0xFFFFFFFF, "", lte_set_ci, MM_CELL_INFO_LTE); + CELL_INFO_SET_HEXSTR (lte_serving_cell->physical_cell_id, 0xFFFFFFFF, "", lte_set_physical_ci, MM_CELL_INFO_LTE); + CELL_INFO_SET_UINT (lte_serving_cell->earfcn, 0xFFFFFFFF, lte_set_earfcn, MM_CELL_INFO_LTE); + CELL_INFO_SET_INT_DOUBLE (lte_serving_cell->rsrp, 0xFFFFFFFF, lte_set_rsrp, MM_CELL_INFO_LTE); + CELL_INFO_SET_INT_DOUBLE (lte_serving_cell->rsrq, 0xFFFFFFFF, lte_set_rsrq, MM_CELL_INFO_LTE); + CELL_INFO_SET_UINT (lte_serving_cell->timing_advance, 0xFFFFFFFF, lte_set_timing_advance, MM_CELL_INFO_LTE); + + list = g_list_append (list, g_steal_pointer (&info)); + } + + if (lte_neighboring_cells_count && lte_neighboring_cells) { + guint i; + + for (i = 0; i < lte_neighboring_cells_count; i++) { + info = mm_cell_info_lte_new_from_dictionary (NULL); + mm_cell_info_set_serving (info, FALSE); + + CELL_INFO_SET_STR (lte_neighboring_cells[i]->provider_id, lte_set_operator_id, MM_CELL_INFO_LTE); + CELL_INFO_SET_HEXSTR (lte_neighboring_cells[i]->tac, 0xFFFFFFFF, "", lte_set_tac, MM_CELL_INFO_LTE); + CELL_INFO_SET_HEXSTR (lte_neighboring_cells[i]->cell_id, 0xFFFFFFFF, "", lte_set_ci, MM_CELL_INFO_LTE); + CELL_INFO_SET_HEXSTR (lte_neighboring_cells[i]->physical_cell_id, 0xFFFFFFFF, "", lte_set_physical_ci, MM_CELL_INFO_LTE); + CELL_INFO_SET_UINT (lte_neighboring_cells[i]->earfcn, 0xFFFFFFFF, lte_set_earfcn, MM_CELL_INFO_LTE); + CELL_INFO_SET_INT_DOUBLE (lte_neighboring_cells[i]->rsrp, 0xFFFFFFFF, lte_set_rsrp, MM_CELL_INFO_LTE); + CELL_INFO_SET_INT_DOUBLE (lte_neighboring_cells[i]->rsrq, 0xFFFFFFFF, lte_set_rsrq, MM_CELL_INFO_LTE); + + list = g_list_append (list, g_steal_pointer (&info)); + } + } + + if (cdma_cells_count && cdma_cells) { + guint i; + + for (i = 0; i < cdma_cells_count; i++) { + info = mm_cell_info_cdma_new_from_dictionary (NULL); + mm_cell_info_set_serving (info, cdma_cells[i]->serving_cell_flag); + + CELL_INFO_SET_HEXSTR (cdma_cells[i]->nid, 0xFFFFFFFF, "", cdma_set_nid, MM_CELL_INFO_CDMA); + CELL_INFO_SET_HEXSTR (cdma_cells[i]->sid, 0xFFFFFFFF, "", cdma_set_sid, MM_CELL_INFO_CDMA); + CELL_INFO_SET_HEXSTR (cdma_cells[i]->base_station_id, 0xFFFFFFFF, "", cdma_set_base_station_id, MM_CELL_INFO_CDMA); + CELL_INFO_SET_HEXSTR (cdma_cells[i]->ref_pn, 0xFFFFFFFF, "", cdma_set_ref_pn, MM_CELL_INFO_CDMA); + CELL_INFO_SET_UINT (cdma_cells[i]->pilot_strength, 0xFFFFFFFF, cdma_set_pilot_strength, MM_CELL_INFO_CDMA); + + list = g_list_append (list, g_steal_pointer (&info)); + } + } + + if (nr_serving_cells_count && nr_serving_cells) { + guint i; + + for (i = 0; i < nr_serving_cells_count; i++) { + info = mm_cell_info_nr5g_new_from_dictionary (NULL); + mm_cell_info_set_serving (info, TRUE); + + CELL_INFO_SET_STR (nr_serving_cells[i]->provider_id, nr5g_set_operator_id, MM_CELL_INFO_NR5G); + CELL_INFO_SET_HEXSTR (nr_serving_cells[i]->tac, 0xFFFFFFFF, "", nr5g_set_tac, MM_CELL_INFO_NR5G); + CELL_INFO_SET_HEXSTR (nr_serving_cells[i]->nci, 0xFFFFFFFFFFFFFFFF, G_GINT64_MODIFIER, nr5g_set_ci, MM_CELL_INFO_NR5G); + CELL_INFO_SET_HEXSTR (nr_serving_cells[i]->physical_cell_id, 0xFFFFFFFF, "", nr5g_set_physical_ci, MM_CELL_INFO_NR5G); + CELL_INFO_SET_UINT (nr_serving_cells[i]->nrarfcn, 0xFFFFFFFF, nr5g_set_nrarfcn, MM_CELL_INFO_NR5G); + CELL_INFO_SET_UINT_DOUBLE_SCALED (nr_serving_cells[i]->rsrp, 0xFFFFFFFF, -156, nr5g_set_rsrp, MM_CELL_INFO_NR5G); + CELL_INFO_SET_UINT_DOUBLE_SCALED (nr_serving_cells[i]->rsrq, 0xFFFFFFFF, -43, nr5g_set_rsrq, MM_CELL_INFO_NR5G); + CELL_INFO_SET_UINT_DOUBLE_SCALED (nr_serving_cells[i]->sinr, 0xFFFFFFFF, -23, nr5g_set_sinr, MM_CELL_INFO_NR5G); + CELL_INFO_SET_UINT (nr_serving_cells[i]->timing_advance, 0xFFFFFFFFFFFFFFFF, nr5g_set_timing_advance, MM_CELL_INFO_NR5G); + + list = g_list_append (list, g_steal_pointer (&info)); + } + } + + if (nr_neighboring_cells_count && nr_neighboring_cells) { + guint i; + + for (i = 0; i < nr_neighboring_cells_count; i++) { + info = mm_cell_info_nr5g_new_from_dictionary (NULL); + mm_cell_info_set_serving (info, FALSE); + + CELL_INFO_SET_STR (nr_neighboring_cells[i]->provider_id, nr5g_set_operator_id, MM_CELL_INFO_NR5G); + CELL_INFO_SET_HEXSTR (nr_neighboring_cells[i]->tac, 0xFFFFFFFF, "", nr5g_set_tac, MM_CELL_INFO_NR5G); + CELL_INFO_SET_STR (nr_neighboring_cells[i]->cell_id, nr5g_set_ci, MM_CELL_INFO_NR5G); + CELL_INFO_SET_HEXSTR (nr_neighboring_cells[i]->physical_cell_id, 0xFFFFFFFF, "", nr5g_set_physical_ci, MM_CELL_INFO_NR5G); + CELL_INFO_SET_UINT_DOUBLE_SCALED (nr_neighboring_cells[i]->rsrp, 0xFFFFFFFF, -156, nr5g_set_rsrp, MM_CELL_INFO_NR5G); + CELL_INFO_SET_UINT_DOUBLE_SCALED (nr_neighboring_cells[i]->rsrq, 0xFFFFFFFF, -43, nr5g_set_rsrq, MM_CELL_INFO_NR5G); + CELL_INFO_SET_UINT_DOUBLE_SCALED (nr_neighboring_cells[i]->sinr, 0xFFFFFFFF, -23, nr5g_set_sinr, MM_CELL_INFO_NR5G); + + list = g_list_append (list, g_steal_pointer (&info)); + } + } + +#undef CELL_INFO_SET_STR +#undef CELL_INFO_SET_HEXSTR +#undef CELL_INFO_SET_UINT +#undef CELL_INFO_SET_INT_DOUBLE +#undef CELL_INFO_SET_UINT_DOUBLE_SCALED + + g_task_return_pointer (task, list, (GDestroyNotify)cell_info_list_free); + g_object_unref (task); +} + +static void +modem_get_cell_info (MMIfaceModem *_self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self); + GTask *task; + MbimDevice *device; + MbimMessage *message; + + if (!peek_device (self, &device, callback, user_data)) + return; + + task = g_task_new (self, NULL, callback, user_data); + + if (!self->priv->is_base_stations_info_supported) { + g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, + "base stations info is not supported"); + g_object_unref (task); + return; + } + + /* Default capacity is 15 */ + if (mbim_device_check_ms_mbimex_version (device, 3, 0)) + message = mbim_message_ms_basic_connect_extensions_v3_base_stations_info_query_new (15, 15, 15, 15, 15, 15, NULL); + else + message = mbim_message_ms_basic_connect_extensions_base_stations_info_query_new (15, 15, 15, 15, 15, NULL); + + mbim_device_command (device, + message, + 300, + NULL, + (GAsyncReadyCallback)base_stations_info_query_ready, + task); +} + +/*****************************************************************************/ /* Create Bearer (Modem interface) */ static MMBaseBearer * @@ -2635,6 +3030,9 @@ query_device_services_ready (MbimDevice *device, } else if (device_services[i]->cids[j] == MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_REGISTRATION_PARAMETERS) { mm_obj_dbg (self, "5GNR registration settings are supported"); self->priv->is_nr5g_registration_settings_supported = TRUE; + } else if (device_services[i]->cids[j] == MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_BASE_STATIONS_INFO) { + mm_obj_dbg (self, "Base stations info is supported"); + self->priv->is_base_stations_info_supported = TRUE; } else if (device_services[i]->cids[j] == MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_PROVISIONED_CONTEXTS) { if (mm_context_get_test_mbimex_profile_management ()) { mm_obj_dbg (self, "Profile management extension is supported"); @@ -8675,6 +9073,8 @@ iface_modem_init (MMIfaceModem *iface) /* Additional actions */ iface->load_signal_quality = modem_load_signal_quality; iface->load_signal_quality_finish = modem_load_signal_quality_finish; + iface->get_cell_info = modem_get_cell_info; + iface->get_cell_info_finish = modem_get_cell_info_finish; /* Unneeded things */ iface->modem_after_power_up = NULL; |