12912Sartem /*************************************************************************** 22912Sartem * CVSID: $Id$ 32912Sartem * 42912Sartem * libhal.c : HAL daemon C convenience library 52912Sartem * 62912Sartem * Copyright (C) 2003 David Zeuthen, <david@fubar.dk> 76293Sartem * Copyright (C) 2007 Codethink Ltd. Author Rob Taylor <rob.taylor@codethink.co.uk> 82912Sartem * 92912Sartem * Licensed under the Academic Free License version 2.1 102912Sartem * 112912Sartem * This program is free software; you can redistribute it and/or modify 122912Sartem * it under the terms of the GNU General Public License as published by 132912Sartem * the Free Software Foundation; either version 2 of the License, or 142912Sartem * (at your option) any later version. 152912Sartem * 162912Sartem * This program is distributed in the hope that it will be useful, 172912Sartem * but WITHOUT ANY WARRANTY; without even the implied warranty of 182912Sartem * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 192912Sartem * GNU General Public License for more details. 202912Sartem * 212912Sartem * You should have received a copy of the GNU General Public License 222912Sartem * along with this program; if not, write to the Free Software 232912Sartem * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 242912Sartem * 252912Sartem **************************************************************************/ 262912Sartem 272912Sartem #ifdef HAVE_CONFIG_H 282912Sartem # include <config.h> 292912Sartem #endif 302912Sartem 312912Sartem #include <stdio.h> 322912Sartem #include <stdlib.h> 332912Sartem #include <string.h> 342912Sartem #include <dbus/dbus.h> 352912Sartem 362912Sartem #include "libhal.h" 372912Sartem 382912Sartem #ifdef ENABLE_NLS 392912Sartem # include <libintl.h> 402912Sartem # define _(String) dgettext (GETTEXT_PACKAGE, String) 412912Sartem # ifdef gettext_noop 422912Sartem # define N_(String) gettext_noop (String) 432912Sartem # else 442912Sartem # define N_(String) (String) 452912Sartem # endif 462912Sartem #else 472912Sartem /* Stubs that do something close enough. */ 482912Sartem # define textdomain(String) (String) 492912Sartem # define gettext(String) (String) 502912Sartem # define dgettext(Domain,Message) (Message) 512912Sartem # define dcgettext(Domain,Message,Type) (Message) 522912Sartem # define bindtextdomain(Domain,Directory) (Domain) 532912Sartem # define _(String) 542912Sartem # define N_(String) (String) 552912Sartem #endif 562912Sartem 576293Sartem /** 586293Sartem * LIBHAL_CHECK_PARAM_VALID: 596293Sartem * @_param_: the prameter to check for 606293Sartem * @_name_: the name of the prameter (for debug output) 616293Sartem * @_ret_: what to use for return value if the prameter is NULL 626293Sartem * 636293Sartem * Handy macro for checking whether a parameter is valid and not NULL. 646293Sartem */ 656293Sartem #define LIBHAL_CHECK_PARAM_VALID(_param_,_name_,_ret_) \ 666293Sartem do { \ 676293Sartem if (_param_ == NULL) { \ 686293Sartem fprintf (stderr, \ 696293Sartem "%s %d : invalid paramater. %s is NULL.\n", \ 706293Sartem __FILE__, __LINE__, _name_); \ 716293Sartem return _ret_; \ 726293Sartem } \ 736293Sartem } while(0) 746293Sartem 756293Sartem 762912Sartem static char **libhal_get_string_array_from_iter (DBusMessageIter *iter, int *num_elements); 772912Sartem 782912Sartem static dbus_bool_t libhal_property_fill_value_from_variant (LibHalProperty *p, DBusMessageIter *var_iter); 792912Sartem 802912Sartem 812912Sartem 822912Sartem /** 832912Sartem * libhal_free_string_array: 842912Sartem * @str_array: the array to be freed 852912Sartem * 862912Sartem * Frees a NULL-terminated array of strings. If passed NULL, does nothing. 872912Sartem */ 882912Sartem void 892912Sartem libhal_free_string_array (char **str_array) 902912Sartem { 912912Sartem if (str_array != NULL) { 922912Sartem int i; 932912Sartem 942912Sartem for (i = 0; str_array[i] != NULL; i++) { 952912Sartem free (str_array[i]); 962912Sartem str_array[i] = NULL; 972912Sartem } 982912Sartem free (str_array); 992912Sartem str_array = NULL; 1002912Sartem } 1012912Sartem } 1022912Sartem 1032912Sartem 1042912Sartem /** 1052912Sartem * libhal_get_string_array_from_iter: 1062912Sartem * @iter: the message iterator to extract the strings from 1072912Sartem * @num_elements: pointer to an integer where to store number of elements (can be NULL) 1082912Sartem * 1092912Sartem * Creates a NULL terminated array of strings from a dbus message iterator. 1102912Sartem * 1112912Sartem * Returns: pointer to the string array 1122912Sartem */ 1132912Sartem static char ** 1142912Sartem libhal_get_string_array_from_iter (DBusMessageIter *iter, int *num_elements) 1152912Sartem { 1162912Sartem int count; 1172912Sartem char **buffer; 1182912Sartem 1192912Sartem count = 0; 1202912Sartem buffer = (char **)malloc (sizeof (char *) * 8); 1212912Sartem 1222912Sartem if (buffer == NULL) 1232912Sartem goto oom; 1242912Sartem 1252912Sartem buffer[0] = NULL; 1262912Sartem while (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING) { 1272912Sartem const char *value; 1282912Sartem char *str; 1292912Sartem 1302912Sartem if ((count % 8) == 0 && count != 0) { 1312912Sartem buffer = realloc (buffer, sizeof (char *) * (count + 8)); 1322912Sartem if (buffer == NULL) 1332912Sartem goto oom; 1342912Sartem } 1352912Sartem 1362912Sartem dbus_message_iter_get_basic (iter, &value); 1372912Sartem str = strdup (value); 1382912Sartem if (str == NULL) 1392912Sartem goto oom; 1402912Sartem 1412912Sartem buffer[count] = str; 1422912Sartem 1432912Sartem dbus_message_iter_next(iter); 1442912Sartem count++; 1452912Sartem } 1462912Sartem 1472912Sartem if ((count % 8) == 0) { 1482912Sartem buffer = realloc (buffer, sizeof (char *) * (count + 1)); 1492912Sartem if (buffer == NULL) 1502912Sartem goto oom; 1512912Sartem } 1522912Sartem 1532912Sartem buffer[count] = NULL; 1542912Sartem if (num_elements != NULL) 1552912Sartem *num_elements = count; 1562912Sartem return buffer; 1572912Sartem 1582912Sartem oom: 1592912Sartem fprintf (stderr, "%s %d : error allocating memory\n", __FILE__, __LINE__); 1602912Sartem return NULL; 1612912Sartem 1622912Sartem } 1632912Sartem 1642912Sartem /** 1652912Sartem * libhal_free_string: 1662912Sartem * @str: the nul-terminated sting to free 1672912Sartem * 1682912Sartem * Used to free strings returned by libhal. 1692912Sartem */ 1702912Sartem void 1712912Sartem libhal_free_string (char *str) 1722912Sartem { 1732912Sartem if (str != NULL) { 1742912Sartem free (str); 1752912Sartem str = NULL; 1762912Sartem } 1772912Sartem } 1782912Sartem 1792912Sartem 1802912Sartem /** 1812912Sartem * LibHalPropertySet: 1822912Sartem * 1832912Sartem * Represents a set of properties. Opaque; use the 1842912Sartem * libhal_property_set_*() family of functions to access it. 1852912Sartem */ 1862912Sartem struct LibHalPropertySet_s { 1872912Sartem unsigned int num_properties; /**< Number of properties in set */ 1882912Sartem LibHalProperty *properties_head; 1892912Sartem /**< Pointer to first property or NULL 1902912Sartem * if there are no properties */ 1912912Sartem }; 1922912Sartem 1932912Sartem /** 1942912Sartem * LibHalProperty: 1952912Sartem * 1962912Sartem * Represents a property. Opaque. 1972912Sartem */ 1982912Sartem struct LibHalProperty_s { 1992912Sartem int type; /**< Type of property */ 2002912Sartem char *key; /**< ASCII string */ 2012912Sartem 2022912Sartem /** Possible values of the property */ 2032912Sartem union { 2042912Sartem char *str_value; /**< UTF-8 zero-terminated string */ 2052912Sartem dbus_int32_t int_value; 2062912Sartem /**< 32-bit signed integer */ 2072912Sartem dbus_uint64_t uint64_value; 2082912Sartem /**< 64-bit unsigned integer */ 2092912Sartem double double_value; /**< IEEE754 double precision float */ 2102912Sartem dbus_bool_t bool_value; 2112912Sartem /**< Truth value */ 2122912Sartem 2132912Sartem char **strlist_value; /**< List of UTF-8 zero-terminated strings */ 2142912Sartem } v; 2152912Sartem 2162912Sartem LibHalProperty *next; /**< Next property or NULL if this is 2172912Sartem * the last */ 2182912Sartem }; 2192912Sartem 2202912Sartem /** 2212912Sartem * LibHalContext: 2222912Sartem * 2232912Sartem * Context for connection to the HAL daemon. Opaque, use the 2242912Sartem * libhal_ctx_*() family of functions to access it. 2252912Sartem */ 2262912Sartem struct LibHalContext_s { 2272912Sartem DBusConnection *connection; /**< D-BUS connection */ 2282912Sartem dbus_bool_t is_initialized; /**< Are we initialised */ 2292912Sartem dbus_bool_t is_shutdown; /**< Have we been shutdown */ 2302912Sartem dbus_bool_t cache_enabled; /**< Is the cache enabled */ 2312912Sartem dbus_bool_t is_direct; /**< Whether the connection to hald is direct */ 2322912Sartem 2332912Sartem /** Device added */ 2342912Sartem LibHalDeviceAdded device_added; 2352912Sartem 2362912Sartem /** Device removed */ 2372912Sartem LibHalDeviceRemoved device_removed; 2382912Sartem 2392912Sartem /** Device got a new capability */ 2402912Sartem LibHalDeviceNewCapability device_new_capability; 2412912Sartem 2422912Sartem /** Device got a new capability */ 2432912Sartem LibHalDeviceLostCapability device_lost_capability; 2442912Sartem 2452912Sartem /** A property of a device changed */ 2462912Sartem LibHalDevicePropertyModified device_property_modified; 2472912Sartem 2482912Sartem /** A non-continous event on the device occured */ 2492912Sartem LibHalDeviceCondition device_condition; 2502912Sartem 2512912Sartem void *user_data; /**< User data */ 2522912Sartem }; 2532912Sartem 2542912Sartem /** 2552912Sartem * libhal_ctx_set_user_data: 2562912Sartem * @ctx: the context for the connection to hald 2572912Sartem * @user_data: user data 2582912Sartem * 2592912Sartem * Set user data for the context. 2602912Sartem * 2612912Sartem * Returns: TRUE if user data was successfully set, FALSE if otherwise 2622912Sartem */ 2632912Sartem dbus_bool_t 2642912Sartem libhal_ctx_set_user_data(LibHalContext *ctx, void *user_data) 2652912Sartem { 2662912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 2672912Sartem ctx->user_data = user_data; 2682912Sartem return TRUE; 2692912Sartem } 2702912Sartem 2712912Sartem /** 2722912Sartem * libhal_ctx_get_user_data: 2732912Sartem * @ctx: the context for the connection to hald 2742912Sartem * 2752912Sartem * Get user data for the context. 2762912Sartem * 2772912Sartem * Returns: opaque pointer stored through libhal_ctx_set_user_data() or NULL if not set. 2782912Sartem */ 2792912Sartem void* 2802912Sartem libhal_ctx_get_user_data(LibHalContext *ctx) 2812912Sartem { 2822912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL); 2832912Sartem return ctx->user_data; 2842912Sartem } 2852912Sartem 2862912Sartem 2872912Sartem /** 2882912Sartem * libhal_property_fill_value_from_variant: 2892912Sartem * @p: the property to fill in 2902912Sartem * @var_iter: variant iterator to extract the value from 2912912Sartem * 2922912Sartem * Fills in the value for the LibHalProperty given a variant iterator. 2932912Sartem * 2942912Sartem * Returns: Whether the value was put in. 2952912Sartem */ 2962912Sartem static dbus_bool_t 2972912Sartem libhal_property_fill_value_from_variant (LibHalProperty *p, DBusMessageIter *var_iter) 2982912Sartem { 2992912Sartem DBusMessageIter iter_array; 3002912Sartem switch (p->type) { 3012912Sartem case DBUS_TYPE_ARRAY: 3022912Sartem if (dbus_message_iter_get_element_type (var_iter) != DBUS_TYPE_STRING) 3032912Sartem return FALSE; 3042912Sartem 3052912Sartem dbus_message_iter_recurse (var_iter, &iter_array); 3062912Sartem p->v.strlist_value = libhal_get_string_array_from_iter (&iter_array, NULL); 3072912Sartem 3082912Sartem p->type = LIBHAL_PROPERTY_TYPE_STRLIST; 3092912Sartem 3102912Sartem break; 3112912Sartem case DBUS_TYPE_STRING: 3122912Sartem { 3132912Sartem const char *v; 3142912Sartem 3152912Sartem dbus_message_iter_get_basic (var_iter, &v); 3162912Sartem 3172912Sartem p->v.str_value = strdup (v); 3182912Sartem if (p->v.str_value == NULL) 3192912Sartem return FALSE; 3202912Sartem p->type = LIBHAL_PROPERTY_TYPE_STRING; 3212912Sartem 3222912Sartem break; 3232912Sartem } 3242912Sartem case DBUS_TYPE_INT32: 3252912Sartem { 3262912Sartem dbus_int32_t v; 3272912Sartem 3282912Sartem dbus_message_iter_get_basic (var_iter, &v); 3292912Sartem 3302912Sartem p->v.int_value = v; 3312912Sartem p->type = LIBHAL_PROPERTY_TYPE_INT32; 3322912Sartem 3332912Sartem break; 3342912Sartem } 3352912Sartem case DBUS_TYPE_UINT64: 3362912Sartem { 3372912Sartem dbus_uint64_t v; 3382912Sartem 3392912Sartem dbus_message_iter_get_basic (var_iter, &v); 3402912Sartem 3412912Sartem p->v.uint64_value = v; 3422912Sartem p->type = LIBHAL_PROPERTY_TYPE_UINT64; 3432912Sartem 3442912Sartem break; 3452912Sartem } 3462912Sartem case DBUS_TYPE_DOUBLE: 3472912Sartem { 3482912Sartem double v; 3492912Sartem 3502912Sartem dbus_message_iter_get_basic (var_iter, &v); 3512912Sartem 3522912Sartem p->v.double_value = v; 3532912Sartem p->type = LIBHAL_PROPERTY_TYPE_DOUBLE; 3542912Sartem 3552912Sartem break; 3562912Sartem } 3572912Sartem case DBUS_TYPE_BOOLEAN: 3582912Sartem { 3592912Sartem double v; 3602912Sartem 3612912Sartem dbus_message_iter_get_basic (var_iter, &v); 3622912Sartem 3632912Sartem p->v.double_value = v; 3642912Sartem p->type = LIBHAL_PROPERTY_TYPE_BOOLEAN; 3652912Sartem 3662912Sartem break; 3672912Sartem } 3682912Sartem default: 3692912Sartem /** @todo report error */ 3702912Sartem break; 3712912Sartem } 3722912Sartem 3732912Sartem return TRUE; 3742912Sartem } 3752912Sartem 3762912Sartem /** 3772912Sartem * libhal_device_get_all_properties: 3782912Sartem * @ctx: the context for the connection to hald 3792912Sartem * @udi: the Unique id of device 3802912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 3812912Sartem * 3822912Sartem * Retrieve all the properties on a device. 3832912Sartem * 3842912Sartem * Returns: An object represent all properties. Must be freed with libhal_free_property_set(). 3852912Sartem */ 3862912Sartem LibHalPropertySet * 3872912Sartem libhal_device_get_all_properties (LibHalContext *ctx, const char *udi, DBusError *error) 3882912Sartem { 3892912Sartem DBusMessage *message; 3902912Sartem DBusMessage *reply; 3912912Sartem DBusMessageIter reply_iter; 3922912Sartem DBusMessageIter dict_iter; 3932912Sartem LibHalPropertySet *result; 3942912Sartem LibHalProperty *p_last; 3952912Sartem DBusError _error; 3962912Sartem 3972912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL); 3982912Sartem 3992912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", udi, 4002912Sartem "org.freedesktop.Hal.Device", 4012912Sartem "GetAllProperties"); 4022912Sartem 4032912Sartem if (message == NULL) { 4042912Sartem fprintf (stderr, 4052912Sartem "%s %d : Couldn't allocate D-BUS message\n", 4062912Sartem __FILE__, __LINE__); 4072912Sartem return NULL; 4082912Sartem } 4092912Sartem 4102912Sartem dbus_error_init (&_error); 4112912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 4122912Sartem message, -1, 4132912Sartem &_error); 4142912Sartem 4152912Sartem dbus_move_error (&_error, error); 4162912Sartem if (error != NULL && dbus_error_is_set (error)) { 4172912Sartem fprintf (stderr, 4182912Sartem "%s %d : %s\n", 4192912Sartem __FILE__, __LINE__, error->message); 4202912Sartem 4212912Sartem dbus_message_unref (message); 4222912Sartem return NULL; 4232912Sartem } 4242912Sartem 4252912Sartem if (reply == NULL) { 4262912Sartem dbus_message_unref (message); 4272912Sartem return NULL; 4282912Sartem } 4292912Sartem 4302912Sartem dbus_message_iter_init (reply, &reply_iter); 4312912Sartem 4322912Sartem result = malloc (sizeof (LibHalPropertySet)); 4332912Sartem if (result == NULL) 4342912Sartem goto oom; 4352912Sartem /* 4362912Sartem result->properties = malloc(sizeof(LibHalProperty)*result->num_properties); 4372912Sartem if( result->properties==NULL ) 4382912Sartem { 4392912Sartem /// @todo cleanup 4402912Sartem return NULL; 4412912Sartem } 4422912Sartem */ 4432912Sartem 4442912Sartem result->properties_head = NULL; 4452912Sartem result->num_properties = 0; 4462912Sartem 4472912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY && 4482912Sartem dbus_message_iter_get_element_type (&reply_iter) != DBUS_TYPE_DICT_ENTRY) { 4492912Sartem fprintf (stderr, "%s %d : error, expecting an array of dict entries\n", 4502912Sartem __FILE__, __LINE__); 4512912Sartem dbus_message_unref (message); 4522912Sartem dbus_message_unref (reply); 4532912Sartem return NULL; 4542912Sartem } 4552912Sartem 4562912Sartem dbus_message_iter_recurse (&reply_iter, &dict_iter); 4572912Sartem 4582912Sartem p_last = NULL; 4592912Sartem 4602912Sartem while (dbus_message_iter_get_arg_type (&dict_iter) == DBUS_TYPE_DICT_ENTRY) 4612912Sartem { 4622912Sartem DBusMessageIter dict_entry_iter, var_iter; 4632912Sartem const char *key; 4642912Sartem LibHalProperty *p; 4652912Sartem 4662912Sartem dbus_message_iter_recurse (&dict_iter, &dict_entry_iter); 4672912Sartem 4682912Sartem dbus_message_iter_get_basic (&dict_entry_iter, &key); 4692912Sartem 4702912Sartem p = malloc (sizeof (LibHalProperty)); 4712912Sartem if (p == NULL) 4722912Sartem goto oom; 4732912Sartem 4742912Sartem p->next = NULL; 4752912Sartem 4762912Sartem if (result->num_properties == 0) 4772912Sartem result->properties_head = p; 4782912Sartem 4792912Sartem if (p_last != NULL) 4802912Sartem p_last->next = p; 4812912Sartem 4822912Sartem p_last = p; 4832912Sartem 4842912Sartem p->key = strdup (key); 4852912Sartem if (p->key == NULL) 4862912Sartem goto oom; 4872912Sartem 4882912Sartem dbus_message_iter_next (&dict_entry_iter); 4892912Sartem 4902912Sartem dbus_message_iter_recurse (&dict_entry_iter, &var_iter); 4912912Sartem 4922912Sartem 4932912Sartem p->type = dbus_message_iter_get_arg_type (&var_iter); 4942912Sartem 4952912Sartem result->num_properties++; 4962912Sartem 4972912Sartem if(!libhal_property_fill_value_from_variant (p, &var_iter)) 4982912Sartem goto oom; 4992912Sartem 5002912Sartem dbus_message_iter_next (&dict_iter); 5012912Sartem } 5022912Sartem 5032912Sartem dbus_message_unref (message); 5042912Sartem dbus_message_unref (reply); 5052912Sartem 5062912Sartem return result; 5072912Sartem 5082912Sartem oom: 5092912Sartem fprintf (stderr, 5102912Sartem "%s %d : error allocating memory\n", 5112912Sartem __FILE__, __LINE__); 5122912Sartem /** @todo FIXME cleanup */ 5132912Sartem return NULL; 5142912Sartem } 5152912Sartem 5162912Sartem /** 5172912Sartem * libhal_free_property_set: 5182912Sartem * @set: property-set to free 5192912Sartem * 5202912Sartem * Free a property set earlier obtained with libhal_device_get_all_properties(). 5212912Sartem */ 5222912Sartem void 5232912Sartem libhal_free_property_set (LibHalPropertySet * set) 5242912Sartem { 5252912Sartem LibHalProperty *p; 5262912Sartem LibHalProperty *q; 5272912Sartem 5282912Sartem if (set == NULL) 5292912Sartem return; 5302912Sartem 5312912Sartem for (p = set->properties_head; p != NULL; p = q) { 5322912Sartem free (p->key); 5332912Sartem if (p->type == DBUS_TYPE_STRING) 5342912Sartem free (p->v.str_value); 5352912Sartem if (p->type == LIBHAL_PROPERTY_TYPE_STRLIST) 5362912Sartem libhal_free_string_array (p->v.strlist_value); 5372912Sartem q = p->next; 5382912Sartem free (p); 5392912Sartem } 5402912Sartem free (set); 5412912Sartem } 5422912Sartem 5432912Sartem /** 5442912Sartem * libhal_property_set_get_num_elems: 5452912Sartem * @set: property set to consider 5462912Sartem * 5472912Sartem * Get the number of properties in a property set. 5482912Sartem * 5492912Sartem * Returns: number of properties in given property set 5502912Sartem */ 5512912Sartem unsigned int 5522912Sartem libhal_property_set_get_num_elems (LibHalPropertySet *set) 5532912Sartem { 5542912Sartem unsigned int num_elems; 5552912Sartem LibHalProperty *p; 5562912Sartem 5572912Sartem if (set == NULL) 5582912Sartem return 0; 5592912Sartem 5602912Sartem num_elems = 0; 5612912Sartem for (p = set->properties_head; p != NULL; p = p->next) 5622912Sartem num_elems++; 5632912Sartem 5642912Sartem return num_elems; 5652912Sartem } 5662912Sartem 5676293Sartem static LibHalProperty * 5686293Sartem property_set_lookup (const LibHalPropertySet *set, const char *key) 5696293Sartem { 5706293Sartem LibHalProperty *p; 5716293Sartem 5726293Sartem LIBHAL_CHECK_PARAM_VALID(set, "*set", NULL); 5736293Sartem LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL); 5746293Sartem 5756293Sartem for (p = set->properties_head; p != NULL; p = p->next) 5766293Sartem if (strcmp (key, p->key) == 0) 5776293Sartem return p; 5786293Sartem 5796293Sartem return NULL; 5806293Sartem } 5816293Sartem 5826293Sartem /** 5836293Sartem * libhal_ps_get_type: 5846293Sartem * @set: property set 5856293Sartem * @key: name of property to inspect 5866293Sartem * 5876293Sartem * Get the type of a given property. 5886293Sartem * 5896293Sartem * Returns: the #LibHalPropertyType of the given property, 5906293Sartem * LIBHAL_PROPERTY_TYPE_INVALID if property is not in the set 5916293Sartem */ 5926293Sartem LibHalPropertyType 5936293Sartem libhal_ps_get_type (const LibHalPropertySet *set, const char *key) 5946293Sartem { 5956293Sartem LibHalProperty *p = property_set_lookup (set, key); 5966293Sartem 5976293Sartem LIBHAL_CHECK_PARAM_VALID(set, "*set", LIBHAL_PROPERTY_TYPE_INVALID); 5986293Sartem LIBHAL_CHECK_PARAM_VALID(key, "*key", LIBHAL_PROPERTY_TYPE_INVALID); 5996293Sartem 6006293Sartem p = property_set_lookup (set, key); 6016293Sartem if (p) return p->type; 6026293Sartem else return LIBHAL_PROPERTY_TYPE_INVALID; 6036293Sartem } 6046293Sartem 6056293Sartem /** 6066293Sartem * libhal_ps_get_string: 6076293Sartem * @set: property set 6086293Sartem * @key: name of property to inspect 6096293Sartem * 6106293Sartem * Get the value of a property of type string. 6116293Sartem * 6126293Sartem * Returns: UTF8 nul-terminated string. This pointer is only valid 6136293Sartem * until libhal_free_property_set() is invoked on the property set 6146293Sartem * this property belongs to. NULL if property is not in the set or not a string 6156293Sartem */ 6166293Sartem const char * 6176293Sartem libhal_ps_get_string (const LibHalPropertySet *set, const char *key) 6186293Sartem { 6196293Sartem LibHalProperty *p; 6206293Sartem 6216293Sartem LIBHAL_CHECK_PARAM_VALID(set, "*set", NULL); 6226293Sartem LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL); 6236293Sartem 6246293Sartem p = property_set_lookup (set, key); 6256293Sartem if (p && p->type == LIBHAL_PROPERTY_TYPE_STRING) 6266293Sartem return p->v.str_value; 6276293Sartem else return NULL; 6286293Sartem } 6296293Sartem 6306293Sartem /** 6316293Sartem * libhal_ps_get_int: 6326293Sartem * @set: property set 6336293Sartem * @key: name of property to inspect 6346293Sartem * 6356293Sartem * Get the value of a property of type signed integer. 6366293Sartem * 6376293Sartem * Returns: property value (32-bit signed integer) 6386293Sartem */ 6396293Sartem dbus_int32_t 6406293Sartem libhal_ps_get_int32 (const LibHalPropertySet *set, const char *key) 6416293Sartem { 6426293Sartem LibHalProperty *p; 6436293Sartem 6446293Sartem LIBHAL_CHECK_PARAM_VALID(set, "*set", 0); 6456293Sartem LIBHAL_CHECK_PARAM_VALID(key, "*key", 0); 6466293Sartem 6476293Sartem p = property_set_lookup (set, key); 6486293Sartem if (p && p->type == LIBHAL_PROPERTY_TYPE_INT32) 6496293Sartem return p->v.int_value; 6506293Sartem else return 0; 6516293Sartem } 6526293Sartem 6536293Sartem /** 6546293Sartem * libhal_ps_get_uint64: 6556293Sartem * @set: property set 6566293Sartem * @key: name of property to inspect 6576293Sartem * 6586293Sartem * Get the value of a property of type unsigned integer. 6596293Sartem * 6606293Sartem * Returns: property value (64-bit unsigned integer) 6616293Sartem */ 6626293Sartem dbus_uint64_t 6636293Sartem libhal_ps_get_uint64 (const LibHalPropertySet *set, const char *key) 6646293Sartem { 6656293Sartem LibHalProperty *p; 6666293Sartem 6676293Sartem LIBHAL_CHECK_PARAM_VALID(set, "*set", 0); 6686293Sartem LIBHAL_CHECK_PARAM_VALID(key, "*key", 0); 6696293Sartem 6706293Sartem p = property_set_lookup (set, key); 6716293Sartem if (p && p->type == LIBHAL_PROPERTY_TYPE_UINT64) 6726293Sartem return p->v.uint64_value; 6736293Sartem else return 0; 6746293Sartem } 6756293Sartem 6766293Sartem /** 6776293Sartem * libhal_ps_get_double: 6786293Sartem * @set: property set 6796293Sartem * @key: name of property to inspect 6806293Sartem * 6816293Sartem * Get the value of a property of type double. 6826293Sartem * 6836293Sartem * Returns: property value (IEEE754 double precision float) 6846293Sartem */ 6856293Sartem double 6866293Sartem libhal_ps_get_double (const LibHalPropertySet *set, const char *key) 6876293Sartem { 6886293Sartem LibHalProperty *p; 6896293Sartem 6906293Sartem LIBHAL_CHECK_PARAM_VALID(set, "*set", 0.0); 6916293Sartem LIBHAL_CHECK_PARAM_VALID(key, "*key", 0.0); 6926293Sartem 6936293Sartem p = property_set_lookup (set, key); 6946293Sartem if (p && p->type == LIBHAL_PROPERTY_TYPE_DOUBLE) 6956293Sartem return p->v.double_value; 6966293Sartem else return 0.0; 6976293Sartem } 6986293Sartem 6996293Sartem /** 7006293Sartem * libhal_ps_get_bool: 7016293Sartem * @set: property set 7026293Sartem * @key: name of property to inspect 7036293Sartem * 7046293Sartem * Get the value of a property of type bool. 7056293Sartem * 7066293Sartem * Returns: property value (bool) 7076293Sartem */ 7086293Sartem dbus_bool_t 7096293Sartem libhal_ps_get_bool (const LibHalPropertySet *set, const char *key) 7106293Sartem { 7116293Sartem LibHalProperty *p; 7126293Sartem 7136293Sartem LIBHAL_CHECK_PARAM_VALID(set, "*set", FALSE); 7146293Sartem LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE); 7156293Sartem 7166293Sartem p = property_set_lookup (set, key); 7176293Sartem if (p && p->type == LIBHAL_PROPERTY_TYPE_BOOLEAN) 7186293Sartem return p->v.bool_value; 7196293Sartem else return FALSE; 7206293Sartem } 7216293Sartem 7226293Sartem /** 7236293Sartem * libhal_ps_get_strlist: 7246293Sartem * @set: property set 7256293Sartem * @key: name of property to inspect 7266293Sartem * 7276293Sartem * Get the value of a property of type string list. 7286293Sartem * 7296293Sartem * Returns: pointer to array of strings, this is owned by the property set 7306293Sartem */ 7316293Sartem const char *const * 7326293Sartem libhal_ps_get_strlist (const LibHalPropertySet *set, const char *key) 7336293Sartem { 7346293Sartem LibHalProperty *p; 7356293Sartem 7366293Sartem LIBHAL_CHECK_PARAM_VALID(set, "*set", NULL); 7376293Sartem LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL); 7386293Sartem 7396293Sartem p = property_set_lookup (set, key); 7406293Sartem if (p && p->type == LIBHAL_PROPERTY_TYPE_STRLIST) 7416293Sartem return (const char *const *) p->v.strlist_value; 7426293Sartem else return NULL; 7436293Sartem } 7446293Sartem 7452912Sartem 7462912Sartem /** 7472912Sartem * libhal_psi_init: 7482912Sartem * @iter: iterator object 7492912Sartem * @set: property set to iterate over 7502912Sartem * 7512912Sartem * Initialize a property set iterator. 7522912Sartem * 7532912Sartem */ 7542912Sartem void 7552912Sartem libhal_psi_init (LibHalPropertySetIterator * iter, LibHalPropertySet * set) 7562912Sartem { 7572912Sartem if (set == NULL) 7582912Sartem return; 7592912Sartem 7602912Sartem iter->set = set; 7612912Sartem iter->idx = 0; 7622912Sartem iter->cur_prop = set->properties_head; 7632912Sartem } 7642912Sartem 7652912Sartem 7662912Sartem /** 7672912Sartem * libhal_psi_has_more: 7682912Sartem * @iter: iterator object 7692912Sartem * 7702912Sartem * Determine whether there are more properties to iterate over. 7712912Sartem * 7722912Sartem * Returns: TRUE if there are more properties, FALSE otherwise. 7732912Sartem */ 7742912Sartem dbus_bool_t 7752912Sartem libhal_psi_has_more (LibHalPropertySetIterator * iter) 7762912Sartem { 7772912Sartem return iter->idx < iter->set->num_properties; 7782912Sartem } 7792912Sartem 7802912Sartem /** 7812912Sartem * libhal_psi_next: 7822912Sartem * @iter: iterator object 7832912Sartem * 7842912Sartem * Advance iterator to next property. 7852912Sartem */ 7862912Sartem void 7872912Sartem libhal_psi_next (LibHalPropertySetIterator * iter) 7882912Sartem { 7892912Sartem iter->idx++; 7902912Sartem iter->cur_prop = iter->cur_prop->next; 7912912Sartem } 7922912Sartem 7932912Sartem /** 7942912Sartem * libhal_psi_get_type: 7952912Sartem * @iter: iterator object 7962912Sartem * 7972912Sartem * Get type of property. 7982912Sartem * 7992912Sartem * Returns: the property type at the iterator's position 8002912Sartem */ 8012912Sartem LibHalPropertyType 8022912Sartem libhal_psi_get_type (LibHalPropertySetIterator * iter) 8032912Sartem { 8042912Sartem return iter->cur_prop->type; 8052912Sartem } 8062912Sartem 8072912Sartem /** 8082912Sartem * libhal_psi_get_key: 8092912Sartem * @iter: iterator object 8102912Sartem * 8112912Sartem * Get the key of a property. 8122912Sartem * 8132912Sartem * Returns: ASCII nul-terminated string. This pointer is only valid 8142912Sartem * until libhal_free_property_set() is invoked on the property set 8152912Sartem * this property belongs to. 8162912Sartem */ 8172912Sartem char * 8182912Sartem libhal_psi_get_key (LibHalPropertySetIterator * iter) 8192912Sartem { 8202912Sartem return iter->cur_prop->key; 8212912Sartem } 8222912Sartem 8232912Sartem /** 8242912Sartem * libhal_psi_get_string: 8252912Sartem * @iter: iterator object 8262912Sartem * 8272912Sartem * Get the value of a property of type string. 8282912Sartem * 8292912Sartem * Returns: UTF8 nul-terminated string. This pointer is only valid 8302912Sartem * until libhal_free_property_set() is invoked on the property set 8312912Sartem * this property belongs to. 8322912Sartem */ 8332912Sartem char * 8342912Sartem libhal_psi_get_string (LibHalPropertySetIterator * iter) 8352912Sartem { 8362912Sartem return iter->cur_prop->v.str_value; 8372912Sartem } 8382912Sartem 8392912Sartem /** 8402912Sartem * libhal_psi_get_int: 8412912Sartem * @iter: iterator object 8422912Sartem * 8432912Sartem * Get the value of a property of type signed integer. 8442912Sartem * 8452912Sartem * Returns: property value (32-bit signed integer) 8462912Sartem */ 8472912Sartem dbus_int32_t 8482912Sartem libhal_psi_get_int (LibHalPropertySetIterator * iter) 8492912Sartem { 8502912Sartem return iter->cur_prop->v.int_value; 8512912Sartem } 8522912Sartem 8532912Sartem /** 8542912Sartem * libhal_psi_get_uint64: 8552912Sartem * @iter: iterator object 8562912Sartem * 8572912Sartem * Get the value of a property of type unsigned integer. 8582912Sartem * 8592912Sartem * Returns: property value (64-bit unsigned integer) 8602912Sartem */ 8612912Sartem dbus_uint64_t 8622912Sartem libhal_psi_get_uint64 (LibHalPropertySetIterator * iter) 8632912Sartem { 8642912Sartem return iter->cur_prop->v.uint64_value; 8652912Sartem } 8662912Sartem 8672912Sartem /** 8682912Sartem * libhal_psi_get_double: 8692912Sartem * @iter: iterator object 8702912Sartem * 8712912Sartem * Get the value of a property of type double. 8722912Sartem * 8732912Sartem * Returns: property value (IEEE754 double precision float) 8742912Sartem */ 8752912Sartem double 8762912Sartem libhal_psi_get_double (LibHalPropertySetIterator * iter) 8772912Sartem { 8782912Sartem return iter->cur_prop->v.double_value; 8792912Sartem } 8802912Sartem 8812912Sartem /** 8822912Sartem * libhal_psi_get_bool: 8832912Sartem * @iter: iterator object 8842912Sartem * 8852912Sartem * Get the value of a property of type bool. 8862912Sartem * 8872912Sartem * Returns: property value (bool) 8882912Sartem */ 8892912Sartem dbus_bool_t 8902912Sartem libhal_psi_get_bool (LibHalPropertySetIterator * iter) 8912912Sartem { 8922912Sartem return iter->cur_prop->v.bool_value; 8932912Sartem } 8942912Sartem 8952912Sartem /** 8962912Sartem * libhal_psi_get_strlist: 8972912Sartem * @iter: iterator object 8982912Sartem * 8992912Sartem * Get the value of a property of type string list. 9002912Sartem * 9012912Sartem * Returns: pointer to array of strings 9022912Sartem */ 9032912Sartem char ** 9042912Sartem libhal_psi_get_strlist (LibHalPropertySetIterator * iter) 9052912Sartem { 9062912Sartem return iter->cur_prop->v.strlist_value; 9072912Sartem } 9082912Sartem 9092912Sartem 9102912Sartem static DBusHandlerResult 9112912Sartem filter_func (DBusConnection * connection, 9122912Sartem DBusMessage * message, void *user_data) 9132912Sartem { 9142912Sartem const char *object_path; 9152912Sartem DBusError error; 9162912Sartem LibHalContext *ctx = (LibHalContext *) user_data; 9172912Sartem 9182912Sartem if (ctx->is_shutdown) 9192912Sartem return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 9202912Sartem 9212912Sartem dbus_error_init (&error); 9222912Sartem 9232912Sartem object_path = dbus_message_get_path (message); 9242912Sartem 9252912Sartem /*printf("*** in filter_func, object_path=%s\n", object_path);*/ 9262912Sartem 9272912Sartem if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager", 9282912Sartem "DeviceAdded")) { 9292912Sartem char *udi; 9302912Sartem if (dbus_message_get_args (message, &error, 9312912Sartem DBUS_TYPE_STRING, &udi, 9322912Sartem DBUS_TYPE_INVALID)) { 9332912Sartem if (ctx->device_added != NULL) { 9342912Sartem ctx->device_added (ctx, udi); 9352912Sartem } 9362912Sartem } else { 9372912Sartem LIBHAL_FREE_DBUS_ERROR(&error); 9382912Sartem } 9392912Sartem return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 9402912Sartem } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager", "DeviceRemoved")) { 9412912Sartem char *udi; 9422912Sartem if (dbus_message_get_args (message, &error, 9432912Sartem DBUS_TYPE_STRING, &udi, 9442912Sartem DBUS_TYPE_INVALID)) { 9452912Sartem if (ctx->device_removed != NULL) { 9462912Sartem ctx->device_removed (ctx, udi); 9472912Sartem } 9482912Sartem } else { 9492912Sartem LIBHAL_FREE_DBUS_ERROR(&error); 9502912Sartem } 9512912Sartem return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 9522912Sartem } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager","NewCapability")) { 9532912Sartem char *udi; 9542912Sartem char *capability; 9552912Sartem if (dbus_message_get_args (message, &error, 9562912Sartem DBUS_TYPE_STRING, &udi, 9572912Sartem DBUS_TYPE_STRING, &capability, 9582912Sartem DBUS_TYPE_INVALID)) { 9592912Sartem if (ctx->device_new_capability != NULL) { 9602912Sartem ctx->device_new_capability (ctx, udi, capability); 9612912Sartem } 9622912Sartem } else { 9632912Sartem LIBHAL_FREE_DBUS_ERROR(&error); 9642912Sartem } 9652912Sartem return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 9662912Sartem } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "Condition")) { 9672912Sartem char *condition_name; 9682912Sartem char *condition_detail; 9692912Sartem if (dbus_message_get_args (message, &error, 9702912Sartem DBUS_TYPE_STRING, &condition_name, 9712912Sartem DBUS_TYPE_STRING, &condition_detail, 9722912Sartem DBUS_TYPE_INVALID)) { 9732912Sartem if (ctx->device_condition != NULL) { 9742912Sartem ctx->device_condition (ctx, object_path, condition_name, condition_detail); 9752912Sartem } 9762912Sartem } else { 9772912Sartem LIBHAL_FREE_DBUS_ERROR(&error); 9782912Sartem } 9792912Sartem return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 9802912Sartem } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "PropertyModified")) { 9812912Sartem if (ctx->device_property_modified != NULL) { 9822912Sartem int i; 9832912Sartem char *key; 9842912Sartem dbus_bool_t removed; 9852912Sartem dbus_bool_t added; 9862912Sartem int num_modifications; 9872912Sartem DBusMessageIter iter; 9882912Sartem DBusMessageIter iter_array; 9892912Sartem 9902912Sartem dbus_message_iter_init (message, &iter); 9912912Sartem dbus_message_iter_get_basic (&iter, &num_modifications); 9922912Sartem dbus_message_iter_next (&iter); 9932912Sartem 9942912Sartem dbus_message_iter_recurse (&iter, &iter_array); 9952912Sartem 9962912Sartem for (i = 0; i < num_modifications; i++) { 9972912Sartem DBusMessageIter iter_struct; 9982912Sartem 9992912Sartem dbus_message_iter_recurse (&iter_array, &iter_struct); 10002912Sartem 10012912Sartem dbus_message_iter_get_basic (&iter_struct, &key); 10022912Sartem dbus_message_iter_next (&iter_struct); 10032912Sartem dbus_message_iter_get_basic (&iter_struct, &removed); 10042912Sartem dbus_message_iter_next (&iter_struct); 10052912Sartem dbus_message_iter_get_basic (&iter_struct, &added); 10062912Sartem 10072912Sartem ctx->device_property_modified (ctx, 10082912Sartem object_path, 10092912Sartem key, removed, 10102912Sartem added); 10112912Sartem 10122912Sartem dbus_message_iter_next (&iter_array); 10132912Sartem } 10142912Sartem 10152912Sartem } 10162912Sartem return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 10172912Sartem } 10182912Sartem 10192912Sartem return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 10202912Sartem } 10212912Sartem 10222912Sartem /* for i18n purposes */ 10232912Sartem static dbus_bool_t libhal_already_initialized_once = FALSE; 10242912Sartem 10252912Sartem 10262912Sartem /** 10272912Sartem * libhal_get_all_devices: 10282912Sartem * @ctx: the context for the connection to hald 10292912Sartem * @num_devices: the number of devices will be stored here 10302912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 10312912Sartem * 10322912Sartem * Get all devices in the Global Device List (GDL). 10332912Sartem * 10342912Sartem * Returns: An array of device identifiers terminated with NULL. It is 10352912Sartem * the responsibility of the caller to free with 10362912Sartem * libhal_free_string_array(). If an error occurs NULL is returned. 10372912Sartem */ 10382912Sartem char ** 10392912Sartem libhal_get_all_devices (LibHalContext *ctx, int *num_devices, DBusError *error) 10402912Sartem { 10412912Sartem DBusMessage *message; 10422912Sartem DBusMessage *reply; 10432912Sartem DBusMessageIter iter_array, reply_iter; 10442912Sartem char **hal_device_names; 10452912Sartem DBusError _error; 10462912Sartem 10472912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL); 10482912Sartem 10492912Sartem *num_devices = 0; 10502912Sartem 10512912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", 10522912Sartem "/org/freedesktop/Hal/Manager", 10532912Sartem "org.freedesktop.Hal.Manager", 10542912Sartem "GetAllDevices"); 10552912Sartem if (message == NULL) { 10562912Sartem fprintf (stderr, "%s %d : Could not allocate D-BUS message\n", __FILE__, __LINE__); 10572912Sartem return NULL; 10582912Sartem } 10592912Sartem 10602912Sartem dbus_error_init (&_error); 10612912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, message, -1, &_error); 10622912Sartem 10632912Sartem dbus_move_error (&_error, error); 10642912Sartem if (error != NULL && dbus_error_is_set (error)) { 10652912Sartem dbus_message_unref (message); 10662912Sartem return NULL; 10672912Sartem } 10682912Sartem if (reply == NULL) { 10692912Sartem dbus_message_unref (message); 10702912Sartem return NULL; 10712912Sartem } 10722912Sartem 10732912Sartem /* now analyze reply */ 10742912Sartem dbus_message_iter_init (reply, &reply_iter); 10752912Sartem 10762912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) { 10772912Sartem fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__); 10782912Sartem return NULL; 10792912Sartem } 10802912Sartem 10812912Sartem dbus_message_iter_recurse (&reply_iter, &iter_array); 10822912Sartem 10832912Sartem hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices); 10842912Sartem 10852912Sartem dbus_message_unref (reply); 10862912Sartem dbus_message_unref (message); 10872912Sartem 10882912Sartem return hal_device_names; 10892912Sartem } 10902912Sartem 10912912Sartem /** 10922912Sartem * libhal_device_get_property_type: 10932912Sartem * @ctx: the context for the connection to hald 10942912Sartem * @udi: the Unique Device Id 10952912Sartem * @key: name of the property 10962912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 10972912Sartem * 10982912Sartem * Query a property type of a device. 10992912Sartem * 11002912Sartem * Returns: A LibHalPropertyType. LIBHAL_PROPERTY_TYPE_INVALID is 11012912Sartem * return if the property doesn't exist. 11022912Sartem */ 11032912Sartem LibHalPropertyType 11042912Sartem libhal_device_get_property_type (LibHalContext *ctx, const char *udi, const char *key, DBusError *error) 11052912Sartem { 11062912Sartem DBusMessage *message; 11072912Sartem DBusMessage *reply; 11082912Sartem DBusMessageIter iter, reply_iter; 11092912Sartem int type; 11102912Sartem DBusError _error; 11112912Sartem 11122912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, LIBHAL_PROPERTY_TYPE_INVALID); /* or return NULL? */ 11132912Sartem 11142912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", udi, 11152912Sartem "org.freedesktop.Hal.Device", 11162912Sartem "GetPropertyType"); 11172912Sartem if (message == NULL) { 11182912Sartem fprintf (stderr, "%s %d : Couldn't allocate D-BUS message\n", __FILE__, __LINE__); 11192912Sartem return LIBHAL_PROPERTY_TYPE_INVALID; 11202912Sartem } 11212912Sartem 11222912Sartem dbus_message_iter_init_append (message, &iter); 11232912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key); 11242912Sartem 11252912Sartem dbus_error_init (&_error); 11262912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 11272912Sartem message, -1, 11282912Sartem &_error); 11292912Sartem 11302912Sartem dbus_move_error (&_error, error); 11312912Sartem if (error != NULL && dbus_error_is_set (error)) { 11322912Sartem dbus_message_unref (message); 11332912Sartem return LIBHAL_PROPERTY_TYPE_INVALID; 11342912Sartem } 11352912Sartem if (reply == NULL) { 11362912Sartem dbus_message_unref (message); 11372912Sartem return LIBHAL_PROPERTY_TYPE_INVALID; 11382912Sartem } 11392912Sartem 11402912Sartem dbus_message_iter_init (reply, &reply_iter); 11412912Sartem dbus_message_iter_get_basic (&reply_iter, &type); 11422912Sartem 11432912Sartem dbus_message_unref (message); 11442912Sartem dbus_message_unref (reply); 11452912Sartem 11462912Sartem return type; 11472912Sartem } 11482912Sartem 11492912Sartem /** 11502912Sartem * libhal_device_get_property_strlist: 11512912Sartem * @ctx: the context for the connection to hald 11522912Sartem * @udi: unique Device Id 11532912Sartem * @key: name of the property 11542912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 11552912Sartem * 11562912Sartem * Get the value of a property of type string list. 11572912Sartem * 11582912Sartem * Returns: Array of pointers to UTF8 nul-terminated strings 11592912Sartem * terminated by NULL. The caller is responsible for freeing this 11602912Sartem * string array with the function libhal_free_string_array(). Returns 11612912Sartem * NULL if the property didn't exist or we are OOM 11622912Sartem */ 11632912Sartem char ** 11642912Sartem libhal_device_get_property_strlist (LibHalContext *ctx, const char *udi, const char *key, DBusError *error) 11652912Sartem { 11662912Sartem DBusMessage *message; 11672912Sartem DBusMessage *reply; 11682912Sartem DBusMessageIter iter, iter_array, reply_iter; 11692912Sartem char **our_strings; 11702912Sartem DBusError _error; 11712912Sartem 11722912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL); 11732912Sartem 11742912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", udi, 11752912Sartem "org.freedesktop.Hal.Device", 11762912Sartem "GetPropertyStringList"); 11772912Sartem if (message == NULL) { 11782912Sartem fprintf (stderr, 11792912Sartem "%s %d : Couldn't allocate D-BUS message\n", 11802912Sartem __FILE__, __LINE__); 11812912Sartem return NULL; 11822912Sartem } 11832912Sartem 11842912Sartem dbus_message_iter_init_append (message, &iter); 11852912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key); 11862912Sartem 11872912Sartem dbus_error_init (&_error); 11882912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 11892912Sartem message, -1, 11902912Sartem &_error); 11912912Sartem 11922912Sartem dbus_move_error (&_error, error); 11932912Sartem if (error != NULL && dbus_error_is_set (error)) { 11942912Sartem dbus_message_unref (message); 11952912Sartem return NULL; 11962912Sartem } 11972912Sartem if (reply == NULL) { 11982912Sartem dbus_message_unref (message); 11992912Sartem return NULL; 12002912Sartem } 12012912Sartem /* now analyse reply */ 12022912Sartem dbus_message_iter_init (reply, &reply_iter); 12032912Sartem 12042912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) { 12052912Sartem fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__); 12062912Sartem return NULL; 12072912Sartem } 12082912Sartem 12092912Sartem dbus_message_iter_recurse (&reply_iter, &iter_array); 12102912Sartem 12112912Sartem our_strings = libhal_get_string_array_from_iter (&iter_array, NULL); 12122912Sartem 12132912Sartem dbus_message_unref (reply); 12142912Sartem dbus_message_unref (message); 12152912Sartem 12162912Sartem return our_strings; 12172912Sartem } 12182912Sartem 12192912Sartem /** 12202912Sartem * libhal_device_get_property_string: 12212912Sartem * @ctx: the context for the connection to hald 12222912Sartem * @udi: the Unique Device Id 12232912Sartem * @key: the name of the property 12242912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 12252912Sartem * 12262912Sartem * Get the value of a property of type string. 12272912Sartem * 12282912Sartem * Returns: UTF8 nul-terminated string. The caller is responsible for 12292912Sartem * freeing this string with the function libhal_free_string(). Returns 12302912Sartem * NULL if the property didn't exist or we are OOM. 12312912Sartem */ 12322912Sartem char * 12332912Sartem libhal_device_get_property_string (LibHalContext *ctx, 12342912Sartem const char *udi, const char *key, DBusError *error) 12352912Sartem { 12362912Sartem DBusMessage *message; 12372912Sartem DBusMessage *reply; 12382912Sartem DBusMessageIter iter, reply_iter; 12392912Sartem char *value; 12402912Sartem char *dbus_str; 12412912Sartem DBusError _error; 12422912Sartem 12432912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL); 12442912Sartem 12452912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", udi, 12462912Sartem "org.freedesktop.Hal.Device", 12472912Sartem "GetPropertyString"); 12482912Sartem 12492912Sartem if (message == NULL) { 12502912Sartem fprintf (stderr, 12512912Sartem "%s %d : Couldn't allocate D-BUS message\n", 12522912Sartem __FILE__, __LINE__); 12532912Sartem return NULL; 12542912Sartem } 12552912Sartem 12562912Sartem dbus_message_iter_init_append (message, &iter); 12572912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key); 12582912Sartem 12592912Sartem dbus_error_init (&_error); 12602912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 12612912Sartem message, -1, 12622912Sartem &_error); 12632912Sartem 12642912Sartem dbus_move_error (&_error, error); 12652912Sartem if (error != NULL && dbus_error_is_set (error)) { 12662912Sartem dbus_message_unref (message); 12672912Sartem return NULL; 12682912Sartem } 12692912Sartem if (reply == NULL) { 12702912Sartem dbus_message_unref (message); 12712912Sartem return NULL; 12722912Sartem } 12732912Sartem 12742912Sartem dbus_message_iter_init (reply, &reply_iter); 12752912Sartem 12762912Sartem /* now analyze reply */ 12772912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != 12782912Sartem DBUS_TYPE_STRING) { 12792912Sartem dbus_message_unref (message); 12802912Sartem dbus_message_unref (reply); 12812912Sartem return NULL; 12822912Sartem } 12832912Sartem 12842912Sartem dbus_message_iter_get_basic (&reply_iter, &dbus_str); 12852912Sartem value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL); 12862912Sartem if (value == NULL) { 12872912Sartem fprintf (stderr, "%s %d : error allocating memory\n", 12882912Sartem __FILE__, __LINE__); 12892912Sartem /** @todo FIXME cleanup */ 12902912Sartem return NULL; 12912912Sartem } 12922912Sartem 12932912Sartem dbus_message_unref (message); 12942912Sartem dbus_message_unref (reply); 12952912Sartem return value; 12962912Sartem } 12972912Sartem 12982912Sartem /** 12992912Sartem * libhal_device_get_property_int: 13002912Sartem * @ctx: the context for the connection to hald 13012912Sartem * @udi: the Unique Device Id 13022912Sartem * @key: name of the property 13032912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 13042912Sartem * 13052912Sartem * Get the value of a property of type integer. 13062912Sartem * 13072912Sartem * Returns: Property value (32-bit signed integer) 13082912Sartem */ 13092912Sartem dbus_int32_t 13102912Sartem libhal_device_get_property_int (LibHalContext *ctx, 13112912Sartem const char *udi, const char *key, DBusError *error) 13122912Sartem { 13132912Sartem DBusMessage *message; 13142912Sartem DBusMessage *reply; 13152912Sartem DBusMessageIter iter, reply_iter; 13162912Sartem dbus_int32_t value; 13172912Sartem DBusError _error; 13182912Sartem 13192912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1); 13202912Sartem 13212912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", udi, 13222912Sartem "org.freedesktop.Hal.Device", 13232912Sartem "GetPropertyInteger"); 13242912Sartem if (message == NULL) { 13252912Sartem fprintf (stderr, 13262912Sartem "%s %d : Couldn't allocate D-BUS message\n", 13272912Sartem __FILE__, __LINE__); 13282912Sartem return -1; 13292912Sartem } 13302912Sartem 13312912Sartem dbus_message_iter_init_append (message, &iter); 13322912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key); 13332912Sartem 13342912Sartem dbus_error_init (&_error); 13352912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 13362912Sartem message, -1, 13372912Sartem &_error); 13382912Sartem 13392912Sartem dbus_move_error (&_error, error); 13402912Sartem if (error != NULL && dbus_error_is_set (error)) { 13412912Sartem dbus_message_unref (message); 13422912Sartem return -1; 13432912Sartem } 13442912Sartem if (reply == NULL) { 13452912Sartem dbus_message_unref (message); 13462912Sartem return -1; 13472912Sartem } 13482912Sartem 13492912Sartem dbus_message_iter_init (reply, &reply_iter); 13502912Sartem 13512912Sartem /* now analyze reply */ 13522912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != 13532912Sartem DBUS_TYPE_INT32) { 13542912Sartem fprintf (stderr, 13552912Sartem "%s %d : property '%s' for device '%s' is not " 13562912Sartem "of type integer\n", __FILE__, __LINE__, key, 13572912Sartem udi); 13582912Sartem dbus_message_unref (message); 13592912Sartem dbus_message_unref (reply); 13602912Sartem return -1; 13612912Sartem } 13622912Sartem dbus_message_iter_get_basic (&reply_iter, &value); 13632912Sartem 13642912Sartem dbus_message_unref (message); 13652912Sartem dbus_message_unref (reply); 13662912Sartem return value; 13672912Sartem } 13682912Sartem 13692912Sartem /** 13702912Sartem * libhal_device_get_property_uint64: 13712912Sartem * @ctx: the context for the connection to hald 13722912Sartem * @udi: the Unique Device Id 13732912Sartem * @key: name of the property 13742912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 13752912Sartem * 13762912Sartem * Get the value of a property of type signed integer. 13772912Sartem * 13782912Sartem * Returns: Property value (64-bit unsigned integer) 13792912Sartem */ 13802912Sartem dbus_uint64_t 13812912Sartem libhal_device_get_property_uint64 (LibHalContext *ctx, 13822912Sartem const char *udi, const char *key, DBusError *error) 13832912Sartem { 13842912Sartem DBusMessage *message; 13852912Sartem DBusMessage *reply; 13862912Sartem DBusMessageIter iter, reply_iter; 13872912Sartem dbus_uint64_t value; 13882912Sartem DBusError _error; 13892912Sartem 13902912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1); 13912912Sartem 13922912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", udi, 13932912Sartem "org.freedesktop.Hal.Device", 13942912Sartem "GetPropertyInteger"); 13952912Sartem if (message == NULL) { 13962912Sartem fprintf (stderr, 13972912Sartem "%s %d : Couldn't allocate D-BUS message\n", 13982912Sartem __FILE__, __LINE__); 13992912Sartem return -1; 14002912Sartem } 14012912Sartem 14022912Sartem dbus_message_iter_init_append (message, &iter); 14032912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key); 14042912Sartem 14052912Sartem dbus_error_init (&_error); 14062912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 14072912Sartem message, -1, 14082912Sartem &_error); 14092912Sartem 14102912Sartem dbus_move_error (&_error, error); 14112912Sartem if (error != NULL && dbus_error_is_set (error)) { 14122912Sartem dbus_message_unref (message); 14132912Sartem return -1; 14142912Sartem } 14152912Sartem if (reply == NULL) { 14162912Sartem dbus_message_unref (message); 14172912Sartem return -1; 14182912Sartem } 14192912Sartem 14202912Sartem dbus_message_iter_init (reply, &reply_iter); 14212912Sartem /* now analyze reply */ 14222912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != 14232912Sartem DBUS_TYPE_UINT64) { 14242912Sartem fprintf (stderr, 14252912Sartem "%s %d : property '%s' for device '%s' is not " 14262912Sartem "of type integer\n", __FILE__, __LINE__, key, 14272912Sartem udi); 14282912Sartem dbus_message_unref (message); 14292912Sartem dbus_message_unref (reply); 14302912Sartem return -1; 14312912Sartem } 14322912Sartem dbus_message_iter_get_basic (&reply_iter, &value); 14332912Sartem 14342912Sartem dbus_message_unref (message); 14352912Sartem dbus_message_unref (reply); 14362912Sartem return value; 14372912Sartem } 14382912Sartem 14392912Sartem /** 14402912Sartem * libhal_device_get_property_double: 14412912Sartem * @ctx: the context for the connection to hald 14422912Sartem * @udi: the Unique Device Id 14432912Sartem * @key: name of the property 14442912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 14452912Sartem * 14462912Sartem * Get the value of a property of type double. 14472912Sartem * 14482912Sartem * Returns: Property value (IEEE754 double precision float) 14492912Sartem */ 14502912Sartem double 14512912Sartem libhal_device_get_property_double (LibHalContext *ctx, 14522912Sartem const char *udi, const char *key, DBusError *error) 14532912Sartem { 14542912Sartem DBusMessage *message; 14552912Sartem DBusMessage *reply; 14562912Sartem DBusMessageIter iter, reply_iter; 14572912Sartem double value; 14582912Sartem DBusError _error; 14592912Sartem 14602912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1.0); 14612912Sartem 14622912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", udi, 14632912Sartem "org.freedesktop.Hal.Device", 14642912Sartem "GetPropertyDouble"); 14652912Sartem if (message == NULL) { 14662912Sartem fprintf (stderr, 14672912Sartem "%s %d : Couldn't allocate D-BUS message\n", 14682912Sartem __FILE__, __LINE__); 14692912Sartem return -1.0f; 14702912Sartem } 14712912Sartem 14722912Sartem dbus_message_iter_init_append (message, &iter); 14732912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key); 14742912Sartem 14752912Sartem dbus_error_init (&_error); 14762912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 14772912Sartem message, -1, 14782912Sartem &_error); 14792912Sartem 14802912Sartem dbus_move_error (&_error, error); 14812912Sartem if (error != NULL && dbus_error_is_set (error)) { 14822912Sartem dbus_message_unref (message); 14832912Sartem return -1.0f; 14842912Sartem } 14852912Sartem if (reply == NULL) { 14862912Sartem dbus_message_unref (message); 14872912Sartem return -1.0f; 14882912Sartem } 14892912Sartem 14902912Sartem dbus_message_iter_init (reply, &reply_iter); 14912912Sartem 14922912Sartem /* now analyze reply */ 14932912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != 14942912Sartem DBUS_TYPE_DOUBLE) { 14952912Sartem fprintf (stderr, 14962912Sartem "%s %d : property '%s' for device '%s' is not " 14972912Sartem "of type double\n", __FILE__, __LINE__, key, udi); 14982912Sartem dbus_message_unref (message); 14992912Sartem dbus_message_unref (reply); 15002912Sartem return -1.0f; 15012912Sartem } 15022912Sartem dbus_message_iter_get_basic (&reply_iter, &value); 15032912Sartem 15042912Sartem dbus_message_unref (message); 15052912Sartem dbus_message_unref (reply); 15062912Sartem return (double) value; 15072912Sartem } 15082912Sartem 15092912Sartem /** 15102912Sartem * libhal_device_get_property_bool: 15112912Sartem * @ctx: the context for the connection to hald 15122912Sartem * @udi: the Unique Device Id 15132912Sartem * @key: name of the property 15142912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 15152912Sartem * 15162912Sartem * Get the value of a property of type bool. 15172912Sartem * 15182912Sartem * Returns: Property value (boolean) 15192912Sartem */ 15202912Sartem dbus_bool_t 15212912Sartem libhal_device_get_property_bool (LibHalContext *ctx, 15222912Sartem const char *udi, const char *key, DBusError *error) 15232912Sartem { 15242912Sartem DBusMessage *message; 15252912Sartem DBusMessage *reply; 15262912Sartem DBusMessageIter iter, reply_iter; 15272912Sartem dbus_bool_t value; 15282912Sartem DBusError _error; 15292912Sartem 15302912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 15312912Sartem 15322912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", udi, 15332912Sartem "org.freedesktop.Hal.Device", 15342912Sartem "GetPropertyBoolean"); 15352912Sartem if (message == NULL) { 15362912Sartem fprintf (stderr, 15372912Sartem "%s %d : Couldn't allocate D-BUS message\n", 15382912Sartem __FILE__, __LINE__); 15392912Sartem return FALSE; 15402912Sartem } 15412912Sartem 15422912Sartem dbus_message_iter_init_append (message, &iter); 15432912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key); 15442912Sartem 15452912Sartem dbus_error_init (&_error); 15462912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 15472912Sartem message, -1, 15482912Sartem &_error); 15492912Sartem 15502912Sartem dbus_move_error (&_error, error); 15512912Sartem if (error != NULL && dbus_error_is_set (error)) { 15522912Sartem dbus_message_unref (message); 15532912Sartem return FALSE; 15542912Sartem } 15552912Sartem if (reply == NULL) { 15562912Sartem dbus_message_unref (message); 15572912Sartem return FALSE; 15582912Sartem } 15592912Sartem 15602912Sartem dbus_message_iter_init (reply, &reply_iter); 15612912Sartem 15622912Sartem /* now analyze reply */ 15632912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != 15642912Sartem DBUS_TYPE_BOOLEAN) { 15652912Sartem fprintf (stderr, 15662912Sartem "%s %d : property '%s' for device '%s' is not " 15672912Sartem "of type bool\n", __FILE__, __LINE__, key, udi); 15682912Sartem dbus_message_unref (message); 15692912Sartem dbus_message_unref (reply); 15702912Sartem return FALSE; 15712912Sartem } 15722912Sartem dbus_message_iter_get_basic (&reply_iter, &value); 15732912Sartem 15742912Sartem dbus_message_unref (message); 15752912Sartem dbus_message_unref (reply); 15762912Sartem return value; 15772912Sartem } 15782912Sartem 15792912Sartem 15802912Sartem /* generic helper */ 15812912Sartem static dbus_bool_t 15822912Sartem libhal_device_set_property_helper (LibHalContext *ctx, 15832912Sartem const char *udi, 15842912Sartem const char *key, 15852912Sartem int type, 15862912Sartem const char *str_value, 15872912Sartem dbus_int32_t int_value, 15882912Sartem dbus_uint64_t uint64_value, 15892912Sartem double double_value, 15902912Sartem dbus_bool_t bool_value, 15912912Sartem DBusError *error) 15922912Sartem { 15932912Sartem DBusMessage *message; 15942912Sartem DBusMessage *reply; 15952912Sartem DBusMessageIter iter; 15962912Sartem char *method_name = NULL; 15972912Sartem 15982912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 15992912Sartem 16002912Sartem /** @todo sanity check incoming params */ 16012912Sartem switch (type) { 16022912Sartem case DBUS_TYPE_INVALID: 16032912Sartem method_name = "RemoveProperty"; 16042912Sartem break; 16052912Sartem case DBUS_TYPE_STRING: 16062912Sartem method_name = "SetPropertyString"; 16072912Sartem break; 16082912Sartem case DBUS_TYPE_INT32: 16092912Sartem case DBUS_TYPE_UINT64: 16102912Sartem method_name = "SetPropertyInteger"; 16112912Sartem break; 16122912Sartem case DBUS_TYPE_DOUBLE: 16132912Sartem method_name = "SetPropertyDouble"; 16142912Sartem break; 16152912Sartem case DBUS_TYPE_BOOLEAN: 16162912Sartem method_name = "SetPropertyBoolean"; 16172912Sartem break; 16182912Sartem 16192912Sartem default: 16202912Sartem /* cannot happen; is not callable from outside this file */ 16212912Sartem break; 16222912Sartem } 16232912Sartem 16242912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", udi, 16252912Sartem "org.freedesktop.Hal.Device", 16262912Sartem method_name); 16272912Sartem if (message == NULL) { 16282912Sartem fprintf (stderr, 16292912Sartem "%s %d : Couldn't allocate D-BUS message\n", 16302912Sartem __FILE__, __LINE__); 16312912Sartem return FALSE; 16322912Sartem } 16332912Sartem 16342912Sartem dbus_message_iter_init_append (message, &iter); 16352912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key); 16362912Sartem switch (type) { 16372912Sartem case DBUS_TYPE_STRING: 16382912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &str_value); 16392912Sartem break; 16402912Sartem case DBUS_TYPE_INT32: 16412912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &int_value); 16422912Sartem break; 16432912Sartem case DBUS_TYPE_UINT64: 16442912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT64, &uint64_value); 16452912Sartem break; 16462912Sartem case DBUS_TYPE_DOUBLE: 16472912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_DOUBLE, &double_value); 16482912Sartem break; 16492912Sartem case DBUS_TYPE_BOOLEAN: 16502912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &bool_value); 16512912Sartem break; 16522912Sartem } 16532912Sartem 16542912Sartem 16552912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 16562912Sartem message, -1, 16572912Sartem error); 1658*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 16592912Sartem dbus_message_unref (message); 16602912Sartem return FALSE; 16612912Sartem } 16622912Sartem 16632912Sartem if (reply == NULL) { 16642912Sartem dbus_message_unref (message); 16652912Sartem return FALSE; 16662912Sartem } 16672912Sartem 16682912Sartem dbus_message_unref (message); 16692912Sartem dbus_message_unref (reply); 16702912Sartem 16712912Sartem return TRUE; 16722912Sartem } 16732912Sartem 16742912Sartem /** 16752912Sartem * libhal_device_set_property_string: 16762912Sartem * @ctx: the context for the connection to hald 16772912Sartem * @udi: the Unique Device Id 16782912Sartem * @key: name of the property 16792912Sartem * @value: value of the property; a UTF8 string 16802912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 16812912Sartem * 16822912Sartem * Set a property of type string. 16832912Sartem * 16842912Sartem * Returns: TRUE if the property was set, FALSE if the device didn't 16852912Sartem * exist or the property had a different type. 16862912Sartem */ 16872912Sartem dbus_bool_t 16882912Sartem libhal_device_set_property_string (LibHalContext *ctx, 16892912Sartem const char *udi, 16902912Sartem const char *key, 16912912Sartem const char *value, 16922912Sartem DBusError *error) 16932912Sartem { 16942912Sartem return libhal_device_set_property_helper (ctx, udi, key, 16952912Sartem DBUS_TYPE_STRING, 16962912Sartem value, 0, 0, 0.0f, FALSE, error); 16972912Sartem } 16982912Sartem 16992912Sartem /** 17002912Sartem * libhal_device_set_property_int: 17012912Sartem * @ctx: the context for the connection to hald 17022912Sartem * @udi: the Unique Device Id 17032912Sartem * @key: name of the property 17042912Sartem * @value: value of the property 17052912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 17062912Sartem * 17072912Sartem * Set a property of type signed integer. 17082912Sartem * 17092912Sartem * Returns: TRUE if the property was set, FALSE if the device didn't 17102912Sartem * exist or the property had a different type. 17112912Sartem */ 17122912Sartem dbus_bool_t 17132912Sartem libhal_device_set_property_int (LibHalContext *ctx, const char *udi, 17142912Sartem const char *key, dbus_int32_t value, DBusError *error) 17152912Sartem { 17162912Sartem return libhal_device_set_property_helper (ctx, udi, key, 17172912Sartem DBUS_TYPE_INT32, 17182912Sartem NULL, value, 0, 0.0f, FALSE, error); 17192912Sartem } 17202912Sartem 17212912Sartem /** 17222912Sartem * libhal_device_set_property_uint64: 17232912Sartem * @ctx: the context for the connection to hald 17242912Sartem * @udi: the Unique Device Id 17252912Sartem * @key: name of the property 17262912Sartem * @value: value of the property 17272912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 17282912Sartem * 17292912Sartem * Set a property of type unsigned integer. 17302912Sartem * 17312912Sartem * Returns: TRUE if the property was set, FALSE if the device didn't 17322912Sartem * exist or the property had a different type. 17332912Sartem */ 17342912Sartem dbus_bool_t 17352912Sartem libhal_device_set_property_uint64 (LibHalContext *ctx, const char *udi, 17362912Sartem const char *key, dbus_uint64_t value, DBusError *error) 17372912Sartem { 17382912Sartem return libhal_device_set_property_helper (ctx, udi, key, 17392912Sartem DBUS_TYPE_UINT64, 17402912Sartem NULL, 0, value, 0.0f, FALSE, error); 17412912Sartem } 17422912Sartem 17432912Sartem /** 17442912Sartem * libhal_device_set_property_double: 17452912Sartem * @ctx: the context for the connection to hald 17462912Sartem * @udi: the Unique Device Id 17472912Sartem * @key: name of the property 17482912Sartem * @value: value of the property 17492912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 17502912Sartem * 17512912Sartem * Set a property of type double. 17522912Sartem * 17532912Sartem * Returns: TRUE if the property was set, FALSE if the device didn't 17542912Sartem * exist or the property had a different type. 17552912Sartem */ 17562912Sartem dbus_bool_t 17572912Sartem libhal_device_set_property_double (LibHalContext *ctx, const char *udi, 17582912Sartem const char *key, double value, DBusError *error) 17592912Sartem { 17602912Sartem return libhal_device_set_property_helper (ctx, udi, key, 17612912Sartem DBUS_TYPE_DOUBLE, 17622912Sartem NULL, 0, 0, value, FALSE, error); 17632912Sartem } 17642912Sartem 17652912Sartem /** 17662912Sartem * libhal_device_set_property_bool: 17672912Sartem * @ctx: the context for the connection to hald 17682912Sartem * @udi: the Unique Device Id 17692912Sartem * @key: name of the property 17702912Sartem * @value: value of the property 17712912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 17722912Sartem * 17732912Sartem * Set a property of type bool. 17742912Sartem * 17752912Sartem * Returns: TRUE if the property was set, FALSE if the device didn't 17762912Sartem * exist or the property had a different type. 17772912Sartem */ 17782912Sartem dbus_bool_t 17792912Sartem libhal_device_set_property_bool (LibHalContext *ctx, const char *udi, 17802912Sartem const char *key, dbus_bool_t value, DBusError *error) 17812912Sartem { 17822912Sartem return libhal_device_set_property_helper (ctx, udi, key, 17832912Sartem DBUS_TYPE_BOOLEAN, 17842912Sartem NULL, 0, 0, 0.0f, value, error); 17852912Sartem } 17862912Sartem 17872912Sartem 17882912Sartem /** 17892912Sartem * libhal_device_remove_property: 17902912Sartem * @ctx: the context for the connection to hald 17912912Sartem * @udi: the Unique Device Id 17922912Sartem * @key: name of the property 17932912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 17942912Sartem * 17952912Sartem * Remove a property. 17962912Sartem * 17972912Sartem * Returns: TRUE if the property was set, FALSE if the device didn't 17982912Sartem * exist 17992912Sartem */ 18002912Sartem dbus_bool_t 18012912Sartem libhal_device_remove_property (LibHalContext *ctx, 18022912Sartem const char *udi, const char *key, DBusError *error) 18032912Sartem { 18042912Sartem return libhal_device_set_property_helper (ctx, udi, key, DBUS_TYPE_INVALID, 18052912Sartem /* DBUS_TYPE_INVALID means remove */ 18062912Sartem NULL, 0, 0, 0.0f, FALSE, error); 18072912Sartem } 18082912Sartem 18092912Sartem /** 18102912Sartem * libhal_device_property_strlist_append: 18112912Sartem * @ctx: the context for the connection to hald 18122912Sartem * @udi: the Unique Device Id 18132912Sartem * @key: name of the property 18142912Sartem * @value: value to append to property 18152912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 18162912Sartem * 18172912Sartem * Append to a property of type strlist. 18182912Sartem * 18192912Sartem * Returns: TRUE if the value was appended, FALSE if the device didn't 18202912Sartem * exist or the property had a different type. 18212912Sartem */ 18222912Sartem dbus_bool_t 18232912Sartem libhal_device_property_strlist_append (LibHalContext *ctx, 18242912Sartem const char *udi, 18252912Sartem const char *key, 18262912Sartem const char *value, 18272912Sartem DBusError *error) 18282912Sartem { 18292912Sartem DBusMessage *message; 18302912Sartem DBusMessage *reply; 18312912Sartem DBusMessageIter iter; 18322912Sartem 18332912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 18342912Sartem 18352912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", udi, 18362912Sartem "org.freedesktop.Hal.Device", 18372912Sartem "StringListAppend"); 18382912Sartem if (message == NULL) { 18392912Sartem fprintf (stderr, 18402912Sartem "%s %d : Couldn't allocate D-BUS message\n", 18412912Sartem __FILE__, __LINE__); 18422912Sartem return FALSE; 18432912Sartem } 18442912Sartem dbus_message_iter_init_append (message, &iter); 18452912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key); 18462912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value); 18472912Sartem 18482912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 18492912Sartem message, -1, 18502912Sartem error); 1851*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 18522912Sartem dbus_message_unref (message); 18532912Sartem return FALSE; 18542912Sartem } 18552912Sartem if (reply == NULL) { 18562912Sartem dbus_message_unref (message); 18572912Sartem return FALSE; 18582912Sartem } 18592912Sartem return TRUE; 18602912Sartem } 18612912Sartem 18622912Sartem /** 18632912Sartem * libhal_device_property_strlist_prepend: 18642912Sartem * @ctx: the context for the connection to hald 18652912Sartem * @udi: the Unique Device Id 18662912Sartem * @key: name of the property 18672912Sartem * @value: value to prepend to property 18682912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 18692912Sartem * 18702912Sartem * Prepend to a property of type strlist. 18712912Sartem * 18722912Sartem * Returns: TRUE if the value was prepended, FALSE if the device 18732912Sartem * didn't exist or the property had a different type. 18742912Sartem */ 18752912Sartem dbus_bool_t 18762912Sartem libhal_device_property_strlist_prepend (LibHalContext *ctx, 18772912Sartem const char *udi, 18782912Sartem const char *key, 18792912Sartem const char *value, 18802912Sartem DBusError *error) 18812912Sartem { 18822912Sartem DBusMessage *message; 18832912Sartem DBusMessage *reply; 18842912Sartem DBusMessageIter iter; 18852912Sartem 18862912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 18872912Sartem 18882912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", udi, 18892912Sartem "org.freedesktop.Hal.Device", 18902912Sartem "StringListPrepend"); 18912912Sartem if (message == NULL) { 18922912Sartem fprintf (stderr, 18932912Sartem "%s %d : Couldn't allocate D-BUS message\n", 18942912Sartem __FILE__, __LINE__); 18952912Sartem return FALSE; 18962912Sartem } 18972912Sartem dbus_message_iter_init_append (message, &iter); 18982912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key); 18992912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value); 19002912Sartem 19012912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 19022912Sartem message, -1, 19032912Sartem error); 1904*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 19052912Sartem dbus_message_unref (message); 19062912Sartem return FALSE; 19072912Sartem } 19082912Sartem if (reply == NULL) { 19092912Sartem dbus_message_unref (message); 19102912Sartem return FALSE; 19112912Sartem } 19122912Sartem return TRUE; 19132912Sartem } 19142912Sartem 19152912Sartem /** 19162912Sartem * libhal_device_property_strlist_remove_index: 19172912Sartem * @ctx: the context for the connection to hald 19182912Sartem * @udi: the Unique Device Id 19192912Sartem * @key: name of the property 19202912Sartem * @idx: index of string to remove in the strlist 19212912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 19222912Sartem * 19232912Sartem * Remove a specified string from a property of type strlist. 19242912Sartem * 19252912Sartem * Returns: TRUE if the string was removed, FALSE if the device didn't 19262912Sartem * exist or the property had a different type. 19272912Sartem */ 19282912Sartem dbus_bool_t 19292912Sartem libhal_device_property_strlist_remove_index (LibHalContext *ctx, 19302912Sartem const char *udi, 19312912Sartem const char *key, 19322912Sartem unsigned int idx, 19332912Sartem DBusError *error) 19342912Sartem { 19352912Sartem DBusMessage *message; 19362912Sartem DBusMessage *reply; 19372912Sartem DBusMessageIter iter; 19382912Sartem 19392912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 19402912Sartem 19412912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", udi, 19422912Sartem "org.freedesktop.Hal.Device", 19432912Sartem "StringListRemoveIndex"); 19442912Sartem if (message == NULL) { 19452912Sartem fprintf (stderr, 19462912Sartem "%s %d : Couldn't allocate D-BUS message\n", 19472912Sartem __FILE__, __LINE__); 19482912Sartem return FALSE; 19492912Sartem } 19502912Sartem dbus_message_iter_init_append (message, &iter); 19512912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key); 19522912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &idx); 19532912Sartem 19542912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 19552912Sartem message, -1, 19562912Sartem error); 1957*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 19582912Sartem dbus_message_unref (message); 19592912Sartem return FALSE; 19602912Sartem } 19612912Sartem if (reply == NULL) { 19622912Sartem dbus_message_unref (message); 19632912Sartem return FALSE; 19642912Sartem } 19652912Sartem return TRUE; 19662912Sartem } 19672912Sartem 19682912Sartem /** 19692912Sartem * libhal_device_property_strlist_remove: 19702912Sartem * @ctx: the context for the connection to hald 19712912Sartem * @udi: the Unique Device Id 19722912Sartem * @key: name of the property 19732912Sartem * @value: the string to remove 19742912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 19752912Sartem * 19762912Sartem * Remove a specified string from a property of type strlist. 19772912Sartem * 19782912Sartem * Returns: TRUE if the string was removed, FALSE if the device didn't 19792912Sartem * exist or the property had a different type. 19802912Sartem */ 19812912Sartem dbus_bool_t 19822912Sartem libhal_device_property_strlist_remove (LibHalContext *ctx, 19832912Sartem const char *udi, 19842912Sartem const char *key, 19852912Sartem const char *value, DBusError *error) 19862912Sartem { 19872912Sartem DBusMessage *message; 19882912Sartem DBusMessage *reply; 19892912Sartem DBusMessageIter iter; 19902912Sartem 19912912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 19922912Sartem 19932912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", udi, 19942912Sartem "org.freedesktop.Hal.Device", 19952912Sartem "StringListRemove"); 19962912Sartem if (message == NULL) { 19972912Sartem fprintf (stderr, 19982912Sartem "%s %d : Couldn't allocate D-BUS message\n", 19992912Sartem __FILE__, __LINE__); 20002912Sartem return FALSE; 20012912Sartem } 20022912Sartem dbus_message_iter_init_append (message, &iter); 20032912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key); 20042912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value); 20052912Sartem 20062912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 20072912Sartem message, -1, 20082912Sartem error); 2009*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 20102912Sartem dbus_message_unref (message); 20112912Sartem return FALSE; 20122912Sartem } 20132912Sartem if (reply == NULL) { 20142912Sartem dbus_message_unref (message); 20152912Sartem return FALSE; 20162912Sartem } 20172912Sartem return TRUE; 20182912Sartem } 20192912Sartem 20202912Sartem 20212912Sartem /** 20222912Sartem * libhal_device_lock: 20232912Sartem * @ctx: the context for the connection to hald 20242912Sartem * @udi: the Unique Device Id 20252912Sartem * @reason_to_lock: a user-presentable reason why the device is locked. 20262912Sartem * @reason_why_locked: a pointer to store the reason why the device cannot be locked on failure, or NULL 20272912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 20282912Sartem * 20292912Sartem * Take an advisory lock on the device. 20302912Sartem * 20312912Sartem * Returns: TRUE if the lock was obtained, FALSE otherwise 20322912Sartem */ 20332912Sartem dbus_bool_t 20342912Sartem libhal_device_lock (LibHalContext *ctx, 20352912Sartem const char *udi, 20362912Sartem const char *reason_to_lock, 20372912Sartem char **reason_why_locked, DBusError *error) 20382912Sartem { 20392912Sartem DBusMessage *message; 20402912Sartem DBusMessageIter iter; 20412912Sartem DBusMessage *reply; 20422912Sartem 20432912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 20442912Sartem 20452912Sartem if (reason_why_locked != NULL) 20462912Sartem *reason_why_locked = NULL; 20472912Sartem 20482912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", 20492912Sartem udi, 20502912Sartem "org.freedesktop.Hal.Device", 20512912Sartem "Lock"); 20522912Sartem 20532912Sartem if (message == NULL) { 20542912Sartem fprintf (stderr, 20552912Sartem "%s %d : Couldn't allocate D-BUS message\n", 20562912Sartem __FILE__, __LINE__); 20572912Sartem return FALSE; 20582912Sartem } 20592912Sartem 20602912Sartem dbus_message_iter_init_append (message, &iter); 20612912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &reason_to_lock); 20622912Sartem 20632912Sartem 20642912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 20652912Sartem message, -1, 20662912Sartem error); 20672912Sartem 2068*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 20692912Sartem if (strcmp (error->name, 20702912Sartem "org.freedesktop.Hal.DeviceAlreadyLocked") == 0) { 20712912Sartem if (reason_why_locked != NULL) { 20722912Sartem *reason_why_locked = 20732912Sartem dbus_malloc0 (strlen (error->message) + 1); 20742912Sartem strcpy (*reason_why_locked, error->message); 20752912Sartem } 20762912Sartem } 20772912Sartem 20782912Sartem dbus_message_unref (message); 20792912Sartem return FALSE; 20802912Sartem } 20812912Sartem 20822912Sartem dbus_message_unref (message); 20832912Sartem 20842912Sartem if (reply == NULL) 20852912Sartem return FALSE; 20862912Sartem 20872912Sartem dbus_message_unref (reply); 20882912Sartem 20892912Sartem return TRUE; 20902912Sartem } 20912912Sartem 20922912Sartem /** 20932912Sartem * libhal_device_unlock: 20942912Sartem * @ctx: the context for the connection to hald 20952912Sartem * @udi: the Unique Device Id 20962912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 20972912Sartem * 20982912Sartem * Release an advisory lock on the device. 20992912Sartem * 21002912Sartem * Returns: TRUE if the device was successfully unlocked, 21012912Sartem * FALSE otherwise 21022912Sartem */ 21032912Sartem dbus_bool_t 21042912Sartem libhal_device_unlock (LibHalContext *ctx, 21052912Sartem const char *udi, DBusError *error) 21062912Sartem { 21072912Sartem DBusMessage *message; 21082912Sartem DBusMessage *reply; 21092912Sartem 21102912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 21112912Sartem 21122912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", 21132912Sartem udi, 21142912Sartem "org.freedesktop.Hal.Device", 21152912Sartem "Unlock"); 21162912Sartem 21172912Sartem if (message == NULL) { 21182912Sartem fprintf (stderr, 21192912Sartem "%s %d : Couldn't allocate D-BUS message\n", 21202912Sartem __FILE__, __LINE__); 21212912Sartem return FALSE; 21222912Sartem } 21232912Sartem 21242912Sartem 21252912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 21262912Sartem message, -1, 21272912Sartem error); 21282912Sartem 2129*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 21302912Sartem dbus_message_unref (message); 21312912Sartem return FALSE; 21322912Sartem } 21332912Sartem 21342912Sartem dbus_message_unref (message); 21352912Sartem 21362912Sartem if (reply == NULL) 21372912Sartem return FALSE; 21382912Sartem 21392912Sartem dbus_message_unref (reply); 21402912Sartem 21412912Sartem return TRUE; 21422912Sartem } 21432912Sartem 21442912Sartem 21452912Sartem /** 21462912Sartem * libhal_new_device: 21472912Sartem * @ctx: the context for the connection to hald 21482912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 21492912Sartem * 21502912Sartem * Create a new device object which will be hidden from applications 21512912Sartem * until the CommitToGdl(), ie. libhal_device_commit_to_gdl(), method 21522912Sartem * is called. Note that the program invoking this method needs to run 21532912Sartem * with super user privileges. 21542912Sartem * 21552912Sartem * Returns: Temporary device unique id or NULL if there was a 21562912Sartem * problem. This string must be freed by the caller. 21572912Sartem */ 21582912Sartem char * 21592912Sartem libhal_new_device (LibHalContext *ctx, DBusError *error) 21602912Sartem { 21612912Sartem DBusMessage *message; 21622912Sartem DBusMessage *reply; 21632912Sartem DBusMessageIter reply_iter; 21642912Sartem char *value; 21652912Sartem char *dbus_str; 21662912Sartem 21672912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL); 21682912Sartem 21692912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", 21702912Sartem "/org/freedesktop/Hal/Manager", 21712912Sartem "org.freedesktop.Hal.Manager", 21722912Sartem "NewDevice"); 21732912Sartem if (message == NULL) { 21742912Sartem fprintf (stderr, 21752912Sartem "%s %d : Couldn't allocate D-BUS message\n", 21762912Sartem __FILE__, __LINE__); 21772912Sartem return NULL; 21782912Sartem } 21792912Sartem 21802912Sartem 21812912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 21822912Sartem message, -1, 21832912Sartem error); 2184*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 21852912Sartem dbus_message_unref (message); 21862912Sartem return NULL; 21872912Sartem } 21882912Sartem if (reply == NULL) { 21892912Sartem dbus_message_unref (message); 21902912Sartem return NULL; 21912912Sartem } 21922912Sartem 21932912Sartem dbus_message_iter_init (reply, &reply_iter); 21942912Sartem 21952912Sartem /* now analyze reply */ 21962912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_STRING) { 21972912Sartem fprintf (stderr, 21982912Sartem "%s %d : expected a string in reply to NewDevice\n", 21992912Sartem __FILE__, __LINE__); 22002912Sartem dbus_message_unref (message); 22012912Sartem dbus_message_unref (reply); 22022912Sartem return NULL; 22032912Sartem } 22042912Sartem 22052912Sartem dbus_message_iter_get_basic (&reply_iter, &dbus_str); 22062912Sartem value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL); 22072912Sartem if (value == NULL) { 22082912Sartem fprintf (stderr, "%s %d : error allocating memory\n", 22092912Sartem __FILE__, __LINE__); 22102912Sartem } 22112912Sartem 22122912Sartem dbus_message_unref (message); 22132912Sartem dbus_message_unref (reply); 22142912Sartem return value; 22152912Sartem } 22162912Sartem 22172912Sartem 22182912Sartem /** 22192912Sartem * libhal_device_commit_to_gdl: 22202912Sartem * @ctx: the context for the connection to hald 22212912Sartem * @temp_udi: the temporary unique device id as returned by libhal_new_device() 22222912Sartem * @udi: the new unique device id. 22232912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 22242912Sartem * 22252912Sartem * When a hidden device has been built using the NewDevice method, 22262912Sartem * ie. libhal_new_device(), and the org.freedesktop.Hal.Device 22272912Sartem * interface this function will commit it to the global device list. 22282912Sartem * 22292912Sartem * This means that the device object will be visible to applications 22302912Sartem * and the HAL daemon will possibly attempt to boot the device 22312912Sartem * (depending on the property RequireEnable). 22322912Sartem * 22332912Sartem * Note that the program invoking this method needs to run with super 22342912Sartem * user privileges. 22352912Sartem * 22362912Sartem * Returns: FALSE if the given unique device id is already in use. 22372912Sartem */ 22382912Sartem dbus_bool_t 22392912Sartem libhal_device_commit_to_gdl (LibHalContext *ctx, 22402912Sartem const char *temp_udi, const char *udi, DBusError *error) 22412912Sartem { 22422912Sartem DBusMessage *message; 22432912Sartem DBusMessage *reply; 22442912Sartem DBusMessageIter iter; 22452912Sartem 22462912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 22472912Sartem 22482912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", 22492912Sartem "/org/freedesktop/Hal/Manager", 22502912Sartem "org.freedesktop.Hal.Manager", 22512912Sartem "CommitToGdl"); 22522912Sartem if (message == NULL) { 22532912Sartem fprintf (stderr, 22542912Sartem "%s %d : Couldn't allocate D-BUS message\n", 22552912Sartem __FILE__, __LINE__); 22562912Sartem return FALSE; 22572912Sartem } 22582912Sartem 22592912Sartem dbus_message_iter_init_append (message, &iter); 22602912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &temp_udi); 22612912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi); 22622912Sartem 22632912Sartem 22642912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 22652912Sartem message, -1, 22662912Sartem error); 2267*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 22682912Sartem dbus_message_unref (message); 22692912Sartem return FALSE; 22702912Sartem } 22712912Sartem if (reply == NULL) { 22722912Sartem dbus_message_unref (message); 22732912Sartem return FALSE; 22742912Sartem } 22752912Sartem 22762912Sartem dbus_message_unref (message); 22772912Sartem dbus_message_unref (reply); 22782912Sartem return TRUE; 22792912Sartem } 22802912Sartem 22812912Sartem /** 22822912Sartem * libhal_remove_device: 22832912Sartem * @ctx: the context for the connection to hald 22842912Sartem * @udi: the Unique device id. 22852912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 22862912Sartem * 22872912Sartem * This method can be invoked when a device is removed. The HAL daemon 22882912Sartem * will shut down the device. Note that the device may still be in the 22892912Sartem * device list if the Persistent property is set to true. 22902912Sartem * 22912912Sartem * Note that the program invoking this method needs to run with super 22922912Sartem * user privileges. 22932912Sartem * 22942912Sartem * Returns: TRUE if the device was removed, FALSE otherwise 22952912Sartem */ 22962912Sartem dbus_bool_t 22972912Sartem libhal_remove_device (LibHalContext *ctx, const char *udi, DBusError *error) 22982912Sartem { 22992912Sartem DBusMessage *message; 23002912Sartem DBusMessage *reply; 23012912Sartem DBusMessageIter iter; 23022912Sartem 23032912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 23042912Sartem 23052912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", 23062912Sartem "/org/freedesktop/Hal/Manager", 23072912Sartem "org.freedesktop.Hal.Manager", 23082912Sartem "Remove"); 23092912Sartem if (message == NULL) { 23102912Sartem fprintf (stderr, 23112912Sartem "%s %d : Couldn't allocate D-BUS message\n", 23122912Sartem __FILE__, __LINE__); 23132912Sartem return FALSE; 23142912Sartem } 23152912Sartem 23162912Sartem dbus_message_iter_init_append (message, &iter); 23172912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi); 23182912Sartem 23192912Sartem 23202912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 23212912Sartem message, -1, 23222912Sartem error); 2323*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 23242912Sartem dbus_message_unref (message); 23252912Sartem return FALSE; 23262912Sartem } 23272912Sartem if (reply == NULL) { 23282912Sartem dbus_message_unref (message); 23292912Sartem return FALSE; 23302912Sartem } 23312912Sartem 23322912Sartem dbus_message_unref (message); 23332912Sartem dbus_message_unref (reply); 23342912Sartem return TRUE; 23352912Sartem } 23362912Sartem 23372912Sartem /** 23382912Sartem * libhal_device_exists: 23392912Sartem * @ctx: the context for the connection to hald 23402912Sartem * @udi: the Unique device id. 23412912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 23422912Sartem * 23432912Sartem * Determine if a device exists. 23442912Sartem * 23452912Sartem * Returns: TRUE if the device exists 23462912Sartem */ 23472912Sartem dbus_bool_t 23482912Sartem libhal_device_exists (LibHalContext *ctx, const char *udi, DBusError *error) 23492912Sartem { 23502912Sartem DBusMessage *message; 23512912Sartem DBusMessage *reply; 23522912Sartem DBusMessageIter iter, reply_iter; 23532912Sartem dbus_bool_t value; 23542912Sartem DBusError _error; 23552912Sartem 23562912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 23572912Sartem 23582912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", 23592912Sartem "/org/freedesktop/Hal/Manager", 23602912Sartem "org.freedesktop.Hal.Manager", 23612912Sartem "DeviceExists"); 23622912Sartem if (message == NULL) { 23632912Sartem fprintf (stderr, 23642912Sartem "%s %d : Couldn't allocate D-BUS message\n", 23652912Sartem __FILE__, __LINE__); 23662912Sartem return FALSE; 23672912Sartem } 23682912Sartem 23692912Sartem dbus_message_iter_init_append (message, &iter); 23702912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi); 23712912Sartem 23722912Sartem dbus_error_init (&_error); 23732912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 23742912Sartem message, -1, 23752912Sartem &_error); 23762912Sartem 23772912Sartem dbus_move_error (&_error, error); 23782912Sartem if (error != NULL && dbus_error_is_set (error)) { 23792912Sartem dbus_message_unref (message); 23802912Sartem return FALSE; 23812912Sartem } 23822912Sartem if (reply == NULL) { 23832912Sartem dbus_message_unref (message); 23842912Sartem return FALSE; 23852912Sartem } 23862912Sartem 23872912Sartem dbus_message_iter_init (reply, &reply_iter); 23882912Sartem 23892912Sartem /* now analyze reply */ 23902912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) { 23912912Sartem fprintf (stderr, 23922912Sartem "%s %d : expected a bool in reply to DeviceExists\n", 23932912Sartem __FILE__, __LINE__); 23942912Sartem dbus_message_unref (message); 23952912Sartem dbus_message_unref (reply); 23962912Sartem return FALSE; 23972912Sartem } 23982912Sartem 23992912Sartem dbus_message_iter_get_basic (&reply_iter, &value); 24002912Sartem 24012912Sartem dbus_message_unref (message); 24022912Sartem dbus_message_unref (reply); 24032912Sartem return value; 24042912Sartem } 24052912Sartem 24062912Sartem /** 24072912Sartem * libhal_device_property_exists: 24082912Sartem * @ctx: the context for the connection to hald 24092912Sartem * @udi: the Unique device id. 24102912Sartem * @key: name of the property 24112912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 24122912Sartem * 24132912Sartem * Determine if a property on a device exists. 24142912Sartem * 24152912Sartem * Returns: TRUE if the device exists, FALSE otherwise 24162912Sartem */ 24172912Sartem dbus_bool_t 24182912Sartem libhal_device_property_exists (LibHalContext *ctx, 24192912Sartem const char *udi, const char *key, DBusError *error) 24202912Sartem { 24212912Sartem DBusMessage *message; 24222912Sartem DBusMessage *reply; 24232912Sartem DBusMessageIter iter, reply_iter; 24242912Sartem dbus_bool_t value; 24252912Sartem DBusError _error; 24262912Sartem 24272912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 24282912Sartem 24292912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", udi, 24302912Sartem "org.freedesktop.Hal.Device", 24312912Sartem "PropertyExists"); 24322912Sartem if (message == NULL) { 24332912Sartem fprintf (stderr, 24342912Sartem "%s %d : Couldn't allocate D-BUS message\n", 24352912Sartem __FILE__, __LINE__); 24362912Sartem return FALSE; 24372912Sartem } 24382912Sartem 24392912Sartem dbus_message_iter_init_append (message, &iter); 24402912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key); 24412912Sartem 24422912Sartem dbus_error_init (&_error); 24432912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 24442912Sartem message, -1, 24452912Sartem &_error); 24462912Sartem 24472912Sartem dbus_move_error (&_error, error); 24482912Sartem if (error != NULL && dbus_error_is_set (error)) { 24492912Sartem dbus_message_unref (message); 24502912Sartem return FALSE; 24512912Sartem } 24522912Sartem if (reply == NULL) { 24532912Sartem dbus_message_unref (message); 24542912Sartem return FALSE; 24552912Sartem } 24562912Sartem 24572912Sartem dbus_message_iter_init (reply, &reply_iter); 24582912Sartem 24592912Sartem /* now analyse reply */ 24602912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) { 24612912Sartem fprintf (stderr, "%s %d : expected a bool in reply to " 24622912Sartem "PropertyExists\n", __FILE__, __LINE__); 24632912Sartem dbus_message_unref (message); 24642912Sartem dbus_message_unref (reply); 24652912Sartem return FALSE; 24662912Sartem } 24672912Sartem 24682912Sartem dbus_message_iter_get_basic (&reply_iter, &value); 24692912Sartem 24702912Sartem dbus_message_unref (message); 24712912Sartem dbus_message_unref (reply); 24722912Sartem return value; 24732912Sartem } 24742912Sartem 24752912Sartem /** 24762912Sartem * libhal_merge_properties: 24772912Sartem * @ctx: the context for the connection to hald 24782912Sartem * @target_udi: the Unique device id of target device to merge to 24792912Sartem * @source_udi: the Unique device id of device to merge from 24802912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 24812912Sartem * 24822912Sartem * Merge properties from one device to another. 24832912Sartem * 24842912Sartem * Returns: TRUE if the properties were merged, FALSE otherwise 24852912Sartem */ 24862912Sartem dbus_bool_t 24872912Sartem libhal_merge_properties (LibHalContext *ctx, 24882912Sartem const char *target_udi, const char *source_udi, DBusError *error) 24892912Sartem { 24902912Sartem DBusMessage *message; 24912912Sartem DBusMessage *reply; 24922912Sartem DBusMessageIter iter; 24932912Sartem 24942912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 24952912Sartem 24962912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", 24972912Sartem "/org/freedesktop/Hal/Manager", 24982912Sartem "org.freedesktop.Hal.Manager", 24992912Sartem "MergeProperties"); 25002912Sartem if (message == NULL) { 25012912Sartem fprintf (stderr, 25022912Sartem "%s %d : Couldn't allocate D-BUS message\n", 25032912Sartem __FILE__, __LINE__); 25042912Sartem return FALSE; 25052912Sartem } 25062912Sartem 25072912Sartem dbus_message_iter_init_append (message, &iter); 25082912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &target_udi); 25092912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &source_udi); 25102912Sartem 25112912Sartem 25122912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 25132912Sartem message, -1, 25142912Sartem error); 2515*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 25162912Sartem dbus_message_unref (message); 25172912Sartem return FALSE; 25182912Sartem } 25192912Sartem if (reply == NULL) { 25202912Sartem dbus_message_unref (message); 25212912Sartem return FALSE; 25222912Sartem } 25232912Sartem 25242912Sartem dbus_message_unref (message); 25252912Sartem dbus_message_unref (reply); 25262912Sartem return TRUE; 25272912Sartem } 25282912Sartem 25292912Sartem /** 25302912Sartem * libhal_device_matches: 25312912Sartem * @ctx: the context for the connection to hald 25322912Sartem * @udi1: the Unique Device Id for device 1 25332912Sartem * @udi2: the Unique Device Id for device 2 25342912Sartem * @property_namespace: the namespace for set of devices, e.g. "usb" 25352912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 25362912Sartem * 25372912Sartem * Check a set of properties for two devices matches. 25382912Sartem * 25392912Sartem * Checks that all properties where keys, starting with a given value 25402912Sartem * (namespace), of the first device is in the second device and that 25412912Sartem * they got the same value and type. 25422912Sartem * 25432912Sartem * Note that the other inclusion isn't tested, so there could be 25442912Sartem * properties (from the given namespace) in the second device not 25452912Sartem * present in the first device. 25462912Sartem * 25472912Sartem * Returns: TRUE if all properties starting with the given namespace 25482912Sartem * parameter from one device is in the other and have the same value. 25492912Sartem */ 25502912Sartem dbus_bool_t 25512912Sartem libhal_device_matches (LibHalContext *ctx, 25522912Sartem const char *udi1, const char *udi2, 25532912Sartem const char *property_namespace, DBusError *error) 25542912Sartem { 25552912Sartem DBusMessage *message; 25562912Sartem DBusMessage *reply; 25572912Sartem DBusMessageIter iter, reply_iter; 25582912Sartem dbus_bool_t value; 25592912Sartem DBusError _error; 25602912Sartem 25612912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 25622912Sartem 25632912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", 25642912Sartem "/org/freedesktop/Hal/Manager", 25652912Sartem "org.freedesktop.Hal.Manager", 25662912Sartem "DeviceMatches"); 25672912Sartem if (message == NULL) { 25682912Sartem fprintf (stderr, 25692912Sartem "%s %d : Couldn't allocate D-BUS message\n", 25702912Sartem __FILE__, __LINE__); 25712912Sartem return FALSE; 25722912Sartem } 25732912Sartem 25742912Sartem dbus_message_iter_init_append (message, &iter); 25752912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, udi1); 25762912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, udi2); 25772912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, property_namespace); 25782912Sartem 25792912Sartem dbus_error_init (&_error); 25802912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 25812912Sartem message, -1, 25822912Sartem &_error); 25832912Sartem 25842912Sartem dbus_move_error (&_error, error); 25852912Sartem if (error != NULL && dbus_error_is_set (error)) { 25862912Sartem dbus_message_unref (message); 25872912Sartem return FALSE; 25882912Sartem } 25892912Sartem if (reply == NULL) { 25902912Sartem dbus_message_unref (message); 25912912Sartem return FALSE; 25922912Sartem } 25932912Sartem /* now analyse reply */ 25942912Sartem dbus_message_iter_init (reply, &reply_iter); 25952912Sartem 25962912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) { 25972912Sartem fprintf (stderr, 25982912Sartem "%s %d : expected a bool in reply to DeviceMatches\n", 25992912Sartem __FILE__, __LINE__); 26002912Sartem dbus_message_unref (message); 26012912Sartem dbus_message_unref (reply); 26022912Sartem return FALSE; 26032912Sartem } 26042912Sartem 26052912Sartem dbus_message_iter_get_basic (&reply_iter, &value); 26062912Sartem 26072912Sartem dbus_message_unref (message); 26082912Sartem dbus_message_unref (reply); 26092912Sartem return value; 26102912Sartem } 26112912Sartem 26122912Sartem /** 26132912Sartem * libhal_device_print: 26142912Sartem * @ctx: the context for the connection to hald 26152912Sartem * @udi: the Unique Device Id 26162912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 26172912Sartem * 26182912Sartem * Print a device to stdout; useful for debugging. 26192912Sartem * 26202912Sartem * Returns: TRUE if device's information could be obtained, FALSE otherwise 26212912Sartem */ 26222912Sartem dbus_bool_t 26232912Sartem libhal_device_print (LibHalContext *ctx, const char *udi, DBusError *error) 26242912Sartem { 26252912Sartem int type; 26262912Sartem char *key; 26272912Sartem LibHalPropertySet *pset; 26282912Sartem LibHalPropertySetIterator i; 26292912Sartem 26302912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 26312912Sartem 26322912Sartem printf ("device_id = %s\n", udi); 26332912Sartem 26342912Sartem if ((pset = libhal_device_get_all_properties (ctx, udi, error)) == NULL) 26352912Sartem return FALSE; 26362912Sartem 26372912Sartem for (libhal_psi_init (&i, pset); libhal_psi_has_more (&i); 26382912Sartem libhal_psi_next (&i)) { 26392912Sartem type = libhal_psi_get_type (&i); 26402912Sartem key = libhal_psi_get_key (&i); 26412912Sartem 26422912Sartem switch (type) { 26432912Sartem case LIBHAL_PROPERTY_TYPE_STRING: 26442912Sartem printf (" %s = '%s' (string)\n", key, 26452912Sartem libhal_psi_get_string (&i)); 26462912Sartem break; 26472912Sartem case LIBHAL_PROPERTY_TYPE_INT32: 26482912Sartem printf (" %s = %d = 0x%x (int)\n", key, 26492912Sartem libhal_psi_get_int (&i), 26502912Sartem libhal_psi_get_int (&i)); 26512912Sartem break; 26522912Sartem case LIBHAL_PROPERTY_TYPE_UINT64: 26532912Sartem printf (" %s = %llu = 0x%llx (uint64)\n", key, 26542912Sartem (long long unsigned int) libhal_psi_get_uint64 (&i), 26552912Sartem (long long unsigned int) libhal_psi_get_uint64 (&i)); 26562912Sartem break; 26572912Sartem case LIBHAL_PROPERTY_TYPE_BOOLEAN: 26582912Sartem printf (" %s = %s (bool)\n", key, 26592912Sartem (libhal_psi_get_bool (&i) ? "true" : 26602912Sartem "false")); 26612912Sartem break; 26622912Sartem case LIBHAL_PROPERTY_TYPE_DOUBLE: 26632912Sartem printf (" %s = %g (double)\n", key, 26642912Sartem libhal_psi_get_double (&i)); 26652912Sartem break; 26662912Sartem case LIBHAL_PROPERTY_TYPE_STRLIST: 26672912Sartem { 26682912Sartem unsigned int j; 26692912Sartem char **str_list; 26702912Sartem 26712912Sartem str_list = libhal_psi_get_strlist (&i); 26722912Sartem printf (" %s = [", key); 26732912Sartem for (j = 0; str_list[j] != NULL; j++) { 26742912Sartem printf ("'%s'", str_list[j]); 26752912Sartem if (str_list[j+1] != NULL) 26762912Sartem printf (", "); 26772912Sartem } 26782912Sartem printf ("] (string list)\n"); 26792912Sartem 26802912Sartem break; 26812912Sartem } 26822912Sartem default: 26832912Sartem printf (" *** unknown type for key %s\n", key); 26842912Sartem break; 26852912Sartem } 26862912Sartem } 26872912Sartem 26882912Sartem libhal_free_property_set (pset); 26892912Sartem 26902912Sartem return TRUE; 26912912Sartem } 26922912Sartem 26932912Sartem /** 26942912Sartem * libhal_manager_find_device_string_match: 26952912Sartem * @ctx: the context for the connection to hald 26962912Sartem * @key: name of the property 26972912Sartem * @value: the value to match 26982912Sartem * @num_devices: pointer to store number of devices 26992912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 27002912Sartem * 27012912Sartem * Find a device in the GDL where a single string property matches a 27022912Sartem * given value. 27032912Sartem * 27042912Sartem * Returns: UDI of devices; free with libhal_free_string_array() 27052912Sartem */ 27062912Sartem char ** 27072912Sartem libhal_manager_find_device_string_match (LibHalContext *ctx, 27082912Sartem const char *key, 27092912Sartem const char *value, int *num_devices, DBusError *error) 27102912Sartem { 27112912Sartem DBusMessage *message; 27122912Sartem DBusMessage *reply; 27132912Sartem DBusMessageIter iter, iter_array, reply_iter; 27142912Sartem char **hal_device_names; 27152912Sartem DBusError _error; 27162912Sartem 27172912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL); 27182912Sartem 27192912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", 27202912Sartem "/org/freedesktop/Hal/Manager", 27212912Sartem "org.freedesktop.Hal.Manager", 27222912Sartem "FindDeviceStringMatch"); 27232912Sartem if (message == NULL) { 27242912Sartem fprintf (stderr, 27252912Sartem "%s %d : Couldn't allocate D-BUS message\n", 27262912Sartem __FILE__, __LINE__); 27272912Sartem return NULL; 27282912Sartem } 27292912Sartem 27302912Sartem dbus_message_iter_init_append (message, &iter); 27312912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key); 27322912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value); 27332912Sartem 27342912Sartem dbus_error_init (&_error); 27352912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 27362912Sartem message, -1, 27372912Sartem &_error); 27382912Sartem 27392912Sartem dbus_move_error (&_error, error); 27402912Sartem if (error != NULL && dbus_error_is_set (error)) { 27412912Sartem dbus_message_unref (message); 27422912Sartem return NULL; 27432912Sartem } 27442912Sartem if (reply == NULL) { 27452912Sartem dbus_message_unref (message); 27462912Sartem return NULL; 27472912Sartem } 27482912Sartem /* now analyse reply */ 27492912Sartem dbus_message_iter_init (reply, &reply_iter); 27502912Sartem 27512912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) { 27522912Sartem fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__); 27532912Sartem return NULL; 27542912Sartem } 27552912Sartem 27562912Sartem dbus_message_iter_recurse (&reply_iter, &iter_array); 27572912Sartem 27582912Sartem hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices); 27592912Sartem 27602912Sartem dbus_message_unref (reply); 27612912Sartem dbus_message_unref (message); 27622912Sartem 27632912Sartem return hal_device_names; 27642912Sartem } 27652912Sartem 27662912Sartem 27672912Sartem /** 27682912Sartem * libhal_device_add_capability: 27692912Sartem * @ctx: the context for the connection to hald 27702912Sartem * @udi: the Unique Device Id 27712912Sartem * @capability: the capability name to add 27722912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 27732912Sartem * 27742912Sartem * Assign a capability to a device. 27752912Sartem * 27762912Sartem * Returns: TRUE if the capability was added, FALSE if the device didn't exist 27772912Sartem */ 27782912Sartem dbus_bool_t 27792912Sartem libhal_device_add_capability (LibHalContext *ctx, 27802912Sartem const char *udi, const char *capability, DBusError *error) 27812912Sartem { 27822912Sartem DBusMessage *message; 27832912Sartem DBusMessage *reply; 27842912Sartem DBusMessageIter iter; 27852912Sartem 27862912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 27872912Sartem 27882912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", udi, 27892912Sartem "org.freedesktop.Hal.Device", 27902912Sartem "AddCapability"); 27912912Sartem if (message == NULL) { 27922912Sartem fprintf (stderr, 27932912Sartem "%s %d : Couldn't allocate D-BUS message\n", 27942912Sartem __FILE__, __LINE__); 27952912Sartem return FALSE; 27962912Sartem } 27972912Sartem 27982912Sartem dbus_message_iter_init_append (message, &iter); 27992912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability); 28002912Sartem 28012912Sartem 28022912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 28032912Sartem message, -1, 28042912Sartem error); 2805*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 28062912Sartem dbus_message_unref (message); 28072912Sartem return FALSE; 28082912Sartem } 28092912Sartem 28102912Sartem if (reply == NULL) { 28112912Sartem dbus_message_unref (message); 28122912Sartem return FALSE; 28132912Sartem } 28142912Sartem 28152912Sartem dbus_message_unref (reply); 28162912Sartem dbus_message_unref (message); 28172912Sartem return TRUE; 28182912Sartem } 28192912Sartem 28202912Sartem /** 28212912Sartem * libhal_device_query_capability: 28222912Sartem * @ctx: the context for the connection to hald 28232912Sartem * @udi: the Unique Device Id 28242912Sartem * @capability: the capability name 28252912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 28262912Sartem * 28272912Sartem * Check if a device has a capability. The result is undefined if the 28282912Sartem * device doesn't exist. 28292912Sartem * 28302912Sartem * Returns: TRUE if the device has the capability, otherwise FALSE 28312912Sartem */ 28322912Sartem dbus_bool_t 28332912Sartem libhal_device_query_capability (LibHalContext *ctx, const char *udi, const char *capability, DBusError *error) 28342912Sartem { 28352912Sartem char **caps; 28362912Sartem unsigned int i; 28372912Sartem dbus_bool_t ret; 28382912Sartem 28392912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 28402912Sartem 28412912Sartem ret = FALSE; 28422912Sartem 28432912Sartem caps = libhal_device_get_property_strlist (ctx, udi, "info.capabilities", error); 28442912Sartem if (caps != NULL) { 28452912Sartem for (i = 0; caps[i] != NULL; i++) { 28462912Sartem if (strcmp (caps[i], capability) == 0) { 28472912Sartem ret = TRUE; 28482912Sartem break; 28492912Sartem } 28502912Sartem } 28512912Sartem libhal_free_string_array (caps); 28522912Sartem } 28532912Sartem 28542912Sartem return ret; 28552912Sartem } 28562912Sartem 28572912Sartem /** 28582912Sartem * libhal_find_device_by_capability: 28592912Sartem * @ctx: the context for the connection to hald 28602912Sartem * @capability: the capability name 28612912Sartem * @num_devices: pointer to store number of devices 28622912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 28632912Sartem * 28642912Sartem * Find devices with a given capability. 28652912Sartem * 28662912Sartem * Returns: UDI of devices; free with libhal_free_string_array() 28672912Sartem */ 28682912Sartem char ** 28692912Sartem libhal_find_device_by_capability (LibHalContext *ctx, 28702912Sartem const char *capability, int *num_devices, DBusError *error) 28712912Sartem { 28722912Sartem DBusMessage *message; 28732912Sartem DBusMessage *reply; 28742912Sartem DBusMessageIter iter, iter_array, reply_iter; 28752912Sartem char **hal_device_names; 28762912Sartem DBusError _error; 28772912Sartem 28782912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL); 28792912Sartem 28802912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", 28812912Sartem "/org/freedesktop/Hal/Manager", 28822912Sartem "org.freedesktop.Hal.Manager", 28832912Sartem "FindDeviceByCapability"); 28842912Sartem if (message == NULL) { 28852912Sartem fprintf (stderr, 28862912Sartem "%s %d : Couldn't allocate D-BUS message\n", 28872912Sartem __FILE__, __LINE__); 28882912Sartem return NULL; 28892912Sartem } 28902912Sartem 28912912Sartem dbus_message_iter_init_append (message, &iter); 28922912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability); 28932912Sartem 28942912Sartem dbus_error_init (&_error); 28952912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 28962912Sartem message, -1, 28972912Sartem &_error); 28982912Sartem 28992912Sartem dbus_move_error (&_error, error); 29002912Sartem if (error != NULL && dbus_error_is_set (error)) { 29012912Sartem dbus_message_unref (message); 29022912Sartem return NULL; 29032912Sartem } 29042912Sartem if (reply == NULL) { 29052912Sartem dbus_message_unref (message); 29062912Sartem return NULL; 29072912Sartem } 29082912Sartem /* now analyse reply */ 29092912Sartem dbus_message_iter_init (reply, &reply_iter); 29102912Sartem 29112912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) { 29122912Sartem fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__); 29132912Sartem return NULL; 29142912Sartem } 29152912Sartem 29162912Sartem dbus_message_iter_recurse (&reply_iter, &iter_array); 29172912Sartem 29182912Sartem hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices); 29192912Sartem 29202912Sartem dbus_message_unref (reply); 29212912Sartem dbus_message_unref (message); 29222912Sartem 29232912Sartem return hal_device_names; 29242912Sartem } 29252912Sartem 29262912Sartem /** 29272912Sartem * libhal_device_property_watch_all: 29282912Sartem * @ctx: the context for the connection to hald 29292912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 29302912Sartem * 29312912Sartem * Watch all devices, ie. the device_property_changed callback is 29322912Sartem * invoked when the properties on any device changes. 29332912Sartem * 29342912Sartem * Returns: TRUE only if the operation succeeded 29352912Sartem */ 29362912Sartem dbus_bool_t 29372912Sartem libhal_device_property_watch_all (LibHalContext *ctx, DBusError *error) 29382912Sartem { 29392912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 29402912Sartem 29412912Sartem dbus_bus_add_match (ctx->connection, 29422912Sartem "type='signal'," 29432912Sartem "interface='org.freedesktop.Hal.Device'," 29442912Sartem "sender='org.freedesktop.Hal'", error); 2945*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 29462912Sartem return FALSE; 29472912Sartem } 29482912Sartem return TRUE; 29492912Sartem } 29502912Sartem 29512912Sartem 29522912Sartem /** 29532912Sartem * libhal_device_add_property_watch: 29542912Sartem * @ctx: the context for the connection to hald 29552912Sartem * @udi: the Unique Device Id 29562912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 29572912Sartem * 29582912Sartem * Add a watch on a device, so the device_property_changed callback is 29592912Sartem * invoked when the properties on the given device changes. 29602912Sartem * 29612912Sartem * The application itself is responsible for deleting the watch, using 29622912Sartem * libhal_device_remove_property_watch, if the device is removed. 29632912Sartem * 29642912Sartem * Returns: TRUE only if the operation succeeded 29652912Sartem */ 29662912Sartem dbus_bool_t 29672912Sartem libhal_device_add_property_watch (LibHalContext *ctx, const char *udi, DBusError *error) 29682912Sartem { 29692912Sartem char buf[512]; 29702912Sartem 29712912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 29722912Sartem 29732912Sartem snprintf (buf, 512, 29742912Sartem "type='signal'," 29752912Sartem "interface='org.freedesktop.Hal.Device'," 29762912Sartem "sender='org.freedesktop.Hal'," "path=%s", udi); 29772912Sartem 29782912Sartem dbus_bus_add_match (ctx->connection, buf, error); 2979*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 29802912Sartem return FALSE; 29812912Sartem } 29822912Sartem return TRUE; 29832912Sartem } 29842912Sartem 29852912Sartem 29862912Sartem /** 29872912Sartem * libhal_device_remove_property_watch: 29882912Sartem * @ctx: the context for the connection to hald 29892912Sartem * @udi: the Unique Device Id 29902912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 29912912Sartem * 29922912Sartem * Remove a watch on a device. 29932912Sartem * 29942912Sartem * Returns: TRUE only if the operation succeeded 29952912Sartem */ 29962912Sartem dbus_bool_t 29972912Sartem libhal_device_remove_property_watch (LibHalContext *ctx, const char *udi, DBusError *error) 29982912Sartem { 29992912Sartem char buf[512]; 30002912Sartem 30012912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 30022912Sartem 30032912Sartem snprintf (buf, 512, 30042912Sartem "type='signal'," 30052912Sartem "interface='org.freedesktop.Hal.Device'," 30062912Sartem "sender='org.freedesktop.Hal'," "path=%s", udi); 30072912Sartem 30082912Sartem dbus_bus_remove_match (ctx->connection, buf, error); 3009*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 30102912Sartem return FALSE; 30112912Sartem } 30122912Sartem return TRUE; 30132912Sartem } 30142912Sartem 30152912Sartem 30162912Sartem /** 30172912Sartem * libhal_ctx_new: 30182912Sartem * 30192912Sartem * Create a new LibHalContext 30202912Sartem * 30212912Sartem * Returns: a new uninitialized LibHalContext object 30222912Sartem */ 30232912Sartem LibHalContext * 30242912Sartem libhal_ctx_new (void) 30252912Sartem { 30262912Sartem LibHalContext *ctx; 30272912Sartem 30282912Sartem if (!libhal_already_initialized_once) { 30292912Sartem bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); 30302912Sartem bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); 30312912Sartem 30322912Sartem libhal_already_initialized_once = TRUE; 30332912Sartem } 30342912Sartem 30352912Sartem ctx = calloc (1, sizeof (LibHalContext)); 30362912Sartem if (ctx == NULL) { 30372912Sartem fprintf (stderr, 30382912Sartem "%s %d : Failed to allocate %d bytes\n", 30392912Sartem __FILE__, __LINE__, sizeof (LibHalContext)); 30402912Sartem return NULL; 30412912Sartem } 30422912Sartem 30432912Sartem ctx->is_initialized = FALSE; 30442912Sartem ctx->is_shutdown = FALSE; 30452912Sartem ctx->connection = NULL; 30462912Sartem ctx->is_direct = FALSE; 30472912Sartem 30482912Sartem return ctx; 30492912Sartem } 30502912Sartem 30512912Sartem /** 30522912Sartem * libhal_ctx_set_cache: 30532912Sartem * @ctx: context to enable/disable cache for 30542912Sartem * @use_cache: whether or not to use cache 30552912Sartem * 30562912Sartem * Enable or disable caching. Note: Caching is not actually 30572912Sartem * implemented yet. 30582912Sartem * 30592912Sartem * Returns: TRUE if cache was successfully enabled/disabled, FALSE otherwise 30602912Sartem */ 30612912Sartem dbus_bool_t 30622912Sartem libhal_ctx_set_cache (LibHalContext *ctx, dbus_bool_t use_cache) 30632912Sartem { 30642912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 30652912Sartem 30662912Sartem ctx->cache_enabled = use_cache; 30672912Sartem return TRUE; 30682912Sartem } 30692912Sartem 30702912Sartem /** 30712912Sartem * libhal_ctx_set_dbus_connection: 30722912Sartem * @ctx: context to set connection for 30732912Sartem * @conn: DBus connection to use 30742912Sartem * 30752912Sartem * Set DBus connection to use to talk to hald. 30762912Sartem * 30772912Sartem * Returns: TRUE if connection was successfully set, FALSE otherwise 30782912Sartem */ 30792912Sartem dbus_bool_t 30802912Sartem libhal_ctx_set_dbus_connection (LibHalContext *ctx, DBusConnection *conn) 30812912Sartem { 30822912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 30832912Sartem 30842912Sartem if (conn == NULL) 30852912Sartem return FALSE; 30862912Sartem 30872912Sartem ctx->connection = conn; 30882912Sartem return TRUE; 30892912Sartem } 30902912Sartem 30912912Sartem /** 30922912Sartem * libhal_ctx_get_dbus_connection: 30932912Sartem * @ctx: context to get connection for 30942912Sartem * 30952912Sartem * Get DBus connection used for talking to hald. 30962912Sartem * 30972912Sartem * Returns: DBus connection to use or NULL 30982912Sartem */ 30992912Sartem DBusConnection * 31002912Sartem libhal_ctx_get_dbus_connection (LibHalContext *ctx) 31012912Sartem { 31022912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 31032912Sartem 31042912Sartem return ctx->connection; 31052912Sartem } 31062912Sartem 31072912Sartem 31082912Sartem /** 31092912Sartem * libhal_ctx_init: 31102912Sartem * @ctx: Context for connection to hald (D-BUS connection should be set with libhal_ctx_set_dbus_connection) 31112912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 31122912Sartem * 31132912Sartem * Initialize the connection to hald. 31142912Sartem * 31152912Sartem * Returns: TRUE if initialization succeeds, FALSE otherwise 31162912Sartem */ 31172912Sartem dbus_bool_t 31182912Sartem libhal_ctx_init (LibHalContext *ctx, DBusError *error) 31192912Sartem { 31202912Sartem DBusError _error; 31212912Sartem dbus_bool_t hald_exists; 31222912Sartem 31232912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 31242912Sartem 31252912Sartem if (ctx->connection == NULL) 31262912Sartem return FALSE; 31272912Sartem 31282912Sartem dbus_error_init (&_error); 31292912Sartem hald_exists = dbus_bus_name_has_owner (ctx->connection, "org.freedesktop.Hal", &_error); 31302912Sartem dbus_move_error (&_error, error); 31312912Sartem if (error != NULL && dbus_error_is_set (error)) { 31322912Sartem return FALSE; 31332912Sartem } 31342912Sartem 31352912Sartem if (!hald_exists) { 31362912Sartem return FALSE; 31372912Sartem } 31382912Sartem 31392912Sartem 31402912Sartem if (!dbus_connection_add_filter (ctx->connection, filter_func, ctx, NULL)) { 31412912Sartem return FALSE; 31422912Sartem } 31432912Sartem 31442912Sartem dbus_bus_add_match (ctx->connection, 31452912Sartem "type='signal'," 31462912Sartem "interface='org.freedesktop.Hal.Manager'," 31472912Sartem "sender='org.freedesktop.Hal'," 31482912Sartem "path='/org/freedesktop/Hal/Manager'", &_error); 31492912Sartem dbus_move_error (&_error, error); 31502912Sartem if (error != NULL && dbus_error_is_set (error)) { 31512912Sartem return FALSE; 31522912Sartem } 31532912Sartem ctx->is_initialized = TRUE; 31542912Sartem ctx->is_direct = FALSE; 31552912Sartem 31562912Sartem return TRUE; 31572912Sartem } 31582912Sartem 31592912Sartem /** 31602912Sartem * libhal_ctx_init_direct: 31612912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 31622912Sartem * 31632912Sartem * Create an already initialized connection to hald. This function should only be used by HAL helpers. 31642912Sartem * 31652912Sartem * Returns: A pointer to an already initialized LibHalContext 31662912Sartem */ 31672912Sartem LibHalContext * 31682912Sartem libhal_ctx_init_direct (DBusError *error) 31692912Sartem { 31702912Sartem char *hald_addr; 31712912Sartem LibHalContext *ctx; 31722912Sartem DBusError _error; 31732912Sartem 31742912Sartem ctx = libhal_ctx_new (); 31752912Sartem if (ctx == NULL) 31762912Sartem goto out; 31772912Sartem 31782912Sartem if (((hald_addr = getenv ("HALD_DIRECT_ADDR"))) == NULL) { 31792912Sartem libhal_ctx_free (ctx); 31802912Sartem ctx = NULL; 31812912Sartem goto out; 31822912Sartem } 31832912Sartem 31842912Sartem dbus_error_init (&_error); 31852912Sartem ctx->connection = dbus_connection_open (hald_addr, &_error); 31862912Sartem dbus_move_error (&_error, error); 31872912Sartem if (error != NULL && dbus_error_is_set (error)) { 31882912Sartem libhal_ctx_free (ctx); 31892912Sartem ctx = NULL; 31902912Sartem goto out; 31912912Sartem } 31922912Sartem 31932912Sartem ctx->is_initialized = TRUE; 31942912Sartem ctx->is_direct = TRUE; 31952912Sartem 31962912Sartem out: 31972912Sartem return ctx; 31982912Sartem } 31992912Sartem 32002912Sartem /** 32012912Sartem * libhal_ctx_shutdown: 32022912Sartem * @ctx: the context for the connection to hald 32032912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 32042912Sartem * 32052912Sartem * Shut down a connection to hald. 32062912Sartem * 32072912Sartem * Returns: TRUE if connection successfully shut down, FALSE otherwise 32082912Sartem */ 32092912Sartem dbus_bool_t 32102912Sartem libhal_ctx_shutdown (LibHalContext *ctx, DBusError *error) 32112912Sartem { 32122912Sartem DBusError myerror; 32132912Sartem 32142912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 32152912Sartem 32162912Sartem if (ctx->is_direct) { 32172912Sartem /* for some reason dbus_connection_set_exit_on_disconnect doesn't work yet so don't unref */ 32182912Sartem /*dbus_connection_unref (ctx->connection);*/ 32192912Sartem } else { 32202912Sartem dbus_error_init (&myerror); 32212912Sartem dbus_bus_remove_match (ctx->connection, 32222912Sartem "type='signal'," 32232912Sartem "interface='org.freedesktop.Hal.Manager'," 32242912Sartem "sender='org.freedesktop.Hal'," 32252912Sartem "path='/org/freedesktop/Hal/Manager'", &myerror); 322611283SFei.Feng@Sun.COM dbus_move_error(&myerror, error); 322711283SFei.Feng@Sun.COM if (error != NULL && dbus_error_is_set(error)) { 32282912Sartem fprintf (stderr, "%s %d : Error unsubscribing to signals, error=%s\n", 32292912Sartem __FILE__, __LINE__, error->message); 32302912Sartem /** @todo clean up */ 32312912Sartem } 32322912Sartem 32332912Sartem /* TODO: remove other matches */ 32342912Sartem 32352912Sartem dbus_connection_remove_filter (ctx->connection, filter_func, ctx); 32362912Sartem } 32372912Sartem 32382912Sartem ctx->is_initialized = FALSE; 32392912Sartem 32402912Sartem return TRUE; 32412912Sartem } 32422912Sartem 32432912Sartem /** 32442912Sartem * libhal_ctx_free: 32452912Sartem * @ctx: pointer to a LibHalContext 32462912Sartem * 32472912Sartem * Free a LibHalContext resource. 32482912Sartem * 32492912Sartem * Returns: TRUE 32502912Sartem */ 32512912Sartem dbus_bool_t 32522912Sartem libhal_ctx_free (LibHalContext *ctx) 32532912Sartem { 32542912Sartem free (ctx); 32552912Sartem return TRUE; 32562912Sartem } 32572912Sartem 32582912Sartem /** 32592912Sartem * libhal_ctx_set_device_added: 32602912Sartem * @ctx: the context for the connection to hald 32612912Sartem * @callback: the function to call when a device is added 32622912Sartem * 32632912Sartem * Set the callback for when a device is added 32642912Sartem * 32652912Sartem * Returns: TRUE if callback was successfully set, FALSE otherwise 32662912Sartem */ 32672912Sartem dbus_bool_t 32682912Sartem libhal_ctx_set_device_added (LibHalContext *ctx, LibHalDeviceAdded callback) 32692912Sartem { 32702912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 32712912Sartem 32722912Sartem ctx->device_added = callback; 32732912Sartem return TRUE; 32742912Sartem } 32752912Sartem 32762912Sartem /** 32772912Sartem * libhal_ctx_set_device_removed: 32782912Sartem * @ctx: the context for the connection to hald 32792912Sartem * @callback: the function to call when a device is removed 32802912Sartem * 32812912Sartem * Set the callback for when a device is removed. 32822912Sartem * 32832912Sartem * Returns: TRUE if callback was successfully set, FALSE otherwise 32842912Sartem */ 32852912Sartem dbus_bool_t 32862912Sartem libhal_ctx_set_device_removed (LibHalContext *ctx, LibHalDeviceRemoved callback) 32872912Sartem { 32882912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 32892912Sartem 32902912Sartem ctx->device_removed = callback; 32912912Sartem return TRUE; 32922912Sartem } 32932912Sartem 32942912Sartem /** 32952912Sartem * libhal_ctx_set_device_new_capability: 32962912Sartem * @ctx: the context for the connection to hald 32972912Sartem * @callback: the function to call when a device gains a new capability 32982912Sartem * 32992912Sartem * Set the callback for when a device gains a new capability. 33002912Sartem * 33012912Sartem * Returns: TRUE if callback was successfully set, FALSE otherwise 33022912Sartem */ 33032912Sartem dbus_bool_t 33042912Sartem libhal_ctx_set_device_new_capability (LibHalContext *ctx, LibHalDeviceNewCapability callback) 33052912Sartem { 33062912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 33072912Sartem 33082912Sartem ctx->device_new_capability = callback; 33092912Sartem return TRUE; 33102912Sartem } 33112912Sartem 33122912Sartem /** 33132912Sartem * libhal_ctx_set_device_lost_capability: 33142912Sartem * @ctx: the context for the connection to hald 33152912Sartem * @callback: the function to call when a device loses a capability 33162912Sartem * 33172912Sartem * Set the callback for when a device loses a capability 33182912Sartem * 33192912Sartem * Returns: TRUE if callback was successfully set, FALSE otherwise 33202912Sartem */ 33212912Sartem dbus_bool_t 33222912Sartem libhal_ctx_set_device_lost_capability (LibHalContext *ctx, LibHalDeviceLostCapability callback) 33232912Sartem { 33242912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 33252912Sartem 33262912Sartem ctx->device_lost_capability = callback; 33272912Sartem return TRUE; 33282912Sartem } 33292912Sartem 33302912Sartem /** 33312912Sartem * libhal_ctx_set_device_property_modified: 33322912Sartem * @ctx: the context for the connection to hald 33332912Sartem * @callback: the function to call when a property is modified on a device 33342912Sartem * 33352912Sartem * Set the callback for when a property is modified on a device. 33362912Sartem * 33372912Sartem * Returns: TRUE if callback was successfully set, FALSE otherwise 33382912Sartem */ 33392912Sartem dbus_bool_t 33402912Sartem libhal_ctx_set_device_property_modified (LibHalContext *ctx, LibHalDevicePropertyModified callback) 33412912Sartem { 33422912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 33432912Sartem 33442912Sartem ctx->device_property_modified = callback; 33452912Sartem return TRUE; 33462912Sartem } 33472912Sartem 33482912Sartem /** 33492912Sartem * libhal_ctx_set_device_condition: 33502912Sartem * @ctx: the context for the connection to hald 33512912Sartem * @callback: the function to call when a device emits a condition 33522912Sartem * 33532912Sartem * Set the callback for when a device emits a condition 33542912Sartem * 33552912Sartem * Returns: TRUE if callback was successfully set, FALSE otherwise 33562912Sartem */ 33572912Sartem dbus_bool_t 33582912Sartem libhal_ctx_set_device_condition (LibHalContext *ctx, LibHalDeviceCondition callback) 33592912Sartem { 33602912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 33612912Sartem 33622912Sartem ctx->device_condition = callback; 33632912Sartem return TRUE; 33642912Sartem } 33652912Sartem 33662912Sartem /** 33672912Sartem * libhal_string_array_length: 33682912Sartem * @str_array: array of strings to consider 33692912Sartem * 33702912Sartem * Get the length of an array of strings. 33712912Sartem * 33722912Sartem * Returns: Number of strings in array 33732912Sartem */ 33742912Sartem unsigned int 33752912Sartem libhal_string_array_length (char **str_array) 33762912Sartem { 33772912Sartem unsigned int i; 33782912Sartem 33792912Sartem if (str_array == NULL) 33802912Sartem return 0; 33812912Sartem 33822912Sartem for (i = 0; str_array[i] != NULL; i++) 33832912Sartem ; 33842912Sartem 33852912Sartem return i; 33862912Sartem } 33872912Sartem 33882912Sartem 33892912Sartem /** 33902912Sartem * libhal_device_rescan: 33912912Sartem * @ctx: the context for the connection to hald 33922912Sartem * @udi: the Unique id of device 33932912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 33942912Sartem * 33952912Sartem * TODO document me. 33962912Sartem * 33972912Sartem * Returns: Whether the operation succeeded 33982912Sartem */ 33992912Sartem dbus_bool_t 34002912Sartem libhal_device_rescan (LibHalContext *ctx, const char *udi, DBusError *error) 34012912Sartem { 34022912Sartem DBusMessage *message; 34032912Sartem DBusMessageIter reply_iter; 34042912Sartem DBusMessage *reply; 34052912Sartem dbus_bool_t result; 34062912Sartem 34072912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 34082912Sartem 34092912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", udi, 34102912Sartem "org.freedesktop.Hal.Device", 34112912Sartem "Rescan"); 34122912Sartem 34132912Sartem if (message == NULL) { 34142912Sartem fprintf (stderr, 34152912Sartem "%s %d : Couldn't allocate D-BUS message\n", 34162912Sartem __FILE__, __LINE__); 34172912Sartem return FALSE; 34182912Sartem } 34192912Sartem 34202912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 34212912Sartem message, -1, 34222912Sartem error); 34232912Sartem 3424*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 34252912Sartem dbus_message_unref (message); 34262912Sartem return FALSE; 34272912Sartem } 34282912Sartem 34292912Sartem dbus_message_unref (message); 34302912Sartem 34312912Sartem if (reply == NULL) 34322912Sartem return FALSE; 34332912Sartem 34342912Sartem dbus_message_iter_init (reply, &reply_iter); 34352912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != 34362912Sartem DBUS_TYPE_BOOLEAN) { 34372912Sartem dbus_message_unref (message); 34382912Sartem dbus_message_unref (reply); 34392912Sartem return FALSE; 34402912Sartem } 34412912Sartem dbus_message_iter_get_basic (&reply_iter, &result); 34422912Sartem 34432912Sartem dbus_message_unref (reply); 34442912Sartem 34452912Sartem return result; 34462912Sartem } 34472912Sartem 34482912Sartem /** 34492912Sartem * libhal_device_reprobe: 34502912Sartem * @ctx: the context for the connection to hald 34512912Sartem * @udi: the Unique id of device 34522912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 34532912Sartem * 34542912Sartem * TODO document me. 34552912Sartem * 34562912Sartem * Returns: Whether the operation succeeded 34572912Sartem */ 34582912Sartem dbus_bool_t 34592912Sartem libhal_device_reprobe (LibHalContext *ctx, const char *udi, DBusError *error) 34602912Sartem { 34612912Sartem DBusMessage *message; 34622912Sartem DBusMessageIter reply_iter; 34632912Sartem DBusMessage *reply; 34642912Sartem dbus_bool_t result; 34652912Sartem 34662912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 34672912Sartem 34682912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", 34692912Sartem udi, 34702912Sartem "org.freedesktop.Hal.Device", 34712912Sartem "Reprobe"); 34722912Sartem 34732912Sartem if (message == NULL) { 34742912Sartem fprintf (stderr, 34752912Sartem "%s %d : Couldn't allocate D-BUS message\n", 34762912Sartem __FILE__, __LINE__); 34772912Sartem return FALSE; 34782912Sartem } 34792912Sartem 34802912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 34812912Sartem message, -1, 34822912Sartem error); 34832912Sartem 3484*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 34852912Sartem dbus_message_unref (message); 34862912Sartem return FALSE; 34872912Sartem } 34882912Sartem 34892912Sartem dbus_message_unref (message); 34902912Sartem 34912912Sartem if (reply == NULL) 34922912Sartem return FALSE; 34932912Sartem 34942912Sartem dbus_message_iter_init (reply, &reply_iter); 34952912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != 34962912Sartem DBUS_TYPE_BOOLEAN) { 34972912Sartem dbus_message_unref (message); 34982912Sartem dbus_message_unref (reply); 34992912Sartem return FALSE; 35002912Sartem } 35012912Sartem dbus_message_iter_get_basic (&reply_iter, &result); 35022912Sartem 35032912Sartem dbus_message_unref (reply); 35042912Sartem 35052912Sartem return result; 35062912Sartem } 35072912Sartem 35082912Sartem /** 35092912Sartem * libhal_device_emit_condition: 35102912Sartem * @ctx: the context for the connection to hald 35112912Sartem * @udi: the Unique Device Id 35122912Sartem * @condition_name: user-readable name of condition 35132912Sartem * @condition_details: user-readable details of condition 35142912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 35152912Sartem * 35162912Sartem * Emit a condition from a device. Can only be used from hald helpers. 35172912Sartem * 35182912Sartem * Returns: TRUE if condition successfully emitted, 35192912Sartem * FALSE otherwise 35202912Sartem */ 35212912Sartem dbus_bool_t libhal_device_emit_condition (LibHalContext *ctx, 35222912Sartem const char *udi, 35232912Sartem const char *condition_name, 35242912Sartem const char *condition_details, 35252912Sartem DBusError *error) 35262912Sartem { 35272912Sartem DBusMessage *message; 35282912Sartem DBusMessageIter iter; 35292912Sartem DBusMessageIter reply_iter; 35302912Sartem DBusMessage *reply; 35312912Sartem dbus_bool_t result; 35322912Sartem 35332912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 35342912Sartem 35352912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", 35362912Sartem udi, 35372912Sartem "org.freedesktop.Hal.Device", 35382912Sartem "EmitCondition"); 35392912Sartem 35402912Sartem if (message == NULL) { 35412912Sartem fprintf (stderr, 35422912Sartem "%s %d : Couldn't allocate D-BUS message\n", 35432912Sartem __FILE__, __LINE__); 35442912Sartem return FALSE; 35452912Sartem } 35462912Sartem 35472912Sartem dbus_message_iter_init_append (message, &iter); 35482912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &condition_name); 35492912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &condition_details); 35502912Sartem 35512912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 35522912Sartem message, -1, 35532912Sartem error); 35542912Sartem 3555*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 35562912Sartem dbus_message_unref (message); 35572912Sartem return FALSE; 35582912Sartem } 35592912Sartem 35602912Sartem dbus_message_unref (message); 35612912Sartem 35622912Sartem if (reply == NULL) 35632912Sartem return FALSE; 35642912Sartem 35652912Sartem dbus_message_iter_init (reply, &reply_iter); 35662912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != 35672912Sartem DBUS_TYPE_BOOLEAN) { 35682912Sartem dbus_message_unref (message); 35692912Sartem dbus_message_unref (reply); 35702912Sartem return FALSE; 35712912Sartem } 35722912Sartem dbus_message_iter_get_basic (&reply_iter, &result); 35732912Sartem 35742912Sartem dbus_message_unref (reply); 35752912Sartem 35762912Sartem return result; 35772912Sartem } 35782912Sartem 35792912Sartem /** 35802912Sartem * libhal_device_addon_is_ready: 35812912Sartem * @ctx: the context for the connection to hald 35822912Sartem * @udi: the Unique Device Id 35832912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 35842912Sartem * 35852912Sartem * HAL addon's must call this method when they are done initializing the device object. The HAL 35862912Sartem * daemon will wait for all addon's to call this. 35872912Sartem * 35882912Sartem * Can only be used from hald helpers. 35892912Sartem * 35902912Sartem * Returns: TRUE if the HAL daemon received the message, FALSE otherwise 35912912Sartem */ 35922912Sartem dbus_bool_t 35932912Sartem libhal_device_addon_is_ready (LibHalContext *ctx, const char *udi, DBusError *error) 35942912Sartem { 35952912Sartem DBusMessage *message; 35962912Sartem DBusMessageIter iter; 35972912Sartem DBusMessageIter reply_iter; 35982912Sartem DBusMessage *reply; 35992912Sartem dbus_bool_t result; 36002912Sartem 36012912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 36022912Sartem 36032912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", 36042912Sartem udi, 36052912Sartem "org.freedesktop.Hal.Device", 36062912Sartem "AddonIsReady"); 36072912Sartem 36082912Sartem if (message == NULL) { 36092912Sartem fprintf (stderr, 36102912Sartem "%s %d : Couldn't allocate D-BUS message\n", 36112912Sartem __FILE__, __LINE__); 36122912Sartem return FALSE; 36132912Sartem } 36142912Sartem 36152912Sartem dbus_message_iter_init_append (message, &iter); 36162912Sartem 36172912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 36182912Sartem message, -1, 36192912Sartem error); 36202912Sartem 3621*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 36222912Sartem dbus_message_unref (message); 36232912Sartem return FALSE; 36242912Sartem } 36252912Sartem 36262912Sartem dbus_message_unref (message); 36272912Sartem 36282912Sartem if (reply == NULL) 36292912Sartem return FALSE; 36302912Sartem 36312912Sartem dbus_message_iter_init (reply, &reply_iter); 36322912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) { 36332912Sartem dbus_message_unref (message); 36342912Sartem dbus_message_unref (reply); 36352912Sartem return FALSE; 36362912Sartem } 36372912Sartem dbus_message_iter_get_basic (&reply_iter, &result); 36382912Sartem 36392912Sartem dbus_message_unref (reply); 36402912Sartem return result; 36412912Sartem } 36422912Sartem 36432912Sartem /** 36442912Sartem * libhal_device_claim_interface: 36452912Sartem * @ctx: the context for the connection to hald 36462912Sartem * @udi: the Unique Device Id 36472912Sartem * @interface_name: Name of interface to claim, e.g. org.freedesktop.Hal.Device.FoobarKindOfThing 36482912Sartem * @introspection_xml: Introspection XML containing what would be inside the interface XML tag 36492912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 36502912Sartem * 36512912Sartem * Claim an interface for a device. All messages to this interface 36522912Sartem * will be forwarded to the helper. Can only be used from hald 36532912Sartem * helpers. 36542912Sartem * 36552912Sartem * Returns: TRUE if interface was claimed, FALSE otherwise 36562912Sartem */ 36572912Sartem dbus_bool_t 36582912Sartem libhal_device_claim_interface (LibHalContext *ctx, 36592912Sartem const char *udi, 36602912Sartem const char *interface_name, 36612912Sartem const char *introspection_xml, 36622912Sartem DBusError *error) 36632912Sartem { 36642912Sartem DBusMessage *message; 36652912Sartem DBusMessageIter iter; 36662912Sartem DBusMessageIter reply_iter; 36672912Sartem DBusMessage *reply; 36682912Sartem dbus_bool_t result; 36692912Sartem 36702912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 36712912Sartem 36722912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", 36732912Sartem udi, 36742912Sartem "org.freedesktop.Hal.Device", 36752912Sartem "ClaimInterface"); 36762912Sartem 36772912Sartem if (message == NULL) { 36782912Sartem fprintf (stderr, 36792912Sartem "%s %d : Couldn't allocate D-BUS message\n", 36802912Sartem __FILE__, __LINE__); 36812912Sartem return FALSE; 36822912Sartem } 36832912Sartem 36842912Sartem dbus_message_iter_init_append (message, &iter); 36852912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface_name); 36862912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &introspection_xml); 36872912Sartem 36882912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 36892912Sartem message, -1, 36902912Sartem error); 36912912Sartem 3692*11992SLin.Guo@Sun.COM if (error != NULL && dbus_error_is_set (error)) { 36932912Sartem dbus_message_unref (message); 36942912Sartem return FALSE; 36952912Sartem } 36962912Sartem 36972912Sartem dbus_message_unref (message); 36982912Sartem 36992912Sartem if (reply == NULL) 37002912Sartem return FALSE; 37012912Sartem 37022912Sartem dbus_message_iter_init (reply, &reply_iter); 37032912Sartem if (dbus_message_iter_get_arg_type (&reply_iter) != 37042912Sartem DBUS_TYPE_BOOLEAN) { 37052912Sartem dbus_message_unref (message); 37062912Sartem dbus_message_unref (reply); 37072912Sartem return FALSE; 37082912Sartem } 37092912Sartem dbus_message_iter_get_basic (&reply_iter, &result); 37102912Sartem 37112912Sartem dbus_message_unref (reply); 37122912Sartem 37132912Sartem return result; 37142912Sartem } 37152912Sartem 37162912Sartem 37172912Sartem 37182912Sartem struct LibHalChangeSetElement_s; 37192912Sartem 37202912Sartem typedef struct LibHalChangeSetElement_s LibHalChangeSetElement; 37212912Sartem 37222912Sartem struct LibHalChangeSetElement_s { 37232912Sartem char *key; 37242912Sartem int change_type; 37252912Sartem union { 37262912Sartem char *val_str; 37272912Sartem dbus_int32_t val_int; 37282912Sartem dbus_uint64_t val_uint64; 37292912Sartem double val_double; 37302912Sartem dbus_bool_t val_bool; 37312912Sartem char **val_strlist; 37322912Sartem } value; 37332912Sartem LibHalChangeSetElement *next; 37342912Sartem LibHalChangeSetElement *prev; 37352912Sartem }; 37362912Sartem 37372912Sartem struct LibHalChangeSet_s { 37382912Sartem char *udi; 37392912Sartem LibHalChangeSetElement *head; 37402912Sartem LibHalChangeSetElement *tail; 37412912Sartem }; 37422912Sartem 37432912Sartem /** 37442912Sartem * libhal_device_new_changeset: 37452912Sartem * @udi: unique device identifier 37462912Sartem * 37472912Sartem * Request a new changeset object. Used for changing multiple properties at once. Useful when 37482912Sartem * performance is critical and also for atomically updating several properties. 37492912Sartem * 37502912Sartem * Returns: A new changeset object or NULL on error 37512912Sartem */ 37522912Sartem LibHalChangeSet * 37532912Sartem libhal_device_new_changeset (const char *udi) 37542912Sartem { 37552912Sartem LibHalChangeSet *changeset; 37562912Sartem 37572912Sartem changeset = calloc (1, sizeof (LibHalChangeSet)); 37582912Sartem if (changeset == NULL) 37592912Sartem goto out; 37602912Sartem 37612912Sartem changeset->udi = strdup (udi); 37622912Sartem if (changeset->udi == NULL) { 37632912Sartem free (changeset); 37642912Sartem changeset = NULL; 37652912Sartem goto out; 37662912Sartem } 37672912Sartem 37682912Sartem changeset->head = NULL; 37692912Sartem changeset->tail = NULL; 37702912Sartem 37712912Sartem out: 37722912Sartem return changeset; 37732912Sartem } 37742912Sartem 37752912Sartem static void 37762912Sartem libhal_changeset_append (LibHalChangeSet *changeset, LibHalChangeSetElement *elem) 37772912Sartem { 37782912Sartem if (changeset->head == NULL) { 37792912Sartem changeset->head = elem; 37802912Sartem changeset->tail = elem; 37812912Sartem elem->next = NULL; 37822912Sartem elem->prev = NULL; 37832912Sartem } else { 37842912Sartem elem->prev = changeset->tail; 37852912Sartem elem->next = NULL; 37862912Sartem elem->prev->next = elem; 37872912Sartem changeset->tail = elem; 37882912Sartem } 37892912Sartem } 37902912Sartem 37912912Sartem 37922912Sartem /** 37932912Sartem * libhal_device_set_property_string: 37942912Sartem * @changeset: the changeset 37952912Sartem * @key: key of property 37962912Sartem * @value: the value to set 37972912Sartem * 37982912Sartem * Set a property. 37992912Sartem * 38002912Sartem * Returns: FALSE on OOM 38012912Sartem */ 38022912Sartem dbus_bool_t 38032912Sartem libhal_changeset_set_property_string (LibHalChangeSet *changeset, const char *key, const char *value) 38042912Sartem { 38052912Sartem LibHalChangeSetElement *elem; 38062912Sartem 38072912Sartem elem = calloc (1, sizeof (LibHalChangeSetElement)); 38082912Sartem if (elem == NULL) 38092912Sartem goto out; 38102912Sartem elem->key = strdup (key); 38112912Sartem if (elem->key == NULL) { 38122912Sartem free (elem); 38132912Sartem elem = NULL; 38142912Sartem goto out; 38152912Sartem } 38162912Sartem 38172912Sartem elem->change_type = LIBHAL_PROPERTY_TYPE_STRING; 38182912Sartem elem->value.val_str = strdup (value); 38192912Sartem if (elem->value.val_str == NULL) { 38202912Sartem free (elem->key); 38212912Sartem free (elem); 38222912Sartem elem = NULL; 38232912Sartem goto out; 38242912Sartem } 38252912Sartem 38262912Sartem libhal_changeset_append (changeset, elem); 38272912Sartem out: 38282912Sartem return elem != NULL; 38292912Sartem } 38302912Sartem 38312912Sartem /** 38322912Sartem * libhal_device_set_property_int: 38332912Sartem * @changeset: the changeset 38342912Sartem * @key: key of property 38352912Sartem * @value: the value to set 38362912Sartem * 38372912Sartem * Set a property. 38382912Sartem * 38392912Sartem * Returns: FALSE on OOM 38402912Sartem */ 38412912Sartem dbus_bool_t 38422912Sartem libhal_changeset_set_property_int (LibHalChangeSet *changeset, const char *key, dbus_int32_t value) 38432912Sartem { 38442912Sartem LibHalChangeSetElement *elem; 38452912Sartem 38462912Sartem elem = calloc (1, sizeof (LibHalChangeSetElement)); 38472912Sartem if (elem == NULL) 38482912Sartem goto out; 38492912Sartem elem->key = strdup (key); 38502912Sartem if (elem->key == NULL) { 38512912Sartem free (elem); 38522912Sartem elem = NULL; 38532912Sartem goto out; 38542912Sartem } 38552912Sartem 38562912Sartem elem->change_type = LIBHAL_PROPERTY_TYPE_INT32; 38572912Sartem elem->value.val_int = value; 38582912Sartem 38592912Sartem libhal_changeset_append (changeset, elem); 38602912Sartem out: 38612912Sartem return elem != NULL; 38622912Sartem } 38632912Sartem 38642912Sartem /** 38652912Sartem * libhal_device_set_property_uint64: 38662912Sartem * @changeset: the changeset 38672912Sartem * @key: key of property 38682912Sartem * @value: the value to set 38692912Sartem * 38702912Sartem * Set a property. 38712912Sartem * 38722912Sartem * Returns: FALSE on OOM 38732912Sartem */ 38742912Sartem dbus_bool_t 38752912Sartem libhal_changeset_set_property_uint64 (LibHalChangeSet *changeset, const char *key, dbus_uint64_t value) 38762912Sartem { 38772912Sartem LibHalChangeSetElement *elem; 38782912Sartem 38792912Sartem elem = calloc (1, sizeof (LibHalChangeSetElement)); 38802912Sartem if (elem == NULL) 38812912Sartem goto out; 38822912Sartem elem->key = strdup (key); 38832912Sartem if (elem->key == NULL) { 38842912Sartem free (elem); 38852912Sartem elem = NULL; 38862912Sartem goto out; 38872912Sartem } 38882912Sartem 38892912Sartem elem->change_type = LIBHAL_PROPERTY_TYPE_UINT64; 38902912Sartem elem->value.val_uint64 = value; 38912912Sartem 38922912Sartem libhal_changeset_append (changeset, elem); 38932912Sartem out: 38942912Sartem return elem != NULL; 38952912Sartem } 38962912Sartem 38972912Sartem /** 38982912Sartem * libhal_device_set_property_double: 38992912Sartem * @changeset: the changeset 39002912Sartem * @key: key of property 39012912Sartem * @value: the value to set 39022912Sartem * 39032912Sartem * Set a property. 39042912Sartem * 39052912Sartem * Returns: FALSE on OOM 39062912Sartem */ 39072912Sartem dbus_bool_t 39082912Sartem libhal_changeset_set_property_double (LibHalChangeSet *changeset, const char *key, double value) 39092912Sartem { 39102912Sartem LibHalChangeSetElement *elem; 39112912Sartem 39122912Sartem elem = calloc (1, sizeof (LibHalChangeSetElement)); 39132912Sartem if (elem == NULL) 39142912Sartem goto out; 39152912Sartem elem->key = strdup (key); 39162912Sartem if (elem->key == NULL) { 39172912Sartem free (elem); 39182912Sartem elem = NULL; 39192912Sartem goto out; 39202912Sartem } 39212912Sartem 39222912Sartem elem->change_type = LIBHAL_PROPERTY_TYPE_DOUBLE; 39232912Sartem elem->value.val_double = value; 39242912Sartem 39252912Sartem libhal_changeset_append (changeset, elem); 39262912Sartem out: 39272912Sartem return elem != NULL; 39282912Sartem } 39292912Sartem 39302912Sartem /** 39312912Sartem * libhal_device_set_property_bool: 39322912Sartem * @changeset: the changeset 39332912Sartem * @key: key of property 39342912Sartem * @value: the value to set 39352912Sartem * 39362912Sartem * Set a property. 39372912Sartem * 39382912Sartem * Returns: FALSE on OOM 39392912Sartem */ 39402912Sartem dbus_bool_t 39412912Sartem libhal_changeset_set_property_bool (LibHalChangeSet *changeset, const char *key, dbus_bool_t value) 39422912Sartem { 39432912Sartem LibHalChangeSetElement *elem; 39442912Sartem 39452912Sartem elem = calloc (1, sizeof (LibHalChangeSetElement)); 39462912Sartem if (elem == NULL) 39472912Sartem goto out; 39482912Sartem elem->key = strdup (key); 39492912Sartem if (elem->key == NULL) { 39502912Sartem free (elem); 39512912Sartem elem = NULL; 39522912Sartem goto out; 39532912Sartem } 39542912Sartem 39552912Sartem elem->change_type = LIBHAL_PROPERTY_TYPE_BOOLEAN; 39562912Sartem elem->value.val_bool = value; 39572912Sartem 39582912Sartem libhal_changeset_append (changeset, elem); 39592912Sartem out: 39602912Sartem return elem != NULL; 39612912Sartem } 39622912Sartem 39632912Sartem /** 39642912Sartem * libhal_device_set_property_strlist: 39652912Sartem * @changeset: the changeset 39662912Sartem * @key: key of property 39672912Sartem * @value: the value to set - NULL terminated array of strings 39682912Sartem * 39692912Sartem * Set a property. 39702912Sartem * 39712912Sartem * Returns: FALSE on OOM 39722912Sartem */ 39732912Sartem dbus_bool_t 39742912Sartem libhal_changeset_set_property_strlist (LibHalChangeSet *changeset, const char *key, const char **value) 39752912Sartem { 39762912Sartem LibHalChangeSetElement *elem; 39772912Sartem char **value_copy; 39782912Sartem int len; 39792912Sartem int i, j; 39802912Sartem 39812912Sartem elem = calloc (1, sizeof (LibHalChangeSetElement)); 39822912Sartem if (elem == NULL) 39832912Sartem goto out; 39842912Sartem elem->key = strdup (key); 39852912Sartem if (elem->key == NULL) { 39862912Sartem free (elem); 39872912Sartem elem = NULL; 39882912Sartem goto out; 39892912Sartem } 39902912Sartem 39912912Sartem for (i = 0; value[i] != NULL; i++) 39922912Sartem ; 39932912Sartem len = i; 39942912Sartem 39952912Sartem value_copy = calloc (len + 1, sizeof (char *)); 39962912Sartem if (value_copy == NULL) { 39972912Sartem free (elem->key); 39982912Sartem free (elem); 39992912Sartem elem = NULL; 40002912Sartem goto out; 40012912Sartem } 40022912Sartem 40032912Sartem for (i = 0; i < len; i++) { 40042912Sartem value_copy[i] = strdup (value[i]); 40052912Sartem if (value_copy[i] == NULL) { 40062912Sartem for (j = 0; j < i; j++) { 40072912Sartem free (value_copy[j]); 40082912Sartem } 40092912Sartem free (value_copy); 40102912Sartem free (elem->key); 40112912Sartem free (elem); 40122912Sartem elem = NULL; 40132912Sartem goto out; 40142912Sartem } 40152912Sartem } 40162912Sartem value_copy[i] = NULL; 40172912Sartem 40182912Sartem elem->change_type = LIBHAL_PROPERTY_TYPE_STRLIST; 40192912Sartem elem->value.val_strlist = value_copy; 40202912Sartem 40212912Sartem libhal_changeset_append (changeset, elem); 40222912Sartem out: 40232912Sartem return elem != NULL; 40242912Sartem } 40252912Sartem 40262912Sartem /** 40272912Sartem * libhal_device_commit_changeset: 40282912Sartem * @ctx: the context for the connection to hald 40292912Sartem * @changeset: the changeset to commit 40302912Sartem * @error: pointer to an initialized dbus error object for returning errors or NULL 40312912Sartem * 40322912Sartem * Commit a changeset to the daemon. 40332912Sartem * 40342912Sartem * Returns: True if the changeset was committed on the daemon side 40352912Sartem */ 40362912Sartem dbus_bool_t 40372912Sartem libhal_device_commit_changeset (LibHalContext *ctx, LibHalChangeSet *changeset, DBusError *error) 40382912Sartem { 40392912Sartem LibHalChangeSetElement *elem; 40402912Sartem DBusMessage *message; 40412912Sartem DBusMessage *reply; 40422912Sartem DBusError _error; 40432912Sartem DBusMessageIter iter; 40442912Sartem DBusMessageIter sub; 40452912Sartem DBusMessageIter sub2; 40462912Sartem DBusMessageIter sub3; 40472912Sartem DBusMessageIter sub4; 40482912Sartem int i; 40492912Sartem 40502912Sartem LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE); 40512912Sartem 40522912Sartem if (changeset->head == NULL) { 40532912Sartem return TRUE; 40542912Sartem } 40552912Sartem 40562912Sartem message = dbus_message_new_method_call ("org.freedesktop.Hal", changeset->udi, 40572912Sartem "org.freedesktop.Hal.Device", 40582912Sartem "SetMultipleProperties"); 40592912Sartem 40602912Sartem if (message == NULL) { 40612912Sartem fprintf (stderr, "%s %d : Couldn't allocate D-BUS message\n", __FILE__, __LINE__); 40622912Sartem return FALSE; 40632912Sartem } 40642912Sartem 40652912Sartem dbus_message_iter_init_append (message, &iter); 40662912Sartem 40672912Sartem dbus_message_iter_open_container (&iter, 40682912Sartem DBUS_TYPE_ARRAY, 40692912Sartem DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING 40702912Sartem DBUS_TYPE_STRING_AS_STRING 40712912Sartem DBUS_TYPE_VARIANT_AS_STRING 40722912Sartem DBUS_DICT_ENTRY_END_CHAR_AS_STRING, 40732912Sartem &sub); 40742912Sartem 40752912Sartem for (elem = changeset->head; elem != NULL; elem = elem->next) { 40762912Sartem dbus_message_iter_open_container (&sub, 40772912Sartem DBUS_TYPE_DICT_ENTRY, 40782912Sartem NULL, 40792912Sartem &sub2); 40802912Sartem dbus_message_iter_append_basic (&sub2, DBUS_TYPE_STRING, &(elem->key)); 40812912Sartem 40822912Sartem switch (elem->change_type) { 40832912Sartem case LIBHAL_PROPERTY_TYPE_STRING: 40842912Sartem dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &sub3); 40852912Sartem dbus_message_iter_append_basic (&sub3, DBUS_TYPE_STRING, &(elem->value.val_str)); 40862912Sartem dbus_message_iter_close_container (&sub2, &sub3); 40872912Sartem break; 40882912Sartem case LIBHAL_PROPERTY_TYPE_STRLIST: 40892912Sartem dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, 40902912Sartem DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING, &sub3); 40912912Sartem dbus_message_iter_open_container (&sub3, DBUS_TYPE_ARRAY, 40922912Sartem DBUS_TYPE_STRING_AS_STRING, &sub4); 40932912Sartem for (i = 0; elem->value.val_strlist[i] != NULL; i++) { 40942912Sartem dbus_message_iter_append_basic (&sub4, DBUS_TYPE_STRING, 40952912Sartem &(elem->value.val_strlist[i])); 40962912Sartem } 40972912Sartem dbus_message_iter_close_container (&sub3, &sub4); 40982912Sartem dbus_message_iter_close_container (&sub2, &sub3); 40992912Sartem break; 41002912Sartem case LIBHAL_PROPERTY_TYPE_INT32: 41012912Sartem dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &sub3); 41022912Sartem dbus_message_iter_append_basic (&sub3, DBUS_TYPE_INT32, &(elem->value.val_int)); 41032912Sartem dbus_message_iter_close_container (&sub2, &sub3); 41042912Sartem break; 41052912Sartem case LIBHAL_PROPERTY_TYPE_UINT64: 41062912Sartem dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_UINT64_AS_STRING, &sub3); 41072912Sartem dbus_message_iter_append_basic (&sub3, DBUS_TYPE_UINT64, &(elem->value.val_uint64)); 41082912Sartem dbus_message_iter_close_container (&sub2, &sub3); 41092912Sartem break; 41102912Sartem case LIBHAL_PROPERTY_TYPE_DOUBLE: 41112912Sartem dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_DOUBLE_AS_STRING, &sub3); 41122912Sartem dbus_message_iter_append_basic (&sub3, DBUS_TYPE_DOUBLE, &(elem->value.val_double)); 41132912Sartem dbus_message_iter_close_container (&sub2, &sub3); 41142912Sartem break; 41152912Sartem case LIBHAL_PROPERTY_TYPE_BOOLEAN: 41162912Sartem dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_BOOLEAN_AS_STRING,&sub3); 41172912Sartem dbus_message_iter_append_basic (&sub3, DBUS_TYPE_BOOLEAN, &(elem->value.val_bool)); 41182912Sartem dbus_message_iter_close_container (&sub2, &sub3); 41192912Sartem break; 41202912Sartem default: 41212912Sartem fprintf (stderr, "%s %d : unknown change_type %d\n", __FILE__, __LINE__, elem->change_type); 41222912Sartem break; 41232912Sartem } 41242912Sartem dbus_message_iter_close_container (&sub, &sub2); 41252912Sartem } 41262912Sartem 41272912Sartem dbus_message_iter_close_container (&iter, &sub); 41282912Sartem 41292912Sartem 41302912Sartem dbus_error_init (&_error); 41312912Sartem reply = dbus_connection_send_with_reply_and_block (ctx->connection, 41322912Sartem message, -1, 41332912Sartem &_error); 41342912Sartem 41352912Sartem dbus_move_error (&_error, error); 41362912Sartem if (error != NULL && dbus_error_is_set (error)) { 41372912Sartem fprintf (stderr, 41382912Sartem "%s %d : %s\n", 41392912Sartem __FILE__, __LINE__, error->message); 41402912Sartem 41412912Sartem dbus_message_unref (message); 41422912Sartem return FALSE; 41432912Sartem } 41442912Sartem 41452912Sartem if (reply == NULL) { 41462912Sartem dbus_message_unref (message); 41472912Sartem return FALSE; 41482912Sartem } 41492912Sartem 41502912Sartem return TRUE; 41512912Sartem } 41522912Sartem 41532912Sartem /** 41542912Sartem * libhal_device_free_changeset: 41552912Sartem * @changeset: the changeset to free 41562912Sartem * 41572912Sartem * Free a changeset. 41582912Sartem */ 41592912Sartem void 41602912Sartem libhal_device_free_changeset (LibHalChangeSet *changeset) 41612912Sartem { 41622912Sartem LibHalChangeSetElement *elem; 41632912Sartem LibHalChangeSetElement *elem2; 41642912Sartem 41652912Sartem for (elem = changeset->head; elem != NULL; elem = elem2) { 41662912Sartem elem2 = elem->next; 41672912Sartem 41682912Sartem switch (elem->change_type) { 41692912Sartem case LIBHAL_PROPERTY_TYPE_STRING: 41702912Sartem free (elem->value.val_str); 41712912Sartem break; 41722912Sartem case LIBHAL_PROPERTY_TYPE_STRLIST: 41732912Sartem libhal_free_string_array (elem->value.val_strlist); 41742912Sartem break; 41752912Sartem /* explicit fallthrough */ 41762912Sartem case LIBHAL_PROPERTY_TYPE_INT32: 41772912Sartem case LIBHAL_PROPERTY_TYPE_UINT64: 41782912Sartem case LIBHAL_PROPERTY_TYPE_DOUBLE: 41792912Sartem case LIBHAL_PROPERTY_TYPE_BOOLEAN: 41802912Sartem break; 41812912Sartem default: 41822912Sartem fprintf (stderr, "%s %d : unknown change_type %d\n", __FILE__, __LINE__, elem->change_type); 41832912Sartem break; 41842912Sartem } 41852912Sartem free (elem); 41862912Sartem } 41872912Sartem 41882912Sartem free (changeset->udi); 41892912Sartem free (changeset); 41902912Sartem } 4191