1*18c2aff7Sartem /***************************************************************************
2*18c2aff7Sartem * CVSID: $Id$
3*18c2aff7Sartem *
4*18c2aff7Sartem * lshal.c : Show devices managed by HAL
5*18c2aff7Sartem *
6*18c2aff7Sartem * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
7*18c2aff7Sartem * Copyright (C) 2005 Pierre Ossman, <drzeus@drzeus.cx>
8*18c2aff7Sartem *
9*18c2aff7Sartem * Licensed under the Academic Free License version 2.1
10*18c2aff7Sartem *
11*18c2aff7Sartem * This program is free software; you can redistribute it and/or modify
12*18c2aff7Sartem * it under the terms of the GNU General Public License as published by
13*18c2aff7Sartem * the Free Software Foundation; either version 2 of the License, or
14*18c2aff7Sartem * (at your option) any later version.
15*18c2aff7Sartem *
16*18c2aff7Sartem * This program is distributed in the hope that it will be useful,
17*18c2aff7Sartem * but WITHOUT ANY WARRANTY; without even the implied warranty of
18*18c2aff7Sartem * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19*18c2aff7Sartem * GNU General Public License for more details.
20*18c2aff7Sartem *
21*18c2aff7Sartem * You should have received a copy of the GNU General Public License
22*18c2aff7Sartem * along with this program; if not, write to the Free Software
23*18c2aff7Sartem * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24*18c2aff7Sartem *
25*18c2aff7Sartem **************************************************************************/
26*18c2aff7Sartem
27*18c2aff7Sartem
28*18c2aff7Sartem #ifdef HAVE_CONFIG_H
29*18c2aff7Sartem # include <config.h>
30*18c2aff7Sartem #endif
31*18c2aff7Sartem
32*18c2aff7Sartem #include <stdio.h>
33*18c2aff7Sartem #include <stdlib.h>
34*18c2aff7Sartem #include <string.h>
35*18c2aff7Sartem #include <unistd.h>
36*18c2aff7Sartem #include <getopt.h>
37*18c2aff7Sartem
38*18c2aff7Sartem #include <glib.h>
39*18c2aff7Sartem #include <dbus/dbus-glib-lowlevel.h>
40*18c2aff7Sartem #include <dbus/dbus-glib.h>
41*18c2aff7Sartem #include <libhal.h>
42*18c2aff7Sartem
43*18c2aff7Sartem #ifdef __SUNPRO_C
44*18c2aff7Sartem #define __FUNCTION__ __func__
45*18c2aff7Sartem #endif
46*18c2aff7Sartem
47*18c2aff7Sartem /**
48*18c2aff7Sartem * @defgroup HalLsHal List HAL devices
49*18c2aff7Sartem * @ingroup HalMisc
50*18c2aff7Sartem *
51*18c2aff7Sartem * @brief A commandline tool, lshal, for displaying and, optionally,
52*18c2aff7Sartem * monitor the devices managed by the HAL daemon. Uses libhal.
53*18c2aff7Sartem *
54*18c2aff7Sartem * @{
55*18c2aff7Sartem */
56*18c2aff7Sartem
57*18c2aff7Sartem /** Macro for terminating the program on an unrecoverable error */
58*18c2aff7Sartem #define DIE(expr) do {printf("*** [DIE] %s:%s():%d : ", __FILE__, __FUNCTION__, __LINE__); printf expr; printf("\n"); exit(1); } while(0)
59*18c2aff7Sartem
60*18c2aff7Sartem #define UDI_BASE "/org/freedesktop/Hal/devices/"
61*18c2aff7Sartem
62*18c2aff7Sartem static LibHalContext *hal_ctx;
63*18c2aff7Sartem static dbus_bool_t long_list = FALSE;
64*18c2aff7Sartem static dbus_bool_t tree_view = FALSE;
65*18c2aff7Sartem static dbus_bool_t short_list = FALSE;
66*18c2aff7Sartem static char *show_device = NULL;
67*18c2aff7Sartem
68*18c2aff7Sartem struct Device {
69*18c2aff7Sartem char *name;
70*18c2aff7Sartem char *parent;
71*18c2aff7Sartem };
72*18c2aff7Sartem
73*18c2aff7Sartem /** Generate a short name for a device
74*18c2aff7Sartem *
75*18c2aff7Sartem * @param udi Universal Device Id
76*18c2aff7Sartem */
77*18c2aff7Sartem static const char *
short_name(const char * udi)78*18c2aff7Sartem short_name (const char *udi)
79*18c2aff7Sartem {
80*18c2aff7Sartem return &udi[sizeof(UDI_BASE) - 1];
81*18c2aff7Sartem }
82*18c2aff7Sartem
83*18c2aff7Sartem /** Print all properties of a device
84*18c2aff7Sartem *
85*18c2aff7Sartem * @param udi Universal Device Id
86*18c2aff7Sartem */
87*18c2aff7Sartem
88*18c2aff7Sartem static void
print_props(const char * udi)89*18c2aff7Sartem print_props (const char *udi)
90*18c2aff7Sartem {
91*18c2aff7Sartem DBusError error;
92*18c2aff7Sartem LibHalPropertySet *props;
93*18c2aff7Sartem LibHalPropertySetIterator it;
94*18c2aff7Sartem int type;
95*18c2aff7Sartem
96*18c2aff7Sartem dbus_error_init (&error);
97*18c2aff7Sartem
98*18c2aff7Sartem props = libhal_device_get_all_properties (hal_ctx, udi, &error);
99*18c2aff7Sartem
100*18c2aff7Sartem /* NOTE : This may be NULL if the device was removed
101*18c2aff7Sartem * in the daemon; this is because
102*18c2aff7Sartem * hal_device_get_all_properties() is a in
103*18c2aff7Sartem * essence an IPC call and other stuff may
104*18c2aff7Sartem * be happening..
105*18c2aff7Sartem */
106*18c2aff7Sartem if (props == NULL) {
107*18c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error);
108*18c2aff7Sartem return;
109*18c2aff7Sartem }
110*18c2aff7Sartem
111*18c2aff7Sartem for (libhal_psi_init (&it, props); libhal_psi_has_more (&it); libhal_psi_next (&it)) {
112*18c2aff7Sartem type = libhal_psi_get_type (&it);
113*18c2aff7Sartem switch (type) {
114*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_STRING:
115*18c2aff7Sartem printf (" %s = '%s' (string)\n",
116*18c2aff7Sartem libhal_psi_get_key (&it),
117*18c2aff7Sartem libhal_psi_get_string (&it));
118*18c2aff7Sartem break;
119*18c2aff7Sartem
120*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_INT32:
121*18c2aff7Sartem printf (" %s = %d (0x%x) (int)\n",
122*18c2aff7Sartem libhal_psi_get_key (&it),
123*18c2aff7Sartem libhal_psi_get_int (&it),
124*18c2aff7Sartem libhal_psi_get_int (&it));
125*18c2aff7Sartem break;
126*18c2aff7Sartem
127*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_UINT64:
128*18c2aff7Sartem printf (" %s = %llu (0x%llx) (uint64)\n",
129*18c2aff7Sartem libhal_psi_get_key (&it),
130*18c2aff7Sartem (long long unsigned int) libhal_psi_get_uint64 (&it),
131*18c2aff7Sartem (long long unsigned int) libhal_psi_get_uint64 (&it));
132*18c2aff7Sartem break;
133*18c2aff7Sartem
134*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_DOUBLE:
135*18c2aff7Sartem printf (" %s = %g (double)\n",
136*18c2aff7Sartem libhal_psi_get_key (&it),
137*18c2aff7Sartem libhal_psi_get_double (&it));
138*18c2aff7Sartem break;
139*18c2aff7Sartem
140*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_BOOLEAN:
141*18c2aff7Sartem printf (" %s = %s (bool)\n",
142*18c2aff7Sartem libhal_psi_get_key (&it),
143*18c2aff7Sartem libhal_psi_get_bool (&it) ? "true" :
144*18c2aff7Sartem "false");
145*18c2aff7Sartem break;
146*18c2aff7Sartem
147*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_STRLIST:
148*18c2aff7Sartem {
149*18c2aff7Sartem unsigned int i;
150*18c2aff7Sartem char **strlist;
151*18c2aff7Sartem
152*18c2aff7Sartem printf (" %s = {", libhal_psi_get_key (&it));
153*18c2aff7Sartem
154*18c2aff7Sartem strlist = libhal_psi_get_strlist (&it);
155*18c2aff7Sartem for (i = 0; strlist[i] != 0; i++) {
156*18c2aff7Sartem printf ("'%s'", strlist[i]);
157*18c2aff7Sartem if (strlist[i+1] != NULL)
158*18c2aff7Sartem printf (", ");
159*18c2aff7Sartem }
160*18c2aff7Sartem printf ("} (string list)\n");
161*18c2aff7Sartem break;
162*18c2aff7Sartem }
163*18c2aff7Sartem
164*18c2aff7Sartem default:
165*18c2aff7Sartem printf ("Unknown type %d=0x%02x\n", type, type);
166*18c2aff7Sartem break;
167*18c2aff7Sartem }
168*18c2aff7Sartem }
169*18c2aff7Sartem
170*18c2aff7Sartem libhal_free_property_set (props);
171*18c2aff7Sartem }
172*18c2aff7Sartem
173*18c2aff7Sartem /** Dumps information about a single device
174*18c2aff7Sartem *
175*18c2aff7Sartem * @param udi Universal Device Id
176*18c2aff7Sartem */
177*18c2aff7Sartem
178*18c2aff7Sartem static void
dump_device(const char * udi)179*18c2aff7Sartem dump_device (const char *udi)
180*18c2aff7Sartem {
181*18c2aff7Sartem DBusError error;
182*18c2aff7Sartem
183*18c2aff7Sartem dbus_error_init (&error);
184*18c2aff7Sartem
185*18c2aff7Sartem if (!libhal_device_exists (hal_ctx, udi, &error)) {
186*18c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error);
187*18c2aff7Sartem return;
188*18c2aff7Sartem }
189*18c2aff7Sartem
190*18c2aff7Sartem if (long_list) {
191*18c2aff7Sartem printf ("udi = '%s'\n", udi);
192*18c2aff7Sartem
193*18c2aff7Sartem print_props (udi);
194*18c2aff7Sartem printf ("\n");
195*18c2aff7Sartem }
196*18c2aff7Sartem else
197*18c2aff7Sartem printf ("%s\n", short_name (udi));
198*18c2aff7Sartem }
199*18c2aff7Sartem
200*18c2aff7Sartem /** Dump all children of device
201*18c2aff7Sartem *
202*18c2aff7Sartem * @param udi Universal Device Id of parent
203*18c2aff7Sartem * @param num_devices Total number of devices in device list
204*18c2aff7Sartem * @param devices List of devices
205*18c2aff7Sartem * @param depth Current recursion depth
206*18c2aff7Sartem */
207*18c2aff7Sartem
208*18c2aff7Sartem static void
dump_children(char * udi,int num_devices,struct Device * devices,int depth)209*18c2aff7Sartem dump_children (char *udi, int num_devices, struct Device *devices, int depth)
210*18c2aff7Sartem {
211*18c2aff7Sartem int i;
212*18c2aff7Sartem
213*18c2aff7Sartem for (i = 0; i < num_devices; i++) {
214*18c2aff7Sartem if (!udi) {
215*18c2aff7Sartem if (devices[i].parent)
216*18c2aff7Sartem continue;
217*18c2aff7Sartem }
218*18c2aff7Sartem else {
219*18c2aff7Sartem if (!devices[i].parent)
220*18c2aff7Sartem continue;
221*18c2aff7Sartem if (strcmp (devices[i].parent, udi))
222*18c2aff7Sartem continue;
223*18c2aff7Sartem }
224*18c2aff7Sartem
225*18c2aff7Sartem if (long_list)
226*18c2aff7Sartem printf ("udi = '%s'\n", devices[i].name);
227*18c2aff7Sartem else {
228*18c2aff7Sartem int j;
229*18c2aff7Sartem if (tree_view) {
230*18c2aff7Sartem for (j = 0;j < depth;j++)
231*18c2aff7Sartem printf(" ");
232*18c2aff7Sartem }
233*18c2aff7Sartem printf ("%s\n", short_name (devices[i].name));
234*18c2aff7Sartem }
235*18c2aff7Sartem
236*18c2aff7Sartem if (long_list) {
237*18c2aff7Sartem print_props (devices[i].name);
238*18c2aff7Sartem printf ("\n");
239*18c2aff7Sartem }
240*18c2aff7Sartem
241*18c2aff7Sartem dump_children(devices[i].name, num_devices, devices, depth + 1);
242*18c2aff7Sartem }
243*18c2aff7Sartem }
244*18c2aff7Sartem
245*18c2aff7Sartem /** Dump all devices to stdout
246*18c2aff7Sartem *
247*18c2aff7Sartem */
248*18c2aff7Sartem static void
dump_devices(void)249*18c2aff7Sartem dump_devices (void)
250*18c2aff7Sartem {
251*18c2aff7Sartem int i;
252*18c2aff7Sartem int num_devices;
253*18c2aff7Sartem char **device_names;
254*18c2aff7Sartem struct Device *devices;
255*18c2aff7Sartem DBusError error;
256*18c2aff7Sartem
257*18c2aff7Sartem dbus_error_init (&error);
258*18c2aff7Sartem
259*18c2aff7Sartem device_names = libhal_get_all_devices (hal_ctx, &num_devices, &error);
260*18c2aff7Sartem if (device_names == NULL) {
261*18c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error);
262*18c2aff7Sartem DIE (("Couldn't obtain list of devices\n"));
263*18c2aff7Sartem }
264*18c2aff7Sartem
265*18c2aff7Sartem devices = malloc (sizeof(struct Device) * num_devices);
266*18c2aff7Sartem if (!devices) {
267*18c2aff7Sartem libhal_free_string_array (device_names);
268*18c2aff7Sartem return;
269*18c2aff7Sartem }
270*18c2aff7Sartem
271*18c2aff7Sartem for (i = 0;i < num_devices;i++) {
272*18c2aff7Sartem devices[i].name = device_names[i];
273*18c2aff7Sartem devices[i].parent = libhal_device_get_property_string (hal_ctx,
274*18c2aff7Sartem device_names[i], "info.parent", &error);
275*18c2aff7Sartem
276*18c2aff7Sartem if (dbus_error_is_set (&error)) {
277*18c2aff7Sartem /* Free the error (which include a dbus_error_init())
278*18c2aff7Sartem This should prevent errors if a call above fails */
279*18c2aff7Sartem dbus_error_free (&error);
280*18c2aff7Sartem }
281*18c2aff7Sartem }
282*18c2aff7Sartem
283*18c2aff7Sartem if (long_list) {
284*18c2aff7Sartem printf ("\n"
285*18c2aff7Sartem "Dumping %d device(s) from the Global Device List:\n"
286*18c2aff7Sartem "-------------------------------------------------\n",
287*18c2aff7Sartem num_devices);
288*18c2aff7Sartem }
289*18c2aff7Sartem
290*18c2aff7Sartem dump_children(NULL, num_devices, devices, 0);
291*18c2aff7Sartem
292*18c2aff7Sartem for (i = 0;i < num_devices;i++) {
293*18c2aff7Sartem if (devices[i].parent)
294*18c2aff7Sartem libhal_free_string (devices[i].parent);
295*18c2aff7Sartem }
296*18c2aff7Sartem
297*18c2aff7Sartem free (devices);
298*18c2aff7Sartem libhal_free_string_array (device_names);
299*18c2aff7Sartem
300*18c2aff7Sartem if (long_list) {
301*18c2aff7Sartem printf ("\n"
302*18c2aff7Sartem "Dumped %d device(s) from the Global Device List.\n"
303*18c2aff7Sartem "------------------------------------------------\n",
304*18c2aff7Sartem num_devices);
305*18c2aff7Sartem
306*18c2aff7Sartem printf ("\n");
307*18c2aff7Sartem }
308*18c2aff7Sartem }
309*18c2aff7Sartem
310*18c2aff7Sartem /** Invoked when a device is added to the Global Device List. Simply prints
311*18c2aff7Sartem * a message on stdout.
312*18c2aff7Sartem *
313*18c2aff7Sartem * @param udi Universal Device Id
314*18c2aff7Sartem */
315*18c2aff7Sartem static void
device_added(LibHalContext * ctx,const char * udi)316*18c2aff7Sartem device_added (LibHalContext *ctx,
317*18c2aff7Sartem const char *udi)
318*18c2aff7Sartem {
319*18c2aff7Sartem if (show_device && strcmp(show_device, udi))
320*18c2aff7Sartem return;
321*18c2aff7Sartem
322*18c2aff7Sartem if (long_list) {
323*18c2aff7Sartem printf ("*** lshal: device_added, udi='%s'\n", udi);
324*18c2aff7Sartem print_props (udi);
325*18c2aff7Sartem } else
326*18c2aff7Sartem printf ("%s added\n", short_name (udi));
327*18c2aff7Sartem }
328*18c2aff7Sartem
329*18c2aff7Sartem /** Invoked when a device is removed from the Global Device List. Simply
330*18c2aff7Sartem * prints a message on stdout.
331*18c2aff7Sartem *
332*18c2aff7Sartem * @param udi Universal Device Id
333*18c2aff7Sartem */
334*18c2aff7Sartem static void
device_removed(LibHalContext * ctx,const char * udi)335*18c2aff7Sartem device_removed (LibHalContext *ctx,
336*18c2aff7Sartem const char *udi)
337*18c2aff7Sartem {
338*18c2aff7Sartem if (show_device && strcmp(show_device, udi))
339*18c2aff7Sartem return;
340*18c2aff7Sartem
341*18c2aff7Sartem if (long_list)
342*18c2aff7Sartem printf ("*** lshal: device_removed, udi='%s'\n", udi);
343*18c2aff7Sartem else
344*18c2aff7Sartem printf ("%s removed\n", short_name (udi));
345*18c2aff7Sartem }
346*18c2aff7Sartem
347*18c2aff7Sartem /** Invoked when device in the Global Device List acquires a new capability.
348*18c2aff7Sartem * Prints the name of the capability to stdout.
349*18c2aff7Sartem *
350*18c2aff7Sartem * @param udi Universal Device Id
351*18c2aff7Sartem * @param capability Name of capability
352*18c2aff7Sartem */
353*18c2aff7Sartem static void
device_new_capability(LibHalContext * ctx,const char * udi,const char * capability)354*18c2aff7Sartem device_new_capability (LibHalContext *ctx,
355*18c2aff7Sartem const char *udi,
356*18c2aff7Sartem const char *capability)
357*18c2aff7Sartem {
358*18c2aff7Sartem if (show_device && strcmp(show_device, udi))
359*18c2aff7Sartem return;
360*18c2aff7Sartem
361*18c2aff7Sartem if (long_list) {
362*18c2aff7Sartem printf ("*** lshal: new_capability, udi='%s'\n", udi);
363*18c2aff7Sartem printf ("*** capability: %s\n", capability);
364*18c2aff7Sartem } else
365*18c2aff7Sartem printf ("%s capability %s added\n", short_name (udi),
366*18c2aff7Sartem capability);
367*18c2aff7Sartem }
368*18c2aff7Sartem
369*18c2aff7Sartem /** Invoked when device in the Global Device List loses a capability.
370*18c2aff7Sartem * Prints the name of the capability to stdout.
371*18c2aff7Sartem *
372*18c2aff7Sartem * @param udi Universal Device Id
373*18c2aff7Sartem * @param capability Name of capability
374*18c2aff7Sartem */
375*18c2aff7Sartem static void
device_lost_capability(LibHalContext * ctx,const char * udi,const char * capability)376*18c2aff7Sartem device_lost_capability (LibHalContext *ctx,
377*18c2aff7Sartem const char *udi,
378*18c2aff7Sartem const char *capability)
379*18c2aff7Sartem {
380*18c2aff7Sartem if (show_device && strcmp(show_device, udi))
381*18c2aff7Sartem return;
382*18c2aff7Sartem
383*18c2aff7Sartem if (long_list) {
384*18c2aff7Sartem printf ("*** lshal: lost_capability, udi='%s'\n", udi);
385*18c2aff7Sartem printf ("*** capability: %s\n", capability);
386*18c2aff7Sartem } else
387*18c2aff7Sartem printf ("%s capability %s lost\n", short_name (udi),
388*18c2aff7Sartem capability);
389*18c2aff7Sartem }
390*18c2aff7Sartem
391*18c2aff7Sartem /** Acquires and prints the value of of a property to stdout.
392*18c2aff7Sartem *
393*18c2aff7Sartem * @param udi Universal Device Id
394*18c2aff7Sartem * @param key Key of property
395*18c2aff7Sartem */
396*18c2aff7Sartem static void
print_property(const char * udi,const char * key)397*18c2aff7Sartem print_property (const char *udi, const char *key)
398*18c2aff7Sartem {
399*18c2aff7Sartem int type;
400*18c2aff7Sartem char *str;
401*18c2aff7Sartem DBusError error;
402*18c2aff7Sartem
403*18c2aff7Sartem dbus_error_init (&error);
404*18c2aff7Sartem
405*18c2aff7Sartem type = libhal_device_get_property_type (hal_ctx, udi, key, &error);
406*18c2aff7Sartem
407*18c2aff7Sartem switch (type) {
408*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_STRING:
409*18c2aff7Sartem str = libhal_device_get_property_string (hal_ctx, udi, key, &error);
410*18c2aff7Sartem printf (long_list?"*** new value: '%s' (string)\n":"'%s'", str);
411*18c2aff7Sartem libhal_free_string (str);
412*18c2aff7Sartem break;
413*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_INT32:
414*18c2aff7Sartem {
415*18c2aff7Sartem dbus_int32_t value = libhal_device_get_property_int (hal_ctx, udi, key, &error);
416*18c2aff7Sartem printf (long_list?"*** new value: %d (0x%x) (int)\n":"%d (0x%x)",
417*18c2aff7Sartem value, value);
418*18c2aff7Sartem }
419*18c2aff7Sartem break;
420*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_UINT64:
421*18c2aff7Sartem {
422*18c2aff7Sartem dbus_uint64_t value = libhal_device_get_property_uint64 (hal_ctx, udi, key, &error);
423*18c2aff7Sartem printf (long_list?"*** new value: %llu (0x%llx) (uint64)\n":"%llu (0x%llx)",
424*18c2aff7Sartem (long long unsigned int) value, (long long unsigned int) value);
425*18c2aff7Sartem }
426*18c2aff7Sartem break;
427*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_DOUBLE:
428*18c2aff7Sartem printf (long_list?"*** new value: %g (double)\n":"%g",
429*18c2aff7Sartem libhal_device_get_property_double (hal_ctx, udi, key, &error));
430*18c2aff7Sartem break;
431*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_BOOLEAN:
432*18c2aff7Sartem printf (long_list?"*** new value: %s (bool)\n":"%s",
433*18c2aff7Sartem libhal_device_get_property_bool (hal_ctx, udi, key, &error) ? "true" : "false");
434*18c2aff7Sartem break;
435*18c2aff7Sartem case LIBHAL_PROPERTY_TYPE_STRLIST:
436*18c2aff7Sartem {
437*18c2aff7Sartem unsigned int i;
438*18c2aff7Sartem char **strlist;
439*18c2aff7Sartem
440*18c2aff7Sartem if (long_list)
441*18c2aff7Sartem printf ("*** new value: {");
442*18c2aff7Sartem else
443*18c2aff7Sartem printf ("{");
444*18c2aff7Sartem
445*18c2aff7Sartem strlist = libhal_device_get_property_strlist (hal_ctx, udi, key, &error);
446*18c2aff7Sartem for (i = 0; strlist[i] != 0; i++) {
447*18c2aff7Sartem printf ("'%s'", strlist[i]);
448*18c2aff7Sartem if (strlist[i+1] != NULL)
449*18c2aff7Sartem printf (", ");
450*18c2aff7Sartem }
451*18c2aff7Sartem if (long_list)
452*18c2aff7Sartem printf ("} (string list)\n");
453*18c2aff7Sartem else
454*18c2aff7Sartem printf ("}");
455*18c2aff7Sartem libhal_free_string_array (strlist);
456*18c2aff7Sartem break;
457*18c2aff7Sartem }
458*18c2aff7Sartem
459*18c2aff7Sartem default:
460*18c2aff7Sartem fprintf (stderr, "Unknown type %d='%c'\n", type, type);
461*18c2aff7Sartem break;
462*18c2aff7Sartem }
463*18c2aff7Sartem
464*18c2aff7Sartem if (dbus_error_is_set (&error))
465*18c2aff7Sartem dbus_error_free (&error);
466*18c2aff7Sartem }
467*18c2aff7Sartem
468*18c2aff7Sartem /** Invoked when a property of a device in the Global Device List is
469*18c2aff7Sartem * changed, and we have we have subscribed to changes for that device.
470*18c2aff7Sartem *
471*18c2aff7Sartem * @param udi Univerisal Device Id
472*18c2aff7Sartem * @param key Key of property
473*18c2aff7Sartem */
474*18c2aff7Sartem static void
property_modified(LibHalContext * ctx,const char * udi,const char * key,dbus_bool_t is_removed,dbus_bool_t is_added)475*18c2aff7Sartem property_modified (LibHalContext *ctx,
476*18c2aff7Sartem const char *udi,
477*18c2aff7Sartem const char *key,
478*18c2aff7Sartem dbus_bool_t is_removed,
479*18c2aff7Sartem dbus_bool_t is_added)
480*18c2aff7Sartem {
481*18c2aff7Sartem if (show_device && strcmp(show_device, udi))
482*18c2aff7Sartem return;
483*18c2aff7Sartem
484*18c2aff7Sartem if (long_list) {
485*18c2aff7Sartem printf ("*** lshal: property_modified, udi=%s, key=%s\n",
486*18c2aff7Sartem udi, key);
487*18c2aff7Sartem printf (" is_removed=%s, is_added=%s\n",
488*18c2aff7Sartem is_removed ? "true" : "false",
489*18c2aff7Sartem is_added ? "true" : "false");
490*18c2aff7Sartem if (!is_removed)
491*18c2aff7Sartem print_property (udi, key);
492*18c2aff7Sartem printf ("\n");
493*18c2aff7Sartem } else {
494*18c2aff7Sartem printf ("%s property %s ", short_name (udi), key);
495*18c2aff7Sartem if (is_removed)
496*18c2aff7Sartem printf ("removed");
497*18c2aff7Sartem else {
498*18c2aff7Sartem printf ("= ");
499*18c2aff7Sartem print_property (udi, key);
500*18c2aff7Sartem
501*18c2aff7Sartem if (is_added)
502*18c2aff7Sartem printf (" (new)");
503*18c2aff7Sartem }
504*18c2aff7Sartem printf ("\n");
505*18c2aff7Sartem }
506*18c2aff7Sartem }
507*18c2aff7Sartem
508*18c2aff7Sartem
509*18c2aff7Sartem /** Invoked when a property of a device in the Global Device List is
510*18c2aff7Sartem * changed, and we have we have subscribed to changes for that device.
511*18c2aff7Sartem *
512*18c2aff7Sartem * @param udi Univerisal Device Id
513*18c2aff7Sartem * @param condition_name Name of condition
514*18c2aff7Sartem * @param message D-BUS message with parameters
515*18c2aff7Sartem */
516*18c2aff7Sartem static void
device_condition(LibHalContext * ctx,const char * udi,const char * condition_name,const char * condition_details)517*18c2aff7Sartem device_condition (LibHalContext *ctx,
518*18c2aff7Sartem const char *udi,
519*18c2aff7Sartem const char *condition_name,
520*18c2aff7Sartem const char *condition_details)
521*18c2aff7Sartem {
522*18c2aff7Sartem if (show_device && strcmp(show_device, udi))
523*18c2aff7Sartem return;
524*18c2aff7Sartem
525*18c2aff7Sartem if (long_list) {
526*18c2aff7Sartem printf ("*** lshal: device_condition, udi=%s\n", udi);
527*18c2aff7Sartem printf (" condition_name=%s\n", condition_name);
528*18c2aff7Sartem printf (" condition_details=%s\n", condition_details);
529*18c2aff7Sartem printf ("\n");
530*18c2aff7Sartem } else {
531*18c2aff7Sartem printf ("%s condition %s = %s\n", short_name (udi),
532*18c2aff7Sartem condition_name, condition_details);
533*18c2aff7Sartem }
534*18c2aff7Sartem }
535*18c2aff7Sartem
536*18c2aff7Sartem
537*18c2aff7Sartem /** Print out program usage.
538*18c2aff7Sartem *
539*18c2aff7Sartem * @param argc Number of arguments given to program
540*18c2aff7Sartem * @param argv Arguments given to program
541*18c2aff7Sartem */
542*18c2aff7Sartem static void
usage(int argc,char * argv[])543*18c2aff7Sartem usage (int argc, char *argv[])
544*18c2aff7Sartem {
545*18c2aff7Sartem fprintf (stderr, "lshal version " PACKAGE_VERSION "\n");
546*18c2aff7Sartem
547*18c2aff7Sartem fprintf (stderr, "\n" "usage : %s [options]\n", argv[0]);
548*18c2aff7Sartem fprintf (stderr,
549*18c2aff7Sartem "\n"
550*18c2aff7Sartem "Options:\n"
551*18c2aff7Sartem " -m, --monitor Monitor device list\n"
552*18c2aff7Sartem " -s, --short short output (print only nonstatic part of udi)\n"
553*18c2aff7Sartem " -l, --long Long output\n"
554*18c2aff7Sartem " -t, --tree Tree view\n"
555*18c2aff7Sartem " -u, --show <udi> Show only the specified device\n"
556*18c2aff7Sartem "\n"
557*18c2aff7Sartem " -h, --help Show this information and exit\n"
558*18c2aff7Sartem " -V, --version Print version number\n"
559*18c2aff7Sartem "\n"
560*18c2aff7Sartem "Without any given options lshal will start with option --long."
561*18c2aff7Sartem "\n"
562*18c2aff7Sartem "Shows all devices and their properties. If the --monitor option is given\n"
563*18c2aff7Sartem "then the device list and all devices are monitored for changes.\n"
564*18c2aff7Sartem "\n");
565*18c2aff7Sartem }
566*18c2aff7Sartem
567*18c2aff7Sartem /** Entry point
568*18c2aff7Sartem *
569*18c2aff7Sartem * @param argc Number of arguments given to program
570*18c2aff7Sartem * @param argv Arguments given to program
571*18c2aff7Sartem * @return Return code
572*18c2aff7Sartem */
573*18c2aff7Sartem int
main(int argc,char * argv[])574*18c2aff7Sartem main (int argc, char *argv[])
575*18c2aff7Sartem {
576*18c2aff7Sartem DBusError error;
577*18c2aff7Sartem dbus_bool_t do_monitor = FALSE;
578*18c2aff7Sartem GMainLoop *loop;
579*18c2aff7Sartem DBusConnection *conn;
580*18c2aff7Sartem
581*18c2aff7Sartem if (argc == 1) {
582*18c2aff7Sartem /* This is the default case lshal without any options */
583*18c2aff7Sartem long_list = TRUE;
584*18c2aff7Sartem }
585*18c2aff7Sartem else {
586*18c2aff7Sartem static const struct option long_options[] = {
587*18c2aff7Sartem {"monitor", no_argument, NULL, 'm'},
588*18c2aff7Sartem {"long", no_argument, NULL, 'l'},
589*18c2aff7Sartem {"short", no_argument, NULL, 's'},
590*18c2aff7Sartem {"tree", no_argument, NULL, 't'},
591*18c2aff7Sartem {"show", required_argument, NULL, 'u'},
592*18c2aff7Sartem {"help", no_argument, NULL, 'h'},
593*18c2aff7Sartem {"usage", no_argument, NULL, 'U'},
594*18c2aff7Sartem {"version", no_argument, NULL, 'V'},
595*18c2aff7Sartem {NULL, 0, NULL, 0}
596*18c2aff7Sartem };
597*18c2aff7Sartem
598*18c2aff7Sartem while (1) {
599*18c2aff7Sartem int c;
600*18c2aff7Sartem
601*18c2aff7Sartem c = getopt_long (argc, argv, "mlstu:hUV", long_options, NULL);
602*18c2aff7Sartem
603*18c2aff7Sartem if (c == -1) {
604*18c2aff7Sartem /* this should happen e.g. if 'lshal -' and this is incorrect/incomplete option */
605*18c2aff7Sartem if (!do_monitor && !long_list && !short_list && !tree_view && !show_device) {
606*18c2aff7Sartem usage (argc, argv);
607*18c2aff7Sartem return 1;
608*18c2aff7Sartem }
609*18c2aff7Sartem
610*18c2aff7Sartem break;
611*18c2aff7Sartem }
612*18c2aff7Sartem
613*18c2aff7Sartem switch (c) {
614*18c2aff7Sartem case 'm':
615*18c2aff7Sartem do_monitor = TRUE;
616*18c2aff7Sartem break;
617*18c2aff7Sartem
618*18c2aff7Sartem case 'l':
619*18c2aff7Sartem long_list = TRUE;
620*18c2aff7Sartem break;
621*18c2aff7Sartem
622*18c2aff7Sartem case 's':
623*18c2aff7Sartem short_list = TRUE;
624*18c2aff7Sartem long_list = FALSE;
625*18c2aff7Sartem break;
626*18c2aff7Sartem
627*18c2aff7Sartem case 't':
628*18c2aff7Sartem tree_view = TRUE;
629*18c2aff7Sartem break;
630*18c2aff7Sartem
631*18c2aff7Sartem case 'u':
632*18c2aff7Sartem if (strchr(optarg, '/') != NULL)
633*18c2aff7Sartem show_device = strdup(optarg);
634*18c2aff7Sartem else {
635*18c2aff7Sartem show_device = malloc(strlen(UDI_BASE) + strlen(optarg) + 1);
636*18c2aff7Sartem memcpy(show_device, UDI_BASE, strlen(UDI_BASE));
637*18c2aff7Sartem memcpy(show_device + strlen(UDI_BASE), optarg, strlen(optarg) + 1);
638*18c2aff7Sartem }
639*18c2aff7Sartem
640*18c2aff7Sartem break;
641*18c2aff7Sartem
642*18c2aff7Sartem case 'h':
643*18c2aff7Sartem case 'U':
644*18c2aff7Sartem usage (argc, argv);
645*18c2aff7Sartem return 0;
646*18c2aff7Sartem
647*18c2aff7Sartem case 'V':
648*18c2aff7Sartem printf ("lshal version " PACKAGE_VERSION "\n");
649*18c2aff7Sartem return 0;
650*18c2aff7Sartem
651*18c2aff7Sartem default:
652*18c2aff7Sartem usage (argc, argv);
653*18c2aff7Sartem return 1;
654*18c2aff7Sartem }
655*18c2aff7Sartem }
656*18c2aff7Sartem }
657*18c2aff7Sartem
658*18c2aff7Sartem if (do_monitor)
659*18c2aff7Sartem loop = g_main_loop_new (NULL, FALSE);
660*18c2aff7Sartem else
661*18c2aff7Sartem loop = NULL;
662*18c2aff7Sartem
663*18c2aff7Sartem dbus_error_init (&error);
664*18c2aff7Sartem conn = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
665*18c2aff7Sartem if (conn == NULL) {
666*18c2aff7Sartem fprintf (stderr, "error: dbus_bus_get: %s: %s\n",
667*18c2aff7Sartem error.name, error.message);
668*18c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error);
669*18c2aff7Sartem return 1;
670*18c2aff7Sartem }
671*18c2aff7Sartem
672*18c2aff7Sartem if (do_monitor)
673*18c2aff7Sartem dbus_connection_setup_with_g_main (conn, NULL);
674*18c2aff7Sartem
675*18c2aff7Sartem if ((hal_ctx = libhal_ctx_new ()) == NULL) {
676*18c2aff7Sartem fprintf (stderr, "error: libhal_ctx_new\n");
677*18c2aff7Sartem return 1;
678*18c2aff7Sartem }
679*18c2aff7Sartem if (!libhal_ctx_set_dbus_connection (hal_ctx, conn)) {
680*18c2aff7Sartem fprintf (stderr, "error: libhal_ctx_set_dbus_connection: %s: %s\n",
681*18c2aff7Sartem error.name, error.message);
682*18c2aff7Sartem return 1;
683*18c2aff7Sartem }
684*18c2aff7Sartem if (!libhal_ctx_init (hal_ctx, &error)) {
685*18c2aff7Sartem if (dbus_error_is_set(&error)) {
686*18c2aff7Sartem fprintf (stderr, "error: libhal_ctx_init: %s: %s\n", error.name, error.message);
687*18c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error);
688*18c2aff7Sartem }
689*18c2aff7Sartem fprintf (stderr, "Could not initialise connection to hald.\n"
690*18c2aff7Sartem "Normally this means the HAL daemon (hald) is not running or not ready.\n");
691*18c2aff7Sartem return 1;
692*18c2aff7Sartem }
693*18c2aff7Sartem
694*18c2aff7Sartem libhal_ctx_set_device_added (hal_ctx, device_added);
695*18c2aff7Sartem libhal_ctx_set_device_removed (hal_ctx, device_removed);
696*18c2aff7Sartem libhal_ctx_set_device_new_capability (hal_ctx, device_new_capability);
697*18c2aff7Sartem libhal_ctx_set_device_lost_capability (hal_ctx, device_lost_capability);
698*18c2aff7Sartem libhal_ctx_set_device_property_modified (hal_ctx, property_modified);
699*18c2aff7Sartem libhal_ctx_set_device_condition (hal_ctx, device_condition);
700*18c2aff7Sartem
701*18c2aff7Sartem if (show_device)
702*18c2aff7Sartem dump_device (show_device);
703*18c2aff7Sartem else if (!do_monitor)
704*18c2aff7Sartem dump_devices ();
705*18c2aff7Sartem
706*18c2aff7Sartem /* run the main loop only if we should monitor */
707*18c2aff7Sartem if (do_monitor && loop != NULL) {
708*18c2aff7Sartem if( long_list || short_list || tree_view )
709*18c2aff7Sartem dump_devices ();
710*18c2aff7Sartem
711*18c2aff7Sartem if ( libhal_device_property_watch_all (hal_ctx, &error) == FALSE) {
712*18c2aff7Sartem fprintf (stderr, "error: monitoring devicelist - libhal_device_property_watch_all: %s: %s\n",
713*18c2aff7Sartem error.name, error.message);
714*18c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error);
715*18c2aff7Sartem return 1;
716*18c2aff7Sartem }
717*18c2aff7Sartem printf ("\nStart monitoring devicelist:\n"
718*18c2aff7Sartem "-------------------------------------------------\n");
719*18c2aff7Sartem g_main_loop_run (loop);
720*18c2aff7Sartem }
721*18c2aff7Sartem
722*18c2aff7Sartem if ( libhal_ctx_shutdown (hal_ctx, &error) == FALSE)
723*18c2aff7Sartem LIBHAL_FREE_DBUS_ERROR (&error);
724*18c2aff7Sartem libhal_ctx_free (hal_ctx);
725*18c2aff7Sartem
726*18c2aff7Sartem dbus_connection_unref (conn);
727*18c2aff7Sartem
728*18c2aff7Sartem if (show_device)
729*18c2aff7Sartem free(show_device);
730*18c2aff7Sartem
731*18c2aff7Sartem return 0;
732*18c2aff7Sartem }
733*18c2aff7Sartem
734*18c2aff7Sartem /**
735*18c2aff7Sartem * @}
736*18c2aff7Sartem */
737