HAL: libhal.c Source File

Main Page | Modules | Data Structures | Directories | File List | Data Fields | Related Pages

# libhal.c

    00001 /***************************************************************************
    00002  * CVSID: $Id: libhal.c,v 1.32.2.1 2005/01/07 03:18:53 david Exp $
    00003  *
    00004  * libhal.c : HAL daemon C convenience library
    00005  *
    00006  * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
    00007  *
    00008  * Licensed under the Academic Free License version 2.0
    00009  *
    00010  * This program is free software; you can redistribute it and/or modify
    00011  * it under the terms of the GNU General Public License as published by
    00012  * the Free Software Foundation; either version 2 of the License, or
    00013  * (at your option) any later version.
    00014  *
    00015  * This program is distributed in the hope that it will be useful,
    00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00018  * GNU General Public License for more details.
    00019  *
    00020  * You should have received a copy of the GNU General Public License
    00021  * along with this program; if not, write to the Free Software
    00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00023  *
    00024  **************************************************************************/
    00025
    00026 #ifdef HAVE_CONFIG_H
    00027 #  include <config.h>
    00028 #endif
    00029
    00030 #include <stdio.h>
    00031 #include <stdlib.h>
    00032 #include <string.h>
    00033 #include <dbus/dbus.h>
    00034
    00035 #include "libhal.h"
    00036
    00037 #ifdef ENABLE_NLS
    00038 # include <libintl.h>
    00039 # define _(String) dgettext (GETTEXT_PACKAGE, String)
    00040 # ifdef gettext_noop
    00041 #   define N_(String) gettext_noop (String)
    00042 # else
    00043 #   define N_(String) (String)
    00044 # endif
    00045 #else
    00046 /* Stubs that do something close enough.  */
    00047 # define textdomain(String) (String)
    00048 # define gettext(String) (String)
    00049 # define dgettext(Domain,Message) (Message)
    00050 # define dcgettext(Domain,Message,Type) (Message)
    00051 # define bindtextdomain(Domain,Directory) (Domain)
    00052 # define _(String)
    00053 # define N_(String) (String)
    00054 #endif
    00055
    00068 void
    00069 hal_free_string_array (char **str_array)
    00070 {
    00071     if (str_array != NULL) {
    00072         int i;
    00073
    00074         for (i = 0; str_array[i] != NULL; i++) {
    00075             free (str_array[i]);
    00076         }
    00077         free (str_array);
    00078     }
    00079 }
    00080
    00085 void
    00086 hal_free_string (char *str)
    00087 {
    00089     free (str);
    00090 }
    00091
    00092
    00094 struct LibHalPropertySet_s {
    00095     unsigned int num_properties;
    00096     LibHalProperty *properties_head;
    00099 };
    00100
    00102 struct LibHalProperty_s {
    00103     int type;
    00104     char *key;
    00107     union {
    00108         char *str_value;
    00109         dbus_int32_t int_value;
    00111         dbus_uint64_t uint64_value;
    00113         double double_value;
    00114         dbus_bool_t bool_value;
    00116     };
    00117
    00118     LibHalProperty *next;
    00120 };
    00121
    00123 struct LibHalContext_s {
    00124     DBusConnection *connection;
    00125     dbus_bool_t is_initialized;
    00126     dbus_bool_t is_shutdown;
    00127     dbus_bool_t cache_enabled;
    00128     const LibHalFunctions *functions;
    00129     void *user_data;
    00130 };
    00131
    00137 void
    00138 hal_ctx_set_user_data(LibHalContext *ctx, void *user_data)
    00139 {
    00140     ctx->user_data = user_data;
    00141 }
    00142
    00149 void*
    00150 hal_ctx_get_user_data(LibHalContext *ctx)
    00151 {
    00152     return ctx->user_data;
    00153 }
    00154
    00155
    00163 LibHalPropertySet *
    00164 hal_device_get_all_properties (LibHalContext *ctx, const char *udi)
    00165 {
    00166     DBusError error;
    00167     DBusMessage *message;
    00168     DBusMessage *reply;
    00169     DBusMessageIter iter;
    00170     DBusMessageIter dict_iter;
    00171     LibHalPropertySet *result;
    00172     LibHalProperty **pn;
    00173
    00174     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
    00175                         "org.freedesktop.Hal.Device",
    00176                         "GetAllProperties");
    00177     if (message == NULL) {
    00178         fprintf (stderr,
    00179              "%s %d : Couldn't allocate D-BUS message\n",
    00180              __FILE__, __LINE__);
    00181         return NULL;
    00182     }
    00183
    00184     dbus_error_init (&error);
    00185     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    00186                                message, -1,
    00187                                &error);
    00188     if (dbus_error_is_set (&error)) {
    00189         fprintf (stderr, "%s %d: %s raised\n\"%s\"\n\n", __FILE__,
    00190              __LINE__, error.name, error.message);
    00191         dbus_message_unref (message);
    00192         return NULL;
    00193     }
    00194
    00195     if (reply == NULL) {
    00196         dbus_message_unref (message);
    00197         return NULL;
    00198     }
    00199
    00200     dbus_message_iter_init (reply, &iter);
    00201
    00202     result = malloc (sizeof (LibHalPropertySet));
    00203     if (result == NULL) {
    00204         fprintf (stderr, "%s %d : error allocating memory\n",
    00205              __FILE__, __LINE__);
    00206         dbus_message_unref (message);
    00207         dbus_message_unref (reply);
    00208         return NULL;
    00209     }
    00210
    00211 /*
    00212     result->properties = malloc(sizeof(LibHalProperty)*result->num_properties);
    00213     if( result->properties==NULL )
    00214     {
    00216     return NULL;
    00217     }
    00218 */
    00219
    00220     pn = &result->properties_head;
    00221     result->num_properties = 0;
    00222
    00223     dbus_message_iter_init_dict_iterator (&iter, &dict_iter);
    00224
    00225     do {
    00226         char *dbus_str;
    00227         LibHalProperty *p;
    00228
    00229         p = malloc (sizeof (LibHalProperty));
    00230         if (p == NULL) {
    00231             fprintf (stderr,
    00232                  "%s %d : error allocating memory\n",
    00233                  __FILE__, __LINE__);
    00235             return NULL;
    00236         }
    00237
    00238         *pn = p;
    00239         pn = &p->next;
    00240         p->next = NULL;
    00241         result->num_properties++;
    00242
    00243         dbus_str = dbus_message_iter_get_dict_key (&dict_iter);
    00244         p->key =
    00245             (char *) ((dbus_str != NULL) ? strdup (dbus_str) :
    00246                   NULL);
    00247         if (p->key == NULL) {
    00248             fprintf (stderr,
    00249                  "%s %d : error allocating memory\n",
    00250                  __FILE__, __LINE__);
    00252             return NULL;
    00253         }
    00254         dbus_free (dbus_str);
    00255
    00256         p->type = dbus_message_iter_get_arg_type (&dict_iter);
    00257
    00258         switch (p->type) {
    00259         case DBUS_TYPE_STRING:
    00260             dbus_str =
    00261                 dbus_message_iter_get_string (&dict_iter);
    00262             p->str_value =
    00263                 (char *) ((dbus_str != NULL) ?
    00264                       strdup (dbus_str) : NULL);
    00265             if (p->str_value == NULL) {
    00266                 fprintf (stderr,
    00267                      "%s %d : error allocating memory\n",
    00268                      __FILE__, __LINE__);
    00270                 return NULL;
    00271             }
    00272             dbus_free (dbus_str);
    00273             break;
    00274         case DBUS_TYPE_INT32:
    00275             p->int_value =
    00276                 dbus_message_iter_get_int32 (&dict_iter);
    00277             break;
    00278         case DBUS_TYPE_UINT64:
    00279             p->uint64_value =
    00280                 dbus_message_iter_get_uint64 (&dict_iter);
    00281             break;
    00282         case DBUS_TYPE_DOUBLE:
    00283             p->double_value =
    00284                 dbus_message_iter_get_double (&dict_iter);
    00285             break;
    00286         case DBUS_TYPE_BOOLEAN:
    00287             p->bool_value =
    00288                 dbus_message_iter_get_boolean (&dict_iter);
    00289             break;
    00290
    00291         default:
    00293             break;
    00294         }
    00295
    00296     }
    00297     while (dbus_message_iter_has_next (&dict_iter) &&
    00298            dbus_message_iter_next (&dict_iter));
    00299
    00300     dbus_message_unref (message);
    00301     dbus_message_unref (reply);
    00302
    00303     return result;
    00304 }
    00305
    00310 void
    00311 hal_free_property_set (LibHalPropertySet * set)
    00312 {
    00313     LibHalProperty *p;
    00314     LibHalProperty *q;
    00315
    00316     if (set == NULL)
    00317         return;
    00318
    00319     for (p = set->properties_head; p != NULL; p = q) {
    00320         free (p->key);
    00321         if (p->type == DBUS_TYPE_STRING)
    00322             free (p->str_value);
    00323         q = p->next;
    00324         free (p);
    00325     }
    00326     free (set);
    00327 }
    00328
    00334 void
    00335 hal_psi_init (LibHalPropertySetIterator * iter, LibHalPropertySet * set)
    00336 {
    00337     iter->set = set;
    00338     iter->index = 0;
    00339     iter->cur_prop = set->properties_head;
    00340 }
    00341
    00347 dbus_bool_t
    00348 hal_psi_has_more (LibHalPropertySetIterator * iter)
    00349 {
    00350     return iter->index < iter->set->num_properties;
    00351 }
    00352
    00357 void
    00358 hal_psi_next (LibHalPropertySetIterator * iter)
    00359 {
    00360     iter->index++;
    00361     iter->cur_prop = iter->cur_prop->next;
    00362 }
    00363
    00370 int
    00371 hal_psi_get_type (LibHalPropertySetIterator * iter)
    00372 {
    00373     return iter->cur_prop->type;
    00374 }
    00375
    00384 char *
    00385 hal_psi_get_key (LibHalPropertySetIterator * iter)
    00386 {
    00387     return iter->cur_prop->key;
    00388 }
    00389
    00398 char *
    00399 hal_psi_get_string (LibHalPropertySetIterator * iter)
    00400 {
    00401     return iter->cur_prop->str_value;
    00402 }
    00403
    00409 dbus_int32_t
    00410 hal_psi_get_int (LibHalPropertySetIterator * iter)
    00411 {
    00412     return iter->cur_prop->int_value;
    00413 }
    00414
    00420 dbus_uint64_t
    00421 hal_psi_get_uint64 (LibHalPropertySetIterator * iter)
    00422 {
    00423     return iter->cur_prop->uint64_value;
    00424 }
    00425
    00431 double
    00432 hal_psi_get_double (LibHalPropertySetIterator * iter)
    00433 {
    00434     return iter->cur_prop->double_value;
    00435 }
    00436
    00442 dbus_bool_t
    00443 hal_psi_get_bool (LibHalPropertySetIterator * iter)
    00444 {
    00445     return iter->cur_prop->bool_value;
    00446 }
    00447
    00448
    00449 #ifndef DOXYGEN_SHOULD_SKIP_THIS
    00450 static DBusHandlerResult
    00451 filter_func (DBusConnection * connection,
    00452          DBusMessage * message, void *user_data)
    00453 {
    00454     const char *object_path;
    00455     DBusError error;
    00456     LibHalContext *ctx = (LibHalContext *) user_data;
    00457
    00458     if (ctx->is_shutdown)
    00459         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    00460
    00461     dbus_error_init (&error);
    00462
    00463     object_path = dbus_message_get_path (message);
    00464
    00465     /*printf("*** in filter_func, object_path=%s\n", object_path); */
    00466
    00467     if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager",
    00468                     "DeviceAdded")) {
    00469         char *udi;
    00470         if (dbus_message_get_args (message, &error,
    00471                        DBUS_TYPE_STRING, &udi,
    00472                        DBUS_TYPE_INVALID)) {
    00473             if (ctx->functions->device_added != NULL) {
    00474                 ctx->functions->device_added (ctx, udi);
    00475             }
    00476             dbus_free (udi);
    00477         }
    00478         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    00479     } else
    00480         if (dbus_message_is_signal
    00481         (message, "org.freedesktop.Hal.Manager",
    00482          "DeviceRemoved")) {
    00483         char *udi;
    00484         if (dbus_message_get_args (message, &error,
    00485                        DBUS_TYPE_STRING, &udi,
    00486                        DBUS_TYPE_INVALID)) {
    00487             if (ctx->functions->device_removed != NULL) {
    00488                 ctx->functions->device_removed (ctx, udi);
    00489             }
    00490             dbus_free (udi);
    00491         }
    00492         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    00493     } else
    00494         if (dbus_message_is_signal
    00495         (message, "org.freedesktop.Hal.Manager",
    00496          "NewCapability")) {
    00497         char *udi;
    00498         char *capability;
    00499         if (dbus_message_get_args (message, &error,
    00500                        DBUS_TYPE_STRING, &udi,
    00501                        DBUS_TYPE_STRING, &capability,
    00502                        DBUS_TYPE_INVALID)) {
    00503             if (ctx->functions->device_new_capability != NULL) {
    00504                 ctx->functions->device_new_capability (ctx,
    00505                                        udi,
    00506                                   capability);
    00507             }
    00508             dbus_free (udi);
    00509             dbus_free (capability);
    00510         }
    00511         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    00512     } else
    00513         if (dbus_message_is_signal
    00514         (message, "org.freedesktop.Hal.Device", "Condition")) {
    00515         if (ctx->functions->device_condition != NULL) {
    00516             DBusMessageIter iter;
    00517             char *condition_name;
    00518
    00519             dbus_message_iter_init (message, &iter);
    00520             condition_name =
    00521                 dbus_message_iter_get_string (&iter);
    00522
    00523             ctx->functions->device_condition (ctx,
    00524                               object_path,
    00525                               condition_name,
    00526                               message);
    00527
    00528             dbus_free (condition_name);
    00529         }
    00530         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    00531     } else
    00532         if (dbus_message_is_signal
    00533         (message, "org.freedesktop.Hal.Device",
    00534          "PropertyModified")) {
    00535         if (ctx->functions->device_property_modified != NULL) {
    00536             int i;
    00537             char *key;
    00538             dbus_bool_t removed, added;
    00539             int num_modifications;
    00540             DBusMessageIter iter;
    00541
    00542             dbus_message_iter_init (message, &iter);
    00543             num_modifications =
    00544                 dbus_message_iter_get_int32 (&iter);
    00545             dbus_message_iter_next (&iter);
    00546
    00547
    00548             for (i = 0; i < num_modifications; i++) {
    00549
    00550                 key = dbus_message_iter_get_string (&iter);
    00551                 dbus_message_iter_next (&iter);
    00552                 removed =
    00553                     dbus_message_iter_get_boolean (&iter);
    00554                 dbus_message_iter_next (&iter);
    00555                 added =
    00556                     dbus_message_iter_get_boolean (&iter);
    00557                 dbus_message_iter_next (&iter);
    00558
    00559                 ctx->functions->
    00560                     device_property_modified (ctx,
    00561                                   object_path,
    00562                                   key, removed,
    00563                                   added);
    00564
    00565                 dbus_free (key);
    00566             }
    00567
    00568         }
    00569         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    00570     }
    00571
    00572     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    00573 }
    00574
    00575 static LibHalFunctions hal_null_functions = {
    00576     NULL /*mainloop_integration */ ,
    00577     NULL /*device_added */ ,
    00578     NULL /*device_removed */ ,
    00579     NULL /*device_new_capability */ ,
    00580     NULL /*device_lost_capability */ ,
    00581     NULL /*property_modified */ ,
    00582     NULL /*device_condition */
    00583 };
    00584 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
    00585
    00586 /* for i18n purposes */
    00587 static dbus_bool_t hal_already_initialized_once = FALSE;
    00588
    00607 LibHalContext*
    00608 hal_initialize (const LibHalFunctions * cb_functions,
    00609         dbus_bool_t use_cache)
    00610 {
    00611     DBusError error;
    00612     LibHalContext *ctx;
    00613
    00614     if (!hal_already_initialized_once) {
    00615         bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
    00616         bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
    00617
    00618         hal_already_initialized_once = TRUE;
    00619     }
    00620
    00621     ctx = malloc (sizeof (LibHalContext));
    00622     if (ctx == NULL) {
    00623         fprintf (stderr, "%s %d : Cannot allocated %d bytes!\n",
    00624              __FILE__, __LINE__, sizeof (LibHalContext));
    00625         return NULL;
    00626     }
    00627
    00628     ctx->is_initialized = FALSE;
    00629     ctx->is_shutdown = FALSE;
    00630
    00631     ctx->cache_enabled = use_cache;
    00632
    00633     ctx->functions = cb_functions;
    00634     /* allow caller to pass NULL */
    00635     if (ctx->functions == NULL)
    00636         ctx->functions = &hal_null_functions;
    00637
    00638     /* connect to hald service on the system bus */
    00639     dbus_error_init (&error);
    00640     ctx->connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
    00641     if (ctx->connection == NULL) {
    00642         fprintf (stderr,
    00643              "%s %d : Error connecting to system bus: %s\n",
    00644              __FILE__, __LINE__, error.message);
    00645         dbus_error_free (&error);
    00646         return NULL;
    00647     }
    00648
    00649     if (ctx->functions->main_loop_integration != NULL) {
    00650
    00651         ctx->functions->main_loop_integration (ctx, ctx->connection);
    00652     }
    00653
    00654     if (!dbus_connection_add_filter
    00655         (ctx->connection, filter_func, ctx, NULL)) {
    00656         fprintf (stderr,
    00657              "%s %d : Error creating connection handler\r\n",
    00658              __FILE__, __LINE__);
    00660         return NULL;
    00661     }
    00662
    00663     dbus_bus_add_match (ctx->connection,
    00664                 "type='signal',"
    00665                 "interface='org.freedesktop.Hal.Manager',"
    00666                 "sender='org.freedesktop.Hal',"
    00667                 "path='/org/freedesktop/Hal/Manager'", &error);
    00668     if (dbus_error_is_set (&error)) {
    00669         fprintf (stderr, "%s %d : Error subscribing to signals, "
    00670              "error=%s\r\n",
    00671              __FILE__, __LINE__, error.message);
    00673         return NULL;
    00674     }
    00675
    00676     ctx->is_initialized = TRUE;
    00677     return ctx;
    00678 }
    00679
    00686 int
    00687 hal_shutdown (LibHalContext *ctx)
    00688 {
    00689     DBusError error;
    00690
    00691     if (!ctx->is_initialized)
    00692         return 1;
    00693
    00694     /* unsubscribe the match rule we added in initialize; this is safe even with multiple
    00695      * instances of libhal running - see the dbus docs */
    00696     dbus_error_init (&error);
    00697     dbus_bus_remove_match (ctx->connection,
    00698                    "type='signal',"
    00699                    "interface='org.freedesktop.Hal.Manager',"
    00700                    "sender='org.freedesktop.Hal',"
    00701                    "path='/org/freedesktop/Hal/Manager'", &error);
    00702     if (dbus_error_is_set (&error)) {
    00703         fprintf (stderr, "%s %d : Error removing match rule, error=%s\r\n",
    00704              __FILE__, __LINE__, error.message);
    00705     }
    00706
    00707     /* TODO: remove all other match rules */
    00708
    00709     /* set a flag so we don't propagte callbacks from this context anymore */
    00710     ctx->is_shutdown = TRUE;
    00711
    00712     /* yikes, it's dangerous to unref the connection since it will terminate the process
    00713      * because this connection may be shared so we cannot set the exit_on_disconnect flag
    00714      *
    00715      * so we don't do that right now
    00716      *
    00717      */
    00718     /*dbus_connection_unref (ctx->connection);*/
    00719
    00720     /* we also refuse to free the resources as filter_function may reference these
    00721      *
    00722      * should free async when our connection goes away.
    00723      */
    00724     /* free (ctx); */
    00725     return 0;
    00726 }
    00727
    00737 char **
    00738 hal_get_all_devices (LibHalContext *ctx, int *num_devices)
    00739 {
    00740     int i;
    00741     DBusError error;
    00742     DBusMessage *message;
    00743     DBusMessage *reply;
    00744     DBusMessageIter iter;
    00745     char **device_names;
    00746     char **hal_device_names;
    00747
    00748     *num_devices = 0;
    00749
    00750     message = dbus_message_new_method_call ("org.freedesktop.Hal",
    00751                         "/org/freedesktop/Hal/Manager",
    00752                         "org.freedesktop.Hal.Manager",
    00753                         "GetAllDevices");
    00754     if (message == NULL) {
    00755         fprintf (stderr,
    00756              "%s %d : Couldn't allocate D-BUS message\n",
    00757              __FILE__, __LINE__);
    00758         return NULL;
    00759     }
    00760
    00761     dbus_error_init (&error);
    00762     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    00763                                message, -1,
    00764                                &error);
    00765     if (dbus_error_is_set (&error)) {
    00766         fprintf (stderr, "%s %d : %s raised\n\"%s\"\n\n", __FILE__,
    00767              __LINE__, error.name, error.message);
    00768         dbus_message_unref (message);
    00769         return NULL;
    00770     }
    00771
    00772     if (reply == NULL) {
    00773         dbus_message_unref (message);
    00774         return NULL;
    00775     }
    00776
    00777     /* now analyze reply */
    00778     dbus_message_iter_init (reply, &iter);
    00779     if (!dbus_message_iter_get_string_array (&iter,
    00780                          &device_names,
    00781                          num_devices)) {
    00782         fprintf (stderr, "%s %d : wrong reply from hald\n",
    00783              __FILE__, __LINE__);
    00784         return NULL;
    00785     }
    00786
    00787     dbus_message_unref (reply);
    00788     dbus_message_unref (message);
    00789
    00790     /* Have to convert from dbus string array to hal string array
    00791      * since we can't poke at the dbus string array for the reason
    00792      * that d-bus use their own memory allocation scheme
    00793      */
    00794     hal_device_names = malloc (sizeof (char *) * ((*num_devices) + 1));
    00795     if (hal_device_names == NULL)
    00796         return NULL;
    00799     for (i = 0; i < (*num_devices); i++) {
    00800         hal_device_names[i] = strdup (device_names[i]);
    00801         if (hal_device_names[i] == NULL) {
    00802             fprintf (stderr,
    00803                  "%s %d : error allocating memory\n",
    00804                  __FILE__, __LINE__);
    00806             return NULL;
    00807         }
    00808     }
    00809     hal_device_names[i] = NULL;
    00810
    00811     dbus_free_string_array (device_names);
    00812
    00813     return hal_device_names;
    00814 }
    00815
    00825 int
    00826 hal_device_get_property_type (LibHalContext *ctx,
    00827                   const char *udi, const char *key)
    00828 {
    00829     DBusError error;
    00830     DBusMessage *message;
    00831     DBusMessage *reply;
    00832     DBusMessageIter iter;
    00833     int type;
    00834
    00835     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
    00836                         "org.freedesktop.Hal.Device",
    00837                         "GetPropertyType");
    00838     if (message == NULL) {
    00839         fprintf (stderr,
    00840              "%s %d : Couldn't allocate D-BUS message\n",
    00841              __FILE__, __LINE__);
    00842         return DBUS_TYPE_NIL;
    00843     }
    00844
    00845     dbus_message_iter_init (message, &iter);
    00846     dbus_message_iter_append_string (&iter, key);
    00847     dbus_error_init (&error);
    00848     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    00849                                message, -1,
    00850                                &error);
    00851     if (dbus_error_is_set (&error)) {
    00852         fprintf (stderr, "%s %d : %s raised\n\"%s\"\n\n", __FILE__,
    00853              __LINE__, error.name, error.message);
    00854         dbus_message_unref (message);
    00855         return DBUS_TYPE_NIL;
    00856     }
    00857     if (reply == NULL) {
    00858         dbus_message_unref (message);
    00859         return DBUS_TYPE_NIL;
    00860     }
    00861
    00862     dbus_message_iter_init (reply, &iter);
    00863     type = dbus_message_iter_get_int32 (&iter);
    00864
    00865     dbus_message_unref (message);
    00866     dbus_message_unref (reply);
    00867
    00868     return type;
    00869 }
    00870
    00882 char *
    00883 hal_device_get_property_string (LibHalContext *ctx,
    00884                 const char *udi, const char *key)
    00885 {
    00886     DBusError error;
    00887     DBusMessage *message;
    00888     DBusMessage *reply;
    00889     DBusMessageIter iter;
    00890     char *value;
    00891     char *dbus_str;
    00892
    00893     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
    00894                         "org.freedesktop.Hal.Device",
    00895                         "GetPropertyString");
    00896     if (message == NULL) {
    00897         fprintf (stderr,
    00898              "%s %d : Couldn't allocate D-BUS message\n",
    00899              __FILE__, __LINE__);
    00900         return NULL;
    00901     }
    00902
    00903     dbus_message_iter_init (message, &iter);
    00904     dbus_message_iter_append_string (&iter, key);
    00905     dbus_error_init (&error);
    00906     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    00907                                message, -1,
    00908                                &error);
    00909     if (dbus_error_is_set (&error)) {
    00910         fprintf (stderr, "%s %d : Error sending msg: %s\n",
    00911              __FILE__, __LINE__, error.message);
    00912         dbus_message_unref (message);
    00913         return NULL;
    00914     }
    00915     if (reply == NULL) {
    00916         dbus_message_unref (message);
    00917         return NULL;
    00918     }
    00919
    00920     dbus_message_iter_init (reply, &iter);
    00921
    00922     /* now analyze reply */
    00923     if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_NIL) {
    00924         fprintf (stderr,
    00925              "%s %d : property '%s' for device '%s' does not "
    00926              "exist\n", __FILE__, __LINE__, key, udi);
    00927         dbus_message_unref (message);
    00928         dbus_message_unref (reply);
    00929         return NULL;
    00930     } else if (dbus_message_iter_get_arg_type (&iter) !=
    00931            DBUS_TYPE_STRING) {
    00932         fprintf (stderr,
    00933              "%s %d : property '%s' for device '%s' is not "
    00934              "of type string\n", __FILE__, __LINE__, key, udi);
    00935         dbus_message_unref (message);
    00936         dbus_message_unref (reply);
    00937         return NULL;
    00938     }
    00939
    00940     dbus_str = dbus_message_iter_get_string (&iter);
    00941     value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
    00942     if (value == NULL) {
    00943         fprintf (stderr, "%s %d : error allocating memory\n",
    00944              __FILE__, __LINE__);
    00946         return NULL;
    00947     }
    00948     dbus_free (dbus_str);
    00949
    00950     dbus_message_unref (message);
    00951     dbus_message_unref (reply);
    00952     return value;
    00953 }
    00954
    00962 dbus_int32_t
    00963 hal_device_get_property_int (LibHalContext *ctx,
    00964                  const char *udi, const char *key)
    00965 {
    00966     DBusError error;
    00967     DBusMessage *message;
    00968     DBusMessage *reply;
    00969     DBusMessageIter iter;
    00970     dbus_int32_t value;
    00971
    00972     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
    00973                         "org.freedesktop.Hal.Device",
    00974                         "GetPropertyInteger");
    00975     if (message == NULL) {
    00976         fprintf (stderr,
    00977              "%s %d : Couldn't allocate D-BUS message\n",
    00978              __FILE__, __LINE__);
    00979         return -1;
    00980     }
    00981
    00982     dbus_message_iter_init (message, &iter);
    00983     dbus_message_iter_append_string (&iter, key);
    00984     dbus_error_init (&error);
    00985     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    00986                                message, -1,
    00987                                &error);
    00988     if (dbus_error_is_set (&error)) {
    00989         fprintf (stderr, "%s %d : Error sending msg: %s\n",
    00990              __FILE__, __LINE__, error.message);
    00991         dbus_message_unref (message);
    00992         return -1;
    00993     }
    00994     if (reply == NULL) {
    00995         dbus_message_unref (message);
    00996         return -1;
    00997     }
    00998
    00999     dbus_message_iter_init (reply, &iter);
    01000
    01001     /* now analyze reply */
    01002     if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_NIL) {
    01003         /* property didn't exist */
    01004         fprintf (stderr,
    01005              "%s %d : property '%s' for device '%s' does not "
    01006              "exist\n", __FILE__, __LINE__, key, udi);
    01007         dbus_message_unref (message);
    01008         dbus_message_unref (reply);
    01009         return -1;
    01010     } else if (dbus_message_iter_get_arg_type (&iter) !=
    01011            DBUS_TYPE_INT32) {
    01012         fprintf (stderr,
    01013              "%s %d : property '%s' for device '%s' is not "
    01014              "of type integer\n", __FILE__, __LINE__, key,
    01015              udi);
    01016         dbus_message_unref (message);
    01017         dbus_message_unref (reply);
    01018         return -1;
    01019     }
    01020     value = dbus_message_iter_get_int32 (&iter);
    01021
    01022     dbus_message_unref (message);
    01023     dbus_message_unref (reply);
    01024     return value;
    01025 }
    01026
    01034 dbus_uint64_t
    01035 hal_device_get_property_uint64 (LibHalContext *ctx,
    01036                  const char *udi, const char *key)
    01037 {
    01038     DBusError error;
    01039     DBusMessage *message;
    01040     DBusMessage *reply;
    01041     DBusMessageIter iter;
    01042     dbus_uint64_t value;
    01043
    01044     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
    01045                         "org.freedesktop.Hal.Device",
    01046                         "GetPropertyInteger");
    01047     if (message == NULL) {
    01048         fprintf (stderr,
    01049              "%s %d : Couldn't allocate D-BUS message\n",
    01050              __FILE__, __LINE__);
    01051         return -1;
    01052     }
    01053
    01054     dbus_message_iter_init (message, &iter);
    01055     dbus_message_iter_append_string (&iter, key);
    01056     dbus_error_init (&error);
    01057     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    01058                                message, -1,
    01059                                &error);
    01060     if (dbus_error_is_set (&error)) {
    01061         fprintf (stderr, "%s %d : Error sending msg: %s\n",
    01062              __FILE__, __LINE__, error.message);
    01063         dbus_message_unref (message);
    01064         return -1;
    01065     }
    01066     if (reply == NULL) {
    01067         dbus_message_unref (message);
    01068         return -1;
    01069     }
    01070
    01071     dbus_message_iter_init (reply, &iter);
    01072
    01073     /* now analyze reply */
    01074     if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_NIL) {
    01075         /* property didn't exist */
    01076         fprintf (stderr,
    01077              "%s %d : property '%s' for device '%s' does not "
    01078              "exist\n", __FILE__, __LINE__, key, udi);
    01079         dbus_message_unref (message);
    01080         dbus_message_unref (reply);
    01081         return -1;
    01082     } else if (dbus_message_iter_get_arg_type (&iter) !=
    01083            DBUS_TYPE_UINT64) {
    01084         fprintf (stderr,
    01085              "%s %d : property '%s' for device '%s' is not "
    01086              "of type integer\n", __FILE__, __LINE__, key,
    01087              udi);
    01088         dbus_message_unref (message);
    01089         dbus_message_unref (reply);
    01090         return -1;
    01091     }
    01092     value = dbus_message_iter_get_uint64 (&iter);
    01093
    01094     dbus_message_unref (message);
    01095     dbus_message_unref (reply);
    01096     return value;
    01097 }
    01098
    01106 double
    01107 hal_device_get_property_double (LibHalContext *ctx,
    01108                 const char *udi, const char *key)
    01109 {
    01110     DBusError error;
    01111     DBusMessage *message;
    01112     DBusMessage *reply;
    01113     DBusMessageIter iter;
    01114     double value;
    01115
    01116     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
    01117                         "org.freedesktop.Hal.Device",
    01118                         "GetPropertyDouble");
    01119     if (message == NULL) {
    01120         fprintf (stderr,
    01121              "%s %d : Couldn't allocate D-BUS message\n",
    01122              __FILE__, __LINE__);
    01123         return -1.0f;
    01124     }
    01125
    01126     dbus_message_iter_init (message, &iter);
    01127     dbus_message_iter_append_string (&iter, key);
    01128     dbus_error_init (&error);
    01129     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    01130                                message, -1,
    01131                                &error);
    01132     if (dbus_error_is_set (&error)) {
    01133         fprintf (stderr, "%s %d : Error sending msg: %s\n",
    01134              __FILE__, __LINE__, error.message);
    01135         dbus_message_unref (message);
    01136         return -1.0f;
    01137     }
    01138     if (reply == NULL) {
    01139         dbus_message_unref (message);
    01140         return -1.0f;
    01141     }
    01142
    01143     dbus_message_iter_init (reply, &iter);
    01144
    01145     /* now analyze reply */
    01146     if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_NIL) {
    01147         /* property didn't exist */
    01148         fprintf (stderr,
    01149              "%s %d : property '%s' for device '%s' does not "
    01150              "exist\n", __FILE__, __LINE__, key, udi);
    01151         dbus_message_unref (message);
    01152         dbus_message_unref (reply);
    01153         return -1.0f;
    01154     } else if (dbus_message_iter_get_arg_type (&iter) !=
    01155            DBUS_TYPE_DOUBLE) {
    01156         fprintf (stderr,
    01157              "%s %d : property '%s' for device '%s' is not "
    01158              "of type double\n", __FILE__, __LINE__, key, udi);
    01159         dbus_message_unref (message);
    01160         dbus_message_unref (reply);
    01161         return -1.0f;
    01162     }
    01163     value = dbus_message_iter_get_double (&iter);
    01164
    01165     dbus_message_unref (message);
    01166     dbus_message_unref (reply);
    01167     return (double) value;
    01168 }
    01169
    01177 dbus_bool_t
    01178 hal_device_get_property_bool (LibHalContext *ctx,
    01179                   const char *udi, const char *key)
    01180 {
    01181     DBusError error;
    01182     DBusMessage *message;
    01183     DBusMessage *reply;
    01184     DBusMessageIter iter;
    01185     double value;
    01186
    01187     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
    01188                         "org.freedesktop.Hal.Device",
    01189                         "GetPropertyBoolean");
    01190     if (message == NULL) {
    01191         fprintf (stderr,
    01192              "%s %d : Couldn't allocate D-BUS message\n",
    01193              __FILE__, __LINE__);
    01194         return FALSE;
    01195     }
    01196
    01197     dbus_message_iter_init (message, &iter);
    01198     dbus_message_iter_append_string (&iter, key);
    01199     dbus_error_init (&error);
    01200     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    01201                                message, -1,
    01202                                &error);
    01203     if (dbus_error_is_set (&error)) {
    01204         fprintf (stderr, "%s %d : Error sending msg: %s\n",
    01205              __FILE__, __LINE__, error.message);
    01206         dbus_message_unref (message);
    01207         return FALSE;
    01208     }
    01209     if (reply == NULL) {
    01210         dbus_message_unref (message);
    01211         return FALSE;
    01212     }
    01213
    01214     dbus_message_iter_init (reply, &iter);
    01215
    01216     /* now analyze reply */
    01217     if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_NIL) {
    01218         /* property didn't exist */
    01219         fprintf (stderr,
    01220              "%s %d : property '%s' for device '%s' does not "
    01221              "exist\n", __FILE__, __LINE__, key, udi);
    01222         dbus_message_unref (message);
    01223         dbus_message_unref (reply);
    01224         return FALSE;
    01225     } else if (dbus_message_iter_get_arg_type (&iter) !=
    01226            DBUS_TYPE_BOOLEAN) {
    01227         fprintf (stderr,
    01228              "%s %d : property '%s' for device '%s' is not "
    01229              "of type bool\n", __FILE__, __LINE__, key, udi);
    01230         dbus_message_unref (message);
    01231         dbus_message_unref (reply);
    01232         return FALSE;
    01233     }
    01234     value = dbus_message_iter_get_boolean (&iter);
    01235
    01236     dbus_message_unref (message);
    01237     dbus_message_unref (reply);
    01238     return value;
    01239 }
    01240
    01241
    01242 /* generic helper */
    01243 static int
    01244 hal_device_set_property_helper (LibHalContext *ctx,
    01245                 const char *udi,
    01246                 const char *key,
    01247                 int type,
    01248                 const char *str_value,
    01249                 dbus_int32_t int_value,
    01250                 dbus_uint64_t uint64_value,
    01251                 double double_value,
    01252                 dbus_bool_t bool_value)
    01253 {
    01254     DBusError error;
    01255     DBusMessage *message;
    01256     DBusMessage *reply;
    01257     DBusMessageIter iter;
    01258     char *method_name = NULL;
    01259
    01262     switch (type) {
    01263     case DBUS_TYPE_NIL:
    01264         method_name = "RemoveProperty";
    01265         break;
    01266     case DBUS_TYPE_STRING:
    01267         method_name = "SetPropertyString";
    01268         break;
    01269     case DBUS_TYPE_INT32:
    01270     case DBUS_TYPE_UINT64:
    01271         method_name = "SetPropertyInteger";
    01272         break;
    01273     case DBUS_TYPE_DOUBLE:
    01274         method_name = "SetPropertyDouble";
    01275         break;
    01276     case DBUS_TYPE_BOOLEAN:
    01277         method_name = "SetPropertyBoolean";
    01278         break;
    01279
    01280     default:
    01281         /* cannot happen; is not callable from outside this file */
    01282         break;
    01283     }
    01284
    01285     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
    01286                         "org.freedesktop.Hal.Device",
    01287                         method_name);
    01288     if (message == NULL) {
    01289         fprintf (stderr,
    01290              "%s %d : Couldn't allocate D-BUS message\n",
    01291              __FILE__, __LINE__);
    01292         return FALSE;
    01293     }
    01294
    01295     dbus_message_iter_init (message, &iter);
    01296     dbus_message_iter_append_string (&iter, key);
    01297     switch (type) {
    01298     case DBUS_TYPE_NIL:
    01299         dbus_message_iter_append_nil (&iter);
    01300         break;
    01301     case DBUS_TYPE_STRING:
    01302         dbus_message_iter_append_string (&iter, str_value);
    01303         break;
    01304     case DBUS_TYPE_INT32:
    01305         dbus_message_iter_append_int32 (&iter, int_value);
    01306         break;
    01307     case DBUS_TYPE_UINT64:
    01308         dbus_message_iter_append_uint64 (&iter, uint64_value);
    01309         break;
    01310     case DBUS_TYPE_DOUBLE:
    01311         dbus_message_iter_append_double (&iter, double_value);
    01312         break;
    01313     case DBUS_TYPE_BOOLEAN:
    01314         dbus_message_iter_append_boolean (&iter, bool_value);
    01315         break;
    01316     }
    01317
    01318     dbus_error_init (&error);
    01319     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    01320                                message, -1,
    01321                                &error);
    01322     if (dbus_error_is_set (&error)) {
    01323         fprintf (stderr, "%s %d: %s raised\n\"%s\"\n\n", __FILE__,
    01324              __LINE__, error.name, error.message);
    01325         dbus_message_unref (message);
    01326         return FALSE;
    01327     }
    01328
    01329     if (reply == NULL) {
    01330         dbus_message_unref (message);
    01331         return FALSE;
    01332     }
    01333
    01334     return TRUE;
    01335 }
    01336
    01347 dbus_bool_t
    01348 hal_device_set_property_string (LibHalContext *ctx,
    01349                 const char *udi,
    01350                 const char *key, const char *value)
    01351 {
    01352     return hal_device_set_property_helper (ctx, udi, key,
    01353                            DBUS_TYPE_STRING,
    01354                            value, 0, 0, 0.0f, FALSE);
    01355 }
    01356
    01367 dbus_bool_t
    01368 hal_device_set_property_int (LibHalContext *ctx, const char *udi,
    01369                  const char *key, dbus_int32_t value)
    01370 {
    01371     return hal_device_set_property_helper (ctx, udi, key,
    01372                            DBUS_TYPE_INT32,
    01373                            NULL, value, 0, 0.0f, FALSE);
    01374 }
    01375
    01386 dbus_bool_t
    01387 hal_device_set_property_uint64 (LibHalContext *ctx, const char *udi,
    01388                  const char *key, dbus_uint64_t value)
    01389 {
    01390     return hal_device_set_property_helper (ctx, udi, key,
    01391                            DBUS_TYPE_UINT64,
    01392                            NULL, 0, value, 0.0f, FALSE);
    01393 }
    01394
    01405 dbus_bool_t
    01406 hal_device_set_property_double (LibHalContext *ctx, const char *udi,
    01407                 const char *key, double value)
    01408 {
    01409     return hal_device_set_property_helper (ctx, udi, key,
    01410                            DBUS_TYPE_DOUBLE,
    01411                            NULL, 0, 0, value, FALSE);
    01412 }
    01413
    01424 dbus_bool_t
    01425 hal_device_set_property_bool (LibHalContext *ctx, const char *udi,
    01426                   const char *key, dbus_bool_t value)
    01427 {
    01428     return hal_device_set_property_helper (ctx, udi, key,
    01429                            DBUS_TYPE_BOOLEAN,
    01430                            NULL, 0, 0, 0.0f, value);
    01431 }
    01432
    01433
    01442 dbus_bool_t
    01443 hal_device_remove_property (LibHalContext *ctx,
    01444                 const char *udi, const char *key)
    01445 {
    01446     return hal_device_set_property_helper (ctx, udi, key, DBUS_TYPE_NIL,
    01447                            /* DBUS_TYPE_NIL means remove */
    01448                            NULL, 0, 0, 0.0f, FALSE);
    01449 }
    01450
    01464 dbus_bool_t
    01465 hal_device_lock (LibHalContext *ctx,
    01466          const char *udi,
    01467          const char *reason_to_lock,
    01468          char **reason_why_locked)
    01469 {
    01470     DBusMessage *message;
    01471     DBusMessageIter iter;
    01472     DBusError error;
    01473     DBusMessage *reply;
    01474
    01475     if (reason_why_locked != NULL)
    01476         *reason_why_locked = NULL;
    01477
    01478     message = dbus_message_new_method_call ("org.freedesktop.Hal",
    01479                         udi,
    01480                         "org.freedesktop.Hal.Device",
    01481                         "Lock");
    01482
    01483     if (message == NULL) {
    01484         fprintf (stderr,
    01485              "%s %d : Couldn't allocate D-BUS message\n",
    01486              __FILE__, __LINE__);
    01487         return FALSE;
    01488     }
    01489
    01490     dbus_message_iter_init (message, &iter);
    01491     dbus_message_iter_append_string (&iter, reason_to_lock);
    01492
    01493     dbus_error_init (&error);
    01494     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    01495                                message, -1,
    01496                                &error);
    01497
    01498     if (dbus_error_is_set (&error)) {
    01499         if (strcmp (error.name,
    01500                 "org.freedesktop.Hal.DeviceAlreadyLocked") == 0) {
    01501             if (reason_why_locked != NULL) {
    01502                 *reason_why_locked =
    01503                     dbus_malloc0 (strlen (error.message) + 1);
    01504                 strcpy (*reason_why_locked, error.message);
    01505             }
    01506         } else {
    01507             fprintf (stderr, "%s %d: %s raised\n\"%s\"\n\n",
    01508                  __FILE__, __LINE__, error.name,
    01509                  error.message);
    01510         }
    01511
    01512         dbus_message_unref (message);
    01513         return FALSE;
    01514     }
    01515
    01516     dbus_message_unref (message);
    01517
    01518     if (reply == NULL)
    01519         return FALSE;
    01520
    01521     dbus_message_unref (reply);
    01522
    01523     return TRUE;
    01524 }
    01525
    01534 dbus_bool_t
    01535 hal_device_unlock (LibHalContext *ctx,
    01536            const char *udi)
    01537 {
    01538     DBusMessage *message;
    01539     DBusError error;
    01540     DBusMessage *reply;
    01541
    01542     message = dbus_message_new_method_call ("org.freedesktop.Hal",
    01543                         udi,
    01544                         "org.freedesktop.Hal.Device",
    01545                         "Unlock");
    01546
    01547     if (message == NULL) {
    01548         fprintf (stderr,
    01549              "%s %d : Couldn't allocate D-BUS message\n",
    01550              __FILE__, __LINE__);
    01551         return FALSE;
    01552     }
    01553
    01554     dbus_error_init (&error);
    01555     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    01556                                message, -1,
    01557                                &error);
    01558
    01559     if (dbus_error_is_set (&error)) {
    01560         fprintf (stderr, "%s %d: %s raised\n\"%s\"\n\n", __FILE__,
    01561              __LINE__, error.name, error.message);
    01562         dbus_message_unref (message);
    01563         return FALSE;
    01564     }
    01565
    01566     dbus_message_unref (message);
    01567
    01568     if (reply == NULL)
    01569         return FALSE;
    01570
    01571     dbus_message_unref (reply);
    01572
    01573     return TRUE;
    01574 }
    01575
    01576
    01588 char *
    01589 hal_agent_new_device (LibHalContext *ctx)
    01590 {
    01591     DBusError error;
    01592     DBusMessage *message;
    01593     DBusMessage *reply;
    01594     DBusMessageIter iter;
    01595     char *value;
    01596     char *dbus_str;
    01597
    01598     message = dbus_message_new_method_call ("org.freedesktop.Hal",
    01599                         "/org/freedesktop/Hal/Manager",
    01600                         "org.freedesktop.Hal.AgentManager",
    01601                         "NewDevice");
    01602     if (message == NULL) {
    01603         fprintf (stderr,
    01604              "%s %d : Couldn't allocate D-BUS message\n",
    01605              __FILE__, __LINE__);
    01606         return NULL;
    01607     }
    01608
    01609     dbus_error_init (&error);
    01610     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    01611                                message, -1,
    01612                                &error);
    01613     if (dbus_error_is_set (&error)) {
    01614         fprintf (stderr, "%s %d : Error sending msg: %s\n",
    01615              __FILE__, __LINE__, error.message);
    01616         dbus_message_unref (message);
    01617         return NULL;
    01618     }
    01619     if (reply == NULL) {
    01620         dbus_message_unref (message);
    01621         return NULL;
    01622     }
    01623
    01624     dbus_message_iter_init (reply, &iter);
    01625
    01626     /* now analyze reply */
    01627     if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) {
    01628         fprintf (stderr,
    01629              "%s %d : expected a string in reply to NewDevice\n",
    01630              __FILE__, __LINE__);
    01631         dbus_message_unref (message);
    01632         dbus_message_unref (reply);
    01633         return NULL;
    01634     }
    01635
    01636     dbus_str = dbus_message_iter_get_string (&iter);
    01637     value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
    01638     if (value == NULL) {
    01639         fprintf (stderr, "%s %d : error allocating memory\n",
    01640              __FILE__, __LINE__);
    01642         return NULL;
    01643     }
    01644     dbus_free (dbus_str);
    01645
    01646     dbus_message_unref (message);
    01647     dbus_message_unref (reply);
    01648     return value;
    01649 }
    01650
    01651
    01670 dbus_bool_t
    01671 hal_agent_commit_to_gdl (LibHalContext *ctx,
    01672              const char *temp_udi, const char *udi)
    01673 {
    01674     DBusError error;
    01675     DBusMessage *message;
    01676     DBusMessage *reply;
    01677     DBusMessageIter iter;
    01678
    01679     message = dbus_message_new_method_call ("org.freedesktop.Hal",
    01680                         "/org/freedesktop/Hal/Manager",
    01681                         "org.freedesktop.Hal.AgentManager",
    01682                         "CommitToGdl");
    01683     if (message == NULL) {
    01684         fprintf (stderr,
    01685              "%s %d : Couldn't allocate D-BUS message\n",
    01686              __FILE__, __LINE__);
    01687         return FALSE;
    01688     }
    01689
    01690     dbus_message_iter_init (message, &iter);
    01691     dbus_message_iter_append_string (&iter, temp_udi);
    01692     dbus_message_iter_append_string (&iter, udi);
    01693
    01694     dbus_error_init (&error);
    01695     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    01696                                message, -1,
    01697                                &error);
    01698     if (dbus_error_is_set (&error)) {
    01699         if (dbus_error_has_name
    01700             (&error, "org.freedesktop.Hal.UdiInUse"))
    01701             return FALSE;
    01702         fprintf (stderr, "%s %d : Error sending msg: %s\n",
    01703              __FILE__, __LINE__, error.message);
    01704         dbus_message_unref (message);
    01705         return FALSE;
    01706     }
    01707     if (reply == NULL) {
    01708         dbus_message_unref (message);
    01709         return FALSE;
    01710     }
    01711
    01712     dbus_message_unref (message);
    01713     dbus_message_unref (reply);
    01714     return TRUE;
    01715 }
    01716
    01728 dbus_bool_t
    01729 hal_agent_remove_device (LibHalContext *ctx, const char *udi)
    01730 {
    01731     DBusError error;
    01732     DBusMessage *message;
    01733     DBusMessage *reply;
    01734     DBusMessageIter iter;
    01735
    01736     message = dbus_message_new_method_call ("org.freedesktop.Hal",
    01737                         "/org/freedesktop/Hal/Manager",
    01738                         "org.freedesktop.Hal.AgentManager",
    01739                         "Remove");
    01740     if (message == NULL) {
    01741         fprintf (stderr,
    01742              "%s %d : Couldn't allocate D-BUS message\n",
    01743              __FILE__, __LINE__);
    01744         return FALSE;
    01745     }
    01746
    01747     dbus_message_iter_init (message, &iter);
    01748     dbus_message_iter_append_string (&iter, udi);
    01749
    01750     dbus_error_init (&error);
    01751     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    01752                                message, -1,
    01753                                &error);
    01754     if (dbus_error_is_set (&error)) {
    01755         fprintf (stderr, "%s %d : Error sending msg: %s\n",
    01756              __FILE__, __LINE__, error.message);
    01757         dbus_message_unref (message);
    01758         return FALSE;
    01759     }
    01760     if (reply == NULL) {
    01761         dbus_message_unref (message);
    01762         return FALSE;
    01763     }
    01764
    01765     dbus_message_unref (message);
    01766     dbus_message_unref (reply);
    01767     return TRUE;
    01768 }
    01769
    01776 dbus_bool_t
    01777 hal_device_exists (LibHalContext *ctx, const char *udi)
    01778 {
    01779     DBusError error;
    01780     DBusMessage *message;
    01781     DBusMessage *reply;
    01782     DBusMessageIter iter;
    01783     dbus_bool_t value;
    01784
    01785     message = dbus_message_new_method_call ("org.freedesktop.Hal",
    01786                         "/org/freedesktop/Hal/Manager",
    01787                         "org.freedesktop.Hal.Manager",
    01788                         "DeviceExists");
    01789     if (message == NULL) {
    01790         fprintf (stderr,
    01791              "%s %d : Couldn't allocate D-BUS message\n",
    01792              __FILE__, __LINE__);
    01793         return FALSE;
    01794     }
    01795
    01796     dbus_message_iter_init (message, &iter);
    01797     dbus_message_iter_append_string (&iter, udi);
    01798
    01799     dbus_error_init (&error);
    01800     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    01801                                message, -1,
    01802                                &error);
    01803     if (dbus_error_is_set (&error)) {
    01804         fprintf (stderr, "%s %d : Error sending msg: %s\n",
    01805              __FILE__, __LINE__, error.message);
    01806         dbus_message_unref (message);
    01807         return FALSE;
    01808     }
    01809     if (reply == NULL) {
    01810         dbus_message_unref (message);
    01811         return FALSE;
    01812     }
    01813
    01814     dbus_message_iter_init (reply, &iter);
    01815
    01816     /* now analyze reply */
    01817     if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_BOOLEAN) {
    01818         fprintf (stderr,
    01819              "%s %d : expected a bool in reply to DeviceExists\n",
    01820              __FILE__, __LINE__);
    01821         dbus_message_unref (message);
    01822         dbus_message_unref (reply);
    01823         return FALSE;
    01824     }
    01825
    01826     value = dbus_message_iter_get_boolean (&iter);
    01827
    01828     dbus_message_unref (message);
    01829     dbus_message_unref (reply);
    01830     return value;
    01831 }
    01832
    01840 dbus_bool_t
    01841 hal_device_property_exists (LibHalContext *ctx,
    01842                 const char *udi, const char *key)
    01843 {
    01844     DBusError error;
    01845     DBusMessage *message;
    01846     DBusMessage *reply;
    01847     DBusMessageIter iter;
    01848     dbus_bool_t value;
    01849
    01850     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
    01851                         "org.freedesktop.Hal.Device",
    01852                         "PropertyExists");
    01853     if (message == NULL) {
    01854         fprintf (stderr,
    01855              "%s %d : Couldn't allocate D-BUS message\n",
    01856              __FILE__, __LINE__);
    01857         return FALSE;
    01858     }
    01859
    01860     dbus_message_iter_init (message, &iter);
    01861     dbus_message_iter_append_string (&iter, key);
    01862
    01863     dbus_error_init (&error);
    01864     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    01865                                message, -1,
    01866                                &error);
    01867     if (dbus_error_is_set (&error)) {
    01868         fprintf (stderr, "%s %d : Error sending msg: %s\n",
    01869              __FILE__, __LINE__, error.message);
    01870         dbus_message_unref (message);
    01871         return FALSE;
    01872     }
    01873     if (reply == NULL) {
    01874         dbus_message_unref (message);
    01875         return FALSE;
    01876     }
    01877
    01878     dbus_message_iter_init (reply, &iter);
    01879
    01880     /* now analyse reply */
    01881     if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_BOOLEAN) {
    01882         fprintf (stderr, "%s %d : expected a bool in reply to "
    01883              "PropertyExists\n", __FILE__, __LINE__);
    01884         dbus_message_unref (message);
    01885         dbus_message_unref (reply);
    01886         return FALSE;
    01887     }
    01888
    01889     value = dbus_message_iter_get_boolean (&iter);
    01890
    01891     dbus_message_unref (message);
    01892     dbus_message_unref (reply);
    01893     return value;
    01894 }
    01895
    01903 dbus_bool_t
    01904 hal_agent_merge_properties (LibHalContext *ctx,
    01905                 const char *target_udi, const char *source_udi)
    01906 {
    01907     DBusError error;
    01908     DBusMessage *message;
    01909     DBusMessage *reply;
    01910     DBusMessageIter iter;
    01911
    01912     message = dbus_message_new_method_call ("org.freedesktop.Hal",
    01913                         "/org/freedesktop/Hal/Manager",
    01914                         "org.freedesktop.Hal.AgentManager",
    01915                         "MergeProperties");
    01916     if (message == NULL) {
    01917         fprintf (stderr,
    01918              "%s %d : Couldn't allocate D-BUS message\n",
    01919              __FILE__, __LINE__);
    01920         return FALSE;
    01921     }
    01922
    01923     dbus_message_iter_init (message, &iter);
    01924     dbus_message_iter_append_string (&iter, target_udi);
    01925     dbus_message_iter_append_string (&iter, source_udi);
    01926
    01927     dbus_error_init (&error);
    01928     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    01929                                message, -1,
    01930                                &error);
    01931     if (dbus_error_is_set (&error)) {
    01932         if (dbus_error_has_name
    01933             (&error, "org.freedesktop.Hal.NoSuchDevice"))
    01934             return FALSE;
    01935         fprintf (stderr, "%s %d : Error sending msg: %s\n",
    01936              __FILE__, __LINE__, error.message);
    01937         dbus_message_unref (message);
    01938         return FALSE;
    01939     }
    01940     if (reply == NULL) {
    01941         dbus_message_unref (message);
    01942         return FALSE;
    01943     }
    01944
    01945     dbus_message_unref (message);
    01946     dbus_message_unref (reply);
    01947     return TRUE;
    01948 }
    01949
    01969 dbus_bool_t
    01970 hal_agent_device_matches (LibHalContext *ctx,
    01971               const char *udi1, const char *udi2,
    01972               const char *property_namespace)
    01973 {
    01974     DBusError error;
    01975     DBusMessage *message;
    01976     DBusMessage *reply;
    01977     DBusMessageIter iter;
    01978     dbus_bool_t value;
    01979
    01980     message = dbus_message_new_method_call ("org.freedesktop.Hal",
    01981                         "/org/freedesktop/Hal/Manager",
    01982                         "org.freedesktop.Hal.AgentManager",
    01983                         "DeviceMatches");
    01984     if (message == NULL) {
    01985         fprintf (stderr,
    01986              "%s %d : Couldn't allocate D-BUS message\n",
    01987              __FILE__, __LINE__);
    01988         return FALSE;
    01989     }
    01990
    01991     dbus_message_iter_init (message, &iter);
    01992     dbus_message_iter_append_string (&iter, udi1);
    01993     dbus_message_iter_append_string (&iter, udi2);
    01994     dbus_message_iter_append_string (&iter, property_namespace);
    01995
    01996     dbus_error_init (&error);
    01997     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    01998                                message, -1,
    01999                                &error);
    02000     if (dbus_error_is_set (&error)) {
    02001         fprintf (stderr, "%s %d : Error sending msg: %s\n",
    02002              __FILE__, __LINE__, error.message);
    02003         dbus_message_unref (message);
    02004         return FALSE;
    02005     }
    02006     if (reply == NULL) {
    02007         dbus_message_unref (message);
    02008         return FALSE;
    02009     }
    02010     /* now analyse reply */
    02011     dbus_message_iter_init (reply, &iter);
    02012     if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_BOOLEAN) {
    02013         fprintf (stderr,
    02014              "%s %d : expected a bool in reply to DeviceMatches\n",
    02015              __FILE__, __LINE__);
    02016         dbus_message_unref (message);
    02017         dbus_message_unref (reply);
    02018         return FALSE;
    02019     }
    02020
    02021     value = dbus_message_iter_get_boolean (&iter);
    02022
    02023     dbus_message_unref (message);
    02024     dbus_message_unref (reply);
    02025     return value;
    02026 }
    02027
    02033 void
    02034 hal_device_print (LibHalContext *ctx, const char *udi)
    02035 {
    02036     int type;
    02037     char *key;
    02038     LibHalPropertySet *pset;
    02039     LibHalPropertySetIterator i;
    02040
    02041     printf ("device_id = %s\n", udi);
    02042
    02043     pset = hal_device_get_all_properties (ctx, udi);
    02044
    02045     for (hal_psi_init (&i, pset); hal_psi_has_more (&i);
    02046          hal_psi_next (&i)) {
    02047         type = hal_psi_get_type (&i);
    02048         key = hal_psi_get_key (&i);
    02049         switch (type) {
    02050         case DBUS_TYPE_STRING:
    02051             printf ("    %s = %s (string)\n", key,
    02052                 hal_psi_get_string (&i));
    02053             break;
    02054         case DBUS_TYPE_INT32:
    02055             printf ("    %s = %d = 0x%x (int)\n", key,
    02056                 hal_psi_get_int (&i),
    02057                 hal_psi_get_int (&i));
    02058             break;
    02059         case DBUS_TYPE_UINT64:
    02060             printf ("    %s = %lld = 0x%llx (uint64)\n", key,
    02061                 hal_psi_get_uint64 (&i),
    02062                 hal_psi_get_uint64 (&i));
    02063             break;
    02064         case DBUS_TYPE_BOOLEAN:
    02065             printf ("    %s = %s (bool)\n", key,
    02066                 (hal_psi_get_bool (&i) ? "true" :
    02067                  "false"));
    02068             break;
    02069         case DBUS_TYPE_DOUBLE:
    02070             printf ("    %s = %g (double)\n", key,
    02071                 hal_psi_get_double (&i));
    02072             break;
    02073         default:
    02074             printf ("    *** unknown type for key %s\n", key);
    02075             break;
    02076         }
    02077     }
    02078     hal_free_property_set (pset);
    02079 }
    02080
    02091 char **
    02092 hal_manager_find_device_string_match (LibHalContext *ctx,
    02093                       const char *key,
    02094                       const char *value, int *num_devices)
    02095 {
    02096     int i;
    02097     DBusError error;
    02098     DBusMessage *message;
    02099     DBusMessage *reply;
    02100     DBusMessageIter iter;
    02101     char **device_names;
    02102     char **hal_device_names;
    02103
    02104     message = dbus_message_new_method_call ("org.freedesktop.Hal",
    02105                         "/org/freedesktop/Hal/Manager",
    02106                         "org.freedesktop.Hal.Manager",
    02107                         "FindDeviceStringMatch");
    02108     if (message == NULL) {
    02109         fprintf (stderr,
    02110              "%s %d : Couldn't allocate D-BUS message\n",
    02111              __FILE__, __LINE__);
    02112         return NULL;
    02113     }
    02114
    02115     dbus_message_iter_init (message, &iter);
    02116     dbus_message_iter_append_string (&iter, key);
    02117     dbus_message_iter_append_string (&iter, value);
    02118
    02119     dbus_error_init (&error);
    02120     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    02121                                message, -1,
    02122                                &error);
    02123     if (dbus_error_is_set (&error)) {
    02124         fprintf (stderr, "%s %d : Error sending msg: %s\n",
    02125              __FILE__, __LINE__, error.message);
    02126         dbus_message_unref (message);
    02127         return NULL;
    02128     }
    02129     if (reply == NULL) {
    02130         dbus_message_unref (message);
    02131         return NULL;
    02132     }
    02133     /* now analyse reply */
    02134     dbus_message_iter_init (reply, &iter);
    02135     if (!dbus_message_iter_get_string_array (&iter,
    02136                          &device_names,
    02137                          num_devices)) {
    02138         fprintf (stderr, "%s %d : wrong reply from hald\n",
    02139              __FILE__, __LINE__);
    02140         return NULL;
    02141     }
    02142
    02143     dbus_message_unref (message);
    02144     dbus_message_unref (reply);
    02145
    02146     /* Have to convert from dbus string array to hal string array
    02147      * since we can't poke at the dbus string array for the reason
    02148      * that d-bus use their own memory allocation scheme
    02149      */
    02150     hal_device_names = malloc (sizeof (char *) * ((*num_devices) + 1));
    02151     if (hal_device_names == NULL)
    02152         return NULL;
    02155     for (i = 0; i < (*num_devices); i++) {
    02156         hal_device_names[i] = strdup (device_names[i]);
    02157         if (hal_device_names[i] == NULL)
    02158             return NULL;
    02160     }
    02161     hal_device_names[i] = NULL;
    02162
    02163     dbus_free_string_array (device_names);
    02164
    02165     return hal_device_names;
    02166 }
    02167
    02168
    02177 dbus_bool_t
    02178 hal_device_add_capability (LibHalContext *ctx,
    02179                const char *udi, const char *capability)
    02180 {
    02181     DBusError error;
    02182     DBusMessage *message;
    02183     DBusMessage *reply;
    02184     DBusMessageIter iter;
    02185
    02186     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
    02187                         "org.freedesktop.Hal.Device",
    02188                         "AddCapability");
    02189     if (message == NULL) {
    02190         fprintf (stderr,
    02191              "%s %d : Couldn't allocate D-BUS message\n",
    02192              __FILE__, __LINE__);
    02193         return FALSE;
    02194     }
    02195
    02196     dbus_message_iter_init (message, &iter);
    02197     dbus_message_iter_append_string (&iter, capability);
    02198
    02199     dbus_error_init (&error);
    02200     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    02201                                message, -1,
    02202                                &error);
    02203     if (dbus_error_is_set (&error)) {
    02204         fprintf (stderr, "%s %d: %s raised\n\"%s\"\n\n", __FILE__,
    02205              __LINE__, error.name, error.message);
    02206         dbus_message_unref (message);
    02207         return FALSE;
    02208     }
    02209
    02210     if (reply == NULL) {
    02211         dbus_message_unref (message);
    02212         return FALSE;
    02213     }
    02214
    02215     dbus_message_unref (reply);
    02216     dbus_message_unref (message);
    02217     return TRUE;
    02218 }
    02219
    02229 dbus_bool_t
    02230 hal_device_query_capability (LibHalContext *ctx,
    02231                  const char *udi, const char *capability)
    02232 {
    02233     dbus_bool_t ret;
    02234     char *caps;
    02235
    02236     caps = hal_device_get_property_string (ctx, udi, "info.capabilities");
    02237     ret = (caps != NULL && strstr (caps, capability) != NULL);
    02238     hal_free_string (caps);
    02239     return ret;
    02240 }
    02241
    02250 char **
    02251 hal_find_device_by_capability (LibHalContext *ctx,
    02252                    const char *capability, int *num_devices)
    02253 {
    02254     int i;
    02255     DBusError error;
    02256     DBusMessage *message;
    02257     DBusMessage *reply;
    02258     DBusMessageIter iter;
    02259     char **device_names;
    02260     char **hal_device_names;
    02261
    02262     message = dbus_message_new_method_call ("org.freedesktop.Hal",
    02263                         "/org/freedesktop/Hal/Manager",
    02264                         "org.freedesktop.Hal.Manager",
    02265                         "FindDeviceByCapability");
    02266     if (message == NULL) {
    02267         fprintf (stderr,
    02268              "%s %d : Couldn't allocate D-BUS message\n",
    02269              __FILE__, __LINE__);
    02270         return NULL;
    02271     }
    02272
    02273     dbus_message_iter_init (message, &iter);
    02274     dbus_message_iter_append_string (&iter, capability);
    02275
    02276     dbus_error_init (&error);
    02277     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
    02278                                message, -1,
    02279                                &error);
    02280     if (dbus_error_is_set (&error)) {
    02281         fprintf (stderr, "%s %d : Error sending msg: %s\n",
    02282              __FILE__, __LINE__, error.message);
    02283         dbus_message_unref (message);
    02284         return NULL;
    02285     }
    02286     if (reply == NULL) {
    02287         dbus_message_unref (message);
    02288         return NULL;
    02289     }
    02290     /* now analyse reply */
    02291     dbus_message_iter_init (reply, &iter);
    02292     if (!dbus_message_iter_get_string_array (&iter,
    02293                          &device_names,
    02294                          num_devices)) {
    02295         fprintf (stderr, "%s %d : wrong reply from hald\n",
    02296              __FILE__, __LINE__);
    02297         return NULL;
    02298     }
    02299
    02300     dbus_message_unref (message);
    02301     dbus_message_unref (reply);
    02302
    02303     /* Have to convert from dbus string array to hal string array
    02304      * since we can't poke at the dbus string array for the reason
    02305      * that d-bus use their own memory allocation scheme
    02306      */
    02307     hal_device_names = malloc (sizeof (char *) * ((*num_devices) + 1));
    02308     if (hal_device_names == NULL)
    02309         return NULL;
    02312     for (i = 0; i < (*num_devices); i++) {
    02313         hal_device_names[i] = strdup (device_names[i]);
    02314         if (hal_device_names[i] == NULL)
    02315             return NULL;
    02317     }
    02318     hal_device_names[i] = NULL;
    02319
    02320     dbus_free_string_array (device_names);
    02321
    02322     return hal_device_names;
    02323 }
    02324
    02332 int
    02333 hal_device_property_watch_all (LibHalContext *ctx)
    02334 {
    02335     DBusError error;
    02336
    02337     dbus_error_init (&error);
    02338
    02339     dbus_bus_add_match (ctx->connection,
    02340                 "type='signal',"
    02341                 "interface='org.freedesktop.Hal.Device',"
    02342                 "sender='org.freedesktop.Hal'", &error);
    02343     if (dbus_error_is_set (&error)) {
    02344         fprintf (stderr, "%s %d : Error subscribing to signals, "
    02345              "error=%s\r\n",
    02346              __FILE__, __LINE__, error.message);
    02347         return 1;
    02348     }
    02349     return 0;
    02350 }
    02351
    02352
    02364 int
    02365 hal_device_add_property_watch (LibHalContext *ctx, const char *udi)
    02366 {
    02367     char buf[512];
    02368     DBusError error;
    02369
    02370     dbus_error_init (&error);
    02371
    02372     snprintf (buf, 512,
    02373           "type='signal',"
    02374           "interface='org.freedesktop.Hal.Device',"
    02375           "sender='org.freedesktop.Hal'," "path=%s", udi);
    02376
    02377     dbus_bus_add_match (ctx->connection, buf, &error);
    02378     if (dbus_error_is_set (&error)) {
    02379         fprintf (stderr, "%s %d : Error subscribing to signals, "
    02380              "error=%s\r\n",
    02381              __FILE__, __LINE__, error.message);
    02382         return 1;
    02383     }
    02384     return 0;
    02385 }
    02386
    02387
    02395 int
    02396 hal_device_remove_property_watch (LibHalContext *ctx, const char *udi)
    02397 {
    02398     char buf[512];
    02399     DBusError error;
    02400
    02401     dbus_error_init (&error);
    02402
    02403     snprintf (buf, 512,
    02404           "type='signal',"
    02405           "interface='org.freedesktop.Hal.Device',"
    02406           "sender='org.freedesktop.Hal'," "path=%s", udi);
    02407
    02408     dbus_bus_remove_match (ctx->connection, buf, &error);
    02409     if (dbus_error_is_set (&error)) {
    02410         fprintf (stderr, "%s %d : Error unsubscribing to signals, "
    02411              "error=%s\r\n",
    02412              __FILE__, __LINE__, error.message);
    02413         return 1;
    02414     }
    02415     return 0;
    02416 }
    02417
    02418