modem: Allow to set current channel list
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 <agx@sigxcpu.org>
This commit is contained in:
committed by
Dan Williams
parent
d8135be6e2
commit
2878833f5c
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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) */
|
||||
|
||||
Reference in New Issue
Block a user