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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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