[PATCH 07/10] mmcli: new '--report-kernel-event-udev' to report kernel events based on udev

Aleksander Morgado aleksander at aleksander.es
Sat Aug 6 13:03:35 UTC 2016


This new mmcli command automatically reports kernel events from the info
gathered from udev. E.g. can be used when the ModemManager daemon was launched
with '--no-auto-scan'.
---
 cli/Makefile.am     |  5 +++
 cli/mmcli-manager.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 100 insertions(+), 1 deletion(-)

diff --git a/cli/Makefile.am b/cli/Makefile.am
index d2573db..6c2d791 100644
--- a/cli/Makefile.am
+++ b/cli/Makefile.am
@@ -38,6 +38,11 @@ mmcli_LDADD = \
 	$(top_builddir)/libmm-glib/libmm-glib.la \
 	$(NULL)
 
+if WITH_UDEV
+mmcli_CPPFLAGS += $(GUDEV_CFLAGS)
+mmcli_LDADD    += $(GUDEV_LIBS)
+endif
+
 completiondir = $(datadir)/bash-completion/completions
 
 install-data-hook:
diff --git a/cli/mmcli-manager.c b/cli/mmcli-manager.c
index d78734f..4818b3d 100644
--- a/cli/mmcli-manager.c
+++ b/cli/mmcli-manager.c
@@ -15,8 +15,8 @@
  * 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) 2011 Aleksander Morgado <aleksander at gnu.org>
  * Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2011-2016 Aleksander Morgado <aleksander at aleksander.es>
  */
 
 #include "config.h"
@@ -29,6 +29,10 @@
 #include <glib.h>
 #include <gio/gio.h>
 
+#if WITH_UDEV
+# include <gudev/gudev.h>
+#endif
+
 #define _LIBMM_INSIDE_MMCLI
 #include "libmm-glib.h"
 
@@ -39,6 +43,9 @@
 typedef struct {
     MMManager *manager;
     GCancellable *cancellable;
+#if WITH_UDEV
+    GUdevClient *udev;
+#endif
 } Context;
 static Context *ctx;
 
@@ -49,6 +56,10 @@ static gboolean scan_modems_flag;
 static gchar *set_logging_str;
 static gchar *report_kernel_event_str;
 
+#if WITH_UDEV
+static gboolean report_kernel_event_udev;
+#endif
+
 static GOptionEntry entries[] = {
     { "set-logging", 'G', 0, G_OPTION_ARG_STRING, &set_logging_str,
       "Set logging level in the ModemManager daemon",
@@ -70,6 +81,12 @@ static GOptionEntry entries[] = {
       "Report kernel event",
       "[\"key=value,...\"]"
     },
+#if WITH_UDEV
+    { "report-kernel-event-udev", 0, 0, G_OPTION_ARG_NONE, &report_kernel_event_udev,
+      "Automatically report kernel events based on udev notifications",
+      NULL
+    },
+#endif
     { NULL }
 };
 
@@ -104,6 +121,10 @@ mmcli_manager_options_enabled (void)
                  !!set_logging_str +
                  !!report_kernel_event_str);
 
+#if WITH_UDEV
+    n_actions += report_kernel_event_udev;
+#endif
+
     if (n_actions > 1) {
         g_printerr ("error: too many manager actions requested\n");
         exit (EXIT_FAILURE);
@@ -112,6 +133,11 @@ mmcli_manager_options_enabled (void)
     if (monitor_modems_flag)
         mmcli_force_async_operation ();
 
+#if WITH_UDEV
+    if (report_kernel_event_udev)
+        mmcli_force_async_operation ();
+#endif
+
     checked = TRUE;
     return !!n_actions;
 }
@@ -122,6 +148,11 @@ context_free (Context *ctx)
     if (!ctx)
         return;
 
+#if WITH_UDEV
+    if (ctx->udev)
+        g_object_unref (ctx->udev);
+#endif
+
     if (ctx->manager)
         g_object_unref (ctx->manager);
     if (ctx->cancellable)
@@ -294,6 +325,26 @@ cancelled (GCancellable *cancellable)
     mmcli_async_operation_done ();
 }
 
+#if WITH_UDEV
+
+static void
+handle_uevent (GUdevClient *client,
+               const char  *action,
+               GUdevDevice *device,
+               gpointer     none)
+{
+    MMKernelEventProperties *properties;
+
+    properties = mm_kernel_event_properties_new ();
+    mm_kernel_event_properties_set_action (properties, action);
+    mm_kernel_event_properties_set_subsystem (properties, g_udev_device_get_subsystem (device));
+    mm_kernel_event_properties_set_name (properties, g_udev_device_get_name (device));
+    mm_manager_report_kernel_event (ctx->manager, properties, NULL, NULL, NULL);
+    g_object_unref (properties);
+}
+
+#endif
+
 static void
 get_manager_ready (GObject      *source,
                    GAsyncResult *result,
@@ -337,6 +388,42 @@ get_manager_ready (GObject      *source,
         return;
     }
 
+#if WITH_UDEV
+    if (report_kernel_event_udev) {
+        const gchar *subsys[] = { "tty", "usbmisc", "net", NULL };
+        guint i;
+
+        ctx->udev = g_udev_client_new (subsys);
+        g_signal_connect (ctx->udev, "uevent", G_CALLBACK (handle_uevent), NULL);
+
+        for (i = 0; subsys[i]; i++) {
+            GList *list, *iter;
+
+            list = g_udev_client_query_by_subsystem (ctx->udev, subsys[i]);
+            for (iter = list; iter; iter = g_list_next (iter)) {
+                MMKernelEventProperties *properties;
+                GUdevDevice *device;
+
+                device = G_UDEV_DEVICE (iter->data);
+                properties = mm_kernel_event_properties_new ();
+                mm_kernel_event_properties_set_action (properties, "add");
+                mm_kernel_event_properties_set_subsystem (properties, subsys[i]);
+                mm_kernel_event_properties_set_name (properties, g_udev_device_get_name (device));
+                mm_manager_report_kernel_event (ctx->manager, properties, NULL, NULL, NULL);
+                g_object_unref (properties);
+            }
+            g_list_free_full (list, (GDestroyNotify) g_object_unref);
+        }
+
+        /* If we get cancelled, operation done */
+        g_cancellable_connect (ctx->cancellable,
+                               G_CALLBACK (cancelled),
+                               NULL,
+                               NULL);
+        return;
+    }
+#endif
+
     /* Request to monitor modems? */
     if (monitor_modems_flag) {
         g_signal_connect (ctx->manager,
@@ -393,6 +480,13 @@ mmcli_manager_run_synchronous (GDBusConnection *connection)
         exit (EXIT_FAILURE);
     }
 
+#if WITH_UDEV
+    if (report_kernel_event_udev) {
+        g_printerr ("error: monitoring udev events cannot be done synchronously\n");
+        exit (EXIT_FAILURE);
+    }
+#endif
+
     /* Initialize context */
     ctx = g_new0 (Context, 1);
     ctx->manager = mmcli_get_manager_sync (connection);
-- 
2.9.0



More information about the ModemManager-devel mailing list