diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-broadband-modem-mbim.c | 250 | ||||
-rw-r--r-- | src/mm-modem-helpers-mbim.c | 171 | ||||
-rw-r--r-- | src/mm-modem-helpers-mbim.h | 30 |
3 files changed, 403 insertions, 48 deletions
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c index 718975c0..a255b588 100644 --- a/src/mm-broadband-modem-mbim.c +++ b/src/mm-broadband-modem-mbim.c @@ -20,6 +20,7 @@ #include <string.h> #include <unistd.h> #include <ctype.h> +#include <math.h> #include "mm-modem-helpers-mbim.h" #include "mm-broadband-modem-mbim.h" @@ -2323,9 +2324,34 @@ modem_reset (MMIfaceModem *_self, /*****************************************************************************/ /* Cell info retrieval */ +typedef enum { + GET_CELL_INFO_STEP_FIRST, + GET_CELL_INFO_STEP_RFIM, + GET_CELL_INFO_STEP_CELL_INFO, + GET_CELL_INFO_STEP_LAST +} GetCellInfoStep; + +typedef struct { + GetCellInfoStep step; + GList *rfim_info_list; + GList *cell_info_list; + GError *saved_error; +} GetCellInfoContext; + +static void +get_cell_info_context_free (GetCellInfoContext *ctx) +{ + mm_rfim_info_list_free (ctx->rfim_info_list); + g_assert (!ctx->saved_error); + g_free (ctx); +} + +static void get_cell_info_step (MbimDevice *device, + GTask *task); + static GList * -modem_get_cell_info_finish (MMIfaceModem *self, - GAsyncResult *res, +modem_get_cell_info_finish (MMIfaceModem *self, + GAsyncResult *res, GError **error) { return g_task_propagate_pointer (G_TASK (res), error); @@ -2365,13 +2391,16 @@ base_stations_info_query_ready (MbimDevice *device, g_autoptr(MbimCellInfoServingNrArray) nr_serving_cells = NULL; guint32 nr_neighboring_cells_count = 0; g_autoptr(MbimCellInfoNeighboringNrArray) nr_neighboring_cells = NULL; + GetCellInfoContext *ctx; self = g_task_get_source_object (task); + ctx = g_task_get_task_data (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); + ctx->saved_error = error; + ctx->step = GET_CELL_INFO_STEP_LAST; + get_cell_info_step (device, task); return; } @@ -2430,8 +2459,9 @@ base_stations_info_query_ready (MbimDevice *device, } if (error) { - g_task_return_error (task, error); - g_object_unref (task); + ctx->saved_error = error; + ctx->step = GET_CELL_INFO_STEP_LAST; + get_cell_info_step (device, task); return; } @@ -2577,18 +2607,33 @@ base_stations_info_query_ready (MbimDevice *device, } if (lte_serving_cell) { + GList *l; + 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); - + 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); + + /* Update cell info with the radio frequency information received previously */ + for (l = ctx->rfim_info_list; l; l = g_list_next (l)) { + MMRfInfo *data; + + data = (MMRfInfo *)(l->data); + if (fabs ((mm_get_downlink_carrier_frequency (lte_serving_cell->earfcn, self)) - data->center_frequency) < FREQUENCY_TOLERENCE) { + mm_obj_dbg (self, "Merging radio frequency data with lte serving cell info"); + CELL_INFO_SET_UINT (data->serving_cell_type, MM_SERVING_CELL_TYPE_INVALID, lte_set_serving_cell_type, MM_CELL_INFO_LTE); + CELL_INFO_SET_UINT (data->bandwidth, 0xFFFFFFFF, lte_set_bandwidth, MM_CELL_INFO_LTE); + ctx->rfim_info_list = g_list_delete_link (ctx->rfim_info_list, l); + mm_rf_info_free (data); + } + } list = g_list_append (list, g_steal_pointer (&info)); } @@ -2632,19 +2677,35 @@ base_stations_info_query_ready (MbimDevice *device, guint i; for (i = 0; i < nr_serving_cells_count; i++) { + GList *l; + 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); - + 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); + + /* Update cell info with the radio frequency information received previously */ + for (l = ctx->rfim_info_list; l; l = g_list_next (l)) { + MMRfInfo *data; + + data = (MMRfInfo *)(l->data); + /* Comparing the derived frequncy value from NRARFCN with received center frequency data to map the NR CELL */ + if (fabs ((mm_get_frequency_from_nrarfcn (nr_serving_cells[i]->nrarfcn, self) * HERTZ_CONV) - data->center_frequency) < FREQUENCY_TOLERENCE) { + mm_obj_dbg (self, "Merging radio frequency data with 5gnr serving cell info"); + CELL_INFO_SET_UINT (data->serving_cell_type, MM_SERVING_CELL_TYPE_INVALID, nr5g_set_serving_cell_type, MM_CELL_INFO_NR5G); + CELL_INFO_SET_UINT (data->bandwidth, 0xFFFFFFFF, nr5g_set_bandwidth, MM_CELL_INFO_NR5G); + ctx->rfim_info_list = g_list_delete_link (ctx->rfim_info_list, l); + mm_rf_info_free (data); + } + } list = g_list_append (list, g_steal_pointer (&info)); } } @@ -2674,44 +2735,137 @@ base_stations_info_query_ready (MbimDevice *device, #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); + ctx->cell_info_list = list; + ctx->step++; + get_cell_info_step (device, task); } static void -modem_get_cell_info (MMIfaceModem *_self, - GAsyncReadyCallback callback, - gpointer user_data) +check_rfim_query_ready (MbimDevice *device, + GAsyncResult *res, + GTask *task) { - MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self); - GTask *task; - MbimDevice *device; - MbimMessage *message; + g_autoptr(MbimMessage) response = NULL; + MbimIntelRfimFrequencyValueArray *freq_info; + guint freq_count; + GetCellInfoContext *ctx; + MMBroadbandModemMbim *self; - if (!peek_device (self, &device, callback, user_data)) - return; + self = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); - task = g_task_new (self, NULL, callback, user_data); + response = mbim_device_command_finish (device, res, NULL); + if (response && + mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, NULL) && + mbim_message_intel_thermal_rf_rfim_response_parse (response, + &freq_count, + &freq_info, + NULL)) { + + ctx->rfim_info_list = mm_rfim_info_list_from_mbim_intel_rfim_frequency_value_array (freq_info, + freq_count, + self); + mbim_intel_rfim_frequency_value_array_free (freq_info); + } else { + mm_obj_dbg (self, "Fetching of bandwidth and serving cell type data failed"); + } + ctx->step++; + get_cell_info_step (device, task); +} + +static void +get_cell_info_step (MbimDevice *device, + GTask *task) +{ + MMBroadbandModemMbim *self; + GetCellInfoContext *ctx; + g_autoptr(MbimMessage) message = NULL; + + self = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); + /* Don't run new steps if we're cancelled */ + if (g_task_return_error_if_cancelled (task)) { + g_object_unref (task); + return; + } + + switch (ctx->step) { + case GET_CELL_INFO_STEP_FIRST: 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; } + ctx->step++; - /* 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); + /* fall through */ + case GET_CELL_INFO_STEP_RFIM: { + mm_obj_dbg (self, "Obtaining RFIM data..."); + message = mbim_message_intel_thermal_rf_rfim_query_new (NULL); + mbim_device_command (device, + message, + 10, + NULL, + (GAsyncReadyCallback)check_rfim_query_ready, + task); + return; + } - mbim_device_command (device, - message, - 300, - NULL, - (GAsyncReadyCallback)base_stations_info_query_ready, - task); + case GET_CELL_INFO_STEP_CELL_INFO: { + mm_obj_dbg (self, "Obtaining cell info..."); + /* 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); + return; + } + + case GET_CELL_INFO_STEP_LAST: + if (ctx->saved_error) + g_task_return_error (task, g_steal_pointer (&ctx->saved_error)); + else if (ctx->cell_info_list) + g_task_return_pointer (task, ctx->cell_info_list, (GDestroyNotify)cell_info_list_free); + else + g_assert_not_reached (); + g_object_unref (task); + return; + + default: + break; + } + + g_assert_not_reached (); +} + + +static void +modem_get_cell_info (MMIfaceModem *_self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self); + MbimDevice *device; + GTask *task; + GetCellInfoContext *ctx; + + if (!peek_device (self, &device, callback, user_data)) + return; + + task = g_task_new (self, NULL, callback, user_data); + ctx = g_new0 (GetCellInfoContext, 1); + ctx->step = GET_CELL_INFO_STEP_FIRST; + g_task_set_task_data (task, ctx, (GDestroyNotify)get_cell_info_context_free); + get_cell_info_step (device, task); } /*****************************************************************************/ diff --git a/src/mm-modem-helpers-mbim.c b/src/mm-modem-helpers-mbim.c index 47776be9..9a903b5d 100644 --- a/src/mm-modem-helpers-mbim.c +++ b/src/mm-modem-helpers-mbim.c @@ -1229,3 +1229,174 @@ mm_signal_from_mbim_signal_state (MbimDataClass data_class, return TRUE; } + +/*****************************************************************************/ + +void +mm_rf_info_free (MMRfInfo *rf_data) +{ + g_free(rf_data); +} + +void +mm_rfim_info_list_free (GList *rfim_info_list) +{ + g_list_free_full (rfim_info_list, (GDestroyNotify) g_free); +} + +GList * +mm_rfim_info_list_from_mbim_intel_rfim_frequency_value_array (MbimIntelRfimFrequencyValueArray *freq_info, + guint freq_count, + gpointer log_object) +{ + GList *info_list = NULL; + guint i; + + g_return_val_if_fail (freq_info != NULL, NULL); + + for (i = 0; i < freq_count; i++) { + MMRfInfo* info; + + /* If Cell info value indicates radio off, then other parameters are invalid. + * So those data will be ignored. */ + if (freq_info[i]->serving_cell_info != MBIM_INTEL_SERVING_CELL_INFO_RADIO_OFF) { + info = g_new0 (MMRfInfo, 1); + info->serving_cell_type = MM_SERVING_CELL_TYPE_UNKNOWN; + switch (freq_info[i]->serving_cell_info) { + case MBIM_INTEL_SERVING_CELL_INFO_PCELL: + info->serving_cell_type = MM_SERVING_CELL_TYPE_PCELL; + break; + case MBIM_INTEL_SERVING_CELL_INFO_SCELL: + info->serving_cell_type = MM_SERVING_CELL_TYPE_SCELL; + break; + case MBIM_INTEL_SERVING_CELL_INFO_PSCELL: + info->serving_cell_type = MM_SERVING_CELL_TYPE_PSCELL; + break; + case MBIM_INTEL_SERVING_CELL_INFO_SSCELL: + info->serving_cell_type = MM_SERVING_CELL_TYPE_SSCELL; + break; + case MBIM_INTEL_SERVING_CELL_INFO_RADIO_OFF: + default: + info->serving_cell_type = MM_SERVING_CELL_TYPE_INVALID; + } + info->bandwidth = freq_info[i]->bandwidth; + info->center_frequency = freq_info[i]->center_frequency; + info_list = g_list_append (info_list, info); + } else + mm_obj_dbg (log_object, "Ignoring radio frequency information due to cell radio off"); + } + + return info_list; +} + +typedef struct LteDlRangeData { + guint8 band; + gdouble fdl_low; + guint32 n_offs_dl; + guint32 range_dl1; + guint32 range_dl2; +} LteDlRangeData; + +static LteDlRangeData lte_dl_range_data [] = { + { 1, 2110, 0, 0, 599}, + { 2, 1930, 600, 600, 1199}, + { 3, 1805, 1200, 1200, 1949}, + { 4, 2110, 1950, 1950, 2399}, + { 5, 869, 2400, 2400, 2649}, + { 6, 875, 2650, 2650, 2749}, + { 7, 2620, 2750, 2750, 3449}, + { 8, 925, 3450, 3450, 3799}, + { 9, 1844.9, 3800, 3800, 4149}, + { 10, 2110, 4150, 4150, 4749}, + { 11, 1475.9, 4750, 4750, 4949}, + { 12, 728, 5000, 5000, 5179}, + { 13, 746, 5180, 5180, 5279}, + { 14, 758, 5280, 5280, 5379}, + { 17, 734, 5730, 5730, 5849}, + { 18, 860, 5850, 5850, 5999}, + { 19, 875, 6000, 6000, 6149}, + { 20, 791, 6150, 6150, 6449}, + { 21, 1495.9, 6450, 6450, 6599}, + { 33, 1900, 36000, 36000, 36199}, + { 34, 2010, 36200, 36200, 36349}, + { 35, 1850, 36350, 36350, 36949}, + { 36, 1930, 36950, 36950, 37549}, + { 37, 1910, 37550, 37550, 37749}, + { 38, 2570, 37750, 37750, 38249}, + { 39, 1880, 38250, 38250, 38649}, + { 40, 2300, 38650, 38650, 39649} +}; + +#define NUM_EUTRA_BANDS (sizeof (lte_dl_range_data) / sizeof (LteDlRangeData)) + +static guint8 +mm_get_downlink_carrier_band (guint32 earfcn, + gpointer log_object) +{ + guint8 i; + + for (i = 0; i < NUM_EUTRA_BANDS; ++i) { + if (lte_dl_range_data[i].range_dl1 <= earfcn && lte_dl_range_data[i].range_dl2 >= earfcn) { + mm_obj_dbg (log_object, "Found matching band: %d for earfcn: %d" , i, earfcn); + return i; + } + } + mm_obj_dbg (log_object, "invalid earfcn: %d ", earfcn); + return NUM_EUTRA_BANDS; +} + +gdouble +mm_get_downlink_carrier_frequency (guint32 earfcn, + gpointer log_object) +{ + guint8 i; + + i = mm_get_downlink_carrier_band (earfcn,log_object); + if (i == NUM_EUTRA_BANDS) + return 0.0; + return 1.0e6 * (lte_dl_range_data[i].fdl_low + 0.1 * (earfcn - lte_dl_range_data[i].n_offs_dl)); +} + +typedef struct NrRangeData { + guint global_khz; + guint range_offset; + guint nrarfcn_offset; + guint range_first; + guint range_last; +} NrRangeData ; + +static NrRangeData nr_range_data [] = { + { 5, 0, 0, 0, 599999}, + { 15, 3000000, 600000, 600000, 2016666}, + { 60, 24250080, 2016667, 2016667, 3279165} +}; + +#define NUM_NR_RANGE_DATA (sizeof (nr_range_data) / sizeof (NrRangeData)) + +static guint8 +mm_get_nr_range_data (guint32 nrarfcn, + gpointer log_object) +{ + guint8 i; + + for (i = 0; i < NUM_NR_RANGE_DATA; ++i) { + if (nr_range_data[i].range_first <= nrarfcn && nr_range_data[i].range_last >= nrarfcn) { + mm_obj_dbg (log_object, "Found matching NR range: %d for nrarfcn: %d" , i, nrarfcn); + return i; + } + } + mm_obj_dbg (log_object, "invalid nrarfcn: %d ", nrarfcn); + return NUM_NR_RANGE_DATA; +} + +gdouble +mm_get_frequency_from_nrarfcn (guint32 nrarfcn, + gpointer log_object) +{ + guint8 i; + + i = mm_get_nr_range_data (nrarfcn,log_object); + if (i == NUM_NR_RANGE_DATA) + return 0.0; + return nr_range_data[i].range_offset + nr_range_data[i].global_khz * (nrarfcn - nr_range_data[i].nrarfcn_offset); +} diff --git a/src/mm-modem-helpers-mbim.h b/src/mm-modem-helpers-mbim.h index ee0a3745..5fdb60fe 100644 --- a/src/mm-modem-helpers-mbim.h +++ b/src/mm-modem-helpers-mbim.h @@ -143,4 +143,34 @@ gboolean mm_signal_from_mbim_signal_state (MbimDataClass data_class, MMSignal **out_lte, MMSignal **out_nr5g); +/*****************************************************************************/ +/* RF utilities */ +/*****************************************************************************/ + +/* Value defined to allow tolerence in the center frequency comparison logic */ +#define FREQUENCY_TOLERENCE 300 + +/* Value used to convert KHz value to Hz */ +#define HERTZ_CONV 1000 + +typedef struct { + MMServingCellType serving_cell_type; + guint32 bandwidth; + guint64 center_frequency; +} MMRfInfo; + +void mm_rf_info_free (MMRfInfo *rf_data); + +void mm_rfim_info_list_free (GList *rfim_info_list); + +GList *mm_rfim_info_list_from_mbim_intel_rfim_frequency_value_array (MbimIntelRfimFrequencyValueArray *freq_info, + guint freq_count, + gpointer log_object); + +gdouble mm_get_downlink_carrier_frequency (guint32 earfcn, + gpointer log_object); + +gdouble mm_get_frequency_from_nrarfcn (guint32 nrarfcn, + gpointer log_object); + #endif /* MM_MODEM_HELPERS_MBIM_H */ |