From d8135be6e2c132e59d3fbe9d231afa88b1e5e2b2 Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Sat, 22 Feb 2025 17:17:32 +0100 Subject: modem-helpers: Add helpers to parse channel lists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `CSCB` has the form ``` CSCB: [0|1],"","" ``` If the first parameter is `0` this specifies the accepted types if `1` it specifies rejected. So far seen in the wild were CSCB strings with accepted types only and a coding scheme of "" so this is what we handle for the moment. Signed-off-by: Guido Günther --- src/mm-modem-helpers.c | 136 +++++++++++++++++++++++++++++++++++++++++ src/mm-modem-helpers.h | 5 ++ src/tests/test-modem-helpers.c | 96 +++++++++++++++++++++++++++++ 3 files changed, 237 insertions(+) (limited to 'src') diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c index 772a2de8..4f0c6248 100644 --- a/src/mm-modem-helpers.c +++ b/src/mm-modem-helpers.c @@ -2936,6 +2936,110 @@ out: return TRUE; } +/*************************************************************************/ + +#define CBS_MAX_CHANNEL G_MAXUINT16 + +GArray * +mm_3gpp_parse_cscb_response (const char *response, GError **error) +{ + g_autoptr(GRegex) r = NULL; + g_autoptr(GMatchInfo) match_info = NULL; + GError *inner_error = NULL; + gsize len; + g_autoptr (GArray) array = g_array_new (FALSE, FALSE, sizeof (MMCellBroadcastChannels)); + g_autofree char *str = NULL; + g_auto (GStrv) intervals = NULL; + int i; + + len = strlen (response); + if (!len) { + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, "empty channel list"); + goto out; + } + + /* + * AT+CSCB=[0|1],"","" + */ + r = g_regex_new ("\\+CSCB:\\s*" + "(\\d),\\s*" /* [0|1] */ + "\"([\\d,\\-]*)\"," /* channel list */ + "\"\"", /* encodings */ + G_REGEX_NEWLINE_CRLF, + 0, + NULL); + g_assert (r != NULL); + + g_regex_match_full (r, response, -1, 0, 0, &match_info, &inner_error); + if (inner_error) + goto out; + + if (!g_match_info_matches (match_info)) { + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't match CSCB response"); + goto out; + } + + str = g_match_info_fetch (match_info, 1); + if (!g_str_equal (str, "0")) { + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Couldn't match type of CSCB response: '%s'", str); + goto out; + } + + str = g_match_info_fetch (match_info, 2); + intervals = g_strsplit (str, ",", -1); + for (i = 0; intervals[i]; i++) { + gchar *interval_separator; + + g_strstrip (intervals[i]); + interval_separator = strstr (intervals[i], "-"); + if (interval_separator) { + /* Add an interval */ + gchar *end; + g_autofree gchar *start = NULL; + MMCellBroadcastChannels channels; + + start = g_strdup (intervals[i]); + interval_separator = strstr (start, "-"); + *(interval_separator++) = '\0'; + end = interval_separator; + + if (mm_get_uint_from_str (start, &channels.start) && + mm_get_uint_from_str (end, &channels.end) && + channels.start <= channels.end && + channels.end <= CBS_MAX_CHANNEL) + g_array_append_val (array, channels); + else { + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Couldn't parse CSCB interval '%s'", intervals[i]); + goto out; + } + } else { + guint channel; + + /* Add single value */ + if (mm_get_uint_from_str (intervals[i], &channel)) { + MMCellBroadcastChannels channels = { + .start = channel, + .end = channel + }; + g_array_append_val (array, channels); + } else { + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Couldn't parse CSCB value '%s'", intervals[i]); + goto out; + } + } + } + + return g_steal_pointer (&array); + + out: + g_assert (inner_error); + g_propagate_error (error, inner_error); + return NULL; +} + /*************************************************************************/ /* CGATT helpers */ @@ -5200,6 +5304,38 @@ out: /*****************************************************************************/ +gboolean +mm_validate_cbs_channels (GArray *channels, GError **error) +{ + guint i; + + for (i = 0; i < channels->len; i++) { + MMCellBroadcastChannels ch = g_array_index (channels, MMCellBroadcastChannels, i); + + if (ch.end < ch.start) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, + "Invalid channels: End channel smaller than start channel"); + return FALSE; + } + + if (ch.start > CBS_MAX_CHANNEL) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, + "Invalid channels: Start channel %u too large", ch.start); + return FALSE; + } + + if (ch.end > CBS_MAX_CHANNEL) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, + "Invalid channels: End channel %u too large", ch.end); + return FALSE; + } + } + + return TRUE; +} + +/*****************************************************************************/ + gboolean mm_sim_parse_cpol_query_response (const gchar *response, guint *out_index, diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h index f4b2ae8b..133c7006 100644 --- a/src/mm-modem-helpers.h +++ b/src/mm-modem-helpers.h @@ -418,6 +418,8 @@ gboolean mm_3gpp_parse_ccwa_service_query_response (const gchar *response, gboolean *status, GError **error); +GArray *mm_3gpp_parse_cscb_response (const char *raw, GError **error); + /* CGATT helpers */ gchar *mm_3gpp_build_cgatt_set_request (MMModem3gppPacketServiceState state); @@ -550,6 +552,9 @@ gboolean mm_parse_supl_address (const gchar *supl, guint16 *out_port, GError **error); +gboolean mm_validate_cbs_channels (GArray *channels, + GError **error); + /*****************************************************************************/ /* SIM specific helpers and utilities */ /*****************************************************************************/ diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c index 538aedfe..6692e56d 100644 --- a/src/tests/test-modem-helpers.c +++ b/src/tests/test-modem-helpers.c @@ -4277,6 +4277,100 @@ test_ccwa_response (void) common_test_ccwa_response (test_ccwa[i].response, test_ccwa[i].expected_status, test_ccwa[i].expected_error); } +/*****************************************************************************/ +/* Test +CSCB channel lists */ + +typedef struct { + const gchar *response; + const MMCellBroadcastChannels *channels; + guint len; + gboolean error; +} TestCscb; + +static void +common_test_cscb_response (const gchar *response, TestCscb *expected) +{ + GError *error = NULL; + GArray *result; + + g_debug ("Testing '%s'", response); + result = mm_3gpp_parse_cscb_response (response, &error); + + if (expected->error) { + g_assert (!result); + g_assert_nonnull (error); + g_error_free (error); + } else { + guint i; + + g_assert_no_error (error); + g_assert (result); + g_assert_cmpint (result->len, ==, expected->len); + for (i = 0; i < expected->len; i++) { + MMCellBroadcastChannels ch = g_array_index (result, MMCellBroadcastChannels, i); + + g_assert_cmpuint (ch.start, ==, expected->channels[i].start); + g_assert_cmpuint (ch.end, ==, expected->channels[i].end); + } + } +} + +static const MMCellBroadcastChannels cscb_one_channel[] = { + { .start = 0, .end = 0 }, +}; + +static const MMCellBroadcastChannels cscb_all_channels[] = { + { .start = 0, .end = 65535 }, +}; + +static const MMCellBroadcastChannels cscb_interval_channels[] = { + { .start = 0, .end = 1 }, + { .start = 100, .end = 200 }, +}; + +static const MMCellBroadcastChannels cscb_dell5821e_channels[] = { + { .start = 4383, .end = 4383 }, + { .start = 4400, .end = 4400 }, + { .start = 4370, .end = 4370 }, + { .start = 4371, .end = 4378 }, + { .start = 4384, .end = 4391 }, + { .start = 4396, .end = 4397 }, +}; + +static TestCscb test_cscb[] = { + { "\r\n+CSCB: 0, \"0\",\"\"\r\n\r\nOK\r\n", /* one channel */ + cscb_one_channel, + G_N_ELEMENTS (cscb_all_channels), + FALSE }, + { "+CSCB: 0,\"0-65535\",\"\"\r\n", /* all channels */ + cscb_all_channels, + G_N_ELEMENTS (cscb_all_channels), + FALSE }, + { "+CSCB: 0,\"0-1,100-200\",\"\"\r\n", /* intervals */ + cscb_interval_channels, + G_N_ELEMENTS (cscb_interval_channels), + FALSE }, + /* Dell 5821e/T77W968 defaults */ + { "+CSCB: 0, \"4383,4400,4370,4371-4378,4384-4391,4396-4397\",\"\"", + cscb_dell5821e_channels, + G_N_ELEMENTS (cscb_dell5821e_channels), + FALSE }, + { "+CSCB: 0,\"0-\",\"\"\r\n", /* broken interval */ + NULL, + 0, + TRUE }, +}; + +static void +test_cscb_response (void) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (test_cscb); i++) + common_test_cscb_response (test_cscb[i].response, &test_cscb[i]); +} + + /*****************************************************************************/ /* Test +CLCC URCs */ @@ -4994,6 +5088,8 @@ int main (int argc, char **argv) g_test_suite_add (suite, TESTCASE (test_ccwa_indication, NULL)); g_test_suite_add (suite, TESTCASE (test_ccwa_response, NULL)); + g_test_suite_add (suite, TESTCASE (test_cscb_response, NULL)); + g_test_suite_add (suite, TESTCASE (test_clcc_response_empty, NULL)); g_test_suite_add (suite, TESTCASE (test_clcc_response_single, NULL)); g_test_suite_add (suite, TESTCASE (test_clcc_response_single_long, NULL)); -- cgit v1.2.3-70-g09d2 From 2878833f5c83fe112f579865a6d318ce8413f452 Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Sat, 22 Feb 2025 17:20:20 +0100 Subject: modem: Allow to set current channel list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds support for setting the channels to override the boot up modem defaults: ``` busctl --system call org.freedesktop.ModemManager1 /org/freedesktop/ModemManager1/Modem/0 org.freedesktop.ModemManager1.Modem.CellBroadcast SetChannels 'a(uu)' 1 0 9999 busctl --system get-property org.freedesktop.ModemManager1 /org/freedesktop/ModemManager1/Modem/0 org.freedesktop.ModemManager1.Modem.CellBroadcast Channels a(uu) 1 0 9999 ``` Closes: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/934 Signed-off-by: Guido Günther --- ...eedesktop.ModemManager1.Modem.CellBroadcast.xml | 22 +++++ src/mm-broadband-modem.c | 62 +++++++++++++ src/mm-iface-modem-cell-broadcast.c | 102 +++++++++++++++++++++ src/mm-iface-modem-cell-broadcast.h | 9 ++ 4 files changed, 195 insertions(+) (limited to 'src') diff --git a/introspection/org.freedesktop.ModemManager1.Modem.CellBroadcast.xml b/introspection/org.freedesktop.ModemManager1.Modem.CellBroadcast.xml index 9e8584a1..572e094c 100644 --- a/introspection/org.freedesktop.ModemManager1.Modem.CellBroadcast.xml +++ b/introspection/org.freedesktop.ModemManager1.Modem.CellBroadcast.xml @@ -87,5 +87,27 @@ --> + + + + + + + + diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 4b13fd09..ffabec2e 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -10603,6 +10603,66 @@ modem_cell_broadcast_create_cbm (MMIfaceModemCellBroadcast *self) return mm_base_cbm_new (MM_BASE_MODEM (self)); } +/***********************************************************************************/ +/* Get channels (CellBroadcast interface) */ + +static gboolean +modem_cell_broadcast_set_channels_finish (MMIfaceModemCellBroadcast *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void +modem_cell_broadcast_set_channels_ready (MMBaseModem *self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + + if (!mm_base_modem_at_command_finish (self, res, &error)) + g_task_return_error (task, error); + else + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static void +modem_cell_broadcast_set_channels (MMIfaceModemCellBroadcast *self, + GArray *channels, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + g_autoptr (GString) cmd = g_string_new ("+CSCB=0,\""); + guint i; + + task = g_task_new (self, NULL, callback, user_data); + + for (i = 0; i < channels->len; i++) { + MMCellBroadcastChannels ch = g_array_index (channels, MMCellBroadcastChannels, i); + + if (i > 0) + g_string_append_c (cmd, ','); + + if (ch.start == ch.end) + g_string_append_printf (cmd, "%u", ch.start); + else + g_string_append_printf (cmd, "%u-%u", ch.start, ch.end); + } + g_string_append (cmd, "\",\"\""); + + mm_obj_dbg (self, "Setting channels..."); + mm_base_modem_at_command ( + MM_BASE_MODEM (self), + cmd->str, + 3, + FALSE, + (GAsyncReadyCallback)modem_cell_broadcast_set_channels_ready, + task); +} + /*********************************************************/ /* Check CellBroadcast support (CellBroadcast interface) */ @@ -14344,6 +14404,8 @@ iface_modem_cell_broadcast_init (MMIfaceModemCellBroadcastInterface *iface) iface->setup_unsolicited_events_finish = modem_cell_broadcast_setup_cleanup_unsolicited_events_finish; iface->cleanup_unsolicited_events = modem_cell_broadcast_cleanup_unsolicited_events; iface->cleanup_unsolicited_events_finish = modem_cell_broadcast_setup_cleanup_unsolicited_events_finish; + iface->set_channels = modem_cell_broadcast_set_channels; + iface->set_channels_finish = modem_cell_broadcast_set_channels_finish; iface->create_cbm = modem_cell_broadcast_create_cbm; } diff --git a/src/mm-iface-modem-cell-broadcast.c b/src/mm-iface-modem-cell-broadcast.c index 8e5af67c..a4ab41e3 100644 --- a/src/mm-iface-modem-cell-broadcast.c +++ b/src/mm-iface-modem-cell-broadcast.c @@ -42,6 +42,102 @@ mm_iface_modem_cell_broadcast_bind_simple_status (MMIfaceModemCellBroadcast *sel /*****************************************************************************/ + +typedef struct { + MmGdbusModemCellBroadcast *skeleton; + GDBusMethodInvocation *invocation; + MMIfaceModemCellBroadcast *self; + GArray *channels; +} HandleSetChannelsCellBroadcastContext; + +static void +handle_set_channels_context_free (HandleSetChannelsCellBroadcastContext *ctx) +{ + g_object_unref (ctx->skeleton); + g_object_unref (ctx->invocation); + g_object_unref (ctx->self); + g_array_unref (ctx->channels); + g_slice_free (HandleSetChannelsCellBroadcastContext, ctx); +} + +static void +set_channels_ready (MMIfaceModemCellBroadcast *self, + GAsyncResult *res, + HandleSetChannelsCellBroadcastContext *ctx) +{ + GError *error = NULL; + + if (!MM_IFACE_MODEM_CELL_BROADCAST_GET_IFACE (self)->set_channels_finish (self, res, &error)) + mm_dbus_method_invocation_take_error (ctx->invocation, error); + else { + mm_gdbus_modem_cell_broadcast_set_channels (ctx->skeleton, + mm_common_cell_broadcast_channels_garray_to_variant (ctx->channels)); + mm_gdbus_modem_cell_broadcast_complete_set_channels (ctx->skeleton, ctx->invocation); + } + + handle_set_channels_context_free (ctx); +} + +static void +handle_set_channels_auth_ready (MMBaseModem *self, + GAsyncResult *res, + HandleSetChannelsCellBroadcastContext *ctx) +{ + GError *error = NULL; + + if (!mm_base_modem_authorize_finish (self, res, &error)) { + mm_dbus_method_invocation_take_error (ctx->invocation, error); + handle_set_channels_context_free (ctx); + return; + } + + /* Validate channels (either number or range) */ + if (!mm_validate_cbs_channels (ctx->channels, &error)) { + mm_dbus_method_invocation_return_gerror (ctx->invocation, error); + handle_set_channels_context_free (ctx); + return; + } + + /* Check if plugin implements it */ + if (!MM_IFACE_MODEM_CELL_BROADCAST_GET_IFACE (self)->set_channels || + !MM_IFACE_MODEM_CELL_BROADCAST_GET_IFACE (self)->set_channels_finish) { + mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, + "Cannot set channels: not implemented"); + handle_set_channels_context_free (ctx); + return; + } + + /* Request to change channels */ + mm_obj_info (self, "processing user request to set channels..."); + MM_IFACE_MODEM_CELL_BROADCAST_GET_IFACE (self)->set_channels (ctx->self, + ctx->channels, + (GAsyncReadyCallback)set_channels_ready, + ctx); +} + +static gboolean +handle_set_channels (MmGdbusModemCellBroadcast *skeleton, + GDBusMethodInvocation *invocation, + GVariant *channels, + MMIfaceModemCellBroadcast *self) +{ + HandleSetChannelsCellBroadcastContext *ctx; + + ctx = g_slice_new0 (HandleSetChannelsCellBroadcastContext); + ctx->skeleton = g_object_ref (skeleton); + ctx->invocation = g_object_ref (invocation); + ctx->self = g_object_ref (self); + ctx->channels = mm_common_cell_broadcast_channels_variant_to_garray (channels); + mm_base_modem_authorize (MM_BASE_MODEM (self), + invocation, + MM_AUTHORIZATION_DEVICE_CONTROL, + (GAsyncReadyCallback)handle_set_channels_auth_ready, + ctx); + return TRUE; +} + +/*****************************************************************************/ + typedef struct { MmGdbusModemCellBroadcast *skeleton; GDBusMethodInvocation *invocation; @@ -315,6 +411,12 @@ interface_initialization_step (GTask *task) case INITIALIZATION_STEP_LAST: /* We are done without errors! */ + + /* Handle method invocations */ + g_signal_connect (ctx->skeleton, + "handle-set-channels", + G_CALLBACK (handle_set_channels), + self); g_signal_connect (ctx->skeleton, "handle-delete", G_CALLBACK (handle_delete), diff --git a/src/mm-iface-modem-cell-broadcast.h b/src/mm-iface-modem-cell-broadcast.h index 5990b865..34cd1b47 100644 --- a/src/mm-iface-modem-cell-broadcast.h +++ b/src/mm-iface-modem-cell-broadcast.h @@ -76,6 +76,15 @@ struct _MMIfaceModemCellBroadcastInterface { /* Create Cbm objects */ MMBaseCbm * (* create_cbm) (MMIfaceModemCellBroadcast *self); + + /* Set channel list */ + void (* set_channels) (MMIfaceModemCellBroadcast *self, + GArray *channels, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (* set_channels_finish) (MMIfaceModemCellBroadcast *self, + GAsyncResult *res, + GError **error); }; /* Initialize CellBroadcast interface (async) */ -- cgit v1.2.3-70-g09d2 From b83df955fa80b5ee167f8dde4dcb879e06758d9d Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Sat, 22 Feb 2025 17:20:59 +0100 Subject: modem: Load current channels on startup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Guido Günther --- src/mm-broadband-modem.c | 61 +++++++++++++++++++++++++++++++++++++ src/mm-iface-modem-cell-broadcast.c | 39 ++++++++++++++++++++++++ src/mm-iface-modem-cell-broadcast.h | 9 ++++++ 3 files changed, 109 insertions(+) (limited to 'src') diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index ffabec2e..5e026449 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -10499,6 +10499,65 @@ modem_cdma_register_in_network (MMIfaceModemCdma *_self, task); } +/*****************************************************************************/ +/* Load currently active channels (CellBroadcast interface) */ + +static GArray * +modem_cell_broadcast_load_channels_finish (MMIfaceModemCellBroadcast *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_pointer (G_TASK (res), error); +} + +static void +cscb_channels_format_check_ready (MMBroadbandModem *self, + GAsyncResult *res, + GTask *task) +{ + const gchar *response; + GError *error = NULL; + GArray *result; + + response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); + if (error) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + /* Parse reply */ + result = mm_3gpp_parse_cscb_response (response, &error); + if (!result) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_task_return_pointer (task, + result, + (GDestroyNotify)g_array_unref); + g_object_unref (task); +} + +static void +modem_cell_broadcast_load_channels (MMIfaceModemCellBroadcast *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + + task = g_task_new (self, NULL, callback, user_data); + + /* Load configured channels */ + mm_base_modem_at_command (MM_BASE_MODEM (self), + "+CSCB?", + 3, + TRUE, + (GAsyncReadyCallback)cscb_channels_format_check_ready, + task); +} + /*****************************************************************************/ static gboolean @@ -14402,6 +14461,8 @@ iface_modem_cell_broadcast_init (MMIfaceModemCellBroadcastInterface *iface) iface->check_support_finish = modem_cell_broadcast_check_support_finish; iface->setup_unsolicited_events = modem_cell_broadcast_setup_unsolicited_events; iface->setup_unsolicited_events_finish = modem_cell_broadcast_setup_cleanup_unsolicited_events_finish; + iface->load_channels = modem_cell_broadcast_load_channels; + iface->load_channels_finish = modem_cell_broadcast_load_channels_finish; iface->cleanup_unsolicited_events = modem_cell_broadcast_cleanup_unsolicited_events; iface->cleanup_unsolicited_events_finish = modem_cell_broadcast_setup_cleanup_unsolicited_events_finish; iface->set_channels = modem_cell_broadcast_set_channels; diff --git a/src/mm-iface-modem-cell-broadcast.c b/src/mm-iface-modem-cell-broadcast.c index a4ab41e3..f543d8f9 100644 --- a/src/mm-iface-modem-cell-broadcast.c +++ b/src/mm-iface-modem-cell-broadcast.c @@ -527,6 +527,7 @@ typedef enum { ENABLING_STEP_FIRST, ENABLING_STEP_SETUP_UNSOLICITED_EVENTS, ENABLING_STEP_ENABLE_UNSOLICITED_EVENTS, + ENABLING_STEP_GET_CHANNELS, ENABLING_STEP_LAST } EnablingStep; @@ -592,6 +593,31 @@ enable_unsolicited_events_ready (MMIfaceModemCellBroadcast *self, interface_enabling_step (task); } +static void +load_channels_ready (MMIfaceModemCellBroadcast *self, + GAsyncResult *res, + GTask *task) +{ + EnablingContext *ctx; + g_autoptr (GError) error = NULL; + g_autoptr (GArray) channels = NULL; + + ctx = g_task_get_task_data (task); + channels = MM_IFACE_MODEM_CELL_BROADCAST_GET_IFACE (self)->load_channels_finish (self, res, &error); + if (channels) { + mm_gdbus_modem_cell_broadcast_set_channels ( + ctx->skeleton, + mm_common_cell_broadcast_channels_garray_to_variant (channels)); + } else { + /* Not critical! */ + mm_obj_warn (self, "Couldn't load current channel list: %s", error->message); + } + + /* Go on with next step */ + ctx->step++; + interface_enabling_step (task); +} + static void interface_enabling_step (GTask *task) { @@ -654,6 +680,19 @@ interface_enabling_step (GTask *task) ctx->step++; /* fall through */ + case ENABLING_STEP_GET_CHANNELS: + /* Read current channel list */ + if (MM_IFACE_MODEM_CELL_BROADCAST_GET_IFACE (self)->load_channels && + MM_IFACE_MODEM_CELL_BROADCAST_GET_IFACE (self)->load_channels_finish) { + MM_IFACE_MODEM_CELL_BROADCAST_GET_IFACE (self)->load_channels ( + self, + (GAsyncReadyCallback)load_channels_ready, + task); + return; + } + ctx->step++; + /* fall through */ + case ENABLING_STEP_LAST: /* We are done without errors! */ g_task_return_boolean (task, TRUE); diff --git a/src/mm-iface-modem-cell-broadcast.h b/src/mm-iface-modem-cell-broadcast.h index 34cd1b47..32170b7b 100644 --- a/src/mm-iface-modem-cell-broadcast.h +++ b/src/mm-iface-modem-cell-broadcast.h @@ -74,6 +74,15 @@ struct _MMIfaceModemCellBroadcastInterface { GAsyncResult *res, GError **error); + /* Asynchronous loading of channel list */ + GArray * (*load_channels_finish) (MMIfaceModemCellBroadcast *self, + GAsyncResult *res, + GError **error); + + void (*load_channels) (MMIfaceModemCellBroadcast *self, + GAsyncReadyCallback callback, + gpointer user_data); + /* Create Cbm objects */ MMBaseCbm * (* create_cbm) (MMIfaceModemCellBroadcast *self); -- cgit v1.2.3-70-g09d2