/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * mmcli -- Control modem status & access 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 3 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 . * * Copyright (C) 2013 Google, Inc. */ #include "config.h" #include #include #include #include #include #include #define _LIBMM_INSIDE_MMCLI #include #include "mmcli.h" #include "mmcli-common.h" /* Context */ typedef struct { MMManager *manager; GCancellable *cancellable; MMObject *object; MMModemOma *modem_oma; } Context; static Context *ctx; /* Options */ static gboolean status_flag; static gchar *setup_str; static gchar *start_str; static gchar *accept_str; static gchar *reject_str; static gboolean cancel_flag; static GOptionEntry entries[] = { { "oma-status", 0, 0, G_OPTION_ARG_NONE, &status_flag, "Current status of the OMA device management", NULL }, { "oma-setup", 0, 0, G_OPTION_ARG_STRING, &setup_str, "Setup OMA features", "[FEATURE1|FEATURE2...]" }, { "oma-start-client-initiated-session", 0, 0, G_OPTION_ARG_STRING, &start_str, "Start client initiated OMA DM session", "[Session type]" }, { "oma-accept-network-initiated-session", 0, 0, G_OPTION_ARG_STRING, &accept_str, "Accept network initiated OMA DM session", "[Session ID]" }, { "oma-reject-network-initiated-session", 0, 0, G_OPTION_ARG_STRING, &reject_str, "Reject network initiated OMA DM session", "[Session ID]" }, { "oma-cancel-session", 0, 0, G_OPTION_ARG_NONE, &cancel_flag, "Cancel current OMA DM session", NULL }, { NULL } }; GOptionGroup * mmcli_modem_oma_get_option_group (void) { GOptionGroup *group; group = g_option_group_new ("oma", "OMA options", "Show OMA options", NULL, NULL); g_option_group_add_entries (group, entries); return group; } gboolean mmcli_modem_oma_options_enabled (void) { static guint n_actions = 0; static gboolean checked = FALSE; if (checked) return !!n_actions; n_actions = (status_flag + !!setup_str + !!start_str + !!accept_str + !!reject_str + cancel_flag); if (n_actions > 1) { g_printerr ("error: too many OMA actions requested\n"); exit (EXIT_FAILURE); } if (status_flag) mmcli_force_sync_operation (); checked = TRUE; return !!n_actions; } static void context_free (Context *ctx) { if (!ctx) return; if (ctx->cancellable) g_object_unref (ctx->cancellable); if (ctx->modem_oma) g_object_unref (ctx->modem_oma); if (ctx->object) g_object_unref (ctx->object); if (ctx->manager) g_object_unref (ctx->manager); g_free (ctx); } static void ensure_modem_oma (void) { if (!ctx->modem_oma) { g_printerr ("error: modem has no OMA capabilities\n"); exit (EXIT_FAILURE); } /* Success */ } void mmcli_modem_oma_shutdown (void) { context_free (ctx); } static void print_oma_status (void) { gchar *features_str; const MMOmaPendingNetworkInitiatedSession *pending_sessions; guint n_pending_sessions; #undef VALIDATE_UNKNOWN #define VALIDATE_UNKNOWN(str) (str ? str : "unknown") features_str = mm_oma_feature_build_string_from_mask (mm_modem_oma_get_features (ctx->modem_oma)); /* Global IDs */ g_print ("\n" "%s\n", VALIDATE_UNKNOWN (mm_modem_oma_get_path (ctx->modem_oma))); /* Overall setup */ g_print (" -------------------------\n" " Setup | features: '%s'\n", VALIDATE_UNKNOWN (features_str)); /* Current session */ if (mm_modem_oma_get_session_type (ctx->modem_oma) != MM_OMA_SESSION_TYPE_UNKNOWN) { g_print (" -------------------------\n" " Current session | type: '%s'\n" " | state: '%s'\n", VALIDATE_UNKNOWN (mm_oma_session_type_get_string (mm_modem_oma_get_session_type (ctx->modem_oma))), VALIDATE_UNKNOWN (mm_oma_session_state_get_string (mm_modem_oma_get_session_state (ctx->modem_oma)))); } /* If 1 or more pending sessions... */ if (mm_modem_peek_pending_network_initiated_sessions (ctx->modem_oma, &pending_sessions, &n_pending_sessions) && n_pending_sessions > 0) { guint i; g_print (" -------------------------\n" " Pending sessions |\n"); for (i = 0; i < n_pending_sessions; i++) { g_print (" [%u] | type: '%s'\n" " | id: '%u'\n", i, VALIDATE_UNKNOWN (mm_oma_session_type_get_string (pending_sessions[i].session_type)), pending_sessions[i].session_id); } } g_free (features_str); } static void setup_process_reply (gboolean result, const GError *error) { if (!result) { g_printerr ("error: couldn't setup OMA features: '%s'\n", error ? error->message : "unknown error"); exit (EXIT_FAILURE); } g_print ("Successfully setup OMA features\n"); } static void setup_ready (MMModemOma *modem, GAsyncResult *result) { gboolean res; GError *error = NULL; res = mm_modem_oma_setup_finish (modem, result, &error); setup_process_reply (res, error); mmcli_async_operation_done (); } static void start_process_reply (gboolean result, const GError *error) { if (!result) { g_printerr ("error: couldn't start OMA session: '%s'\n", error ? error->message : "unknown error"); exit (EXIT_FAILURE); } g_print ("Successfully started OMA session\n"); } static void start_ready (MMModemOma *modem, GAsyncResult *result) { gboolean res; GError *error = NULL; res = mm_modem_oma_start_client_initiated_session_finish (modem, result, &error); start_process_reply (res, error); mmcli_async_operation_done (); } static void accept_process_reply (gboolean result, const GError *error) { if (!result) { g_printerr ("error: couldn't %s OMA session: '%s'\n", accept_str ? "accept" : "reject", error ? error->message : "unknown error"); exit (EXIT_FAILURE); } g_print ("Successfully %s OMA session\n", accept_str ? "accepted" : "rejected"); } static void accept_ready (MMModemOma *modem, GAsyncResult *result) { gboolean res; GError *error = NULL; res = mm_modem_oma_accept_network_initiated_session_finish (modem, result, &error); accept_process_reply (res, error); mmcli_async_operation_done (); } static void cancel_process_reply (gboolean result, const GError *error) { if (!result) { g_printerr ("error: couldn't cancel OMA session: '%s'\n", error ? error->message : "unknown error"); exit (EXIT_FAILURE); } g_print ("Successfully cancelled OMA session\n"); } static void cancel_ready (MMModemOma *modem, GAsyncResult *result) { gboolean res; GError *error = NULL; res = mm_modem_oma_cancel_session_finish (modem, result, &error); cancel_process_reply (res, error); mmcli_async_operation_done (); } static void get_modem_ready (GObject *source, GAsyncResult *result) { ctx->object = mmcli_get_modem_finish (result, &ctx->manager); ctx->modem_oma = mm_object_get_modem_oma (ctx->object); /* Setup operation timeout */ if (ctx->modem_oma) mmcli_force_operation_timeout (G_DBUS_PROXY (ctx->modem_oma)); ensure_modem_oma (); g_assert (!status_flag); /* Request to setup OMA features? */ if (setup_str) { GError *error = NULL; MMOmaFeature features; features = mm_common_get_oma_features_from_string (setup_str, &error); if (error) { g_printerr ("Error parsing OMA features string: '%s'\n", error->message); exit (EXIT_FAILURE); } g_debug ("Asynchronously setting up OMA features..."); mm_modem_oma_setup (ctx->modem_oma, features, ctx->cancellable, (GAsyncReadyCallback)setup_ready, NULL); return; } /* Request to start session? */ if (start_str) { GError *error = NULL; MMOmaSessionType session_type; session_type = mm_common_get_oma_session_type_from_string (start_str, &error); if (error) { g_printerr ("Error parsing OMA session type string: '%s'\n", error->message); exit (EXIT_FAILURE); } g_debug ("Asynchronously starting OMA session..."); mm_modem_oma_start_client_initiated_session (ctx->modem_oma, session_type, ctx->cancellable, (GAsyncReadyCallback)start_ready, NULL); return; } /* Request to accept or reject session? */ if (accept_str || reject_str) { guint session_id; if (!mm_get_uint_from_str (accept_str ? accept_str : reject_str, &session_id)) { g_printerr ("Error parsing OMA session id string: not a number"); exit (EXIT_FAILURE); } g_debug ("Asynchronously %s OMA session...", accept_str ? "accepting" : "rejecting"); mm_modem_oma_accept_network_initiated_session (ctx->modem_oma, session_id, !!accept_str, ctx->cancellable, (GAsyncReadyCallback)accept_ready, NULL); return; } /* Request to cancel a session? */ if (cancel_flag) { g_debug ("Asynchronously cancelling OMA session..."); mm_modem_oma_cancel_session (ctx->modem_oma, ctx->cancellable, (GAsyncReadyCallback)cancel_ready, NULL); return; } g_warn_if_reached (); } void mmcli_modem_oma_run_asynchronous (GDBusConnection *connection, GCancellable *cancellable) { /* Initialize context */ ctx = g_new0 (Context, 1); if (cancellable) ctx->cancellable = g_object_ref (cancellable); /* Get proper modem */ mmcli_get_modem (connection, mmcli_get_common_modem_string (), cancellable, (GAsyncReadyCallback)get_modem_ready, NULL); } void mmcli_modem_oma_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_oma = mm_object_get_modem_oma (ctx->object); /* Setup operation timeout */ if (ctx->modem_oma) mmcli_force_operation_timeout (G_DBUS_PROXY (ctx->modem_oma)); ensure_modem_oma (); /* Request to get status? */ if (status_flag) { g_debug ("Printing OMA status..."); print_oma_status (); return; } /* Request to setup OMA features? */ if (setup_str) { gboolean result; GError *error = NULL; MMOmaFeature features; features = mm_common_get_oma_features_from_string (setup_str, &error); if (error) { g_printerr ("Error parsing OMA features string: '%s'\n", error->message); exit (EXIT_FAILURE); } g_debug ("Synchronously setting up OMA features..."); result = mm_modem_oma_setup_sync (ctx->modem_oma, features, NULL, &error); setup_process_reply (result, error); return; } /* Request to start session? */ if (start_str) { gboolean result; GError *error = NULL; MMOmaSessionType session_type; session_type = mm_common_get_oma_session_type_from_string (start_str, &error); if (error) { g_printerr ("Error parsing OMA session type string: '%s'\n", error->message); exit (EXIT_FAILURE); } g_debug ("Synchronously starting OMA session..."); result = mm_modem_oma_start_client_initiated_session_sync (ctx->modem_oma, session_type, NULL, &error); start_process_reply (result, error); return; } /* Request to accept or reject session? */ if (accept_str || reject_str) { gboolean result; GError *error = NULL; guint session_id; if (!mm_get_uint_from_str (accept_str ? accept_str : reject_str, &session_id)) { g_printerr ("Error parsing OMA session id string: not a number"); exit (EXIT_FAILURE); } g_debug ("Synchronously %s OMA session...", accept_str ? "accepting" : "rejecting"); result = mm_modem_oma_accept_network_initiated_session_sync (ctx->modem_oma, session_id, !!accept_str, NULL, &error); accept_process_reply (result, error); return; } /* Request to cancel a session? */ if (cancel_flag) { gboolean result; g_debug ("Synchronously cancelling OMA session..."); result = mm_modem_oma_cancel_session_sync (ctx->modem_oma, NULL, &error); cancel_process_reply (result, error); return; } g_warn_if_reached (); }