|
/***************************************************************************
|
|
* CVSID: $Id$
|
|
*
|
|
* libhal.c : HAL daemon C convenience library
|
|
*
|
|
* Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
|
|
* Copyright (C) 2006 Sjoerd Simons, <sjoerd@luon.net>
|
|
* Copyright (C) 2007 Codethink Ltd. Author Rob Taylor <rob.taylor@codethink.co.uk>
|
|
*
|
|
* Licensed under the Academic Free License version 2.1
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
**************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <dbus/dbus.h>
|
|
|
|
#include "uthash.h"
|
|
#include "libhal.h"
|
|
|
|
#ifdef ENABLE_NLS
|
|
# include <libintl.h>
|
|
# define _(String) dgettext (GETTEXT_PACKAGE, String)
|
|
# ifdef gettext_noop
|
|
# define N_(String) gettext_noop (String)
|
|
# else
|
|
# define N_(String) (String)
|
|
# endif
|
|
#else
|
|
/* Stubs that do something close enough. */
|
|
# define textdomain(String) (String)
|
|
# define gettext(String) (String)
|
|
# define dgettext(Domain,Message) (Message)
|
|
# define dcgettext(Domain,Message,Type) (Message)
|
|
# define bindtextdomain(Domain,Directory) (Domain)
|
|
# define _(String)
|
|
# define N_(String) (String)
|
|
#endif
|
|
|
|
/**
|
|
* LIBHAL_CHECK_PARAM_VALID:
|
|
* @_param_: the prameter to check for
|
|
* @_name_: the name of the prameter (for debug output)
|
|
* @_ret_: what to use for return value if the prameter is NULL
|
|
*
|
|
* Handy macro for checking whether a parameter is valid and not NULL.
|
|
*/
|
|
#define LIBHAL_CHECK_PARAM_VALID(_param_,_name_,_ret_) \
|
|
do { \
|
|
if (_param_ == NULL) { \
|
|
fprintf (stderr, \
|
|
"%s %d : invalid paramater. %s is NULL.\n", \
|
|
__FILE__, __LINE__, _name_); \
|
|
return _ret_; \
|
|
} \
|
|
} while(0)
|
|
|
|
/**
|
|
* LIBHAL_CHECK_UDI_VALID:
|
|
* @_udi_: the UID to check for
|
|
* @_ret_: what to use for return value if udi is invalid
|
|
*
|
|
* Handy macro for checking whether a UID is valid and not NULL.
|
|
*/
|
|
#define LIBHAL_CHECK_UDI_VALID(_udi_,_ret_) \
|
|
do { \
|
|
if (_udi_ == NULL) { \
|
|
fprintf (stderr, \
|
|
"%s %d : invalid udi %s. udi is NULL.\n", \
|
|
__FILE__, __LINE__, _udi_); \
|
|
return _ret_; \
|
|
} else { \
|
|
if(strncmp(_udi_, "/org/freedesktop/Hal/devices/", 29) != 0) { \
|
|
fprintf (stderr, \
|
|
"%s %d : invalid udi: %s doesn't start" \
|
|
"with '/org/freedesktop/Hal/devices/'. \n", \
|
|
__FILE__, __LINE__, _udi_); \
|
|
return _ret_; \
|
|
} \
|
|
} \
|
|
} while(0)
|
|
|
|
static char **libhal_get_string_array_from_iter (DBusMessageIter *iter, int *num_elements);
|
|
|
|
static dbus_bool_t libhal_property_fill_value_from_variant (LibHalProperty *p, DBusMessageIter *var_iter);
|
|
|
|
|
|
/**
|
|
* libhal_free_string_array:
|
|
* @str_array: the array to be freed
|
|
*
|
|
* Frees a NULL-terminated array of strings. If passed NULL, does nothing.
|
|
*/
|
|
void
|
|
libhal_free_string_array (char **str_array)
|
|
{
|
|
if (str_array != NULL) {
|
|
int i;
|
|
|
|
for (i = 0; str_array[i] != NULL; i++) {
|
|
free (str_array[i]);
|
|
str_array[i] = NULL;
|
|
}
|
|
free (str_array);
|
|
str_array = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_get_string_array_from_iter:
|
|
* @iter: the message iterator to extract the strings from
|
|
* @num_elements: pointer to an integer where to store number of elements (can be NULL)
|
|
*
|
|
* Creates a NULL terminated array of strings from a dbus message iterator.
|
|
*
|
|
* Returns: pointer to the string array
|
|
*/
|
|
static char **
|
|
libhal_get_string_array_from_iter (DBusMessageIter *iter, int *num_elements)
|
|
{
|
|
int count;
|
|
char **buffer;
|
|
char **t;
|
|
|
|
count = 0;
|
|
buffer = (char **)malloc (sizeof (char *) * 8);
|
|
|
|
if (buffer == NULL)
|
|
goto oom;
|
|
|
|
buffer[0] = NULL;
|
|
while (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING) {
|
|
const char *value;
|
|
char *str;
|
|
|
|
if ((count % 8) == 0 && count != 0) {
|
|
t = realloc (buffer, sizeof (char *) * (count + 8));
|
|
if (t == NULL)
|
|
goto oom;
|
|
else
|
|
buffer = t;
|
|
}
|
|
|
|
dbus_message_iter_get_basic (iter, &value);
|
|
str = strdup (value);
|
|
if (str == NULL)
|
|
goto oom;
|
|
|
|
buffer[count] = str;
|
|
|
|
dbus_message_iter_next(iter);
|
|
count++;
|
|
}
|
|
|
|
if ((count % 8) == 0) {
|
|
t = realloc (buffer, sizeof (char *) * (count + 1));
|
|
if (t == NULL)
|
|
goto oom;
|
|
else
|
|
buffer = t;
|
|
}
|
|
|
|
buffer[count] = NULL;
|
|
if (num_elements != NULL)
|
|
*num_elements = count;
|
|
return buffer;
|
|
|
|
oom:
|
|
if (buffer != NULL)
|
|
free (buffer);
|
|
fprintf (stderr, "%s %d : error allocating memory\n", __FILE__, __LINE__);
|
|
return NULL;
|
|
|
|
}
|
|
|
|
/**
|
|
* libhal_free_string:
|
|
* @str: the nul-terminated sting to free
|
|
*
|
|
* Used to free strings returned by libhal.
|
|
*/
|
|
void
|
|
libhal_free_string (char *str)
|
|
{
|
|
if (str != NULL) {
|
|
free (str);
|
|
str = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* LibHalPropertySet:
|
|
*
|
|
* Represents a set of properties. Opaque; use the
|
|
* libhal_property_set_*() family of functions to access it.
|
|
*/
|
|
struct LibHalPropertySet_s {
|
|
LibHalProperty *properties;
|
|
};
|
|
|
|
/**
|
|
* LibHalProperty:
|
|
*
|
|
* Represents a property. Opaque.
|
|
*/
|
|
struct LibHalProperty_s {
|
|
LibHalPropertyType type; /**< Type of property */
|
|
char *key; /**< ASCII string */
|
|
|
|
/** Possible values of the property */
|
|
union {
|
|
char *str_value; /**< UTF-8 zero-terminated string */
|
|
dbus_int32_t int_value; /**< 32-bit signed integer */
|
|
dbus_uint64_t uint64_value; /**< 64-bit unsigned integer */
|
|
double double_value; /**< IEEE754 double precision float */
|
|
dbus_bool_t bool_value; /**< Truth value */
|
|
char **strlist_value; /**< List of UTF-8 zero-terminated strings */
|
|
} v;
|
|
|
|
UT_hash_handle hh; /*makes this hashable*/
|
|
};
|
|
|
|
/**
|
|
* LibHalContext:
|
|
*
|
|
* Context for connection to the HAL daemon. Opaque, use the
|
|
* libhal_ctx_*() family of functions to access it.
|
|
*/
|
|
struct LibHalContext_s {
|
|
DBusConnection *connection; /**< D-BUS connection */
|
|
dbus_bool_t is_initialized; /**< Are we initialised */
|
|
dbus_bool_t is_shutdown; /**< Have we been shutdown */
|
|
dbus_bool_t cache_enabled; /**< Is the cache enabled */
|
|
dbus_bool_t is_direct; /**< Whether the connection to hald is direct */
|
|
|
|
/** Device added */
|
|
LibHalDeviceAdded device_added;
|
|
|
|
/** Device removed */
|
|
LibHalDeviceRemoved device_removed;
|
|
|
|
/** Device got a new capability */
|
|
LibHalDeviceNewCapability device_new_capability;
|
|
|
|
/** Device got a new capability */
|
|
LibHalDeviceLostCapability device_lost_capability;
|
|
|
|
/** A property of a device changed */
|
|
LibHalDevicePropertyModified device_property_modified;
|
|
|
|
/** A non-continous event on the device occured */
|
|
LibHalDeviceCondition device_condition;
|
|
|
|
/** A global interface lock is acquired */
|
|
LibHalGlobalInterfaceLockAcquired global_interface_lock_acquired;
|
|
|
|
/** A global interface lock is released */
|
|
LibHalGlobalInterfaceLockReleased global_interface_lock_released;
|
|
|
|
/** An interface lock is acquired */
|
|
LibHalInterfaceLockAcquired interface_lock_acquired;
|
|
|
|
/** An interface lock is released */
|
|
LibHalInterfaceLockReleased interface_lock_released;
|
|
|
|
/** Singleton device added */
|
|
LibHalSingletonDeviceAdded singleton_device_added;
|
|
|
|
/** Singleton device removed*/
|
|
LibHalSingletonDeviceRemoved singleton_device_removed;
|
|
|
|
void *user_data; /**< User data */
|
|
};
|
|
|
|
/**
|
|
* libhal_ctx_set_user_data:
|
|
* @ctx: the context for the connection to hald
|
|
* @user_data: user data
|
|
*
|
|
* Set user data for the context.
|
|
*
|
|
* Returns: TRUE if user data was successfully set, FALSE if otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ctx_set_user_data(LibHalContext *ctx, void *user_data)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
ctx->user_data = user_data;
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_ctx_get_user_data:
|
|
* @ctx: the context for the connection to hald
|
|
*
|
|
* Get user data for the context.
|
|
*
|
|
* Returns: opaque pointer stored through libhal_ctx_set_user_data() or NULL if not set.
|
|
*/
|
|
void*
|
|
libhal_ctx_get_user_data(LibHalContext *ctx)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
|
|
return ctx->user_data;
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_property_fill_value_from_variant:
|
|
* @p: the property to fill in
|
|
* @var_iter: variant iterator to extract the value from
|
|
*
|
|
* Fills in the value for the LibHalProperty given a variant iterator.
|
|
*
|
|
* Returns: Whether the value was put in.
|
|
*/
|
|
static dbus_bool_t
|
|
libhal_property_fill_value_from_variant (LibHalProperty *p, DBusMessageIter *var_iter)
|
|
{
|
|
DBusMessageIter iter_array;
|
|
|
|
LIBHAL_CHECK_PARAM_VALID(p, "LibHalProperty *p", FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(var_iter, "DBusMessageIter *var_iter", FALSE);
|
|
|
|
switch (p->type) {
|
|
case DBUS_TYPE_ARRAY:
|
|
if (dbus_message_iter_get_element_type (var_iter) != DBUS_TYPE_STRING)
|
|
return FALSE;
|
|
|
|
dbus_message_iter_recurse (var_iter, &iter_array);
|
|
p->v.strlist_value = libhal_get_string_array_from_iter (&iter_array, NULL);
|
|
|
|
p->type = LIBHAL_PROPERTY_TYPE_STRLIST;
|
|
|
|
break;
|
|
case DBUS_TYPE_STRING:
|
|
{
|
|
const char *v;
|
|
|
|
dbus_message_iter_get_basic (var_iter, &v);
|
|
|
|
p->v.str_value = strdup (v);
|
|
if (p->v.str_value == NULL)
|
|
return FALSE;
|
|
p->type = LIBHAL_PROPERTY_TYPE_STRING;
|
|
|
|
break;
|
|
}
|
|
case DBUS_TYPE_INT32:
|
|
{
|
|
dbus_int32_t v;
|
|
|
|
dbus_message_iter_get_basic (var_iter, &v);
|
|
|
|
p->v.int_value = v;
|
|
p->type = LIBHAL_PROPERTY_TYPE_INT32;
|
|
|
|
break;
|
|
}
|
|
case DBUS_TYPE_UINT64:
|
|
{
|
|
dbus_uint64_t v;
|
|
|
|
dbus_message_iter_get_basic (var_iter, &v);
|
|
|
|
p->v.uint64_value = v;
|
|
p->type = LIBHAL_PROPERTY_TYPE_UINT64;
|
|
|
|
break;
|
|
}
|
|
case DBUS_TYPE_DOUBLE:
|
|
{
|
|
double v;
|
|
|
|
dbus_message_iter_get_basic (var_iter, &v);
|
|
|
|
p->v.double_value = v;
|
|
p->type = LIBHAL_PROPERTY_TYPE_DOUBLE;
|
|
|
|
break;
|
|
}
|
|
case DBUS_TYPE_BOOLEAN:
|
|
{
|
|
double v;
|
|
|
|
dbus_message_iter_get_basic (var_iter, &v);
|
|
|
|
p->v.double_value = v;
|
|
p->type = LIBHAL_PROPERTY_TYPE_BOOLEAN;
|
|
|
|
break;
|
|
}
|
|
default:
|
|
/** @todo report error */
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static LibHalPropertySet *
|
|
get_property_set (DBusMessageIter *iter)
|
|
{
|
|
LibHalPropertySet *result;
|
|
DBusMessageIter dict_iter;
|
|
|
|
result = malloc (sizeof (LibHalPropertySet));
|
|
if (result == NULL)
|
|
goto oom;
|
|
|
|
/*
|
|
result->properties = malloc(sizeof(LibHalProperty)*result->num_properties);
|
|
if( result->properties==NULL )
|
|
{
|
|
/// @todo cleanup
|
|
return NULL;
|
|
}
|
|
*/
|
|
|
|
result->properties = NULL;
|
|
|
|
if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_ARRAY &&
|
|
dbus_message_iter_get_element_type (iter) != DBUS_TYPE_DICT_ENTRY) {
|
|
fprintf (stderr, "%s %d : error, expecting an array of dict entries\n",
|
|
__FILE__, __LINE__);
|
|
free (result);
|
|
return NULL;
|
|
}
|
|
|
|
dbus_message_iter_recurse (iter, &dict_iter);
|
|
|
|
while (dbus_message_iter_get_arg_type (&dict_iter) == DBUS_TYPE_DICT_ENTRY)
|
|
{
|
|
DBusMessageIter dict_entry_iter, var_iter;
|
|
const char *key;
|
|
LibHalProperty *p;
|
|
|
|
dbus_message_iter_recurse (&dict_iter, &dict_entry_iter);
|
|
|
|
dbus_message_iter_get_basic (&dict_entry_iter, &key);
|
|
|
|
p = malloc (sizeof (LibHalProperty));
|
|
if (p == NULL)
|
|
goto oom;
|
|
|
|
p->key = strdup (key);
|
|
if (p->key == NULL) {
|
|
free (p);
|
|
goto oom;
|
|
}
|
|
|
|
dbus_message_iter_next (&dict_entry_iter);
|
|
|
|
dbus_message_iter_recurse (&dict_entry_iter, &var_iter);
|
|
|
|
p->type = (LibHalPropertyType) dbus_message_iter_get_arg_type (&var_iter);
|
|
|
|
if (!libhal_property_fill_value_from_variant (p, &var_iter)) {
|
|
free (p);
|
|
goto oom;
|
|
}
|
|
|
|
HASH_ADD_KEYPTR (hh, result->properties, p->key, strlen (p->key), p);
|
|
|
|
dbus_message_iter_next (&dict_iter);
|
|
}
|
|
|
|
return result;
|
|
|
|
oom:
|
|
if (result != NULL)
|
|
libhal_free_property_set (result);
|
|
|
|
fprintf (stderr,
|
|
"%s %d : error allocating memory\n",
|
|
__FILE__, __LINE__);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_get_all_properties:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique id of device
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Retrieve all the properties on a device.
|
|
*
|
|
* Returns: An object represent all properties. Must be freed with libhal_free_property_set().
|
|
*/
|
|
LibHalPropertySet *
|
|
libhal_device_get_all_properties (LibHalContext *ctx, const char *udi, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter reply_iter;
|
|
LibHalPropertySet *result;
|
|
DBusError _error;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
|
|
LIBHAL_CHECK_UDI_VALID(udi, NULL);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"GetAllProperties");
|
|
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return NULL;
|
|
}
|
|
|
|
dbus_error_init (&_error);
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
&_error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
fprintf (stderr,
|
|
"%s %d : %s\n",
|
|
__FILE__, __LINE__, error->message);
|
|
return NULL;
|
|
}
|
|
|
|
if (reply == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
|
|
result = get_property_set (&reply_iter);
|
|
|
|
dbus_message_unref (reply);
|
|
|
|
return result;
|
|
}
|
|
|
|
static int
|
|
key_sort (LibHalProperty *a, LibHalProperty *b)
|
|
{
|
|
return strcmp (a->key, b->key);
|
|
}
|
|
|
|
/**
|
|
* libhal_property_set_sort:
|
|
* @set: property-set to sort
|
|
*
|
|
* Sort all properties according to property name.
|
|
*/
|
|
void
|
|
libhal_property_set_sort (LibHalPropertySet *set)
|
|
{
|
|
if (set == NULL)
|
|
return;
|
|
|
|
HASH_SORT (set->properties, key_sort);
|
|
}
|
|
|
|
/**
|
|
* libhal_free_property_set:
|
|
* @set: property-set to free
|
|
*
|
|
* Free a property set earlier obtained with libhal_device_get_all_properties().
|
|
*/
|
|
void
|
|
libhal_free_property_set (LibHalPropertySet * set)
|
|
{
|
|
LibHalProperty *p, *p_old;
|
|
|
|
if (set == NULL)
|
|
return;
|
|
|
|
for (p = set->properties; p != NULL;) {
|
|
HASH_DELETE (hh, set->properties, p);
|
|
free (p->key);
|
|
if (p->type == DBUS_TYPE_STRING)
|
|
free (p->v.str_value);
|
|
if (p->type == LIBHAL_PROPERTY_TYPE_STRLIST)
|
|
libhal_free_string_array (p->v.strlist_value);
|
|
p_old = p;
|
|
p = p->hh.next;
|
|
free (p_old);
|
|
}
|
|
free (set);
|
|
}
|
|
|
|
/**
|
|
* libhal_property_set_get_num_elems:
|
|
* @set: property set to consider
|
|
*
|
|
* Get the number of properties in a property set.
|
|
*
|
|
* Returns: number of properties in given property set
|
|
*/
|
|
unsigned int
|
|
libhal_property_set_get_num_elems (LibHalPropertySet *set)
|
|
{
|
|
unsigned int num_elems;
|
|
LibHalProperty *p;
|
|
|
|
LIBHAL_CHECK_PARAM_VALID(set, "*set", 0);
|
|
|
|
num_elems = 0;
|
|
for (p = set->properties; p != NULL; p = p->hh.next)
|
|
num_elems++;
|
|
|
|
return num_elems;
|
|
}
|
|
|
|
static LibHalProperty *
|
|
property_set_lookup (const LibHalPropertySet *set, const char *key)
|
|
{
|
|
LibHalProperty *p;
|
|
|
|
LIBHAL_CHECK_PARAM_VALID(set, "*set", NULL);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
|
|
|
|
HASH_FIND_STR (set->properties, key, p);
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* libhal_ps_get_type:
|
|
* @set: property set
|
|
* @key: name of property to inspect
|
|
*
|
|
* Get the type of a given property.
|
|
*
|
|
* Returns: the #LibHalPropertyType of the given property,
|
|
* LIBHAL_PROPERTY_TYPE_INVALID if property is not in the set
|
|
*/
|
|
LibHalPropertyType
|
|
libhal_ps_get_type (const LibHalPropertySet *set, const char *key)
|
|
{
|
|
LibHalProperty *p;
|
|
|
|
LIBHAL_CHECK_PARAM_VALID(set, "*set", LIBHAL_PROPERTY_TYPE_INVALID);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", LIBHAL_PROPERTY_TYPE_INVALID);
|
|
|
|
p = property_set_lookup (set, key);
|
|
if (p) return p->type;
|
|
else return LIBHAL_PROPERTY_TYPE_INVALID;
|
|
}
|
|
|
|
/**
|
|
* libhal_ps_get_string:
|
|
* @set: property set
|
|
* @key: name of property to inspect
|
|
*
|
|
* Get the value of a property of type string.
|
|
*
|
|
* Returns: UTF8 nul-terminated string. This pointer is only valid
|
|
* until libhal_free_property_set() is invoked on the property set
|
|
* this property belongs to. NULL if property is not in the set or not a string
|
|
*/
|
|
const char *
|
|
libhal_ps_get_string (const LibHalPropertySet *set, const char *key)
|
|
{
|
|
LibHalProperty *p;
|
|
|
|
LIBHAL_CHECK_PARAM_VALID(set, "*set", NULL);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
|
|
|
|
p = property_set_lookup (set, key);
|
|
if (p && p->type == LIBHAL_PROPERTY_TYPE_STRING)
|
|
return p->v.str_value;
|
|
else return NULL;
|
|
}
|
|
|
|
/**
|
|
* libhal_ps_get_int:
|
|
* @set: property set
|
|
* @key: name of property to inspect
|
|
*
|
|
* Get the value of a property of type signed integer.
|
|
*
|
|
* Returns: property value (32-bit signed integer)
|
|
*/
|
|
dbus_int32_t
|
|
libhal_ps_get_int32 (const LibHalPropertySet *set, const char *key)
|
|
{
|
|
LibHalProperty *p;
|
|
|
|
LIBHAL_CHECK_PARAM_VALID(set, "*set", 0);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", 0);
|
|
|
|
p = property_set_lookup (set, key);
|
|
if (p && p->type == LIBHAL_PROPERTY_TYPE_INT32)
|
|
return p->v.int_value;
|
|
else return 0;
|
|
}
|
|
|
|
/**
|
|
* libhal_ps_get_uint64:
|
|
* @set: property set
|
|
* @key: name of property to inspect
|
|
*
|
|
* Get the value of a property of type unsigned integer.
|
|
*
|
|
* Returns: property value (64-bit unsigned integer)
|
|
*/
|
|
dbus_uint64_t
|
|
libhal_ps_get_uint64 (const LibHalPropertySet *set, const char *key)
|
|
{
|
|
LibHalProperty *p;
|
|
|
|
LIBHAL_CHECK_PARAM_VALID(set, "*set", 0);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", 0);
|
|
|
|
p = property_set_lookup (set, key);
|
|
if (p && p->type == LIBHAL_PROPERTY_TYPE_UINT64)
|
|
return p->v.uint64_value;
|
|
else return 0;
|
|
}
|
|
|
|
/**
|
|
* libhal_ps_get_double:
|
|
* @set: property set
|
|
* @key: name of property to inspect
|
|
*
|
|
* Get the value of a property of type double.
|
|
*
|
|
* Returns: property value (IEEE754 double precision float)
|
|
*/
|
|
double
|
|
libhal_ps_get_double (const LibHalPropertySet *set, const char *key)
|
|
{
|
|
LibHalProperty *p;
|
|
|
|
LIBHAL_CHECK_PARAM_VALID(set, "*set", 0.0);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", 0.0);
|
|
|
|
p = property_set_lookup (set, key);
|
|
if (p && p->type == LIBHAL_PROPERTY_TYPE_DOUBLE)
|
|
return p->v.double_value;
|
|
else return 0.0;
|
|
}
|
|
|
|
/**
|
|
* libhal_ps_get_bool:
|
|
* @set: property set
|
|
* @key: name of property to inspect
|
|
*
|
|
* Get the value of a property of type bool.
|
|
*
|
|
* Returns: property value (bool)
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ps_get_bool (const LibHalPropertySet *set, const char *key)
|
|
{
|
|
LibHalProperty *p;
|
|
|
|
LIBHAL_CHECK_PARAM_VALID(set, "*set", FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
|
|
p = property_set_lookup (set, key);
|
|
if (p && p->type == LIBHAL_PROPERTY_TYPE_BOOLEAN)
|
|
return p->v.bool_value;
|
|
else return FALSE;
|
|
}
|
|
|
|
/**
|
|
* libhal_ps_get_strlist:
|
|
* @set: property set
|
|
* @key: name of property to inspect
|
|
*
|
|
* Get the value of a property of type string list.
|
|
*
|
|
* Returns: pointer to array of strings, this is owned by the property set
|
|
*/
|
|
const char *const *
|
|
libhal_ps_get_strlist (const LibHalPropertySet *set, const char *key)
|
|
{
|
|
LibHalProperty *p;
|
|
|
|
LIBHAL_CHECK_PARAM_VALID(set, "*set", NULL);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
|
|
|
|
p = property_set_lookup (set, key);
|
|
if (p && p->type == LIBHAL_PROPERTY_TYPE_STRLIST)
|
|
return (const char *const *) p->v.strlist_value;
|
|
else return NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_psi_init:
|
|
* @iter: iterator object
|
|
* @set: property set to iterate over
|
|
*
|
|
* Initialize a property set iterator.
|
|
*
|
|
*/
|
|
void
|
|
libhal_psi_init (LibHalPropertySetIterator * iter, LibHalPropertySet * set)
|
|
{
|
|
if (set == NULL)
|
|
return;
|
|
|
|
iter->set = set;
|
|
iter->idx = -1; //deprecated
|
|
iter->cur_prop = set->properties;
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_psi_has_more:
|
|
* @iter: iterator object
|
|
*
|
|
* Determine whether there are more properties to iterate over.
|
|
*
|
|
* Returns: TRUE if there are more properties, FALSE otherwise.
|
|
*/
|
|
dbus_bool_t
|
|
libhal_psi_has_more (LibHalPropertySetIterator * iter)
|
|
{
|
|
return (iter->cur_prop != NULL);
|
|
}
|
|
|
|
/**
|
|
* libhal_psi_next:
|
|
* @iter: iterator object
|
|
*
|
|
* Advance iterator to next property.
|
|
*/
|
|
void
|
|
libhal_psi_next (LibHalPropertySetIterator * iter)
|
|
{
|
|
iter->cur_prop = iter->cur_prop->hh.next;
|
|
}
|
|
|
|
/**
|
|
* libhal_psi_get_type:
|
|
* @iter: iterator object
|
|
*
|
|
* Get type of property.
|
|
*
|
|
* Returns: the property type at the iterator's position
|
|
*/
|
|
LibHalPropertyType
|
|
libhal_psi_get_type (LibHalPropertySetIterator * iter)
|
|
{
|
|
return iter->cur_prop->type;
|
|
}
|
|
|
|
/**
|
|
* libhal_psi_get_key:
|
|
* @iter: iterator object
|
|
*
|
|
* Get the key of a property.
|
|
*
|
|
* Returns: ASCII nul-terminated string. This pointer is only valid
|
|
* until libhal_free_property_set() is invoked on the property set
|
|
* this property belongs to.
|
|
*/
|
|
char *
|
|
libhal_psi_get_key (LibHalPropertySetIterator * iter)
|
|
{
|
|
return iter->cur_prop->key;
|
|
}
|
|
|
|
/**
|
|
* libhal_psi_get_string:
|
|
* @iter: iterator object
|
|
*
|
|
* Get the value of a property of type string.
|
|
*
|
|
* Returns: UTF8 nul-terminated string. This pointer is only valid
|
|
* until libhal_free_property_set() is invoked on the property set
|
|
* this property belongs to.
|
|
*/
|
|
char *
|
|
libhal_psi_get_string (LibHalPropertySetIterator * iter)
|
|
{
|
|
return iter->cur_prop->v.str_value;
|
|
}
|
|
|
|
/**
|
|
* libhal_psi_get_int:
|
|
* @iter: iterator object
|
|
*
|
|
* Get the value of a property of type signed integer.
|
|
*
|
|
* Returns: property value (32-bit signed integer)
|
|
*/
|
|
dbus_int32_t
|
|
libhal_psi_get_int (LibHalPropertySetIterator * iter)
|
|
{
|
|
return iter->cur_prop->v.int_value;
|
|
}
|
|
|
|
/**
|
|
* libhal_psi_get_uint64:
|
|
* @iter: iterator object
|
|
*
|
|
* Get the value of a property of type unsigned integer.
|
|
*
|
|
* Returns: property value (64-bit unsigned integer)
|
|
*/
|
|
dbus_uint64_t
|
|
libhal_psi_get_uint64 (LibHalPropertySetIterator * iter)
|
|
{
|
|
return iter->cur_prop->v.uint64_value;
|
|
}
|
|
|
|
/**
|
|
* libhal_psi_get_double:
|
|
* @iter: iterator object
|
|
*
|
|
* Get the value of a property of type double.
|
|
*
|
|
* Returns: property value (IEEE754 double precision float)
|
|
*/
|
|
double
|
|
libhal_psi_get_double (LibHalPropertySetIterator * iter)
|
|
{
|
|
return iter->cur_prop->v.double_value;
|
|
}
|
|
|
|
/**
|
|
* libhal_psi_get_bool:
|
|
* @iter: iterator object
|
|
*
|
|
* Get the value of a property of type bool.
|
|
*
|
|
* Returns: property value (bool)
|
|
*/
|
|
dbus_bool_t
|
|
libhal_psi_get_bool (LibHalPropertySetIterator * iter)
|
|
{
|
|
return iter->cur_prop->v.bool_value;
|
|
}
|
|
|
|
/**
|
|
* libhal_psi_get_strlist:
|
|
* @iter: iterator object
|
|
*
|
|
* Get the value of a property of type string list.
|
|
*
|
|
* Returns: pointer to array of strings
|
|
*/
|
|
char **
|
|
libhal_psi_get_strlist (LibHalPropertySetIterator * iter)
|
|
{
|
|
return iter->cur_prop->v.strlist_value;
|
|
}
|
|
|
|
static DBusHandlerResult
|
|
singleton_device_changed (LibHalContext *ctx, DBusConnection *connection, DBusMessage *msg, dbus_bool_t added)
|
|
{
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter;
|
|
LibHalPropertySet *set;
|
|
const char *udi;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
|
|
|
|
dbus_message_iter_init (msg, &iter);
|
|
|
|
/* First should be the device UDI */
|
|
if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
|
|
goto malformed;
|
|
|
|
dbus_message_iter_get_basic (&iter, &udi);
|
|
|
|
dbus_message_iter_next (&iter);
|
|
|
|
/* then the property set*/
|
|
set = get_property_set (&iter);
|
|
|
|
if (!set)
|
|
goto malformed;
|
|
if (added)
|
|
(ctx->singleton_device_added)(ctx, udi, set);
|
|
else
|
|
(ctx->singleton_device_removed)(ctx, udi, set);
|
|
|
|
libhal_free_property_set (set);
|
|
|
|
reply = dbus_message_new_method_return (msg);
|
|
if (reply == NULL)
|
|
goto oom;
|
|
|
|
if (!dbus_connection_send (connection, reply, NULL)) {
|
|
dbus_message_unref (reply);
|
|
goto oom;
|
|
}
|
|
|
|
dbus_message_unref (reply);
|
|
|
|
return DBUS_HANDLER_RESULT_HANDLED;
|
|
|
|
malformed:
|
|
fprintf (stderr, "%s %d : singlton device changed message malformed\n", __FILE__, __LINE__);
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
oom:
|
|
fprintf (stderr, "%s %d : error allocating memory\n", __FILE__, __LINE__);
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
}
|
|
|
|
static DBusHandlerResult
|
|
filter_func (DBusConnection * connection,
|
|
DBusMessage * message, void *user_data)
|
|
{
|
|
const char *object_path;
|
|
DBusError error;
|
|
LibHalContext *ctx = (LibHalContext *) user_data;
|
|
|
|
if (ctx->is_shutdown)
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
|
|
dbus_error_init (&error);
|
|
|
|
object_path = dbus_message_get_path (message);
|
|
|
|
/*fprintf (stderr, "*** libhal filer_func: connection=%p obj_path=%s interface=%s method=%s\n",
|
|
connection,
|
|
dbus_message_get_path (message),
|
|
dbus_message_get_interface (message),
|
|
dbus_message_get_member (message));
|
|
*/
|
|
|
|
if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager",
|
|
"DeviceAdded")) {
|
|
char *udi;
|
|
if (dbus_message_get_args (message, &error,
|
|
DBUS_TYPE_STRING, &udi,
|
|
DBUS_TYPE_INVALID)) {
|
|
if (ctx->device_added != NULL) {
|
|
ctx->device_added (ctx, udi);
|
|
}
|
|
} else {
|
|
LIBHAL_FREE_DBUS_ERROR(&error);
|
|
}
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
} else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager", "DeviceRemoved")) {
|
|
char *udi;
|
|
if (dbus_message_get_args (message, &error,
|
|
DBUS_TYPE_STRING, &udi,
|
|
DBUS_TYPE_INVALID)) {
|
|
if (ctx->device_removed != NULL) {
|
|
ctx->device_removed (ctx, udi);
|
|
}
|
|
} else {
|
|
LIBHAL_FREE_DBUS_ERROR(&error);
|
|
}
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
} else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager","NewCapability")) {
|
|
char *udi;
|
|
char *capability;
|
|
if (dbus_message_get_args (message, &error,
|
|
DBUS_TYPE_STRING, &udi,
|
|
DBUS_TYPE_STRING, &capability,
|
|
DBUS_TYPE_INVALID)) {
|
|
if (ctx->device_new_capability != NULL) {
|
|
ctx->device_new_capability (ctx, udi, capability);
|
|
}
|
|
} else {
|
|
LIBHAL_FREE_DBUS_ERROR(&error);
|
|
}
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
} else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager","GlobalInterfaceLockAcquired")) {
|
|
char *lock_name;
|
|
char *lock_owner;
|
|
int num_locks;
|
|
if (dbus_message_get_args (message, &error,
|
|
DBUS_TYPE_STRING, &lock_name,
|
|
DBUS_TYPE_STRING, &lock_owner,
|
|
DBUS_TYPE_INT32, &num_locks,
|
|
DBUS_TYPE_INVALID)) {
|
|
if (ctx->global_interface_lock_acquired != NULL) {
|
|
ctx->global_interface_lock_acquired (ctx, lock_name, lock_owner, num_locks);
|
|
}
|
|
} else {
|
|
LIBHAL_FREE_DBUS_ERROR(&error);
|
|
}
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
} else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager","GlobalInterfaceLockReleased")) {
|
|
char *lock_name;
|
|
char *lock_owner;
|
|
int num_locks;
|
|
if (dbus_message_get_args (message, &error,
|
|
DBUS_TYPE_STRING, &lock_name,
|
|
DBUS_TYPE_STRING, &lock_owner,
|
|
DBUS_TYPE_INT32, &num_locks,
|
|
DBUS_TYPE_INVALID)) {
|
|
if (ctx->global_interface_lock_released != NULL) {
|
|
ctx->global_interface_lock_released (ctx, lock_name, lock_owner, num_locks);
|
|
}
|
|
} else {
|
|
LIBHAL_FREE_DBUS_ERROR(&error);
|
|
}
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
} else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "Condition")) {
|
|
char *condition_name;
|
|
char *condition_detail;
|
|
if (dbus_message_get_args (message, &error,
|
|
DBUS_TYPE_STRING, &condition_name,
|
|
DBUS_TYPE_STRING, &condition_detail,
|
|
DBUS_TYPE_INVALID)) {
|
|
if (ctx->device_condition != NULL) {
|
|
ctx->device_condition (ctx, object_path, condition_name, condition_detail);
|
|
}
|
|
} else {
|
|
LIBHAL_FREE_DBUS_ERROR(&error);
|
|
}
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
} else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device","InterfaceLockAcquired")) {
|
|
char *lock_name;
|
|
char *lock_owner;
|
|
int num_locks;
|
|
if (dbus_message_get_args (message, &error,
|
|
DBUS_TYPE_STRING, &lock_name,
|
|
DBUS_TYPE_STRING, &lock_owner,
|
|
DBUS_TYPE_INT32, &num_locks,
|
|
DBUS_TYPE_INVALID)) {
|
|
if (ctx->interface_lock_acquired != NULL) {
|
|
ctx->interface_lock_acquired (ctx, object_path, lock_name, lock_owner, num_locks);
|
|
}
|
|
} else {
|
|
LIBHAL_FREE_DBUS_ERROR(&error);
|
|
}
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
} else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device","InterfaceLockReleased")) {
|
|
char *lock_name;
|
|
char *lock_owner;
|
|
int num_locks;
|
|
if (dbus_message_get_args (message, &error,
|
|
DBUS_TYPE_STRING, &lock_name,
|
|
DBUS_TYPE_STRING, &lock_owner,
|
|
DBUS_TYPE_INT32, &num_locks,
|
|
DBUS_TYPE_INVALID)) {
|
|
if (ctx->interface_lock_released != NULL) {
|
|
ctx->interface_lock_released (ctx, object_path, lock_name, lock_owner, num_locks);
|
|
}
|
|
} else {
|
|
LIBHAL_FREE_DBUS_ERROR(&error);
|
|
}
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
} else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "PropertyModified")) {
|
|
if (ctx->device_property_modified != NULL) {
|
|
int i;
|
|
char *key;
|
|
dbus_bool_t removed;
|
|
dbus_bool_t added;
|
|
int num_modifications;
|
|
DBusMessageIter iter;
|
|
DBusMessageIter iter_array;
|
|
|
|
dbus_message_iter_init (message, &iter);
|
|
dbus_message_iter_get_basic (&iter, &num_modifications);
|
|
dbus_message_iter_next (&iter);
|
|
|
|
dbus_message_iter_recurse (&iter, &iter_array);
|
|
|
|
for (i = 0; i < num_modifications; i++) {
|
|
DBusMessageIter iter_struct;
|
|
|
|
dbus_message_iter_recurse (&iter_array, &iter_struct);
|
|
|
|
dbus_message_iter_get_basic (&iter_struct, &key);
|
|
dbus_message_iter_next (&iter_struct);
|
|
dbus_message_iter_get_basic (&iter_struct, &removed);
|
|
dbus_message_iter_next (&iter_struct);
|
|
dbus_message_iter_get_basic (&iter_struct, &added);
|
|
|
|
ctx->device_property_modified (ctx,
|
|
object_path,
|
|
key, removed,
|
|
added);
|
|
|
|
dbus_message_iter_next (&iter_array);
|
|
}
|
|
|
|
}
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
} else if (dbus_message_is_method_call (message,
|
|
"org.freedesktop.Hal.SingletonAddon",
|
|
"DeviceAdded") &&
|
|
strcmp (dbus_message_get_path (message),
|
|
"/org/freedesktop/Hal/SingletonAddon") == 0) {
|
|
return singleton_device_changed (ctx, connection, message, TRUE);
|
|
} else if (dbus_message_is_method_call (message,
|
|
"org.freedesktop.Hal.SingletonAddon",
|
|
"DeviceRemoved") &&
|
|
strcmp (dbus_message_get_path (message),
|
|
"/org/freedesktop/Hal/SingletonAddon") == 0) {
|
|
return singleton_device_changed (ctx, connection, message, FALSE);
|
|
}
|
|
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
}
|
|
|
|
/**
|
|
* libhal_get_all_devices:
|
|
* @ctx: the context for the connection to hald
|
|
* @num_devices: the number of devices will be stored here
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Get all devices in the Global Device List (GDL).
|
|
*
|
|
* Returns: An array of device identifiers terminated with NULL. It is
|
|
* the responsibility of the caller to free with
|
|
* libhal_free_string_array(). If an error occurs NULL is returned.
|
|
*/
|
|
char **
|
|
libhal_get_all_devices (LibHalContext *ctx, int *num_devices, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter_array, reply_iter;
|
|
char **hal_device_names;
|
|
DBusError _error;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
|
|
|
|
*num_devices = 0;
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
"/org/freedesktop/Hal/Manager",
|
|
"org.freedesktop.Hal.Manager",
|
|
"GetAllDevices");
|
|
if (message == NULL) {
|
|
fprintf (stderr, "%s %d : Could not allocate D-BUS message\n", __FILE__, __LINE__);
|
|
return NULL;
|
|
}
|
|
|
|
dbus_error_init (&_error);
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection, message, -1, &_error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return NULL;
|
|
}
|
|
if (reply == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
/* now analyze reply */
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
|
|
fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__);
|
|
dbus_message_unref (reply);
|
|
return NULL;
|
|
}
|
|
|
|
dbus_message_iter_recurse (&reply_iter, &iter_array);
|
|
|
|
hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
|
|
|
|
dbus_message_unref (reply);
|
|
return hal_device_names;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_get_property_type:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @key: name of the property
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Query a property type of a device.
|
|
*
|
|
* Returns: A LibHalPropertyType. LIBHAL_PROPERTY_TYPE_INVALID is
|
|
* return if the property doesn't exist.
|
|
*/
|
|
LibHalPropertyType
|
|
libhal_device_get_property_type (LibHalContext *ctx, const char *udi, const char *key, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter, reply_iter;
|
|
LibHalPropertyType type;
|
|
DBusError _error;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, LIBHAL_PROPERTY_TYPE_INVALID); /* or return NULL? */
|
|
LIBHAL_CHECK_UDI_VALID(udi, LIBHAL_PROPERTY_TYPE_INVALID);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", LIBHAL_PROPERTY_TYPE_INVALID);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"GetPropertyType");
|
|
if (message == NULL) {
|
|
fprintf (stderr, "%s %d : Couldn't allocate D-BUS message\n", __FILE__, __LINE__);
|
|
return LIBHAL_PROPERTY_TYPE_INVALID;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
|
|
|
|
dbus_error_init (&_error);
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
&_error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return LIBHAL_PROPERTY_TYPE_INVALID;
|
|
}
|
|
if (reply == NULL) {
|
|
return LIBHAL_PROPERTY_TYPE_INVALID;
|
|
}
|
|
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
dbus_message_iter_get_basic (&reply_iter, &type);
|
|
|
|
dbus_message_unref (reply);
|
|
return type;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_get_property_strlist:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: unique Device Id
|
|
* @key: name of the property
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Get the value of a property of type string list.
|
|
*
|
|
* Returns: Array of pointers to UTF8 nul-terminated strings
|
|
* terminated by NULL. The caller is responsible for freeing this
|
|
* string array with the function libhal_free_string_array(). Returns
|
|
* NULL if the property didn't exist or we are OOM
|
|
*/
|
|
char **
|
|
libhal_device_get_property_strlist (LibHalContext *ctx, const char *udi, const char *key, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter, iter_array, reply_iter;
|
|
char **our_strings;
|
|
DBusError _error;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
|
|
LIBHAL_CHECK_UDI_VALID(udi, NULL);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"GetPropertyStringList");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return NULL;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
|
|
|
|
dbus_error_init (&_error);
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
&_error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return NULL;
|
|
}
|
|
if (reply == NULL) {
|
|
return NULL;
|
|
}
|
|
/* now analyse reply */
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
|
|
fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__);
|
|
dbus_message_unref (reply);
|
|
return NULL;
|
|
}
|
|
|
|
dbus_message_iter_recurse (&reply_iter, &iter_array);
|
|
|
|
our_strings = libhal_get_string_array_from_iter (&iter_array, NULL);
|
|
|
|
dbus_message_unref (reply);
|
|
return our_strings;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_get_property_string:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @key: the name of the property
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Get the value of a property of type string.
|
|
*
|
|
* Returns: UTF8 nul-terminated string. The caller is responsible for
|
|
* freeing this string with the function libhal_free_string(). Returns
|
|
* NULL if the property didn't exist or we are OOM.
|
|
*/
|
|
char *
|
|
libhal_device_get_property_string (LibHalContext *ctx,
|
|
const char *udi, const char *key, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter, reply_iter;
|
|
char *value;
|
|
char *dbus_str;
|
|
DBusError _error;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
|
|
LIBHAL_CHECK_UDI_VALID(udi, NULL);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"GetPropertyString");
|
|
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return NULL;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
|
|
|
|
dbus_error_init (&_error);
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
&_error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return NULL;
|
|
}
|
|
if (reply == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
|
|
/* now analyze reply */
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) !=
|
|
DBUS_TYPE_STRING) {
|
|
dbus_message_unref (reply);
|
|
return NULL;
|
|
}
|
|
|
|
dbus_message_iter_get_basic (&reply_iter, &dbus_str);
|
|
value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
|
|
if (value == NULL) {
|
|
fprintf (stderr, "%s %d : error allocating memory\n",
|
|
__FILE__, __LINE__);
|
|
}
|
|
|
|
dbus_message_unref (reply);
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_get_property_int:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @key: name of the property
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Get the value of a property of type integer.
|
|
*
|
|
* Returns: Property value (32-bit signed integer)
|
|
*/
|
|
dbus_int32_t
|
|
libhal_device_get_property_int (LibHalContext *ctx,
|
|
const char *udi, const char *key, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter, reply_iter;
|
|
dbus_int32_t value;
|
|
DBusError _error;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1);
|
|
LIBHAL_CHECK_UDI_VALID(udi, -1);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", -1);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"GetPropertyInteger");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return -1;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
|
|
|
|
dbus_error_init (&_error);
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
&_error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return -1;
|
|
}
|
|
if (reply == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
|
|
/* now analyze reply */
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) !=
|
|
DBUS_TYPE_INT32) {
|
|
fprintf (stderr,
|
|
"%s %d : property '%s' for device '%s' is not "
|
|
"of type integer\n", __FILE__, __LINE__, key,
|
|
udi);
|
|
dbus_message_unref (reply);
|
|
return -1;
|
|
}
|
|
dbus_message_iter_get_basic (&reply_iter, &value);
|
|
|
|
dbus_message_unref (reply);
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_get_property_uint64:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @key: name of the property
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Get the value of a property of type signed integer.
|
|
*
|
|
* Returns: Property value (64-bit unsigned integer)
|
|
*/
|
|
dbus_uint64_t
|
|
libhal_device_get_property_uint64 (LibHalContext *ctx,
|
|
const char *udi, const char *key, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter, reply_iter;
|
|
dbus_uint64_t value;
|
|
DBusError _error;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1);
|
|
LIBHAL_CHECK_UDI_VALID(udi, -1);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", -1);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"GetPropertyInteger");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return -1;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
|
|
|
|
dbus_error_init (&_error);
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
&_error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return -1;
|
|
}
|
|
if (reply == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
/* now analyze reply */
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) !=
|
|
DBUS_TYPE_UINT64) {
|
|
fprintf (stderr,
|
|
"%s %d : property '%s' for device '%s' is not "
|
|
"of type integer\n", __FILE__, __LINE__, key,
|
|
udi);
|
|
dbus_message_unref (reply);
|
|
return -1;
|
|
}
|
|
dbus_message_iter_get_basic (&reply_iter, &value);
|
|
|
|
dbus_message_unref (reply);
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_get_property_double:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @key: name of the property
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Get the value of a property of type double.
|
|
*
|
|
* Returns: Property value (IEEE754 double precision float)
|
|
*/
|
|
double
|
|
libhal_device_get_property_double (LibHalContext *ctx,
|
|
const char *udi, const char *key, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter, reply_iter;
|
|
double value;
|
|
DBusError _error;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1.0);
|
|
LIBHAL_CHECK_UDI_VALID(udi, -1.0);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", -1.0);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"GetPropertyDouble");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return -1.0f;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
|
|
|
|
dbus_error_init (&_error);
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
&_error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return -1.0f;
|
|
}
|
|
if (reply == NULL) {
|
|
return -1.0f;
|
|
}
|
|
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
|
|
/* now analyze reply */
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) !=
|
|
DBUS_TYPE_DOUBLE) {
|
|
fprintf (stderr,
|
|
"%s %d : property '%s' for device '%s' is not "
|
|
"of type double\n", __FILE__, __LINE__, key, udi);
|
|
dbus_message_unref (reply);
|
|
return -1.0f;
|
|
}
|
|
dbus_message_iter_get_basic (&reply_iter, &value);
|
|
|
|
dbus_message_unref (reply);
|
|
return (double) value;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_get_property_bool:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @key: name of the property
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Get the value of a property of type bool.
|
|
*
|
|
* Returns: Property value (boolean)
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_get_property_bool (LibHalContext *ctx,
|
|
const char *udi, const char *key, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter, reply_iter;
|
|
dbus_bool_t value;
|
|
DBusError _error;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"GetPropertyBoolean");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
|
|
|
|
dbus_error_init (&_error);
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
&_error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
|
|
/* now analyze reply */
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) !=
|
|
DBUS_TYPE_BOOLEAN) {
|
|
fprintf (stderr,
|
|
"%s %d : property '%s' for device '%s' is not "
|
|
"of type bool\n", __FILE__, __LINE__, key, udi);
|
|
dbus_message_unref (reply);
|
|
return FALSE;
|
|
}
|
|
dbus_message_iter_get_basic (&reply_iter, &value);
|
|
|
|
dbus_message_unref (reply);
|
|
return value;
|
|
}
|
|
|
|
|
|
/* generic helper */
|
|
static dbus_bool_t
|
|
libhal_device_set_property_helper (LibHalContext *ctx,
|
|
const char *udi,
|
|
const char *key,
|
|
int type,
|
|
const char *str_value,
|
|
dbus_int32_t int_value,
|
|
dbus_uint64_t uint64_value,
|
|
double double_value,
|
|
dbus_bool_t bool_value,
|
|
DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter;
|
|
char *method_name = NULL;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
|
|
/** @todo sanity check incoming params */
|
|
switch (type) {
|
|
case DBUS_TYPE_INVALID:
|
|
method_name = "RemoveProperty";
|
|
break;
|
|
case DBUS_TYPE_STRING:
|
|
method_name = "SetPropertyString";
|
|
break;
|
|
case DBUS_TYPE_INT32:
|
|
case DBUS_TYPE_UINT64:
|
|
method_name = "SetPropertyInteger";
|
|
break;
|
|
case DBUS_TYPE_DOUBLE:
|
|
method_name = "SetPropertyDouble";
|
|
break;
|
|
case DBUS_TYPE_BOOLEAN:
|
|
method_name = "SetPropertyBoolean";
|
|
break;
|
|
|
|
default:
|
|
/* cannot happen; is not callable from outside this file */
|
|
break;
|
|
}
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
|
|
"org.freedesktop.Hal.Device",
|
|
method_name);
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
|
|
switch (type) {
|
|
case DBUS_TYPE_STRING:
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &str_value);
|
|
break;
|
|
case DBUS_TYPE_INT32:
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &int_value);
|
|
break;
|
|
case DBUS_TYPE_UINT64:
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT64, &uint64_value);
|
|
break;
|
|
case DBUS_TYPE_DOUBLE:
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_DOUBLE, &double_value);
|
|
break;
|
|
case DBUS_TYPE_BOOLEAN:
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &bool_value);
|
|
break;
|
|
}
|
|
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_unref (reply);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_set_property_string:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @key: name of the property
|
|
* @value: value of the property; a UTF8 string
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Set a property of type string.
|
|
*
|
|
* Returns: TRUE if the property was set, FALSE if the device didn't
|
|
* exist or the property had a different type.
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_set_property_string (LibHalContext *ctx,
|
|
const char *udi,
|
|
const char *key,
|
|
const char *value,
|
|
DBusError *error)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(value, "*value", FALSE);
|
|
|
|
return libhal_device_set_property_helper (ctx, udi, key,
|
|
DBUS_TYPE_STRING,
|
|
value, 0, 0, 0.0f, FALSE, error);
|
|
}
|
|
|
|
/**
|
|
* libhal_device_set_property_int:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @key: name of the property
|
|
* @value: value of the property
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Set a property of type signed integer.
|
|
*
|
|
* Returns: TRUE if the property was set, FALSE if the device didn't
|
|
* exist or the property had a different type.
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_set_property_int (LibHalContext *ctx, const char *udi,
|
|
const char *key, dbus_int32_t value, DBusError *error)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
|
|
return libhal_device_set_property_helper (ctx, udi, key,
|
|
DBUS_TYPE_INT32,
|
|
NULL, value, 0, 0.0f, FALSE, error);
|
|
}
|
|
|
|
/**
|
|
* libhal_device_set_property_uint64:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @key: name of the property
|
|
* @value: value of the property
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Set a property of type unsigned integer.
|
|
*
|
|
* Returns: TRUE if the property was set, FALSE if the device didn't
|
|
* exist or the property had a different type.
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_set_property_uint64 (LibHalContext *ctx, const char *udi,
|
|
const char *key, dbus_uint64_t value, DBusError *error)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
|
|
return libhal_device_set_property_helper (ctx, udi, key,
|
|
DBUS_TYPE_UINT64,
|
|
NULL, 0, value, 0.0f, FALSE, error);
|
|
}
|
|
|
|
/**
|
|
* libhal_device_set_property_double:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @key: name of the property
|
|
* @value: value of the property
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Set a property of type double.
|
|
*
|
|
* Returns: TRUE if the property was set, FALSE if the device didn't
|
|
* exist or the property had a different type.
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_set_property_double (LibHalContext *ctx, const char *udi,
|
|
const char *key, double value, DBusError *error)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
|
|
return libhal_device_set_property_helper (ctx, udi, key,
|
|
DBUS_TYPE_DOUBLE,
|
|
NULL, 0, 0, value, FALSE, error);
|
|
}
|
|
|
|
/**
|
|
* libhal_device_set_property_bool:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @key: name of the property
|
|
* @value: value of the property
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Set a property of type bool.
|
|
*
|
|
* Returns: TRUE if the property was set, FALSE if the device didn't
|
|
* exist or the property had a different type.
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_set_property_bool (LibHalContext *ctx, const char *udi,
|
|
const char *key, dbus_bool_t value, DBusError *error)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
|
|
return libhal_device_set_property_helper (ctx, udi, key,
|
|
DBUS_TYPE_BOOLEAN,
|
|
NULL, 0, 0, 0.0f, value, error);
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_device_remove_property:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @key: name of the property
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Remove a property.
|
|
*
|
|
* Returns: TRUE if the property was set, FALSE if the device didn't
|
|
* exist
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_remove_property (LibHalContext *ctx,
|
|
const char *udi, const char *key, DBusError *error)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
|
|
return libhal_device_set_property_helper (ctx, udi, key, DBUS_TYPE_INVALID,
|
|
/* DBUS_TYPE_INVALID means remove */
|
|
NULL, 0, 0, 0.0f, FALSE, error);
|
|
}
|
|
|
|
/**
|
|
* libhal_device_property_strlist_append:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @key: name of the property
|
|
* @value: value to append to property
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Append to a property of type strlist.
|
|
*
|
|
* Returns: TRUE if the value was appended, FALSE if the device didn't
|
|
* exist or the property had a different type.
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_property_strlist_append (LibHalContext *ctx,
|
|
const char *udi,
|
|
const char *key,
|
|
const char *value,
|
|
DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(value, "*value", FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"StringListAppend");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_unref (reply);
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_property_strlist_prepend:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @key: name of the property
|
|
* @value: value to prepend to property
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Prepend to a property of type strlist.
|
|
*
|
|
* Returns: TRUE if the value was prepended, FALSE if the device
|
|
* didn't exist or the property had a different type.
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_property_strlist_prepend (LibHalContext *ctx,
|
|
const char *udi,
|
|
const char *key,
|
|
const char *value,
|
|
DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(value, "*value", FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"StringListPrepend");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_unref (reply);
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_property_strlist_remove_index:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @key: name of the property
|
|
* @idx: index of string to remove in the strlist
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Remove a specified string from a property of type strlist.
|
|
*
|
|
* Returns: TRUE if the string was removed, FALSE if the device didn't
|
|
* exist or the property had a different type.
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_property_strlist_remove_index (LibHalContext *ctx,
|
|
const char *udi,
|
|
const char *key,
|
|
unsigned int idx,
|
|
DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"StringListRemoveIndex");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &idx);
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_unref (reply);
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_property_strlist_remove:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @key: name of the property
|
|
* @value: the string to remove
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Remove a specified string from a property of type strlist.
|
|
*
|
|
* Returns: TRUE if the string was removed, FALSE if the device didn't
|
|
* exist or the property had a different type.
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_property_strlist_remove (LibHalContext *ctx,
|
|
const char *udi,
|
|
const char *key,
|
|
const char *value, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(value, "*value", FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"StringListRemove");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_unref (reply);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_device_lock:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @reason_to_lock: a user-presentable reason why the device is locked.
|
|
* @reason_why_locked: a pointer to store the reason why the device cannot be locked on failure, or NULL
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Take an advisory lock on the device.
|
|
*
|
|
* Returns: TRUE if the lock was obtained, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_lock (LibHalContext *ctx,
|
|
const char *udi,
|
|
const char *reason_to_lock,
|
|
char **reason_why_locked, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessageIter iter;
|
|
DBusMessage *reply;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
|
|
if (reason_why_locked != NULL)
|
|
*reason_why_locked = NULL;
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"Lock");
|
|
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &reason_to_lock);
|
|
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
if (strcmp (error->name,
|
|
"org.freedesktop.Hal.DeviceAlreadyLocked") == 0) {
|
|
if (reason_why_locked != NULL) {
|
|
*reason_why_locked =
|
|
dbus_malloc0 (strlen (error->message) + 1);
|
|
if (*reason_why_locked == NULL)
|
|
return FALSE;
|
|
strcpy (*reason_why_locked, error->message);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL)
|
|
return FALSE;
|
|
|
|
dbus_message_unref (reply);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_unlock:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Release an advisory lock on the device.
|
|
*
|
|
* Returns: TRUE if the device was successfully unlocked,
|
|
* FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_unlock (LibHalContext *ctx,
|
|
const char *udi, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"Unlock");
|
|
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL)
|
|
return FALSE;
|
|
|
|
dbus_message_unref (reply);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_new_device:
|
|
* @ctx: the context for the connection to hald
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Create a new device object which will be hidden from applications
|
|
* until the CommitToGdl(), ie. libhal_device_commit_to_gdl(), method
|
|
* is called. Note that the program invoking this method needs to run
|
|
* with super user privileges.
|
|
*
|
|
* Returns: Temporary device unique id or NULL if there was a
|
|
* problem. This string must be freed by the caller.
|
|
*/
|
|
char *
|
|
libhal_new_device (LibHalContext *ctx, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter reply_iter;
|
|
char *value;
|
|
char *dbus_str;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
"/org/freedesktop/Hal/Manager",
|
|
"org.freedesktop.Hal.Manager",
|
|
"NewDevice");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return NULL;
|
|
}
|
|
if (reply == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
|
|
/* now analyze reply */
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_STRING) {
|
|
fprintf (stderr,
|
|
"%s %d : expected a string in reply to NewDevice\n",
|
|
__FILE__, __LINE__);
|
|
dbus_message_unref (reply);
|
|
return NULL;
|
|
}
|
|
|
|
dbus_message_iter_get_basic (&reply_iter, &dbus_str);
|
|
value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
|
|
if (value == NULL) {
|
|
fprintf (stderr, "%s %d : error allocating memory\n",
|
|
__FILE__, __LINE__);
|
|
}
|
|
|
|
dbus_message_unref (reply);
|
|
return value;
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_device_commit_to_gdl:
|
|
* @ctx: the context for the connection to hald
|
|
* @temp_udi: the temporary unique device id as returned by libhal_new_device()
|
|
* @udi: the new unique device id.
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* When a hidden device has been built using the NewDevice method,
|
|
* ie. libhal_new_device(), and the org.freedesktop.Hal.Device
|
|
* interface this function will commit it to the global device list.
|
|
*
|
|
* This means that the device object will be visible to applications
|
|
* and the HAL daemon will possibly attempt to boot the device
|
|
* (depending on the property RequireEnable).
|
|
*
|
|
* Note that the program invoking this method needs to run with super
|
|
* user privileges.
|
|
*
|
|
* Returns: FALSE if the given unique device id is already in use.
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_commit_to_gdl (LibHalContext *ctx,
|
|
const char *temp_udi, const char *udi, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(temp_udi, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
"/org/freedesktop/Hal/Manager",
|
|
"org.freedesktop.Hal.Manager",
|
|
"CommitToGdl");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &temp_udi);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
|
|
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_unref (reply);
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_remove_device:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique device id.
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* This method can be invoked when a device is removed. The HAL daemon
|
|
* will shut down the device. Note that the device may still be in the
|
|
* device list if the Persistent property is set to true.
|
|
*
|
|
* Note that the program invoking this method needs to run with super
|
|
* user privileges.
|
|
*
|
|
* Returns: TRUE if the device was removed, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_remove_device (LibHalContext *ctx, const char *udi, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
"/org/freedesktop/Hal/Manager",
|
|
"org.freedesktop.Hal.Manager",
|
|
"Remove");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
|
|
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_unref (reply);
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_exists:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique device id.
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Determine if a device exists.
|
|
*
|
|
* Returns: TRUE if the device exists
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_exists (LibHalContext *ctx, const char *udi, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter, reply_iter;
|
|
dbus_bool_t value;
|
|
DBusError _error;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
"/org/freedesktop/Hal/Manager",
|
|
"org.freedesktop.Hal.Manager",
|
|
"DeviceExists");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
|
|
|
|
dbus_error_init (&_error);
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
&_error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
|
|
/* now analyze reply */
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
|
|
fprintf (stderr,
|
|
"%s %d : expected a bool in reply to DeviceExists\n",
|
|
__FILE__, __LINE__);
|
|
dbus_message_unref (reply);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_get_basic (&reply_iter, &value);
|
|
|
|
dbus_message_unref (reply);
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_property_exists:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique device id.
|
|
* @key: name of the property
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Determine if a property on a device exists.
|
|
*
|
|
* Returns: TRUE if the device exists, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_property_exists (LibHalContext *ctx,
|
|
const char *udi, const char *key, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter, reply_iter;
|
|
dbus_bool_t value;
|
|
DBusError _error;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"PropertyExists");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
|
|
|
|
dbus_error_init (&_error);
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
&_error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
|
|
/* now analyse reply */
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
|
|
fprintf (stderr, "%s %d : expected a bool in reply to "
|
|
"PropertyExists\n", __FILE__, __LINE__);
|
|
dbus_message_unref (reply);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_get_basic (&reply_iter, &value);
|
|
|
|
dbus_message_unref (reply);
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* libhal_merge_properties:
|
|
* @ctx: the context for the connection to hald
|
|
* @target_udi: the Unique device id of target device to merge to
|
|
* @source_udi: the Unique device id of device to merge from
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Merge properties from one device to another.
|
|
*
|
|
* Returns: TRUE if the properties were merged, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_merge_properties (LibHalContext *ctx,
|
|
const char *target_udi, const char *source_udi, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(target_udi, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(source_udi, FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
"/org/freedesktop/Hal/Manager",
|
|
"org.freedesktop.Hal.Manager",
|
|
"MergeProperties");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &target_udi);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &source_udi);
|
|
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_unref (reply);
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_matches:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi1: the Unique Device Id for device 1
|
|
* @udi2: the Unique Device Id for device 2
|
|
* @property_namespace: the namespace for set of devices, e.g. "usb"
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Check a set of properties for two devices matches.
|
|
*
|
|
* Checks that all properties where keys, starting with a given value
|
|
* (namespace), of the first device is in the second device and that
|
|
* they got the same value and type.
|
|
*
|
|
* Note that the other inclusion isn't tested, so there could be
|
|
* properties (from the given namespace) in the second device not
|
|
* present in the first device.
|
|
*
|
|
* Returns: TRUE if all properties starting with the given namespace
|
|
* parameter from one device is in the other and have the same value.
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_matches (LibHalContext *ctx,
|
|
const char *udi1, const char *udi2,
|
|
const char *property_namespace, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter, reply_iter;
|
|
dbus_bool_t value;
|
|
DBusError _error;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi1, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi2, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(property_namespace, "*property_namespace", FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
"/org/freedesktop/Hal/Manager",
|
|
"org.freedesktop.Hal.Manager",
|
|
"DeviceMatches");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, udi1);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, udi2);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, property_namespace);
|
|
|
|
dbus_error_init (&_error);
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
&_error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL) {
|
|
return FALSE;
|
|
}
|
|
/* now analyse reply */
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
|
|
fprintf (stderr,
|
|
"%s %d : expected a bool in reply to DeviceMatches\n",
|
|
__FILE__, __LINE__);
|
|
dbus_message_unref (reply);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_get_basic (&reply_iter, &value);
|
|
|
|
dbus_message_unref (reply);
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_print:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Print a device to stdout; useful for debugging.
|
|
*
|
|
* Returns: TRUE if device's information could be obtained, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_print (LibHalContext *ctx, const char *udi, DBusError *error)
|
|
{
|
|
int type;
|
|
char *key;
|
|
LibHalPropertySet *pset;
|
|
LibHalPropertySetIterator i;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
|
|
printf ("device_id = %s\n", udi);
|
|
|
|
if ((pset = libhal_device_get_all_properties (ctx, udi, error)) == NULL)
|
|
return FALSE;
|
|
|
|
for (libhal_psi_init (&i, pset); libhal_psi_has_more (&i);
|
|
libhal_psi_next (&i)) {
|
|
type = libhal_psi_get_type (&i);
|
|
key = libhal_psi_get_key (&i);
|
|
|
|
switch (type) {
|
|
case LIBHAL_PROPERTY_TYPE_STRING:
|
|
printf (" %s = '%s' (string)\n", key,
|
|
libhal_psi_get_string (&i));
|
|
break;
|
|
case LIBHAL_PROPERTY_TYPE_INT32:
|
|
printf (" %s = %d = 0x%x (int)\n", key,
|
|
libhal_psi_get_int (&i),
|
|
libhal_psi_get_int (&i));
|
|
break;
|
|
case LIBHAL_PROPERTY_TYPE_UINT64:
|
|
printf (" %s = %llu = 0x%llx (uint64)\n", key,
|
|
(long long unsigned int) libhal_psi_get_uint64 (&i),
|
|
(long long unsigned int) libhal_psi_get_uint64 (&i));
|
|
break;
|
|
case LIBHAL_PROPERTY_TYPE_BOOLEAN:
|
|
printf (" %s = %s (bool)\n", key,
|
|
(libhal_psi_get_bool (&i) ? "true" :
|
|
"false"));
|
|
break;
|
|
case LIBHAL_PROPERTY_TYPE_DOUBLE:
|
|
printf (" %s = %g (double)\n", key,
|
|
libhal_psi_get_double (&i));
|
|
break;
|
|
case LIBHAL_PROPERTY_TYPE_STRLIST:
|
|
{
|
|
unsigned int j;
|
|
char **str_list;
|
|
|
|
str_list = libhal_psi_get_strlist (&i);
|
|
printf (" %s = [", key);
|
|
for (j = 0; str_list[j] != NULL; j++) {
|
|
printf ("'%s'", str_list[j]);
|
|
if (str_list[j+1] != NULL)
|
|
printf (", ");
|
|
}
|
|
printf ("] (string list)\n");
|
|
|
|
break;
|
|
}
|
|
default:
|
|
printf (" *** unknown type for key %s\n", key);
|
|
break;
|
|
}
|
|
}
|
|
|
|
libhal_free_property_set (pset);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_manager_find_device_string_match:
|
|
* @ctx: the context for the connection to hald
|
|
* @key: name of the property
|
|
* @value: the value to match
|
|
* @num_devices: pointer to store number of devices
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Find a device in the GDL where a single string property matches a
|
|
* given value.
|
|
*
|
|
* Returns: UDI of devices; free with libhal_free_string_array()
|
|
*/
|
|
char **
|
|
libhal_manager_find_device_string_match (LibHalContext *ctx,
|
|
const char *key,
|
|
const char *value, int *num_devices, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter, iter_array, reply_iter;
|
|
char **hal_device_names;
|
|
DBusError _error;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
|
|
LIBHAL_CHECK_PARAM_VALID(value, "*value", NULL);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
"/org/freedesktop/Hal/Manager",
|
|
"org.freedesktop.Hal.Manager",
|
|
"FindDeviceStringMatch");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return NULL;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
|
|
|
|
dbus_error_init (&_error);
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
&_error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return NULL;
|
|
}
|
|
if (reply == NULL) {
|
|
return NULL;
|
|
}
|
|
/* now analyse reply */
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
|
|
fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__);
|
|
return NULL;
|
|
}
|
|
|
|
dbus_message_iter_recurse (&reply_iter, &iter_array);
|
|
|
|
hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
|
|
|
|
dbus_message_unref (reply);
|
|
return hal_device_names;
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_device_add_capability:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @capability: the capability name to add
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Assign a capability to a device.
|
|
*
|
|
* Returns: TRUE if the capability was added, FALSE if the device didn't exist
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_add_capability (LibHalContext *ctx,
|
|
const char *udi, const char *capability, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(capability, "*capability", FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"AddCapability");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability);
|
|
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_unref (reply);
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_query_capability:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @capability: the capability name
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Check if a device has a capability. The result is undefined if the
|
|
* device doesn't exist.
|
|
*
|
|
* Returns: TRUE if the device has the capability, otherwise FALSE
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_query_capability (LibHalContext *ctx, const char *udi, const char *capability, DBusError *error)
|
|
{
|
|
char **caps;
|
|
unsigned int i;
|
|
dbus_bool_t ret;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(capability, "*capability", FALSE);
|
|
|
|
ret = FALSE;
|
|
|
|
caps = libhal_device_get_property_strlist (ctx, udi, "info.capabilities", error);
|
|
if (caps != NULL) {
|
|
for (i = 0; caps[i] != NULL; i++) {
|
|
if (strcmp (caps[i], capability) == 0) {
|
|
ret = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
libhal_free_string_array (caps);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* libhal_find_device_by_capability:
|
|
* @ctx: the context for the connection to hald
|
|
* @capability: the capability name
|
|
* @num_devices: pointer to store number of devices
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Find devices with a given capability.
|
|
*
|
|
* Returns: UDI of devices; free with libhal_free_string_array()
|
|
*/
|
|
char **
|
|
libhal_find_device_by_capability (LibHalContext *ctx,
|
|
const char *capability, int *num_devices, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter, iter_array, reply_iter;
|
|
char **hal_device_names;
|
|
DBusError _error;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
|
|
LIBHAL_CHECK_PARAM_VALID(capability, "*capability", NULL);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
"/org/freedesktop/Hal/Manager",
|
|
"org.freedesktop.Hal.Manager",
|
|
"FindDeviceByCapability");
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return NULL;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability);
|
|
|
|
dbus_error_init (&_error);
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
&_error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return NULL;
|
|
}
|
|
if (reply == NULL) {
|
|
return NULL;
|
|
}
|
|
/* now analyse reply */
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
|
|
fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__);
|
|
return NULL;
|
|
}
|
|
|
|
dbus_message_iter_recurse (&reply_iter, &iter_array);
|
|
|
|
hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
|
|
|
|
dbus_message_unref (reply);
|
|
return hal_device_names;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_property_watch_all:
|
|
* @ctx: the context for the connection to hald
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Watch all devices, ie. the device_property_changed callback is
|
|
* invoked when the properties on any device changes.
|
|
*
|
|
* Returns: TRUE only if the operation succeeded
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_property_watch_all (LibHalContext *ctx, DBusError *error)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
|
|
dbus_bus_add_match (ctx->connection,
|
|
"type='signal',"
|
|
"interface='org.freedesktop.Hal.Device',"
|
|
"sender='org.freedesktop.Hal'", error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
dbus_bool_t
|
|
libhal_device_property_remove_watch_all (LibHalContext *ctx, DBusError *error)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
|
|
dbus_bus_remove_match (ctx->connection,
|
|
"type='signal',"
|
|
"interface='org.freedesktop.Hal.Device',"
|
|
"sender='org.freedesktop.Hal'", error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_device_add_property_watch:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Add a watch on a device, so the device_property_changed callback is
|
|
* invoked when the properties on the given device changes.
|
|
*
|
|
* The application itself is responsible for deleting the watch, using
|
|
* libhal_device_remove_property_watch, if the device is removed.
|
|
*
|
|
* Returns: TRUE only if the operation succeeded
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_add_property_watch (LibHalContext *ctx, const char *udi, DBusError *error)
|
|
{
|
|
char buf[512];
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
|
|
snprintf (buf, 512,
|
|
"type='signal',"
|
|
"interface='org.freedesktop.Hal.Device',"
|
|
"sender='org.freedesktop.Hal'," "path=%s", udi);
|
|
|
|
dbus_bus_add_match (ctx->connection, buf, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_device_remove_property_watch:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Remove a watch on a device.
|
|
*
|
|
* Returns: TRUE only if the operation succeeded
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_remove_property_watch (LibHalContext *ctx, const char *udi, DBusError *error)
|
|
{
|
|
char buf[512];
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
|
|
snprintf (buf, 512,
|
|
"type='signal',"
|
|
"interface='org.freedesktop.Hal.Device',"
|
|
"sender='org.freedesktop.Hal'," "path=%s", udi);
|
|
|
|
dbus_bus_remove_match (ctx->connection, buf, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_ctx_new:
|
|
*
|
|
* Create a new LibHalContext
|
|
*
|
|
* Returns: a new uninitialized LibHalContext object
|
|
*/
|
|
LibHalContext *
|
|
libhal_ctx_new (void)
|
|
{
|
|
LibHalContext *ctx;
|
|
|
|
ctx = calloc (1, sizeof (LibHalContext));
|
|
if (ctx == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Failed to allocate %lu bytes\n",
|
|
__FILE__, __LINE__, (unsigned long) sizeof (LibHalContext));
|
|
return NULL;
|
|
}
|
|
|
|
ctx->is_initialized = FALSE;
|
|
ctx->is_shutdown = FALSE;
|
|
ctx->connection = NULL;
|
|
ctx->is_direct = FALSE;
|
|
|
|
return ctx;
|
|
}
|
|
|
|
/**
|
|
* libhal_ctx_set_cache:
|
|
* @ctx: context to enable/disable cache for
|
|
* @use_cache: whether or not to use cache
|
|
*
|
|
* Enable or disable caching. Note: Caching is not actually
|
|
* implemented yet.
|
|
*
|
|
* Returns: TRUE if cache was successfully enabled/disabled, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ctx_set_cache (LibHalContext *ctx, dbus_bool_t use_cache)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
|
|
ctx->cache_enabled = use_cache;
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_ctx_set_dbus_connection:
|
|
* @ctx: context to set connection for
|
|
* @conn: DBus connection to use
|
|
*
|
|
* Set DBus connection to use to talk to hald.
|
|
*
|
|
* Returns: TRUE if connection was successfully set, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ctx_set_dbus_connection (LibHalContext *ctx, DBusConnection *conn)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
|
|
if (conn == NULL)
|
|
return FALSE;
|
|
|
|
ctx->connection = conn;
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_ctx_get_dbus_connection:
|
|
* @ctx: context to get connection for
|
|
*
|
|
* Get DBus connection used for talking to hald.
|
|
*
|
|
* Returns: DBus connection to use or NULL
|
|
*/
|
|
DBusConnection *
|
|
libhal_ctx_get_dbus_connection (LibHalContext *ctx)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
|
|
|
|
return ctx->connection;
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_ctx_init:
|
|
* @ctx: Context for connection to hald (D-BUS connection should be set with libhal_ctx_set_dbus_connection)
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Initialize the connection to hald.
|
|
*
|
|
* Returns: TRUE if initialization succeeds, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ctx_init (LibHalContext *ctx, DBusError *error)
|
|
{
|
|
DBusError _error;
|
|
dbus_bool_t hald_exists;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
|
|
if (ctx->connection == NULL)
|
|
return FALSE;
|
|
|
|
dbus_error_init (&_error);
|
|
hald_exists = dbus_bus_name_has_owner (ctx->connection, "org.freedesktop.Hal", &_error);
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!hald_exists) {
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
if (!dbus_connection_add_filter (ctx->connection, filter_func, ctx, NULL)) {
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_bus_add_match (ctx->connection,
|
|
"type='signal',"
|
|
"interface='org.freedesktop.Hal.Manager',"
|
|
"sender='org.freedesktop.Hal',"
|
|
"path='/org/freedesktop/Hal/Manager'", &_error);
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
ctx->is_initialized = TRUE;
|
|
ctx->is_direct = FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_ctx_init_direct:
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Create an already initialized connection to hald. This function should only be used by HAL helpers.
|
|
*
|
|
* Returns: A pointer to an already initialized LibHalContext
|
|
*/
|
|
LibHalContext *
|
|
libhal_ctx_init_direct (DBusError *error)
|
|
{
|
|
char *hald_addr;
|
|
LibHalContext *ctx;
|
|
DBusError _error;
|
|
|
|
ctx = libhal_ctx_new ();
|
|
if (ctx == NULL)
|
|
goto out;
|
|
|
|
if (((hald_addr = getenv ("HALD_DIRECT_ADDR"))) == NULL) {
|
|
libhal_ctx_free (ctx);
|
|
ctx = NULL;
|
|
goto out;
|
|
}
|
|
|
|
dbus_error_init (&_error);
|
|
ctx->connection = dbus_connection_open (hald_addr, &_error);
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
libhal_ctx_free (ctx);
|
|
ctx = NULL;
|
|
goto out;
|
|
}
|
|
|
|
if (!dbus_connection_add_filter (ctx->connection, filter_func, ctx, NULL)) {
|
|
libhal_ctx_free (ctx);
|
|
ctx = NULL;
|
|
goto out;
|
|
}
|
|
|
|
|
|
ctx->is_initialized = TRUE;
|
|
ctx->is_direct = TRUE;
|
|
|
|
out:
|
|
return ctx;
|
|
}
|
|
|
|
/**
|
|
* libhal_ctx_shutdown:
|
|
* @ctx: the context for the connection to hald
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Shut down a connection to hald.
|
|
*
|
|
* Returns: TRUE if connection successfully shut down, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ctx_shutdown (LibHalContext *ctx, DBusError *error)
|
|
{
|
|
DBusError myerror;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
|
|
if (ctx->is_direct) {
|
|
/* for some reason dbus_connection_set_exit_on_disconnect doesn't work yet so don't unref */
|
|
/*dbus_connection_unref (ctx->connection);*/
|
|
} else {
|
|
dbus_error_init (&myerror);
|
|
dbus_bus_remove_match (ctx->connection,
|
|
"type='signal',"
|
|
"interface='org.freedesktop.Hal.Manager',"
|
|
"sender='org.freedesktop.Hal',"
|
|
"path='/org/freedesktop/Hal/Manager'", &myerror);
|
|
dbus_move_error (&myerror, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
fprintf (stderr, "%s %d : Error unsubscribing to signals, error=%s\n",
|
|
__FILE__, __LINE__, error->message);
|
|
/** @todo clean up */
|
|
}
|
|
|
|
/* TODO: remove other matches */
|
|
|
|
dbus_connection_remove_filter (ctx->connection, filter_func, ctx);
|
|
}
|
|
|
|
ctx->is_initialized = FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_ctx_free:
|
|
* @ctx: pointer to a LibHalContext
|
|
*
|
|
* Free a LibHalContext resource.
|
|
*
|
|
* Returns: TRUE
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ctx_free (LibHalContext *ctx)
|
|
{
|
|
free (ctx);
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_ctx_set_device_added:
|
|
* @ctx: the context for the connection to hald
|
|
* @callback: the function to call when a device is added
|
|
*
|
|
* Set the callback for when a device is added
|
|
*
|
|
* Returns: TRUE if callback was successfully set, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ctx_set_device_added (LibHalContext *ctx, LibHalDeviceAdded callback)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
|
|
ctx->device_added = callback;
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_ctx_set_device_removed:
|
|
* @ctx: the context for the connection to hald
|
|
* @callback: the function to call when a device is removed
|
|
*
|
|
* Set the callback for when a device is removed.
|
|
*
|
|
* Returns: TRUE if callback was successfully set, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ctx_set_device_removed (LibHalContext *ctx, LibHalDeviceRemoved callback)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
|
|
ctx->device_removed = callback;
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_ctx_set_device_new_capability:
|
|
* @ctx: the context for the connection to hald
|
|
* @callback: the function to call when a device gains a new capability
|
|
*
|
|
* Set the callback for when a device gains a new capability.
|
|
*
|
|
* Returns: TRUE if callback was successfully set, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ctx_set_device_new_capability (LibHalContext *ctx, LibHalDeviceNewCapability callback)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
|
|
ctx->device_new_capability = callback;
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_ctx_set_device_lost_capability:
|
|
* @ctx: the context for the connection to hald
|
|
* @callback: the function to call when a device loses a capability
|
|
*
|
|
* Set the callback for when a device loses a capability
|
|
*
|
|
* Returns: TRUE if callback was successfully set, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ctx_set_device_lost_capability (LibHalContext *ctx, LibHalDeviceLostCapability callback)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
|
|
ctx->device_lost_capability = callback;
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_ctx_set_device_property_modified:
|
|
* @ctx: the context for the connection to hald
|
|
* @callback: the function to call when a property is modified on a device
|
|
*
|
|
* Set the callback for when a property is modified on a device.
|
|
*
|
|
* Returns: TRUE if callback was successfully set, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ctx_set_device_property_modified (LibHalContext *ctx, LibHalDevicePropertyModified callback)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
|
|
ctx->device_property_modified = callback;
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_ctx_set_device_condition:
|
|
* @ctx: the context for the connection to hald
|
|
* @callback: the function to call when a device emits a condition
|
|
*
|
|
* Set the callback for when a device emits a condition
|
|
*
|
|
* Returns: TRUE if callback was successfully set, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ctx_set_device_condition (LibHalContext *ctx, LibHalDeviceCondition callback)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
|
|
ctx->device_condition = callback;
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_ctx_set_singleton_device_added:
|
|
* @ctx: the context for the connection to hald
|
|
* @callback: the function to call when a device emits a condition
|
|
*
|
|
* Set the callback for when a singleton should handle a new device
|
|
*
|
|
* Returns: TRUE if callback was successfully set, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ctx_set_singleton_device_added (LibHalContext *ctx, LibHalSingletonDeviceAdded callback)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
|
|
ctx->singleton_device_added = callback;
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_ctx_set_singleton_device_removed:
|
|
* @ctx: the context for the connection to hald
|
|
* @callback: the function to call when a device emits a condition
|
|
*
|
|
* Set the callback for when a singleton should discard a device
|
|
*
|
|
* Returns: TRUE if callback was successfully set, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ctx_set_singleton_device_removed (LibHalContext *ctx, LibHalSingletonDeviceRemoved callback)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
|
|
ctx->singleton_device_removed = callback;
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_string_array_length:
|
|
* @str_array: array of strings to consider
|
|
*
|
|
* Get the length of an array of strings.
|
|
*
|
|
* Returns: Number of strings in array
|
|
*/
|
|
unsigned int
|
|
libhal_string_array_length (char **str_array)
|
|
{
|
|
unsigned int i;
|
|
|
|
if (str_array == NULL)
|
|
return 0;
|
|
|
|
for (i = 0; str_array[i] != NULL; i++)
|
|
;
|
|
|
|
return i;
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_device_rescan:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique id of device
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* TODO document me.
|
|
*
|
|
* Returns: Whether the operation succeeded
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_rescan (LibHalContext *ctx, const char *udi, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessageIter reply_iter;
|
|
DBusMessage *reply;
|
|
dbus_bool_t result;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"Rescan");
|
|
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL)
|
|
return FALSE;
|
|
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) !=
|
|
DBUS_TYPE_BOOLEAN) {
|
|
dbus_message_unref (reply);
|
|
return FALSE;
|
|
}
|
|
dbus_message_iter_get_basic (&reply_iter, &result);
|
|
|
|
dbus_message_unref (reply);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_reprobe:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique id of device
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* TODO document me.
|
|
*
|
|
* Returns: Whether the operation succeeded
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_reprobe (LibHalContext *ctx, const char *udi, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessageIter reply_iter;
|
|
DBusMessage *reply;
|
|
dbus_bool_t result;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"Reprobe");
|
|
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL)
|
|
return FALSE;
|
|
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) !=
|
|
DBUS_TYPE_BOOLEAN) {
|
|
dbus_message_unref (reply);
|
|
return FALSE;
|
|
}
|
|
dbus_message_iter_get_basic (&reply_iter, &result);
|
|
|
|
dbus_message_unref (reply);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_emit_condition:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @condition_name: user-readable name of condition
|
|
* @condition_details: user-readable details of condition
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Emit a condition from a device. Can only be used from hald helpers.
|
|
*
|
|
* Returns: TRUE if condition successfully emitted,
|
|
* FALSE otherwise
|
|
*/
|
|
dbus_bool_t libhal_device_emit_condition (LibHalContext *ctx,
|
|
const char *udi,
|
|
const char *condition_name,
|
|
const char *condition_details,
|
|
DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessageIter iter;
|
|
DBusMessageIter reply_iter;
|
|
DBusMessage *reply;
|
|
dbus_bool_t result;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(condition_name, "*condition_name", FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(condition_details, "*condition_details", FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"EmitCondition");
|
|
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &condition_name);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &condition_details);
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
fprintf (stderr,
|
|
"%s %d : Failure sending D-BUS message: %s: %s\n",
|
|
__FILE__, __LINE__, error->name, error->message);
|
|
return FALSE;
|
|
}
|
|
|
|
if (reply == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Got no reply\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) !=
|
|
DBUS_TYPE_BOOLEAN) {
|
|
dbus_message_unref (reply);
|
|
fprintf (stderr,
|
|
"%s %d : Malformed reply\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
dbus_message_iter_get_basic (&reply_iter, &result);
|
|
|
|
dbus_message_unref (reply);
|
|
|
|
return result;
|
|
}
|
|
|
|
static dbus_bool_t
|
|
addon_is_ready(LibHalContext *ctx, const char *identifier,
|
|
dbus_bool_t singleton, DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessageIter iter;
|
|
DBusMessage *reply;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(identifier, "*identifier", FALSE);
|
|
|
|
if (singleton) {
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
"/org/freedesktop/Hal/Manager",
|
|
"org.freedesktop.Hal.Manager",
|
|
"SingletonAddonIsReady");
|
|
} else {
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
identifier,
|
|
"org.freedesktop.Hal.Device",
|
|
"AddonIsReady");
|
|
}
|
|
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &identifier);
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL)
|
|
return FALSE;
|
|
|
|
dbus_message_unref (reply);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_device_addon_is_ready:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id this addon is handling
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* HAL addon's must call this method when they are done initializing the device object. The HAL
|
|
* daemon will wait for all addon's to call this.
|
|
*
|
|
* Can only be used from hald helpers.
|
|
*
|
|
* Returns: TRUE if the HAL daemon received the message, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_addon_is_ready (LibHalContext *ctx,
|
|
const char *udi,
|
|
DBusError *error)
|
|
{
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
|
|
return addon_is_ready (ctx, udi, FALSE, error);
|
|
}
|
|
|
|
/**
|
|
* libhal_device_singleton_addon_is_ready:
|
|
* @ctx: the context for the connection to hald
|
|
* @command_line: commandline singleton was started with
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* HAL singleton addon's must call this method when they are done initializing the device object. The HAL
|
|
* daemon will wait for all addon's to call this.
|
|
*
|
|
* Can only be used from hald helpers.
|
|
*
|
|
* Returns: TRUE if the HAL daemon received the message, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_singleton_addon_is_ready (LibHalContext *ctx,
|
|
const char *command_line,
|
|
DBusError *error)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(command_line, "*command_line", FALSE);
|
|
|
|
return addon_is_ready (ctx, command_line, TRUE, error);
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_device_claim_interface:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique Device Id
|
|
* @interface_name: Name of interface to claim, e.g. org.freedesktop.Hal.Device.FoobarKindOfThing
|
|
* @introspection_xml: Introspection XML containing what would be inside the interface XML tag
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Claim an interface for a device. All messages to this interface
|
|
* will be forwarded to the helper. Can only be used from hald
|
|
* helpers.
|
|
*
|
|
* Returns: TRUE if interface was claimed, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_claim_interface (LibHalContext *ctx,
|
|
const char *udi,
|
|
const char *interface_name,
|
|
const char *introspection_xml,
|
|
DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessageIter iter;
|
|
DBusMessageIter reply_iter;
|
|
DBusMessage *reply;
|
|
dbus_bool_t result;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(interface_name, "*interface_name", FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"ClaimInterface");
|
|
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface_name);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &introspection_xml);
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL)
|
|
return FALSE;
|
|
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) !=
|
|
DBUS_TYPE_BOOLEAN) {
|
|
dbus_message_unref (reply);
|
|
return FALSE;
|
|
}
|
|
dbus_message_iter_get_basic (&reply_iter, &result);
|
|
|
|
dbus_message_unref (reply);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
struct LibHalChangeSetElement_s;
|
|
|
|
typedef struct LibHalChangeSetElement_s LibHalChangeSetElement;
|
|
|
|
struct LibHalChangeSetElement_s {
|
|
char *key;
|
|
int change_type;
|
|
union {
|
|
char *val_str;
|
|
dbus_int32_t val_int;
|
|
dbus_uint64_t val_uint64;
|
|
double val_double;
|
|
dbus_bool_t val_bool;
|
|
char **val_strlist;
|
|
} value;
|
|
LibHalChangeSetElement *next;
|
|
LibHalChangeSetElement *prev;
|
|
};
|
|
|
|
struct LibHalChangeSet_s {
|
|
char *udi;
|
|
LibHalChangeSetElement *head;
|
|
LibHalChangeSetElement *tail;
|
|
};
|
|
|
|
/**
|
|
* libhal_device_new_changeset:
|
|
* @udi: unique device identifier
|
|
*
|
|
* Request a new changeset object. Used for changing multiple properties at once. Useful when
|
|
* performance is critical and also for atomically updating several properties.
|
|
*
|
|
* Returns: A new changeset object or NULL on error
|
|
*/
|
|
LibHalChangeSet *
|
|
libhal_device_new_changeset (const char *udi)
|
|
{
|
|
LibHalChangeSet *changeset;
|
|
|
|
LIBHAL_CHECK_UDI_VALID(udi, NULL);
|
|
|
|
changeset = calloc (1, sizeof (LibHalChangeSet));
|
|
if (changeset == NULL)
|
|
goto out;
|
|
|
|
changeset->udi = strdup (udi);
|
|
if (changeset->udi == NULL) {
|
|
free (changeset);
|
|
changeset = NULL;
|
|
goto out;
|
|
}
|
|
|
|
changeset->head = NULL;
|
|
changeset->tail = NULL;
|
|
|
|
out:
|
|
return changeset;
|
|
}
|
|
|
|
static void
|
|
libhal_changeset_append (LibHalChangeSet *changeset, LibHalChangeSetElement *elem)
|
|
{
|
|
LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", (void) NULL );
|
|
LIBHAL_CHECK_PARAM_VALID(elem, "*elem", (void) NULL);
|
|
|
|
if (changeset->head == NULL) {
|
|
changeset->head = elem;
|
|
changeset->tail = elem;
|
|
elem->next = NULL;
|
|
elem->prev = NULL;
|
|
} else {
|
|
elem->prev = changeset->tail;
|
|
elem->next = NULL;
|
|
elem->prev->next = elem;
|
|
changeset->tail = elem;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_changeset_set_property_string:
|
|
* @changeset: the changeset
|
|
* @key: key of property
|
|
* @value: the value to set
|
|
*
|
|
* Set a property.
|
|
*
|
|
* Returns: FALSE on OOM
|
|
*/
|
|
dbus_bool_t
|
|
libhal_changeset_set_property_string (LibHalChangeSet *changeset, const char *key, const char *value)
|
|
{
|
|
LibHalChangeSetElement *elem;
|
|
|
|
LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(value, "*value", FALSE);
|
|
|
|
elem = calloc (1, sizeof (LibHalChangeSetElement));
|
|
if (elem == NULL)
|
|
goto out;
|
|
elem->key = strdup (key);
|
|
if (elem->key == NULL) {
|
|
free (elem);
|
|
elem = NULL;
|
|
goto out;
|
|
}
|
|
|
|
elem->change_type = LIBHAL_PROPERTY_TYPE_STRING;
|
|
elem->value.val_str = strdup (value);
|
|
if (elem->value.val_str == NULL) {
|
|
free (elem->key);
|
|
free (elem);
|
|
elem = NULL;
|
|
goto out;
|
|
}
|
|
|
|
libhal_changeset_append (changeset, elem);
|
|
out:
|
|
return elem != NULL;
|
|
}
|
|
|
|
/**
|
|
* libhal_changeset_set_property_int:
|
|
* @changeset: the changeset
|
|
* @key: key of property
|
|
* @value: the value to set
|
|
*
|
|
* Set a property.
|
|
*
|
|
* Returns: FALSE on OOM
|
|
*/
|
|
dbus_bool_t
|
|
libhal_changeset_set_property_int (LibHalChangeSet *changeset, const char *key, dbus_int32_t value)
|
|
{
|
|
LibHalChangeSetElement *elem;
|
|
|
|
LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
|
|
elem = calloc (1, sizeof (LibHalChangeSetElement));
|
|
if (elem == NULL)
|
|
goto out;
|
|
elem->key = strdup (key);
|
|
if (elem->key == NULL) {
|
|
free (elem);
|
|
elem = NULL;
|
|
goto out;
|
|
}
|
|
|
|
elem->change_type = LIBHAL_PROPERTY_TYPE_INT32;
|
|
elem->value.val_int = value;
|
|
|
|
libhal_changeset_append (changeset, elem);
|
|
out:
|
|
return elem != NULL;
|
|
}
|
|
|
|
/**
|
|
* libhal_changeset_set_property_uint64:
|
|
* @changeset: the changeset
|
|
* @key: key of property
|
|
* @value: the value to set
|
|
*
|
|
* Set a property.
|
|
*
|
|
* Returns: FALSE on OOM
|
|
*/
|
|
dbus_bool_t
|
|
libhal_changeset_set_property_uint64 (LibHalChangeSet *changeset, const char *key, dbus_uint64_t value)
|
|
{
|
|
LibHalChangeSetElement *elem;
|
|
|
|
LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
|
|
elem = calloc (1, sizeof (LibHalChangeSetElement));
|
|
if (elem == NULL)
|
|
goto out;
|
|
elem->key = strdup (key);
|
|
if (elem->key == NULL) {
|
|
free (elem);
|
|
elem = NULL;
|
|
goto out;
|
|
}
|
|
|
|
elem->change_type = LIBHAL_PROPERTY_TYPE_UINT64;
|
|
elem->value.val_uint64 = value;
|
|
|
|
libhal_changeset_append (changeset, elem);
|
|
out:
|
|
return elem != NULL;
|
|
}
|
|
|
|
/**
|
|
* libhal_changeset_set_property_double:
|
|
* @changeset: the changeset
|
|
* @key: key of property
|
|
* @value: the value to set
|
|
*
|
|
* Set a property.
|
|
*
|
|
* Returns: FALSE on OOM
|
|
*/
|
|
dbus_bool_t
|
|
libhal_changeset_set_property_double (LibHalChangeSet *changeset, const char *key, double value)
|
|
{
|
|
LibHalChangeSetElement *elem;
|
|
|
|
LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
|
|
elem = calloc (1, sizeof (LibHalChangeSetElement));
|
|
if (elem == NULL)
|
|
goto out;
|
|
elem->key = strdup (key);
|
|
if (elem->key == NULL) {
|
|
free (elem);
|
|
elem = NULL;
|
|
goto out;
|
|
}
|
|
|
|
elem->change_type = LIBHAL_PROPERTY_TYPE_DOUBLE;
|
|
elem->value.val_double = value;
|
|
|
|
libhal_changeset_append (changeset, elem);
|
|
out:
|
|
return elem != NULL;
|
|
}
|
|
|
|
/**
|
|
* libhal_changeset_set_property_bool:
|
|
* @changeset: the changeset
|
|
* @key: key of property
|
|
* @value: the value to set
|
|
*
|
|
* Set a property.
|
|
*
|
|
* Returns: FALSE on OOM
|
|
*/
|
|
dbus_bool_t
|
|
libhal_changeset_set_property_bool (LibHalChangeSet *changeset, const char *key, dbus_bool_t value)
|
|
{
|
|
LibHalChangeSetElement *elem;
|
|
|
|
LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
|
|
elem = calloc (1, sizeof (LibHalChangeSetElement));
|
|
if (elem == NULL)
|
|
goto out;
|
|
elem->key = strdup (key);
|
|
if (elem->key == NULL) {
|
|
free (elem);
|
|
elem = NULL;
|
|
goto out;
|
|
}
|
|
|
|
elem->change_type = LIBHAL_PROPERTY_TYPE_BOOLEAN;
|
|
elem->value.val_bool = value;
|
|
|
|
libhal_changeset_append (changeset, elem);
|
|
out:
|
|
return elem != NULL;
|
|
}
|
|
|
|
/**
|
|
* libhal_changeset_set_property_strlist:
|
|
* @changeset: the changeset
|
|
* @key: key of property
|
|
* @value: the value to set - NULL terminated array of strings
|
|
*
|
|
* Set a property.
|
|
*
|
|
* Returns: FALSE on OOM
|
|
*/
|
|
dbus_bool_t
|
|
libhal_changeset_set_property_strlist (LibHalChangeSet *changeset, const char *key, const char **value)
|
|
{
|
|
LibHalChangeSetElement *elem;
|
|
char **value_copy;
|
|
int len;
|
|
int i, j;
|
|
|
|
LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
|
|
|
|
elem = calloc (1, sizeof (LibHalChangeSetElement));
|
|
if (elem == NULL)
|
|
goto out;
|
|
elem->key = strdup (key);
|
|
if (elem->key == NULL) {
|
|
free (elem);
|
|
elem = NULL;
|
|
goto out;
|
|
}
|
|
|
|
for (i = 0; value[i] != NULL; i++)
|
|
;
|
|
len = i;
|
|
|
|
value_copy = calloc (len + 1, sizeof (char *));
|
|
if (value_copy == NULL) {
|
|
free (elem->key);
|
|
free (elem);
|
|
elem = NULL;
|
|
goto out;
|
|
}
|
|
|
|
for (i = 0; i < len; i++) {
|
|
value_copy[i] = strdup (value[i]);
|
|
if (value_copy[i] == NULL) {
|
|
for (j = 0; j < i; j++) {
|
|
free (value_copy[j]);
|
|
}
|
|
free (value_copy);
|
|
free (elem->key);
|
|
free (elem);
|
|
elem = NULL;
|
|
goto out;
|
|
}
|
|
}
|
|
value_copy[i] = NULL;
|
|
|
|
elem->change_type = LIBHAL_PROPERTY_TYPE_STRLIST;
|
|
elem->value.val_strlist = value_copy;
|
|
|
|
libhal_changeset_append (changeset, elem);
|
|
out:
|
|
return elem != NULL;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_commit_changeset:
|
|
* @ctx: the context for the connection to hald
|
|
* @changeset: the changeset to commit
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Commit a changeset to the daemon.
|
|
*
|
|
* Returns: True if the changeset was committed on the daemon side
|
|
*/
|
|
dbus_bool_t
|
|
libhal_device_commit_changeset (LibHalContext *ctx, LibHalChangeSet *changeset, DBusError *error)
|
|
{
|
|
LibHalChangeSetElement *elem;
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusError _error;
|
|
DBusMessageIter iter;
|
|
DBusMessageIter sub;
|
|
DBusMessageIter sub2;
|
|
DBusMessageIter sub3;
|
|
DBusMessageIter sub4;
|
|
int i;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(changeset->udi, FALSE);
|
|
|
|
if (changeset->head == NULL) {
|
|
return TRUE;
|
|
}
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal", changeset->udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"SetMultipleProperties");
|
|
|
|
if (message == NULL) {
|
|
fprintf (stderr, "%s %d : Couldn't allocate D-BUS message\n", __FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
|
|
dbus_message_iter_open_container (&iter,
|
|
DBUS_TYPE_ARRAY,
|
|
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
|
|
DBUS_TYPE_STRING_AS_STRING
|
|
DBUS_TYPE_VARIANT_AS_STRING
|
|
DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
|
|
&sub);
|
|
|
|
for (elem = changeset->head; elem != NULL; elem = elem->next) {
|
|
dbus_message_iter_open_container (&sub,
|
|
DBUS_TYPE_DICT_ENTRY,
|
|
NULL,
|
|
&sub2);
|
|
dbus_message_iter_append_basic (&sub2, DBUS_TYPE_STRING, &(elem->key));
|
|
|
|
switch (elem->change_type) {
|
|
case LIBHAL_PROPERTY_TYPE_STRING:
|
|
dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &sub3);
|
|
dbus_message_iter_append_basic (&sub3, DBUS_TYPE_STRING, &(elem->value.val_str));
|
|
dbus_message_iter_close_container (&sub2, &sub3);
|
|
break;
|
|
case LIBHAL_PROPERTY_TYPE_STRLIST:
|
|
dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT,
|
|
DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING, &sub3);
|
|
dbus_message_iter_open_container (&sub3, DBUS_TYPE_ARRAY,
|
|
DBUS_TYPE_STRING_AS_STRING, &sub4);
|
|
for (i = 0; elem->value.val_strlist[i] != NULL; i++) {
|
|
dbus_message_iter_append_basic (&sub4, DBUS_TYPE_STRING,
|
|
&(elem->value.val_strlist[i]));
|
|
}
|
|
dbus_message_iter_close_container (&sub3, &sub4);
|
|
dbus_message_iter_close_container (&sub2, &sub3);
|
|
break;
|
|
case LIBHAL_PROPERTY_TYPE_INT32:
|
|
dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &sub3);
|
|
dbus_message_iter_append_basic (&sub3, DBUS_TYPE_INT32, &(elem->value.val_int));
|
|
dbus_message_iter_close_container (&sub2, &sub3);
|
|
break;
|
|
case LIBHAL_PROPERTY_TYPE_UINT64:
|
|
dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_UINT64_AS_STRING, &sub3);
|
|
dbus_message_iter_append_basic (&sub3, DBUS_TYPE_UINT64, &(elem->value.val_uint64));
|
|
dbus_message_iter_close_container (&sub2, &sub3);
|
|
break;
|
|
case LIBHAL_PROPERTY_TYPE_DOUBLE:
|
|
dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_DOUBLE_AS_STRING, &sub3);
|
|
dbus_message_iter_append_basic (&sub3, DBUS_TYPE_DOUBLE, &(elem->value.val_double));
|
|
dbus_message_iter_close_container (&sub2, &sub3);
|
|
break;
|
|
case LIBHAL_PROPERTY_TYPE_BOOLEAN:
|
|
dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_BOOLEAN_AS_STRING,&sub3);
|
|
dbus_message_iter_append_basic (&sub3, DBUS_TYPE_BOOLEAN, &(elem->value.val_bool));
|
|
dbus_message_iter_close_container (&sub2, &sub3);
|
|
break;
|
|
default:
|
|
fprintf (stderr, "%s %d : unknown change_type %d\n", __FILE__, __LINE__, elem->change_type);
|
|
break;
|
|
}
|
|
dbus_message_iter_close_container (&sub, &sub2);
|
|
}
|
|
|
|
dbus_message_iter_close_container (&iter, &sub);
|
|
|
|
|
|
dbus_error_init (&_error);
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
&_error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
fprintf (stderr,
|
|
"%s %d : %s\n",
|
|
__FILE__, __LINE__, error->message);
|
|
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_unref (reply);
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_free_changeset:
|
|
* @changeset: the changeset to free
|
|
*
|
|
* Free a changeset.
|
|
*/
|
|
void
|
|
libhal_device_free_changeset (LibHalChangeSet *changeset)
|
|
{
|
|
LibHalChangeSetElement *elem;
|
|
LibHalChangeSetElement *elem2;
|
|
|
|
for (elem = changeset->head; elem != NULL; elem = elem2) {
|
|
elem2 = elem->next;
|
|
|
|
switch (elem->change_type) {
|
|
case LIBHAL_PROPERTY_TYPE_STRING:
|
|
free (elem->value.val_str);
|
|
break;
|
|
case LIBHAL_PROPERTY_TYPE_STRLIST:
|
|
libhal_free_string_array (elem->value.val_strlist);
|
|
break;
|
|
/* explicit fallthrough */
|
|
case LIBHAL_PROPERTY_TYPE_INT32:
|
|
case LIBHAL_PROPERTY_TYPE_UINT64:
|
|
case LIBHAL_PROPERTY_TYPE_DOUBLE:
|
|
case LIBHAL_PROPERTY_TYPE_BOOLEAN:
|
|
break;
|
|
default:
|
|
fprintf (stderr, "%s %d : unknown change_type %d\n", __FILE__, __LINE__, elem->change_type);
|
|
break;
|
|
}
|
|
free (elem->key);
|
|
free (elem);
|
|
}
|
|
|
|
free (changeset->udi);
|
|
free (changeset);
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_device_acquire_interface_lock:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique id of device
|
|
* @interface: the intername name to lock
|
|
* @exclusive: whether the lock should be exclusive
|
|
* @error: pointer to an initialized dbus error object for returning errors
|
|
*
|
|
* Releases a lock on an interface for a specific device.
|
|
*
|
|
* Returns: TRUE iff the lock was acquired
|
|
**/
|
|
dbus_bool_t
|
|
libhal_device_acquire_interface_lock (LibHalContext *ctx,
|
|
const char *udi,
|
|
const char *interface,
|
|
dbus_bool_t exclusive,
|
|
DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessageIter iter;
|
|
DBusMessage *reply;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(interface, "*interface", FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"AcquireInterfaceLock");
|
|
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &exclusive);
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL)
|
|
return FALSE;
|
|
|
|
dbus_message_unref (reply);
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_release_interface_lock:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique id of device
|
|
* @interface: the intername name to unlock
|
|
* @error: pointer to an initialized dbus error object for returning errors
|
|
*
|
|
* Acquires a lock on an interface for a specific device.
|
|
*
|
|
* Returns: TRUE iff the lock was released.
|
|
**/
|
|
dbus_bool_t libhal_device_release_interface_lock (LibHalContext *ctx,
|
|
const char *udi,
|
|
const char *interface,
|
|
DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessageIter iter;
|
|
DBusMessage *reply;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(interface, "*interface", FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"ReleaseInterfaceLock");
|
|
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface);
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL)
|
|
return FALSE;
|
|
|
|
dbus_message_unref (reply);
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_acquire_global_interface_lock:
|
|
* @ctx: the context for the connection to hald
|
|
* @interface: the intername name to lock
|
|
* @exclusive: whether the lock should be exclusive
|
|
* @error: pointer to an initialized dbus error object for returning errors
|
|
*
|
|
* Acquires a global lock on an interface.
|
|
*
|
|
* Returns: TRUE iff the lock was acquired
|
|
**/
|
|
dbus_bool_t libhal_acquire_global_interface_lock (LibHalContext *ctx,
|
|
const char *interface,
|
|
dbus_bool_t exclusive,
|
|
DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessageIter iter;
|
|
DBusMessage *reply;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(interface, "*interface", FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
"/org/freedesktop/Hal/Manager",
|
|
"org.freedesktop.Hal.Manager",
|
|
"AcquireGlobalInterfaceLock");
|
|
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &exclusive);
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL)
|
|
return FALSE;
|
|
|
|
dbus_message_unref (reply);
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_release_global_interface_lock:
|
|
* @ctx: the context for the connection to hald
|
|
* @interface: the intername name to unlock
|
|
* @error: pointer to an initialized dbus error object for returning errors
|
|
*
|
|
* Releases a global lock on an interface.
|
|
*
|
|
* Returns: TRUE iff the lock was released
|
|
**/
|
|
dbus_bool_t libhal_release_global_interface_lock (LibHalContext *ctx,
|
|
const char *interface,
|
|
DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessageIter iter;
|
|
DBusMessage *reply;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID(interface, "*interface", FALSE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
"/org/freedesktop/Hal/Manager",
|
|
"org.freedesktop.Hal.Manager",
|
|
"ReleaseGlobalInterfaceLock");
|
|
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface);
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return FALSE;
|
|
}
|
|
if (reply == NULL)
|
|
return FALSE;
|
|
|
|
dbus_message_unref (reply);
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_is_caller_locked_out:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique id of device
|
|
* @interface: the intername name to check
|
|
* @caller: the caller to check for
|
|
* @error: pointer to an initialized dbus error object for returning errors
|
|
*
|
|
* Determines whether a given process on the system message bus is
|
|
* locked out from an interface on a specific device. Only HAL helpers
|
|
* are privileged to use this method.
|
|
*
|
|
* Returns: Whether the given caller is locked out
|
|
**/
|
|
dbus_bool_t
|
|
libhal_device_is_caller_locked_out (LibHalContext *ctx,
|
|
const char *udi,
|
|
const char *interface,
|
|
const char *caller,
|
|
DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessageIter iter;
|
|
DBusMessage *reply;
|
|
DBusMessageIter reply_iter;
|
|
dbus_bool_t value;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, TRUE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, TRUE);
|
|
LIBHAL_CHECK_PARAM_VALID(interface, "*interface", TRUE);
|
|
LIBHAL_CHECK_PARAM_VALID(caller, "*caller", TRUE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"IsCallerLockedOut");
|
|
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return TRUE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &caller);
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return TRUE;
|
|
}
|
|
if (reply == NULL)
|
|
return TRUE;
|
|
|
|
/* now analyze reply */
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
|
|
dbus_message_unref (reply);
|
|
return TRUE;
|
|
}
|
|
dbus_message_iter_get_basic (&reply_iter, &value);
|
|
dbus_message_unref (reply);
|
|
return value;
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_ctx_set_global_interface_lock_acquired:
|
|
* @ctx: the context for the connection to hald
|
|
* @callback: the callback
|
|
*
|
|
* Set the callback for when a global interface lock is acquired.
|
|
*
|
|
* Returns: TRUE if callback was successfully set, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ctx_set_global_interface_lock_acquired (LibHalContext *ctx, LibHalGlobalInterfaceLockAcquired callback)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT (ctx, FALSE);
|
|
|
|
ctx->global_interface_lock_acquired = callback;
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_ctx_set_global_interface_lock_released:
|
|
* @ctx: the context for the connection to hald
|
|
* @callback: the callback
|
|
*
|
|
* Set the callback for when a global interface lock is released.
|
|
*
|
|
* Returns: TRUE if callback was successfully set, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ctx_set_global_interface_lock_released (LibHalContext *ctx, LibHalGlobalInterfaceLockReleased callback)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT (ctx, FALSE);
|
|
|
|
ctx->global_interface_lock_released = callback;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/**
|
|
* libhal_ctx_set_interface_lock_acquired:
|
|
* @ctx: the context for the connection to hald
|
|
* @callback: the callback
|
|
*
|
|
* Set the callback for when an interface lock is acquired.
|
|
*
|
|
* Returns: TRUE if callback was successfully set, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ctx_set_interface_lock_acquired (LibHalContext *ctx, LibHalInterfaceLockAcquired callback)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT (ctx, FALSE);
|
|
|
|
ctx->interface_lock_acquired = callback;
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* libhal_ctx_set_interface_lock_released:
|
|
* @ctx: the context for the connection to hald
|
|
* @callback: the callback
|
|
*
|
|
* Set the callback for when an interface lock is released.
|
|
*
|
|
* Returns: TRUE if callback was successfully set, FALSE otherwise
|
|
*/
|
|
dbus_bool_t
|
|
libhal_ctx_set_interface_lock_released (LibHalContext *ctx, LibHalInterfaceLockReleased callback)
|
|
{
|
|
LIBHAL_CHECK_LIBHALCONTEXT (ctx, FALSE);
|
|
|
|
ctx->interface_lock_released = callback;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* libhal_device_is_locked_by_others:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique id of device
|
|
* @interface: the intername name to check
|
|
* @error: pointer to an initialized dbus error object for returning errors or NULL
|
|
*
|
|
* Determines whether a determines other processes than the caller holds a lock on the given device.
|
|
*
|
|
* Returns: If another process is holding a lock on the device
|
|
**/
|
|
dbus_bool_t
|
|
libhal_device_is_locked_by_others (LibHalContext *ctx,
|
|
const char *udi,
|
|
const char *interface,
|
|
DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessageIter iter;
|
|
DBusMessage *reply;
|
|
DBusMessageIter reply_iter;
|
|
dbus_bool_t value;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, TRUE);
|
|
LIBHAL_CHECK_UDI_VALID(udi, TRUE);
|
|
LIBHAL_CHECK_PARAM_VALID(interface, "*interface", TRUE);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"IsLockedByOthers");
|
|
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return TRUE;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface);
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return TRUE;
|
|
}
|
|
if (reply == NULL)
|
|
return TRUE;
|
|
|
|
/* now analyze reply */
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
|
|
dbus_message_unref (reply);
|
|
return TRUE;
|
|
}
|
|
dbus_message_iter_get_basic (&reply_iter, &value);
|
|
dbus_message_unref (reply);
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* libhal_device_is_caller_privileged:
|
|
* @ctx: the context for the connection to hald
|
|
* @udi: the Unique id of device
|
|
* @action: the action to check for
|
|
* @caller: the caller to check for
|
|
* @error: pointer to an initialized dbus error object for returning errors
|
|
*
|
|
* Determines if a given caller have a given privilege on a given
|
|
* device. Will always error out if HAL is not built with PolicyKit
|
|
* support.
|
|
*
|
|
* Returns: The textual reply from PolicyKit. See the #PolicyKitResult
|
|
* enumeration in the PolicyKit documentation for details. The caller
|
|
* is responsible for freeing this string with the function
|
|
* libhal_free_string().
|
|
**/
|
|
char*
|
|
libhal_device_is_caller_privileged (LibHalContext *ctx,
|
|
const char *udi,
|
|
const char *action,
|
|
const char *caller,
|
|
DBusError *error)
|
|
{
|
|
DBusMessage *message;
|
|
DBusMessageIter iter;
|
|
DBusMessage *reply;
|
|
DBusMessageIter reply_iter;
|
|
char *dbus_str;
|
|
char *value;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
|
|
LIBHAL_CHECK_UDI_VALID(udi, NULL);
|
|
LIBHAL_CHECK_PARAM_VALID(action, "*action", NULL);
|
|
LIBHAL_CHECK_PARAM_VALID(caller, "*caller", NULL);
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
udi,
|
|
"org.freedesktop.Hal.Device",
|
|
"IsCallerPrivileged");
|
|
|
|
if (message == NULL) {
|
|
fprintf (stderr,
|
|
"%s %d : Couldn't allocate D-BUS message\n",
|
|
__FILE__, __LINE__);
|
|
return NULL;
|
|
}
|
|
|
|
dbus_message_iter_init_append (message, &iter);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &action);
|
|
dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &caller);
|
|
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection,
|
|
message, -1,
|
|
error);
|
|
|
|
dbus_message_unref (message);
|
|
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
return NULL;
|
|
}
|
|
if (reply == NULL)
|
|
return NULL;
|
|
|
|
/* now analyze reply */
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_STRING) {
|
|
dbus_message_unref (reply);
|
|
return NULL;
|
|
}
|
|
dbus_message_iter_get_basic (&reply_iter, &dbus_str);
|
|
value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
|
|
if (value == NULL) {
|
|
fprintf (stderr, "%s %d : error allocating memory\n", __FILE__, __LINE__);
|
|
}
|
|
dbus_message_unref (reply);
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* libhal_get_all_devices_with_properties:
|
|
* @out_num_devices: Return location for number of devices
|
|
* @out_udi: Return location for array of of udi's. Caller should free this with libhal_free_string_array() when done with it.
|
|
* @out_properties: Return location for array of #LibHalPropertySet objects. Caller should free each one of them with libhal_free_property_set() when done with it
|
|
* @error: Return location for error
|
|
*
|
|
* Get all devices in the hal database as well as all properties for each device.
|
|
*
|
|
* Return: %TRUE if success; %FALSE and @error will be set.
|
|
**/
|
|
dbus_bool_t libhal_get_all_devices_with_properties (LibHalContext *ctx,
|
|
int *out_num_devices,
|
|
char ***out_udi,
|
|
LibHalPropertySet ***out_properties,
|
|
DBusError *error)
|
|
{
|
|
|
|
DBusMessage *message;
|
|
DBusMessage *reply;
|
|
DBusMessageIter iter_array, reply_iter;
|
|
DBusError _error;
|
|
char **udi_array;
|
|
char **_udi_array;
|
|
LibHalPropertySet **prop_array;
|
|
LibHalPropertySet **_prop_array;
|
|
size_t count;
|
|
unsigned int n;
|
|
|
|
LIBHAL_CHECK_LIBHALCONTEXT (ctx, FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID (out_num_devices, "*out_num_devices",FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID (out_udi, "***out_udi", FALSE);
|
|
LIBHAL_CHECK_PARAM_VALID (out_properties, "***out_properties", FALSE);
|
|
|
|
*out_num_devices = 0;
|
|
*out_udi = NULL;
|
|
*out_properties = NULL;
|
|
|
|
count = 0;
|
|
udi_array = NULL;
|
|
prop_array = NULL;
|
|
|
|
message = dbus_message_new_method_call ("org.freedesktop.Hal",
|
|
"/org/freedesktop/Hal/Manager",
|
|
"org.freedesktop.Hal.Manager",
|
|
"GetAllDevicesWithProperties");
|
|
if (message == NULL) {
|
|
fprintf (stderr, "%s %d : Could not allocate D-BUS message\n", __FILE__, __LINE__);
|
|
goto fail;
|
|
}
|
|
|
|
dbus_error_init (&_error);
|
|
reply = dbus_connection_send_with_reply_and_block (ctx->connection, message, -1, &_error);
|
|
|
|
dbus_move_error (&_error, error);
|
|
if (error != NULL && dbus_error_is_set (error)) {
|
|
dbus_message_unref (message);
|
|
goto fail;
|
|
}
|
|
if (reply == NULL) {
|
|
dbus_message_unref (message);
|
|
goto fail;
|
|
}
|
|
|
|
/* now analyze reply */
|
|
dbus_message_iter_init (reply, &reply_iter);
|
|
|
|
if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
|
|
fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__);
|
|
goto fail;
|
|
}
|
|
|
|
dbus_message_iter_recurse (&reply_iter, &iter_array);
|
|
|
|
#define _BLOCK_SIZE 32
|
|
|
|
udi_array = (char **) malloc (sizeof (char*) * _BLOCK_SIZE);
|
|
if (udi_array == NULL)
|
|
goto fail;
|
|
|
|
prop_array = (LibHalPropertySet **) malloc (sizeof (void*) * _BLOCK_SIZE);
|
|
if (prop_array == NULL)
|
|
goto fail;
|
|
|
|
while (dbus_message_iter_get_arg_type (&iter_array) == DBUS_TYPE_STRUCT) {
|
|
DBusMessageIter iter_struct;
|
|
const char *value;
|
|
LibHalPropertySet *pset;
|
|
char *udi;
|
|
|
|
if ((count % _BLOCK_SIZE) == 0 && count > 0) {
|
|
_udi_array = (char **) realloc (udi_array, sizeof (char*) * (count + _BLOCK_SIZE));
|
|
_prop_array = (LibHalPropertySet **) realloc (prop_array, sizeof (void*) * (count+_BLOCK_SIZE));
|
|
if (_udi_array == NULL || _prop_array == NULL)
|
|
goto fail;
|
|
udi_array = _udi_array;
|
|
prop_array = _prop_array;
|
|
}
|
|
|
|
dbus_message_iter_recurse (&iter_array, &iter_struct);
|
|
|
|
dbus_message_iter_get_basic (&iter_struct, &value);
|
|
udi = strdup (value);
|
|
if (udi == NULL)
|
|
goto fail;
|
|
|
|
dbus_message_iter_next(&iter_struct);
|
|
|
|
pset = get_property_set (&iter_struct);
|
|
|
|
udi_array[count] = udi;
|
|
prop_array[count] = pset;
|
|
count++;
|
|
|
|
dbus_message_iter_next (&iter_array);
|
|
}
|
|
|
|
if ((count % _BLOCK_SIZE) == 0 && count > 0) {
|
|
_udi_array = (char **) realloc (udi_array, sizeof (char*) * (count + _BLOCK_SIZE));
|
|
_prop_array = (LibHalPropertySet **) realloc (prop_array, sizeof (void*) * (count + _BLOCK_SIZE));
|
|
if (_udi_array == NULL || _prop_array == NULL)
|
|
goto fail;
|
|
udi_array = _udi_array;
|
|
prop_array = _prop_array;
|
|
}
|
|
udi_array[count] = NULL;
|
|
prop_array[count] = NULL;
|
|
|
|
*out_num_devices = count;
|
|
*out_udi = udi_array;
|
|
*out_properties = prop_array;
|
|
|
|
dbus_message_unref (reply);
|
|
dbus_message_unref (message);
|
|
|
|
return TRUE;
|
|
|
|
fail:
|
|
if (udi_array != NULL) {
|
|
for (n = 0; n < count; n++) {
|
|
free (udi_array[n]);
|
|
}
|
|
free (udi_array);
|
|
}
|
|
|
|
if (prop_array != NULL) {
|
|
for (n = 0; n < count; n++) {
|
|
free (prop_array[n]);
|
|
}
|
|
free (prop_array);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|