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             str_array[i] = NULL;
00084         }
00085         free (str_array);
00086         str_array = NULL;
00087     }
00088 }
00089 
00090 
00097 static char **
00098 libhal_get_string_array_from_iter (DBusMessageIter *iter, int *num_elements)
00099 {
00100     int count;
00101     char **buffer;
00102 
00103     count = 0;
00104     buffer = (char **)malloc (sizeof (char *) * 8);
00105 
00106     if (buffer == NULL)
00107         goto oom;
00108 
00109     buffer[0] = NULL;
00110     while (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING) {
00111         const char *value;
00112         char *str;
00113         
00114         if ((count % 8) == 0 && count != 0) {
00115             buffer = realloc (buffer, sizeof (char *) * (count + 8));
00116             if (buffer == NULL)
00117                 goto oom;
00118         }
00119         
00120         dbus_message_iter_get_basic (iter, &value);
00121         str = strdup (value);
00122         if (str == NULL)
00123             goto oom;
00124 
00125         buffer[count] = str;
00126 
00127         dbus_message_iter_next(iter);
00128         count++;
00129     }
00130 
00131     if ((count % 8) == 0) {
00132         buffer = realloc (buffer, sizeof (char *) * (count + 1));
00133         if (buffer == NULL)
00134             goto oom;
00135     }
00136 
00137     buffer[count] = NULL;
00138     if (num_elements != NULL)
00139         *num_elements = count;
00140     return buffer;
00141 
00142 oom:
00143     fprintf (stderr, "%s %d : error allocating memory\n", __FILE__, __LINE__);
00144     return NULL;
00145 
00146 }
00147 
00152 void
00153 libhal_free_string (char *str)
00154 {
00156     if (str != NULL) {
00157         free (str);
00158         str = NULL;
00159     }
00160 }
00161 
00162 
00164 struct LibHalPropertySet_s {
00165     unsigned int num_properties; 
00166     LibHalProperty *properties_head;
00169 };
00170 
00172 struct LibHalProperty_s {
00173     int type;            
00174     char *key;           
00177     union {
00178         char *str_value;     
00179         dbus_int32_t int_value;
00181         dbus_uint64_t uint64_value;
00183         double double_value; 
00184         dbus_bool_t bool_value;
00187         char **strlist_value; 
00188     };
00189 
00190     LibHalProperty *next;        
00192 };
00193 
00195 struct LibHalContext_s {
00196     DBusConnection *connection;           
00197     dbus_bool_t is_initialized;           
00198     dbus_bool_t is_shutdown;              
00199     dbus_bool_t cache_enabled;            
00200     dbus_bool_t is_direct;                
00203     LibHalDeviceAdded device_added;
00204 
00206     LibHalDeviceRemoved device_removed;
00207 
00209     LibHalDeviceNewCapability device_new_capability;
00210 
00212     LibHalDeviceLostCapability device_lost_capability;
00213 
00215     LibHalDevicePropertyModified device_property_modified;
00216 
00218     LibHalDeviceCondition device_condition;
00219 
00220     void *user_data;                      
00221 };
00222 
00230 dbus_bool_t
00231 libhal_ctx_set_user_data(LibHalContext *ctx, void *user_data)
00232 {
00233     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
00234     ctx->user_data = user_data;
00235     return TRUE;
00236 }
00237 
00244 void*
00245 libhal_ctx_get_user_data(LibHalContext *ctx)
00246 {
00247     LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
00248     return ctx->user_data;
00249 }
00250 
00251 
00257 static dbus_bool_t
00258 libhal_property_fill_value_from_variant (LibHalProperty *p, DBusMessageIter *var_iter)
00259 {
00260     DBusMessageIter iter_array;
00261     switch (p->type) {
00262     case DBUS_TYPE_ARRAY:
00263         if (dbus_message_iter_get_element_type (var_iter) != DBUS_TYPE_STRING)
00264             return FALSE;
00265 
00266         dbus_message_iter_recurse (var_iter, &iter_array);
00267         p->strlist_value = libhal_get_string_array_from_iter (&iter_array, NULL);
00268 
00269         p->type = LIBHAL_PROPERTY_TYPE_STRLIST; 
00270 
00271         break;
00272     case DBUS_TYPE_STRING:
00273     {
00274         const char *v;
00275 
00276         dbus_message_iter_get_basic (var_iter, &v);
00277 
00278         p->str_value = strdup (v);
00279         if (p->str_value == NULL) 
00280             return FALSE;
00281         p->type = LIBHAL_PROPERTY_TYPE_STRING; 
00282 
00283         break;
00284     }
00285     case DBUS_TYPE_INT32:
00286     {
00287         dbus_int32_t v;
00288         
00289         dbus_message_iter_get_basic (var_iter, &v);
00290         
00291         p->int_value = v;
00292         p->type = LIBHAL_PROPERTY_TYPE_INT32; 
00293 
00294         break;
00295     }
00296     case DBUS_TYPE_UINT64:
00297     {
00298         dbus_uint64_t v;
00299         
00300         dbus_message_iter_get_basic (var_iter, &v);
00301 
00302         p->uint64_value = v;
00303         p->type = LIBHAL_PROPERTY_TYPE_UINT64; 
00304         
00305         break;
00306     }
00307     case DBUS_TYPE_DOUBLE:
00308     {
00309         double v;
00310 
00311         dbus_message_iter_get_basic (var_iter, &v);
00312 
00313         p->double_value = v;
00314         p->type = LIBHAL_PROPERTY_TYPE_DOUBLE; 
00315 
00316         break;
00317     }
00318     case DBUS_TYPE_BOOLEAN:
00319     {
00320         double v;
00321 
00322         dbus_message_iter_get_basic (var_iter, &v);
00323 
00324         p->double_value = v;
00325         p->type = LIBHAL_PROPERTY_TYPE_BOOLEAN; 
00326 
00327         break;
00328     }
00329     default:
00331         break;
00332     }
00333 
00334     return TRUE;
00335 }
00336 
00346 LibHalPropertySet *
00347 libhal_device_get_all_properties (LibHalContext *ctx, const char *udi, DBusError *error)
00348 {   
00349     DBusMessage *message;
00350     DBusMessage *reply;
00351     DBusMessageIter reply_iter;
00352     DBusMessageIter dict_iter;
00353     LibHalPropertySet *result;
00354     LibHalProperty *p_last;
00355     DBusError _error;
00356 
00357     LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
00358     
00359     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
00360                         "org.freedesktop.Hal.Device",
00361                         "GetAllProperties");
00362 
00363     if (message == NULL) {
00364         fprintf (stderr,
00365              "%s %d : Couldn't allocate D-BUS message\n",
00366              __FILE__, __LINE__);
00367         return NULL;
00368     }
00369 
00370     dbus_error_init (&_error);
00371     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
00372                                message, -1,
00373                                &_error);
00374 
00375     dbus_move_error (&_error, error);
00376     if (error != NULL && dbus_error_is_set (error)) {
00377         fprintf (stderr,
00378              "%s %d : %s\n",
00379              __FILE__, __LINE__, error->message);
00380 
00381         dbus_message_unref (message);
00382         return NULL;
00383     }
00384 
00385     if (reply == NULL) {
00386         dbus_message_unref (message);
00387         return NULL;
00388     }
00389 
00390     dbus_message_iter_init (reply, &reply_iter);
00391 
00392     result = malloc (sizeof (LibHalPropertySet));
00393     if (result == NULL) 
00394         goto oom;
00395 /*
00396     result->properties = malloc(sizeof(LibHalProperty)*result->num_properties);
00397     if( result->properties==NULL )
00398     {
00400     return NULL;
00401     }
00402 */
00403 
00404     result->properties_head = NULL;
00405     result->num_properties = 0;
00406 
00407     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY  &&
00408         dbus_message_iter_get_element_type (&reply_iter) != DBUS_TYPE_DICT_ENTRY) {
00409         fprintf (stderr, "%s %d : error, expecting an array of dict entries\n",
00410              __FILE__, __LINE__);
00411         dbus_message_unref (message);
00412         dbus_message_unref (reply);
00413         return NULL;
00414     }
00415 
00416     dbus_message_iter_recurse (&reply_iter, &dict_iter);
00417 
00418     p_last = NULL;
00419 
00420     while (dbus_message_iter_get_arg_type (&dict_iter) == DBUS_TYPE_DICT_ENTRY)
00421     {
00422         DBusMessageIter dict_entry_iter, var_iter;
00423         const char *key;
00424         LibHalProperty *p;
00425 
00426         dbus_message_iter_recurse (&dict_iter, &dict_entry_iter);
00427 
00428         dbus_message_iter_get_basic (&dict_entry_iter, &key);
00429 
00430         p = malloc (sizeof (LibHalProperty));
00431         if (p == NULL)
00432             goto oom;
00433 
00434         p->next = NULL;
00435 
00436         if (result->num_properties == 0)
00437             result->properties_head = p;
00438 
00439         if (p_last != NULL)
00440             p_last->next = p;
00441 
00442         p_last = p;
00443 
00444         p->key = strdup (key);
00445         if (p->key == NULL)
00446             goto oom;
00447 
00448         dbus_message_iter_next (&dict_entry_iter);
00449 
00450         dbus_message_iter_recurse (&dict_entry_iter, &var_iter);
00451 
00452 
00453         p->type = dbus_message_iter_get_arg_type (&var_iter);
00454     
00455         result->num_properties++;
00456 
00457         if(!libhal_property_fill_value_from_variant (p, &var_iter))
00458             goto oom;
00459 
00460         dbus_message_iter_next (&dict_iter);
00461     }
00462 
00463     dbus_message_unref (message);
00464     dbus_message_unref (reply);
00465 
00466     return result;
00467 
00468 oom:
00469     fprintf (stderr,
00470         "%s %d : error allocating memory\n",
00471          __FILE__, __LINE__);
00473     return NULL;
00474 }
00475 
00480 void
00481 libhal_free_property_set (LibHalPropertySet * set)
00482 {
00483     LibHalProperty *p;
00484     LibHalProperty *q;
00485 
00486     if (set == NULL)
00487         return;
00488 
00489     for (p = set->properties_head; p != NULL; p = q) {
00490         free (p->key);
00491         if (p->type == DBUS_TYPE_STRING)
00492             free (p->str_value);
00493         if (p->type == LIBHAL_PROPERTY_TYPE_STRLIST)
00494             libhal_free_string_array (p->strlist_value);
00495         q = p->next;
00496         free (p);
00497     }
00498     free (set);
00499 }
00500 
00506 unsigned int 
00507 libhal_property_set_get_num_elems (LibHalPropertySet *set)
00508 {
00509     unsigned int num_elems;
00510     LibHalProperty *p;
00511 
00512     if (set == NULL)
00513         return 0;
00514     
00515     num_elems = 0;
00516     for (p = set->properties_head; p != NULL; p = p->next)
00517         num_elems++;
00518 
00519     return num_elems;
00520 }
00521 
00522 
00528 void
00529 libhal_psi_init (LibHalPropertySetIterator * iter, LibHalPropertySet * set)
00530 {
00531     if (set == NULL)
00532         return;
00533 
00534     iter->set = set;
00535     iter->index = 0;
00536     iter->cur_prop = set->properties_head;
00537 }
00538 
00539 
00546 dbus_bool_t
00547 libhal_psi_has_more (LibHalPropertySetIterator * iter)
00548 {
00549     return iter->index < iter->set->num_properties;
00550 }
00551 
00556 void
00557 libhal_psi_next (LibHalPropertySetIterator * iter)
00558 {
00559     iter->index++;
00560     iter->cur_prop = iter->cur_prop->next;
00561 }
00562 
00568 LibHalPropertyType
00569 libhal_psi_get_type (LibHalPropertySetIterator * iter)
00570 {
00571     return iter->cur_prop->type;
00572 }
00573 
00582 char *
00583 libhal_psi_get_key (LibHalPropertySetIterator * iter)
00584 {
00585     return iter->cur_prop->key;
00586 }
00587 
00596 char *
00597 libhal_psi_get_string (LibHalPropertySetIterator * iter)
00598 {
00599     return iter->cur_prop->str_value;
00600 }
00601 
00607 dbus_int32_t
00608 libhal_psi_get_int (LibHalPropertySetIterator * iter)
00609 {
00610     return iter->cur_prop->int_value;
00611 }
00612 
00618 dbus_uint64_t
00619 libhal_psi_get_uint64 (LibHalPropertySetIterator * iter)
00620 {
00621     return iter->cur_prop->uint64_value;
00622 }
00623 
00629 double
00630 libhal_psi_get_double (LibHalPropertySetIterator * iter)
00631 {
00632     return iter->cur_prop->double_value;
00633 }
00634 
00640 dbus_bool_t
00641 libhal_psi_get_bool (LibHalPropertySetIterator * iter)
00642 {
00643     return iter->cur_prop->bool_value;
00644 }
00645 
00651 char **
00652 libhal_psi_get_strlist (LibHalPropertySetIterator * iter)
00653 {
00654     return iter->cur_prop->strlist_value;
00655 }
00656 
00657 
00658 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00659 static DBusHandlerResult
00660 filter_func (DBusConnection * connection,
00661          DBusMessage * message, void *user_data)
00662 {
00663     const char *object_path;
00664     DBusError error;
00665     LibHalContext *ctx = (LibHalContext *) user_data;
00666 
00667     if (ctx->is_shutdown)
00668         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00669 
00670     dbus_error_init (&error);
00671 
00672     object_path = dbus_message_get_path (message);
00673 
00674     /*printf("*** in filter_func, object_path=%s\n", object_path);*/
00675 
00676     if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager",
00677                     "DeviceAdded")) {
00678         char *udi;
00679         if (dbus_message_get_args (message, &error,
00680                        DBUS_TYPE_STRING, &udi,
00681                        DBUS_TYPE_INVALID)) {
00682             if (ctx->device_added != NULL) {
00683                 ctx->device_added (ctx, udi);
00684             }
00685         }
00686         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00687     } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager", "DeviceRemoved")) {
00688         char *udi;
00689         if (dbus_message_get_args (message, &error,
00690                        DBUS_TYPE_STRING, &udi,
00691                        DBUS_TYPE_INVALID)) {
00692             if (ctx->device_removed != NULL) {
00693                 ctx->device_removed (ctx, udi);
00694             }
00695         }
00696         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00697     } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager","NewCapability")) {
00698         char *udi;
00699         char *capability;
00700         if (dbus_message_get_args (message, &error,
00701                        DBUS_TYPE_STRING, &udi,
00702                        DBUS_TYPE_STRING, &capability,
00703                        DBUS_TYPE_INVALID)) {
00704             if (ctx->device_new_capability != NULL) {
00705                 ctx->device_new_capability (ctx, udi, capability);
00706             }
00707         }
00708         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00709     } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "Condition")) {
00710         char *condition_name;
00711         char *condition_detail;
00712         if (dbus_message_get_args (message, &error,
00713                        DBUS_TYPE_STRING, &condition_name,
00714                        DBUS_TYPE_STRING, &condition_detail,
00715                        DBUS_TYPE_INVALID)) {
00716             if (ctx->device_condition != NULL) {
00717                 ctx->device_condition (ctx, object_path, condition_name, condition_detail);
00718             }
00719         }
00720         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00721     } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "PropertyModified")) {
00722         if (ctx->device_property_modified != NULL) {
00723             int i;
00724             char *key;
00725             dbus_bool_t removed;
00726             dbus_bool_t added;
00727             int num_modifications;
00728             DBusMessageIter iter;
00729             DBusMessageIter iter_array;
00730     
00731             dbus_message_iter_init (message, &iter);
00732             dbus_message_iter_get_basic (&iter, &num_modifications);
00733             dbus_message_iter_next (&iter);
00734 
00735             dbus_message_iter_recurse (&iter, &iter_array);
00736 
00737             for (i = 0; i < num_modifications; i++) {
00738                 DBusMessageIter iter_struct;
00739 
00740                 dbus_message_iter_recurse (&iter_array, &iter_struct);
00741 
00742                 dbus_message_iter_get_basic (&iter_struct, &key);
00743                 dbus_message_iter_next (&iter_struct);
00744                 dbus_message_iter_get_basic (&iter_struct, &removed);
00745                 dbus_message_iter_next (&iter_struct);
00746                 dbus_message_iter_get_basic (&iter_struct, &added);
00747                 
00748                 ctx->device_property_modified (ctx, 
00749                                    object_path,
00750                                    key, removed,
00751                                    added);
00752                 
00753                 dbus_message_iter_next (&iter_array);
00754             }
00755             
00756         }
00757         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00758     }
00759     
00760     LIBHAL_FREE_DBUS_ERROR(&error);
00761     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00762 }
00763 
00764 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
00765 
00766 /* for i18n purposes */
00767 static dbus_bool_t libhal_already_initialized_once = FALSE;
00768 
00769 #if 0
00770 
00788 LibHalContext*
00789 libhal_initialize (const LibHalFunctions * cb_functions,
00790         dbus_bool_t use_cache)
00791 {
00792     DBusError error;
00793     LibHalContext *ctx;
00794 
00795     if (!libhal_already_initialized_once) {
00796         bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
00797         bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
00798         
00799         libhal_already_initialized_once = TRUE;
00800     }
00801     
00802     ctx = malloc (sizeof (LibHalContext));
00803     if (ctx == NULL) {
00804         fprintf (stderr, "%s %d : Cannot allocated %d bytes!\n",
00805              __FILE__, __LINE__, sizeof (LibHalContext));
00806         return NULL;
00807     }
00808 
00809     ctx->is_initialized = FALSE;
00810     ctx->is_shutdown = FALSE;
00811 
00812     ctx->cache_enabled = use_cache;
00813 
00814     ctx->functions = cb_functions;
00815     /* allow caller to pass NULL */
00816     if (ctx->functions == NULL)
00817         ctx->functions = &libhal_null_functions;
00818 
00819     /* connect to hald service on the system bus */
00820     
00821     ctx->connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
00822     if (ctx->connection == NULL) {
00823         fprintf (stderr,
00824              "%s %d : Error connecting to system bus: %s\n",
00825              __FILE__, __LINE__, error.message);
00826         dbus_error_free (&error);
00827         return NULL;
00828     }
00829 
00830     if (ctx->main_loop_integration != NULL) {
00831 
00832         ctx->main_loop_integration (ctx, ctx->connection);
00833     }
00834 
00835     if (!dbus_connection_add_filter
00836         (ctx->connection, filter_func, ctx, NULL)) {
00837         fprintf (stderr,
00838              "%s %d : Error creating connection handler\r\n",
00839              __FILE__, __LINE__);
00841         return NULL;
00842     }
00843 
00844     dbus_bus_add_match (ctx->connection,
00845                 "type='signal',"
00846                 "interface='org.freedesktop.Hal.Manager',"
00847                 "sender='org.freedesktop.Hal',"
00848                 "path='/org/freedesktop/Hal/Manager'", &error);
00849     if (dbus_error_is_set (&error)) {
00850         fprintf (stderr, "%s %d : Error subscribing to signals, "
00851              "error=%s\r\n",
00852              __FILE__, __LINE__, error.message);
00854         return NULL;
00855     }
00856 
00857     ctx->is_initialized = TRUE;
00858     return ctx;
00859 }
00860 
00867 int
00868 libhal_shutdown (LibHalContext *ctx)
00869 {
00870     DBusError error;
00871 
00872     if (!ctx->is_initialized)
00873         return 1;
00874 
00875     /* unsubscribe the match rule we added in initialize; this is safe even with multiple
00876      * instances of libhal running - see the dbus docs */
00877     
00878     dbus_bus_remove_match (ctx->connection,
00879                    "type='signal',"
00880                    "interface='org.freedesktop.Hal.Manager',"
00881                    "sender='org.freedesktop.Hal',"
00882                    "path='/org/freedesktop/Hal/Manager'", &error);
00883     if (dbus_error_is_set (&error)) {
00884         fprintf (stderr, "%s %d : Error removing match rule, error=%s\r\n",
00885              __FILE__, __LINE__, error.message);
00886     }
00887 
00888     /* TODO: remove all other match rules */
00889 
00890     /* set a flag so we don't propagte callbacks from this context anymore */
00891     ctx->is_shutdown = TRUE;
00892 
00893     /* yikes, it's dangerous to unref the connection since it will terminate the process
00894      * because this connection may be shared so we cannot set the exit_on_disconnect flag
00895      *
00896      * so we don't do that right now 
00897      *
00898      */
00899     /*dbus_connection_unref (ctx->connection);*/
00900 
00901     /* we also refuse to free the resources as filter_function may reference these 
00902      * 
00903      * should free async when our connection goes away.
00904      */
00905     /* free (ctx); */
00906     return 0;
00907 }
00908 #endif
00909 
00921 char **
00922 libhal_get_all_devices (LibHalContext *ctx, int *num_devices, DBusError *error)
00923 {   
00924     DBusMessage *message;
00925     DBusMessage *reply;
00926     DBusMessageIter iter_array, reply_iter;
00927     char **hal_device_names;
00928     DBusError _error;
00929 
00930     LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
00931 
00932     *num_devices = 0;
00933 
00934     message = dbus_message_new_method_call ("org.freedesktop.Hal",
00935                         "/org/freedesktop/Hal/Manager",
00936                         "org.freedesktop.Hal.Manager",
00937                         "GetAllDevices");
00938     if (message == NULL) {
00939         fprintf (stderr, "%s %d : Could not allocate D-BUS message\n", __FILE__, __LINE__);
00940         return NULL;
00941     }
00942 
00943     dbus_error_init (&_error);
00944     reply = dbus_connection_send_with_reply_and_block (ctx->connection, message, -1, &_error);
00945 
00946     dbus_move_error (&_error, error);
00947     if (error != NULL && dbus_error_is_set (error)) {
00948         dbus_message_unref (message);
00949         return NULL;
00950     }
00951     if (reply == NULL) {
00952         dbus_message_unref (message);
00953         return NULL;
00954     }
00955 
00956     /* now analyze reply */
00957     dbus_message_iter_init (reply, &reply_iter);
00958 
00959     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
00960         fprintf (stderr, "%s %d : wrong reply from hald.  Expecting an array.\n", __FILE__, __LINE__);
00961         return NULL;
00962     }
00963     
00964     dbus_message_iter_recurse (&reply_iter, &iter_array);
00965 
00966     hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
00967               
00968     dbus_message_unref (reply);
00969     dbus_message_unref (message);
00970 
00971     return hal_device_names;
00972 }
00973 
00987 LibHalPropertyType
00988 libhal_device_get_property_type (LibHalContext *ctx, const char *udi, const char *key, DBusError *error)
00989 {
00990     DBusMessage *message;
00991     DBusMessage *reply;
00992     DBusMessageIter iter, reply_iter;
00993     int type;
00994     DBusError _error;
00995 
00996     LIBHAL_CHECK_LIBHALCONTEXT(ctx, LIBHAL_PROPERTY_TYPE_INVALID); // or return NULL?
00997     
00998     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
00999                         "org.freedesktop.Hal.Device",
01000                         "GetPropertyType");
01001     if (message == NULL) {
01002         fprintf (stderr, "%s %d : Couldn't allocate D-BUS message\n", __FILE__, __LINE__);
01003         return LIBHAL_PROPERTY_TYPE_INVALID;
01004     }
01005 
01006     dbus_message_iter_init_append (message, &iter);
01007     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01008 
01009     dbus_error_init (&_error);
01010     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01011                                message, -1,
01012                                &_error);
01013 
01014     dbus_move_error (&_error, error);
01015     if (error != NULL && dbus_error_is_set (error)) {
01016         dbus_message_unref (message);
01017         return LIBHAL_PROPERTY_TYPE_INVALID;
01018     }
01019     if (reply == NULL) {
01020         dbus_message_unref (message);
01021         return LIBHAL_PROPERTY_TYPE_INVALID;
01022     }
01023 
01024     dbus_message_iter_init (reply, &reply_iter);
01025     dbus_message_iter_get_basic (&reply_iter, &type);
01026 
01027     dbus_message_unref (message);
01028     dbus_message_unref (reply);
01029 
01030     return type;
01031 }
01032 
01048 char **
01049 libhal_device_get_property_strlist (LibHalContext *ctx, const char *udi, const char *key, DBusError *error)
01050 {   
01051     DBusMessage *message;
01052     DBusMessage *reply;
01053     DBusMessageIter iter, iter_array, reply_iter;
01054     char **our_strings;
01055     DBusError _error;
01056     
01057     LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
01058 
01059     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01060                         "org.freedesktop.Hal.Device",
01061                         "GetPropertyStringList");
01062     if (message == NULL) {
01063         fprintf (stderr,
01064              "%s %d : Couldn't allocate D-BUS message\n",
01065              __FILE__, __LINE__);
01066         return NULL;
01067     }
01068 
01069     dbus_message_iter_init_append (message, &iter);
01070     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01071 
01072     dbus_error_init (&_error);
01073     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01074                                message, -1,
01075                                &_error);
01076 
01077     dbus_move_error (&_error, error);
01078     if (error != NULL && dbus_error_is_set (error)) {
01079         dbus_message_unref (message);
01080         return NULL;
01081     }
01082     if (reply == NULL) {
01083         dbus_message_unref (message);
01084         return NULL;
01085     }
01086     /* now analyse reply */
01087     dbus_message_iter_init (reply, &reply_iter);
01088 
01089     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
01090         fprintf (stderr, "%s %d : wrong reply from hald.  Expecting an array.\n", __FILE__, __LINE__);
01091         return NULL;
01092     }
01093     
01094     dbus_message_iter_recurse (&reply_iter, &iter_array);
01095 
01096     our_strings = libhal_get_string_array_from_iter (&iter_array, NULL);
01097               
01098     dbus_message_unref (reply);
01099     dbus_message_unref (message);
01100 
01101     return our_strings;
01102 }
01103 
01117 char *
01118 libhal_device_get_property_string (LibHalContext *ctx,
01119                    const char *udi, const char *key, DBusError *error)
01120 {   
01121     DBusMessage *message;
01122     DBusMessage *reply;
01123     DBusMessageIter iter, reply_iter;
01124     char *value;
01125     char *dbus_str;
01126     DBusError _error;
01127 
01128     LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
01129 
01130     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01131                         "org.freedesktop.Hal.Device",
01132                         "GetPropertyString");
01133 
01134     if (message == NULL) {
01135         fprintf (stderr,
01136              "%s %d : Couldn't allocate D-BUS message\n",
01137              __FILE__, __LINE__);
01138         return NULL;
01139     }
01140 
01141     dbus_message_iter_init_append (message, &iter);
01142     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01143 
01144     dbus_error_init (&_error);
01145     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01146                                message, -1,
01147                                &_error);
01148 
01149     dbus_move_error (&_error, error);
01150     if (error != NULL && dbus_error_is_set (error)) {
01151         dbus_message_unref (message);
01152         return NULL;
01153     }
01154     if (reply == NULL) {
01155         dbus_message_unref (message);
01156         return NULL;
01157     }
01158 
01159     dbus_message_iter_init (reply, &reply_iter);
01160 
01161     /* now analyze reply */
01162     if (dbus_message_iter_get_arg_type (&reply_iter) !=
01163            DBUS_TYPE_STRING) {
01164         dbus_message_unref (message);
01165         dbus_message_unref (reply);
01166         return NULL;
01167     }
01168 
01169     dbus_message_iter_get_basic (&reply_iter, &dbus_str);
01170     value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
01171     if (value == NULL) {
01172         fprintf (stderr, "%s %d : error allocating memory\n",
01173              __FILE__, __LINE__);
01175         return NULL;
01176     }
01177 
01178     dbus_message_unref (message);
01179     dbus_message_unref (reply);
01180     return value;
01181 }
01182 
01192 dbus_int32_t
01193 libhal_device_get_property_int (LibHalContext *ctx, 
01194                 const char *udi, const char *key, DBusError *error)
01195 {
01196     DBusMessage *message;
01197     DBusMessage *reply;
01198     DBusMessageIter iter, reply_iter;
01199     dbus_int32_t value;
01200     DBusError _error;
01201 
01202     LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1);
01203 
01204     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01205                         "org.freedesktop.Hal.Device",
01206                         "GetPropertyInteger");
01207     if (message == NULL) {
01208         fprintf (stderr,
01209              "%s %d : Couldn't allocate D-BUS message\n",
01210              __FILE__, __LINE__);
01211         return -1;
01212     }
01213 
01214     dbus_message_iter_init_append (message, &iter);
01215     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01216 
01217     dbus_error_init (&_error);
01218     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01219                                message, -1,
01220                                &_error);
01221 
01222     dbus_move_error (&_error, error);
01223     if (error != NULL && dbus_error_is_set (error)) {
01224         dbus_message_unref (message);
01225         return -1;
01226     }
01227     if (reply == NULL) {
01228         dbus_message_unref (message);
01229         return -1;
01230     }
01231 
01232     dbus_message_iter_init (reply, &reply_iter);
01233 
01234     /* now analyze reply */
01235     if (dbus_message_iter_get_arg_type (&reply_iter) !=
01236            DBUS_TYPE_INT32) {
01237         fprintf (stderr,
01238              "%s %d : property '%s' for device '%s' is not "
01239              "of type integer\n", __FILE__, __LINE__, key,
01240              udi);
01241         dbus_message_unref (message);
01242         dbus_message_unref (reply);
01243         return -1;
01244     }
01245     dbus_message_iter_get_basic (&reply_iter, &value);
01246 
01247     dbus_message_unref (message);
01248     dbus_message_unref (reply);
01249     return value;
01250 }
01251 
01261 dbus_uint64_t
01262 libhal_device_get_property_uint64 (LibHalContext *ctx, 
01263                    const char *udi, const char *key, DBusError *error)
01264 {
01265     DBusMessage *message;
01266     DBusMessage *reply;
01267     DBusMessageIter iter, reply_iter;
01268     dbus_uint64_t value;
01269     DBusError _error;
01270 
01271     LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1);
01272 
01273     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01274                         "org.freedesktop.Hal.Device",
01275                         "GetPropertyInteger");
01276     if (message == NULL) {
01277         fprintf (stderr,
01278              "%s %d : Couldn't allocate D-BUS message\n",
01279              __FILE__, __LINE__);
01280         return -1;
01281     }
01282 
01283     dbus_message_iter_init_append (message, &iter);
01284     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01285 
01286     dbus_error_init (&_error);
01287     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01288                                message, -1,
01289                                &_error);
01290     
01291     dbus_move_error (&_error, error);
01292     if (error != NULL && dbus_error_is_set (error)) {
01293         dbus_message_unref (message);
01294         return -1;
01295     }
01296     if (reply == NULL) {
01297         dbus_message_unref (message);
01298         return -1;
01299     }
01300 
01301     dbus_message_iter_init (reply, &reply_iter);
01302     /* now analyze reply */
01303     if (dbus_message_iter_get_arg_type (&reply_iter) !=
01304            DBUS_TYPE_UINT64) {
01305         fprintf (stderr,
01306              "%s %d : property '%s' for device '%s' is not "
01307              "of type integer\n", __FILE__, __LINE__, key,
01308              udi);
01309         dbus_message_unref (message);
01310         dbus_message_unref (reply);
01311         return -1;
01312     }
01313     dbus_message_iter_get_basic (&reply_iter, &value);
01314 
01315     dbus_message_unref (message);
01316     dbus_message_unref (reply);
01317     return value;
01318 }
01319 
01329 double
01330 libhal_device_get_property_double (LibHalContext *ctx, 
01331                    const char *udi, const char *key, DBusError *error)
01332 {
01333     DBusMessage *message;
01334     DBusMessage *reply;
01335     DBusMessageIter iter, reply_iter;
01336     double value;
01337     DBusError _error;
01338 
01339     LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1.0);
01340 
01341     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01342                         "org.freedesktop.Hal.Device",
01343                         "GetPropertyDouble");
01344     if (message == NULL) {
01345         fprintf (stderr,
01346              "%s %d : Couldn't allocate D-BUS message\n",
01347              __FILE__, __LINE__);
01348         return -1.0f;
01349     }
01350 
01351     dbus_message_iter_init_append (message, &iter);
01352     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01353 
01354     dbus_error_init (&_error);
01355     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01356                                message, -1,
01357                                &_error);
01358 
01359     dbus_move_error (&_error, error);
01360     if (error != NULL && dbus_error_is_set (error)) {
01361         dbus_message_unref (message);
01362         return -1.0f;
01363     }
01364     if (reply == NULL) {
01365         dbus_message_unref (message);
01366         return -1.0f;
01367     }
01368 
01369     dbus_message_iter_init (reply, &reply_iter);
01370 
01371     /* now analyze reply */
01372     if (dbus_message_iter_get_arg_type (&reply_iter) !=
01373            DBUS_TYPE_DOUBLE) {
01374         fprintf (stderr,
01375              "%s %d : property '%s' for device '%s' is not "
01376              "of type double\n", __FILE__, __LINE__, key, udi);
01377         dbus_message_unref (message);
01378         dbus_message_unref (reply);
01379         return -1.0f;
01380     }
01381     dbus_message_iter_get_basic (&reply_iter, &value);
01382 
01383     dbus_message_unref (message);
01384     dbus_message_unref (reply);
01385     return (double) value;
01386 }
01387 
01397 dbus_bool_t
01398 libhal_device_get_property_bool (LibHalContext *ctx, 
01399                  const char *udi, const char *key, DBusError *error)
01400 {
01401     DBusMessage *message;
01402     DBusMessage *reply;
01403     DBusMessageIter iter, reply_iter;
01404     dbus_bool_t value;
01405     DBusError _error;
01406 
01407     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
01408 
01409     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01410                         "org.freedesktop.Hal.Device",
01411                         "GetPropertyBoolean");
01412     if (message == NULL) {
01413         fprintf (stderr,
01414              "%s %d : Couldn't allocate D-BUS message\n",
01415              __FILE__, __LINE__);
01416         return FALSE;
01417     }
01418 
01419     dbus_message_iter_init_append (message, &iter);
01420     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01421     
01422     dbus_error_init (&_error);
01423     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01424                                message, -1,
01425                                &_error);
01426 
01427     dbus_move_error (&_error, error);
01428     if (error != NULL && dbus_error_is_set (error)) {
01429         dbus_message_unref (message);
01430         return FALSE;
01431     }
01432     if (reply == NULL) {
01433         dbus_message_unref (message);
01434         return FALSE;
01435     }
01436 
01437     dbus_message_iter_init (reply, &reply_iter);
01438 
01439     /* now analyze reply */
01440     if (dbus_message_iter_get_arg_type (&reply_iter) !=
01441            DBUS_TYPE_BOOLEAN) {
01442         fprintf (stderr,
01443              "%s %d : property '%s' for device '%s' is not "
01444              "of type bool\n", __FILE__, __LINE__, key, udi);
01445         dbus_message_unref (message);
01446         dbus_message_unref (reply);
01447         return FALSE;
01448     }
01449     dbus_message_iter_get_basic (&reply_iter, &value);
01450 
01451     dbus_message_unref (message);
01452     dbus_message_unref (reply);
01453     return value;
01454 }
01455 
01456 
01457 /* generic helper */
01458 static dbus_bool_t
01459 libhal_device_set_property_helper (LibHalContext *ctx, 
01460                    const char *udi,
01461                    const char *key,
01462                    int type,
01463                    const char *str_value,
01464                    dbus_int32_t int_value,
01465                    dbus_uint64_t uint64_value,
01466                    double double_value,
01467                    dbus_bool_t bool_value,
01468                    DBusError *error)
01469 {
01470     DBusMessage *message;
01471     DBusMessage *reply;
01472     DBusMessageIter iter;
01473     char *method_name = NULL;
01474 
01475     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
01476     
01478     switch (type) {
01479     case DBUS_TYPE_INVALID:
01480         method_name = "RemoveProperty";
01481         break;
01482     case DBUS_TYPE_STRING:
01483         method_name = "SetPropertyString";
01484         break;
01485     case DBUS_TYPE_INT32:
01486     case DBUS_TYPE_UINT64:
01487         method_name = "SetPropertyInteger";
01488         break;
01489     case DBUS_TYPE_DOUBLE:
01490         method_name = "SetPropertyDouble";
01491         break;
01492     case DBUS_TYPE_BOOLEAN:
01493         method_name = "SetPropertyBoolean";
01494         break;
01495 
01496     default:
01497         /* cannot happen; is not callable from outside this file */
01498         break;
01499     }
01500 
01501     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01502                         "org.freedesktop.Hal.Device",
01503                         method_name);
01504     if (message == NULL) {
01505         fprintf (stderr,
01506              "%s %d : Couldn't allocate D-BUS message\n",
01507              __FILE__, __LINE__);
01508         return FALSE;
01509     }
01510 
01511     dbus_message_iter_init_append (message, &iter);
01512     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01513     switch (type) {
01514     case DBUS_TYPE_STRING:
01515         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &str_value);
01516         break;
01517     case DBUS_TYPE_INT32:
01518         dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &int_value);
01519         break;
01520     case DBUS_TYPE_UINT64:
01521         dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT64, &uint64_value);
01522         break;
01523     case DBUS_TYPE_DOUBLE:
01524         dbus_message_iter_append_basic (&iter, DBUS_TYPE_DOUBLE, &double_value);
01525         break;
01526     case DBUS_TYPE_BOOLEAN:
01527         dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &bool_value);
01528         break;
01529     }
01530 
01531     
01532     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01533                                message, -1,
01534                                error);
01535     if (dbus_error_is_set (error)) {
01536         dbus_message_unref (message);
01537         return FALSE;
01538     }
01539 
01540     if (reply == NULL) {
01541         dbus_message_unref (message);
01542         return FALSE;
01543     }
01544 
01545     dbus_message_unref (message);
01546     dbus_message_unref (reply);
01547 
01548     return TRUE;
01549 }
01550 
01563 dbus_bool_t
01564 libhal_device_set_property_string (LibHalContext *ctx, 
01565                    const char *udi,
01566                    const char *key, 
01567                    const char *value,
01568                    DBusError *error)
01569 {
01570     return libhal_device_set_property_helper (ctx, udi, key,
01571                           DBUS_TYPE_STRING,
01572                           value, 0, 0, 0.0f, FALSE, error);
01573 }
01574 
01587 dbus_bool_t
01588 libhal_device_set_property_int (LibHalContext *ctx, const char *udi,
01589                 const char *key, dbus_int32_t value, DBusError *error)
01590 {
01591     return libhal_device_set_property_helper (ctx, udi, key,
01592                           DBUS_TYPE_INT32,
01593                           NULL, value, 0, 0.0f, FALSE, error);
01594 }
01595 
01608 dbus_bool_t
01609 libhal_device_set_property_uint64 (LibHalContext *ctx, const char *udi,
01610                    const char *key, dbus_uint64_t value, DBusError *error)
01611 {
01612     return libhal_device_set_property_helper (ctx, udi, key,
01613                           DBUS_TYPE_UINT64,
01614                           NULL, 0, value, 0.0f, FALSE, error);
01615 }
01616 
01629 dbus_bool_t
01630 libhal_device_set_property_double (LibHalContext *ctx, const char *udi,
01631                    const char *key, double value, DBusError *error)
01632 {
01633     return libhal_device_set_property_helper (ctx, udi, key,
01634                           DBUS_TYPE_DOUBLE,
01635                           NULL, 0, 0, value, FALSE, error);
01636 }
01637 
01650 dbus_bool_t
01651 libhal_device_set_property_bool (LibHalContext *ctx, const char *udi,
01652                  const char *key, dbus_bool_t value, DBusError *error)
01653 {
01654     return libhal_device_set_property_helper (ctx, udi, key,
01655                           DBUS_TYPE_BOOLEAN,
01656                           NULL, 0, 0, 0.0f, value, error);
01657 }
01658 
01659 
01670 dbus_bool_t
01671 libhal_device_remove_property (LibHalContext *ctx, 
01672                    const char *udi, const char *key, DBusError *error)
01673 {
01674     return libhal_device_set_property_helper (ctx, udi, key, DBUS_TYPE_INVALID, 
01675                           /* DBUS_TYPE_INVALID means remove */
01676                           NULL, 0, 0, 0.0f, FALSE, error);
01677 }
01678 
01691 dbus_bool_t
01692 libhal_device_property_strlist_append (LibHalContext *ctx, 
01693                        const char *udi,
01694                        const char *key,
01695                        const char *value,
01696                        DBusError *error)
01697 {
01698     DBusMessage *message;
01699     DBusMessage *reply;
01700     DBusMessageIter iter;
01701 
01702     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
01703 
01704     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01705                         "org.freedesktop.Hal.Device",
01706                         "StringListAppend");
01707     if (message == NULL) {
01708         fprintf (stderr,
01709              "%s %d : Couldn't allocate D-BUS message\n",
01710              __FILE__, __LINE__);
01711         return FALSE;
01712     }
01713     dbus_message_iter_init_append (message, &iter);
01714     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01715     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
01716     
01717     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01718                                message, -1,
01719                                error);
01720     if (dbus_error_is_set (error)) {
01721         dbus_message_unref (message);
01722         return FALSE;
01723     }
01724     if (reply == NULL) {
01725         dbus_message_unref (message);
01726         return FALSE;
01727     }
01728     return TRUE;
01729 }
01730 
01743 dbus_bool_t
01744 libhal_device_property_strlist_prepend (LibHalContext *ctx, 
01745                     const char *udi,
01746                     const char *key,
01747                     const char *value, 
01748                     DBusError *error)
01749 {
01750     DBusMessage *message;
01751     DBusMessage *reply;
01752     DBusMessageIter iter;
01753 
01754     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
01755 
01756     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01757                         "org.freedesktop.Hal.Device",
01758                         "StringListPrepend");
01759     if (message == NULL) {
01760         fprintf (stderr,
01761              "%s %d : Couldn't allocate D-BUS message\n",
01762              __FILE__, __LINE__);
01763         return FALSE;
01764     }
01765     dbus_message_iter_init_append (message, &iter);
01766     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01767     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
01768     
01769     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01770                                message, -1,
01771                                error);
01772     if (dbus_error_is_set (error)) {
01773         dbus_message_unref (message);
01774         return FALSE;
01775     }
01776     if (reply == NULL) {
01777         dbus_message_unref (message);
01778         return FALSE;
01779     }
01780     return TRUE;
01781 }
01782 
01795 dbus_bool_t
01796 libhal_device_property_strlist_remove_index (LibHalContext *ctx, 
01797                          const char *udi,
01798                          const char *key,
01799                          unsigned int index,
01800                          DBusError *error)
01801 {
01802     DBusMessage *message;
01803     DBusMessage *reply;
01804     DBusMessageIter iter;
01805 
01806     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
01807 
01808     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01809                         "org.freedesktop.Hal.Device",
01810                         "StringListRemoveIndex");
01811     if (message == NULL) {
01812         fprintf (stderr,
01813              "%s %d : Couldn't allocate D-BUS message\n",
01814              __FILE__, __LINE__);
01815         return FALSE;
01816     }
01817     dbus_message_iter_init_append (message, &iter);
01818     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01819     dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &index);
01820     
01821     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01822                                message, -1,
01823                                error);
01824     if (dbus_error_is_set (error)) {
01825         dbus_message_unref (message);
01826         return FALSE;
01827     }
01828     if (reply == NULL) {
01829         dbus_message_unref (message);
01830         return FALSE;
01831     }
01832     return TRUE;
01833 }
01834 
01847 dbus_bool_t
01848 libhal_device_property_strlist_remove (LibHalContext *ctx, 
01849                        const char *udi,
01850                        const char *key,
01851                        const char *value, DBusError *error)
01852 {
01853     DBusMessage *message;
01854     DBusMessage *reply;
01855     DBusMessageIter iter;
01856 
01857     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
01858 
01859     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01860                         "org.freedesktop.Hal.Device",
01861                         "StringListRemove");
01862     if (message == NULL) {
01863         fprintf (stderr,
01864              "%s %d : Couldn't allocate D-BUS message\n",
01865              __FILE__, __LINE__);
01866         return FALSE;
01867     }
01868     dbus_message_iter_init_append (message, &iter);
01869     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01870     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
01871     
01872     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01873                                message, -1,
01874                                error);
01875     if (dbus_error_is_set (error)) {
01876         dbus_message_unref (message);
01877         return FALSE;
01878     }
01879     if (reply == NULL) {
01880         dbus_message_unref (message);
01881         return FALSE;
01882     }
01883     return TRUE;
01884 }
01885 
01886 
01901 dbus_bool_t
01902 libhal_device_lock (LibHalContext *ctx,
01903             const char *udi,
01904             const char *reason_to_lock,
01905             char **reason_why_locked, DBusError *error)
01906 {
01907     DBusMessage *message;
01908     DBusMessageIter iter;
01909     DBusMessage *reply;
01910 
01911     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
01912 
01913     if (reason_why_locked != NULL)
01914         *reason_why_locked = NULL;
01915 
01916     message = dbus_message_new_method_call ("org.freedesktop.Hal",
01917                         udi,
01918                         "org.freedesktop.Hal.Device",
01919                         "Lock");
01920 
01921     if (message == NULL) {
01922         fprintf (stderr,
01923              "%s %d : Couldn't allocate D-BUS message\n",
01924              __FILE__, __LINE__);
01925         return FALSE;
01926     }
01927 
01928     dbus_message_iter_init_append (message, &iter);
01929     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &reason_to_lock);
01930 
01931     
01932     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01933                                message, -1,
01934                                error);
01935 
01936     if (dbus_error_is_set (error)) {
01937         if (strcmp (error->name,
01938                 "org.freedesktop.Hal.DeviceAlreadyLocked") == 0) {
01939             if (reason_why_locked != NULL) {
01940                 *reason_why_locked =
01941                     dbus_malloc0 (strlen (error->message) + 1);
01942                 strcpy (*reason_why_locked, error->message);
01943             }
01944         }
01945 
01946         dbus_message_unref (message);
01947         return FALSE;
01948     }
01949 
01950     dbus_message_unref (message);
01951 
01952     if (reply == NULL)
01953         return FALSE;
01954 
01955     dbus_message_unref (reply);
01956 
01957     return TRUE;
01958 }
01959 
01969 dbus_bool_t
01970 libhal_device_unlock (LibHalContext *ctx,
01971               const char *udi, DBusError *error)
01972 {
01973     DBusMessage *message;
01974     DBusMessage *reply;
01975 
01976     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
01977 
01978     message = dbus_message_new_method_call ("org.freedesktop.Hal",
01979                         udi,
01980                         "org.freedesktop.Hal.Device",
01981                         "Unlock");
01982 
01983     if (message == NULL) {
01984         fprintf (stderr,
01985              "%s %d : Couldn't allocate D-BUS message\n",
01986              __FILE__, __LINE__);
01987         return FALSE;
01988     }
01989 
01990     
01991     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01992                                message, -1,
01993                                error);
01994 
01995     if (dbus_error_is_set (error)) {
01996         dbus_message_unref (message);
01997         return FALSE;
01998     }
01999 
02000     dbus_message_unref (message);
02001 
02002     if (reply == NULL)
02003         return FALSE;
02004 
02005     dbus_message_unref (reply);
02006 
02007     return TRUE;
02008 }
02009 
02010 
02024 char *
02025 libhal_new_device (LibHalContext *ctx, DBusError *error)
02026 {
02027     DBusMessage *message;
02028     DBusMessage *reply;
02029     DBusMessageIter reply_iter;
02030     char *value;
02031     char *dbus_str;
02032 
02033     LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
02034 
02035     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02036                         "/org/freedesktop/Hal/Manager",
02037                         "org.freedesktop.Hal.Manager",
02038                         "NewDevice");
02039     if (message == NULL) {
02040         fprintf (stderr,
02041              "%s %d : Couldn't allocate D-BUS message\n",
02042              __FILE__, __LINE__);
02043         return NULL;
02044     }
02045 
02046     
02047     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02048                                message, -1,
02049                                error);
02050     if (dbus_error_is_set (error)) {
02051         dbus_message_unref (message);
02052         return NULL;
02053     }
02054     if (reply == NULL) {
02055         dbus_message_unref (message);
02056         return NULL;
02057     }
02058 
02059     dbus_message_iter_init (reply, &reply_iter);
02060 
02061     /* now analyze reply */
02062     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_STRING) {
02063         fprintf (stderr,
02064              "%s %d : expected a string in reply to NewDevice\n",
02065              __FILE__, __LINE__);
02066         dbus_message_unref (message);
02067         dbus_message_unref (reply);
02068         return NULL;
02069     }
02070 
02071     dbus_message_iter_get_basic (&reply_iter, &dbus_str);
02072     value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
02073     if (value == NULL) {
02074         fprintf (stderr, "%s %d : error allocating memory\n",
02075              __FILE__, __LINE__);
02076     }
02077 
02078     dbus_message_unref (message);
02079     dbus_message_unref (reply);
02080     return value;
02081 }
02082 
02083 
02104 dbus_bool_t
02105 libhal_device_commit_to_gdl (LibHalContext *ctx, 
02106                  const char *temp_udi, const char *udi, DBusError *error)
02107 {
02108     DBusMessage *message;
02109     DBusMessage *reply;
02110     DBusMessageIter iter;
02111 
02112     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02113 
02114     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02115                         "/org/freedesktop/Hal/Manager",
02116                         "org.freedesktop.Hal.Manager",
02117                         "CommitToGdl");
02118     if (message == NULL) {
02119         fprintf (stderr,
02120              "%s %d : Couldn't allocate D-BUS message\n",
02121              __FILE__, __LINE__);
02122         return FALSE;
02123     }
02124 
02125     dbus_message_iter_init_append (message, &iter);
02126     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &temp_udi);
02127     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
02128 
02129     
02130     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02131                                message, -1,
02132                                error);
02133     if (dbus_error_is_set (error)) {
02134         dbus_message_unref (message);
02135         return FALSE;
02136     }
02137     if (reply == NULL) {
02138         dbus_message_unref (message);
02139         return FALSE;
02140     }
02141 
02142     dbus_message_unref (message);
02143     dbus_message_unref (reply);
02144     return TRUE;
02145 }
02146 
02160 dbus_bool_t
02161 libhal_remove_device (LibHalContext *ctx, const char *udi, DBusError *error)
02162 {
02163     DBusMessage *message;
02164     DBusMessage *reply;
02165     DBusMessageIter iter;
02166 
02167     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02168 
02169     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02170                         "/org/freedesktop/Hal/Manager",
02171                         "org.freedesktop.Hal.Manager",
02172                         "Remove");
02173     if (message == NULL) {
02174         fprintf (stderr,
02175              "%s %d : Couldn't allocate D-BUS message\n",
02176              __FILE__, __LINE__);
02177         return FALSE;
02178     }
02179 
02180     dbus_message_iter_init_append (message, &iter);
02181     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
02182 
02183     
02184     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02185                                message, -1,
02186                                error);
02187     if (dbus_error_is_set (error)) {
02188         dbus_message_unref (message);
02189         return FALSE;
02190     }
02191     if (reply == NULL) {
02192         dbus_message_unref (message);
02193         return FALSE;
02194     }
02195 
02196     dbus_message_unref (message);
02197     dbus_message_unref (reply);
02198     return TRUE;
02199 }
02200 
02209 dbus_bool_t
02210 libhal_device_exists (LibHalContext *ctx, const char *udi, DBusError *error)
02211 {
02212     DBusMessage *message;
02213     DBusMessage *reply;
02214     DBusMessageIter iter, reply_iter;
02215     dbus_bool_t value;
02216     DBusError _error;
02217 
02218     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02219 
02220     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02221                         "/org/freedesktop/Hal/Manager",
02222                         "org.freedesktop.Hal.Manager",
02223                         "DeviceExists");
02224     if (message == NULL) {
02225         fprintf (stderr,
02226              "%s %d : Couldn't allocate D-BUS message\n",
02227              __FILE__, __LINE__);
02228         return FALSE;
02229     }
02230 
02231     dbus_message_iter_init_append (message, &iter);
02232     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
02233 
02234     dbus_error_init (&_error);
02235     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02236                                message, -1,
02237                                &_error);
02238 
02239     dbus_move_error (&_error, error);
02240     if (error != NULL && dbus_error_is_set (error)) {
02241         dbus_message_unref (message);
02242         return FALSE;
02243     }
02244     if (reply == NULL) {
02245         dbus_message_unref (message);
02246         return FALSE;
02247     }
02248 
02249     dbus_message_iter_init (reply, &reply_iter);
02250 
02251     /* now analyze reply */
02252     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
02253         fprintf (stderr,
02254              "%s %d : expected a bool in reply to DeviceExists\n",
02255              __FILE__, __LINE__);
02256         dbus_message_unref (message);
02257         dbus_message_unref (reply);
02258         return FALSE;
02259     }
02260 
02261     dbus_message_iter_get_basic (&reply_iter, &value);
02262 
02263     dbus_message_unref (message);
02264     dbus_message_unref (reply);
02265     return value;
02266 }
02267 
02277 dbus_bool_t
02278 libhal_device_property_exists (LibHalContext *ctx, 
02279                    const char *udi, const char *key, DBusError *error)
02280 {
02281     DBusMessage *message;
02282     DBusMessage *reply;
02283     DBusMessageIter iter, reply_iter;
02284     dbus_bool_t value;
02285     DBusError _error;
02286 
02287     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02288 
02289     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
02290                         "org.freedesktop.Hal.Device",
02291                         "PropertyExists");
02292     if (message == NULL) {
02293         fprintf (stderr,
02294              "%s %d : Couldn't allocate D-BUS message\n",
02295              __FILE__, __LINE__);
02296         return FALSE;
02297     }
02298 
02299     dbus_message_iter_init_append (message, &iter);
02300     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
02301 
02302     dbus_error_init (&_error);
02303     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02304                                message, -1,
02305                                &_error);
02306 
02307     dbus_move_error (&_error, error);
02308     if (error != NULL && dbus_error_is_set (error)) {
02309         dbus_message_unref (message);
02310         return FALSE;
02311     }
02312     if (reply == NULL) {
02313         dbus_message_unref (message);
02314         return FALSE;
02315     }
02316 
02317     dbus_message_iter_init (reply, &reply_iter);
02318 
02319     /* now analyse reply */
02320     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
02321         fprintf (stderr, "%s %d : expected a bool in reply to "
02322              "PropertyExists\n", __FILE__, __LINE__);
02323         dbus_message_unref (message);
02324         dbus_message_unref (reply);
02325         return FALSE;
02326     }
02327 
02328     dbus_message_iter_get_basic (&reply_iter, &value);
02329 
02330     dbus_message_unref (message);
02331     dbus_message_unref (reply);
02332     return value;
02333 }
02334 
02344 dbus_bool_t
02345 libhal_merge_properties (LibHalContext *ctx, 
02346              const char *target_udi, const char *source_udi, DBusError *error)
02347 {
02348     DBusMessage *message;
02349     DBusMessage *reply;
02350     DBusMessageIter iter;
02351 
02352     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02353 
02354     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02355                         "/org/freedesktop/Hal/Manager",
02356                         "org.freedesktop.Hal.Manager",
02357                         "MergeProperties");
02358     if (message == NULL) {
02359         fprintf (stderr,
02360              "%s %d : Couldn't allocate D-BUS message\n",
02361              __FILE__, __LINE__);
02362         return FALSE;
02363     }
02364 
02365     dbus_message_iter_init_append (message, &iter);
02366     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &target_udi);
02367     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &source_udi);
02368 
02369     
02370     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02371                                message, -1,
02372                                error);
02373     if (dbus_error_is_set (error)) {
02374         dbus_message_unref (message);
02375         return FALSE;
02376     }
02377     if (reply == NULL) {
02378         dbus_message_unref (message);
02379         return FALSE;
02380     }
02381 
02382     dbus_message_unref (message);
02383     dbus_message_unref (reply);
02384     return TRUE;
02385 }
02386 
02408 dbus_bool_t
02409 libhal_device_matches (LibHalContext *ctx, 
02410                  const char *udi1, const char *udi2,
02411                  const char *property_namespace, DBusError *error)
02412 {
02413     DBusMessage *message;
02414     DBusMessage *reply;
02415     DBusMessageIter iter, reply_iter;
02416     dbus_bool_t value;
02417     DBusError _error;
02418 
02419     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02420 
02421     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02422                         "/org/freedesktop/Hal/Manager",
02423                         "org.freedesktop.Hal.Manager",
02424                         "DeviceMatches");
02425     if (message == NULL) {
02426         fprintf (stderr,
02427              "%s %d : Couldn't allocate D-BUS message\n",
02428              __FILE__, __LINE__);
02429         return FALSE;
02430     }
02431 
02432     dbus_message_iter_init_append (message, &iter);
02433     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, udi1);
02434     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, udi2);
02435     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, property_namespace);
02436 
02437     dbus_error_init (&_error);
02438     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02439                                message, -1,
02440                                &_error);
02441 
02442     dbus_move_error (&_error, error);
02443     if (error != NULL && dbus_error_is_set (error)) {
02444         dbus_message_unref (message);
02445         return FALSE;
02446     }
02447     if (reply == NULL) {
02448         dbus_message_unref (message);
02449         return FALSE;
02450     }
02451     /* now analyse reply */
02452     dbus_message_iter_init (reply, &reply_iter);
02453 
02454     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
02455         fprintf (stderr,
02456              "%s %d : expected a bool in reply to DeviceMatches\n",
02457              __FILE__, __LINE__);
02458         dbus_message_unref (message);
02459         dbus_message_unref (reply);
02460         return FALSE;
02461     }
02462 
02463     dbus_message_iter_get_basic (&reply_iter, &value);
02464 
02465     dbus_message_unref (message);
02466     dbus_message_unref (reply);
02467     return value;
02468 }
02469 
02479 dbus_bool_t
02480 libhal_device_print (LibHalContext *ctx, const char *udi, DBusError *error)
02481 {
02482     int type;
02483     char *key;
02484     LibHalPropertySet *pset;
02485     LibHalPropertySetIterator i;
02486 
02487     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02488 
02489     printf ("device_id = %s\n", udi);
02490 
02491     if ((pset = libhal_device_get_all_properties (ctx, udi, error)) == NULL)
02492         return FALSE;
02493 
02494     for (libhal_psi_init (&i, pset); libhal_psi_has_more (&i);
02495          libhal_psi_next (&i)) {
02496         type = libhal_psi_get_type (&i);
02497         key = libhal_psi_get_key (&i);
02498 
02499         switch (type) {
02500         case LIBHAL_PROPERTY_TYPE_STRING:
02501             printf ("    %s = '%s' (string)\n", key,
02502                 libhal_psi_get_string (&i));
02503             break;
02504         case LIBHAL_PROPERTY_TYPE_INT32:
02505             printf ("    %s = %d = 0x%x (int)\n", key,
02506                 libhal_psi_get_int (&i),
02507                 libhal_psi_get_int (&i));
02508             break;
02509         case LIBHAL_PROPERTY_TYPE_UINT64:
02510             printf ("    %s = %lld = 0x%llx (uint64)\n", key,
02511                 libhal_psi_get_uint64 (&i),
02512                 libhal_psi_get_uint64 (&i));
02513             break;
02514         case LIBHAL_PROPERTY_TYPE_BOOLEAN:
02515             printf ("    %s = %s (bool)\n", key,
02516                 (libhal_psi_get_bool (&i) ? "true" :
02517                  "false"));
02518             break;
02519         case LIBHAL_PROPERTY_TYPE_DOUBLE:
02520             printf ("    %s = %g (double)\n", key,
02521                 libhal_psi_get_double (&i));
02522             break;
02523         case LIBHAL_PROPERTY_TYPE_STRLIST:
02524         {
02525             unsigned int j;
02526             char **str_list;
02527 
02528             str_list = libhal_psi_get_strlist (&i);
02529             printf ("    %s = [", key);
02530             for (j = 0; str_list[j] != NULL; j++) {
02531                 printf ("'%s'", str_list[j]);
02532                 if (str_list[j+1] != NULL)
02533                     printf (", ");
02534             }
02535             printf ("] (string list)\n");
02536 
02537             break;
02538         }
02539         default:
02540             printf ("    *** unknown type for key %s\n", key);
02541             break;
02542         }
02543     }
02544 
02545     libhal_free_property_set (pset);
02546 
02547     return TRUE;
02548 }
02549 
02562 char **
02563 libhal_manager_find_device_string_match (LibHalContext *ctx, 
02564                      const char *key,
02565                      const char *value, int *num_devices, DBusError *error)
02566 {
02567     DBusMessage *message;
02568     DBusMessage *reply;
02569     DBusMessageIter iter, iter_array, reply_iter;
02570     char **hal_device_names;
02571     DBusError _error;
02572 
02573     LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
02574 
02575     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02576                         "/org/freedesktop/Hal/Manager",
02577                         "org.freedesktop.Hal.Manager",
02578                         "FindDeviceStringMatch");
02579     if (message == NULL) {
02580         fprintf (stderr,
02581              "%s %d : Couldn't allocate D-BUS message\n",
02582              __FILE__, __LINE__);
02583         return NULL;
02584     }
02585 
02586     dbus_message_iter_init_append (message, &iter);
02587     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
02588     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
02589 
02590     dbus_error_init (&_error);
02591     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02592                                message, -1,
02593                                &_error);
02594 
02595     dbus_move_error (&_error, error);
02596     if (error != NULL && dbus_error_is_set (error)) {
02597         dbus_message_unref (message);
02598         return NULL;
02599     }
02600     if (reply == NULL) {
02601         dbus_message_unref (message);
02602         return NULL;
02603     }
02604     /* now analyse reply */
02605     dbus_message_iter_init (reply, &reply_iter);
02606 
02607     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
02608         fprintf (stderr, "%s %d : wrong reply from hald.  Expecting an array.\n", __FILE__, __LINE__);
02609         return NULL;
02610     }
02611     
02612     dbus_message_iter_recurse (&reply_iter, &iter_array);
02613 
02614     hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
02615               
02616     dbus_message_unref (reply);
02617     dbus_message_unref (message);
02618 
02619     return hal_device_names;
02620 }
02621 
02622 
02633 dbus_bool_t
02634 libhal_device_add_capability (LibHalContext *ctx, 
02635                   const char *udi, const char *capability, DBusError *error)
02636 {
02637     DBusMessage *message;
02638     DBusMessage *reply;
02639     DBusMessageIter iter;
02640 
02641     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02642 
02643     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
02644                         "org.freedesktop.Hal.Device",
02645                         "AddCapability");
02646     if (message == NULL) {
02647         fprintf (stderr,
02648              "%s %d : Couldn't allocate D-BUS message\n",
02649              __FILE__, __LINE__);
02650         return FALSE;
02651     }
02652 
02653     dbus_message_iter_init_append (message, &iter);
02654     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability);
02655 
02656     
02657     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02658                                message, -1,
02659                                error);
02660     if (dbus_error_is_set (error)) {
02661         dbus_message_unref (message);
02662         return FALSE;
02663     }
02664 
02665     if (reply == NULL) {
02666         dbus_message_unref (message);
02667         return FALSE;
02668     }
02669 
02670     dbus_message_unref (reply);
02671     dbus_message_unref (message);
02672     return TRUE;
02673 }
02674 
02686 dbus_bool_t
02687 libhal_device_query_capability (LibHalContext *ctx, const char *udi, const char *capability, DBusError *error)
02688 {
02689     char **caps;
02690     unsigned int i;
02691     dbus_bool_t ret;
02692 
02693     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02694 
02695     ret = FALSE;
02696 
02697     caps = libhal_device_get_property_strlist (ctx, udi, "info.capabilities", error);
02698     if (caps != NULL) {
02699         for (i = 0; caps[i] != NULL; i++) {
02700             if (strcmp (caps[i], capability) == 0) {
02701                 ret = TRUE;
02702                 break;
02703             }
02704         }
02705         libhal_free_string_array (caps);
02706     }
02707 
02708     return ret;
02709 }
02710 
02721 char **
02722 libhal_find_device_by_capability (LibHalContext *ctx, 
02723                   const char *capability, int *num_devices, DBusError *error)
02724 {
02725     DBusMessage *message;
02726     DBusMessage *reply;
02727     DBusMessageIter iter, iter_array, reply_iter;
02728     char **hal_device_names;
02729     DBusError _error;
02730 
02731     LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
02732 
02733     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02734                         "/org/freedesktop/Hal/Manager",
02735                         "org.freedesktop.Hal.Manager",
02736                         "FindDeviceByCapability");
02737     if (message == NULL) {
02738         fprintf (stderr,
02739              "%s %d : Couldn't allocate D-BUS message\n",
02740              __FILE__, __LINE__);
02741         return NULL;
02742     }
02743 
02744     dbus_message_iter_init_append (message, &iter);
02745     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability);
02746 
02747     dbus_error_init (&_error);
02748     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02749                                message, -1,
02750                                &_error);
02751     
02752     dbus_move_error (&_error, error);
02753     if (error != NULL && dbus_error_is_set (error)) {
02754         dbus_message_unref (message);
02755         return NULL;
02756     }
02757     if (reply == NULL) {
02758         dbus_message_unref (message);
02759         return NULL;
02760     }
02761     /* now analyse reply */
02762     dbus_message_iter_init (reply, &reply_iter);
02763 
02764     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
02765         fprintf (stderr, "%s %d : wrong reply from hald.  Expecting an array.\n", __FILE__, __LINE__);
02766         return NULL;
02767     }
02768     
02769     dbus_message_iter_recurse (&reply_iter, &iter_array);
02770 
02771     hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
02772               
02773     dbus_message_unref (reply);
02774     dbus_message_unref (message);
02775 
02776     return hal_device_names;
02777 }
02778 
02787 dbus_bool_t
02788 libhal_device_property_watch_all (LibHalContext *ctx, DBusError *error)
02789 {
02790     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02791 
02792     dbus_bus_add_match (ctx->connection,
02793                 "type='signal',"
02794                 "interface='org.freedesktop.Hal.Device',"
02795                 "sender='org.freedesktop.Hal'", error);
02796     if (dbus_error_is_set (error)) {
02797         return FALSE;
02798     }
02799     return TRUE;
02800 }
02801 
02802 
02815 dbus_bool_t
02816 libhal_device_add_property_watch (LibHalContext *ctx, const char *udi, DBusError *error)
02817 {   
02818     char buf[512];
02819     
02820     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02821 
02822     snprintf (buf, 512,
02823           "type='signal',"
02824           "interface='org.freedesktop.Hal.Device',"
02825           "sender='org.freedesktop.Hal'," "path=%s", udi);
02826 
02827     dbus_bus_add_match (ctx->connection, buf, error);
02828     if (dbus_error_is_set (error)) {
02829         return FALSE;
02830     }
02831     return TRUE;
02832 }
02833 
02834 
02843 dbus_bool_t
02844 libhal_device_remove_property_watch (LibHalContext *ctx, const char *udi, DBusError *error)
02845 {   
02846     char buf[512];
02847     
02848     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02849 
02850     snprintf (buf, 512,
02851           "type='signal',"
02852           "interface='org.freedesktop.Hal.Device',"
02853           "sender='org.freedesktop.Hal'," "path=%s", udi);
02854 
02855     dbus_bus_remove_match (ctx->connection, buf, error);
02856     if (dbus_error_is_set (error)) {
02857         return FALSE;
02858     }
02859     return TRUE;
02860 }
02861 
02862 
02867 LibHalContext *
02868 libhal_ctx_new (void)
02869 {
02870     LibHalContext *ctx;
02871 
02872     if (!libhal_already_initialized_once) {
02873         bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
02874         bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
02875         
02876         libhal_already_initialized_once = TRUE;
02877     }
02878 
02879     ctx = calloc (1, sizeof (LibHalContext));
02880     if (ctx == NULL) {
02881         fprintf (stderr, 
02882              "%s %d : Failed to allocate %d bytes\n",
02883              __FILE__, __LINE__, sizeof (LibHalContext));
02884         return NULL;
02885     }
02886 
02887     ctx->is_initialized = FALSE;
02888     ctx->is_shutdown = FALSE;
02889     ctx->connection = NULL;
02890     ctx->is_direct = FALSE;
02891 
02892     return ctx;
02893 }
02894 
02904 dbus_bool_t
02905 libhal_ctx_set_cache (LibHalContext *ctx, dbus_bool_t use_cache)
02906 {
02907     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02908 
02909     ctx->cache_enabled = use_cache;
02910     return TRUE;
02911 }
02912 
02920 dbus_bool_t
02921 libhal_ctx_set_dbus_connection (LibHalContext *ctx, DBusConnection *conn)
02922 {
02923     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02924 
02925     if (conn == NULL)
02926         return FALSE;
02927 
02928     ctx->connection = conn;
02929     return TRUE;
02930 }
02931 
02940 dbus_bool_t 
02941 libhal_ctx_init (LibHalContext *ctx, DBusError *error)
02942 {
02943     DBusError _error;
02944     dbus_bool_t hald_exists;
02945 
02946     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
02947 
02948     if (ctx->connection == NULL)
02949         return FALSE;
02950 
02951     dbus_error_init (&_error);
02952     hald_exists = dbus_bus_name_has_owner (ctx->connection, "org.freedesktop.Hal", &_error);
02953     dbus_move_error (&_error, error);
02954     if (error != NULL && dbus_error_is_set (error)) {
02955         return FALSE;
02956     }
02957 
02958     if (!hald_exists) {
02959         return FALSE;
02960     }
02961 
02962     
02963     if (!dbus_connection_add_filter (ctx->connection, filter_func, ctx, NULL)) {
02964         return FALSE;
02965     }
02966 
02967     dbus_bus_add_match (ctx->connection, 
02968                 "type='signal',"
02969                 "interface='org.freedesktop.Hal.Manager',"
02970                 "sender='org.freedesktop.Hal',"
02971                 "path='/org/freedesktop/Hal/Manager'", &_error);
02972     dbus_move_error (&_error, error);
02973     if (error != NULL && dbus_error_is_set (error)) {
02974         return FALSE;
02975     }
02976     ctx->is_initialized = TRUE;
02977     ctx->is_direct = FALSE;
02978 
02979     return TRUE;
02980 }
02981 
02988 LibHalContext *
02989 libhal_ctx_init_direct (DBusError *error)
02990 {
02991     char *hald_addr;
02992     LibHalContext *ctx;
02993     DBusError _error;
02994 
02995     ctx = libhal_ctx_new ();
02996     if (ctx == NULL)
02997         goto out;
02998 
02999     if (((hald_addr = getenv ("HALD_DIRECT_ADDR"))) == NULL) {
03000         libhal_ctx_free (ctx);
03001         ctx = NULL;
03002         goto out;
03003     }
03004 
03005     dbus_error_init (&_error);
03006     ctx->connection = dbus_connection_open (hald_addr, &_error);
03007     dbus_move_error (&_error, error);
03008     if (error != NULL && dbus_error_is_set (error)) {
03009         libhal_ctx_free (ctx);
03010         ctx = NULL;
03011         goto out;
03012     }
03013 
03014     ctx->is_initialized = TRUE;
03015     ctx->is_direct = TRUE;
03016 
03017 out:
03018     return ctx;
03019 }
03020 
03029 dbus_bool_t    
03030 libhal_ctx_shutdown (LibHalContext *ctx, DBusError *error)
03031 {   
03032     DBusError myerror;
03033 
03034     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03035 
03036     if (ctx->is_direct) {
03037         /* for some reason dbus_connection_set_exit_on_disconnect doesn't work yet so don't unref */
03038         /*dbus_connection_unref (ctx->connection);*/
03039     } else {
03040         dbus_error_init (&myerror);
03041         dbus_bus_remove_match (ctx->connection, 
03042                        "type='signal',"
03043                        "interface='org.freedesktop.Hal.Manager',"
03044                        "sender='org.freedesktop.Hal',"
03045                        "path='/org/freedesktop/Hal/Manager'", &myerror);
03046         if (dbus_error_is_set (&myerror)) {
03047             dbus_move_error (&myerror, error);
03048             fprintf (stderr, "%s %d : Error unsubscribing to signals, error=%s\n", 
03049                  __FILE__, __LINE__, error->message);
03051         }
03052 
03053         /* TODO: remove other matches */
03054 
03055         dbus_connection_remove_filter (ctx->connection, filter_func, ctx);
03056     }
03057 
03058     ctx->is_initialized = FALSE;
03059 
03060     return TRUE;
03061 }
03062 
03068 dbus_bool_t    
03069 libhal_ctx_free (LibHalContext *ctx)
03070 {
03071     free (ctx);
03072     return TRUE;
03073 }
03074 
03082 dbus_bool_t
03083 libhal_ctx_set_device_added (LibHalContext *ctx, LibHalDeviceAdded callback)
03084 {
03085     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03086     
03087     ctx->device_added = callback;
03088     return TRUE;
03089 }
03090 
03098 dbus_bool_t
03099 libhal_ctx_set_device_removed (LibHalContext *ctx, LibHalDeviceRemoved callback)
03100 {
03101     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03102     
03103     ctx->device_removed = callback;
03104     return TRUE;
03105 }
03106 
03115 dbus_bool_t
03116 libhal_ctx_set_device_new_capability (LibHalContext *ctx, LibHalDeviceNewCapability callback)
03117 {
03118     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03119     
03120     ctx->device_new_capability = callback;
03121     return TRUE;
03122 }
03123 
03132 dbus_bool_t
03133 libhal_ctx_set_device_lost_capability (LibHalContext *ctx, LibHalDeviceLostCapability callback)
03134 {
03135     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03136     
03137     ctx->device_lost_capability = callback;
03138     return TRUE;
03139 }
03140 
03149 dbus_bool_t
03150 libhal_ctx_set_device_property_modified (LibHalContext *ctx, LibHalDevicePropertyModified callback)
03151 {
03152     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03153     
03154     ctx->device_property_modified = callback;
03155     return TRUE;
03156 }
03157 
03165 dbus_bool_t
03166 libhal_ctx_set_device_condition (LibHalContext *ctx, LibHalDeviceCondition callback)
03167 {
03168     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03169     
03170     ctx->device_condition = callback;
03171     return TRUE;
03172 }
03173 
03179 unsigned int libhal_string_array_length (char **str_array)
03180 {
03181     unsigned int i;
03182 
03183     if (str_array == NULL)
03184         return 0;
03185 
03186     for (i = 0; str_array[i] != NULL; i++)
03187         ;
03188 
03189     return i;
03190 }
03191 
03192 
03193 dbus_bool_t 
03194 libhal_device_rescan (LibHalContext *ctx, const char *udi, DBusError *error)
03195 {
03196     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03197     
03198     DBusMessage *message;
03199     DBusMessageIter reply_iter;
03200     DBusMessage *reply;
03201     dbus_bool_t result;
03202 
03203     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
03204                         "org.freedesktop.Hal.Device",
03205                         "Rescan");
03206 
03207     if (message == NULL) {
03208         fprintf (stderr,
03209              "%s %d : Couldn't allocate D-BUS message\n",
03210              __FILE__, __LINE__);
03211         return FALSE;
03212     }
03213     
03214     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
03215                                message, -1,
03216                                error);
03217 
03218     if (dbus_error_is_set (error)) {
03219         dbus_message_unref (message);
03220         return FALSE;
03221     }
03222 
03223     dbus_message_unref (message);
03224 
03225     if (reply == NULL)
03226         return FALSE;
03227 
03228     dbus_message_iter_init (reply, &reply_iter);
03229     if (dbus_message_iter_get_arg_type (&reply_iter) !=
03230            DBUS_TYPE_BOOLEAN) {
03231         dbus_message_unref (message);
03232         dbus_message_unref (reply);
03233         return FALSE;
03234     }
03235     dbus_message_iter_get_basic (&reply_iter, &result);
03236 
03237     dbus_message_unref (reply);
03238 
03239     return result;
03240 }
03241 
03242 dbus_bool_t
03243 libhal_device_reprobe (LibHalContext *ctx, const char *udi, DBusError *error)
03244 {
03245     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03246     
03247     DBusMessage *message;
03248     DBusMessageIter reply_iter;
03249     DBusMessage *reply;
03250     dbus_bool_t result;
03251 
03252     message = dbus_message_new_method_call ("org.freedesktop.Hal",
03253                         udi,
03254                         "org.freedesktop.Hal.Device",
03255                         "Reprobe");
03256 
03257     if (message == NULL) {
03258         fprintf (stderr,
03259              "%s %d : Couldn't allocate D-BUS message\n",
03260              __FILE__, __LINE__);
03261         return FALSE;
03262     }
03263     
03264     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
03265                                message, -1,
03266                                error);
03267 
03268     if (dbus_error_is_set (error)) {
03269         dbus_message_unref (message);
03270         return FALSE;
03271     }
03272 
03273     dbus_message_unref (message);
03274 
03275     if (reply == NULL)
03276         return FALSE;
03277 
03278     dbus_message_iter_init (reply, &reply_iter);
03279     if (dbus_message_iter_get_arg_type (&reply_iter) !=
03280            DBUS_TYPE_BOOLEAN) {
03281         dbus_message_unref (message);
03282         dbus_message_unref (reply);
03283         return FALSE;
03284     }
03285     dbus_message_iter_get_basic (&reply_iter, &result);
03286 
03287     dbus_message_unref (reply);
03288 
03289     return result;
03290 }
03291 
03303 dbus_bool_t libhal_device_emit_condition (LibHalContext *ctx,
03304                       const char *udi,
03305                       const char *condition_name,
03306                       const char *condition_details,
03307                       DBusError *error)
03308 {
03309     LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
03310     
03311     DBusMessage *message;
03312     DBusMessageIter iter;
03313     DBusMessageIter reply_iter;
03314     DBusMessage *reply;
03315     dbus_bool_t result;
03316 
03317     message = dbus_message_new_method_call ("org.freedesktop.Hal",
03318                         udi,
03319                         "org.freedesktop.Hal.Device",
03320                         "EmitCondition");
03321 
03322     if (message == NULL) {
03323         fprintf (stderr,
03324              "%s %d : Couldn't allocate D-BUS message\n",
03325              __FILE__, __LINE__);
03326         return FALSE;
03327     }
03328 
03329     dbus_message_iter_init_append (message, &iter);
03330     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &condition_name);
03331     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &condition_details);
03332     
03333     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
03334                                message, -1,
03335                                error);
03336 
03337     if (dbus_error_is_set (error)) {
03338         dbus_message_unref (message);
03339         return FALSE;
03340     }
03341 
03342     dbus_message_unref (message);
03343 
03344     if (reply == NULL)
03345         return FALSE;
03346 
03347     dbus_message_iter_init (reply, &reply_iter);
03348     if (dbus_message_iter_get_arg_type (&reply_iter) !=
03349            DBUS_TYPE_BOOLEAN) {
03350         dbus_message_unref (message);
03351         dbus_message_unref (reply);
03352         return FALSE;
03353     }
03354     dbus_message_iter_get_basic (&reply_iter, &result);
03355 
03356     dbus_message_unref (reply);
03357 
03358     return result;  
03359 }
03360 

Generated on Fri Nov 23 17:14:31 2007 for HAL by  doxygen 1.4.6