#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.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
# 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
#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)
#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);
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;
}
}
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;
}
void
libhal_free_string (char *str)
{
if (str != NULL) {
free (str);
str = NULL;
}
}
struct LibHalPropertySet_s {
unsigned int num_properties;
LibHalProperty *properties_head;
};
struct LibHalProperty_s {
LibHalPropertyType type;
char *key;
union {
char *str_value;
dbus_int32_t int_value;
dbus_uint64_t uint64_value;
double double_value;
dbus_bool_t bool_value;
char **strlist_value;
} v;
LibHalProperty *next;
};
struct LibHalContext_s {
DBusConnection *connection;
dbus_bool_t is_initialized;
dbus_bool_t is_shutdown;
dbus_bool_t cache_enabled;
dbus_bool_t is_direct;
LibHalDeviceAdded device_added;
LibHalDeviceRemoved device_removed;
LibHalDeviceNewCapability device_new_capability;
LibHalDeviceLostCapability device_lost_capability;
LibHalDevicePropertyModified device_property_modified;
LibHalDeviceCondition device_condition;
void *user_data;
};
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;
}
void*
libhal_ctx_get_user_data(LibHalContext *ctx)
{
LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
return ctx->user_data;
}
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:
break;
}
return TRUE;
}
LibHalPropertySet *
libhal_device_get_all_properties (LibHalContext *ctx, const char *udi, DBusError *error)
{
DBusMessage *message;
DBusMessage *reply;
DBusMessageIter reply_iter;
DBusMessageIter dict_iter;
LibHalPropertySet *result;
LibHalProperty *p_last;
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_move_error (&_error, error);
if (error != NULL && dbus_error_is_set (error)) {
fprintf (stderr,
"%s %d : %s\n",
__FILE__, __LINE__, error->message);
dbus_message_unref (message);
return NULL;
}
if (reply == NULL) {
dbus_message_unref (message);
return NULL;
}
dbus_message_iter_init (reply, &reply_iter);
result = malloc (sizeof (LibHalPropertySet));
if (result == NULL)
goto oom;
result->properties_head = NULL;
result->num_properties = 0;
if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY &&
dbus_message_iter_get_element_type (&reply_iter) != DBUS_TYPE_DICT_ENTRY) {
fprintf (stderr, "%s %d : error, expecting an array of dict entries\n",
__FILE__, __LINE__);
dbus_message_unref (message);
dbus_message_unref (reply);
return NULL;
}
dbus_message_iter_recurse (&reply_iter, &dict_iter);
p_last = NULL;
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->next = NULL;
if (result->num_properties == 0)
result->properties_head = p;
if (p_last != NULL)
p_last->next = p;
p_last = p;
p->key = strdup (key);
if (p->key == NULL)
goto oom;
dbus_message_iter_next (&dict_entry_iter);
dbus_message_iter_recurse (&dict_entry_iter, &var_iter);
p->type = dbus_message_iter_get_arg_type (&var_iter);
result->num_properties++;
if(!libhal_property_fill_value_from_variant (p, &var_iter))
goto oom;
dbus_message_iter_next (&dict_iter);
}
dbus_message_unref (message);
dbus_message_unref (reply);
return result;
oom:
fprintf (stderr,
"%s %d : error allocating memory\n",
__FILE__, __LINE__);
return NULL;
}
void
libhal_free_property_set (LibHalPropertySet * set)
{
LibHalProperty *p;
LibHalProperty *q;
if (set == NULL)
return;
for (p = set->properties_head; p != NULL; p = q) {
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);
q = p->next;
free (p);
}
free (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_head; p != NULL; p = p->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);
for (p = set->properties_head; p != NULL; p = p->next)
if (strcmp (key, p->key) == 0)
return p;
return NULL;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
void
libhal_psi_init (LibHalPropertySetIterator * iter, LibHalPropertySet * set)
{
if (set == NULL)
return;
iter->set = set;
iter->idx = 0;
iter->cur_prop = set->properties_head;
}
dbus_bool_t
libhal_psi_has_more (LibHalPropertySetIterator * iter)
{
return iter->idx < iter->set->num_properties;
}
void
libhal_psi_next (LibHalPropertySetIterator * iter)
{
iter->idx++;
iter->cur_prop = iter->cur_prop->next;
}
LibHalPropertyType
libhal_psi_get_type (LibHalPropertySetIterator * iter)
{
return iter->cur_prop->type;
}
char *
libhal_psi_get_key (LibHalPropertySetIterator * iter)
{
return iter->cur_prop->key;
}
char *
libhal_psi_get_string (LibHalPropertySetIterator * iter)
{
return iter->cur_prop->v.str_value;
}
dbus_int32_t
libhal_psi_get_int (LibHalPropertySetIterator * iter)
{
return iter->cur_prop->v.int_value;
}
dbus_uint64_t
libhal_psi_get_uint64 (LibHalPropertySetIterator * iter)
{
return iter->cur_prop->v.uint64_value;
}
double
libhal_psi_get_double (LibHalPropertySetIterator * iter)
{
return iter->cur_prop->v.double_value;
}
dbus_bool_t
libhal_psi_get_bool (LibHalPropertySetIterator * iter)
{
return iter->cur_prop->v.bool_value;
}
char **
libhal_psi_get_strlist (LibHalPropertySetIterator * iter)
{
return iter->cur_prop->v.strlist_value;
}
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);
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.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", "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;
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
static dbus_bool_t libhal_already_initialized_once = FALSE;
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;
}
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;
}
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);
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;
}
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;
}
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;
}
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);
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;
}
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);
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;
}
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);
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;
}
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);
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;
}
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);
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;
}
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);
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:
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;
}
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);
}
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);
}
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);
}
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);
}
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);
}
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,
NULL, 0, 0, 0.0f, FALSE, error);
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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);
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;
}
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;
}
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;
}
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);
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;
}
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);
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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_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;
}
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;
}
LibHalContext *
libhal_ctx_new (void)
{
LibHalContext *ctx;
if (!libhal_already_initialized_once) {
bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
libhal_already_initialized_once = TRUE;
}
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;
}
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;
}
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;
}
DBusConnection *
libhal_ctx_get_dbus_connection (LibHalContext *ctx)
{
LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
return ctx->connection;
}
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;
}
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;
}
ctx->is_initialized = TRUE;
ctx->is_direct = TRUE;
out:
return ctx;
}
dbus_bool_t
libhal_ctx_shutdown (LibHalContext *ctx, DBusError *error)
{
DBusError myerror;
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
if (ctx->is_direct) {
} 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);
}
dbus_connection_remove_filter (ctx->connection, filter_func, ctx);
}
ctx->is_initialized = FALSE;
return TRUE;
}
dbus_bool_t
libhal_ctx_free (LibHalContext *ctx)
{
free (ctx);
return TRUE;
}
dbus_bool_t
libhal_ctx_set_device_added (LibHalContext *ctx, LibHalDeviceAdded callback)
{
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
ctx->device_added = callback;
return TRUE;
}
dbus_bool_t
libhal_ctx_set_device_removed (LibHalContext *ctx, LibHalDeviceRemoved callback)
{
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
ctx->device_removed = callback;
return TRUE;
}
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;
}
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;
}
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;
}
dbus_bool_t
libhal_ctx_set_device_condition (LibHalContext *ctx, LibHalDeviceCondition callback)
{
LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
ctx->device_condition = callback;
return TRUE;
}
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;
}
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;
}
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;
}
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;
}
dbus_bool_t
libhal_device_addon_is_ready (LibHalContext *ctx, const char *udi, 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);
message = dbus_message_new_method_call ("org.freedesktop.Hal",
udi,
"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);
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;
}
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;
};
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", );
LIBHAL_CHECK_PARAM_VALID(elem, "*elem", );
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;
}
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
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);
}