118c2aff7Sartem /***************************************************************************
218c2aff7Sartem * CVSID: $Id$
318c2aff7Sartem *
418c2aff7Sartem * lshal.c : Show devices managed by HAL
518c2aff7Sartem *
618c2aff7Sartem * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
718c2aff7Sartem * Copyright (C) 2005 Pierre Ossman, <drzeus@drzeus.cx>
818c2aff7Sartem *
918c2aff7Sartem * Licensed under the Academic Free License version 2.1
1018c2aff7Sartem *
1118c2aff7Sartem * This program is free software; you can redistribute it and/or modify
1218c2aff7Sartem * it under the terms of the GNU General Public License as published by
1318c2aff7Sartem * the Free Software Foundation; either version 2 of the License, or
1418c2aff7Sartem * (at your option) any later version.
1518c2aff7Sartem *
1618c2aff7Sartem * This program is distributed in the hope that it will be useful,
1718c2aff7Sartem * but WITHOUT ANY WARRANTY; without even the implied warranty of
1818c2aff7Sartem * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1918c2aff7Sartem * GNU General Public License for more details.
2018c2aff7Sartem *
2118c2aff7Sartem * You should have received a copy of the GNU General Public License
2218c2aff7Sartem * along with this program; if not, write to the Free Software
2318c2aff7Sartem * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2418c2aff7Sartem *
2518c2aff7Sartem **************************************************************************/
2618c2aff7Sartem
2718c2aff7Sartem
2818c2aff7Sartem #ifdef HAVE_CONFIG_H
2918c2aff7Sartem # include <config.h>
3018c2aff7Sartem #endif
3118c2aff7Sartem
3218c2aff7Sartem #include <stdio.h>
3318c2aff7Sartem #include <stdlib.h>
3418c2aff7Sartem #include <string.h>
3518c2aff7Sartem #include <unistd.h>
3618c2aff7Sartem #include <getopt.h>
3718c2aff7Sartem
3818c2aff7Sartem #include <glib.h>
3918c2aff7Sartem #include <dbus/dbus-glib-lowlevel.h>
4018c2aff7Sartem #include <dbus/dbus-glib.h>
4118c2aff7Sartem #include <libhal.h>
4218c2aff7Sartem
4318c2aff7Sartem #ifdef __SUNPRO_C
4418c2aff7Sartem #define __FUNCTION__ __func__
4518c2aff7Sartem #endif
4618c2aff7Sartem
4718c2aff7Sartem /**
4818c2aff7Sartem * @defgroup HalLsHal List HAL devices
4918c2aff7Sartem * @ingroup HalMisc
5018c2aff7Sartem *
5118c2aff7Sartem * @brief A commandline tool, lshal, for displaying and, optionally,
5218c2aff7Sartem * monitor the devices managed by the HAL daemon. Uses libhal.
5318c2aff7Sartem *
5418c2aff7Sartem * @{
5518c2aff7Sartem */
5618c2aff7Sartem
5718c2aff7Sartem /** Macro for terminating the program on an unrecoverable error */
5818c2aff7Sartem #define DIE(expr) do {printf("*** [DIE] %s:%s():%d : ", __FILE__, __FUNCTION__, __LINE__); printf expr; printf("\n"); exit(1); } while(0)
5918c2aff7Sartem
6018c2aff7Sartem #define UDI_BASE "/org/freedesktop/Hal/devices/"
6118c2aff7Sartem
6218c2aff7Sartem static LibHalContext *hal_ctx;
6318c2aff7Sartem static dbus_bool_t long_list = FALSE;
6418c2aff7Sartem static dbus_bool_t tree_view = FALSE;
6518c2aff7Sartem static dbus_bool_t short_list = FALSE;
6618c2aff7Sartem static char *show_device = NULL;
6718c2aff7Sartem
6818c2aff7Sartem struct Device {
6918c2aff7Sartem char *name;
7018c2aff7Sartem char *parent;
7118c2aff7Sartem };
7218c2aff7Sartem
7318c2aff7Sartem /** Generate a short name for a device
7418c2aff7Sartem *
7518c2aff7Sartem * @param udi Universal Device Id
7618c2aff7Sartem */
7718c2aff7Sartem static const char *
short_name(const char * udi)7818c2aff7Sartem short_name (const char *udi)
7918c2aff7Sartem {
8018c2aff7Sartem return &udi[sizeof(UDI_BASE) - 1];
8118c2aff7Sartem }
8218c2aff7Sartem
8318c2aff7Sartem /** Print all properties of a device
8418c2aff7Sartem *
8518c2aff7Sartem * @param udi Universal Device Id
8618c2aff7Sartem */
8718c2aff7Sartem
8818c2aff7Sartem static void
print_props(const char * udi)8918c2aff7Sartem print_props (const char *udi)
9018c2aff7Sartem {
9118c2aff7Sartem DBusError error;
9218c2aff7Sartem LibHalPropertySet *props;
9318c2aff7Sartem LibHalPropertySetIterator it;
9418c2aff7Sartem int type;
9518c2aff7Sartem
9618c2aff7Sartem dbus_error_init (&error);
9718c2aff7Sartem
9818c2aff7Sartem props = libhal_device_get_all_properties (hal_ctx, udi, &error);
9918c2aff7Sartem
10018c2aff7Sartem /* NOTE : This may be NULL if the device was removed
10118c2aff7Sartem * in the daemon; this is because
10218c2aff7Sartem * hal_device_get_all_properties() is a in
10318c2aff7Sartem * essence an IPC call and other stuff may
10418c2aff7Sartem * be happening..
10518c2aff7Sartem */
10618c2aff7Sartem if (props == NULL) {
10718c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error);
10818c2aff7Sartem return;
10918c2aff7Sartem }
11018c2aff7Sartem
11118c2aff7Sartem for (libhal_psi_init (&it, props); libhal_psi_has_more (&it); libhal_psi_next (&it)) {
11218c2aff7Sartem type = libhal_psi_get_type (&it);
11318c2aff7Sartem switch (type) {
11418c2aff7Sartem case LIBHAL_PROPERTY_TYPE_STRING:
11518c2aff7Sartem printf (" %s = '%s' (string)\n",
11618c2aff7Sartem libhal_psi_get_key (&it),
11718c2aff7Sartem libhal_psi_get_string (&it));
11818c2aff7Sartem break;
11918c2aff7Sartem
12018c2aff7Sartem case LIBHAL_PROPERTY_TYPE_INT32:
12118c2aff7Sartem printf (" %s = %d (0x%x) (int)\n",
12218c2aff7Sartem libhal_psi_get_key (&it),
12318c2aff7Sartem libhal_psi_get_int (&it),
12418c2aff7Sartem libhal_psi_get_int (&it));
12518c2aff7Sartem break;
12618c2aff7Sartem
12718c2aff7Sartem case LIBHAL_PROPERTY_TYPE_UINT64:
12818c2aff7Sartem printf (" %s = %llu (0x%llx) (uint64)\n",
12918c2aff7Sartem libhal_psi_get_key (&it),
13018c2aff7Sartem (long long unsigned int) libhal_psi_get_uint64 (&it),
13118c2aff7Sartem (long long unsigned int) libhal_psi_get_uint64 (&it));
13218c2aff7Sartem break;
13318c2aff7Sartem
13418c2aff7Sartem case LIBHAL_PROPERTY_TYPE_DOUBLE:
13518c2aff7Sartem printf (" %s = %g (double)\n",
13618c2aff7Sartem libhal_psi_get_key (&it),
13718c2aff7Sartem libhal_psi_get_double (&it));
13818c2aff7Sartem break;
13918c2aff7Sartem
14018c2aff7Sartem case LIBHAL_PROPERTY_TYPE_BOOLEAN:
14118c2aff7Sartem printf (" %s = %s (bool)\n",
14218c2aff7Sartem libhal_psi_get_key (&it),
14318c2aff7Sartem libhal_psi_get_bool (&it) ? "true" :
14418c2aff7Sartem "false");
14518c2aff7Sartem break;
14618c2aff7Sartem
14718c2aff7Sartem case LIBHAL_PROPERTY_TYPE_STRLIST:
14818c2aff7Sartem {
14918c2aff7Sartem unsigned int i;
15018c2aff7Sartem char **strlist;
15118c2aff7Sartem
15218c2aff7Sartem printf (" %s = {", libhal_psi_get_key (&it));
15318c2aff7Sartem
15418c2aff7Sartem strlist = libhal_psi_get_strlist (&it);
15518c2aff7Sartem for (i = 0; strlist[i] != 0; i++) {
15618c2aff7Sartem printf ("'%s'", strlist[i]);
15718c2aff7Sartem if (strlist[i+1] != NULL)
15818c2aff7Sartem printf (", ");
15918c2aff7Sartem }
16018c2aff7Sartem printf ("} (string list)\n");
16118c2aff7Sartem break;
16218c2aff7Sartem }
16318c2aff7Sartem
16418c2aff7Sartem default:
16518c2aff7Sartem printf ("Unknown type %d=0x%02x\n", type, type);
16618c2aff7Sartem break;
16718c2aff7Sartem }
16818c2aff7Sartem }
16918c2aff7Sartem
17018c2aff7Sartem libhal_free_property_set (props);
17118c2aff7Sartem }
17218c2aff7Sartem
17318c2aff7Sartem /** Dumps information about a single device
17418c2aff7Sartem *
17518c2aff7Sartem * @param udi Universal Device Id
17618c2aff7Sartem */
17718c2aff7Sartem
17818c2aff7Sartem static void
dump_device(const char * udi)17918c2aff7Sartem dump_device (const char *udi)
18018c2aff7Sartem {
18118c2aff7Sartem DBusError error;
18218c2aff7Sartem
18318c2aff7Sartem dbus_error_init (&error);
18418c2aff7Sartem
18518c2aff7Sartem if (!libhal_device_exists (hal_ctx, udi, &error)) {
18618c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error);
18718c2aff7Sartem return;
18818c2aff7Sartem }
18918c2aff7Sartem
19018c2aff7Sartem if (long_list) {
19118c2aff7Sartem printf ("udi = '%s'\n", udi);
19218c2aff7Sartem
19318c2aff7Sartem print_props (udi);
19418c2aff7Sartem printf ("\n");
19518c2aff7Sartem }
19618c2aff7Sartem else
19718c2aff7Sartem printf ("%s\n", short_name (udi));
19818c2aff7Sartem }
19918c2aff7Sartem
20018c2aff7Sartem /** Dump all children of device
20118c2aff7Sartem *
20218c2aff7Sartem * @param udi Universal Device Id of parent
20318c2aff7Sartem * @param num_devices Total number of devices in device list
20418c2aff7Sartem * @param devices List of devices
20518c2aff7Sartem * @param depth Current recursion depth
20618c2aff7Sartem */
20718c2aff7Sartem
20818c2aff7Sartem static void
dump_children(char * udi,int num_devices,struct Device * devices,int depth)20918c2aff7Sartem dump_children (char *udi, int num_devices, struct Device *devices, int depth)
21018c2aff7Sartem {
21118c2aff7Sartem int i;
21218c2aff7Sartem
21318c2aff7Sartem for (i = 0; i < num_devices; i++) {
21418c2aff7Sartem if (!udi) {
21518c2aff7Sartem if (devices[i].parent)
21618c2aff7Sartem continue;
21718c2aff7Sartem }
21818c2aff7Sartem else {
21918c2aff7Sartem if (!devices[i].parent)
22018c2aff7Sartem continue;
22118c2aff7Sartem if (strcmp (devices[i].parent, udi))
22218c2aff7Sartem continue;
22318c2aff7Sartem }
22418c2aff7Sartem
22518c2aff7Sartem if (long_list)
22618c2aff7Sartem printf ("udi = '%s'\n", devices[i].name);
22718c2aff7Sartem else {
22818c2aff7Sartem int j;
22918c2aff7Sartem if (tree_view) {
23018c2aff7Sartem for (j = 0;j < depth;j++)
23118c2aff7Sartem printf(" ");
23218c2aff7Sartem }
23318c2aff7Sartem printf ("%s\n", short_name (devices[i].name));
23418c2aff7Sartem }
23518c2aff7Sartem
23618c2aff7Sartem if (long_list) {
23718c2aff7Sartem print_props (devices[i].name);
23818c2aff7Sartem printf ("\n");
23918c2aff7Sartem }
24018c2aff7Sartem
24118c2aff7Sartem dump_children(devices[i].name, num_devices, devices, depth + 1);
24218c2aff7Sartem }
24318c2aff7Sartem }
24418c2aff7Sartem
24518c2aff7Sartem /** Dump all devices to stdout
24618c2aff7Sartem *
24718c2aff7Sartem */
24818c2aff7Sartem static void
dump_devices(void)24918c2aff7Sartem dump_devices (void)
25018c2aff7Sartem {
25118c2aff7Sartem int i;
25218c2aff7Sartem int num_devices;
25318c2aff7Sartem char **device_names;
25418c2aff7Sartem struct Device *devices;
25518c2aff7Sartem DBusError error;
25618c2aff7Sartem
25718c2aff7Sartem dbus_error_init (&error);
25818c2aff7Sartem
25918c2aff7Sartem device_names = libhal_get_all_devices (hal_ctx, &num_devices, &error);
26018c2aff7Sartem if (device_names == NULL) {
26118c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error);
26218c2aff7Sartem DIE (("Couldn't obtain list of devices\n"));
26318c2aff7Sartem }
26418c2aff7Sartem
26518c2aff7Sartem devices = malloc (sizeof(struct Device) * num_devices);
26618c2aff7Sartem if (!devices) {
26718c2aff7Sartem libhal_free_string_array (device_names);
26818c2aff7Sartem return;
26918c2aff7Sartem }
27018c2aff7Sartem
27118c2aff7Sartem for (i = 0;i < num_devices;i++) {
27218c2aff7Sartem devices[i].name = device_names[i];
27318c2aff7Sartem devices[i].parent = libhal_device_get_property_string (hal_ctx,
27418c2aff7Sartem device_names[i], "info.parent", &error);
27518c2aff7Sartem
27618c2aff7Sartem if (dbus_error_is_set (&error)) {
27718c2aff7Sartem /* Free the error (which include a dbus_error_init())
27818c2aff7Sartem This should prevent errors if a call above fails */
27918c2aff7Sartem dbus_error_free (&error);
28018c2aff7Sartem }
28118c2aff7Sartem }
28218c2aff7Sartem
28318c2aff7Sartem if (long_list) {
28418c2aff7Sartem printf ("\n"
28518c2aff7Sartem "Dumping %d device(s) from the Global Device List:\n"
28618c2aff7Sartem "-------------------------------------------------\n",
28718c2aff7Sartem num_devices);
28818c2aff7Sartem }
28918c2aff7Sartem
29018c2aff7Sartem dump_children(NULL, num_devices, devices, 0);
29118c2aff7Sartem
29218c2aff7Sartem for (i = 0;i < num_devices;i++) {
29318c2aff7Sartem if (devices[i].parent)
29418c2aff7Sartem libhal_free_string (devices[i].parent);
29518c2aff7Sartem }
29618c2aff7Sartem
29718c2aff7Sartem free (devices);
29818c2aff7Sartem libhal_free_string_array (device_names);
29918c2aff7Sartem
30018c2aff7Sartem if (long_list) {
30118c2aff7Sartem printf ("\n"
30218c2aff7Sartem "Dumped %d device(s) from the Global Device List.\n"
30318c2aff7Sartem "------------------------------------------------\n",
30418c2aff7Sartem num_devices);
30518c2aff7Sartem
30618c2aff7Sartem printf ("\n");
30718c2aff7Sartem }
30818c2aff7Sartem }
30918c2aff7Sartem
31018c2aff7Sartem /** Invoked when a device is added to the Global Device List. Simply prints
31118c2aff7Sartem * a message on stdout.
31218c2aff7Sartem *
31318c2aff7Sartem * @param udi Universal Device Id
31418c2aff7Sartem */
31518c2aff7Sartem static void
device_added(LibHalContext * ctx,const char * udi)31618c2aff7Sartem device_added (LibHalContext *ctx,
31718c2aff7Sartem const char *udi)
31818c2aff7Sartem {
31918c2aff7Sartem if (show_device && strcmp(show_device, udi))
32018c2aff7Sartem return;
32118c2aff7Sartem
32218c2aff7Sartem if (long_list) {
32318c2aff7Sartem printf ("*** lshal: device_added, udi='%s'\n", udi);
32418c2aff7Sartem print_props (udi);
32518c2aff7Sartem } else
32618c2aff7Sartem printf ("%s added\n", short_name (udi));
32718c2aff7Sartem }
32818c2aff7Sartem
32918c2aff7Sartem /** Invoked when a device is removed from the Global Device List. Simply
33018c2aff7Sartem * prints a message on stdout.
33118c2aff7Sartem *
33218c2aff7Sartem * @param udi Universal Device Id
33318c2aff7Sartem */
33418c2aff7Sartem static void
device_removed(LibHalContext * ctx,const char * udi)33518c2aff7Sartem device_removed (LibHalContext *ctx,
33618c2aff7Sartem const char *udi)
33718c2aff7Sartem {
33818c2aff7Sartem if (show_device && strcmp(show_device, udi))
33918c2aff7Sartem return;
34018c2aff7Sartem
34118c2aff7Sartem if (long_list)
34218c2aff7Sartem printf ("*** lshal: device_removed, udi='%s'\n", udi);
34318c2aff7Sartem else
34418c2aff7Sartem printf ("%s removed\n", short_name (udi));
34518c2aff7Sartem }
34618c2aff7Sartem
34718c2aff7Sartem /** Invoked when device in the Global Device List acquires a new capability.
34818c2aff7Sartem * Prints the name of the capability to stdout.
34918c2aff7Sartem *
35018c2aff7Sartem * @param udi Universal Device Id
35118c2aff7Sartem * @param capability Name of capability
35218c2aff7Sartem */
35318c2aff7Sartem static void
device_new_capability(LibHalContext * ctx,const char * udi,const char * capability)35418c2aff7Sartem device_new_capability (LibHalContext *ctx,
35518c2aff7Sartem const char *udi,
35618c2aff7Sartem const char *capability)
35718c2aff7Sartem {
35818c2aff7Sartem if (show_device && strcmp(show_device, udi))
35918c2aff7Sartem return;
36018c2aff7Sartem
36118c2aff7Sartem if (long_list) {
36218c2aff7Sartem printf ("*** lshal: new_capability, udi='%s'\n", udi);
36318c2aff7Sartem printf ("*** capability: %s\n", capability);
36418c2aff7Sartem } else
36518c2aff7Sartem printf ("%s capability %s added\n", short_name (udi),
36618c2aff7Sartem capability);
36718c2aff7Sartem }
36818c2aff7Sartem
36918c2aff7Sartem /** Invoked when device in the Global Device List loses a capability.
37018c2aff7Sartem * Prints the name of the capability to stdout.
37118c2aff7Sartem *
37218c2aff7Sartem * @param udi Universal Device Id
37318c2aff7Sartem * @param capability Name of capability
37418c2aff7Sartem */
37518c2aff7Sartem static void
device_lost_capability(LibHalContext * ctx,const char * udi,const char * capability)37618c2aff7Sartem device_lost_capability (LibHalContext *ctx,
37718c2aff7Sartem const char *udi,
37818c2aff7Sartem const char *capability)
37918c2aff7Sartem {
38018c2aff7Sartem if (show_device && strcmp(show_device, udi))
38118c2aff7Sartem return;
38218c2aff7Sartem
38318c2aff7Sartem if (long_list) {
38418c2aff7Sartem printf ("*** lshal: lost_capability, udi='%s'\n", udi);
38518c2aff7Sartem printf ("*** capability: %s\n", capability);
38618c2aff7Sartem } else
38718c2aff7Sartem printf ("%s capability %s lost\n", short_name (udi),
38818c2aff7Sartem capability);
38918c2aff7Sartem }
39018c2aff7Sartem
39118c2aff7Sartem /** Acquires and prints the value of of a property to stdout.
39218c2aff7Sartem *
39318c2aff7Sartem * @param udi Universal Device Id
39418c2aff7Sartem * @param key Key of property
39518c2aff7Sartem */
39618c2aff7Sartem static void
print_property(const char * udi,const char * key)39718c2aff7Sartem print_property (const char *udi, const char *key)
39818c2aff7Sartem {
39918c2aff7Sartem int type;
40018c2aff7Sartem char *str;
40118c2aff7Sartem DBusError error;
40218c2aff7Sartem
40318c2aff7Sartem dbus_error_init (&error);
40418c2aff7Sartem
40518c2aff7Sartem type = libhal_device_get_property_type (hal_ctx, udi, key, &error);
40618c2aff7Sartem
40718c2aff7Sartem switch (type) {
40818c2aff7Sartem case LIBHAL_PROPERTY_TYPE_STRING:
40918c2aff7Sartem str = libhal_device_get_property_string (hal_ctx, udi, key, &error);
41018c2aff7Sartem printf (long_list?"*** new value: '%s' (string)\n":"'%s'", str);
41118c2aff7Sartem libhal_free_string (str);
41218c2aff7Sartem break;
41318c2aff7Sartem case LIBHAL_PROPERTY_TYPE_INT32:
41418c2aff7Sartem {
41518c2aff7Sartem dbus_int32_t value = libhal_device_get_property_int (hal_ctx, udi, key, &error);
41618c2aff7Sartem printf (long_list?"*** new value: %d (0x%x) (int)\n":"%d (0x%x)",
41718c2aff7Sartem value, value);
41818c2aff7Sartem }
41918c2aff7Sartem break;
42018c2aff7Sartem case LIBHAL_PROPERTY_TYPE_UINT64:
42118c2aff7Sartem {
42218c2aff7Sartem dbus_uint64_t value = libhal_device_get_property_uint64 (hal_ctx, udi, key, &error);
42318c2aff7Sartem printf (long_list?"*** new value: %llu (0x%llx) (uint64)\n":"%llu (0x%llx)",
42418c2aff7Sartem (long long unsigned int) value, (long long unsigned int) value);
42518c2aff7Sartem }
42618c2aff7Sartem break;
42718c2aff7Sartem case LIBHAL_PROPERTY_TYPE_DOUBLE:
42818c2aff7Sartem printf (long_list?"*** new value: %g (double)\n":"%g",
42918c2aff7Sartem libhal_device_get_property_double (hal_ctx, udi, key, &error));
43018c2aff7Sartem break;
43118c2aff7Sartem case LIBHAL_PROPERTY_TYPE_BOOLEAN:
43218c2aff7Sartem printf (long_list?"*** new value: %s (bool)\n":"%s",
43318c2aff7Sartem libhal_device_get_property_bool (hal_ctx, udi, key, &error) ? "true" : "false");
43418c2aff7Sartem break;
43518c2aff7Sartem case LIBHAL_PROPERTY_TYPE_STRLIST:
43618c2aff7Sartem {
43718c2aff7Sartem unsigned int i;
43818c2aff7Sartem char **strlist;
43918c2aff7Sartem
44018c2aff7Sartem if (long_list)
44118c2aff7Sartem printf ("*** new value: {");
44218c2aff7Sartem else
44318c2aff7Sartem printf ("{");
44418c2aff7Sartem
44518c2aff7Sartem strlist = libhal_device_get_property_strlist (hal_ctx, udi, key, &error);
44618c2aff7Sartem for (i = 0; strlist[i] != 0; i++) {
44718c2aff7Sartem printf ("'%s'", strlist[i]);
44818c2aff7Sartem if (strlist[i+1] != NULL)
44918c2aff7Sartem printf (", ");
45018c2aff7Sartem }
45118c2aff7Sartem if (long_list)
45218c2aff7Sartem printf ("} (string list)\n");
45318c2aff7Sartem else
45418c2aff7Sartem printf ("}");
45518c2aff7Sartem libhal_free_string_array (strlist);
45618c2aff7Sartem break;
45718c2aff7Sartem }
45818c2aff7Sartem
45918c2aff7Sartem default:
46018c2aff7Sartem fprintf (stderr, "Unknown type %d='%c'\n", type, type);
46118c2aff7Sartem break;
46218c2aff7Sartem }
46318c2aff7Sartem
46418c2aff7Sartem if (dbus_error_is_set (&error))
46518c2aff7Sartem dbus_error_free (&error);
46618c2aff7Sartem }
46718c2aff7Sartem
46818c2aff7Sartem /** Invoked when a property of a device in the Global Device List is
46918c2aff7Sartem * changed, and we have we have subscribed to changes for that device.
47018c2aff7Sartem *
47118c2aff7Sartem * @param udi Univerisal Device Id
47218c2aff7Sartem * @param key Key of property
47318c2aff7Sartem */
47418c2aff7Sartem static void
property_modified(LibHalContext * ctx,const char * udi,const char * key,dbus_bool_t is_removed,dbus_bool_t is_added)47518c2aff7Sartem property_modified (LibHalContext *ctx,
47618c2aff7Sartem const char *udi,
47718c2aff7Sartem const char *key,
47818c2aff7Sartem dbus_bool_t is_removed,
47918c2aff7Sartem dbus_bool_t is_added)
48018c2aff7Sartem {
48118c2aff7Sartem if (show_device && strcmp(show_device, udi))
48218c2aff7Sartem return;
48318c2aff7Sartem
48418c2aff7Sartem if (long_list) {
48518c2aff7Sartem printf ("*** lshal: property_modified, udi=%s, key=%s\n",
48618c2aff7Sartem udi, key);
48718c2aff7Sartem printf (" is_removed=%s, is_added=%s\n",
48818c2aff7Sartem is_removed ? "true" : "false",
48918c2aff7Sartem is_added ? "true" : "false");
49018c2aff7Sartem if (!is_removed)
49118c2aff7Sartem print_property (udi, key);
49218c2aff7Sartem printf ("\n");
49318c2aff7Sartem } else {
49418c2aff7Sartem printf ("%s property %s ", short_name (udi), key);
49518c2aff7Sartem if (is_removed)
49618c2aff7Sartem printf ("removed");
49718c2aff7Sartem else {
49818c2aff7Sartem printf ("= ");
49918c2aff7Sartem print_property (udi, key);
50018c2aff7Sartem
50118c2aff7Sartem if (is_added)
50218c2aff7Sartem printf (" (new)");
50318c2aff7Sartem }
50418c2aff7Sartem printf ("\n");
50518c2aff7Sartem }
50618c2aff7Sartem }
50718c2aff7Sartem
50818c2aff7Sartem
50918c2aff7Sartem /** Invoked when a property of a device in the Global Device List is
51018c2aff7Sartem * changed, and we have we have subscribed to changes for that device.
51118c2aff7Sartem *
51218c2aff7Sartem * @param udi Univerisal Device Id
51318c2aff7Sartem * @param condition_name Name of condition
51418c2aff7Sartem * @param message D-BUS message with parameters
51518c2aff7Sartem */
51618c2aff7Sartem static void
device_condition(LibHalContext * ctx,const char * udi,const char * condition_name,const char * condition_details)51718c2aff7Sartem device_condition (LibHalContext *ctx,
51818c2aff7Sartem const char *udi,
51918c2aff7Sartem const char *condition_name,
52018c2aff7Sartem const char *condition_details)
52118c2aff7Sartem {
52218c2aff7Sartem if (show_device && strcmp(show_device, udi))
52318c2aff7Sartem return;
52418c2aff7Sartem
52518c2aff7Sartem if (long_list) {
52618c2aff7Sartem printf ("*** lshal: device_condition, udi=%s\n", udi);
52718c2aff7Sartem printf (" condition_name=%s\n", condition_name);
52818c2aff7Sartem printf (" condition_details=%s\n", condition_details);
52918c2aff7Sartem printf ("\n");
53018c2aff7Sartem } else {
53118c2aff7Sartem printf ("%s condition %s = %s\n", short_name (udi),
53218c2aff7Sartem condition_name, condition_details);
53318c2aff7Sartem }
53418c2aff7Sartem }
53518c2aff7Sartem
53618c2aff7Sartem
53718c2aff7Sartem /** Print out program usage.
53818c2aff7Sartem *
53918c2aff7Sartem * @param argc Number of arguments given to program
54018c2aff7Sartem * @param argv Arguments given to program
54118c2aff7Sartem */
54218c2aff7Sartem static void
usage(int argc,char * argv[])54318c2aff7Sartem usage (int argc, char *argv[])
54418c2aff7Sartem {
54518c2aff7Sartem fprintf (stderr, "lshal version " PACKAGE_VERSION "\n");
54618c2aff7Sartem
54718c2aff7Sartem fprintf (stderr, "\n" "usage : %s [options]\n", argv[0]);
54818c2aff7Sartem fprintf (stderr,
54918c2aff7Sartem "\n"
55018c2aff7Sartem "Options:\n"
55118c2aff7Sartem " -m, --monitor Monitor device list\n"
55218c2aff7Sartem " -s, --short short output (print only nonstatic part of udi)\n"
55318c2aff7Sartem " -l, --long Long output\n"
55418c2aff7Sartem " -t, --tree Tree view\n"
55518c2aff7Sartem " -u, --show <udi> Show only the specified device\n"
55618c2aff7Sartem "\n"
55718c2aff7Sartem " -h, --help Show this information and exit\n"
55818c2aff7Sartem " -V, --version Print version number\n"
55918c2aff7Sartem "\n"
56018c2aff7Sartem "Without any given options lshal will start with option --long."
56118c2aff7Sartem "\n"
56218c2aff7Sartem "Shows all devices and their properties. If the --monitor option is given\n"
56318c2aff7Sartem "then the device list and all devices are monitored for changes.\n"
56418c2aff7Sartem "\n");
56518c2aff7Sartem }
56618c2aff7Sartem
56718c2aff7Sartem /** Entry point
56818c2aff7Sartem *
56918c2aff7Sartem * @param argc Number of arguments given to program
57018c2aff7Sartem * @param argv Arguments given to program
57118c2aff7Sartem * @return Return code
57218c2aff7Sartem */
57318c2aff7Sartem int
main(int argc,char * argv[])57418c2aff7Sartem main (int argc, char *argv[])
57518c2aff7Sartem {
57618c2aff7Sartem DBusError error;
57718c2aff7Sartem dbus_bool_t do_monitor = FALSE;
57818c2aff7Sartem GMainLoop *loop;
57918c2aff7Sartem DBusConnection *conn;
58018c2aff7Sartem
58118c2aff7Sartem if (argc == 1) {
58218c2aff7Sartem /* This is the default case lshal without any options */
58318c2aff7Sartem long_list = TRUE;
58418c2aff7Sartem }
58518c2aff7Sartem else {
58618c2aff7Sartem static const struct option long_options[] = {
58718c2aff7Sartem {"monitor", no_argument, NULL, 'm'},
58818c2aff7Sartem {"long", no_argument, NULL, 'l'},
58918c2aff7Sartem {"short", no_argument, NULL, 's'},
59018c2aff7Sartem {"tree", no_argument, NULL, 't'},
59118c2aff7Sartem {"show", required_argument, NULL, 'u'},
59218c2aff7Sartem {"help", no_argument, NULL, 'h'},
59318c2aff7Sartem {"usage", no_argument, NULL, 'U'},
59418c2aff7Sartem {"version", no_argument, NULL, 'V'},
59518c2aff7Sartem {NULL, 0, NULL, 0}
59618c2aff7Sartem };
59718c2aff7Sartem
59818c2aff7Sartem while (1) {
59918c2aff7Sartem int c;
600*55fea89dSDan Cross
60118c2aff7Sartem c = getopt_long (argc, argv, "mlstu:hUV", long_options, NULL);
60218c2aff7Sartem
60318c2aff7Sartem if (c == -1) {
60418c2aff7Sartem /* this should happen e.g. if 'lshal -' and this is incorrect/incomplete option */
60518c2aff7Sartem if (!do_monitor && !long_list && !short_list && !tree_view && !show_device) {
60618c2aff7Sartem usage (argc, argv);
60718c2aff7Sartem return 1;
60818c2aff7Sartem }
609*55fea89dSDan Cross
61018c2aff7Sartem break;
61118c2aff7Sartem }
61218c2aff7Sartem
61318c2aff7Sartem switch (c) {
614*55fea89dSDan Cross case 'm':
61518c2aff7Sartem do_monitor = TRUE;
61618c2aff7Sartem break;
61718c2aff7Sartem
61818c2aff7Sartem case 'l':
61918c2aff7Sartem long_list = TRUE;
62018c2aff7Sartem break;
62118c2aff7Sartem
62218c2aff7Sartem case 's':
62318c2aff7Sartem short_list = TRUE;
62418c2aff7Sartem long_list = FALSE;
62518c2aff7Sartem break;
626*55fea89dSDan Cross
62718c2aff7Sartem case 't':
62818c2aff7Sartem tree_view = TRUE;
62918c2aff7Sartem break;
630*55fea89dSDan Cross
63118c2aff7Sartem case 'u':
63218c2aff7Sartem if (strchr(optarg, '/') != NULL)
63318c2aff7Sartem show_device = strdup(optarg);
63418c2aff7Sartem else {
63518c2aff7Sartem show_device = malloc(strlen(UDI_BASE) + strlen(optarg) + 1);
63618c2aff7Sartem memcpy(show_device, UDI_BASE, strlen(UDI_BASE));
63718c2aff7Sartem memcpy(show_device + strlen(UDI_BASE), optarg, strlen(optarg) + 1);
63818c2aff7Sartem }
639*55fea89dSDan Cross
64018c2aff7Sartem break;
641*55fea89dSDan Cross
64218c2aff7Sartem case 'h':
64318c2aff7Sartem case 'U':
64418c2aff7Sartem usage (argc, argv);
64518c2aff7Sartem return 0;
646*55fea89dSDan Cross
64718c2aff7Sartem case 'V':
64818c2aff7Sartem printf ("lshal version " PACKAGE_VERSION "\n");
64918c2aff7Sartem return 0;
65018c2aff7Sartem
65118c2aff7Sartem default:
65218c2aff7Sartem usage (argc, argv);
65318c2aff7Sartem return 1;
65418c2aff7Sartem }
65518c2aff7Sartem }
65618c2aff7Sartem }
657*55fea89dSDan Cross
65818c2aff7Sartem if (do_monitor)
65918c2aff7Sartem loop = g_main_loop_new (NULL, FALSE);
66018c2aff7Sartem else
66118c2aff7Sartem loop = NULL;
66218c2aff7Sartem
66318c2aff7Sartem dbus_error_init (&error);
66418c2aff7Sartem conn = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
66518c2aff7Sartem if (conn == NULL) {
66618c2aff7Sartem fprintf (stderr, "error: dbus_bus_get: %s: %s\n",
66718c2aff7Sartem error.name, error.message);
66818c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error);
66918c2aff7Sartem return 1;
67018c2aff7Sartem }
67118c2aff7Sartem
67218c2aff7Sartem if (do_monitor)
67318c2aff7Sartem dbus_connection_setup_with_g_main (conn, NULL);
67418c2aff7Sartem
67518c2aff7Sartem if ((hal_ctx = libhal_ctx_new ()) == NULL) {
67618c2aff7Sartem fprintf (stderr, "error: libhal_ctx_new\n");
67718c2aff7Sartem return 1;
67818c2aff7Sartem }
67918c2aff7Sartem if (!libhal_ctx_set_dbus_connection (hal_ctx, conn)) {
68018c2aff7Sartem fprintf (stderr, "error: libhal_ctx_set_dbus_connection: %s: %s\n",
68118c2aff7Sartem error.name, error.message);
68218c2aff7Sartem return 1;
68318c2aff7Sartem }
68418c2aff7Sartem if (!libhal_ctx_init (hal_ctx, &error)) {
68518c2aff7Sartem if (dbus_error_is_set(&error)) {
68618c2aff7Sartem fprintf (stderr, "error: libhal_ctx_init: %s: %s\n", error.name, error.message);
68718c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error);
68818c2aff7Sartem }
68918c2aff7Sartem fprintf (stderr, "Could not initialise connection to hald.\n"
69018c2aff7Sartem "Normally this means the HAL daemon (hald) is not running or not ready.\n");
69118c2aff7Sartem return 1;
69218c2aff7Sartem }
69318c2aff7Sartem
69418c2aff7Sartem libhal_ctx_set_device_added (hal_ctx, device_added);
69518c2aff7Sartem libhal_ctx_set_device_removed (hal_ctx, device_removed);
69618c2aff7Sartem libhal_ctx_set_device_new_capability (hal_ctx, device_new_capability);
69718c2aff7Sartem libhal_ctx_set_device_lost_capability (hal_ctx, device_lost_capability);
69818c2aff7Sartem libhal_ctx_set_device_property_modified (hal_ctx, property_modified);
69918c2aff7Sartem libhal_ctx_set_device_condition (hal_ctx, device_condition);
70018c2aff7Sartem
70118c2aff7Sartem if (show_device)
70218c2aff7Sartem dump_device (show_device);
70318c2aff7Sartem else if (!do_monitor)
70418c2aff7Sartem dump_devices ();
70518c2aff7Sartem
70618c2aff7Sartem /* run the main loop only if we should monitor */
70718c2aff7Sartem if (do_monitor && loop != NULL) {
70818c2aff7Sartem if( long_list || short_list || tree_view )
70918c2aff7Sartem dump_devices ();
710*55fea89dSDan Cross
71118c2aff7Sartem if ( libhal_device_property_watch_all (hal_ctx, &error) == FALSE) {
71218c2aff7Sartem fprintf (stderr, "error: monitoring devicelist - libhal_device_property_watch_all: %s: %s\n",
71318c2aff7Sartem error.name, error.message);
71418c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error);
71518c2aff7Sartem return 1;
71618c2aff7Sartem }
71718c2aff7Sartem printf ("\nStart monitoring devicelist:\n"
71818c2aff7Sartem "-------------------------------------------------\n");
71918c2aff7Sartem g_main_loop_run (loop);
72018c2aff7Sartem }
72118c2aff7Sartem
72218c2aff7Sartem if ( libhal_ctx_shutdown (hal_ctx, &error) == FALSE)
72318c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error);
72418c2aff7Sartem libhal_ctx_free (hal_ctx);
72518c2aff7Sartem
72618c2aff7Sartem dbus_connection_unref (conn);
72718c2aff7Sartem
72818c2aff7Sartem if (show_device)
72918c2aff7Sartem free(show_device);
73018c2aff7Sartem
73118c2aff7Sartem return 0;
73218c2aff7Sartem }
73318c2aff7Sartem
73418c2aff7Sartem /**
73518c2aff7Sartem * @}
73618c2aff7Sartem */
737