aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/mmcli-modem.c67
-rw-r--r--libmm-glib/mm-modem.c59
-rw-r--r--libmm-glib/mm-modem.h15
-rw-r--r--new/org.freedesktop.ModemManager1.Modem.xml14
-rw-r--r--src/mm-broadband-modem.c31
-rw-r--r--src/mm-iface-modem.c56
-rw-r--r--src/mm-iface-modem.h10
7 files changed, 252 insertions, 0 deletions
diff --git a/cli/mmcli-modem.c b/cli/mmcli-modem.c
index 73deafb3..541e9069 100644
--- a/cli/mmcli-modem.c
+++ b/cli/mmcli-modem.c
@@ -51,6 +51,8 @@ static gboolean enable_flag;
static gboolean disable_flag;
static gboolean reset_flag;
static gchar *factory_reset_str;
+static gchar *command_str;
+static gint command_timeout;
static gboolean list_bearers_flag;
static gchar *create_bearer_str;
static gchar *delete_bearer_str;
@@ -79,6 +81,14 @@ static GOptionEntry entries[] = {
"Reset a given modem to its factory state",
"[CODE]"
},
+ { "command", 0, 0, G_OPTION_ARG_STRING, &command_str,
+ "Send an AT command to the modem",
+ "[COMMAND]"
+ },
+ { "command-timeout", 0, 0, G_OPTION_ARG_INT, &command_timeout,
+ "Timeout for AT command",
+ "[SECONDS]"
+ },
{ "list-bearers", 0, 0, G_OPTION_ARG_NONE, &list_bearers_flag,
"List packet data bearers available in a given modem",
NULL
@@ -139,6 +149,7 @@ mmcli_modem_options_enabled (void)
!!create_bearer_str +
!!delete_bearer_str +
!!factory_reset_str +
+ !!command_str +
!!set_allowed_modes_str +
!!set_preferred_mode_str +
!!set_allowed_bands_str);
@@ -542,6 +553,35 @@ factory_reset_ready (MMModem *modem,
mmcli_async_operation_done ();
}
+
+static void
+command_process_reply (gchar *result,
+ const GError *error)
+{
+ if (!result) {
+ g_printerr ("error: command failed: '%s'\n",
+ error ? error->message : "unknown error");
+ exit (EXIT_FAILURE);
+ }
+
+ g_print ("response: '%s'\n", result);
+ g_free (result);
+}
+
+static void
+command_ready (MMModem *modem,
+ GAsyncResult *result,
+ gpointer nothing)
+{
+ gchar * operation_result;
+ GError *error = NULL;
+
+ operation_result = mm_modem_command_finish (modem, result, &error);
+ command_process_reply (operation_result, error);
+
+ mmcli_async_operation_done ();
+}
+
static void
list_bearers_process_reply (GList *result,
const GError *error)
@@ -825,6 +865,18 @@ get_modem_ready (GObject *source,
return;
}
+ /* Request to send a command to the modem? */
+ if (command_str) {
+ g_debug ("Asynchronously sending a command to the modem...");
+ mm_modem_command (ctx->modem,
+ command_str,
+ command_timeout ? command_timeout : 30,
+ ctx->cancellable,
+ (GAsyncReadyCallback)command_ready,
+ NULL);
+ return;
+ }
+
/* Request to list bearers? */
if (list_bearers_flag) {
g_debug ("Asynchronously listing bearers in modem...");
@@ -983,6 +1035,21 @@ mmcli_modem_run_synchronous (GDBusConnection *connection)
return;
}
+
+ /* Request to send a command to the modem? */
+ if (command_str) {
+ gchar *result;
+
+ g_debug ("Synchronously sending command to modem...");
+ result = mm_modem_command_sync (ctx->modem,
+ command_str,
+ command_timeout ? command_timeout : 30,
+ NULL,
+ &error);
+ command_process_reply (result, error);
+ return;
+ }
+
/* Request to list the bearers? */
if (list_bearers_flag) {
GList *result;
diff --git a/libmm-glib/mm-modem.c b/libmm-glib/mm-modem.c
index 1b3f2521..bc1887ba 100644
--- a/libmm-glib/mm-modem.c
+++ b/libmm-glib/mm-modem.c
@@ -1449,6 +1449,65 @@ mm_modem_factory_reset_sync (MMModem *self,
error);
}
+
+void
+mm_modem_command (MMModem *self,
+ const gchar *cmd,
+ guint timeout,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (MM_GDBUS_IS_MODEM (self));
+
+ mm_gdbus_modem_call_command (self,
+ cmd,
+ timeout,
+ cancellable,
+ callback,
+ user_data);
+}
+
+gchar *
+mm_modem_command_finish (MMModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ gchar *result;
+
+ g_return_val_if_fail (MM_GDBUS_IS_MODEM (self), FALSE);
+
+ if (!mm_gdbus_modem_call_command_finish (self,
+ &result,
+ res,
+ error))
+ return NULL;
+
+ return result;
+}
+
+gchar *
+mm_modem_command_sync (MMModem *self,
+ const gchar *cmd,
+ guint timeout,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gchar *result;
+
+ g_return_val_if_fail (MM_GDBUS_IS_MODEM (self), NULL);
+
+ if (!mm_gdbus_modem_call_command_sync (self,
+ cmd,
+ timeout,
+ &result,
+ cancellable,
+ error))
+ return NULL;
+
+ return result;
+}
+
gboolean
mm_modem_set_allowed_modes_finish (MMModem *self,
GAsyncResult *res,
diff --git a/libmm-glib/mm-modem.h b/libmm-glib/mm-modem.h
index f7406338..90c33e91 100644
--- a/libmm-glib/mm-modem.h
+++ b/libmm-glib/mm-modem.h
@@ -161,6 +161,21 @@ gboolean mm_modem_factory_reset_sync (MMModem *self,
GCancellable *cancellable,
GError **error);
+void mm_modem_command (MMModem *self,
+ const gchar *cmd,
+ guint timeout,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gchar *mm_modem_command_finish (MMModem *self,
+ GAsyncResult *res,
+ GError **error);
+gchar *mm_modem_command_sync (MMModem *self,
+ const gchar *arg_cmd,
+ guint timeout,
+ GCancellable *cancellable,
+ GError **error);
+
void mm_modem_set_allowed_modes (MMModem *self,
MMModemMode modes,
MMModemMode preferred,
diff --git a/new/org.freedesktop.ModemManager1.Modem.xml b/new/org.freedesktop.ModemManager1.Modem.xml
index 26a0f1bb..c98f6d9c 100644
--- a/new/org.freedesktop.ModemManager1.Modem.xml
+++ b/new/org.freedesktop.ModemManager1.Modem.xml
@@ -147,6 +147,20 @@
</method>
<!--
+ Command
+ @cmd The command string, e.g. "AT+GCAP" or "+GCAP" (leading AT is inserted if necessary)
+ @timeout The number of seconds to wait for a response
+ @response The modem's response
+
+ Send an arbitrary AT command to a modem and get the response.
+ -->
+ <method name="Command">
+ <arg name="cmd" type="s" direction="in" />
+ <arg name="timeout" type="u" direction="in" />
+ <arg name="response" type="s" direction="out" />
+ </method>
+
+ <!--
StateChanged:
@old: A <link linkend="MMModemState">MMModemState</link> value, specifying the new state.
@new: A <link linkend="MMModemState">MMModemState</link> value, specifying the new state.
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index 6d9b16fa..0baff2d5 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -1862,6 +1862,35 @@ modem_power_up (MMIfaceModem *self,
}
/*****************************************************************************/
+/* Sending a command to the modem (Modem interface) */
+
+static const gchar *
+modem_command_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return mm_base_modem_at_command_finish (MM_BASE_MODEM (self),
+ res,
+ error);
+}
+
+static void
+modem_command (MMIfaceModem *self,
+ const gchar *cmd,
+ guint timeout,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+
+ mm_base_modem_at_command (MM_BASE_MODEM (self), cmd, timeout,
+ FALSE,
+ NULL, /* cancellable */
+ callback,
+ user_data);
+}
+
+
+/*****************************************************************************/
/* Initializing the modem (Modem interface) */
static gboolean
@@ -6668,6 +6697,8 @@ iface_modem_init (MMIfaceModem *iface)
iface->load_signal_quality_finish = modem_load_signal_quality_finish;
iface->create_bearer = modem_create_bearer;
iface->create_bearer_finish = modem_create_bearer_finish;
+ iface->command = modem_command;
+ iface->command_finish = modem_command_finish;
}
static void
diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c
index 17bf93a8..a6e1968c 100644
--- a/src/mm-iface-modem.c
+++ b/src/mm-iface-modem.c
@@ -20,6 +20,7 @@
#include "mm-modem-helpers.h"
#include "mm-iface-modem.h"
#include "mm-base-modem.h"
+#include "mm-base-modem-at.h"
#include "mm-sim.h"
#include "mm-bearer-list.h"
#include "mm-log.h"
@@ -302,6 +303,57 @@ handle_create_bearer (MmGdbusModem *skeleton,
return TRUE;
}
+static void
+command_done (MMIfaceModem *self,
+ GAsyncResult *res,
+ DbusCallContext *ctx)
+{
+ GError *error = NULL;
+ const gchar *result;
+
+ result = MM_IFACE_MODEM_GET_INTERFACE (self)->command_finish (self,
+ res,
+ &error);
+ if (error)
+ g_dbus_method_invocation_take_error (ctx->invocation,
+ error);
+ else
+ mm_gdbus_modem_complete_command (ctx->skeleton,
+ ctx->invocation,
+ result);
+ dbus_call_context_free (ctx);
+}
+
+static gboolean
+handle_command (MmGdbusModem *skeleton,
+ GDBusMethodInvocation *invocation,
+ const gchar *cmd,
+ guint timeout,
+ MMIfaceModem *self)
+{
+
+ /* If command is not implemented, report an error */
+ if (!MM_IFACE_MODEM_GET_INTERFACE (self)->command ||
+ !MM_IFACE_MODEM_GET_INTERFACE (self)->command_finish) {
+ g_dbus_method_invocation_return_error (invocation,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNSUPPORTED,
+ "Cannot send AT command to modem: "
+ "operation not supported");
+ return TRUE;
+ }
+
+ MM_IFACE_MODEM_GET_INTERFACE (self)->command (self,
+ cmd,
+ timeout,
+ (GAsyncReadyCallback)command_done,
+ dbus_call_context_new (skeleton,
+ invocation,
+ self));
+
+ return TRUE;
+}
+
/*****************************************************************************/
static gboolean
@@ -2921,6 +2973,10 @@ interface_initialization_step (InitializationContext *ctx)
G_CALLBACK (handle_create_bearer),
ctx->self);
g_signal_connect (ctx->skeleton,
+ "handle-command",
+ G_CALLBACK (handle_command),
+ ctx->self);
+ g_signal_connect (ctx->skeleton,
"handle-delete-bearer",
G_CALLBACK (handle_delete_bearer),
ctx->self);
diff --git a/src/mm-iface-modem.h b/src/mm-iface-modem.h
index de2564ec..f5a16252 100644
--- a/src/mm-iface-modem.h
+++ b/src/mm-iface-modem.h
@@ -163,6 +163,16 @@ struct _MMIfaceModem {
GAsyncResult *res,
GError **error);
+ /* Asynchronous command operation */
+ void (*command) (MMIfaceModem *self,
+ const gchar *cmd,
+ guint timeout,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ const gchar * (*command_finish) (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error);
+
/* Asynchronous allowed band setting operation */
void (*set_allowed_bands) (MMIfaceModem *self,
GArray *bands_array,