diff options
-rw-r--r-- | introspection/org.freedesktop.ModemManager1.Modem.CellBroadcast.xml | 22 | ||||
-rw-r--r-- | src/mm-broadband-modem.c | 62 | ||||
-rw-r--r-- | src/mm-iface-modem-cell-broadcast.c | 102 | ||||
-rw-r--r-- | src/mm-iface-modem-cell-broadcast.h | 9 |
4 files changed, 195 insertions, 0 deletions
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 @@ --> <property name="CellBroadcasts" type="ao" access="read" /> + <!-- + SetChannels: + @channels: The list of channels + + Set the list of channels to receive Cell Broadcasts for. + + Since: 1.24 + --> + <method name="SetChannels"> + <arg name="channels" type="a(uu)" direction="in" /> + </method> + + <!-- + Channels: + + The list of channels that cell broadcast messages are + received for. + + Since: 1.24 + --> + <property name="Channels" type="a(uu)" access="read" /> + </interface> </node> 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) */ |