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

libhal.c

00001 /***************************************************************************
00002  * CVSID: $Id: libhal.c,v 1.49 2005/05/11 17:20:55 david Exp $
00003  *
00004  * libhal.c : HAL daemon C convenience library
00005  *
00006  * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
00007  *
00008  * Licensed under the Academic Free License version 2.0
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  **************************************************************************/
00025 
00026 #ifdef HAVE_CONFIG_H
00027 #  include <config.h>
00028 #endif
00029 
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include <dbus/dbus.h>
00034 
00035 #include "libhal.h"
00036 
00037 #ifdef ENABLE_NLS
00038 # include <libintl.h>
00039 # define _(String) dgettext (GETTEXT_PACKAGE, String)
00040 # ifdef gettext_noop
00041 #   define N_(String) gettext_noop (String)
00042 # else
00043 #   define N_(String) (String)
00044 # endif
00045 #else
00046 /* Stubs that do something close enough.  */
00047 # define textdomain(String) (String)
00048 # define gettext(String) (String)
00049 # define dgettext(Domain,Message) (Message)
00050 # define dcgettext(Domain,Message,Type) (Message)
00051 # define bindtextdomain(Domain,Directory) (Domain)
00052 # define _(String)
00053 # define N_(String) (String)
00054 #endif
00055 
00056 static char **libhal_get_string_array_from_iter (DBusMessageIter *iter, int *num_elements);
00057 
00058 static dbus_bool_t libhal_property_fill_value_from_variant (LibHalProperty *p, DBusMessageIter *var_iter);
00059 
00060 
00061 
00074 void
00075 libhal_free_string_array (char **str_array)
00076 {
00077     if (str_array != NULL) {
00078         int i;
00079 
00080         for (i = 0; str_array[i] != NULL; i++) {
00081             free (str_array[i]);
00082         }
00083         free (str_array);
00084     }
00085 }
00086 
00087 
00094 static char **
00095 libhal_get_string_array_from_iter (DBusMessageIter *iter, int *num_elements)
00096 {
00097     int count;
00098     char **buffer;
00099 
00100     count = 0;
00101     buffer = (char **)malloc (sizeof (char *) * 8);
00102 
00103     if (buffer == NULL)
00104         goto oom;
00105 
00106     buffer[0] = NULL;
00107     while (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING) {
00108         const char *value;
00109         char *str;
00110         
00111         if ((count % 8) == 0 && count != 0) {
00112             buffer = realloc (buffer, sizeof (char *) * (count + 8));
00113             if (buffer == NULL)
00114                 goto oom;
00115         }
00116         
00117         dbus_message_iter_get_basic (iter, &value);
00118         str = strdup (value);
00119         if (str == NULL)
00120             goto oom;
00121 
00122         buffer[count] = str;
00123 
00124         dbus_message_iter_next(iter);
00125         count++;
00126     }
00127 
00128     if ((count % 8) == 0) {
00129         buffer = realloc (buffer, sizeof (char *) * (count + 1));
00130         if (buffer == NULL)
00131             goto oom;
00132     }
00133 
00134     buffer[count] = NULL;
00135     if (num_elements != NULL)
00136         *num_elements = count;
00137     return buffer;
00138 
00139 oom:
00140     fprintf (stderr, "%s %d : error allocating memory\n", __FILE__, __LINE__);
00141     return NULL;
00142 
00143 }
00144 
00149 void
00150 libhal_free_string (char *str)
00151 {
00153     free (str);
00154 }
00155 
00156 
00158 struct LibHalPropertySet_s {
00159     unsigned int num_properties; 
00160     LibHalProperty *properties_head;
00163 };
00164 
00166 struct LibHalProperty_s {
00167     int type;            
00168     char *key;           
00171     union {
00172         char *str_value;     
00173         dbus_int32_t int_value;
00175         dbus_uint64_t uint64_value;
00177         double double_value; 
00178         dbus_bool_t bool_value;
00181         char **strlist_value; 
00182     };
00183 
00184     LibHalProperty *next;        
00186 };
00187 
00189 struct LibHalContext_s {
00190     DBusConnection *connection;           
00191     dbus_bool_t is_initialized;           
00192     dbus_bool_t is_shutdown;              
00193     dbus_bool_t cache_enabled;            
00194     dbus_bool_t is_direct;                
00197     LibHalDeviceAdded device_added;
00198 
00200     LibHalDeviceRemoved device_removed;
00201 
00203     LibHalDeviceNewCapability device_new_capability;
00204 
00206     LibHalDeviceLostCapability device_lost_capability;
00207 
00209     LibHalDevicePropertyModified device_property_modified;
00210 
00212     LibHalDeviceCondition device_condition;
00213 
00214     void *user_data;                      
00215 };
00216 
00224 dbus_bool_t
00225 libhal_ctx_set_user_data(LibHalContext *ctx, void *user_data)
00226 {
00227     if (ctx == NULL)
00228         return FALSE;
00229     ctx->user_data = user_data;
00230     return TRUE;
00231 }
00232 
00239 void*
00240 libhal_ctx_get_user_data(LibHalContext *ctx)
00241 {
00242     return ctx->user_data;
00243 }
00244 
00245 
00251 static dbus_bool_t
00252 libhal_property_fill_value_from_variant (LibHalProperty *p, DBusMessageIter *var_iter)
00253 {
00254     DBusMessageIter iter_array;
00255     switch (p->type) {
00256     case DBUS_TYPE_ARRAY:
00257         if (dbus_message_iter_get_element_type (var_iter) != DBUS_TYPE_STRING)
00258             return FALSE;
00259 
00260         dbus_message_iter_recurse (var_iter, &iter_array);
00261         p->strlist_value = libhal_get_string_array_from_iter (&iter_array, NULL);
00262 
00263         p->type = LIBHAL_PROPERTY_TYPE_STRLIST; 
00264 
00265         break;
00266     case DBUS_TYPE_STRING:
00267     {
00268         const char *v;
00269 
00270         dbus_message_iter_get_basic (var_iter, &v);
00271 
00272         p->str_value = strdup (v);
00273         if (p->str_value == NULL) 
00274             return FALSE;
00275         p->type = LIBHAL_PROPERTY_TYPE_STRING; 
00276 
00277         break;
00278     }
00279     case DBUS_TYPE_INT32:
00280     {
00281         dbus_int32_t v;
00282         
00283         dbus_message_iter_get_basic (var_iter, &v);
00284         
00285         p->int_value = v;
00286         p->type = LIBHAL_PROPERTY_TYPE_INT32; 
00287 
00288         break;
00289     }
00290     case DBUS_TYPE_UINT64:
00291     {
00292         dbus_uint64_t v;
00293         
00294         dbus_message_iter_get_basic (var_iter, &v);
00295 
00296         p->uint64_value = v;
00297         p->type = LIBHAL_PROPERTY_TYPE_UINT64; 
00298         
00299         break;
00300     }
00301     case DBUS_TYPE_DOUBLE:
00302     {
00303         double v;
00304 
00305         dbus_message_iter_get_basic (var_iter, &v);
00306 
00307         p->double_value = v;
00308         p->type = LIBHAL_PROPERTY_TYPE_DOUBLE; 
00309 
00310         break;
00311     }
00312     case DBUS_TYPE_BOOLEAN:
00313     {
00314         double v;
00315 
00316         dbus_message_iter_get_basic (var_iter, &v);
00317 
00318         p->double_value = v;
00319         p->type = LIBHAL_PROPERTY_TYPE_BOOLEAN; 
00320 
00321         break;
00322     }
00323     default:
00325         break;
00326     }
00327 
00328     return TRUE;
00329 }
00330 
00340 LibHalPropertySet *
00341 libhal_device_get_all_properties (LibHalContext *ctx, const char *udi, DBusError *error)
00342 {
00343     DBusMessage *message;
00344     DBusMessage *reply;
00345     DBusMessageIter reply_iter;
00346     DBusMessageIter dict_iter;
00347     LibHalPropertySet *result;
00348     LibHalProperty *p_last;
00349     DBusError _error;
00350 
00351     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
00352                         "org.freedesktop.Hal.Device",
00353                         "GetAllProperties");
00354 
00355     if (message == NULL) {
00356         fprintf (stderr,
00357              "%s %d : Couldn't allocate D-BUS message\n",
00358              __FILE__, __LINE__);
00359         return NULL;
00360     }
00361 
00362     dbus_error_init (&_error);
00363     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
00364                                message, -1,
00365                                &_error);
00366 
00367     dbus_move_error (&_error, error);
00368     if (error != NULL && dbus_error_is_set (error)) {
00369         fprintf (stderr,
00370              "%s %d : %s\n",
00371              __FILE__, __LINE__, error->message);
00372 
00373         dbus_message_unref (message);
00374         return NULL;
00375     }
00376 
00377     if (reply == NULL) {
00378         dbus_message_unref (message);
00379         return NULL;
00380     }
00381 
00382     dbus_message_iter_init (reply, &reply_iter);
00383 
00384     result = malloc (sizeof (LibHalPropertySet));
00385     if (result == NULL) 
00386         goto oom;
00387 /*
00388     result->properties = malloc(sizeof(LibHalProperty)*result->num_properties);
00389     if( result->properties==NULL )
00390     {
00392     return NULL;
00393     }
00394 */
00395 
00396     result->properties_head = NULL;
00397     result->num_properties = 0;
00398 
00399     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY  &&
00400         dbus_message_iter_get_element_type (&reply_iter) != DBUS_TYPE_DICT_ENTRY) {
00401         fprintf (stderr, "%s %d : error, expecting an array of dict entries\n",
00402              __FILE__, __LINE__);
00403         dbus_message_unref (message);
00404         dbus_message_unref (reply);
00405         return NULL;
00406     }
00407 
00408     dbus_message_iter_recurse (&reply_iter, &dict_iter);
00409 
00410     p_last = NULL;
00411 
00412     while (dbus_message_iter_get_arg_type (&dict_iter) == DBUS_TYPE_DICT_ENTRY)
00413     {
00414         DBusMessageIter dict_entry_iter, var_iter;
00415         const char *key;
00416         LibHalProperty *p;
00417 
00418         dbus_message_iter_recurse (&dict_iter, &dict_entry_iter);
00419 
00420         dbus_message_iter_get_basic (&dict_entry_iter, &key);
00421 
00422         p = malloc (sizeof (LibHalProperty));
00423         if (p == NULL)
00424             goto oom;
00425 
00426         p->next = NULL;
00427 
00428         if (result->num_properties == 0)
00429             result->properties_head = p;
00430 
00431         if (p_last != NULL)
00432             p_last->next = p;
00433 
00434         p_last = p;
00435 
00436         p->key = strdup (key);
00437         if (p->key == NULL)
00438             goto oom;
00439 
00440         dbus_message_iter_next (&dict_entry_iter);
00441 
00442         dbus_message_iter_recurse (&dict_entry_iter, &var_iter);
00443 
00444 
00445         p->type = dbus_message_iter_get_arg_type (&var_iter);
00446     
00447         result->num_properties++;
00448 
00449         if(!libhal_property_fill_value_from_variant (p, &var_iter))
00450             goto oom;
00451 
00452         dbus_message_iter_next (&dict_iter);
00453     }
00454 
00455     dbus_message_unref (message);
00456     dbus_message_unref (reply);
00457 
00458     return result;
00459 
00460 oom:
00461     fprintf (stderr,
00462         "%s %d : error allocating memory\n",
00463          __FILE__, __LINE__);
00465     return NULL;
00466 }
00467 
00472 void
00473 libhal_free_property_set (LibHalPropertySet * set)
00474 {
00475     LibHalProperty *p;
00476     LibHalProperty *q;
00477 
00478     if (set == NULL)
00479         return;
00480 
00481     for (p = set->properties_head; p != NULL; p = q) {
00482         free (p->key);
00483         if (p->type == DBUS_TYPE_STRING)
00484             free (p->str_value);
00485         if (p->type == LIBHAL_PROPERTY_TYPE_STRLIST)
00486             libhal_free_string_array (p->strlist_value);
00487         q = p->next;
00488         free (p);
00489     }
00490     free (set);
00491 }
00492 
00498 unsigned int 
00499 libhal_property_set_get_num_elems (LibHalPropertySet *set)
00500 {
00501     unsigned int num_elems;
00502     LibHalProperty *p;
00503 
00504     num_elems = 0;
00505     for (p = set->properties_head; p != NULL; p = p->next)
00506         num_elems++;
00507 
00508     return num_elems;
00509 }
00510 
00511 
00517 void
00518 libhal_psi_init (LibHalPropertySetIterator * iter, LibHalPropertySet * set)
00519 {
00520     iter->set = set;
00521     iter->index = 0;
00522     iter->cur_prop = set->properties_head;
00523 }
00524 
00525 
00532 dbus_bool_t
00533 libhal_psi_has_more (LibHalPropertySetIterator * iter)
00534 {
00535     return iter->index < iter->set->num_properties;
00536 }
00537 
00542 void
00543 libhal_psi_next (LibHalPropertySetIterator * iter)
00544 {
00545     iter->index++;
00546     iter->cur_prop = iter->cur_prop->next;
00547 }
00548 
00554 LibHalPropertyType
00555 libhal_psi_get_type (LibHalPropertySetIterator * iter)
00556 {
00557     return iter->cur_prop->type;
00558 }
00559 
00568 char *
00569 libhal_psi_get_key (LibHalPropertySetIterator * iter)
00570 {
00571     return iter->cur_prop->key;
00572 }
00573 
00582 char *
00583 libhal_psi_get_string (LibHalPropertySetIterator * iter)
00584 {
00585     return iter->cur_prop->str_value;
00586 }
00587 
00593 dbus_int32_t
00594 libhal_psi_get_int (LibHalPropertySetIterator * iter)
00595 {
00596     return iter->cur_prop->int_value;
00597 }
00598 
00604 dbus_uint64_t
00605 libhal_psi_get_uint64 (LibHalPropertySetIterator * iter)
00606 {
00607     return iter->cur_prop->uint64_value;
00608 }
00609 
00615 double
00616 libhal_psi_get_double (LibHalPropertySetIterator * iter)
00617 {
00618     return iter->cur_prop->double_value;
00619 }
00620 
00626 dbus_bool_t
00627 libhal_psi_get_bool (LibHalPropertySetIterator * iter)
00628 {
00629     return iter->cur_prop->bool_value;
00630 }
00631 
00637 char **
00638 libhal_psi_get_strlist (LibHalPropertySetIterator * iter)
00639 {
00640     return iter->cur_prop->strlist_value;
00641 }
00642 
00643 
00644 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00645 static DBusHandlerResult
00646 filter_func (DBusConnection * connection,
00647          DBusMessage * message, void *user_data)
00648 {
00649     const char *object_path;
00650     DBusError error;
00651     LibHalContext *ctx = (LibHalContext *) user_data;
00652 
00653     if (ctx->is_shutdown)
00654         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00655 
00656     dbus_error_init (&error);
00657 
00658     object_path = dbus_message_get_path (message);
00659 
00660     /*printf("*** in filter_func, object_path=%s\n", object_path);*/
00661 
00662     if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager",
00663                     "DeviceAdded")) {
00664         char *udi;
00665         if (dbus_message_get_args (message, &error,
00666                        DBUS_TYPE_STRING, &udi,
00667                        DBUS_TYPE_INVALID)) {
00668             if (ctx->device_added != NULL) {
00669                 ctx->device_added (ctx, udi);
00670             }
00671         }
00672         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00673     } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager", "DeviceRemoved")) {
00674         char *udi;
00675         if (dbus_message_get_args (message, &error,
00676                        DBUS_TYPE_STRING, &udi,
00677                        DBUS_TYPE_INVALID)) {
00678             if (ctx->device_removed != NULL) {
00679                 ctx->device_removed (ctx, udi);
00680             }
00681         }
00682         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00683     } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager","NewCapability")) {
00684         char *udi;
00685         char *capability;
00686         if (dbus_message_get_args (message, &error,
00687                        DBUS_TYPE_STRING, &udi,
00688                        DBUS_TYPE_STRING, &capability,
00689                        DBUS_TYPE_INVALID)) {
00690             if (ctx->device_new_capability != NULL) {
00691                 ctx->device_new_capability (ctx, udi, capability);
00692             }
00693         }
00694         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00695     } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "Condition")) {
00696         char *condition_name;
00697         char *condition_detail;
00698         if (dbus_message_get_args (message, &error,
00699                        DBUS_TYPE_STRING, &condition_name,
00700                        DBUS_TYPE_STRING, &condition_detail,
00701                        DBUS_TYPE_INVALID)) {
00702             if (ctx->device_condition != NULL) {
00703                 ctx->device_condition (ctx, object_path, condition_name, condition_detail);
00704             }
00705         }
00706         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00707     } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "PropertyModified")) {
00708         if (ctx->device_property_modified != NULL) {
00709             int i;
00710             char *key;
00711             dbus_bool_t removed;
00712             dbus_bool_t added;
00713             int num_modifications;
00714             DBusMessageIter iter;
00715             DBusMessageIter iter_array;
00716     
00717             dbus_message_iter_init (message, &iter);
00718             dbus_message_iter_get_basic (&iter, &num_modifications);
00719             dbus_message_iter_next (&iter);
00720 
00721             dbus_message_iter_recurse (&iter, &iter_array);
00722 
00723             for (i = 0; i < num_modifications; i++) {
00724                 DBusMessageIter iter_struct;
00725 
00726                 dbus_message_iter_recurse (&iter_array, &iter_struct);
00727 
00728                 dbus_message_iter_get_basic (&iter_struct, &key);
00729                 dbus_message_iter_next (&iter_struct);
00730                 dbus_message_iter_get_basic (&iter_struct, &removed);
00731                 dbus_message_iter_next (&iter_struct);
00732                 dbus_message_iter_get_basic (&iter_struct, &added);
00733                 
00734                 ctx->device_property_modified (ctx, 
00735                                    object_path,
00736                                    key, removed,
00737                                    added);
00738                 
00739                 dbus_message_iter_next (&iter_array);
00740             }
00741             
00742         }
00743         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00744     }
00745     
00746     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00747 }
00748 
00749 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
00750 
00751 /* for i18n purposes */
00752 static dbus_bool_t libhal_already_initialized_once = FALSE;
00753 
00754 #if 0
00755 
00773 LibHalContext*
00774 libhal_initialize (const LibHalFunctions * cb_functions,
00775         dbus_bool_t use_cache)
00776 {
00777     DBusError error;
00778     LibHalContext *ctx;
00779 
00780     if (!libhal_already_initialized_once) {
00781         bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
00782         bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
00783         
00784         libhal_already_initialized_once = TRUE;
00785     }
00786     
00787     ctx = malloc (sizeof (LibHalContext));
00788     if (ctx == NULL) {
00789         fprintf (stderr, "%s %d : Cannot allocated %d bytes!\n",
00790              __FILE__, __LINE__, sizeof (LibHalContext));
00791         return NULL;
00792     }
00793 
00794     ctx->is_initialized = FALSE;
00795     ctx->is_shutdown = FALSE;
00796 
00797     ctx->cache_enabled = use_cache;
00798 
00799     ctx->functions = cb_functions;
00800     /* allow caller to pass NULL */
00801     if (ctx->functions == NULL)
00802         ctx->functions = &libhal_null_functions;
00803 
00804     /* connect to hald service on the system bus */
00805     
00806     ctx->connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
00807     if (ctx->connection == NULL) {
00808         fprintf (stderr,
00809              "%s %d : Error connecting to system bus: %s\n",
00810              __FILE__, __LINE__, error.message);
00811         dbus_error_free (&error);
00812         return NULL;
00813     }
00814 
00815     if (ctx->main_loop_integration != NULL) {
00816 
00817         ctx->main_loop_integration (ctx, ctx->connection);
00818     }
00819 
00820     if (!dbus_connection_add_filter
00821         (ctx->connection, filter_func, ctx, NULL)) {
00822         fprintf (stderr,
00823              "%s %d : Error creating connection handler\r\n",
00824              __FILE__, __LINE__);
00826         return NULL;
00827     }
00828 
00829     dbus_bus_add_match (ctx->connection,
00830                 "type='signal',"
00831                 "interface='org.freedesktop.Hal.Manager',"
00832                 "sender='org.freedesktop.Hal',"
00833                 "path='/org/freedesktop/Hal/Manager'", &error);
00834     if (dbus_error_is_set (&error)) {
00835         fprintf (stderr, "%s %d : Error subscribing to signals, "
00836              "error=%s\r\n",
00837              __FILE__, __LINE__, error.message);
00839         return NULL;
00840     }
00841 
00842     ctx->is_initialized = TRUE;
00843     return ctx;
00844 }
00845 
00852 int
00853 libhal_shutdown (LibHalContext *ctx)
00854 {
00855     DBusError error;
00856 
00857     if (!ctx->is_initialized)
00858         return 1;
00859 
00860     /* unsubscribe the match rule we added in initialize; this is safe even with multiple
00861      * instances of libhal running - see the dbus docs */
00862     
00863     dbus_bus_remove_match (ctx->connection,
00864                    "type='signal',"
00865                    "interface='org.freedesktop.Hal.Manager',"
00866                    "sender='org.freedesktop.Hal',"
00867                    "path='/org/freedesktop/Hal/Manager'", &error);
00868     if (dbus_error_is_set (&error)) {
00869         fprintf (stderr, "%s %d : Error removing match rule, error=%s\r\n",
00870              __FILE__, __LINE__, error.message);
00871     }
00872 
00873     /* TODO: remove all other match rules */
00874 
00875     /* set a flag so we don't propagte callbacks from this context anymore */
00876     ctx->is_shutdown = TRUE;
00877 
00878     /* yikes, it's dangerous to unref the connection since it will terminate the process
00879      * because this connection may be shared so we cannot set the exit_on_disconnect flag
00880      *
00881      * so we don't do that right now 
00882      *
00883      */
00884     /*dbus_connection_unref (ctx->connection);*/
00885 
00886     /* we also refuse to free the resources as filter_function may reference these 
00887      * 
00888      * should free async when our connection goes away.
00889      */
00890     /* free (ctx); */
00891     return 0;
00892 }
00893 #endif
00894 
00906 char **
00907 libhal_get_all_devices (LibHalContext *ctx, int *num_devices, DBusError *error)
00908 {
00909     DBusMessage *message;
00910     DBusMessage *reply;
00911     DBusMessageIter iter_array, reply_iter;
00912     char **hal_device_names;
00913     DBusError _error;
00914 
00915     *num_devices = 0;
00916 
00917     message = dbus_message_new_method_call ("org.freedesktop.Hal",
00918                         "/org/freedesktop/Hal/Manager",
00919                         "org.freedesktop.Hal.Manager",
00920                         "GetAllDevices");
00921     if (message == NULL) {
00922         fprintf (stderr, "%s %d : Could not allocate D-BUS message\n", __FILE__, __LINE__);
00923         return NULL;
00924     }
00925 
00926     dbus_error_init (&_error);
00927     reply = dbus_connection_send_with_reply_and_block (ctx->connection, message, -1, &_error);
00928 
00929     dbus_move_error (&_error, error);
00930     if (error != NULL && dbus_error_is_set (error)) {
00931         dbus_message_unref (message);
00932         return NULL;
00933     }
00934     if (reply == NULL) {
00935         dbus_message_unref (message);
00936         return NULL;
00937     }
00938 
00939     /* now analyze reply */
00940     dbus_message_iter_init (reply, &reply_iter);
00941 
00942     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
00943         fprintf (stderr, "%s %d : wrong reply from hald.  Expecting an array.\n", __FILE__, __LINE__);
00944         return NULL;
00945     }
00946     
00947     dbus_message_iter_recurse (&reply_iter, &iter_array);
00948 
00949     hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
00950               
00951     dbus_message_unref (reply);
00952     dbus_message_unref (message);
00953 
00954     return hal_device_names;
00955 }
00956 
00970 LibHalPropertyType
00971 libhal_device_get_property_type (LibHalContext *ctx, const char *udi, const char *key, DBusError *error)
00972 {
00973     DBusMessage *message;
00974     DBusMessage *reply;
00975     DBusMessageIter iter, reply_iter;
00976     int type;
00977     DBusError _error;
00978 
00979     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
00980                         "org.freedesktop.Hal.Device",
00981                         "GetPropertyType");
00982     if (message == NULL) {
00983         fprintf (stderr, "%s %d : Couldn't allocate D-BUS message\n", __FILE__, __LINE__);
00984         return LIBHAL_PROPERTY_TYPE_INVALID;
00985     }
00986 
00987     dbus_message_iter_init_append (message, &iter);
00988     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
00989 
00990     dbus_error_init (&_error);
00991     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
00992                                message, -1,
00993                                &_error);
00994 
00995     dbus_move_error (&_error, error);
00996     if (error != NULL && dbus_error_is_set (error)) {
00997         dbus_message_unref (message);
00998         return LIBHAL_PROPERTY_TYPE_INVALID;
00999     }
01000     if (reply == NULL) {
01001         dbus_message_unref (message);
01002         return LIBHAL_PROPERTY_TYPE_INVALID;
01003     }
01004 
01005     dbus_message_iter_init (reply, &reply_iter);
01006     dbus_message_iter_get_basic (&reply_iter, &type);
01007 
01008     dbus_message_unref (message);
01009     dbus_message_unref (reply);
01010 
01011     return type;
01012 }
01013 
01029 char **
01030 libhal_device_get_property_strlist (LibHalContext *ctx, const char *udi, const char *key, DBusError *error)
01031 {
01032     DBusMessage *message;
01033     DBusMessage *reply;
01034     DBusMessageIter iter, iter_array, reply_iter;
01035     char **our_strings;
01036     DBusError _error;
01037 
01038     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01039                         "org.freedesktop.Hal.Device",
01040                         "GetPropertyStringList");
01041     if (message == NULL) {
01042         fprintf (stderr,
01043              "%s %d : Couldn't allocate D-BUS message\n",
01044              __FILE__, __LINE__);
01045         return NULL;
01046     }
01047 
01048     dbus_message_iter_init_append (message, &iter);
01049     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01050 
01051     dbus_error_init (&_error);
01052     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01053                                message, -1,
01054                                &_error);
01055 
01056     dbus_move_error (&_error, error);
01057     if (error != NULL && dbus_error_is_set (error)) {
01058         dbus_message_unref (message);
01059         return NULL;
01060     }
01061     if (reply == NULL) {
01062         dbus_message_unref (message);
01063         return NULL;
01064     }
01065     /* now analyse reply */
01066     dbus_message_iter_init (reply, &reply_iter);
01067 
01068     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
01069         fprintf (stderr, "%s %d : wrong reply from hald.  Expecting an array.\n", __FILE__, __LINE__);
01070         return NULL;
01071     }
01072     
01073     dbus_message_iter_recurse (&reply_iter, &iter_array);
01074 
01075     our_strings = libhal_get_string_array_from_iter (&iter_array, NULL);
01076               
01077     dbus_message_unref (reply);
01078     dbus_message_unref (message);
01079 
01080     return our_strings;
01081 }
01082 
01096 char *
01097 libhal_device_get_property_string (LibHalContext *ctx,
01098                    const char *udi, const char *key, DBusError *error)
01099 {
01100     DBusMessage *message;
01101     DBusMessage *reply;
01102     DBusMessageIter iter, reply_iter;
01103     char *value;
01104     char *dbus_str;
01105     DBusError _error;
01106 
01107     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01108                         "org.freedesktop.Hal.Device",
01109                         "GetPropertyString");
01110 
01111     if (message == NULL) {
01112         fprintf (stderr,
01113              "%s %d : Couldn't allocate D-BUS message\n",
01114              __FILE__, __LINE__);
01115         return NULL;
01116     }
01117 
01118     dbus_message_iter_init_append (message, &iter);
01119     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01120 
01121     dbus_error_init (&_error);
01122     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01123                                message, -1,
01124                                &_error);
01125 
01126     dbus_move_error (&_error, error);
01127     if (error != NULL && dbus_error_is_set (error)) {
01128         dbus_message_unref (message);
01129         return NULL;
01130     }
01131     if (reply == NULL) {
01132         dbus_message_unref (message);
01133         return NULL;
01134     }
01135 
01136     dbus_message_iter_init (reply, &reply_iter);
01137 
01138     /* now analyze reply */
01139     if (dbus_message_iter_get_arg_type (&reply_iter) !=
01140            DBUS_TYPE_STRING) {
01141         dbus_message_unref (message);
01142         dbus_message_unref (reply);
01143         return NULL;
01144     }
01145 
01146     dbus_message_iter_get_basic (&reply_iter, &dbus_str);
01147     value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
01148     if (value == NULL) {
01149         fprintf (stderr, "%s %d : error allocating memory\n",
01150              __FILE__, __LINE__);
01152         return NULL;
01153     }
01154 
01155     dbus_message_unref (message);
01156     dbus_message_unref (reply);
01157     return value;
01158 }
01159 
01169 dbus_int32_t
01170 libhal_device_get_property_int (LibHalContext *ctx, 
01171                 const char *udi, const char *key, DBusError *error)
01172 {
01173     DBusMessage *message;
01174     DBusMessage *reply;
01175     DBusMessageIter iter, reply_iter;
01176     dbus_int32_t value;
01177     DBusError _error;
01178 
01179     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01180                         "org.freedesktop.Hal.Device",
01181                         "GetPropertyInteger");
01182     if (message == NULL) {
01183         fprintf (stderr,
01184              "%s %d : Couldn't allocate D-BUS message\n",
01185              __FILE__, __LINE__);
01186         return -1;
01187     }
01188 
01189     dbus_message_iter_init_append (message, &iter);
01190     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01191 
01192     dbus_error_init (&_error);
01193     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01194                                message, -1,
01195                                &_error);
01196 
01197     dbus_move_error (&_error, error);
01198     if (error != NULL && dbus_error_is_set (error)) {
01199         dbus_message_unref (message);
01200         return -1;
01201     }
01202     if (reply == NULL) {
01203         dbus_message_unref (message);
01204         return -1;
01205     }
01206 
01207     dbus_message_iter_init (reply, &reply_iter);
01208 
01209     /* now analyze reply */
01210     if (dbus_message_iter_get_arg_type (&reply_iter) !=
01211            DBUS_TYPE_INT32) {
01212         fprintf (stderr,
01213              "%s %d : property '%s' for device '%s' is not "
01214              "of type integer\n", __FILE__, __LINE__, key,
01215              udi);
01216         dbus_message_unref (message);
01217         dbus_message_unref (reply);
01218         return -1;
01219     }
01220     dbus_message_iter_get_basic (&reply_iter, &value);
01221 
01222     dbus_message_unref (message);
01223     dbus_message_unref (reply);
01224     return value;
01225 }
01226 
01236 dbus_uint64_t
01237 libhal_device_get_property_uint64 (LibHalContext *ctx, 
01238                    const char *udi, const char *key, DBusError *error)
01239 {
01240     DBusMessage *message;
01241     DBusMessage *reply;
01242     DBusMessageIter iter, reply_iter;
01243     dbus_uint64_t value;
01244     DBusError _error;
01245 
01246     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01247                         "org.freedesktop.Hal.Device",
01248                         "GetPropertyInteger");
01249     if (message == NULL) {
01250         fprintf (stderr,
01251              "%s %d : Couldn't allocate D-BUS message\n",
01252              __FILE__, __LINE__);
01253         return -1;
01254     }
01255 
01256     dbus_message_iter_init_append (message, &iter);
01257     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01258 
01259     dbus_error_init (&_error);
01260     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01261                                message, -1,
01262                                &_error);
01263     
01264     dbus_move_error (&_error, error);
01265     if (error != NULL && dbus_error_is_set (error)) {
01266         dbus_message_unref (message);
01267         return -1;
01268     }
01269     if (reply == NULL) {
01270         dbus_message_unref (message);
01271         return -1;
01272     }
01273 
01274     dbus_message_iter_init (reply, &reply_iter);
01275     /* now analyze reply */
01276     if (dbus_message_iter_get_arg_type (&reply_iter) !=
01277            DBUS_TYPE_UINT64) {
01278         fprintf (stderr,
01279              "%s %d : property '%s' for device '%s' is not "
01280              "of type integer\n", __FILE__, __LINE__, key,
01281              udi);
01282         dbus_message_unref (message);
01283         dbus_message_unref (reply);
01284         return -1;
01285     }
01286     dbus_message_iter_get_basic (&reply_iter, &value);
01287 
01288     dbus_message_unref (message);
01289     dbus_message_unref (reply);
01290     return value;
01291 }
01292 
01302 double
01303 libhal_device_get_property_double (LibHalContext *ctx, 
01304                    const char *udi, const char *key, DBusError *error)
01305 {
01306     DBusMessage *message;
01307     DBusMessage *reply;
01308     DBusMessageIter iter, reply_iter;
01309     double value;
01310     DBusError _error;
01311 
01312     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01313                         "org.freedesktop.Hal.Device",
01314                         "GetPropertyDouble");
01315     if (message == NULL) {
01316         fprintf (stderr,
01317              "%s %d : Couldn't allocate D-BUS message\n",
01318              __FILE__, __LINE__);
01319         return -1.0f;
01320     }
01321 
01322     dbus_message_iter_init_append (message, &iter);
01323     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01324 
01325     dbus_error_init (&_error);
01326     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01327                                message, -1,
01328                                &_error);
01329 
01330     dbus_move_error (&_error, error);
01331     if (error != NULL && dbus_error_is_set (error)) {
01332         dbus_message_unref (message);
01333         return -1.0f;
01334     }
01335     if (reply == NULL) {
01336         dbus_message_unref (message);
01337         return -1.0f;
01338     }
01339 
01340     dbus_message_iter_init (reply, &reply_iter);
01341 
01342     /* now analyze reply */
01343     if (dbus_message_iter_get_arg_type (&reply_iter) !=
01344            DBUS_TYPE_DOUBLE) {
01345         fprintf (stderr,
01346              "%s %d : property '%s' for device '%s' is not "
01347              "of type double\n", __FILE__, __LINE__, key, udi);
01348         dbus_message_unref (message);
01349         dbus_message_unref (reply);
01350         return -1.0f;
01351     }
01352     dbus_message_iter_get_basic (&reply_iter, &value);
01353 
01354     dbus_message_unref (message);
01355     dbus_message_unref (reply);
01356     return (double) value;
01357 }
01358 
01368 dbus_bool_t
01369 libhal_device_get_property_bool (LibHalContext *ctx, 
01370                  const char *udi, const char *key, DBusError *error)
01371 {
01372     DBusMessage *message;
01373     DBusMessage *reply;
01374     DBusMessageIter iter, reply_iter;
01375     dbus_bool_t value;
01376     DBusError _error;
01377 
01378     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01379                         "org.freedesktop.Hal.Device",
01380                         "GetPropertyBoolean");
01381     if (message == NULL) {
01382         fprintf (stderr,
01383              "%s %d : Couldn't allocate D-BUS message\n",
01384              __FILE__, __LINE__);
01385         return FALSE;
01386     }
01387 
01388     dbus_message_iter_init_append (message, &iter);
01389     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01390     
01391     dbus_error_init (&_error);
01392     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01393                                message, -1,
01394                                &_error);
01395 
01396     dbus_move_error (&_error, error);
01397     if (error != NULL && dbus_error_is_set (error)) {
01398         dbus_message_unref (message);
01399         return FALSE;
01400     }
01401     if (reply == NULL) {
01402         dbus_message_unref (message);
01403         return FALSE;
01404     }
01405 
01406     dbus_message_iter_init (reply, &reply_iter);
01407 
01408     /* now analyze reply */
01409     if (dbus_message_iter_get_arg_type (&reply_iter) !=
01410            DBUS_TYPE_BOOLEAN) {
01411         fprintf (stderr,
01412              "%s %d : property '%s' for device '%s' is not "
01413              "of type bool\n", __FILE__, __LINE__, key, udi);
01414         dbus_message_unref (message);
01415         dbus_message_unref (reply);
01416         return FALSE;
01417     }
01418     dbus_message_iter_get_basic (&reply_iter, &value);
01419 
01420     dbus_message_unref (message);
01421     dbus_message_unref (reply);
01422     return value;
01423 }
01424 
01425 
01426 /* generic helper */
01427 static dbus_bool_t
01428 libhal_device_set_property_helper (LibHalContext *ctx, 
01429                    const char *udi,
01430                    const char *key,
01431                    int type,
01432                    const char *str_value,
01433                    dbus_int32_t int_value,
01434                    dbus_uint64_t uint64_value,
01435                    double double_value,
01436                    dbus_bool_t bool_value,
01437                    DBusError *error)
01438 {
01439     DBusMessage *message;
01440     DBusMessage *reply;
01441     DBusMessageIter iter;
01442     char *method_name = NULL;
01443 
01445     switch (type) {
01446     case DBUS_TYPE_INVALID:
01447         method_name = "RemoveProperty";
01448         break;
01449     case DBUS_TYPE_STRING:
01450         method_name = "SetPropertyString";
01451         break;
01452     case DBUS_TYPE_INT32:
01453     case DBUS_TYPE_UINT64:
01454         method_name = "SetPropertyInteger";
01455         break;
01456     case DBUS_TYPE_DOUBLE:
01457         method_name = "SetPropertyDouble";
01458         break;
01459     case DBUS_TYPE_BOOLEAN:
01460         method_name = "SetPropertyBoolean";
01461         break;
01462 
01463     default:
01464         /* cannot happen; is not callable from outside this file */
01465         break;
01466     }
01467 
01468     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01469                         "org.freedesktop.Hal.Device",
01470                         method_name);
01471     if (message == NULL) {
01472         fprintf (stderr,
01473              "%s %d : Couldn't allocate D-BUS message\n",
01474              __FILE__, __LINE__);
01475         return FALSE;
01476     }
01477 
01478     dbus_message_iter_init_append (message, &iter);
01479     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01480     switch (type) {
01481     case DBUS_TYPE_STRING:
01482         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &str_value);
01483         break;
01484     case DBUS_TYPE_INT32:
01485         dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &int_value);
01486         break;
01487     case DBUS_TYPE_UINT64:
01488         dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT64, &uint64_value);
01489         break;
01490     case DBUS_TYPE_DOUBLE:
01491         dbus_message_iter_append_basic (&iter, DBUS_TYPE_DOUBLE, &double_value);
01492         break;
01493     case DBUS_TYPE_BOOLEAN:
01494         dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &bool_value);
01495         break;
01496     }
01497 
01498     
01499     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01500                                message, -1,
01501                                error);
01502     if (dbus_error_is_set (error)) {
01503         dbus_message_unref (message);
01504         return FALSE;
01505     }
01506 
01507     if (reply == NULL) {
01508         dbus_message_unref (message);
01509         return FALSE;
01510     }
01511 
01512     dbus_message_unref (message);
01513     dbus_message_unref (reply);
01514 
01515     return TRUE;
01516 }
01517 
01530 dbus_bool_t
01531 libhal_device_set_property_string (LibHalContext *ctx, 
01532                    const char *udi,
01533                    const char *key, 
01534                    const char *value,
01535                    DBusError *error)
01536 {
01537     return libhal_device_set_property_helper (ctx, udi, key,
01538                           DBUS_TYPE_STRING,
01539                           value, 0, 0, 0.0f, FALSE, error);
01540 }
01541 
01554 dbus_bool_t
01555 libhal_device_set_property_int (LibHalContext *ctx, const char *udi,
01556                 const char *key, dbus_int32_t value, DBusError *error)
01557 {
01558     return libhal_device_set_property_helper (ctx, udi, key,
01559                           DBUS_TYPE_INT32,
01560                           NULL, value, 0, 0.0f, FALSE, error);
01561 }
01562 
01575 dbus_bool_t
01576 libhal_device_set_property_uint64 (LibHalContext *ctx, const char *udi,
01577                    const char *key, dbus_uint64_t value, DBusError *error)
01578 {
01579     return libhal_device_set_property_helper (ctx, udi, key,
01580                           DBUS_TYPE_UINT64,
01581                           NULL, 0, value, 0.0f, FALSE, error);
01582 }
01583 
01596 dbus_bool_t
01597 libhal_device_set_property_double (LibHalContext *ctx, const char *udi,
01598                    const char *key, double value, DBusError *error)
01599 {
01600     return libhal_device_set_property_helper (ctx, udi, key,
01601                           DBUS_TYPE_DOUBLE,
01602                           NULL, 0, 0, value, FALSE, error);
01603 }
01604 
01617 dbus_bool_t
01618 libhal_device_set_property_bool (LibHalContext *ctx, const char *udi,
01619                  const char *key, dbus_bool_t value, DBusError *error)
01620 {
01621     return libhal_device_set_property_helper (ctx, udi, key,
01622                           DBUS_TYPE_BOOLEAN,
01623                           NULL, 0, 0, 0.0f, value, error);
01624 }
01625 
01626 
01637 dbus_bool_t
01638 libhal_device_remove_property (LibHalContext *ctx, 
01639                    const char *udi, const char *key, DBusError *error)
01640 {
01641     return libhal_device_set_property_helper (ctx, udi, key, DBUS_TYPE_INVALID, 
01642                           /* DBUS_TYPE_INVALID means remove */
01643                           NULL, 0, 0, 0.0f, FALSE, error);
01644 }
01645 
01658 dbus_bool_t
01659 libhal_device_property_strlist_append (LibHalContext *ctx, 
01660                        const char *udi,
01661                        const char *key,
01662                        const char *value,
01663                        DBusError *error)
01664 {
01665     DBusMessage *message;
01666     DBusMessage *reply;
01667     DBusMessageIter iter;
01668 
01669     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01670                         "org.freedesktop.Hal.Device",
01671                         "StringListAppend");
01672     if (message == NULL) {
01673         fprintf (stderr,
01674              "%s %d : Couldn't allocate D-BUS message\n",
01675              __FILE__, __LINE__);
01676         return FALSE;
01677     }
01678     dbus_message_iter_init_append (message, &iter);
01679     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01680     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
01681     
01682     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01683                                message, -1,
01684                                error);
01685     if (dbus_error_is_set (error)) {
01686         dbus_message_unref (message);
01687         return FALSE;
01688     }
01689     if (reply == NULL) {
01690         dbus_message_unref (message);
01691         return FALSE;
01692     }
01693     return TRUE;
01694 }
01695 
01708 dbus_bool_t
01709 libhal_device_property_strlist_prepend (LibHalContext *ctx, 
01710                     const char *udi,
01711                     const char *key,
01712                     const char *value, 
01713                     DBusError *error)
01714 {
01715     DBusMessage *message;
01716     DBusMessage *reply;
01717     DBusMessageIter iter;
01718 
01719     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01720                         "org.freedesktop.Hal.Device",
01721                         "StringListPrepend");
01722     if (message == NULL) {
01723         fprintf (stderr,
01724              "%s %d : Couldn't allocate D-BUS message\n",
01725              __FILE__, __LINE__);
01726         return FALSE;
01727     }
01728     dbus_message_iter_init_append (message, &iter);
01729     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01730     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
01731     
01732     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01733                                message, -1,
01734                                error);
01735     if (dbus_error_is_set (error)) {
01736         dbus_message_unref (message);
01737         return FALSE;
01738     }
01739     if (reply == NULL) {
01740         dbus_message_unref (message);
01741         return FALSE;
01742     }
01743     return TRUE;
01744 }
01745 
01758 dbus_bool_t
01759 libhal_device_property_strlist_remove_index (LibHalContext *ctx, 
01760                          const char *udi,
01761                          const char *key,
01762                          unsigned int index,
01763                          DBusError *error)
01764 {
01765     DBusMessage *message;
01766     DBusMessage *reply;
01767     DBusMessageIter iter;
01768 
01769     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01770                         "org.freedesktop.Hal.Device",
01771                         "StringListRemoveIndex");
01772     if (message == NULL) {
01773         fprintf (stderr,
01774              "%s %d : Couldn't allocate D-BUS message\n",
01775              __FILE__, __LINE__);
01776         return FALSE;
01777     }
01778     dbus_message_iter_init_append (message, &iter);
01779     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01780     dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &index);
01781     
01782     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01783                                message, -1,
01784                                error);
01785     if (dbus_error_is_set (error)) {
01786         dbus_message_unref (message);
01787         return FALSE;
01788     }
01789     if (reply == NULL) {
01790         dbus_message_unref (message);
01791         return FALSE;
01792     }
01793     return TRUE;
01794 }
01795 
01808 dbus_bool_t
01809 libhal_device_property_strlist_remove (LibHalContext *ctx, 
01810                        const char *udi,
01811                        const char *key,
01812                        const char *value, DBusError *error)
01813 {
01814     DBusMessage *message;
01815     DBusMessage *reply;
01816     DBusMessageIter iter;
01817 
01818     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
01819                         "org.freedesktop.Hal.Device",
01820                         "StringListRemove");
01821     if (message == NULL) {
01822         fprintf (stderr,
01823              "%s %d : Couldn't allocate D-BUS message\n",
01824              __FILE__, __LINE__);
01825         return FALSE;
01826     }
01827     dbus_message_iter_init_append (message, &iter);
01828     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
01829     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
01830     
01831     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01832                                message, -1,
01833                                error);
01834     if (dbus_error_is_set (error)) {
01835         dbus_message_unref (message);
01836         return FALSE;
01837     }
01838     if (reply == NULL) {
01839         dbus_message_unref (message);
01840         return FALSE;
01841     }
01842     return TRUE;
01843 }
01844 
01845 
01860 dbus_bool_t
01861 libhal_device_lock (LibHalContext *ctx,
01862             const char *udi,
01863             const char *reason_to_lock,
01864             char **reason_why_locked, DBusError *error)
01865 {
01866     DBusMessage *message;
01867     DBusMessageIter iter;
01868     DBusMessage *reply;
01869 
01870     if (reason_why_locked != NULL)
01871         *reason_why_locked = NULL;
01872 
01873     message = dbus_message_new_method_call ("org.freedesktop.Hal",
01874                         udi,
01875                         "org.freedesktop.Hal.Device",
01876                         "Lock");
01877 
01878     if (message == NULL) {
01879         fprintf (stderr,
01880              "%s %d : Couldn't allocate D-BUS message\n",
01881              __FILE__, __LINE__);
01882         return FALSE;
01883     }
01884 
01885     dbus_message_iter_init_append (message, &iter);
01886     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &reason_to_lock);
01887 
01888     
01889     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01890                                message, -1,
01891                                error);
01892 
01893     if (dbus_error_is_set (error)) {
01894         if (strcmp (error->name,
01895                 "org.freedesktop.Hal.DeviceAlreadyLocked") == 0) {
01896             if (reason_why_locked != NULL) {
01897                 *reason_why_locked =
01898                     dbus_malloc0 (strlen (error->message) + 1);
01899                 strcpy (*reason_why_locked, error->message);
01900             }
01901         }
01902 
01903         dbus_message_unref (message);
01904         return FALSE;
01905     }
01906 
01907     dbus_message_unref (message);
01908 
01909     if (reply == NULL)
01910         return FALSE;
01911 
01912     dbus_message_unref (reply);
01913 
01914     return TRUE;
01915 }
01916 
01926 dbus_bool_t
01927 libhal_device_unlock (LibHalContext *ctx,
01928               const char *udi, DBusError *error)
01929 {
01930     DBusMessage *message;
01931     DBusMessage *reply;
01932 
01933     message = dbus_message_new_method_call ("org.freedesktop.Hal",
01934                         udi,
01935                         "org.freedesktop.Hal.Device",
01936                         "Unlock");
01937 
01938     if (message == NULL) {
01939         fprintf (stderr,
01940              "%s %d : Couldn't allocate D-BUS message\n",
01941              __FILE__, __LINE__);
01942         return FALSE;
01943     }
01944 
01945     
01946     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
01947                                message, -1,
01948                                error);
01949 
01950     if (dbus_error_is_set (error)) {
01951         dbus_message_unref (message);
01952         return FALSE;
01953     }
01954 
01955     dbus_message_unref (message);
01956 
01957     if (reply == NULL)
01958         return FALSE;
01959 
01960     dbus_message_unref (reply);
01961 
01962     return TRUE;
01963 }
01964 
01965 
01979 char *
01980 libhal_agent_new_device (LibHalContext *ctx, DBusError *error)
01981 {
01982     DBusMessage *message;
01983     DBusMessage *reply;
01984     DBusMessageIter reply_iter;
01985     char *value;
01986     char *dbus_str;
01987 
01988     message = dbus_message_new_method_call ("org.freedesktop.Hal",
01989                         "/org/freedesktop/Hal/Manager",
01990                         "org.freedesktop.Hal.AgentManager",
01991                         "NewDevice");
01992     if (message == NULL) {
01993         fprintf (stderr,
01994              "%s %d : Couldn't allocate D-BUS message\n",
01995              __FILE__, __LINE__);
01996         return NULL;
01997     }
01998 
01999     
02000     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02001                                message, -1,
02002                                error);
02003     if (dbus_error_is_set (error)) {
02004         dbus_message_unref (message);
02005         return NULL;
02006     }
02007     if (reply == NULL) {
02008         dbus_message_unref (message);
02009         return NULL;
02010     }
02011 
02012     dbus_message_iter_init (reply, &reply_iter);
02013 
02014     /* now analyze reply */
02015     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_STRING) {
02016         fprintf (stderr,
02017              "%s %d : expected a string in reply to NewDevice\n",
02018              __FILE__, __LINE__);
02019         dbus_message_unref (message);
02020         dbus_message_unref (reply);
02021         return NULL;
02022     }
02023 
02024     dbus_message_iter_get_basic (&reply_iter, &dbus_str);
02025     value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
02026     if (value == NULL) {
02027         fprintf (stderr, "%s %d : error allocating memory\n",
02028              __FILE__, __LINE__);
02030         return NULL;
02031     }
02032 
02033     dbus_message_unref (message);
02034     dbus_message_unref (reply);
02035     return value;
02036 }
02037 
02038 
02059 dbus_bool_t
02060 libhal_agent_commit_to_gdl (LibHalContext *ctx, 
02061                 const char *temp_udi, const char *udi, DBusError *error)
02062 {
02063     DBusMessage *message;
02064     DBusMessage *reply;
02065     DBusMessageIter iter;
02066 
02067     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02068                         "/org/freedesktop/Hal/Manager",
02069                         "org.freedesktop.Hal.AgentManager",
02070                         "CommitToGdl");
02071     if (message == NULL) {
02072         fprintf (stderr,
02073              "%s %d : Couldn't allocate D-BUS message\n",
02074              __FILE__, __LINE__);
02075         return FALSE;
02076     }
02077 
02078     dbus_message_iter_init_append (message, &iter);
02079     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &temp_udi);
02080     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
02081 
02082     
02083     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02084                                message, -1,
02085                                error);
02086     if (dbus_error_is_set (error)) {
02087         dbus_message_unref (message);
02088         return FALSE;
02089     }
02090     if (reply == NULL) {
02091         dbus_message_unref (message);
02092         return FALSE;
02093     }
02094 
02095     dbus_message_unref (message);
02096     dbus_message_unref (reply);
02097     return TRUE;
02098 }
02099 
02113 dbus_bool_t
02114 libhal_agent_remove_device (LibHalContext *ctx, const char *udi, DBusError *error)
02115 {
02116     DBusMessage *message;
02117     DBusMessage *reply;
02118     DBusMessageIter iter;
02119 
02120     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02121                         "/org/freedesktop/Hal/Manager",
02122                         "org.freedesktop.Hal.AgentManager",
02123                         "Remove");
02124     if (message == NULL) {
02125         fprintf (stderr,
02126              "%s %d : Couldn't allocate D-BUS message\n",
02127              __FILE__, __LINE__);
02128         return FALSE;
02129     }
02130 
02131     dbus_message_iter_init_append (message, &iter);
02132     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
02133 
02134     
02135     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02136                                message, -1,
02137                                error);
02138     if (dbus_error_is_set (error)) {
02139         dbus_message_unref (message);
02140         return FALSE;
02141     }
02142     if (reply == NULL) {
02143         dbus_message_unref (message);
02144         return FALSE;
02145     }
02146 
02147     dbus_message_unref (message);
02148     dbus_message_unref (reply);
02149     return TRUE;
02150 }
02151 
02160 dbus_bool_t
02161 libhal_device_exists (LibHalContext *ctx, const char *udi, DBusError *error)
02162 {
02163     DBusMessage *message;
02164     DBusMessage *reply;
02165     DBusMessageIter iter, reply_iter;
02166     dbus_bool_t value;
02167     DBusError _error;
02168 
02169     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02170                         "/org/freedesktop/Hal/Manager",
02171                         "org.freedesktop.Hal.Manager",
02172                         "DeviceExists");
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     dbus_error_init (&_error);
02184     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02185                                message, -1,
02186                                &_error);
02187 
02188     dbus_move_error (&_error, error);
02189     if (error != NULL && dbus_error_is_set (error)) {
02190         dbus_message_unref (message);
02191         return FALSE;
02192     }
02193     if (reply == NULL) {
02194         dbus_message_unref (message);
02195         return FALSE;
02196     }
02197 
02198     dbus_message_iter_init (reply, &reply_iter);
02199 
02200     /* now analyze reply */
02201     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
02202         fprintf (stderr,
02203              "%s %d : expected a bool in reply to DeviceExists\n",
02204              __FILE__, __LINE__);
02205         dbus_message_unref (message);
02206         dbus_message_unref (reply);
02207         return FALSE;
02208     }
02209 
02210     dbus_message_iter_get_basic (&reply_iter, &value);
02211 
02212     dbus_message_unref (message);
02213     dbus_message_unref (reply);
02214     return value;
02215 }
02216 
02226 dbus_bool_t
02227 libhal_device_property_exists (LibHalContext *ctx, 
02228                    const char *udi, const char *key, DBusError *error)
02229 {
02230     DBusMessage *message;
02231     DBusMessage *reply;
02232     DBusMessageIter iter, reply_iter;
02233     dbus_bool_t value;
02234     DBusError _error;
02235 
02236     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
02237                         "org.freedesktop.Hal.Device",
02238                         "PropertyExists");
02239     if (message == NULL) {
02240         fprintf (stderr,
02241              "%s %d : Couldn't allocate D-BUS message\n",
02242              __FILE__, __LINE__);
02243         return FALSE;
02244     }
02245 
02246     dbus_message_iter_init_append (message, &iter);
02247     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
02248 
02249     dbus_error_init (&_error);
02250     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02251                                message, -1,
02252                                &_error);
02253 
02254     dbus_move_error (&_error, error);
02255     if (error != NULL && dbus_error_is_set (error)) {
02256         dbus_message_unref (message);
02257         return FALSE;
02258     }
02259     if (reply == NULL) {
02260         dbus_message_unref (message);
02261         return FALSE;
02262     }
02263 
02264     dbus_message_iter_init (reply, &reply_iter);
02265 
02266     /* now analyse reply */
02267     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
02268         fprintf (stderr, "%s %d : expected a bool in reply to "
02269              "PropertyExists\n", __FILE__, __LINE__);
02270         dbus_message_unref (message);
02271         dbus_message_unref (reply);
02272         return FALSE;
02273     }
02274 
02275     dbus_message_iter_get_basic (&reply_iter, &value);
02276 
02277     dbus_message_unref (message);
02278     dbus_message_unref (reply);
02279     return value;
02280 }
02281 
02291 dbus_bool_t
02292 libhal_agent_merge_properties (LibHalContext *ctx, 
02293                    const char *target_udi, const char *source_udi, DBusError *error)
02294 {
02295     DBusMessage *message;
02296     DBusMessage *reply;
02297     DBusMessageIter iter;
02298 
02299     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02300                         "/org/freedesktop/Hal/Manager",
02301                         "org.freedesktop.Hal.AgentManager",
02302                         "MergeProperties");
02303     if (message == NULL) {
02304         fprintf (stderr,
02305              "%s %d : Couldn't allocate D-BUS message\n",
02306              __FILE__, __LINE__);
02307         return FALSE;
02308     }
02309 
02310     dbus_message_iter_init_append (message, &iter);
02311     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &target_udi);
02312     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &source_udi);
02313 
02314     
02315     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02316                                message, -1,
02317                                error);
02318     if (dbus_error_is_set (error)) {
02319         dbus_message_unref (message);
02320         return FALSE;
02321     }
02322     if (reply == NULL) {
02323         dbus_message_unref (message);
02324         return FALSE;
02325     }
02326 
02327     dbus_message_unref (message);
02328     dbus_message_unref (reply);
02329     return TRUE;
02330 }
02331 
02353 dbus_bool_t
02354 libhal_agent_device_matches (LibHalContext *ctx, 
02355                  const char *udi1, const char *udi2,
02356                  const char *property_namespace, DBusError *error)
02357 {
02358     DBusMessage *message;
02359     DBusMessage *reply;
02360     DBusMessageIter iter, reply_iter;
02361     dbus_bool_t value;
02362     DBusError _error;
02363 
02364     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02365                         "/org/freedesktop/Hal/Manager",
02366                         "org.freedesktop.Hal.AgentManager",
02367                         "DeviceMatches");
02368     if (message == NULL) {
02369         fprintf (stderr,
02370              "%s %d : Couldn't allocate D-BUS message\n",
02371              __FILE__, __LINE__);
02372         return FALSE;
02373     }
02374 
02375     dbus_message_iter_init_append (message, &iter);
02376     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, udi1);
02377     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, udi2);
02378     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, property_namespace);
02379 
02380     dbus_error_init (&_error);
02381     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02382                                message, -1,
02383                                &_error);
02384 
02385     dbus_move_error (&_error, error);
02386     if (error != NULL && dbus_error_is_set (error)) {
02387         dbus_message_unref (message);
02388         return FALSE;
02389     }
02390     if (reply == NULL) {
02391         dbus_message_unref (message);
02392         return FALSE;
02393     }
02394     /* now analyse reply */
02395     dbus_message_iter_init (reply, &reply_iter);
02396 
02397     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
02398         fprintf (stderr,
02399              "%s %d : expected a bool in reply to DeviceMatches\n",
02400              __FILE__, __LINE__);
02401         dbus_message_unref (message);
02402         dbus_message_unref (reply);
02403         return FALSE;
02404     }
02405 
02406     dbus_message_iter_get_basic (&reply_iter, &value);
02407 
02408     dbus_message_unref (message);
02409     dbus_message_unref (reply);
02410     return value;
02411 }
02412 
02422 dbus_bool_t
02423 libhal_device_print (LibHalContext *ctx, const char *udi, DBusError *error)
02424 {
02425     int type;
02426     char *key;
02427     LibHalPropertySet *pset;
02428     LibHalPropertySetIterator i;
02429 
02430     printf ("device_id = %s\n", udi);
02431 
02432     if ((pset = libhal_device_get_all_properties (ctx, udi, error)) == NULL)
02433         return FALSE;
02434 
02435     for (libhal_psi_init (&i, pset); libhal_psi_has_more (&i);
02436          libhal_psi_next (&i)) {
02437         type = libhal_psi_get_type (&i);
02438         key = libhal_psi_get_key (&i);
02439 
02440         switch (type) {
02441         case LIBHAL_PROPERTY_TYPE_STRING:
02442             printf ("    %s = '%s' (string)\n", key,
02443                 libhal_psi_get_string (&i));
02444             break;
02445         case LIBHAL_PROPERTY_TYPE_INT32:
02446             printf ("    %s = %d = 0x%x (int)\n", key,
02447                 libhal_psi_get_int (&i),
02448                 libhal_psi_get_int (&i));
02449             break;
02450         case LIBHAL_PROPERTY_TYPE_UINT64:
02451             printf ("    %s = %lld = 0x%llx (uint64)\n", key,
02452                 libhal_psi_get_uint64 (&i),
02453                 libhal_psi_get_uint64 (&i));
02454             break;
02455         case LIBHAL_PROPERTY_TYPE_BOOLEAN:
02456             printf ("    %s = %s (bool)\n", key,
02457                 (libhal_psi_get_bool (&i) ? "true" :
02458                  "false"));
02459             break;
02460         case LIBHAL_PROPERTY_TYPE_DOUBLE:
02461             printf ("    %s = %g (double)\n", key,
02462                 libhal_psi_get_double (&i));
02463             break;
02464         case LIBHAL_PROPERTY_TYPE_STRLIST:
02465         {
02466             unsigned int j;
02467             char **str_list;
02468 
02469             str_list = libhal_psi_get_strlist (&i);
02470             printf ("    %s = [", key);
02471             for (j = 0; str_list[j] != NULL; j++) {
02472                 printf ("'%s'", str_list[j]);
02473                 if (str_list[j+1] != NULL)
02474                     printf (", ");
02475             }
02476             printf ("] (string list)\n");
02477 
02478             break;
02479         }
02480         default:
02481             printf ("    *** unknown type for key %s\n", key);
02482             break;
02483         }
02484     }
02485 
02486     libhal_free_property_set (pset);
02487 
02488     return TRUE;
02489 }
02490 
02503 char **
02504 libhal_manager_find_device_string_match (LibHalContext *ctx, 
02505                      const char *key,
02506                      const char *value, int *num_devices, DBusError *error)
02507 {
02508     DBusMessage *message;
02509     DBusMessage *reply;
02510     DBusMessageIter iter, iter_array, reply_iter;
02511     char **hal_device_names;
02512     DBusError _error;
02513 
02514     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02515                         "/org/freedesktop/Hal/Manager",
02516                         "org.freedesktop.Hal.Manager",
02517                         "FindDeviceStringMatch");
02518     if (message == NULL) {
02519         fprintf (stderr,
02520              "%s %d : Couldn't allocate D-BUS message\n",
02521              __FILE__, __LINE__);
02522         return NULL;
02523     }
02524 
02525     dbus_message_iter_init_append (message, &iter);
02526     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
02527     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
02528 
02529     dbus_error_init (&_error);
02530     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02531                                message, -1,
02532                                &_error);
02533 
02534     dbus_move_error (&_error, error);
02535     if (error != NULL && dbus_error_is_set (error)) {
02536         dbus_message_unref (message);
02537         return NULL;
02538     }
02539     if (reply == NULL) {
02540         dbus_message_unref (message);
02541         return NULL;
02542     }
02543     /* now analyse reply */
02544     dbus_message_iter_init (reply, &reply_iter);
02545 
02546     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
02547         fprintf (stderr, "%s %d : wrong reply from hald.  Expecting an array.\n", __FILE__, __LINE__);
02548         return NULL;
02549     }
02550     
02551     dbus_message_iter_recurse (&reply_iter, &iter_array);
02552 
02553     hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
02554               
02555     dbus_message_unref (reply);
02556     dbus_message_unref (message);
02557 
02558     return hal_device_names;
02559 }
02560 
02561 
02572 dbus_bool_t
02573 libhal_device_add_capability (LibHalContext *ctx, 
02574                   const char *udi, const char *capability, DBusError *error)
02575 {
02576     DBusMessage *message;
02577     DBusMessage *reply;
02578     DBusMessageIter iter;
02579 
02580     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
02581                         "org.freedesktop.Hal.Device",
02582                         "AddCapability");
02583     if (message == NULL) {
02584         fprintf (stderr,
02585              "%s %d : Couldn't allocate D-BUS message\n",
02586              __FILE__, __LINE__);
02587         return FALSE;
02588     }
02589 
02590     dbus_message_iter_init_append (message, &iter);
02591     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability);
02592 
02593     
02594     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02595                                message, -1,
02596                                error);
02597     if (dbus_error_is_set (error)) {
02598         dbus_message_unref (message);
02599         return FALSE;
02600     }
02601 
02602     if (reply == NULL) {
02603         dbus_message_unref (message);
02604         return FALSE;
02605     }
02606 
02607     dbus_message_unref (reply);
02608     dbus_message_unref (message);
02609     return TRUE;
02610 }
02611 
02623 dbus_bool_t
02624 libhal_device_query_capability (LibHalContext *ctx, const char *udi, const char *capability, DBusError *error)
02625 {
02626     char **caps;
02627     unsigned int i;
02628     dbus_bool_t ret;
02629 
02630     ret = FALSE;
02631 
02632     caps = libhal_device_get_property_strlist (ctx, udi, "info.capabilities", error);
02633     if (caps != NULL) {
02634         for (i = 0; caps[i] != NULL; i++) {
02635             if (strcmp (caps[i], capability) == 0) {
02636                 ret = TRUE;
02637                 break;
02638             }
02639         }
02640         libhal_free_string_array (caps);
02641     }
02642 
02643     return ret;
02644 }
02645 
02656 char **
02657 libhal_find_device_by_capability (LibHalContext *ctx, 
02658                   const char *capability, int *num_devices, DBusError *error)
02659 {
02660     DBusMessage *message;
02661     DBusMessage *reply;
02662     DBusMessageIter iter, iter_array, reply_iter;
02663     char **hal_device_names;
02664     DBusError _error;
02665 
02666     message = dbus_message_new_method_call ("org.freedesktop.Hal",
02667                         "/org/freedesktop/Hal/Manager",
02668                         "org.freedesktop.Hal.Manager",
02669                         "FindDeviceByCapability");
02670     if (message == NULL) {
02671         fprintf (stderr,
02672              "%s %d : Couldn't allocate D-BUS message\n",
02673              __FILE__, __LINE__);
02674         return NULL;
02675     }
02676 
02677     dbus_message_iter_init_append (message, &iter);
02678     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability);
02679 
02680     dbus_error_init (&_error);
02681     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
02682                                message, -1,
02683                                &_error);
02684     
02685     dbus_move_error (&_error, error);
02686     if (error != NULL && dbus_error_is_set (error)) {
02687         dbus_message_unref (message);
02688         return NULL;
02689     }
02690     if (reply == NULL) {
02691         dbus_message_unref (message);
02692         return NULL;
02693     }
02694     /* now analyse reply */
02695     dbus_message_iter_init (reply, &reply_iter);
02696 
02697     if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
02698         fprintf (stderr, "%s %d : wrong reply from hald.  Expecting an array.\n", __FILE__, __LINE__);
02699         return NULL;
02700     }
02701     
02702     dbus_message_iter_recurse (&reply_iter, &iter_array);
02703 
02704     hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
02705               
02706     dbus_message_unref (reply);
02707     dbus_message_unref (message);
02708 
02709     return hal_device_names;
02710 }
02711 
02720 dbus_bool_t
02721 libhal_device_property_watch_all (LibHalContext *ctx, DBusError *error)
02722 {
02723     dbus_bus_add_match (ctx->connection,
02724                 "type='signal',"
02725                 "interface='org.freedesktop.Hal.Device',"
02726                 "sender='org.freedesktop.Hal'", error);
02727     if (dbus_error_is_set (error)) {
02728         return FALSE;
02729     }
02730     return TRUE;
02731 }
02732 
02733 
02746 dbus_bool_t
02747 libhal_device_add_property_watch (LibHalContext *ctx, const char *udi, DBusError *error)
02748 {
02749     char buf[512];
02750 
02751     snprintf (buf, 512,
02752           "type='signal',"
02753           "interface='org.freedesktop.Hal.Device',"
02754           "sender='org.freedesktop.Hal'," "path=%s", udi);
02755 
02756     dbus_bus_add_match (ctx->connection, buf, error);
02757     if (dbus_error_is_set (error)) {
02758         return FALSE;
02759     }
02760     return TRUE;
02761 }
02762 
02763 
02772 dbus_bool_t
02773 libhal_device_remove_property_watch (LibHalContext *ctx, const char *udi, DBusError *error)
02774 {
02775     char buf[512];
02776 
02777     snprintf (buf, 512,
02778           "type='signal',"
02779           "interface='org.freedesktop.Hal.Device',"
02780           "sender='org.freedesktop.Hal'," "path=%s", udi);
02781 
02782     dbus_bus_remove_match (ctx->connection, buf, error);
02783     if (dbus_error_is_set (error)) {
02784         return FALSE;
02785     }
02786     return TRUE;
02787 }
02788 
02789 
02794 LibHalContext *
02795 libhal_ctx_new (void)
02796 {
02797     LibHalContext *ctx;
02798 
02799     if (!libhal_already_initialized_once) {
02800         bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
02801         bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
02802         
02803         libhal_already_initialized_once = TRUE;
02804     }
02805 
02806     ctx = calloc (1, sizeof (LibHalContext));
02807     if (ctx == NULL) {
02808         fprintf (stderr, "%s %d : Failed to allocate %d bytes\n", __FILE__, __LINE__, sizeof (LibHalContext));
02809         return NULL;
02810     }
02811 
02812     ctx->is_initialized = FALSE;
02813     ctx->is_shutdown = FALSE;
02814     ctx->connection = NULL;
02815     ctx->is_direct = FALSE;
02816 
02817     return ctx;
02818 }
02819 
02829 dbus_bool_t
02830 libhal_ctx_set_cache (LibHalContext *ctx, dbus_bool_t use_cache)
02831 {
02832     if (ctx == NULL)
02833         return FALSE;
02834 
02835     ctx->cache_enabled = use_cache;
02836     return TRUE;
02837 }
02838 
02846 dbus_bool_t
02847 libhal_ctx_set_dbus_connection (LibHalContext *ctx, DBusConnection *conn)
02848 {
02849     if (ctx == NULL)
02850         return FALSE;
02851 
02852     if (conn == NULL)
02853         return FALSE;
02854 
02855     ctx->connection = conn;
02856     return TRUE;
02857 }
02858 
02867 dbus_bool_t 
02868 libhal_ctx_init (LibHalContext *ctx, DBusError *error)
02869 {
02870     DBusError _error;
02871 
02872     if (ctx == NULL)
02873         return FALSE;
02874 
02875     if (ctx->connection == NULL)
02876         return FALSE;
02877 
02878     
02879     if (!dbus_connection_add_filter (ctx->connection, filter_func, ctx, NULL)) {
02880         return FALSE;
02881     }
02882 
02883     dbus_error_init (&_error);
02884     dbus_bus_add_match (ctx->connection, 
02885                 "type='signal',"
02886                 "interface='org.freedesktop.Hal.Manager',"
02887                 "sender='org.freedesktop.Hal',"
02888                 "path='/org/freedesktop/Hal/Manager'", &_error);
02889     dbus_move_error (&_error, error);
02890     if (error != NULL && dbus_error_is_set (error)) {
02891         return FALSE;
02892     }
02893     ctx->is_initialized = TRUE;
02894     ctx->is_direct = FALSE;
02895 
02896     return TRUE;
02897 }
02898 
02905 LibHalContext *
02906 libhal_ctx_init_direct (DBusError *error)
02907 {
02908     char *hald_addr;
02909     LibHalContext *ctx;
02910     DBusError _error;
02911 
02912     ctx = libhal_ctx_new ();
02913     if (ctx == NULL)
02914         goto out;
02915 
02916     if (((hald_addr = getenv ("HALD_DIRECT_ADDR"))) == NULL) {
02917         libhal_ctx_free (ctx);
02918         ctx = NULL;
02919         goto out;
02920     }
02921 
02922     dbus_error_init (&_error);
02923     ctx->connection = dbus_connection_open (hald_addr, &_error);
02924     dbus_move_error (&_error, error);
02925     if (error != NULL && dbus_error_is_set (error)) {
02926         libhal_ctx_free (ctx);
02927         ctx = NULL;
02928         goto out;
02929     }
02930 
02931     ctx->is_initialized = TRUE;
02932     ctx->is_direct = TRUE;
02933 
02934 out:
02935     return ctx;
02936 }
02937 
02946 dbus_bool_t    
02947 libhal_ctx_shutdown (LibHalContext *ctx, DBusError *error)
02948 {
02949     DBusError myerror;
02950 
02951     if (ctx->is_direct) {
02952         /* for some reason dbus_connection_set_exit_on_disconnect doesn't work yet so don't unref */
02953         /*dbus_connection_unref (ctx->connection);*/
02954     } else {
02955         dbus_error_init (&myerror);
02956         dbus_bus_remove_match (ctx->connection, 
02957                        "type='signal',"
02958                        "interface='org.freedesktop.Hal.Manager',"
02959                        "sender='org.freedesktop.Hal',"
02960                        "path='/org/freedesktop/Hal/Manager'", &myerror);
02961         if (dbus_error_is_set (&myerror)) {
02962             fprintf (stderr, "%s %d : Error unsubscribing to signals, error=%s\n", 
02963                  __FILE__, __LINE__, error->message);
02965         }
02966 
02967         /* TODO: remove other matches */
02968 
02969         dbus_connection_remove_filter (ctx->connection, filter_func, ctx);
02970     }
02971 
02972     ctx->is_initialized = FALSE;
02973 
02974     return TRUE;
02975 }
02976 
02982 dbus_bool_t    
02983 libhal_ctx_free (LibHalContext *ctx)
02984 {
02985     free (ctx);
02986     return TRUE;
02987 }
02988 
02996 dbus_bool_t
02997 libhal_ctx_set_device_added (LibHalContext *ctx, LibHalDeviceAdded callback)
02998 {
02999     if (ctx == NULL)
03000         return FALSE;
03001     ctx->device_added = callback;
03002     return TRUE;
03003 }
03004 
03012 dbus_bool_t
03013 libhal_ctx_set_device_removed (LibHalContext *ctx, LibHalDeviceRemoved callback)
03014 {
03015     if (ctx == NULL)
03016         return FALSE;
03017     ctx->device_removed = callback;
03018     return TRUE;
03019 }
03020 
03029 dbus_bool_t
03030 libhal_ctx_set_device_new_capability (LibHalContext *ctx, LibHalDeviceNewCapability callback)
03031 {
03032     if (ctx == NULL)
03033         return FALSE;
03034     ctx->device_new_capability = callback;
03035     return TRUE;
03036 }
03037 
03046 dbus_bool_t
03047 libhal_ctx_set_device_lost_capability (LibHalContext *ctx, LibHalDeviceLostCapability callback)
03048 {
03049     if (ctx == NULL)
03050         return FALSE;
03051     ctx->device_lost_capability = callback;
03052     return TRUE;
03053 }
03054 
03063 dbus_bool_t
03064 libhal_ctx_set_device_property_modified (LibHalContext *ctx, LibHalDevicePropertyModified callback)
03065 {
03066     if (ctx == NULL)
03067         return FALSE;
03068     ctx->device_property_modified = callback;
03069     return TRUE;
03070 }
03071 
03079 dbus_bool_t
03080 libhal_ctx_set_device_condition (LibHalContext *ctx, LibHalDeviceCondition callback)
03081 {
03082     if (ctx == NULL)
03083         return FALSE;
03084     ctx->device_condition = callback;
03085     return TRUE;
03086 }
03087 
03093 unsigned int libhal_string_array_length (char **str_array)
03094 {
03095     unsigned int i;
03096 
03097     if (str_array == NULL)
03098         return 0;
03099 
03100     for (i = 0; str_array[i] != NULL; i++)
03101         ;
03102 
03103     return i;
03104 }
03105 
03106 
03107 dbus_bool_t 
03108 libhal_device_rescan (LibHalContext *ctx, const char *udi, DBusError *error)
03109 {
03110     DBusMessage *message;
03111     DBusMessageIter reply_iter;
03112     DBusMessage *reply;
03113     dbus_bool_t result;
03114 
03115     message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
03116                         "org.freedesktop.Hal.Device",
03117                         "Rescan");
03118 
03119     if (message == NULL) {
03120         fprintf (stderr,
03121              "%s %d : Couldn't allocate D-BUS message\n",
03122              __FILE__, __LINE__);
03123         return FALSE;
03124     }
03125     
03126     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
03127                                message, -1,
03128                                error);
03129 
03130     if (dbus_error_is_set (error)) {
03131         dbus_message_unref (message);
03132         return FALSE;
03133     }
03134 
03135     dbus_message_unref (message);
03136 
03137     if (reply == NULL)
03138         return FALSE;
03139 
03140     dbus_message_iter_init (reply, &reply_iter);
03141     if (dbus_message_iter_get_arg_type (&reply_iter) !=
03142            DBUS_TYPE_BOOLEAN) {
03143         dbus_message_unref (message);
03144         dbus_message_unref (reply);
03145         return FALSE;
03146     }
03147     dbus_message_iter_get_basic (&reply_iter, &result);
03148 
03149     dbus_message_unref (reply);
03150 
03151     return result;
03152 }
03153 
03154 dbus_bool_t
03155 libhal_device_reprobe (LibHalContext *ctx, const char *udi, DBusError *error)
03156 {
03157     DBusMessage *message;
03158     DBusMessageIter reply_iter;
03159     DBusMessage *reply;
03160     dbus_bool_t result;
03161 
03162     message = dbus_message_new_method_call ("org.freedesktop.Hal",
03163                         udi,
03164                         "org.freedesktop.Hal.Device",
03165                         "Reprobe");
03166 
03167     if (message == NULL) {
03168         fprintf (stderr,
03169              "%s %d : Couldn't allocate D-BUS message\n",
03170              __FILE__, __LINE__);
03171         return FALSE;
03172     }
03173     
03174     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
03175                                message, -1,
03176                                error);
03177 
03178     if (dbus_error_is_set (error)) {
03179         dbus_message_unref (message);
03180         return FALSE;
03181     }
03182 
03183     dbus_message_unref (message);
03184 
03185     if (reply == NULL)
03186         return FALSE;
03187 
03188     dbus_message_iter_init (reply, &reply_iter);
03189     if (dbus_message_iter_get_arg_type (&reply_iter) !=
03190            DBUS_TYPE_BOOLEAN) {
03191         dbus_message_unref (message);
03192         dbus_message_unref (reply);
03193         return FALSE;
03194     }
03195     dbus_message_iter_get_basic (&reply_iter, &result);
03196 
03197     dbus_message_unref (reply);
03198 
03199     return result;
03200 }
03201 
03213 dbus_bool_t libhal_device_emit_condition (LibHalContext *ctx,
03214                       const char *udi,
03215                       const char *condition_name,
03216                       const char *condition_details,
03217                       DBusError *error)
03218 {
03219     DBusMessage *message;
03220     DBusMessageIter iter;
03221     DBusMessageIter reply_iter;
03222     DBusMessage *reply;
03223     dbus_bool_t result;
03224 
03225     message = dbus_message_new_method_call ("org.freedesktop.Hal",
03226                         udi,
03227                         "org.freedesktop.Hal.Device",
03228                         "EmitCondition");
03229 
03230     if (message == NULL) {
03231         fprintf (stderr,
03232              "%s %d : Couldn't allocate D-BUS message\n",
03233              __FILE__, __LINE__);
03234         return FALSE;
03235     }
03236 
03237     dbus_message_iter_init_append (message, &iter);
03238     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &condition_name);
03239     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &condition_details);
03240     
03241     reply = dbus_connection_send_with_reply_and_block (ctx->connection,
03242                                message, -1,
03243                                error);
03244 
03245     if (dbus_error_is_set (error)) {
03246         dbus_message_unref (message);
03247         return FALSE;
03248     }
03249 
03250     dbus_message_unref (message);
03251 
03252     if (reply == NULL)
03253         return FALSE;
03254 
03255     dbus_message_iter_init (reply, &reply_iter);
03256     if (dbus_message_iter_get_arg_type (&reply_iter) !=
03257            DBUS_TYPE_BOOLEAN) {
03258         dbus_message_unref (message);
03259         dbus_message_unref (reply);
03260         return FALSE;
03261     }
03262     dbus_message_iter_get_basic (&reply_iter, &result);
03263 
03264     dbus_message_unref (reply);
03265 
03266     return result;  
03267 }
03268 

Generated on Mon May 23 10:13:20 2005 for HAL by  doxygen 1.4.2