diff options
Diffstat (limited to 'libmm-glib')
-rw-r--r-- | libmm-glib/Makefile.am | 3 | ||||
-rw-r--r-- | libmm-glib/libmm-glib.h | 1 | ||||
-rw-r--r-- | libmm-glib/mm-kernel-event-properties.c | 454 | ||||
-rw-r--r-- | libmm-glib/mm-kernel-event-properties.h | 97 | ||||
-rw-r--r-- | libmm-glib/mm-manager.c | 124 | ||||
-rw-r--r-- | libmm-glib/mm-manager.h | 14 |
6 files changed, 693 insertions, 0 deletions
diff --git a/libmm-glib/Makefile.am b/libmm-glib/Makefile.am index e257d6f0..64bca40e 100644 --- a/libmm-glib/Makefile.am +++ b/libmm-glib/Makefile.am @@ -81,6 +81,8 @@ libmm_glib_la_SOURCES = \ mm-cdma-manual-activation-properties.c \ mm-signal.h \ mm-signal.c \ + mm-kernel-event-properties.h \ + mm-kernel-event-properties.c \ $(NULL) libmm_glib_la_CPPFLAGS = \ @@ -149,6 +151,7 @@ include_HEADERS = \ mm-firmware-properties.h \ mm-cdma-manual-activation-properties.h \ mm-signal.h \ + mm-kernel-event-properties.h \ $(NULL) CLEANFILES = diff --git a/libmm-glib/libmm-glib.h b/libmm-glib/libmm-glib.h index fa4c7e2f..53f0a196 100644 --- a/libmm-glib/libmm-glib.h +++ b/libmm-glib/libmm-glib.h @@ -72,6 +72,7 @@ #include <mm-firmware-properties.h> #include <mm-cdma-manual-activation-properties.h> #include <mm-signal.h> +#include <mm-kernel-event-properties.h> /* generated */ #include <mm-errors-types.h> diff --git a/libmm-glib/mm-kernel-event-properties.c b/libmm-glib/mm-kernel-event-properties.c new file mode 100644 index 00000000..6782fbf7 --- /dev/null +++ b/libmm-glib/mm-kernel-event-properties.c @@ -0,0 +1,454 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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: + * + * Copyright (C) 2016 Velocloud, Inc. + */ + +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +#include "mm-errors-types.h" +#include "mm-enums-types.h" +#include "mm-common-helpers.h" +#include "mm-kernel-event-properties.h" + +/** + * SECTION: mm-kernel-event-properties + * @title: MMKernelEventProperties + * @short_description: Helper object to handle kernel event properties. + * + * The #MMKernelEventProperties is an object handling the properties to be set + * in reported kernel events. + * + * This object is created by the user and passed to ModemManager with either + * mm_manager_report_kernel_event() or mm_manager_report_kernel_event_sync(). + */ + +G_DEFINE_TYPE (MMKernelEventProperties, mm_kernel_event_properties, G_TYPE_OBJECT) + +#define PROPERTY_ACTION "action" +#define PROPERTY_SUBSYSTEM "subsystem" +#define PROPERTY_NAME "name" +#define PROPERTY_UID "uid" + +struct _MMKernelEventPropertiesPrivate { + gchar *action; + gchar *subsystem; + gchar *name; + gchar *uid; +}; + +/*****************************************************************************/ + +/** + * mm_kernel_event_properties_set_action: + * @self: A #MMKernelEventProperties. + * @action: The action to set. + * + * Sets the action. + */ +void +mm_kernel_event_properties_set_action (MMKernelEventProperties *self, + const gchar *action) +{ + g_return_if_fail (MM_IS_KERNEL_EVENT_PROPERTIES (self)); + + g_free (self->priv->action); + self->priv->action = g_strdup (action); +} + +/** + * mm_kernel_event_properties_get_action: + * @self: A #MMKernelEventProperties. + * + * Gets the action. + * + * Returns: (transfer none): The action. Do not free the returned value, it is owned by @self. + */ +const gchar * +mm_kernel_event_properties_get_action (MMKernelEventProperties *self) +{ + g_return_val_if_fail (MM_IS_KERNEL_EVENT_PROPERTIES (self), NULL); + + return self->priv->action; +} + +/*****************************************************************************/ + +/** + * mm_kernel_event_properties_set_subsystem: + * @self: A #MMKernelEventProperties. + * @subsystem: The subsystem to set. + * + * Sets the subsystem. + */ +void +mm_kernel_event_properties_set_subsystem (MMKernelEventProperties *self, + const gchar *subsystem) +{ + g_return_if_fail (MM_IS_KERNEL_EVENT_PROPERTIES (self)); + + g_free (self->priv->subsystem); + self->priv->subsystem = g_strdup (subsystem); +} + +/** + * mm_kernel_event_properties_get_subsystem: + * @self: A #MMKernelEventProperties. + * + * Gets the subsystem. + * + * Returns: (transfer none): The subsystem. Do not free the returned value, it is owned by @self. + */ +const gchar * +mm_kernel_event_properties_get_subsystem (MMKernelEventProperties *self) +{ + g_return_val_if_fail (MM_IS_KERNEL_EVENT_PROPERTIES (self), NULL); + + return self->priv->subsystem; +} + +/*****************************************************************************/ + +/** + * mm_kernel_event_properties_set_name: + * @self: A #MMKernelEventProperties. + * @name: The name to set. + * + * Sets the name. + */ +void +mm_kernel_event_properties_set_name (MMKernelEventProperties *self, + const gchar *name) +{ + g_return_if_fail (MM_IS_KERNEL_EVENT_PROPERTIES (self)); + + g_free (self->priv->name); + self->priv->name = g_strdup (name); +} + +/** + * mm_kernel_event_properties_get_name: + * @self: A #MMKernelEventProperties. + * + * Gets the name. + * + * Returns: (transfer none): The name. Do not free the returned value, it is owned by @self. + */ +const gchar * +mm_kernel_event_properties_get_name (MMKernelEventProperties *self) +{ + g_return_val_if_fail (MM_IS_KERNEL_EVENT_PROPERTIES (self), NULL); + + return self->priv->name; +} + +/*****************************************************************************/ + +/** + * mm_kernel_event_properties_set_uid: + * @self: A #MMKernelEventProperties. + * @uid: The uid to set. + * + * Sets the unique ID of the physical device. + */ +void +mm_kernel_event_properties_set_uid (MMKernelEventProperties *self, + const gchar *uid) +{ + g_return_if_fail (MM_IS_KERNEL_EVENT_PROPERTIES (self)); + + g_free (self->priv->uid); + self->priv->uid = g_strdup (uid); +} + +/** + * mm_kernel_event_properties_get_uid: + * @self: A #MMKernelEventProperties. + * + * Gets the unique ID of the physical device. + * + * Returns: (transfer none): The uid. Do not free the returned value, it is owned by @self. + */ +const gchar * +mm_kernel_event_properties_get_uid (MMKernelEventProperties *self) +{ + g_return_val_if_fail (MM_IS_KERNEL_EVENT_PROPERTIES (self), NULL); + + return self->priv->uid; +} + +/*****************************************************************************/ + +GVariant * +mm_kernel_event_properties_get_dictionary (MMKernelEventProperties *self) +{ + GVariantBuilder builder; + + /* We do allow NULL */ + if (!self) + return NULL; + + g_return_val_if_fail (MM_IS_KERNEL_EVENT_PROPERTIES (self), NULL); + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + + if (self->priv->action) + g_variant_builder_add (&builder, + "{sv}", + PROPERTY_ACTION, + g_variant_new_string (self->priv->action)); + + if (self->priv->subsystem) + g_variant_builder_add (&builder, + "{sv}", + PROPERTY_SUBSYSTEM, + g_variant_new_string (self->priv->subsystem)); + + if (self->priv->name) + g_variant_builder_add (&builder, + "{sv}", + PROPERTY_NAME, + g_variant_new_string (self->priv->name)); + + if (self->priv->uid) + g_variant_builder_add (&builder, + "{sv}", + PROPERTY_UID, + g_variant_new_string (self->priv->uid)); + + return g_variant_ref_sink (g_variant_builder_end (&builder)); +} + +/*****************************************************************************/ + +static gboolean +consume_string (MMKernelEventProperties *self, + const gchar *key, + const gchar *value, + GError **error) +{ + if (g_str_equal (key, PROPERTY_ACTION)) + mm_kernel_event_properties_set_action (self, value); + else if (g_str_equal (key, PROPERTY_SUBSYSTEM)) + mm_kernel_event_properties_set_subsystem (self, value); + else if (g_str_equal (key, PROPERTY_NAME)) + mm_kernel_event_properties_set_name (self, value); + else if (g_str_equal (key, PROPERTY_UID)) + mm_kernel_event_properties_set_uid (self, value); + else { + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_INVALID_ARGS, + "Invalid properties string, unexpected key '%s'", + key); + return FALSE; + } + + return TRUE; +} + +typedef struct { + MMKernelEventProperties *properties; + GError *error; +} ParseKeyValueContext; + +static gboolean +key_value_foreach (const gchar *key, + const gchar *value, + ParseKeyValueContext *ctx) +{ + return consume_string (ctx->properties, + key, + value, + &ctx->error); +} + +MMKernelEventProperties * +mm_kernel_event_properties_new_from_string (const gchar *str, + GError **error) +{ + ParseKeyValueContext ctx; + + ctx.properties = mm_kernel_event_properties_new (); + ctx.error = NULL; + + mm_common_parse_key_value_string (str, + &ctx.error, + (MMParseKeyValueForeachFn) key_value_foreach, + &ctx); + + /* If error, destroy the object */ + if (ctx.error) { + g_propagate_error (error, ctx.error); + g_object_unref (ctx.properties); + ctx.properties = NULL; + } + + return ctx.properties; +} + +/*****************************************************************************/ + +static gboolean +consume_variant (MMKernelEventProperties *properties, + const gchar *key, + GVariant *value, + GError **error) +{ + if (g_str_equal (key, PROPERTY_ACTION)) + mm_kernel_event_properties_set_action ( + properties, + g_variant_get_string (value, NULL)); + else if (g_str_equal (key, PROPERTY_SUBSYSTEM)) + mm_kernel_event_properties_set_subsystem ( + properties, + g_variant_get_string (value, NULL)); + else if (g_str_equal (key, PROPERTY_NAME)) + mm_kernel_event_properties_set_name ( + properties, + g_variant_get_string (value, NULL)); + else if (g_str_equal (key, PROPERTY_UID)) + mm_kernel_event_properties_set_uid ( + properties, + g_variant_get_string (value, NULL)); + else { + /* Set error */ + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_INVALID_ARGS, + "Invalid properties dictionary, unexpected key '%s'", + key); + return FALSE; + } + + return TRUE; +} + +MMKernelEventProperties * +mm_kernel_event_properties_new_from_dictionary (GVariant *dictionary, + GError **error) +{ + GError *inner_error = NULL; + GVariantIter iter; + gchar *key; + GVariant *value; + MMKernelEventProperties *properties; + + properties = mm_kernel_event_properties_new (); + if (!dictionary) + return properties; + + if (!g_variant_is_of_type (dictionary, G_VARIANT_TYPE ("a{sv}"))) { + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_INVALID_ARGS, + "Cannot create kernel event properties from dictionary: " + "invalid variant type received"); + g_object_unref (properties); + return NULL; + } + + g_variant_iter_init (&iter, dictionary); + while (!inner_error && + g_variant_iter_next (&iter, "{sv}", &key, &value)) { + consume_variant (properties, + key, + value, + &inner_error); + g_free (key); + g_variant_unref (value); + } + + /* If error, destroy the object */ + if (inner_error) { + g_propagate_error (error, inner_error); + g_object_unref (properties); + properties = NULL; + } + + return properties; +} + +/*****************************************************************************/ + +/** + * mm_kernel_event_properties_dup: + * @orig: a #MMKernelEventProperties + * + * Returns a copy of @orig. + * + * Returns: (transfer full): a #MMKernelEventProperties + */ +MMKernelEventProperties * +mm_kernel_event_properties_dup (MMKernelEventProperties *orig) +{ + GVariant *dict; + MMKernelEventProperties *copy; + GError *error = NULL; + + g_return_val_if_fail (MM_IS_KERNEL_EVENT_PROPERTIES (orig), NULL); + + dict = mm_kernel_event_properties_get_dictionary (orig); + copy = mm_kernel_event_properties_new_from_dictionary (dict, &error); + g_assert_no_error (error); + g_variant_unref (dict); + + return copy; +} + +/*****************************************************************************/ + +/** + * mm_kernel_event_properties_new: + * + * Creates a new empty #MMKernelEventProperties. + * + * Returns: (transfer full): a #MMKernelEventProperties. The returned value should be freed with g_object_unref(). + */ +MMKernelEventProperties * +mm_kernel_event_properties_new (void) +{ + return (MM_KERNEL_EVENT_PROPERTIES (g_object_new (MM_TYPE_KERNEL_EVENT_PROPERTIES, NULL))); +} + +static void +mm_kernel_event_properties_init (MMKernelEventProperties *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + MM_TYPE_KERNEL_EVENT_PROPERTIES, + MMKernelEventPropertiesPrivate); +} + +static void +finalize (GObject *object) +{ + MMKernelEventProperties *self = MM_KERNEL_EVENT_PROPERTIES (object); + + g_free (self->priv->action); + g_free (self->priv->subsystem); + g_free (self->priv->name); + g_free (self->priv->uid); + + G_OBJECT_CLASS (mm_kernel_event_properties_parent_class)->finalize (object); +} + +static void +mm_kernel_event_properties_class_init (MMKernelEventPropertiesClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (MMKernelEventPropertiesPrivate)); + + object_class->finalize = finalize; +} diff --git a/libmm-glib/mm-kernel-event-properties.h b/libmm-glib/mm-kernel-event-properties.h new file mode 100644 index 00000000..576e356b --- /dev/null +++ b/libmm-glib/mm-kernel-event-properties.h @@ -0,0 +1,97 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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: + * + * Copyright (C) 2016 Velocloud, Inc. + */ + +#ifndef MM_KERNEL_EVENT_PROPERTIES_H +#define MM_KERNEL_EVENT_PROPERTIES_H + +#if !defined (__LIBMM_GLIB_H_INSIDE__) && !defined (LIBMM_GLIB_COMPILATION) +#error "Only <libmm-glib.h> can be included directly." +#endif + +#include <ModemManager.h> +#include <glib-object.h> + +G_BEGIN_DECLS + +#define MM_TYPE_KERNEL_EVENT_PROPERTIES (mm_kernel_event_properties_get_type ()) +#define MM_KERNEL_EVENT_PROPERTIES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_KERNEL_EVENT_PROPERTIES, MMKernelEventProperties)) +#define MM_KERNEL_EVENT_PROPERTIES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_KERNEL_EVENT_PROPERTIES, MMKernelEventPropertiesClass)) +#define MM_IS_KERNEL_EVENT_PROPERTIES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_KERNEL_EVENT_PROPERTIES)) +#define MM_IS_KERNEL_EVENT_PROPERTIES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_KERNEL_EVENT_PROPERTIES)) +#define MM_KERNEL_EVENT_PROPERTIES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_KERNEL_EVENT_PROPERTIES, MMKernelEventPropertiesClass)) + +typedef struct _MMKernelEventProperties MMKernelEventProperties; +typedef struct _MMKernelEventPropertiesClass MMKernelEventPropertiesClass; +typedef struct _MMKernelEventPropertiesPrivate MMKernelEventPropertiesPrivate; + +/** + * MMKernelEventProperties: + * + * The #MMKernelEventProperties structure contains private data and should only be + * accessed using the provided API. + */ +struct _MMKernelEventProperties { + /*< private >*/ + GObject parent; + MMKernelEventPropertiesPrivate *priv; +}; + +struct _MMKernelEventPropertiesClass { + /*< private >*/ + GObjectClass parent; +}; + +GType mm_kernel_event_properties_get_type (void); + +MMKernelEventProperties *mm_kernel_event_properties_new (void); + +void mm_kernel_event_properties_set_action (MMKernelEventProperties *self, + const gchar *action); +const gchar *mm_kernel_event_properties_get_action (MMKernelEventProperties *self); + +void mm_kernel_event_properties_set_subsystem (MMKernelEventProperties *self, + const gchar *subsystem); +const gchar *mm_kernel_event_properties_get_subsystem (MMKernelEventProperties *self); + +void mm_kernel_event_properties_set_name (MMKernelEventProperties *self, + const gchar *name); +const gchar *mm_kernel_event_properties_get_name (MMKernelEventProperties *self); + +void mm_kernel_event_properties_set_uid (MMKernelEventProperties *self, + const gchar *uid); +const gchar *mm_kernel_event_properties_get_uid (MMKernelEventProperties *self); + +/*****************************************************************************/ +/* ModemManager/libmm-glib/mmcli specific methods */ + +#if defined (_LIBMM_INSIDE_MM) || \ + defined (_LIBMM_INSIDE_MMCLI) || \ + defined (LIBMM_GLIB_COMPILATION) + +MMKernelEventProperties *mm_kernel_event_properties_new_from_string (const gchar *str, + GError **error); + +MMKernelEventProperties *mm_kernel_event_properties_new_from_dictionary (GVariant *dictionary, + GError **error); + +MMKernelEventProperties *mm_kernel_event_properties_dup (MMKernelEventProperties *orig); + +GVariant *mm_kernel_event_properties_get_dictionary (MMKernelEventProperties *self); + +#endif + +G_END_DECLS + +#endif /* MM_KERNEL_EVENT_PROPERTIES_H */ diff --git a/libmm-glib/mm-manager.c b/libmm-glib/mm-manager.c index cb196b3f..6a9ce5dd 100644 --- a/libmm-glib/mm-manager.c +++ b/libmm-glib/mm-manager.c @@ -497,6 +497,130 @@ mm_manager_scan_devices_sync (MMManager *manager, /*****************************************************************************/ +/** + * mm_manager_report_kernel_event_finish: + * @manager: A #MMManager. + * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to mm_manager_report_kernel_event(). + * @error: Return location for error or %NULL. + * + * Finishes an operation started with mm_manager_report_kernel_event(). + * + * Returns: %TRUE if the operation succeded, %FALSE if @error is set. + */ +gboolean +mm_manager_report_kernel_event_finish (MMManager *manager, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void +report_kernel_event_ready (MmGdbusOrgFreedesktopModemManager1 *manager_iface_proxy, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + + if (!mm_gdbus_org_freedesktop_modem_manager1_call_report_kernel_event_finish ( + manager_iface_proxy, + res, + &error)) + g_task_return_error (task, error); + else + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +/** + * mm_manager_report_kernel_event: + * @manager: A #MMManager. + * @properties: the properties of the kernel event. + * @cancellable: (allow-none): A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL. + * @user_data: User data to pass to @callback. + * + * Asynchronously report kernel event. + * + * When the operation is finished, @callback will be invoked in the + * <link linkend="g-main-context-push-thread-default">thread-default main loop</link> + * of the thread you are calling this method from. You can then call + * mm_manager_report_kernel_event_finish() to get the result of the operation. + * + * See mm_manager_report_kernel_event_sync() for the synchronous, blocking version of this method. + */ +void +mm_manager_report_kernel_event (MMManager *manager, + MMKernelEventProperties *properties, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + GError *inner_error = NULL; + GVariant *dictionary; + + g_return_if_fail (MM_IS_MANAGER (manager)); + + task = g_task_new (manager, cancellable, callback, user_data); + + if (!ensure_modem_manager1_proxy (manager, &inner_error)) { + g_task_return_error (task, inner_error); + g_object_unref (task); + return; + } + + dictionary = mm_kernel_event_properties_get_dictionary (properties); + mm_gdbus_org_freedesktop_modem_manager1_call_report_kernel_event ( + manager->priv->manager_iface_proxy, + dictionary, + cancellable, + (GAsyncReadyCallback)report_kernel_event_ready, + task); + g_variant_unref (dictionary); +} + +/** + * mm_manager_report_kernel_event_sync: + * @manager: A #MMManager. + * @properties: the properties of the kernel event. + * @cancellable: (allow-none): A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Synchronously report kernel event. + * + * The calling thread is blocked until a reply is received. + * + * See mm_manager_report_kernel_event() for the asynchronous version of this method. + * + * Returns: %TRUE if the operation succeded, %FALSE if @error is set. + */ +gboolean +mm_manager_report_kernel_event_sync (MMManager *manager, + MMKernelEventProperties *properties, + GCancellable *cancellable, + GError **error) +{ + GVariant *dictionary; + gboolean result; + + g_return_val_if_fail (MM_IS_MANAGER (manager), FALSE); + + if (!ensure_modem_manager1_proxy (manager, error)) + return FALSE; + + dictionary = mm_kernel_event_properties_get_dictionary (properties); + result = (mm_gdbus_org_freedesktop_modem_manager1_call_report_kernel_event_sync ( + manager->priv->manager_iface_proxy, + dictionary, + cancellable, + error)); + g_variant_unref (dictionary); + return result; +} + +/*****************************************************************************/ + static void register_dbus_errors (void) { diff --git a/libmm-glib/mm-manager.h b/libmm-glib/mm-manager.h index 96c3066a..57a129f5 100644 --- a/libmm-glib/mm-manager.h +++ b/libmm-glib/mm-manager.h @@ -33,6 +33,7 @@ #include <ModemManager.h> #include "mm-gdbus-modem.h" +#include "mm-kernel-event-properties.h" G_BEGIN_DECLS @@ -108,6 +109,19 @@ gboolean mm_manager_scan_devices_sync (MMManager *manager, GCancellable *cancellable, GError **error); +void mm_manager_report_kernel_event (MMManager *manager, + MMKernelEventProperties *properties, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_manager_report_kernel_event_finish (MMManager *manager, + GAsyncResult *res, + GError **error); +gboolean mm_manager_report_kernel_event_sync (MMManager *manager, + MMKernelEventProperties *properties, + GCancellable *cancellable, + GError **error); + G_END_DECLS #endif /* _MM_MANAGER_H_ */ |