libhal.c

00001 /***************************************************************************
00002  * CVSID: $Id: libhal.c,v 1.56 2005/11/02 15:38:14 david Exp $
00003  *
00004  * libhal.c : HAL daemon C convenience library
00005  *
00006  * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
00007  * Copyright (C) 2005 Danny Kukawka, <danny.kukawka@web.de>
00008  *
00009  * Licensed under the Academic Free License version 2.1
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024  *
00025  **************************************************************************/
00026 
00027 #ifdef HAVE_CONFIG_H
00028 #  include <config.h>
00029 #endif
00030 
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <dbus/dbus.h>
00035 
00036 #include "libhal.h"
00037 
00038 #ifdef ENABLE_NLS
00039 # include <libintl.h>
00040 # define _(String) dgettext (GETTEXT_PACKAGE, String)
00041 # ifdef gettext_noop
00042 #   define N_(String) gettext_noop (String)
00043 # else
00044 #   define N_(String) (String)
00045 # endif
00046 #else
00047 /* Stubs that do something close enough.  */
00048 # define textdomain(String) (String)
00049 # define gettext(String) (String)
00050 # define dgettext(Domain,Message) (Message)
00051 # define dcgettext(Domain,Message,Type) (Message)
00052 # define bindtextdomain(Domain,Directory) (Domain)
00053 # define _(String)
00054 # define N_(String) (String)
00055 #endif
00056 
00057 static char **libhal_get_string_array_from_iter (DBusMessageIter *iter, int *num_elements);
00058 
00059 static dbus_bool_t libhal_property_fill_value_from_variant (LibHalProperty *p, DBusMessageIter *var_iter);
00060 
00061 
00062 
00075 void
00076 libhal_free_string_array (char **str_array)
00077 {
00078     if (str_array != NULL) {
00079         int i;
00080 
00081         for (i = 0; str_array[i] != NULL; i++) {
00082             free (str_array[i]);
00083         }
00084         free (str_array);
00085     }
00086 }
00087 
00088 
00095 static char **
00096 libhal_get_string_array_from_iter (DBusMessageIter *iter, int *num_elements)
00097 {
00098     int count;
00099     char **buffer;
00100 
00101     count = 0;
00102     buffer = (char **)malloc (sizeof (char *) * 8);
00103 
00104     if (buffer == NULL)
00105         goto oom;
00106 
00107     buffer[0] = NULL;
00108     while (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING) {
00109         const char *value;
00110         char *str;
00111         
00112         if ((count % 8) == 0 && count != 0) {
00113             buffer = realloc (buffer, sizeof (char *) * (count + 8));
00114             if (buffer == NULL)
00115                 goto oom;
00116         }
00117         
00118         dbus_message_iter_get_basic (iter, &value);
00119         str = strdup (value);
00120         if (str == NULL)
00121             goto oom;
00122 
00123         buffer[count] = str;
00124 
00125         dbus_message_iter_next(iter);
00126         count++;
00127     }
00128 
00129     if ((count % 8) == 0) {
00130         buffer = realloc (buffer, sizeof (char *) * (count + 1));
00131         if (buffer == NULL)
00132             goto oom;
00133     }
00134 
00135     buffer[count] = NULL;
00136     if (num_elements != NULL)
00137         *num_elements = count;
00138     return buffer;
00139 
00140 oom:
00141     fprintf (stderr, "%s %d : error allocating memory\n", __FILE__, __LINE__);
00142     return NULL;
00143 
00144 }
00145 
00150 void
00151 libhal_free_string (char *str)
00152 {
00154     free (str);
00155 }
00156 
00157 
00159 struct LibHalPropertySet_s {
00160     unsigned int num_properties; 
00161     LibHalProperty *properties_head;
00164 };
00165 
00167 struct LibHalProperty_s {
00168     int type;            
00169     char *key;           
00172     union {
00173         char *str_value;     
00174         dbus_int32_t int_value;
00176         dbus_uint64_t uint64_value;
00178         double double_value; 
00179         dbus_bool_t bool_value;
00182         char **strlist_value; 
00183     };
00184 
00185     LibHalProperty *next;        
00187 };
00188 
00190 struct LibHalContext_s {
00191     DBusConnection *connection;           
00192     dbus_bool_t is_initialized;           
00193     dbus_bool_t is_shutdown;              
00194     dbus_bool_t cache_enabled;            
00195     dbus_bool_t is_direct;                
00198     LibHalDeviceAdded device_added;
00199 
00201     LibHalDeviceRemoved device_removed;
00202 
00204     LibHalDeviceNewCapability device_new_capability;
00205 
00207     LibHalDeviceLostCapability device_lost_capability;
00208 
00210     LibHalDevicePropertyModified device_property_modified;
00211 
00213     LibHalDeviceCondition device_condition;
00214 
00215     void *user_data;                      
00216 };
00217 
00225 dbus_bool_t
00226 libhal_ctx_set_user_data(LibHalContext *ctx, void *user_data)
00227 {
00228     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
00229     ctx->user_data = user_data;
00230     return TRUE;
00231 }
00232 
00239 void*
00240 libhal_ctx_get_user_data(LibHalContext *ctx)
00241 {
00242     LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
00243     return ctx->user_data;
00244 }
00245 
00246 
00252 static dbus_bool_t
00253 libhal_property_fill_value_from_variant (LibHalProperty *p, DBusMessageIter *var_iter)
00254 {
00255     DBusMessageIter iter_array;
00256     switch (p->type) {
00257     case DBUS_TYPE_ARRAY:
00258         if (dbus_message_iter_get_element_type (var_iter) != DBUS_TYPE_STRING)
00259             return FALSE;
00260 
00261         dbus_message_iter_recurse (var_iter, &iter_array);
00262         p->strlist_value = libhal_get_string_array_from_iter (&iter_array, NULL);
00263 
00264         p->type = LIBHAL_PROPERTY_TYPE_STRLIST; 
00265 
00266         break;
00267     case DBUS_TYPE_STRING:
00268     {
00269         const char *v;
00270 
00271         dbus_message_iter_get_basic (var_iter, &v);
00272 
00273         p->str_value = strdup (v);
00274         if (p->str_value == NULL) 
00275             return FALSE;
00276         p->type = LIBHAL_PROPERTY_TYPE_STRING; 
00277 
00278         break;
00279     }
00280     case DBUS_TYPE_INT32:
00281     {
00282         dbus_int32_t v;
00283         
00284         dbus_message_iter_get_basic (var_iter, &v);
00285         
00286         p->int_value = v;
00287         p->type = LIBHAL_PROPERTY_TYPE_INT32; 
00288 
00289         break;
00290     }
00291     case DBUS_TYPE_UINT64:
00292     {
00293         dbus_uint64_t v;
00294         
00295         dbus_message_iter_get_basic (var_iter, &v);
00296 
00297         p->uint64_value = v;
00298         p->type = LIBHAL_PROPERTY_TYPE_UINT64; 
00299         
00300         break;
00301     }
00302     case DBUS_TYPE_DOUBLE:
00303     {
00304         double v;
00305 
00306         dbus_message_iter_get_basic (var_iter, &v);
00307 
00308         p->double_value = v;
00309         p->type = LIBHAL_PROPERTY_TYPE_DOUBLE; 
00310 
00311         break;
00312     }
00313     case DBUS_TYPE_BOOLEAN:
00314     {
00315         double v;
00316 
00317         dbus_message_iter_get_basic (var_iter, &v);
00318 
00319         p->double_value = v;
00320         p->type = LIBHAL_PROPERTY_TYPE_BOOLEAN; 
00321 
00322         break;
00323     }
00324     default:
00326         break;
00327     }
00328 
00329     return TRUE;
00330 }
00331 
00341 LibHalPropertySet *
00342 libhal_device_get_all_properties (LibHalContext *ctx, const char *udi, DBusError *error)
00343 {   
00344     DBusMessage *message;
00345     DBusMessage *reply;
00346     DBusMessageIter reply_iter;
00347     DBusMessageIter dict_iter;
00348     LibHalPropertySet *result;
00349     LibHalProperty *p_last;
00350     DBusError _error;
00351 
00352     LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
00353     
00354     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
00355                         "org.freedesktop.Hal.Device",
00356                         "GetAllProperties");
00357 
00358     if (message == NULL) {
00359         fprintf (stderr,
00360              "%s %d : Couldn't allocate D-BUS message\n",
00361              __FILE__, __LINE__);
00362         return NULL;
00363     }
00364 
00365     dbus_error_init (&_error);
00366     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
00367                                message, -1,
00368                                &_error);
00369 
00370     dbus_move_error (&_error, error);
00371     if (error != NULL && dbus_error_is_set (error)) {
00372         fprintf (stderr,
00373              "%s %d : %s\n",
00374              __FILE__, __LINE__, error->message);
00375 
00376         dbus_message_unref (message);
00377         return NULL;
00378     }
00379 
00380     if (reply == NULL) {
00381         dbus_message_unref (message);
00382         return NULL;
00383     }
00384 
00385     dbus_message_iter_init (reply, &reply_iter);
00386 
00387     result = malloc (sizeof (LibHalPropertySet));
00388     if (result == NULL) 
00389         goto oom;
00390 /*
00391     result->properties = malloc(sizeof(LibHalProperty)*result->num_properties);
00392     if( result->properties==NULL )
00393     {
00395     return NULL;
00396     }
00397 */
00398 
00399     result->properties_head = NULL;
00400     result->num_properties = 0;
00401 
00402     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY  &&
00403         dbus_message_iter_get_element_type (&reply_iter) != DBUS_TYPE_DICT_ENTRY) {
00404         fprintf (stderr, "%s %d : error, expecting an array of dict entries\n",
00405              __FILE__, __LINE__);
00406         dbus_message_unref (message);
00407         dbus_message_unref (reply);
00408         return NULL;
00409     }
00410 
00411     dbus_message_iter_recurse (&reply_iter, &dict_iter);
00412 
00413     p_last = NULL;
00414 
00415     while (dbus_message_iter_get_arg_type (&dict_iter) == DBUS_TYPE_DICT_ENTRY)
00416     {
00417         DBusMessageIter dict_entry_iter, var_iter;
00418         const char *key;
00419         LibHalProperty *p;
00420 
00421         dbus_message_iter_recurse (&dict_iter, &dict_entry_iter);
00422 
00423         dbus_message_iter_get_basic (&dict_entry_iter, &key);
00424 
00425         p = malloc (sizeof (LibHalProperty));
00426         if (p == NULL)
00427             goto oom;
00428 
00429         p->next = NULL;
00430 
00431         if (result->num_properties == 0)
00432             result->properties_head = p;
00433 
00434         if (p_last != NULL)
00435             p_last->next = p;
00436 
00437         p_last = p;
00438 
00439         p->key = strdup (key);
00440         if (p->key == NULL)
00441             goto oom;
00442 
00443         dbus_message_iter_next (&dict_entry_iter);
00444 
00445         dbus_message_iter_recurse (&dict_entry_iter, &var_iter);
00446 
00447 
00448         p->type = dbus_message_iter_get_arg_type (&var_iter);
00449     
00450         result->num_properties++;
00451 
00452         if(!libhal_property_fill_value_from_variant (p, &var_iter))
00453             goto oom;
00454 
00455         dbus_message_iter_next (&dict_iter);
00456     }
00457 
00458     dbus_message_unref (message);
00459     dbus_message_unref (reply);
00460 
00461     return result;
00462 
00463 oom:
00464     fprintf (stderr,
00465         "%s %d : error allocating memory\n",
00466          __FILE__, __LINE__);
00468     return NULL;
00469 }
00470 
00475 void
00476 libhal_free_property_set (LibHalPropertySet * set)
00477 {
00478     LibHalProperty *p;
00479     LibHalProperty *q;
00480 
00481     if (set == NULL)
00482         return;
00483 
00484     for (p = set->properties_head; p != NULL; p = q) {
00485         free (p->key);
00486         if (p->type == DBUS_TYPE_STRING)
00487             free (p->str_value);
00488         if (p->type == LIBHAL_PROPERTY_TYPE_STRLIST)
00489             libhal_free_string_array (p->strlist_value);
00490         q = p->next;
00491         free (p);
00492     }
00493     free (set);
00494 }
00495 
00501 unsigned int 
00502 libhal_property_set_get_num_elems (LibHalPropertySet *set)
00503 {
00504     unsigned int num_elems;
00505     LibHalProperty *p;
00506 
00507     if (set == NULL)
00508         return 0;
00509     
00510     num_elems = 0;
00511     for (p = set->properties_head; p != NULL; p = p->next)
00512         num_elems++;
00513 
00514     return num_elems;
00515 }
00516 
00517 
00523 void
00524 libhal_psi_init (LibHalPropertySetIterator * iter, LibHalPropertySet * set)
00525 {
00526     if (set == NULL)
00527         return;
00528 
00529     iter->set = set;
00530     iter->index = 0;
00531     iter->cur_prop = set->properties_head;
00532 }
00533 
00534 
00541 dbus_bool_t
00542 libhal_psi_has_more (LibHalPropertySetIterator * iter)
00543 {
00544     return iter->index < iter->set->num_properties;
00545 }
00546 
00551 void
00552 libhal_psi_next (LibHalPropertySetIterator * iter)
00553 {
00554     iter->index++;
00555     iter->cur_prop = iter->cur_prop->next;
00556 }
00557 
00563 LibHalPropertyType
00564 libhal_psi_get_type (LibHalPropertySetIterator * iter)
00565 {
00566     return iter->cur_prop->type;
00567 }
00568 
00577 char *
00578 libhal_psi_get_key (LibHalPropertySetIterator * iter)
00579 {
00580     return iter->cur_prop->key;
00581 }
00582 
00591 char *
00592 libhal_psi_get_string (LibHalPropertySetIterator * iter)
00593 {
00594     return iter->cur_prop->str_value;
00595 }
00596 
00602 dbus_int32_t
00603 libhal_psi_get_int (LibHalPropertySetIterator * iter)
00604 {
00605     return iter->cur_prop->int_value;
00606 }
00607 
00613 dbus_uint64_t
00614 libhal_psi_get_uint64 (LibHalPropertySetIterator * iter)
00615 {
00616     return iter->cur_prop->uint64_value;
00617 }
00618 
00624 double
00625 libhal_psi_get_double (LibHalPropertySetIterator * iter)
00626 {
00627     return iter->cur_prop->double_value;
00628 }
00629 
00635 dbus_bool_t
00636 libhal_psi_get_bool (LibHalPropertySetIterator * iter)
00637 {
00638     return iter->cur_prop->bool_value;
00639 }
00640 
00646 char **
00647 libhal_psi_get_strlist (LibHalPropertySetIterator * iter)
00648 {
00649     return iter->cur_prop->strlist_value;
00650 }
00651 
00652 
00653 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00654 static DBusHandlerResult
00655 filter_func (DBusConnection * connection,
00656          DBusMessage * message, void *user_data)
00657 {
00658     const char *object_path;
00659     DBusError error;
00660     LibHalContext *ctx = (LibHalContext *) user_data;
00661 
00662     if (ctx->is_shutdown)
00663         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00664 
00665     dbus_error_init (&error);
00666 
00667     object_path = dbus_message_get_path (message);
00668 
00669     /*printf("*** in filter_func, object_path=%s\n", object_path);*/
00670 
00671     if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager",
00672                     "DeviceAdded")) {
00673         char *udi;
00674         if (dbus_message_get_args (message, &error,
00675                        DBUS_TYPE_STRING, &udi,
00676                        DBUS_TYPE_INVALID)) {
00677             if (ctx->device_added != NULL) {
00678                 ctx->device_added (ctx, udi);
00679             }
00680         }
00681         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00682     } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager", "DeviceRemoved")) {
00683         char *udi;
00684         if (dbus_message_get_args (message, &error,
00685                        DBUS_TYPE_STRING, &udi,
00686                        DBUS_TYPE_INVALID)) {
00687             if (ctx->device_removed != NULL) {
00688                 ctx->device_removed (ctx, udi);
00689             }
00690         }
00691         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00692     } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager","NewCapability")) {
00693         char *udi;
00694         char *capability;
00695         if (dbus_message_get_args (message, &error,
00696                        DBUS_TYPE_STRING, &udi,
00697                        DBUS_TYPE_STRING, &capability,
00698                        DBUS_TYPE_INVALID)) {
00699             if (ctx->device_new_capability != NULL) {
00700                 ctx->device_new_capability (ctx, udi, capability);
00701             }
00702         }
00703         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00704     } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "Condition")) {
00705         char *condition_name;
00706         char *condition_detail;
00707         if (dbus_message_get_args (message, &error,
00708                        DBUS_TYPE_STRING, &condition_name,
00709                        DBUS_TYPE_STRING, &condition_detail,
00710                        DBUS_TYPE_INVALID)) {
00711             if (ctx->device_condition != NULL) {
00712                 ctx->device_condition (ctx, object_path, condition_name, condition_detail);
00713             }
00714         }
00715         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00716     } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "PropertyModified")) {
00717         if (ctx->device_property_modified != NULL) {
00718             int i;
00719             char *key;
00720             dbus_bool_t removed;
00721             dbus_bool_t added;
00722             int num_modifications;
00723             DBusMessageIter iter;
00724             DBusMessageIter iter_array;
00725     
00726             dbus_message_iter_init (message, &iter);
00727             dbus_message_iter_get_basic (&iter, &num_modifications);
00728             dbus_message_iter_next (&iter);
00729 
00730             dbus_message_iter_recurse (&iter, &iter_array);
00731 
00732             for (i = 0; i < num_modifications; i++) {
00733                 DBusMessageIter iter_struct;
00734 
00735                 dbus_message_iter_recurse (&iter_array, &iter_struct);
00736 
00737                 dbus_message_iter_get_basic (&iter_struct, &key);
00738                 dbus_message_iter_next (&iter_struct);
00739                 dbus_message_iter_get_basic (&iter_struct, &removed);
00740                 dbus_message_iter_next (&iter_struct);
00741                 dbus_message_iter_get_basic (&iter_struct, &added);
00742                 
00743                 ctx->device_property_modified (ctx, 
00744                                    object_path,
00745                                    key, removed,
00746                                    added);
00747                 
00748                 dbus_message_iter_next (&iter_array);
00749             }
00750             
00751         }
00752         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00753     }
00754     
00755     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00756 }
00757 
00758 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
00759 
00760 /* for i18n purposes */
00761 static dbus_bool_t libhal_already_initialized_once = FALSE;
00762 
00763 #if 0
00764 
00782 LibHalContext*
00783 libhal_initialize (const LibHalFunctions * cb_functions,
00784         dbus_bool_t use_cache)
00785 {
00786     DBusError error;
00787     LibHalContext *ctx;
00788 
00789     if (!libhal_already_initialized_once) {
00790         bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
00791         bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
00792         
00793         libhal_already_initialized_once = TRUE;
00794     }
00795     
00796     ctx = malloc (sizeof (LibHalContext));
00797     if (ctx == NULL) {
00798         fprintf (stderr, "%s %d : Cannot allocated %d bytes!\n",
00799              __FILE__, __LINE__, sizeof (LibHalContext));
00800         return NULL;
00801     }
00802 
00803     ctx->is_initialized = FALSE;
00804     ctx->is_shutdown = FALSE;
00805 
00806     ctx->cache_enabled = use_cache;
00807 
00808     ctx->functions = cb_functions;
00809     /* allow caller to pass NULL */
00810     if (ctx->functions == NULL)
00811         ctx->functions = &libhal_null_functions;
00812 
00813     /* connect to hald service on the system bus */
00814     
00815     ctx->connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
00816     if (ctx->connection == NULL) {
00817         fprintf (stderr,
00818              "%s %d : Error connecting to system bus: %s\n",
00819              __FILE__, __LINE__, error.message);
00820         dbus_error_free (&error);
00821         return NULL;
00822     }
00823 
00824     if (ctx->main_loop_integration != NULL) {
00825 
00826         ctx->main_loop_integration (ctx, ctx->connection);
00827     }
00828 
00829     if (!dbus_connection_add_filter
00830         (ctx->connection, filter_func, ctx, NULL)) {
00831         fprintf (stderr,
00832              "%s %d : Error creating connection handler\r\n",
00833              __FILE__, __LINE__);
00835         return NULL;
00836     }
00837 
00838     dbus_bus_add_match (ctx->connection,
00839                 "type='signal',"
00840                 "interface='org.freedesktop.Hal.Manager',"
00841                 "sender='org.freedesktop.Hal',"
00842                 "path='/org/freedesktop/Hal/Manager'", &error);
00843     if (dbus_error_is_set (&error)) {
00844         fprintf (stderr, "%s %d : Error subscribing to signals, "
00845              "error=%s\r\n",
00846              __FILE__, __LINE__, error.message);
00848         return NULL;
00849     }
00850 
00851     ctx->is_initialized = TRUE;
00852     return ctx;
00853 }
00854 
00861 int
00862 libhal_shutdown (LibHalContext *ctx)
00863 {
00864     DBusError error;
00865 
00866     if (!ctx->is_initialized)
00867         return 1;
00868 
00869     /* unsubscribe the match rule we added in initialize; this is safe even with multiple
00870      * instances of libhal running - see the dbus docs */
00871     
00872     dbus_bus_remove_match (ctx->connection,
00873                    "type='signal',"
00874                    "interface='org.freedesktop.Hal.Manager',"
00875                    "sender='org.freedesktop.Hal',"
00876                    "path='/org/freedesktop/Hal/Manager'", &error);
00877     if (dbus_error_is_set (&error)) {
00878         fprintf (stderr, "%s %d : Error removing match rule, error=%s\r\n",
00879              __FILE__, __LINE__, error.message);
00880     }
00881 
00882     /* TODO: remove all other match rules */
00883 
00884     /* set a flag so we don't propagte callbacks from this context anymore */
00885     ctx->is_shutdown = TRUE;
00886 
00887     /* yikes, it's dangerous to unref the connection since it will terminate the process
00888      * because this connection may be shared so we cannot set the exit_on_disconnect flag
00889      *
00890      * so we don't do that right now 
00891      *
00892      */
00893     /*dbus_connection_unref (ctx->connection);*/
00894 
00895     /* we also refuse to free the resources as filter_function may reference these 
00896      * 
00897      * should free async when our connection goes away.
00898      */
00899     /* free (ctx); */
00900     return 0;
00901 }
00902 #endif
00903 
00915 char **
00916 libhal_get_all_devices (LibHalContext *ctx, int *num_devices, DBusError *error)
00917 {   
00918     DBusMessage *message;
00919     DBusMessage *reply;
00920     DBusMessageIter iter_array, reply_iter;
00921     char **hal_device_names;
00922     DBusError _error;
00923 
00924     LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
00925 
00926     *num_devices = 0;
00927 
00928     message = dbus_message_new_method_call ("org.freedesktop.Hal",
00929                         "/org/freedesktop/Hal/Manager",
00930                         "org.freedesktop.Hal.Manager",
00931                         "GetAllDevices");
00932     if (message == NULL) {
00933         fprintf (stderr, "%s %d : Could not allocate D-BUS message\n", __FILE__, __LINE__);
00934         return NULL;
00935     }
00936 
00937     dbus_error_init (&_error);
00938     reply = dbus_connection_send_with_reply_and_block (ctx->connection, message, -1, &_error);
00939 
00940     dbus_move_error (&_error, error);
00941     if (error != NULL && dbus_error_is_set (error)) {
00942         dbus_message_unref (message);
00943         return NULL;
00944     }
00945     if (reply == NULL) {
00946         dbus_message_unref (message);
00947         return NULL;
00948     }
00949 
00950     /* now analyze reply */
00951     dbus_message_iter_init (reply, &reply_iter);
00952 
00953     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
00954         fprintf (stderr, "%s %d : wrong reply from hald.  Expecting an array.\n", __FILE__, __LINE__);
00955         return NULL;
00956     }
00957     
00958     dbus_message_iter_recurse (&reply_iter, &iter_array);
00959 
00960     hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
00961               
00962     dbus_message_unref (reply);
00963     dbus_message_unref (message);
00964 
00965     return hal_device_names;
00966 }
00967 
00981 LibHalPropertyType
00982 libhal_device_get_property_type (LibHalContext *ctx, const char *udi, const char *key, DBusError *error)
00983 {
00984     DBusMessage *message;
00985     DBusMessage *reply;
00986     DBusMessageIter iter, reply_iter;
00987     int type;
00988     DBusError _error;
00989 
00990     LIBHAL_CHECK_LIBHALCONTEXT(ctx, LIBHAL_PROPERTY_TYPE_INVALID); // or return NULL?
00991     
00992     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
00993                         "org.freedesktop.Hal.Device",
00994                         "GetPropertyType");
00995     if (message == NULL) {
00996         fprintf (stderr, "%s %d : Couldn't allocate D-BUS message\n", __FILE__, __LINE__);
00997         return LIBHAL_PROPERTY_TYPE_INVALID;
00998     }
00999 
01000     dbus_message_iter_init_append (message, &iter);
01001     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01002 
01003     dbus_error_init (&_error);
01004     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01005                                message, -1,
01006                                &_error);
01007 
01008     dbus_move_error (&_error, error);
01009     if (error != NULL && dbus_error_is_set (error)) {
01010         dbus_message_unref (message);
01011         return LIBHAL_PROPERTY_TYPE_INVALID;
01012     }
01013     if (reply == NULL) {
01014         dbus_message_unref (message);
01015         return LIBHAL_PROPERTY_TYPE_INVALID;
01016     }
01017 
01018     dbus_message_iter_init (reply, &reply_iter);
01019     dbus_message_iter_get_basic (&reply_iter, &type);
01020 
01021     dbus_message_unref (message);
01022     dbus_message_unref (reply);
01023 
01024     return type;
01025 }
01026 
01042 char **
01043 libhal_device_get_property_strlist (LibHalContext *ctx, const char *udi, const char *key, DBusError *error)
01044 {   
01045     DBusMessage *message;
01046     DBusMessage *reply;
01047     DBusMessageIter iter, iter_array, reply_iter;
01048     char **our_strings;
01049     DBusError _error;
01050     
01051     LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
01052 
01053     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01054                         "org.freedesktop.Hal.Device",
01055                         "GetPropertyStringList");
01056     if (message == NULL) {
01057         fprintf (stderr,
01058              "%s %d : Couldn't allocate D-BUS message\n",
01059              __FILE__, __LINE__);
01060         return NULL;
01061     }
01062 
01063     dbus_message_iter_init_append (message, &iter);
01064     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01065 
01066     dbus_error_init (&_error);
01067     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01068                                message, -1,
01069                                &_error);
01070 
01071     dbus_move_error (&_error, error);
01072     if (error != NULL && dbus_error_is_set (error)) {
01073         dbus_message_unref (message);
01074         return NULL;
01075     }
01076     if (reply == NULL) {
01077         dbus_message_unref (message);
01078         return NULL;
01079     }
01080     /* now analyse reply */
01081     dbus_message_iter_init (reply, &reply_iter);
01082 
01083     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
01084         fprintf (stderr, "%s %d : wrong reply from hald.  Expecting an array.\n", __FILE__, __LINE__);
01085         return NULL;
01086     }
01087     
01088     dbus_message_iter_recurse (&reply_iter, &iter_array);
01089 
01090     our_strings = libhal_get_string_array_from_iter (&iter_array, NULL);
01091               
01092     dbus_message_unref (reply);
01093     dbus_message_unref (message);
01094 
01095     return our_strings;
01096 }
01097 
01111 char *
01112 libhal_device_get_property_string (LibHalContext *ctx,
01113                    const char *udi, const char *key, DBusError *error)
01114 {   
01115     DBusMessage *message;
01116     DBusMessage *reply;
01117     DBusMessageIter iter, reply_iter;
01118     char *value;
01119     char *dbus_str;
01120     DBusError _error;
01121 
01122     LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
01123 
01124     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01125                         "org.freedesktop.Hal.Device",
01126                         "GetPropertyString");
01127 
01128     if (message == NULL) {
01129         fprintf (stderr,
01130              "%s %d : Couldn't allocate D-BUS message\n",
01131              __FILE__, __LINE__);
01132         return NULL;
01133     }
01134 
01135     dbus_message_iter_init_append (message, &iter);
01136     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01137 
01138     dbus_error_init (&_error);
01139     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01140                                message, -1,
01141                                &_error);
01142 
01143     dbus_move_error (&_error, error);
01144     if (error != NULL && dbus_error_is_set (error)) {
01145         dbus_message_unref (message);
01146         return NULL;
01147     }
01148     if (reply == NULL) {
01149         dbus_message_unref (message);
01150         return NULL;
01151     }
01152 
01153     dbus_message_iter_init (reply, &reply_iter);
01154 
01155     /* now analyze reply */
01156     if (dbus_message_iter_get_arg_type (&reply_iter) !=
01157            DBUS_TYPE_STRING) {
01158         dbus_message_unref (message);
01159         dbus_message_unref (reply);
01160         return NULL;
01161     }
01162 
01163     dbus_message_iter_get_basic (&reply_iter, &dbus_str);
01164     value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
01165     if (value == NULL) {
01166         fprintf (stderr, "%s %d : error allocating memory\n",
01167              __FILE__, __LINE__);
01169         return NULL;
01170     }
01171 
01172     dbus_message_unref (message);
01173     dbus_message_unref (reply);
01174     return value;
01175 }
01176 
01186 dbus_int32_t
01187 libhal_device_get_property_int (LibHalContext *ctx, 
01188                 const char *udi, const char *key, DBusError *error)
01189 {
01190     DBusMessage *message;
01191     DBusMessage *reply;
01192     DBusMessageIter iter, reply_iter;
01193     dbus_int32_t value;
01194     DBusError _error;
01195 
01196     LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1);
01197 
01198     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01199                         "org.freedesktop.Hal.Device",
01200                         "GetPropertyInteger");
01201     if (message == NULL) {
01202         fprintf (stderr,
01203              "%s %d : Couldn't allocate D-BUS message\n",
01204              __FILE__, __LINE__);
01205         return -1;
01206     }
01207 
01208     dbus_message_iter_init_append (message, &iter);
01209     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01210 
01211     dbus_error_init (&_error);
01212     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01213                                message, -1,
01214                                &_error);
01215 
01216     dbus_move_error (&_error, error);
01217     if (error != NULL && dbus_error_is_set (error)) {
01218         dbus_message_unref (message);
01219         return -1;
01220     }
01221     if (reply == NULL) {
01222         dbus_message_unref (message);
01223         return -1;
01224     }
01225 
01226     dbus_message_iter_init (reply, &reply_iter);
01227 
01228     /* now analyze reply */
01229     if (dbus_message_iter_get_arg_type (&reply_iter) !=
01230            DBUS_TYPE_INT32) {
01231         fprintf (stderr,
01232              "%s %d : property '%s' for device '%s' is not "
01233              "of type integer\n", __FILE__, __LINE__, key,
01234              udi);
01235         dbus_message_unref (message);
01236         dbus_message_unref (reply);
01237         return -1;
01238     }
01239     dbus_message_iter_get_basic (&reply_iter, &value);
01240 
01241     dbus_message_unref (message);
01242     dbus_message_unref (reply);
01243     return value;
01244 }
01245 
01255 dbus_uint64_t
01256 libhal_device_get_property_uint64 (LibHalContext *ctx, 
01257                    const char *udi, const char *key, DBusError *error)
01258 {
01259     DBusMessage *message;
01260     DBusMessage *reply;
01261     DBusMessageIter iter, reply_iter;
01262     dbus_uint64_t value;
01263     DBusError _error;
01264 
01265     LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1);
01266 
01267     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01268                         "org.freedesktop.Hal.Device",
01269                         "GetPropertyInteger");
01270     if (message == NULL) {
01271         fprintf (stderr,
01272              "%s %d : Couldn't allocate D-BUS message\n",
01273              __FILE__, __LINE__);
01274         return -1;
01275     }
01276 
01277     dbus_message_iter_init_append (message, &iter);
01278     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01279 
01280     dbus_error_init (&_error);
01281     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01282                                message, -1,
01283                                &_error);
01284     
01285     dbus_move_error (&_error, error);
01286     if (error != NULL && dbus_error_is_set (error)) {
01287         dbus_message_unref (message);
01288         return -1;
01289     }
01290     if (reply == NULL) {
01291         dbus_message_unref (message);
01292         return -1;
01293     }
01294 
01295     dbus_message_iter_init (reply, &reply_iter);
01296     /* now analyze reply */
01297     if (dbus_message_iter_get_arg_type (&reply_iter) !=
01298            DBUS_TYPE_UINT64) {
01299         fprintf (stderr,
01300              "%s %d : property '%s' for device '%s' is not "
01301              "of type integer\n", __FILE__, __LINE__, key,
01302              udi);
01303         dbus_message_unref (message);
01304         dbus_message_unref (reply);
01305         return -1;
01306     }
01307     dbus_message_iter_get_basic (&reply_iter, &value);
01308 
01309     dbus_message_unref (message);
01310     dbus_message_unref (reply);
01311     return value;
01312 }
01313 
01323 double
01324 libhal_device_get_property_double (LibHalContext *ctx, 
01325                    const char *udi, const char *key, DBusError *error)
01326 {
01327     DBusMessage *message;
01328     DBusMessage *reply;
01329     DBusMessageIter iter, reply_iter;
01330     double value;
01331     DBusError _error;
01332 
01333     LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1.0);
01334 
01335     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01336                         "org.freedesktop.Hal.Device",
01337                         "GetPropertyDouble");
01338     if (message == NULL) {
01339         fprintf (stderr,
01340              "%s %d : Couldn't allocate D-BUS message\n",
01341              __FILE__, __LINE__);
01342         return -1.0f;
01343     }
01344 
01345     dbus_message_iter_init_append (message, &iter);
01346     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01347 
01348     dbus_error_init (&_error);
01349     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01350                                message, -1,
01351                                &_error);
01352 
01353     dbus_move_error (&_error, error);
01354     if (error != NULL && dbus_error_is_set (error)) {
01355         dbus_message_unref (message);
01356         return -1.0f;
01357     }
01358     if (reply == NULL) {
01359         dbus_message_unref (message);
01360         return -1.0f;
01361     }
01362 
01363     dbus_message_iter_init (reply, &reply_iter);
01364 
01365     /* now analyze reply */
01366     if (dbus_message_iter_get_arg_type (&reply_iter) !=
01367            DBUS_TYPE_DOUBLE) {
01368         fprintf (stderr,
01369              "%s %d : property '%s' for device '%s' is not "
01370              "of type double\n", __FILE__, __LINE__, key, udi);
01371         dbus_message_unref (message);
01372         dbus_message_unref (reply);
01373         return -1.0f;
01374     }
01375     dbus_message_iter_get_basic (&reply_iter, &value);
01376 
01377     dbus_message_unref (message);
01378     dbus_message_unref (reply);
01379     return (double) value;
01380 }
01381 
01391 dbus_bool_t
01392 libhal_device_get_property_bool (LibHalContext *ctx, 
01393                  const char *udi, const char *key, DBusError *error)
01394 {
01395     DBusMessage *message;
01396     DBusMessage *reply;
01397     DBusMessageIter iter, reply_iter;
01398     dbus_bool_t value;
01399     DBusError _error;
01400 
01401     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
01402 
01403     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01404                         "org.freedesktop.Hal.Device",
01405                         "GetPropertyBoolean");
01406     if (message == NULL) {
01407         fprintf (stderr,
01408              "%s %d : Couldn't allocate D-BUS message\n",
01409              __FILE__, __LINE__);
01410         return FALSE;
01411     }
01412 
01413     dbus_message_iter_init_append (message, &iter);
01414     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01415     
01416     dbus_error_init (&_error);
01417     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01418                                message, -1,
01419                                &_error);
01420 
01421     dbus_move_error (&_error, error);
01422     if (error != NULL && dbus_error_is_set (error)) {
01423         dbus_message_unref (message);
01424         return FALSE;
01425     }
01426     if (reply == NULL) {
01427         dbus_message_unref (message);
01428         return FALSE;
01429     }
01430 
01431     dbus_message_iter_init (reply, &reply_iter);
01432 
01433     /* now analyze reply */
01434     if (dbus_message_iter_get_arg_type (&reply_iter) !=
01435            DBUS_TYPE_BOOLEAN) {
01436         fprintf (stderr,
01437              "%s %d : property '%s' for device '%s' is not "
01438              "of type bool\n", __FILE__, __LINE__, key, udi);
01439         dbus_message_unref (message);
01440         dbus_message_unref (reply);
01441         return FALSE;
01442     }
01443     dbus_message_iter_get_basic (&reply_iter, &value);
01444 
01445     dbus_message_unref (message);
01446     dbus_message_unref (reply);
01447     return value;
01448 }
01449 
01450 
01451 /* generic helper */
01452 static dbus_bool_t
01453 libhal_device_set_property_helper (LibHalContext *ctx, 
01454                    const char *udi,
01455                    const char *key,
01456                    int type,
01457                    const char *str_value,
01458                    dbus_int32_t int_value,
01459                    dbus_uint64_t uint64_value,
01460                    double double_value,
01461                    dbus_bool_t bool_value,
01462                    DBusError *error)
01463 {
01464     DBusMessage *message;
01465     DBusMessage *reply;
01466     DBusMessageIter iter;
01467     char *method_name = NULL;
01468 
01469     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
01470     
01472     switch (type) {
01473     case DBUS_TYPE_INVALID:
01474         method_name = "RemoveProperty";
01475         break;
01476     case DBUS_TYPE_STRING:
01477         method_name = "SetPropertyString";
01478         break;
01479     case DBUS_TYPE_INT32:
01480     case DBUS_TYPE_UINT64:
01481         method_name = "SetPropertyInteger";
01482         break;
01483     case DBUS_TYPE_DOUBLE:
01484         method_name = "SetPropertyDouble";
01485         break;
01486     case DBUS_TYPE_BOOLEAN:
01487         method_name = "SetPropertyBoolean";
01488         break;
01489 
01490     default:
01491         /* cannot happen; is not callable from outside this file */
01492         break;
01493     }
01494 
01495     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01496                         "org.freedesktop.Hal.Device",
01497                         method_name);
01498     if (message == NULL) {
01499         fprintf (stderr,
01500              "%s %d : Couldn't allocate D-BUS message\n",
01501              __FILE__, __LINE__);
01502         return FALSE;
01503     }
01504 
01505     dbus_message_iter_init_append (message, &iter);
01506     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01507     switch (type) {
01508     case DBUS_TYPE_STRING:
01509         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &str_value);
01510         break;
01511     case DBUS_TYPE_INT32:
01512         dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &int_value);
01513         break;
01514     case DBUS_TYPE_UINT64:
01515         dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT64, &uint64_value);
01516         break;
01517     case DBUS_TYPE_DOUBLE:
01518         dbus_message_iter_append_basic (&iter, DBUS_TYPE_DOUBLE, &double_value);
01519         break;
01520     case DBUS_TYPE_BOOLEAN:
01521         dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &bool_value);
01522         break;
01523     }
01524 
01525     
01526     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01527                                message, -1,
01528                                error);
01529     if (dbus_error_is_set (error)) {
01530         dbus_message_unref (message);
01531         return FALSE;
01532     }
01533 
01534     if (reply == NULL) {
01535         dbus_message_unref (message);
01536         return FALSE;
01537     }
01538 
01539     dbus_message_unref (message);
01540     dbus_message_unref (reply);
01541 
01542     return TRUE;
01543 }
01544 
01557 dbus_bool_t
01558 libhal_device_set_property_string (LibHalContext *ctx, 
01559                    const char *udi,
01560                    const char *key, 
01561                    const char *value,
01562                    DBusError *error)
01563 {
01564     return libhal_device_set_property_helper (ctx, udi, key,
01565                           DBUS_TYPE_STRING,
01566                           value, 0, 0, 0.0f, FALSE, error);
01567 }
01568 
01581 dbus_bool_t
01582 libhal_device_set_property_int (LibHalContext *ctx, const char *udi,
01583                 const char *key, dbus_int32_t value, DBusError *error)
01584 {
01585     return libhal_device_set_property_helper (ctx, udi, key,
01586                           DBUS_TYPE_INT32,
01587                           NULL, value, 0, 0.0f, FALSE, error);
01588 }
01589 
01602 dbus_bool_t
01603 libhal_device_set_property_uint64 (LibHalContext *ctx, const char *udi,
01604                    const char *key, dbus_uint64_t value, DBusError *error)
01605 {
01606     return libhal_device_set_property_helper (ctx, udi, key,
01607                           DBUS_TYPE_UINT64,
01608                           NULL, 0, value, 0.0f, FALSE, error);
01609 }
01610 
01623 dbus_bool_t
01624 libhal_device_set_property_double (LibHalContext *ctx, const char *udi,
01625                    const char *key, double value, DBusError *error)
01626 {
01627     return libhal_device_set_property_helper (ctx, udi, key,
01628                           DBUS_TYPE_DOUBLE,
01629                           NULL, 0, 0, value, FALSE, error);
01630 }
01631 
01644 dbus_bool_t
01645 libhal_device_set_property_bool (LibHalContext *ctx, const char *udi,
01646                  const char *key, dbus_bool_t value, DBusError *error)
01647 {
01648     return libhal_device_set_property_helper (ctx, udi, key,
01649                           DBUS_TYPE_BOOLEAN,
01650                           NULL, 0, 0, 0.0f, value, error);
01651 }
01652 
01653 
01664 dbus_bool_t
01665 libhal_device_remove_property (LibHalContext *ctx, 
01666                    const char *udi, const char *key, DBusError *error)
01667 {
01668     return libhal_device_set_property_helper (ctx, udi, key, DBUS_TYPE_INVALID, 
01669                           /* DBUS_TYPE_INVALID means remove */
01670                           NULL, 0, 0, 0.0f, FALSE, error);
01671 }
01672 
01685 dbus_bool_t
01686 libhal_device_property_strlist_append (LibHalContext *ctx, 
01687                        const char *udi,
01688                        const char *key,
01689                        const char *value,
01690                        DBusError *error)
01691 {
01692     DBusMessage *message;
01693     DBusMessage *reply;
01694     DBusMessageIter iter;
01695 
01696     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
01697 
01698     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01699                         "org.freedesktop.Hal.Device",
01700                         "StringListAppend");
01701     if (message == NULL) {
01702         fprintf (stderr,
01703              "%s %d : Couldn't allocate D-BUS message\n",
01704              __FILE__, __LINE__);
01705         return FALSE;
01706     }
01707     dbus_message_iter_init_append (message, &iter);
01708     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01709     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
01710     
01711     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01712                                message, -1,
01713                                error);
01714     if (dbus_error_is_set (error)) {
01715         dbus_message_unref (message);
01716         return FALSE;
01717     }
01718     if (reply == NULL) {
01719         dbus_message_unref (message);
01720         return FALSE;
01721     }
01722     return TRUE;
01723 }
01724 
01737 dbus_bool_t
01738 libhal_device_property_strlist_prepend (LibHalContext *ctx, 
01739                     const char *udi,
01740                     const char *key,
01741                     const char *value, 
01742                     DBusError *error)
01743 {
01744     DBusMessage *message;
01745     DBusMessage *reply;
01746     DBusMessageIter iter;
01747 
01748     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
01749 
01750     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01751                         "org.freedesktop.Hal.Device",
01752                         "StringListPrepend");
01753     if (message == NULL) {
01754         fprintf (stderr,
01755              "%s %d : Couldn't allocate D-BUS message\n",
01756              __FILE__, __LINE__);
01757         return FALSE;
01758     }
01759     dbus_message_iter_init_append (message, &iter);
01760     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01761     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
01762     
01763     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01764                                message, -1,
01765                                error);
01766     if (dbus_error_is_set (error)) {
01767         dbus_message_unref (message);
01768         return FALSE;
01769     }
01770     if (reply == NULL) {
01771         dbus_message_unref (message);
01772         return FALSE;
01773     }
01774     return TRUE;
01775 }
01776 
01789 dbus_bool_t
01790 libhal_device_property_strlist_remove_index (LibHalContext *ctx, 
01791                          const char *udi,
01792                          const char *key,
01793                          unsigned int index,
01794                          DBusError *error)
01795 {
01796     DBusMessage *message;
01797     DBusMessage *reply;
01798     DBusMessageIter iter;
01799 
01800     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
01801 
01802     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01803                         "org.freedesktop.Hal.Device",
01804                         "StringListRemoveIndex");
01805     if (message == NULL) {
01806         fprintf (stderr,
01807              "%s %d : Couldn't allocate D-BUS message\n",
01808              __FILE__, __LINE__);
01809         return FALSE;
01810     }
01811     dbus_message_iter_init_append (message, &iter);
01812     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01813     dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &index);
01814     
01815     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01816                                message, -1,
01817                                error);
01818     if (dbus_error_is_set (error)) {
01819         dbus_message_unref (message);
01820         return FALSE;
01821     }
01822     if (reply == NULL) {
01823         dbus_message_unref (message);
01824         return FALSE;
01825     }
01826     return TRUE;
01827 }
01828 
01841 dbus_bool_t
01842 libhal_device_property_strlist_remove (LibHalContext *ctx, 
01843                        const char *udi,
01844                        const char *key,
01845                        const char *value, DBusError *error)
01846 {
01847     DBusMessage *message;
01848     DBusMessage *reply;
01849     DBusMessageIter iter;
01850 
01851     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
01852 
01853     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01854                         "org.freedesktop.Hal.Device",
01855                         "StringListRemove");
01856     if (message == NULL) {
01857         fprintf (stderr,
01858              "%s %d : Couldn't allocate D-BUS message\n",
01859              __FILE__, __LINE__);
01860         return FALSE;
01861     }
01862     dbus_message_iter_init_append (message, &iter);
01863     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01864     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
01865     
01866     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01867                                message, -1,
01868                                error);
01869     if (dbus_error_is_set (error)) {
01870         dbus_message_unref (message);
01871         return FALSE;
01872     }
01873     if (reply == NULL) {
01874         dbus_message_unref (message);
01875         return FALSE;
01876     }
01877     return TRUE;
01878 }
01879 
01880 
01895 dbus_bool_t
01896 libhal_device_lock (LibHalContext *ctx,
01897             const char *udi,
01898             const char *reason_to_lock,
01899             char **reason_why_locked, DBusError *error)
01900 {
01901     DBusMessage *message;
01902     DBusMessageIter iter;
01903     DBusMessage *reply;
01904 
01905     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
01906 
01907     if (reason_why_locked != NULL)
01908         *reason_why_locked = NULL;
01909 
01910     message = dbus_message_new_method_call ("org.freedesktop.Hal",
01911                         udi,
01912                         "org.freedesktop.Hal.Device",
01913                         "Lock");
01914 
01915     if (message == NULL) {
01916         fprintf (stderr,
01917              "%s %d : Couldn't allocate D-BUS message\n",
01918              __FILE__, __LINE__);
01919         return FALSE;
01920     }
01921 
01922     dbus_message_iter_init_append (message, &iter);
01923     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &reason_to_lock);
01924 
01925     
01926     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01927                                message, -1,
01928                                error);
01929 
01930     if (dbus_error_is_set (error)) {
01931         if (strcmp (error->name,
01932                 "org.freedesktop.Hal.DeviceAlreadyLocked") == 0) {
01933             if (reason_why_locked != NULL) {
01934                 *reason_why_locked =
01935                     dbus_malloc0 (strlen (error->message) + 1);
01936                 strcpy (*reason_why_locked, error->message);
01937             }
01938         }
01939 
01940         dbus_message_unref (message);
01941         return FALSE;
01942     }
01943 
01944     dbus_message_unref (message);
01945 
01946     if (reply == NULL)
01947         return FALSE;
01948 
01949     dbus_message_unref (reply);
01950 
01951     return TRUE;
01952 }
01953 
01963 dbus_bool_t
01964 libhal_device_unlock (LibHalContext *ctx,
01965               const char *udi, DBusError *error)
01966 {
01967     DBusMessage *message;
01968     DBusMessage *reply;
01969 
01970     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
01971 
01972     message = dbus_message_new_method_call ("org.freedesktop.Hal",
01973                         udi,
01974                         "org.freedesktop.Hal.Device",
01975                         "Unlock");
01976 
01977     if (message == NULL) {
01978         fprintf (stderr,
01979              "%s %d : Couldn't allocate D-BUS message\n",
01980              __FILE__, __LINE__);
01981         return FALSE;
01982     }
01983 
01984     
01985     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01986                                message, -1,
01987                                error);
01988 
01989     if (dbus_error_is_set (error)) {
01990         dbus_message_unref (message);
01991         return FALSE;
01992     }
01993 
01994     dbus_message_unref (message);
01995 
01996     if (reply == NULL)
01997         return FALSE;
01998 
01999     dbus_message_unref (reply);
02000 
02001     return TRUE;
02002 }
02003 
02004 
02018 char *
02019 libhal_new_device (LibHalContext *ctx, DBusError *error)
02020 {
02021     DBusMessage *message;
02022     DBusMessage *reply;
02023     DBusMessageIter reply_iter;
02024     char *value;
02025     char *dbus_str;
02026 
02027     LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
02028 
02029     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02030                         "/org/freedesktop/Hal/Manager",
02031                         "org.freedesktop.Hal.Manager",
02032                         "NewDevice");
02033     if (message == NULL) {
02034         fprintf (stderr,
02035              "%s %d : Couldn't allocate D-BUS message\n",
02036              __FILE__, __LINE__);
02037         return NULL;
02038     }
02039 
02040     
02041     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02042                                message, -1,
02043                                error);
02044     if (dbus_error_is_set (error)) {
02045         dbus_message_unref (message);
02046         return NULL;
02047     }
02048     if (reply == NULL) {
02049         dbus_message_unref (message);
02050         return NULL;
02051     }
02052 
02053     dbus_message_iter_init (reply, &reply_iter);
02054 
02055     /* now analyze reply */
02056     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_STRING) {
02057         fprintf (stderr,
02058              "%s %d : expected a string in reply to NewDevice\n",
02059              __FILE__, __LINE__);
02060         dbus_message_unref (message);
02061         dbus_message_unref (reply);
02062         return NULL;
02063     }
02064 
02065     dbus_message_iter_get_basic (&reply_iter, &dbus_str);
02066     value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
02067     if (value == NULL) {
02068         fprintf (stderr, "%s %d : error allocating memory\n",
02069              __FILE__, __LINE__);
02071         return NULL;
02072     }
02073 
02074     dbus_message_unref (message);
02075     dbus_message_unref (reply);
02076     return value;
02077 }
02078 
02079 
02100 dbus_bool_t
02101 libhal_device_commit_to_gdl (LibHalContext *ctx, 
02102                  const char *temp_udi, const char *udi, DBusError *error)
02103 {
02104     DBusMessage *message;
02105     DBusMessage *reply;
02106     DBusMessageIter iter;
02107 
02108     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02109 
02110     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02111                         "/org/freedesktop/Hal/Manager",
02112                         "org.freedesktop.Hal.Manager",
02113                         "CommitToGdl");
02114     if (message == NULL) {
02115         fprintf (stderr,
02116              "%s %d : Couldn't allocate D-BUS message\n",
02117              __FILE__, __LINE__);
02118         return FALSE;
02119     }
02120 
02121     dbus_message_iter_init_append (message, &iter);
02122     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &temp_udi);
02123     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
02124 
02125     
02126     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02127                                message, -1,
02128                                error);
02129     if (dbus_error_is_set (error)) {
02130         dbus_message_unref (message);
02131         return FALSE;
02132     }
02133     if (reply == NULL) {
02134         dbus_message_unref (message);
02135         return FALSE;
02136     }
02137 
02138     dbus_message_unref (message);
02139     dbus_message_unref (reply);
02140     return TRUE;
02141 }
02142 
02156 dbus_bool_t
02157 libhal_remove_device (LibHalContext *ctx, const char *udi, DBusError *error)
02158 {
02159     DBusMessage *message;
02160     DBusMessage *reply;
02161     DBusMessageIter iter;
02162 
02163     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02164 
02165     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02166                         "/org/freedesktop/Hal/Manager",
02167                         "org.freedesktop.Hal.Manager",
02168                         "Remove");
02169     if (message == NULL) {
02170         fprintf (stderr,
02171              "%s %d : Couldn't allocate D-BUS message\n",
02172              __FILE__, __LINE__);
02173         return FALSE;
02174     }
02175 
02176     dbus_message_iter_init_append (message, &iter);
02177     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
02178 
02179     
02180     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02181                                message, -1,
02182                                error);
02183     if (dbus_error_is_set (error)) {
02184         dbus_message_unref (message);
02185         return FALSE;
02186     }
02187     if (reply == NULL) {
02188         dbus_message_unref (message);
02189         return FALSE;
02190     }
02191 
02192     dbus_message_unref (message);
02193     dbus_message_unref (reply);
02194     return TRUE;
02195 }
02196 
02205 dbus_bool_t
02206 libhal_device_exists (LibHalContext *ctx, const char *udi, DBusError *error)
02207 {
02208     DBusMessage *message;
02209     DBusMessage *reply;
02210     DBusMessageIter iter, reply_iter;
02211     dbus_bool_t value;
02212     DBusError _error;
02213 
02214     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02215 
02216     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02217                         "/org/freedesktop/Hal/Manager",
02218                         "org.freedesktop.Hal.Manager",
02219                         "DeviceExists");
02220     if (message == NULL) {
02221         fprintf (stderr,
02222              "%s %d : Couldn't allocate D-BUS message\n",
02223              __FILE__, __LINE__);
02224         return FALSE;
02225     }
02226 
02227     dbus_message_iter_init_append (message, &iter);
02228     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
02229 
02230     dbus_error_init (&_error);
02231     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02232                                message, -1,
02233                                &_error);
02234 
02235     dbus_move_error (&_error, error);
02236     if (error != NULL && dbus_error_is_set (error)) {
02237         dbus_message_unref (message);
02238         return FALSE;
02239     }
02240     if (reply == NULL) {
02241         dbus_message_unref (message);
02242         return FALSE;
02243     }
02244 
02245     dbus_message_iter_init (reply, &reply_iter);
02246 
02247     /* now analyze reply */
02248     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
02249         fprintf (stderr,
02250              "%s %d : expected a bool in reply to DeviceExists\n",
02251              __FILE__, __LINE__);
02252         dbus_message_unref (message);
02253         dbus_message_unref (reply);
02254         return FALSE;
02255     }
02256 
02257     dbus_message_iter_get_basic (&reply_iter, &value);
02258 
02259     dbus_message_unref (message);
02260     dbus_message_unref (reply);
02261     return value;
02262 }
02263 
02273 dbus_bool_t
02274 libhal_device_property_exists (LibHalContext *ctx, 
02275                    const char *udi, const char *key, DBusError *error)
02276 {
02277     DBusMessage *message;
02278     DBusMessage *reply;
02279     DBusMessageIter iter, reply_iter;
02280     dbus_bool_t value;
02281     DBusError _error;
02282 
02283     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02284 
02285     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
02286                         "org.freedesktop.Hal.Device",
02287                         "PropertyExists");
02288     if (message == NULL) {
02289         fprintf (stderr,
02290              "%s %d : Couldn't allocate D-BUS message\n",
02291              __FILE__, __LINE__);
02292         return FALSE;
02293     }
02294 
02295     dbus_message_iter_init_append (message, &iter);
02296     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
02297 
02298     dbus_error_init (&_error);
02299     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02300                                message, -1,
02301                                &_error);
02302 
02303     dbus_move_error (&_error, error);
02304     if (error != NULL && dbus_error_is_set (error)) {
02305         dbus_message_unref (message);
02306         return FALSE;
02307     }
02308     if (reply == NULL) {
02309         dbus_message_unref (message);
02310         return FALSE;
02311     }
02312 
02313     dbus_message_iter_init (reply, &reply_iter);
02314 
02315     /* now analyse reply */
02316     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
02317         fprintf (stderr, "%s %d : expected a bool in reply to "
02318              "PropertyExists\n", __FILE__, __LINE__);
02319         dbus_message_unref (message);
02320         dbus_message_unref (reply);
02321         return FALSE;
02322     }
02323 
02324     dbus_message_iter_get_basic (&reply_iter, &value);
02325 
02326     dbus_message_unref (message);
02327     dbus_message_unref (reply);
02328     return value;
02329 }
02330 
02340 dbus_bool_t
02341 libhal_merge_properties (LibHalContext *ctx, 
02342              const char *target_udi, const char *source_udi, DBusError *error)
02343 {
02344     DBusMessage *message;
02345     DBusMessage *reply;
02346     DBusMessageIter iter;
02347 
02348     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02349 
02350     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02351                         "/org/freedesktop/Hal/Manager",
02352                         "org.freedesktop.Hal.Manager",
02353                         "MergeProperties");
02354     if (message == NULL) {
02355         fprintf (stderr,
02356              "%s %d : Couldn't allocate D-BUS message\n",
02357              __FILE__, __LINE__);
02358         return FALSE;
02359     }
02360 
02361     dbus_message_iter_init_append (message, &iter);
02362     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &target_udi);
02363     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &source_udi);
02364 
02365     
02366     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02367                                message, -1,
02368                                error);
02369     if (dbus_error_is_set (error)) {
02370         dbus_message_unref (message);
02371         return FALSE;
02372     }
02373     if (reply == NULL) {
02374         dbus_message_unref (message);
02375         return FALSE;
02376     }
02377 
02378     dbus_message_unref (message);
02379     dbus_message_unref (reply);
02380     return TRUE;
02381 }
02382 
02404 dbus_bool_t
02405 libhal_device_matches (LibHalContext *ctx, 
02406                  const char *udi1, const char *udi2,
02407                  const char *property_namespace, DBusError *error)
02408 {
02409     DBusMessage *message;
02410     DBusMessage *reply;
02411     DBusMessageIter iter, reply_iter;
02412     dbus_bool_t value;
02413     DBusError _error;
02414 
02415     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02416 
02417     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02418                         "/org/freedesktop/Hal/Manager",
02419                         "org.freedesktop.Hal.Manager",
02420                         "DeviceMatches");
02421     if (message == NULL) {
02422         fprintf (stderr,
02423              "%s %d : Couldn't allocate D-BUS message\n",
02424              __FILE__, __LINE__);
02425         return FALSE;
02426     }
02427 
02428     dbus_message_iter_init_append (message, &iter);
02429     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, udi1);
02430     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, udi2);
02431     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, property_namespace);
02432 
02433     dbus_error_init (&_error);
02434     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02435                                message, -1,
02436                                &_error);
02437 
02438     dbus_move_error (&_error, error);
02439     if (error != NULL && dbus_error_is_set (error)) {
02440         dbus_message_unref (message);
02441         return FALSE;
02442     }
02443     if (reply == NULL) {
02444         dbus_message_unref (message);
02445         return FALSE;
02446     }
02447     /* now analyse reply */
02448     dbus_message_iter_init (reply, &reply_iter);
02449 
02450     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
02451         fprintf (stderr,
02452              "%s %d : expected a bool in reply to DeviceMatches\n",
02453              __FILE__, __LINE__);
02454         dbus_message_unref (message);
02455         dbus_message_unref (reply);
02456         return FALSE;
02457     }
02458 
02459     dbus_message_iter_get_basic (&reply_iter, &value);
02460 
02461     dbus_message_unref (message);
02462     dbus_message_unref (reply);
02463     return value;
02464 }
02465 
02475 dbus_bool_t
02476 libhal_device_print (LibHalContext *ctx, const char *udi, DBusError *error)
02477 {
02478     int type;
02479     char *key;
02480     LibHalPropertySet *pset;
02481     LibHalPropertySetIterator i;
02482 
02483     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02484 
02485     printf ("device_id = %s\n", udi);
02486 
02487     if ((pset = libhal_device_get_all_properties (ctx, udi, error)) == NULL)
02488         return FALSE;
02489 
02490     for (libhal_psi_init (&i, pset); libhal_psi_has_more (&i);
02491          libhal_psi_next (&i)) {
02492         type = libhal_psi_get_type (&i);
02493         key = libhal_psi_get_key (&i);
02494 
02495         switch (type) {
02496         case LIBHAL_PROPERTY_TYPE_STRING:
02497             printf ("    %s = '%s' (string)\n", key,
02498                 libhal_psi_get_string (&i));
02499             break;
02500         case LIBHAL_PROPERTY_TYPE_INT32:
02501             printf ("    %s = %d = 0x%x (int)\n", key,
02502                 libhal_psi_get_int (&i),
02503                 libhal_psi_get_int (&i));
02504             break;
02505         case LIBHAL_PROPERTY_TYPE_UINT64:
02506             printf ("    %s = %lld = 0x%llx (uint64)\n", key,
02507                 libhal_psi_get_uint64 (&i),
02508                 libhal_psi_get_uint64 (&i));
02509             break;
02510         case LIBHAL_PROPERTY_TYPE_BOOLEAN:
02511             printf ("    %s = %s (bool)\n", key,
02512                 (libhal_psi_get_bool (&i) ? "true" :
02513                  "false"));
02514             break;
02515         case LIBHAL_PROPERTY_TYPE_DOUBLE:
02516             printf ("    %s = %g (double)\n", key,
02517                 libhal_psi_get_double (&i));
02518             break;
02519         case LIBHAL_PROPERTY_TYPE_STRLIST:
02520         {
02521             unsigned int j;
02522             char **str_list;
02523 
02524             str_list = libhal_psi_get_strlist (&i);
02525             printf ("    %s = [", key);
02526             for (j = 0; str_list[j] != NULL; j++) {
02527                 printf ("'%s'", str_list[j]);
02528                 if (str_list[j+1] != NULL)
02529                     printf (", ");
02530             }
02531             printf ("] (string list)\n");
02532 
02533             break;
02534         }
02535         default:
02536             printf ("    *** unknown type for key %s\n", key);
02537             break;
02538         }
02539     }
02540 
02541     libhal_free_property_set (pset);
02542 
02543     return TRUE;
02544 }
02545 
02558 char **
02559 libhal_manager_find_device_string_match (LibHalContext *ctx, 
02560                      const char *key,
02561                      const char *value, int *num_devices, DBusError *error)
02562 {
02563     DBusMessage *message;
02564     DBusMessage *reply;
02565     DBusMessageIter iter, iter_array, reply_iter;
02566     char **hal_device_names;
02567     DBusError _error;
02568 
02569     LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
02570 
02571     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02572                         "/org/freedesktop/Hal/Manager",
02573                         "org.freedesktop.Hal.Manager",
02574                         "FindDeviceStringMatch");
02575     if (message == NULL) {
02576         fprintf (stderr,
02577              "%s %d : Couldn't allocate D-BUS message\n",
02578              __FILE__, __LINE__);
02579         return NULL;
02580     }
02581 
02582     dbus_message_iter_init_append (message, &iter);
02583     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
02584     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
02585 
02586     dbus_error_init (&_error);
02587     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02588                                message, -1,
02589                                &_error);
02590 
02591     dbus_move_error (&_error, error);
02592     if (error != NULL && dbus_error_is_set (error)) {
02593         dbus_message_unref (message);
02594         return NULL;
02595     }
02596     if (reply == NULL) {
02597         dbus_message_unref (message);
02598         return NULL;
02599     }
02600     /* now analyse reply */
02601     dbus_message_iter_init (reply, &reply_iter);
02602 
02603     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
02604         fprintf (stderr, "%s %d : wrong reply from hald.  Expecting an array.\n", __FILE__, __LINE__);
02605         return NULL;
02606     }
02607     
02608     dbus_message_iter_recurse (&reply_iter, &iter_array);
02609 
02610     hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
02611               
02612     dbus_message_unref (reply);
02613     dbus_message_unref (message);
02614 
02615     return hal_device_names;
02616 }
02617 
02618 
02629 dbus_bool_t
02630 libhal_device_add_capability (LibHalContext *ctx, 
02631                   const char *udi, const char *capability, DBusError *error)
02632 {
02633     DBusMessage *message;
02634     DBusMessage *reply;
02635     DBusMessageIter iter;
02636 
02637     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02638 
02639     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
02640                         "org.freedesktop.Hal.Device",
02641                         "AddCapability");
02642     if (message == NULL) {
02643         fprintf (stderr,
02644              "%s %d : Couldn't allocate D-BUS message\n",
02645              __FILE__, __LINE__);
02646         return FALSE;
02647     }
02648 
02649     dbus_message_iter_init_append (message, &iter);
02650     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability);
02651 
02652     
02653     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02654                                message, -1,
02655                                error);
02656     if (dbus_error_is_set (error)) {
02657         dbus_message_unref (message);
02658         return FALSE;
02659     }
02660 
02661     if (reply == NULL) {
02662         dbus_message_unref (message);
02663         return FALSE;
02664     }
02665 
02666     dbus_message_unref (reply);
02667     dbus_message_unref (message);
02668     return TRUE;
02669 }
02670 
02682 dbus_bool_t
02683 libhal_device_query_capability (LibHalContext *ctx, const char *udi, const char *capability, DBusError *error)
02684 {
02685     char **caps;
02686     unsigned int i;
02687     dbus_bool_t ret;
02688 
02689     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02690 
02691     ret = FALSE;
02692 
02693     caps = libhal_device_get_property_strlist (ctx, udi, "info.capabilities", error);
02694     if (caps != NULL) {
02695         for (i = 0; caps[i] != NULL; i++) {
02696             if (strcmp (caps[i], capability) == 0) {
02697                 ret = TRUE;
02698                 break;
02699             }
02700         }
02701         libhal_free_string_array (caps);
02702     }
02703 
02704     return ret;
02705 }
02706 
02717 char **
02718 libhal_find_device_by_capability (LibHalContext *ctx, 
02719                   const char *capability, int *num_devices, DBusError *error)
02720 {
02721     DBusMessage *message;
02722     DBusMessage *reply;
02723     DBusMessageIter iter, iter_array, reply_iter;
02724     char **hal_device_names;
02725     DBusError _error;
02726 
02727     LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
02728 
02729     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02730                         "/org/freedesktop/Hal/Manager",
02731                         "org.freedesktop.Hal.Manager",
02732                         "FindDeviceByCapability");
02733     if (message == NULL) {
02734         fprintf (stderr,
02735              "%s %d : Couldn't allocate D-BUS message\n",
02736              __FILE__, __LINE__);
02737         return NULL;
02738     }
02739 
02740     dbus_message_iter_init_append (message, &iter);
02741     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability);
02742 
02743     dbus_error_init (&_error);
02744     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02745                                message, -1,
02746                                &_error);
02747     
02748     dbus_move_error (&_error, error);
02749     if (error != NULL && dbus_error_is_set (error)) {
02750         dbus_message_unref (message);
02751         return NULL;
02752     }
02753     if (reply == NULL) {
02754         dbus_message_unref (message);
02755         return NULL;
02756     }
02757     /* now analyse reply */
02758     dbus_message_iter_init (reply, &reply_iter);
02759 
02760     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
02761         fprintf (stderr, "%s %d : wrong reply from hald.  Expecting an array.\n", __FILE__, __LINE__);
02762         return NULL;
02763     }
02764     
02765     dbus_message_iter_recurse (&reply_iter, &iter_array);
02766 
02767     hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
02768               
02769     dbus_message_unref (reply);
02770     dbus_message_unref (message);
02771 
02772     return hal_device_names;
02773 }
02774 
02783 dbus_bool_t
02784 libhal_device_property_watch_all (LibHalContext *ctx, DBusError *error)
02785 {
02786     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02787 
02788     dbus_bus_add_match (ctx->connection,
02789                 "type='signal',"
02790                 "interface='org.freedesktop.Hal.Device',"
02791                 "sender='org.freedesktop.Hal'", error);
02792     if (dbus_error_is_set (error)) {
02793         return FALSE;
02794     }
02795     return TRUE;
02796 }
02797 
02798 
02811 dbus_bool_t
02812 libhal_device_add_property_watch (LibHalContext *ctx, const char *udi, DBusError *error)
02813 {   
02814     char buf[512];
02815     
02816     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02817 
02818     snprintf (buf, 512,
02819           "type='signal',"
02820           "interface='org.freedesktop.Hal.Device',"
02821           "sender='org.freedesktop.Hal'," "path=%s", udi);
02822 
02823     dbus_bus_add_match (ctx->connection, buf, error);
02824     if (dbus_error_is_set (error)) {
02825         return FALSE;
02826     }
02827     return TRUE;
02828 }
02829 
02830 
02839 dbus_bool_t
02840 libhal_device_remove_property_watch (LibHalContext *ctx, const char *udi, DBusError *error)
02841 {   
02842     char buf[512];
02843     
02844     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02845 
02846     snprintf (buf, 512,
02847           "type='signal',"
02848           "interface='org.freedesktop.Hal.Device',"
02849           "sender='org.freedesktop.Hal'," "path=%s", udi);
02850 
02851     dbus_bus_remove_match (ctx->connection, buf, error);
02852     if (dbus_error_is_set (error)) {
02853         return FALSE;
02854     }
02855     return TRUE;
02856 }
02857 
02858 
02863 LibHalContext *
02864 libhal_ctx_new (void)
02865 {
02866     LibHalContext *ctx;
02867 
02868     if (!libhal_already_initialized_once) {
02869         bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
02870         bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
02871         
02872         libhal_already_initialized_once = TRUE;
02873     }
02874 
02875     ctx = calloc (1, sizeof (LibHalContext));
02876     if (ctx == NULL) {
02877         fprintf (stderr, 
02878              "%s %d : Failed to allocate %d bytes\n",
02879              __FILE__, __LINE__, sizeof (LibHalContext));
02880         return NULL;
02881     }
02882 
02883     ctx->is_initialized = FALSE;
02884     ctx->is_shutdown = FALSE;
02885     ctx->connection = NULL;
02886     ctx->is_direct = FALSE;
02887 
02888     return ctx;
02889 }
02890 
02900 dbus_bool_t
02901 libhal_ctx_set_cache (LibHalContext *ctx, dbus_bool_t use_cache)
02902 {
02903     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02904 
02905     ctx->cache_enabled = use_cache;
02906     return TRUE;
02907 }
02908 
02916 dbus_bool_t
02917 libhal_ctx_set_dbus_connection (LibHalContext *ctx, DBusConnection *conn)
02918 {
02919     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02920 
02921     if (conn == NULL)
02922         return FALSE;
02923 
02924     ctx->connection = conn;
02925     return TRUE;
02926 }
02927 
02936 dbus_bool_t 
02937 libhal_ctx_init (LibHalContext *ctx, DBusError *error)
02938 {
02939     DBusError _error;
02940     dbus_bool_t hald_exists;
02941 
02942     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02943 
02944     if (ctx->connection == NULL)
02945         return FALSE;
02946 
02947     dbus_error_init (&_error);
02948     hald_exists = dbus_bus_name_has_owner (ctx->connection, "org.freedesktop.Hal", &_error);
02949     dbus_move_error (&_error, error);
02950     if (error != NULL && dbus_error_is_set (error)) {
02951         return FALSE;
02952     }
02953 
02954     if (!hald_exists) {
02955         return FALSE;
02956     }
02957 
02958     
02959     if (!dbus_connection_add_filter (ctx->connection, filter_func, ctx, NULL)) {
02960         return FALSE;
02961     }
02962 
02963     dbus_bus_add_match (ctx->connection, 
02964                 "type='signal',"
02965                 "interface='org.freedesktop.Hal.Manager',"
02966                 "sender='org.freedesktop.Hal',"
02967                 "path='/org/freedesktop/Hal/Manager'", &_error);
02968     dbus_move_error (&_error, error);
02969     if (error != NULL && dbus_error_is_set (error)) {
02970         return FALSE;
02971     }
02972     ctx->is_initialized = TRUE;
02973     ctx->is_direct = FALSE;
02974 
02975     return TRUE;
02976 }
02977 
02984 LibHalContext *
02985 libhal_ctx_init_direct (DBusError *error)
02986 {
02987     char *hald_addr;
02988     LibHalContext *ctx;
02989     DBusError _error;
02990 
02991     ctx = libhal_ctx_new ();
02992     if (ctx == NULL)
02993         goto out;
02994 
02995     if (((hald_addr = getenv ("HALD_DIRECT_ADDR"))) == NULL) {
02996         libhal_ctx_free (ctx);
02997         ctx = NULL;
02998         goto out;
02999     }
03000 
03001     dbus_error_init (&_error);
03002     ctx->connection = dbus_connection_open (hald_addr, &_error);
03003     dbus_move_error (&_error, error);
03004     if (error != NULL && dbus_error_is_set (error)) {
03005         libhal_ctx_free (ctx);
03006         ctx = NULL;
03007         goto out;
03008     }
03009 
03010     ctx->is_initialized = TRUE;
03011     ctx->is_direct = TRUE;
03012 
03013 out:
03014     return ctx;
03015 }
03016 
03025 dbus_bool_t    
03026 libhal_ctx_shutdown (LibHalContext *ctx, DBusError *error)
03027 {   
03028     DBusError myerror;
03029 
03030     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03031 
03032     if (ctx->is_direct) {
03033         /* for some reason dbus_connection_set_exit_on_disconnect doesn't work yet so don't unref */
03034         /*dbus_connection_unref (ctx->connection);*/
03035     } else {
03036         dbus_error_init (&myerror);
03037         dbus_bus_remove_match (ctx->connection, 
03038                        "type='signal',"
03039                        "interface='org.freedesktop.Hal.Manager',"
03040                        "sender='org.freedesktop.Hal',"
03041                        "path='/org/freedesktop/Hal/Manager'", &myerror);
03042         if (dbus_error_is_set (&myerror)) {
03043             fprintf (stderr, "%s %d : Error unsubscribing to signals, error=%s\n", 
03044                  __FILE__, __LINE__, error->message);
03046         }
03047 
03048         /* TODO: remove other matches */
03049 
03050         dbus_connection_remove_filter (ctx->connection, filter_func, ctx);
03051     }
03052 
03053     ctx->is_initialized = FALSE;
03054 
03055     return TRUE;
03056 }
03057 
03063 dbus_bool_t    
03064 libhal_ctx_free (LibHalContext *ctx)
03065 {
03066     free (ctx);
03067     return TRUE;
03068 }
03069 
03077 dbus_bool_t
03078 libhal_ctx_set_device_added (LibHalContext *ctx, LibHalDeviceAdded callback)
03079 {
03080     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03081     
03082     ctx->device_added = callback;
03083     return TRUE;
03084 }
03085 
03093 dbus_bool_t
03094 libhal_ctx_set_device_removed (LibHalContext *ctx, LibHalDeviceRemoved callback)
03095 {
03096     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03097     
03098     ctx->device_removed = callback;
03099     return TRUE;
03100 }
03101 
03110 dbus_bool_t
03111 libhal_ctx_set_device_new_capability (LibHalContext *ctx, LibHalDeviceNewCapability callback)
03112 {
03113     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03114     
03115     ctx->device_new_capability = callback;
03116     return TRUE;
03117 }
03118 
03127 dbus_bool_t
03128 libhal_ctx_set_device_lost_capability (LibHalContext *ctx, LibHalDeviceLostCapability callback)
03129 {
03130     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03131     
03132     ctx->device_lost_capability = callback;
03133     return TRUE;
03134 }
03135 
03144 dbus_bool_t
03145 libhal_ctx_set_device_property_modified (LibHalContext *ctx, LibHalDevicePropertyModified callback)
03146 {
03147     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03148     
03149     ctx->device_property_modified = callback;
03150     return TRUE;
03151 }
03152 
03160 dbus_bool_t
03161 libhal_ctx_set_device_condition (LibHalContext *ctx, LibHalDeviceCondition callback)
03162 {
03163     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03164     
03165     ctx->device_condition = callback;
03166     return TRUE;
03167 }
03168 
03174 unsigned int libhal_string_array_length (char **str_array)
03175 {
03176     unsigned int i;
03177 
03178     if (str_array == NULL)
03179         return 0;
03180 
03181     for (i = 0; str_array[i] != NULL; i++)
03182         ;
03183 
03184     return i;
03185 }
03186 
03187 
03188 dbus_bool_t 
03189 libhal_device_rescan (LibHalContext *ctx, const char *udi, DBusError *error)
03190 {
03191     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03192     
03193     DBusMessage *message;
03194     DBusMessageIter reply_iter;
03195     DBusMessage *reply;
03196     dbus_bool_t result;
03197 
03198     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
03199                         "org.freedesktop.Hal.Device",
03200                         "Rescan");
03201 
03202     if (message == NULL) {
03203         fprintf (stderr,
03204              "%s %d : Couldn't allocate D-BUS message\n",
03205              __FILE__, __LINE__);
03206         return FALSE;
03207     }
03208     
03209     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
03210                                message, -1,
03211                                error);
03212 
03213     if (dbus_error_is_set (error)) {
03214         dbus_message_unref (message);
03215         return FALSE;
03216     }
03217 
03218     dbus_message_unref (message);
03219 
03220     if (reply == NULL)
03221         return FALSE;
03222 
03223     dbus_message_iter_init (reply, &reply_iter);
03224     if (dbus_message_iter_get_arg_type (&reply_iter) !=
03225            DBUS_TYPE_BOOLEAN) {
03226         dbus_message_unref (message);
03227         dbus_message_unref (reply);
03228         return FALSE;
03229     }
03230     dbus_message_iter_get_basic (&reply_iter, &result);
03231 
03232     dbus_message_unref (reply);
03233 
03234     return result;
03235 }
03236 
03237 dbus_bool_t
03238 libhal_device_reprobe (LibHalContext *ctx, const char *udi, DBusError *error)
03239 {
03240     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03241     
03242     DBusMessage *message;
03243     DBusMessageIter reply_iter;
03244     DBusMessage *reply;
03245     dbus_bool_t result;
03246 
03247     message = dbus_message_new_method_call ("org.freedesktop.Hal",
03248                         udi,
03249                         "org.freedesktop.Hal.Device",
03250                         "Reprobe");
03251 
03252     if (message == NULL) {
03253         fprintf (stderr,
03254              "%s %d : Couldn't allocate D-BUS message\n",
03255              __FILE__, __LINE__);
03256         return FALSE;
03257     }
03258     
03259     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
03260                                message, -1,
03261                                error);
03262 
03263     if (dbus_error_is_set (error)) {
03264         dbus_message_unref (message);
03265         return FALSE;
03266     }
03267 
03268     dbus_message_unref (message);
03269 
03270     if (reply == NULL)
03271         return FALSE;
03272 
03273     dbus_message_iter_init (reply, &reply_iter);
03274     if (dbus_message_iter_get_arg_type (&reply_iter) !=
03275            DBUS_TYPE_BOOLEAN) {
03276         dbus_message_unref (message);
03277         dbus_message_unref (reply);
03278         return FALSE;
03279     }
03280     dbus_message_iter_get_basic (&reply_iter, &result);
03281 
03282     dbus_message_unref (reply);
03283 
03284     return result;
03285 }
03286 
03298 dbus_bool_t libhal_device_emit_condition (LibHalContext *ctx,
03299                       const char *udi,
03300                       const char *condition_name,
03301                       const char *condition_details,
03302                       DBusError *error)
03303 {
03304     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03305     
03306     DBusMessage *message;
03307     DBusMessageIter iter;
03308     DBusMessageIter reply_iter;
03309     DBusMessage *reply;
03310     dbus_bool_t result;
03311 
03312     message = dbus_message_new_method_call ("org.freedesktop.Hal",
03313                         udi,
03314                         "org.freedesktop.Hal.Device",
03315                         "EmitCondition");
03316 
03317     if (message == NULL) {
03318         fprintf (stderr,
03319              "%s %d : Couldn't allocate D-BUS message\n",
03320              __FILE__, __LINE__);
03321         return FALSE;
03322     }
03323 
03324     dbus_message_iter_init_append (message, &iter);
03325     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &condition_name);
03326     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &condition_details);
03327     
03328     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
03329                                message, -1,
03330                                error);
03331 
03332     if (dbus_error_is_set (error)) {
03333         dbus_message_unref (message);
03334         return FALSE;
03335     }
03336 
03337     dbus_message_unref (message);
03338 
03339     if (reply == NULL)
03340         return FALSE;
03341 
03342     dbus_message_iter_init (reply, &reply_iter);
03343     if (dbus_message_iter_get_arg_type (&reply_iter) !=
03344            DBUS_TYPE_BOOLEAN) {
03345         dbus_message_unref (message);
03346         dbus_message_unref (reply);
03347         return FALSE;
03348     }
03349     dbus_message_iter_get_basic (&reply_iter, &result);
03350 
03351     dbus_message_unref (reply);
03352 
03353     return result;  
03354 }
03355 

Generated on Fri Jun 16 18:03:41 2006 for HAL by  doxygen 1.4.6