
g_type_init() has been deprecated (and also marked with the attribute 'deprecated') since glib 2.36 as the type system is automatically initialized. Since the minimum version of glib required by ModemManager is 2.36, calling g_type_init() isn't necessarily in the ModemManager code.
179 lines
4.7 KiB
C
179 lines
4.7 KiB
C
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; 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.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Copyright (C) 2009 Red Hat, Inc.
|
|
*/
|
|
|
|
#include <glib.h>
|
|
#include <gudev/gudev.h>
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <signal.h>
|
|
|
|
static GMainLoop *loop = NULL;
|
|
|
|
static void
|
|
signal_handler (int signo)
|
|
{
|
|
if (signo == SIGINT || signo == SIGTERM) {
|
|
g_message ("Caught signal %d, shutting down...", signo);
|
|
g_main_loop_quit (loop);
|
|
}
|
|
}
|
|
|
|
static void
|
|
setup_signals (void)
|
|
{
|
|
struct sigaction action;
|
|
sigset_t mask;
|
|
|
|
sigemptyset (&mask);
|
|
action.sa_handler = signal_handler;
|
|
action.sa_mask = mask;
|
|
action.sa_flags = 0;
|
|
sigaction (SIGTERM, &action, NULL);
|
|
sigaction (SIGINT, &action, NULL);
|
|
}
|
|
|
|
static void
|
|
println (guint indent, const char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
GString *output;
|
|
int i;
|
|
|
|
g_return_if_fail (fmt != NULL);
|
|
|
|
output = g_string_sized_new (250);
|
|
|
|
for (i = 0; i < indent; i++)
|
|
g_string_append_c (output, ' ');
|
|
|
|
va_start (args, fmt);
|
|
g_string_append_vprintf (output, fmt, args);
|
|
va_end (args);
|
|
|
|
g_print ("%s\n", output->str);
|
|
g_string_free (output, TRUE);
|
|
}
|
|
|
|
static void
|
|
dump_device_and_parent (GUdevDevice *device, guint indent)
|
|
{
|
|
const char **list, **iter;
|
|
GUdevDevice *parent;
|
|
char propstr[500];
|
|
guint32 namelen = 0, i;
|
|
|
|
println (indent, "------------------------------------------------------");
|
|
println (indent, "Name: %s", g_udev_device_get_name (device));
|
|
println (indent, "Type: %s", g_udev_device_get_devtype (device));
|
|
println (indent, "Subsys: %s", g_udev_device_get_subsystem (device));
|
|
println (indent, "Number: %s", g_udev_device_get_number (device));
|
|
println (indent, "Path: %s", g_udev_device_get_sysfs_path (device));
|
|
println (indent, "Driver: %s", g_udev_device_get_driver (device));
|
|
println (indent, "Action: %s", g_udev_device_get_action (device));
|
|
println (indent, "Seq Num: %lu", g_udev_device_get_seqnum (device));
|
|
println (indent, "Dev File: %s", g_udev_device_get_device_file (device));
|
|
|
|
println (indent, "");
|
|
println (indent, "Properties:");
|
|
|
|
/* Get longest property name length for alignment */
|
|
list = (const char **) g_udev_device_get_property_keys (device);
|
|
for (iter = list; iter && *iter; iter++) {
|
|
if (strlen (*iter) > namelen)
|
|
namelen = strlen (*iter);
|
|
}
|
|
namelen++;
|
|
|
|
for (iter = list; iter && *iter; iter++) {
|
|
strcpy (propstr, *iter);
|
|
strcat (propstr, ":");
|
|
for (i = 0; i < namelen - strlen (*iter); i++)
|
|
strcat (propstr, " ");
|
|
strcat (propstr, g_udev_device_get_property (device, *iter));
|
|
println (indent + 2, "%s", propstr);
|
|
}
|
|
|
|
println (indent, "");
|
|
|
|
parent = g_udev_device_get_parent (device);
|
|
if (parent) {
|
|
dump_device_and_parent (parent, indent + 4);
|
|
g_object_unref (parent);
|
|
}
|
|
}
|
|
|
|
static void
|
|
handle_uevent (GUdevClient *client,
|
|
const char *action,
|
|
GUdevDevice *device,
|
|
gpointer user_data)
|
|
{
|
|
const char *expected_subsys = user_data;
|
|
const char *subsys;
|
|
|
|
g_return_if_fail (client != NULL);
|
|
g_return_if_fail (action != NULL);
|
|
g_return_if_fail (device != NULL);
|
|
|
|
/* A bit paranoid */
|
|
subsys = g_udev_device_get_subsystem (device);
|
|
g_return_if_fail (subsys != NULL);
|
|
|
|
g_return_if_fail (!strcmp (subsys, expected_subsys));
|
|
|
|
g_print ("---- (EVENT: %s) ----\n", action);
|
|
dump_device_and_parent (device, 0);
|
|
g_print ("\n");
|
|
}
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
GUdevClient *client;
|
|
const char *subsys[2] = { NULL, NULL };
|
|
GList *list, *iter;
|
|
|
|
if (argc != 2) {
|
|
g_warning ("Usage: %s [subsystem]", argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
loop = g_main_loop_new (NULL, FALSE);
|
|
|
|
setup_signals ();
|
|
|
|
subsys[0] = argv[1];
|
|
client = g_udev_client_new (subsys);
|
|
g_signal_connect (client, "uevent", G_CALLBACK (handle_uevent), (gpointer) subsys[0]);
|
|
|
|
list = g_udev_client_query_by_subsystem (client, subsys[0]);
|
|
for (iter = list; iter; iter = g_list_next (iter)) {
|
|
dump_device_and_parent (G_UDEV_DEVICE (iter->data), 0);
|
|
g_print ("\n");
|
|
g_object_unref (G_UDEV_DEVICE (iter->data));
|
|
}
|
|
|
|
g_main_loop_run (loop);
|
|
|
|
return 0;
|
|
}
|
|
|