/***************************************************************************
* CVSID: $Id$
*
* device.c : HalDevice methods
*
* Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
* Copyright (C) 2004 Novell, Inc.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
**************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <string.h>
#include "hald.h"
#include "device.h"
#include "hald_marshal.h"
#include "logger.h"
#include "hald_runner.h"
static GObjectClass *parent_class;
enum {
PROPERTY_CHANGED,
CAPABILITY_ADDED,
CALLOUTS_FINISHED,
CANCELLED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
#ifdef HALD_MEMLEAK_DBG
int dbg_hal_device_object_delta = 0;
#endif
static void
hal_device_finalize (GObject *obj)
{
HalDevice *device = HAL_DEVICE (obj);
runner_device_finalized (device);
#ifdef HALD_MEMLEAK_DBG
dbg_hal_device_object_delta--;
printf ("************* in finalize for udi=%s\n", device->udi);
#endif
g_slist_foreach (device->properties, (GFunc) hal_property_free, NULL);
g_slist_free (device->properties);
g_free (device->udi);
if (parent_class->finalize)
parent_class->finalize (obj);
}
static void
hal_device_class_init (HalDeviceClass *klass)
{
GObjectClass *obj_class = (GObjectClass *) klass;
parent_class = g_type_class_peek_parent (klass);
obj_class->finalize = hal_device_finalize;
signals[PROPERTY_CHANGED] =
g_signal_new ("property_changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (HalDeviceClass,
property_changed),
NULL, NULL,
hald_marshal_VOID__STRING_BOOL_BOOL,
G_TYPE_NONE, 3,
G_TYPE_STRING,
G_TYPE_BOOLEAN,
G_TYPE_BOOLEAN);
signals[CAPABILITY_ADDED] =
g_signal_new ("capability_added",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (HalDeviceClass,
capability_added),
NULL, NULL,
hald_marshal_VOID__STRING,
G_TYPE_NONE, 1,
G_TYPE_STRING);
signals[CALLOUTS_FINISHED] =
g_signal_new ("callouts_finished",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (HalDeviceClass,
callouts_finished),
NULL, NULL,
hald_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[CANCELLED] =
g_signal_new ("cancelled",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (HalDeviceClass,
cancelled),
NULL, NULL,
hald_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
hal_device_init (HalDevice *device)
{
static int temp_device_counter = 0;
device->udi = g_strdup_printf ("/org/freedesktop/Hal/devices/temp/%d",
temp_device_counter++);
device->num_addons = 0;
device->num_addons_ready = 0;
}
GType
hal_device_get_type (void)
{
static GType type = 0;
if (!type) {
static GTypeInfo type_info = {
sizeof (HalDeviceClass),
NULL, NULL,
(GClassInitFunc) hal_device_class_init,
NULL, NULL,
sizeof (HalDevice),
0,
(GInstanceInitFunc) hal_device_init,
NULL
};
type = g_type_register_static (G_TYPE_OBJECT,
"HalDevice",
&type_info,
0);
}
return type;
}
HalDevice *
hal_device_new (void)
{
HalDevice *device;
device = g_object_new (HAL_TYPE_DEVICE, NULL, NULL);
#ifdef HALD_MEMLEAK_DBG
dbg_hal_device_object_delta++;
#endif
return device;
}
/** Merge all properties from source where the key starts with
* source_namespace and put them onto target replacing source_namespace
* with target_namespace
*
* @param target Device to put properties onto
* @param source Device to retrieve properties from
* @param target_namespace Replace source namespace with this namespace
* @param source_namespace Source namespace that property keys must match
*/
void
hal_device_merge_with_rewrite (HalDevice *target,
HalDevice *source,
const char *target_namespace,
const char *source_namespace)
{
GSList *iter;
size_t source_ns_len;
source_ns_len = strlen (source_namespace);
/* doesn't handle info.capabilities */
/* device_property_atomic_update_begin (); */
for (iter = source->properties; iter != NULL; iter = iter->next) {
HalProperty *p = iter->data;
int type;
const char *key;
int target_type;
gchar *target_key;
key = hal_property_get_key (p);
/* only care about properties that match source namespace */
if (strncmp(key, source_namespace, source_ns_len) != 0)
continue;
target_key = g_strdup_printf("%s%s", target_namespace,
key+source_ns_len);
type = hal_property_get_type (p);
/* only remove target if it exists with a different type */
target_type = hal_device_property_get_type (target, key);
if (target_type != HAL_PROPERTY_TYPE_INVALID && target_type != type)
hal_device_property_remove (target, key);
switch (type) {
case HAL_PROPERTY_TYPE_STRING:
hal_device_property_set_string (
target, target_key,
hal_property_get_string (p));
break;
case HAL_PROPERTY_TYPE_INT32:
hal_device_property_set_int (
target, target_key,
hal_property_get_int (p));
break;
case HAL_PROPERTY_TYPE_UINT64:
hal_device_property_set_uint64 (
target, target_key,
hal_property_get_uint64 (p));
break;
case HAL_PROPERTY_TYPE_BOOLEAN:
hal_device_property_set_bool (
target, target_key,
hal_property_get_bool (p));
break;
case HAL_PROPERTY_TYPE_DOUBLE:
hal_device_property_set_double (
target, target_key,
hal_property_get_double (p));
break;
default:
HAL_WARNING (("Unknown property type %d", type));
break;
}
g_free (target_key);
}
/* device_property_atomic_update_end (); */
}
void
hal_device_merge (HalDevice *target, HalDevice *source)
{
GSList *iter;
GSList *caps;
/* device_property_atomic_update_begin (); */
for (iter = source->properties; iter != NULL; iter = iter->next) {
HalProperty *p = iter->data;
int type;
const char *key;
int target_type;
key = hal_property_get_key (p);
type = hal_property_get_type (p);
/* handle info.capabilities in a special way */
if (strcmp (key, "info.capabilities") == 0)
continue;
/* only remove target if it exists with a different type */
target_type = hal_device_property_get_type (target, key);
if (target_type != HAL_PROPERTY_TYPE_INVALID && target_type != type)
hal_device_property_remove (target, key);
switch (type) {
case HAL_PROPERTY_TYPE_STRING:
hal_device_property_set_string (
target, key,
hal_property_get_string (p));
break;
case HAL_PROPERTY_TYPE_INT32:
hal_device_property_set_int (
target, key,
hal_property_get_int (p));
break;
case HAL_PROPERTY_TYPE_UINT64:
hal_device_property_set_uint64 (
target, key,
hal_property_get_uint64 (p));
break;
case HAL_PROPERTY_TYPE_BOOLEAN:
hal_device_property_set_bool (
target, key,
hal_property_get_bool (p));
break;
case HAL_PROPERTY_TYPE_DOUBLE:
hal_device_property_set_double (
target, key,
hal_property_get_double (p));
break;
default:
HAL_WARNING (("Unknown property type %d", type));
break;
}
}
/* device_property_atomic_update_end (); */
caps = hal_device_property_get_strlist (source, "info.capabilities");
for (iter = caps; iter != NULL; iter = iter->next) {
if (!hal_device_has_capability (target, iter->data))
hal_device_add_capability (target, iter->data);
}
}
gboolean
hal_device_matches (HalDevice *device1, HalDevice *device2,
const char *namespace)
{
int len;
GSList *iter;
len = strlen (namespace);
for (iter = device1->properties; iter != NULL; iter = iter->next) {
HalProperty *p;
const char *key;
int type;
p = (HalProperty *) iter->data;
key = hal_property_get_key (p);
type = hal_property_get_type (p);
if (strncmp (key, namespace, len) != 0)
continue;
if (!hal_device_has_property (device2, key))
return FALSE;
switch (type) {
case HAL_PROPERTY_TYPE_STRING:
if (strcmp (hal_property_get_string (p),
hal_device_property_get_string (device2,
key)) != 0)
return FALSE;
break;
case HAL_PROPERTY_TYPE_INT32:
if (hal_property_get_int (p) !=
hal_device_property_get_int (device2, key))
return FALSE;
break;
case HAL_PROPERTY_TYPE_UINT64:
if (hal_property_get_uint64 (p) !=
hal_device_property_get_uint64 (device2, key))
return FALSE;
break;
case HAL_PROPERTY_TYPE_BOOLEAN:
if (hal_property_get_bool (p) !=
hal_device_property_get_bool (device2, key))
return FALSE;
break;
case HAL_PROPERTY_TYPE_DOUBLE:
if (hal_property_get_double (p) !=
hal_device_property_get_double (device2, key))
return FALSE;
break;
default:
HAL_WARNING (("Unknown property type %d", type));
break;
}
}
return TRUE;
}
const char *
hal_device_get_udi (HalDevice *device)
{
return device->udi;
}
void
hal_device_set_udi (HalDevice *device, const char *udi)
{
if (device->udi != NULL)
g_free (device->udi);
device->udi = g_strdup (udi);
}
void
hal_device_add_capability (HalDevice *device, const char *capability)
{
if (hal_device_property_strlist_add (device, "info.capabilities", capability))
g_signal_emit (device, signals[CAPABILITY_ADDED], 0, capability);
}
gboolean
hal_device_has_capability (HalDevice *device, const char *capability)
{
GSList *caps;
GSList *iter;
gboolean matched = FALSE;
caps = hal_device_property_get_strlist (device, "info.capabilities");
if (caps == NULL)
return FALSE;
for (iter = caps; iter != NULL; iter = iter->next) {
if (strcmp (iter->data, capability) == 0) {
matched = TRUE;
break;
}
}
return matched;
}
gboolean
hal_device_has_property (HalDevice *device, const char *key)
{
g_return_val_if_fail (device != NULL, FALSE);
g_return_val_if_fail (key != NULL, FALSE);
return hal_device_property_find (device, key) != NULL;
}
int
hal_device_num_properties (HalDevice *device)
{
g_return_val_if_fail (device != NULL, -1);
return g_slist_length (device->properties);
}
HalProperty *
hal_device_property_find (HalDevice *device, const char *key)
{
GSList *iter;
g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (key != NULL, NULL);
for (iter = device->properties; iter != NULL; iter = iter->next) {
HalProperty *p = iter->data;
if (strcmp (hal_property_get_key (p), key) == 0)
return p;
}
return NULL;
}
char *
hal_device_property_to_string (HalDevice *device, const char *key)
{
HalProperty *prop;
prop = hal_device_property_find (device, key);
if (!prop)
return NULL;
return hal_property_to_string (prop);
}
void
hal_device_property_foreach (HalDevice *device,
HalDevicePropertyForeachFn callback,
gpointer user_data)
{
GSList *iter;
g_return_if_fail (device != NULL);
g_return_if_fail (callback != NULL);
for (iter = device->properties; iter != NULL; iter = iter->next) {
HalProperty *p = iter->data;
gboolean cont;
cont = callback (device, p, user_data);
if (cont == FALSE)
return;
}
}
int
hal_device_property_get_type (HalDevice *device, const char *key)
{
HalProperty *prop;
g_return_val_if_fail (device != NULL, HAL_PROPERTY_TYPE_INVALID);
g_return_val_if_fail (key != NULL, HAL_PROPERTY_TYPE_INVALID);
prop = hal_device_property_find (device, key);
if (prop != NULL)
return hal_property_get_type (prop);
else
return HAL_PROPERTY_TYPE_INVALID;
}
const char *
hal_device_property_get_string (HalDevice *device, const char *key)
{
HalProperty *prop;
g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (key != NULL, NULL);
prop = hal_device_property_find (device, key);
if (prop != NULL)
return hal_property_get_string (prop);
else
return NULL;
}
const char *
hal_device_property_get_as_string (HalDevice *device, const char *key, char *buf, size_t bufsize)
{
HalProperty *prop;
g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (buf != NULL, NULL);
prop = hal_device_property_find (device, key);
if (prop != NULL) {
switch (hal_property_get_type (prop)) {
case HAL_PROPERTY_TYPE_STRING:
strncpy (buf, hal_property_get_string (prop), bufsize);
break;
case HAL_PROPERTY_TYPE_INT32:
snprintf (buf, bufsize, "%d", hal_property_get_int (prop));
break;
case HAL_PROPERTY_TYPE_UINT64:
snprintf (buf, bufsize, "%llu", (long long unsigned int) hal_property_get_uint64 (prop));
break;
case HAL_PROPERTY_TYPE_DOUBLE:
snprintf (buf, bufsize, "%f", hal_property_get_double (prop));
break;
case HAL_PROPERTY_TYPE_BOOLEAN:
strncpy (buf, hal_property_get_bool (prop) ? "true" : "false", bufsize);
break;
case HAL_PROPERTY_TYPE_STRLIST:
/* print out as "\tval1\tval2\val3\t" */
{
GSList *iter;
guint i;
if (bufsize > 0)
buf[0] = '\t';
i = 1;
for (iter = hal_property_get_strlist (prop);
iter != NULL && i < bufsize;
iter = g_slist_next (iter)) {
guint len;
const char *str;
str = (const char *) iter->data;
len = strlen (str);
strncpy (buf + i, str, bufsize - i);
i += len;
if (i < bufsize) {
buf[i] = '\t';
i++;
}
}
}
break;
}
return buf;
} else {
buf[0] = '\0';
return NULL;
}
}
dbus_int32_t
hal_device_property_get_int (HalDevice *device, const char *key)
{
HalProperty *prop;
g_return_val_if_fail (device != NULL, -1);
g_return_val_if_fail (key != NULL, -1);
prop = hal_device_property_find (device, key);
if (prop != NULL)
return hal_property_get_int (prop);
else
return -1;
}
dbus_uint64_t
hal_device_property_get_uint64 (HalDevice *device, const char *key)
{
HalProperty *prop;
g_return_val_if_fail (device != NULL, -1);
g_return_val_if_fail (key != NULL, -1);
prop = hal_device_property_find (device, key);
if (prop != NULL)
return hal_property_get_uint64 (prop);
else
return -1;
}
dbus_bool_t
hal_device_property_get_bool (HalDevice *device, const char *key)
{
HalProperty *prop;
g_return_val_if_fail (device != NULL, FALSE);
g_return_val_if_fail (key != NULL, FALSE);
prop = hal_device_property_find (device, key);
if (prop != NULL)
return hal_property_get_bool (prop);
else
return FALSE;
}
double
hal_device_property_get_double (HalDevice *device, const char *key)
{
HalProperty *prop;
g_return_val_if_fail (device != NULL, -1.0);
g_return_val_if_fail (key != NULL, -1.0);
prop = hal_device_property_find (device, key);
if (prop != NULL)
return hal_property_get_double (prop);
else
return -1.0;
}
gboolean
hal_device_property_set_string (HalDevice *device, const char *key,
const char *value)
{
HalProperty *prop;
/* check if property already exists */
prop = hal_device_property_find (device, key);
if (prop != NULL) {
if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRING)
return FALSE;
/* don't bother setting the same value */
if (value != NULL &&
strcmp (hal_property_get_string (prop), value) == 0)
return TRUE;
hal_property_set_string (prop, value);
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, FALSE);
} else {
prop = hal_property_new_string (key, value);
device->properties = g_slist_prepend (device->properties, prop);
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, TRUE);
}
return TRUE;
}
gboolean
hal_device_property_set_int (HalDevice *device, const char *key,
dbus_int32_t value)
{
HalProperty *prop;
/* check if property already exists */
prop = hal_device_property_find (device, key);
if (prop != NULL) {
if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_INT32)
return FALSE;
/* don't bother setting the same value */
if (hal_property_get_int (prop) == value)
return TRUE;
hal_property_set_int (prop, value);
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, FALSE);
} else {
prop = hal_property_new_int (key, value);
device->properties = g_slist_prepend (device->properties, prop);
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, TRUE);
}
return TRUE;
}
gboolean
hal_device_property_set_uint64 (HalDevice *device, const char *key,
dbus_uint64_t value)
{
HalProperty *prop;
/* check if property already exists */
prop = hal_device_property_find (device, key);
if (prop != NULL) {
if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_UINT64)
return FALSE;
/* don't bother setting the same value */
if (hal_property_get_uint64 (prop) == value)
return TRUE;
hal_property_set_uint64 (prop, value);
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, FALSE);
} else {
prop = hal_property_new_uint64 (key, value);
device->properties = g_slist_prepend (device->properties, prop);
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, TRUE);
}
return TRUE;
}
gboolean
hal_device_property_set_bool (HalDevice *device, const char *key,
dbus_bool_t value)
{
HalProperty *prop;
/* check if property already exists */
prop = hal_device_property_find (device, key);
if (prop != NULL) {
if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_BOOLEAN)
return FALSE;
/* don't bother setting the same value */
if (hal_property_get_bool (prop) == value)
return TRUE;
hal_property_set_bool (prop, value);
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, FALSE);
} else {
prop = hal_property_new_bool (key, value);
device->properties = g_slist_prepend (device->properties, prop);
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, TRUE);
}
return TRUE;
}
gboolean
hal_device_property_set_double (HalDevice *device, const char *key,
double value)
{
HalProperty *prop;
/* check if property already exists */
prop = hal_device_property_find (device, key);
if (prop != NULL) {
if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_DOUBLE)
return FALSE;
/* don't bother setting the same value */
if (hal_property_get_double (prop) == value)
return TRUE;
hal_property_set_double (prop, value);
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, FALSE);
} else {
prop = hal_property_new_double (key, value);
device->properties = g_slist_prepend (device->properties, prop);
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, TRUE);
}
return TRUE;
}
gboolean
hal_device_copy_property (HalDevice *from_device, const char *from, HalDevice *to_device, const char *to)
{
gboolean rc;
rc = FALSE;
if (hal_device_has_property (from_device, from)) {
switch (hal_device_property_get_type (from_device, from)) {
case HAL_PROPERTY_TYPE_STRING:
rc = hal_device_property_set_string (
to_device, to, hal_device_property_get_string (from_device, from));
break;
case HAL_PROPERTY_TYPE_INT32:
rc = hal_device_property_set_int (
to_device, to, hal_device_property_get_int (from_device, from));
break;
case HAL_PROPERTY_TYPE_UINT64:
rc = hal_device_property_set_uint64 (
to_device, to, hal_device_property_get_uint64 (from_device, from));
break;
case HAL_PROPERTY_TYPE_BOOLEAN:
rc = hal_device_property_set_bool (
to_device, to, hal_device_property_get_bool (from_device, from));
break;
case HAL_PROPERTY_TYPE_DOUBLE:
rc = hal_device_property_set_double (
to_device, to, hal_device_property_get_double (from_device, from));
break;
}
}
return rc;
}
gboolean
hal_device_property_remove (HalDevice *device, const char *key)
{
HalProperty *prop;
prop = hal_device_property_find (device, key);
if (prop == NULL)
return FALSE;
device->properties = g_slist_remove (device->properties, prop);
hal_property_free (prop);
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, TRUE, FALSE);
return TRUE;
}
gboolean
hal_device_property_set_attribute (HalDevice *device,
const char *key,
enum PropertyAttribute attr,
gboolean val)
{
HalProperty *prop;
prop = hal_device_property_find (device, key);
if (prop == NULL)
return FALSE;
return TRUE;
}
void
hal_device_print (HalDevice *device)
{
GSList *iter;
fprintf (stderr, "device udi = %s\n", hal_device_get_udi (device));
for (iter = device->properties; iter != NULL; iter = iter->next) {
HalProperty *p = iter->data;
int type;
const char *key;
key = hal_property_get_key (p);
type = hal_property_get_type (p);
switch (type) {
case HAL_PROPERTY_TYPE_STRING:
fprintf (stderr, " %s = '%s' (string)\n", key,
hal_property_get_string (p));
break;
case HAL_PROPERTY_TYPE_INT32:
fprintf (stderr, " %s = %d 0x%x (int)\n", key,
hal_property_get_int (p),
hal_property_get_int (p));
break;
case HAL_PROPERTY_TYPE_UINT64:
fprintf (stderr, " %s = %llu 0x%llx (uint64)\n", key,
(long long unsigned int) hal_property_get_uint64 (p),
(long long unsigned int) hal_property_get_uint64 (p));
break;
case HAL_PROPERTY_TYPE_DOUBLE:
fprintf (stderr, " %s = %g (double)\n", key,
hal_property_get_double (p));
break;
case HAL_PROPERTY_TYPE_BOOLEAN:
fprintf (stderr, " %s = %s (bool)\n", key,
(hal_property_get_bool (p) ? "true" :
"false"));
break;
default:
HAL_WARNING (("Unknown property type %d", type));
break;
}
}
fprintf (stderr, "\n");
}
typedef struct {
char *key;
HalDevice *device;
HalDeviceAsyncCallback callback;
gpointer user_data;
guint prop_signal_id;
guint timeout_id;
} AsyncMatchInfo;
static void
destroy_async_match_info (AsyncMatchInfo *ai)
{
g_free (ai->key);
g_signal_handler_disconnect (ai->device, ai->prop_signal_id);
g_source_remove (ai->timeout_id);
g_object_unref (ai->device);
g_free (ai);
}
static void
prop_changed_cb (HalDevice *device, const char *key,
gboolean removed, gboolean added, gpointer user_data)
{
AsyncMatchInfo *ai = user_data;
if (strcmp (key, ai->key) != 0)
return;
/* the property is no longer there */
if (removed)
goto cleanup;
ai->callback (ai->device, ai->user_data, TRUE);
cleanup:
destroy_async_match_info (ai);
}
static gboolean
async_wait_timeout (gpointer user_data)
{
AsyncMatchInfo *ai = (AsyncMatchInfo *) user_data;
ai->callback (ai->device, ai->user_data, FALSE);
destroy_async_match_info (ai);
return FALSE;
}
void
hal_device_async_wait_property (HalDevice *device,
const char *key,
HalDeviceAsyncCallback callback,
gpointer user_data,
int timeout)
{
HalProperty *prop;
AsyncMatchInfo *ai;
/* check if property already exists */
prop = hal_device_property_find (device, key);
if (prop != NULL || timeout==0) {
callback (device, user_data, prop != NULL);
return;
}
ai = g_new0 (AsyncMatchInfo, 1);
ai->device = g_object_ref (device);
ai->key = g_strdup (key);
ai->callback = callback;
ai->user_data = user_data;
ai->prop_signal_id = g_signal_connect (device, "property_changed",
G_CALLBACK (prop_changed_cb),
ai);
ai->timeout_id = g_timeout_add (timeout, async_wait_timeout, ai);
}
void
hal_device_callouts_finished (HalDevice *device)
{
g_signal_emit (device, signals[CALLOUTS_FINISHED], 0);
}
/** Used when giving up on a device, e.g. if no device file appeared
*/
void
hal_device_cancel (HalDevice *device)
{
HAL_INFO (("udi=%s", device->udi));
g_signal_emit (device, signals[CANCELLED], 0);
}
GSList *
hal_device_property_get_strlist (HalDevice *device,
const char *key)
{
HalProperty *prop;
g_return_val_if_fail (device != NULL, NULL);
g_return_val_if_fail (key != NULL, NULL);
prop = hal_device_property_find (device, key);
if (prop != NULL)
return hal_property_get_strlist (prop);
else
return NULL;
}
const char *
hal_device_property_get_strlist_elem (HalDevice *device,
const char *key,
guint index)
{
GSList *strlist;
GSList *i;
strlist = hal_device_property_get_strlist (device, key);
if (strlist == NULL)
return NULL;
i = g_slist_nth (strlist, index);
if (i == NULL)
return NULL;
return (const char *) i->data;
}
gboolean
hal_device_property_strlist_append (HalDevice *device,
const char *key,
const char *value)
{
HalProperty *prop;
/* check if property already exists */
prop = hal_device_property_find (device, key);
if (prop != NULL) {
if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST)
return FALSE;
hal_property_strlist_append (prop, value);
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, FALSE);
} else {
prop = hal_property_new_strlist (key);
hal_property_strlist_append (prop, value);
device->properties = g_slist_prepend (device->properties, prop);
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, TRUE);
}
return TRUE;
}
gboolean
hal_device_property_strlist_prepend (HalDevice *device,
const char *key,
const char *value)
{
HalProperty *prop;
/* check if property already exists */
prop = hal_device_property_find (device, key);
if (prop != NULL) {
if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST)
return FALSE;
hal_property_strlist_prepend (prop, value);
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, FALSE);
} else {
prop = hal_property_new_strlist (key);
hal_property_strlist_prepend (prop, value);
device->properties = g_slist_prepend (device->properties, prop);
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, TRUE);
}
return TRUE;
}
gboolean
hal_device_property_strlist_remove_elem (HalDevice *device,
const char *key,
guint index)
{
HalProperty *prop;
/* check if property already exists */
prop = hal_device_property_find (device, key);
if (prop == NULL)
return FALSE;
if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST)
return FALSE;
if (hal_property_strlist_remove_elem (prop, index)) {
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, FALSE);
return TRUE;
}
return FALSE;
}
gboolean
hal_device_property_strlist_clear (HalDevice *device,
const char *key)
{
HalProperty *prop;
/* check if property already exists */
prop = hal_device_property_find (device, key);
if (prop == NULL) {
prop = hal_property_new_strlist (key);
device->properties = g_slist_prepend (device->properties, prop);
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, TRUE);
return TRUE;
}
if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST)
return FALSE;
if (hal_property_strlist_clear (prop)) {
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, FALSE);
return TRUE;
}
return FALSE;
}
gboolean
hal_device_property_strlist_add (HalDevice *device,
const char *key,
const char *value)
{
HalProperty *prop;
gboolean res;
res = FALSE;
/* check if property already exists */
prop = hal_device_property_find (device, key);
if (prop != NULL) {
if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST)
goto out;
res = hal_property_strlist_add (prop, value);
if (res) {
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, FALSE);
}
} else {
prop = hal_property_new_strlist (key);
hal_property_strlist_prepend (prop, value);
device->properties = g_slist_prepend (device->properties, prop);
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, TRUE);
res = TRUE;
}
out:
return res;
}
gboolean
hal_device_property_strlist_remove (HalDevice *device,
const char *key,
const char *value)
{
HalProperty *prop;
/* check if property already exists */
prop = hal_device_property_find (device, key);
if (prop == NULL)
return FALSE;
if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST)
return FALSE;
if (hal_property_strlist_remove (prop, value)) {
g_signal_emit (device, signals[PROPERTY_CHANGED], 0,
key, FALSE, FALSE);
}
return TRUE;
}
gboolean
hal_device_property_strlist_is_empty (HalDevice *device,
const char *key)
{
GSList *strlist;
if ( hal_device_has_property (device, key)) {
strlist = hal_device_property_get_strlist (device, key);
if (strlist == NULL )
return TRUE;
if (g_slist_length (strlist) > 0)
return FALSE;
else
return TRUE;
}
return FALSE;
}
void
hal_device_inc_num_addons (HalDevice *device)
{
device->num_addons++;
}
gboolean
hal_device_inc_num_ready_addons (HalDevice *device)
{
if (hal_device_are_all_addons_ready (device)) {
HAL_ERROR (("In hal_device_inc_num_ready_addons for udi=%s but all addons are already ready!",
device->udi));
return FALSE;
}
device->num_addons_ready++;
return TRUE;
}
gboolean
hal_device_are_all_addons_ready (HalDevice *device)
{
if (device->num_addons_ready == device->num_addons) {
return TRUE;
} else {
return FALSE;
}
}