libhal.c

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

Generated on Sat Jun 17 12:01:19 2006 for HAL by  doxygen 1.4.6