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

libhal.c

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

Generated on Wed Aug 13 16:57:53 2008 for HAL by  doxygen 1.3.9.1