diff options
author | Guido Günther <agx@sigxcpu.org> | 2024-08-23 19:52:32 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2024-12-01 21:41:10 +0000 |
commit | b491bc474e8607ca306c84d2c1a95bc664685190 (patch) | |
tree | d7b045072d4fa6c1e87457a8e4857eea31fe233e /cli | |
parent | 502e0c920f694d6f89371fef33e8212835790669 (diff) |
cli: Add support for listing and deleting Cell Broadcast messages
This adds
```
$ mmcli -m 0 --cell-broadcast-list-cbm
/org/freedesktop/ModemManager1/CBM/0 (received)
/org/freedesktop/ModemManager1/CBM/0 (received)
$ mmcli -m 0 --cell-broadcast-delete-cbm=0
successfully deleted CBM from modem
$ mmcli -m 0 --cbm 0
--------------------------
General | path: /org/freedesktop/ModemManager1/CBM/1
--------------------------
Content | text: This is a test of the Ontario Alert Ready System. There is no danger to your health or safety
--------------------------
Properties | update: 0
| message code: 0
```
Signed-off-by: Guido Günther <agx@sigxcpu.org>
Diffstat (limited to 'cli')
-rw-r--r-- | cli/meson.build | 2 | ||||
-rw-r--r-- | cli/mmcli-cbm.c | 150 | ||||
-rw-r--r-- | cli/mmcli-common.c | 274 | ||||
-rw-r--r-- | cli/mmcli-common.h | 14 | ||||
-rw-r--r-- | cli/mmcli-modem-cell-broadcast.c | 355 | ||||
-rw-r--r-- | cli/mmcli-output.c | 9 | ||||
-rw-r--r-- | cli/mmcli-output.h | 9 | ||||
-rw-r--r-- | cli/mmcli.c | 19 | ||||
-rw-r--r-- | cli/mmcli.h | 16 |
9 files changed, 848 insertions, 0 deletions
diff --git a/cli/meson.build b/cli/meson.build index b020749b..19029d51 100644 --- a/cli/meson.build +++ b/cli/meson.build @@ -5,12 +5,14 @@ sources = files( 'mmcli-bearer.c', 'mmcli.c', 'mmcli-call.c', + 'mmcli-cbm.c', 'mmcli-common.c', 'mmcli-manager.c', 'mmcli-modem-3gpp.c', 'mmcli-modem-3gpp-profile-manager.c', 'mmcli-modem-3gpp-ussd.c', 'mmcli-modem.c', + 'mmcli-modem-cell-broadcast.c', 'mmcli-modem-cdma.c', 'mmcli-modem-firmware.c', 'mmcli-modem-location.c', diff --git a/cli/mmcli-cbm.c b/cli/mmcli-cbm.c new file mode 100644 index 00000000..8cef4905 --- /dev/null +++ b/cli/mmcli-cbm.c @@ -0,0 +1,150 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * mmcli -- Control cbm information from the command line + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright (C) 2024 Guido Günther <agx@sigxcpu.org> + */ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <locale.h> +#include <string.h> + +#include <glib.h> +#include <gio/gio.h> + +#define _LIBMM_INSIDE_MMCLI +#include <libmm-glib.h> + +#include "mmcli.h" +#include "mmcli-common.h" +#include "mmcli-output.h" + +/* Context */ +typedef struct { + MMManager *manager; + MMObject *object; + GCancellable *cancellable; + MMCbm *cbm; +} Context; +static Context *ctx; + +/* Options */ +static gboolean info_flag; /* set when no action found */ + +static GOptionEntry entries[] = { + /* no options just info */ + { NULL } +}; + +GOptionGroup * +mmcli_cbm_get_option_group (void) +{ + GOptionGroup *group; + + group = g_option_group_new ("cbm", + "CBM options:", + "Show CBM options", + NULL, + NULL); + g_option_group_add_entries (group, entries); + + return group; +} + +gboolean +mmcli_cbm_options_enabled (void) +{ + static gboolean checked = FALSE; + int n_actions = 0; + + if (checked) + return n_actions; + + if (mmcli_get_common_cbm_string ()) { + /* default to info */ + info_flag = TRUE; + n_actions++; + } + + if (info_flag) + mmcli_force_sync_operation (); + + checked = TRUE; + return !!n_actions; +} + +static void +context_free (void) +{ + if (!ctx) + return; + + if (ctx->cancellable) + g_object_unref (ctx->cancellable); + if (ctx->cbm) + g_object_unref (ctx->cbm); + if (ctx->object) + g_object_unref (ctx->object); + if (ctx->manager) + g_object_unref (ctx->manager); + g_free (ctx); +} + +void +mmcli_cbm_shutdown (void) +{ + context_free (); +} + +static void +print_cbm_info (MMCbm *cbm) +{ + gchar *channel; + gchar *update; + gchar *code; + + update = g_strdup_printf ("%u", mm_cbm_get_update (cbm)); + channel = g_strdup_printf ("%u", mm_cbm_get_channel (cbm)); + code = g_strdup_printf ("%u", mm_cbm_get_message_code (cbm)); + + mmcli_output_string (MMC_F_CBM_GENERAL_DBUS_PATH, mm_cbm_get_path (cbm)); + mmcli_output_string (MMC_F_CBM_CONTENT_TEXT, mm_cbm_get_text (cbm)); + mmcli_output_string_take (MMC_F_CBM_PROPERTIES_CHANNEL, channel); + mmcli_output_string_take (MMC_F_CBM_PROPERTIES_UPDATE, update); + mmcli_output_string_take (MMC_F_CBM_PROPERTIES_MESSAGE_CODE, code); + + mmcli_output_dump (); +} + +void +mmcli_cbm_run_synchronous (GDBusConnection *connection) +{ + /* Initialize context */ + ctx = g_new0 (Context, 1); + ctx->cbm = mmcli_get_cbm_sync (connection, + mmcli_get_common_cbm_string (), + &ctx->manager, + &ctx->object); + + /* Setup operation timeout */ + mmcli_force_operation_timeout (G_DBUS_PROXY (ctx->cbm)); + + g_debug ("Printing CBM info..."); + print_cbm_info (ctx->cbm); +} diff --git a/cli/mmcli-common.c b/cli/mmcli-common.c index 592b7a1e..42778ece 100644 --- a/cli/mmcli-common.c +++ b/cli/mmcli-common.c @@ -1583,6 +1583,269 @@ mmcli_get_call_sync (GDBusConnection *connection, } /******************************************************************************/ +/* Cell Broadcast Message */ + +typedef struct { + gchar *cbm_path; + MMManager *manager; + GList *modems; + MMObject *current; +} GetCbmContext; + +typedef struct { + MMManager *manager; + MMObject *object; + MMCbm *cbm; +} GetCbmResults; + +static void +get_cbm_results_free (GetCbmResults *results) +{ + g_object_unref (results->manager); + g_object_unref (results->object); + g_object_unref (results->cbm); + g_free (results); +} + +static void +get_cbm_context_free (GetCbmContext *ctx) +{ + if (ctx->current) + g_object_unref (ctx->current); + if (ctx->manager) + g_object_unref (ctx->manager); + g_list_free_full (ctx->modems, g_object_unref); + g_free (ctx->cbm_path); + g_free (ctx); +} + +MMCbm * +mmcli_get_cbm_finish (GAsyncResult *res, + MMManager **o_manager, + MMObject **o_object) +{ + GetCbmResults *results; + MMCbm *obj; + + results = g_task_propagate_pointer (G_TASK (res), NULL); + g_assert (results); + if (o_manager) + *o_manager = g_object_ref (results->manager); + if (o_object) + *o_object = g_object_ref (results->object); + obj = g_object_ref (results->cbm); + get_cbm_results_free (results); + return obj; +} + +static void look_for_cbm_in_modem (GTask *task); + +static MMCbm * +find_cbm_in_list (GList *list, + const gchar *cbm_path) +{ + GList *l; + + for (l = list; l; l = g_list_next (l)) { + MMCbm *cbm = MM_CBM (l->data); + + if (g_str_equal (mm_cbm_get_path (cbm), cbm_path)) { + g_debug ("CBM found at '%s'\n", cbm_path); + return g_object_ref (cbm); + } + } + + return NULL; +} + +static void +list_cbm_ready (MMModemCellBroadcast *modem, + GAsyncResult *res, + GTask *task) +{ + GetCbmContext *ctx; + GetCbmResults *results; + MMCbm *found; + GList *cbm_list; + GError *error = NULL; + + ctx = g_task_get_task_data (task); + + cbm_list = mm_modem_cell_broadcast_list_finish (modem, res, &error); + if (error) { + g_printerr ("error: couldn't list CBM at '%s': '%s'\n", + mm_modem_cell_broadcast_get_path (modem), + error->message); + exit (EXIT_FAILURE); + } + + found = find_cbm_in_list (cbm_list, ctx->cbm_path); + g_list_free_full (cbm_list, g_object_unref); + + if (!found) { + /* Not found, try with next modem */ + look_for_cbm_in_modem (task); + return; + } + + /* Found! */ + results = g_new (GetCbmResults, 1); + results->manager = g_object_ref (ctx->manager); + results->object = g_object_ref (ctx->current); + results->cbm = found; + g_task_return_pointer (task, results, (GDestroyNotify) get_cbm_results_free); + g_object_unref (task); +} + +static void +look_for_cbm_in_modem (GTask *task) +{ + GetCbmContext *ctx; + MMModemCellBroadcast *modem; + + ctx = g_task_get_task_data (task); + + if (!ctx->modems) { + g_printerr ("error: couldn't find CBM at '%s': 'not found in any modem'\n", + ctx->cbm_path); + exit (EXIT_FAILURE); + } + + /* Loop looking for the cbm in each modem found */ + ctx->current = MM_OBJECT (ctx->modems->data); + ctx->modems = g_list_delete_link (ctx->modems, ctx->modems); + + modem = mm_object_get_modem_cell_broadcast (ctx->current); + if (!modem) { + /* Current modem has no cell broadcast capabilities, try with next modem */ + look_for_cbm_in_modem (task); + return; + } + + g_debug ("Looking for cbm '%s' in modem '%s'...", + ctx->cbm_path, + mm_object_get_path (ctx->current)); + mm_modem_cell_broadcast_list (modem, + g_task_get_cancellable (task), + (GAsyncReadyCallback)list_cbm_ready, + task); + g_object_unref (modem); +} + +static void +get_cbm_manager_ready (GDBusConnection *connection, + GAsyncResult *res, + GTask *task) +{ + GetCbmContext *ctx; + + ctx = g_task_get_task_data (task); + + ctx->manager = mmcli_get_manager_finish (res); + ctx->modems = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (ctx->manager)); + if (!ctx->modems) { + g_printerr ("error: couldn't find CBM at '%s': 'no modems found'\n", + ctx->cbm_path); + exit (EXIT_FAILURE); + } + + look_for_cbm_in_modem (task); +} + +void +mmcli_get_cbm (GDBusConnection *connection, + const gchar *str, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + GetCbmContext *ctx; + + task = g_task_new (connection, cancellable, callback, user_data); + + ctx = g_new0 (GetCbmContext, 1); + get_object_lookup_info (str, "CBM", MM_DBUS_CBM_PREFIX, + &ctx->cbm_path, NULL, NULL, NULL); + g_task_set_task_data (task, ctx, (GDestroyNotify) get_cbm_context_free); + + mmcli_get_manager (connection, + cancellable, + (GAsyncReadyCallback)get_cbm_manager_ready, + task); +} + +MMCbm * +mmcli_get_cbm_sync (GDBusConnection *connection, + const gchar *str, + MMManager **o_manager, + MMObject **o_object) +{ + MMManager *manager; + GList *modems; + GList *l; + MMCbm *found = NULL; + gchar *cbm_path = NULL; + + get_object_lookup_info (str, "CBM", MM_DBUS_CBM_PREFIX, + &cbm_path, NULL, NULL, NULL); + + manager = mmcli_get_manager_sync (connection); + modems = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (manager)); + if (!modems) { + g_printerr ("error: couldn't find CBM at '%s': 'no modems found'\n", + cbm_path); + exit (EXIT_FAILURE); + } + + for (l = modems; !found && l; l = g_list_next (l)) { + GError *error = NULL; + MMObject *object; + MMModemCellBroadcast *modem; + GList *cbm_list; + + object = MM_OBJECT (l->data); + modem = mm_object_get_modem_cell_broadcast (object); + + /* If this modem doesn't implement cell broadcast, continue to next one */ + if (!modem) + continue; + + cbm_list = mm_modem_cell_broadcast_list_sync (modem, NULL, &error); + if (error) { + g_printerr ("error: couldn't list CBM at '%s': '%s'\n", + mm_modem_cell_broadcast_get_path (modem), + error->message); + exit (EXIT_FAILURE); + } + + found = find_cbm_in_list (cbm_list, cbm_path); + g_list_free_full (cbm_list, g_object_unref); + + if (found && o_object) + *o_object = g_object_ref (object); + + g_object_unref (modem); + } + + if (!found) { + g_printerr ("error: couldn't find CBM at '%s': 'not found in any modem'\n", + cbm_path); + exit (EXIT_FAILURE); + } + + g_list_free_full (modems, g_object_unref); + g_free (cbm_path); + + if (o_manager) + *o_manager = manager; + else + g_object_unref (manager); + + return found; +} + +/******************************************************************************/ const gchar * mmcli_get_state_reason_string (MMModemStateChangeReason reason) @@ -1607,6 +1870,7 @@ static gchar *bearer_str; static gchar *sim_str; static gchar *sms_str; static gchar *call_str; +static gchar *cbm_str; static GOptionEntry entries[] = { { "modem", 'm', 0, G_OPTION_ARG_STRING, &modem_str, @@ -1629,6 +1893,10 @@ static GOptionEntry entries[] = { "Specify Call by path or index. Shows Call information if no action specified.", "[PATH|INDEX]" }, + { "cbm", 'o', 0, G_OPTION_ARG_STRING, &cbm_str, + "Specify CBM by path or index. Shows Cbm information if no action specified.", + "[PATH|INDEX]" + }, { NULL } }; @@ -1678,6 +1946,12 @@ mmcli_get_common_call_string (void) return call_str; } +const gchar * +mmcli_get_common_cbm_string (void) +{ + return cbm_str; +} + gchar * mmcli_prefix_newlines (const gchar *prefix, const gchar *str) diff --git a/cli/mmcli-common.h b/cli/mmcli-common.h index 237ebb55..d7a57c47 100644 --- a/cli/mmcli-common.h +++ b/cli/mmcli-common.h @@ -96,6 +96,19 @@ MMCall *mmcli_get_call_sync (GDBusConnection *connection, MMManager **manager, MMObject **object); +void mmcli_get_cbm (GDBusConnection *connection, + const gchar *str, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +MMCbm *mmcli_get_cbm_finish (GAsyncResult *res, + MMManager **manager, + MMObject **object); +MMCbm *mmcli_get_cbm_sync (GDBusConnection *connection, + const gchar *str, + MMManager **manager, + MMObject **object); + const gchar *mmcli_get_state_reason_string (MMModemStateChangeReason reason); GOptionGroup *mmcli_get_common_option_group (void); @@ -104,6 +117,7 @@ const gchar *mmcli_get_common_bearer_string (void); const gchar *mmcli_get_common_sim_string (void); const gchar *mmcli_get_common_sms_string (void); const gchar *mmcli_get_common_call_string (void); +const gchar *mmcli_get_common_cbm_string (void); gchar *mmcli_prefix_newlines (const gchar *prefix, const gchar *str); diff --git a/cli/mmcli-modem-cell-broadcast.c b/cli/mmcli-modem-cell-broadcast.c new file mode 100644 index 00000000..8121e8a5 --- /dev/null +++ b/cli/mmcli-modem-cell-broadcast.c @@ -0,0 +1,355 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * mmcli -- Control cell broadcast information from the command line + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright (C) 2024 Guido Günther <agx@sigxcpu.org> + */ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <locale.h> +#include <string.h> + +#include <glib.h> +#include <gio/gio.h> + +#define _LIBMM_INSIDE_MMCLI +#include <libmm-glib.h> + +#include "mmcli.h" +#include "mmcli-common.h" +#include "mmcli-output.h" + +/* Context */ +typedef struct { + GDBusConnection *connection; + MMManager *manager; + GCancellable *cancellable; + MMObject *object; + MMModemCellBroadcast *modem_cell_broadcast; +} Context; +static Context *ctx; + +/* Options */ +static gboolean status_flag; +static gboolean list_flag; +static gchar *delete_str; + +static GOptionEntry entries[] = { + { "cell-broadcast-list-cbm", 0, 0, G_OPTION_ARG_NONE, &list_flag, + "List cell broadcast messages available in a given modem", + NULL + }, + { "cell-broadcast-delete-cbm", 0, 0, G_OPTION_ARG_STRING, &delete_str, + "Delete a cell broadcast message from a given modem", + "[PATH|INDEX]" + }, + { NULL } +}; + +GOptionGroup * +mmcli_modem_cell_broadcast_get_option_group (void) +{ + GOptionGroup *group; + + group = g_option_group_new ("cell-broadcast", + "Cell Broadcast options:", + "Show Cell Broadcast options", + NULL, + NULL); + g_option_group_add_entries (group, entries); + + return group; +} + +gboolean +mmcli_modem_cell_broadcast_options_enabled (void) +{ + static guint n_actions = 0; + static gboolean checked = FALSE; + + if (checked) + return !!n_actions; + + n_actions = (list_flag + + !!delete_str); + + if (n_actions > 1) { + g_printerr ("error: too many Cell Broadcast actions requested\n"); + exit (EXIT_FAILURE); + } + + if (status_flag) + mmcli_force_sync_operation (); + + checked = TRUE; + return !!n_actions; +} + +static void +context_free (void) +{ + if (!ctx) + return; + + if (ctx->cancellable) + g_object_unref (ctx->cancellable); + if (ctx->modem_cell_broadcast) + g_object_unref (ctx->modem_cell_broadcast); + if (ctx->object) + g_object_unref (ctx->object); + if (ctx->manager) + g_object_unref (ctx->manager); + if (ctx->connection) + g_object_unref (ctx->connection); + g_free (ctx); +} + +static void +ensure_modem_cell_broadcast (void) +{ + if (mm_modem_get_state (mm_object_peek_modem (ctx->object)) < MM_MODEM_STATE_ENABLED) { + g_printerr ("error: modem not enabled yet\n"); + exit (EXIT_FAILURE); + } + + if (!ctx->modem_cell_broadcast) { + g_printerr ("error: modem has no cell broadcast capabilities\n"); + exit (EXIT_FAILURE); + } + + /* Success */ +} + +void +mmcli_modem_cell_broadcast_shutdown (void) +{ + context_free (); +} + +static void +output_cbm_info (MMCbm *cbm) +{ + gchar *extra; + + extra = g_strdup_printf ("(%s)", mm_cbm_state_get_string (mm_cbm_get_state (cbm))); + mmcli_output_listitem (MMC_F_CBM_LIST_DBUS_PATH, + " ", + mm_cbm_get_path (cbm), + extra); + g_free (extra); +} + +static void +list_process_reply (GList *result, + const GError *error) +{ + GList *l; + + if (error) { + g_printerr ("error: couldn't list CBM: '%s'\n", + error->message); + exit (EXIT_FAILURE); + } + + for (l = result; l; l = g_list_next (l)) + output_cbm_info (MM_CBM (l->data)); + mmcli_output_list_dump (MMC_F_CBM_LIST_DBUS_PATH); +} + +static void +list_ready (MMModemCellBroadcast *modem, + GAsyncResult *result, + gpointer nothing) +{ + GList *operation_result; + GError *error = NULL; + + operation_result = mm_modem_cell_broadcast_list_finish (modem, result, &error); + list_process_reply (operation_result, error); + + mmcli_async_operation_done (); +} + +static void +delete_process_reply (gboolean result, + const GError *error) +{ + if (!result) { + g_printerr ("error: couldn't delete CBM: '%s'\n", + error ? error->message : "unknown error"); + exit (EXIT_FAILURE); + } + + g_print ("successfully deleted CBM from modem\n"); +} + +static void +delete_ready (MMModemCellBroadcast *modem, + GAsyncResult *result, + gpointer nothing) +{ + gboolean operation_result; + GError *error = NULL; + + operation_result = mm_modem_cell_broadcast_delete_finish (modem, result, &error); + delete_process_reply (operation_result, error); + + mmcli_async_operation_done (); +} + +static void +get_cbm_to_delete_ready (GDBusConnection *connection, + GAsyncResult *res) +{ + MMCbm *cbm; + MMObject *obj = NULL; + + cbm = mmcli_get_cbm_finish (res, NULL, &obj); + if (!g_str_equal (mm_object_get_path (obj), mm_modem_cell_broadcast_get_path (ctx->modem_cell_broadcast))) { + g_printerr ("error: CBM '%s' not owned by modem '%s'", + mm_cbm_get_path (cbm), + mm_modem_cell_broadcast_get_path (ctx->modem_cell_broadcast)); + exit (EXIT_FAILURE); + } + + mm_modem_cell_broadcast_delete (ctx->modem_cell_broadcast, + mm_cbm_get_path (cbm), + ctx->cancellable, + (GAsyncReadyCallback)delete_ready, + NULL); + g_object_unref (cbm); + g_object_unref (obj); +} + +static void +get_modem_ready (GObject *source, + GAsyncResult *result, + gpointer none) +{ + ctx->object = mmcli_get_modem_finish (result, &ctx->manager); + ctx->modem_cell_broadcast = mm_object_get_modem_cell_broadcast (ctx->object); + + /* Setup operation timeout */ + if (ctx->modem_cell_broadcast) + mmcli_force_operation_timeout (G_DBUS_PROXY (ctx->modem_cell_broadcast)); + + ensure_modem_cell_broadcast (); + + if (status_flag) + g_assert_not_reached (); + + /* Request to list CBM? */ + if (list_flag) { + g_debug ("Asynchronously listing CBM in modem..."); + mm_modem_cell_broadcast_list (ctx->modem_cell_broadcast, + ctx->cancellable, + (GAsyncReadyCallback)list_ready, + NULL); + return; + } + + /* Request to delete a given CBM? */ + if (delete_str) { + mmcli_get_cbm (ctx->connection, + delete_str, + ctx->cancellable, + (GAsyncReadyCallback)get_cbm_to_delete_ready, + NULL); + return; + } + + g_warn_if_reached (); +} + +void +mmcli_modem_cell_broadcast_run_asynchronous (GDBusConnection *connection, + GCancellable *cancellable) +{ + /* Initialize context */ + ctx = g_new0 (Context, 1); + if (cancellable) + ctx->cancellable = g_object_ref (cancellable); + ctx->connection = g_object_ref (connection); + + /* Get proper modem */ + mmcli_get_modem (connection, + mmcli_get_common_modem_string (), + cancellable, + (GAsyncReadyCallback)get_modem_ready, + NULL); +} + +void +mmcli_modem_cell_broadcast_run_synchronous (GDBusConnection *connection) +{ + GError *error = NULL; + + /* Initialize context */ + ctx = g_new0 (Context, 1); + ctx->object = mmcli_get_modem_sync (connection, + mmcli_get_common_modem_string (), + &ctx->manager); + ctx->modem_cell_broadcast = mm_object_get_modem_cell_broadcast (ctx->object); + + /* Setup operation timeout */ + if (ctx->modem_cell_broadcast) + mmcli_force_operation_timeout (G_DBUS_PROXY (ctx->modem_cell_broadcast)); + + ensure_modem_cell_broadcast (); + + /* Request to list the CBM? */ + if (list_flag) { + GList *result; + + g_debug ("Synchronously listing CBM messages..."); + result = mm_modem_cell_broadcast_list_sync (ctx->modem_cell_broadcast, NULL, &error); + list_process_reply (result, error); + return; + } + + /* Request to delete a given CBM? */ + if (delete_str) { + gboolean result; + MMCbm *cbm; + MMObject *obj = NULL; + + cbm = mmcli_get_cbm_sync (connection, + delete_str, + NULL, + &obj); + if (!g_str_equal (mm_object_get_path (obj), mm_modem_cell_broadcast_get_path (ctx->modem_cell_broadcast))) { + g_printerr ("error: CBM '%s' not owned by modem '%s'", + mm_cbm_get_path (cbm), + mm_modem_cell_broadcast_get_path (ctx->modem_cell_broadcast)); + exit (EXIT_FAILURE); + } + + result = mm_modem_cell_broadcast_delete_sync (ctx->modem_cell_broadcast, + mm_cbm_get_path (cbm), + NULL, + &error); + g_object_unref (cbm); + g_object_unref (obj); + + delete_process_reply (result, error); + return; + } + + g_warn_if_reached (); +} diff --git a/cli/mmcli-output.c b/cli/mmcli-output.c index c1c064da..1884e906 100644 --- a/cli/mmcli-output.c +++ b/cli/mmcli-output.c @@ -87,6 +87,9 @@ static SectionInfo section_infos[] = { [MMC_S_SMS_PROPERTIES] = { "Properties" }, [MMC_S_SIM_GENERAL] = { "General" }, [MMC_S_SIM_PROPERTIES] = { "Properties" }, + [MMC_S_CBM_GENERAL] = { "General" }, + [MMC_S_CBM_CONTENT] = { "Content" }, + [MMC_S_CBM_PROPERTIES] = { "Properties" }, }; /******************************************************************************/ @@ -285,6 +288,11 @@ static FieldInfo field_infos[] = { [MMC_F_CALL_AUDIO_FORMAT_ENCODING] = { "call.audio-format.encoding", "encoding", MMC_S_CALL_AUDIO_FORMAT, }, [MMC_F_CALL_AUDIO_FORMAT_RESOLUTION] = { "call.audio-format.resolution", "resolution", MMC_S_CALL_AUDIO_FORMAT, }, [MMC_F_CALL_AUDIO_FORMAT_RATE] = { "call.audio-format.rate", "rate", MMC_S_CALL_AUDIO_FORMAT, }, + [MMC_F_CBM_GENERAL_DBUS_PATH] = { "cbm.dbus-path", "path", MMC_S_CBM_GENERAL, }, + [MMC_F_CBM_CONTENT_TEXT] = { "cbm.content.text", "text", MMC_S_CBM_CONTENT, }, + [MMC_F_CBM_PROPERTIES_CHANNEL] = { "cbm.properties.channel", "channel", MMC_S_CBM_PROPERTIES, }, + [MMC_F_CBM_PROPERTIES_UPDATE] = { "cbm.properties.update", "update", MMC_S_CBM_PROPERTIES, }, + [MMC_F_CBM_PROPERTIES_MESSAGE_CODE] = { "cbm.properties.message-code", "message code", MMC_S_CBM_PROPERTIES, }, [MMC_F_SMS_GENERAL_DBUS_PATH] = { "sms.dbus-path", "path", MMC_S_SMS_GENERAL, }, [MMC_F_SMS_CONTENT_NUMBER] = { "sms.content.number", "number", MMC_S_SMS_CONTENT, }, [MMC_F_SMS_CONTENT_TEXT] = { "sms.content.text", "text", MMC_S_SMS_CONTENT, }, @@ -321,6 +329,7 @@ static FieldInfo field_infos[] = { [MMC_F_MODEM_LIST_DBUS_PATH] = { "modem-list", "modems", MMC_S_UNKNOWN, }, [MMC_F_SMS_LIST_DBUS_PATH] = { "modem.messaging.sms", "sms messages", MMC_S_UNKNOWN, }, [MMC_F_CALL_LIST_DBUS_PATH] = { "modem.voice.call", "calls", MMC_S_UNKNOWN, }, + [MMC_F_CBM_LIST_DBUS_PATH] = { "modem.cell-broadcast.cbm", "cell broadcast messages", MMC_S_UNKNOWN, }, }; /******************************************************************************/ diff --git a/cli/mmcli-output.h b/cli/mmcli-output.h index f942f16b..8dde1412 100644 --- a/cli/mmcli-output.h +++ b/cli/mmcli-output.h @@ -83,6 +83,9 @@ typedef enum { MMC_S_SMS_PROPERTIES, MMC_S_SIM_GENERAL, MMC_S_SIM_PROPERTIES, + MMC_S_CBM_GENERAL, + MMC_S_CBM_CONTENT, + MMC_S_CBM_PROPERTIES, } MmcS; /******************************************************************************/ @@ -303,6 +306,11 @@ typedef enum { MMC_F_CALL_AUDIO_FORMAT_ENCODING, MMC_F_CALL_AUDIO_FORMAT_RESOLUTION, MMC_F_CALL_AUDIO_FORMAT_RATE, + MMC_F_CBM_GENERAL_DBUS_PATH, + MMC_F_CBM_CONTENT_TEXT, + MMC_F_CBM_PROPERTIES_CHANNEL, + MMC_F_CBM_PROPERTIES_UPDATE, + MMC_F_CBM_PROPERTIES_MESSAGE_CODE, MMC_F_SMS_GENERAL_DBUS_PATH, MMC_F_SMS_CONTENT_NUMBER, MMC_F_SMS_CONTENT_TEXT, @@ -340,6 +348,7 @@ typedef enum { MMC_F_MODEM_LIST_DBUS_PATH, MMC_F_SMS_LIST_DBUS_PATH, MMC_F_CALL_LIST_DBUS_PATH, + MMC_F_CBM_LIST_DBUS_PATH, } MmcF; /******************************************************************************/ diff --git a/cli/mmcli.c b/cli/mmcli.c index 1e98e51d..062e1714 100644 --- a/cli/mmcli.c +++ b/cli/mmcli.c @@ -269,6 +269,10 @@ main (gint argc, gchar **argv) g_option_context_add_group (context, mmcli_call_get_option_group ()); g_option_context_add_group (context, + mmcli_modem_cell_broadcast_get_option_group ()); + g_option_context_add_group (context, + mmcli_cbm_get_option_group ()); + g_option_context_add_group (context, test_get_option_group ()); g_option_context_add_main_entries (context, main_entries, NULL); g_option_context_parse (context, &argc, &argv, NULL); @@ -361,6 +365,10 @@ main (gint argc, gchar **argv) else mmcli_call_run_synchronous (connection); } + /* Cbm options? */ + else if (mmcli_cbm_options_enabled ()) { + mmcli_cbm_run_synchronous (connection); + } /* Modem 3GPP options? */ else if (mmcli_modem_3gpp_options_enabled ()) { if (async_flag) @@ -452,6 +460,13 @@ main (gint argc, gchar **argv) else mmcli_modem_oma_run_synchronous (connection); } + /* Modem Cell Broadcast options? */ + else if (mmcli_modem_cell_broadcast_options_enabled ()) { + if (async_flag) + mmcli_modem_cell_broadcast_run_asynchronous (connection, cancellable); + else + mmcli_modem_cell_broadcast_run_synchronous (connection); + } /* Modem options? * NOTE: let this check be always the last one, as other groups also need * having a modem specified, and therefore if -m is set, modem options @@ -500,6 +515,8 @@ main (gint argc, gchar **argv) mmcli_modem_signal_shutdown (); } else if (mmcli_modem_oma_options_enabled ()) { mmcli_modem_oma_shutdown (); + } else if (mmcli_modem_cell_broadcast_options_enabled ()) { + mmcli_modem_cell_broadcast_shutdown (); } else if (mmcli_sim_options_enabled ()) { mmcli_sim_shutdown (); } else if (mmcli_bearer_options_enabled ()) { @@ -508,6 +525,8 @@ main (gint argc, gchar **argv) mmcli_sms_shutdown (); } else if (mmcli_call_options_enabled ()) { mmcli_call_shutdown (); + } else if (mmcli_cbm_options_enabled ()) { + mmcli_cbm_shutdown (); } else if (mmcli_modem_options_enabled ()) { mmcli_modem_shutdown (); } diff --git a/cli/mmcli.h b/cli/mmcli.h index de5cc804..94dff694 100644 --- a/cli/mmcli.h +++ b/cli/mmcli.h @@ -150,6 +150,14 @@ void mmcli_modem_oma_run_asynchronous (GDBusConnection *connection, void mmcli_modem_oma_run_synchronous (GDBusConnection *connection); void mmcli_modem_oma_shutdown (void); +/* CellBroadcast group */ +GOptionGroup *mmcli_modem_cell_broadcast_get_option_group (void); +gboolean mmcli_modem_cell_broadcast_options_enabled (void); +void mmcli_modem_cell_broadcast_run_asynchronous (GDBusConnection *connection, + GCancellable *cancellable); +void mmcli_modem_cell_broadcast_run_synchronous (GDBusConnection *connection); +void mmcli_modem_cell_broadcast_shutdown (void); + /* Bearer group */ GOptionGroup *mmcli_bearer_get_option_group (void); gboolean mmcli_bearer_options_enabled (void); @@ -182,4 +190,12 @@ void mmcli_call_run_asynchronous (GDBusConnection *connection, void mmcli_call_run_synchronous (GDBusConnection *connection); void mmcli_call_shutdown (void); +/* CBM group */ +GOptionGroup *mmcli_cbm_get_option_group (void); +gboolean mmcli_cbm_options_enabled (void); +void mmcli_cbm_run_asynchronous (GDBusConnection *connection, + GCancellable *cancellable); +void mmcli_cbm_run_synchronous (GDBusConnection *connection); +void mmcli_cbm_shutdown (void); + #endif /* __MMCLI_H__ */ |