summaryrefslogtreecommitdiff
path: root/hald
diff options
context:
space:
mode:
authorDavid Zeuthen <david@fubar.dk>2003-11-15 01:14:52 +0000
committerDavid Zeuthen <david@fubar.dk>2003-11-15 01:14:52 +0000
commite892e576b75f3ab7d5f47117aacdf8c07f76da1a (patch)
tree5592bf63e9f50f27b0c1c7b160aec8e2d97d197e /hald
parentd0bd5f0f2b6b6c1b5602729fe0998767d0afef5e (diff)
Remove calls to free(); we are causing segfaults because of we are
interferring with D-BUS memory management (usb_compute_parent): Remove calls to free(); same reason (usb_probe): Call usb_compute_parents() (usb_hotplug): Remove calls to free(); same as above; compute parents for all USB devices every time a single device is added/removed (main): Sleep for one second before handling hotplug event to allow the kernel to update /proc/bus/usb/devices new file new file add device_info.[ch] Change signature of HalDevicePropertyChangeCallback with an added parameter to allow the callback handler to see if a device have been added Change to new signature of property_change_cb Don't print LOG_TRACE() Call di_search_and_merge() to handle .fdi files (agent_manager_commit_to_gdl): Call ds_gdl_add() (filter_func): Don't log entry on every method invocation (property_changed): Implement Use Product, Vendor, Category properties to display information, if available. Handle property changed; reloads device tree when a Parent property changes. Subscribe to signals org.freedesktop.Hal.Device interface to catch property changes Listen to property changes on device objects new directory new directory new directory new file new file new file new file
Diffstat (limited to 'hald')
-rw-r--r--hald/Makefile.am3
-rw-r--r--hald/device_info.c640
-rw-r--r--hald/device_info.h37
-rw-r--r--hald/device_store.c18
-rw-r--r--hald/device_store.h9
-rw-r--r--hald/logger.h4
-rw-r--r--hald/main.c80
7 files changed, 770 insertions, 21 deletions
diff --git a/hald/Makefile.am b/hald/Makefile.am
index 17fa9ac3..227e9fb1 100644
--- a/hald/Makefile.am
+++ b/hald/Makefile.am
@@ -11,7 +11,8 @@ bin_PROGRAMS = hald
hald_SOURCES = \
main.c \
logger.h \
- device_store.c device_store.h
+ device_store.c device_store.h \
+ device_info.c device_info.h
hald_LDADD = @PACKAGE_LIBS@
diff --git a/hald/device_info.c b/hald/device_info.c
new file mode 100644
index 00000000..402c8758
--- /dev/null
+++ b/hald/device_info.c
@@ -0,0 +1,640 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * device_store.c : Search for .fdi files and merge on match
+ *
+ * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
+ *
+ * Licensed under the Academic Free License version 2.0
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <expat.h>
+#include <assert.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+
+#include <libhal/libhal.h> /* for common defines etc. */
+
+#include "logger.h"
+#include "device_info.h"
+
+/**
+ * @defgroup DeviceInfo Device Info File Parsing
+ * @ingroup HalDaemon
+ * @brief Parsing of device info files
+ * @{
+ */
+
+
+/** Maximum nesting depth */
+#define MAX_DEPTH 32
+
+/** Maximum amount of CDATA */
+#define CDATA_BUF_SIZE 1024
+
+/** Max length of property key */
+#define MAX_KEY_SIZE 128
+
+/** Possible elements the parser can process */
+enum
+{
+ /** Not processing a known tag */
+ CURELEM_UNKNOWN = -1,
+
+ /** Processing a deviceinfo element */
+ CURELEM_DEVICE_INFO = 0,
+
+ /** Processing a device element */
+ CURELEM_DEVICE = 1,
+
+ /** Processing a match element */
+ CURELEM_MATCH = 2,
+
+ /** Processing a merge element */
+ CURELEM_MERGE = 3,
+};
+
+/** Parsing Context
+ */
+typedef struct
+{
+ /** Name of file being parsed */
+ char* file;
+
+ /** Parser object */
+ XML_Parser parser;
+
+ /** Device we are trying to match*/
+ HalDevice* device;
+
+ /** Buffer to put CDATA in */
+ char cdata_buf[CDATA_BUF_SIZE];
+
+ /** Current length of CDATA buffer */
+ int cdata_buf_len;
+
+ /** Current depth we are parsing at */
+ int depth;
+
+ /** Element currently being processed */
+ int curelem;
+
+ /** Stack of elements being processed */
+ int curelem_stack[MAX_DEPTH];
+
+ /** #TRUE if parsing of document have been aborted */
+ dbus_bool_t aborted;
+
+
+ /** Depth of match-fail */
+ int match_depth_first_fail;
+
+ /** #TRUE if all matches on prior depths have been OK */
+ dbus_bool_t match_ok;
+
+
+
+ /** When merging, the key to store the value in */
+ char merge_key[MAX_KEY_SIZE];
+
+ /** Type to merge*/
+ int merge_type;
+
+ /** Set to #TRUE if a device is matched */
+ dbus_bool_t device_matched;
+
+} ParsingContext;
+
+/** Called when the match element begins.
+ *
+ * @param pc Parsing context
+ * @param attr Attribute key/value pairs
+ * @return #FALSE if the device in question didn't
+ * match the data in the attributes
+ */
+static dbus_bool_t handle_match(ParsingContext* pc, const char** attr)
+{
+ const char* key;
+ int num_attrib;
+
+ for(num_attrib=0; attr[num_attrib]!=NULL; num_attrib++)
+ ;
+
+ if( num_attrib!=4 )
+ return FALSE;
+
+ if( strcmp(attr[0], "key")!=0 )
+ return FALSE;
+ key = attr[1];
+
+ if( strcmp(attr[2], "string")==0 )
+ {
+ const char* value;
+
+ /* match string property */
+
+ value = attr[3];
+
+ LOG_INFO(("Checking that key='%s' is a string that equals '%s'",
+ key, value));
+
+ if( ds_property_get_type(pc->device, key)!=DBUS_TYPE_STRING )
+ return FALSE;
+
+ if( strcmp(ds_property_get_string(pc->device, key), value)!=0 )
+ return FALSE;
+
+ LOG_INFO(("*** string match for key %s", key));
+ return TRUE;
+ }
+ else if( strcmp(attr[2], "int")==0 )
+ {
+ dbus_int32_t value;
+
+ /* match integer property */
+ value = strtol(attr[3], NULL, 0);
+
+ /** @todo Check error condition */
+
+ LOG_INFO(("Checking that key='%s' is a int that equals %d",
+ key, value));
+
+ if( ds_property_get_type(pc->device, key)!=DBUS_TYPE_INT32 )
+ return FALSE;
+
+ if( ds_property_get_int(pc->device, key)!=value )
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/** Called when the merge element begins.
+ *
+ * @param pc Parsing context
+ * @param attr Attribute key/value pairs
+ */
+static void handle_merge(ParsingContext* pc, const char** attr)
+{
+ int num_attrib;
+
+ for(num_attrib=0; attr[num_attrib]!=NULL; num_attrib++)
+ ;
+
+ if( num_attrib!=4 )
+ return;
+
+ if( strcmp(attr[0], "key")!=0 )
+ return;
+ strncpy(pc->merge_key, attr[1], MAX_KEY_SIZE);
+
+ if( strcmp(attr[2], "type")!=0 )
+ return;
+
+ if( strcmp(attr[3], "string")==0 )
+ {
+ /* match string property */
+ pc->merge_type = DBUS_TYPE_STRING;
+ return;
+ }
+
+ return;
+}
+
+/** Abort parsing of document
+ *
+ * @param pc Parsing context
+ */
+static void parsing_abort(ParsingContext* pc)
+{
+ /* Grr, expat can't abort parsing */
+ LOG_ERROR(("Aborting parsing of document"));
+ pc->aborted = TRUE;
+}
+
+/** Called by expat when an element begins.
+ *
+ * @param pc Parsing context
+ * @param el Element name
+ * @param attr Attribute key/value pairs
+ */
+static void start(ParsingContext *pc, const char *el, const char **attr)
+{
+ int i;
+
+ if( pc->aborted )
+ return;
+
+ pc->cdata_buf_len = 0;
+
+ for (i = 0; i < pc->depth; i++)
+ printf(" ");
+
+ printf("%s", el);
+
+ for (i = 0; attr[i]; i += 2) {
+ printf(" %s='%s'", attr[i], attr[i + 1]);
+ }
+
+ printf(" curelem=%d\n", pc->curelem);
+
+ if( strcmp(el, "match")==0 )
+ {
+ if( pc->curelem!=CURELEM_DEVICE && pc->curelem!=CURELEM_MATCH )
+ {
+ LOG_ERROR(("%s:%d:%d: Element <match> can only be inside "
+ "<device> and <match>",
+ pc->file,
+ XML_GetCurrentLineNumber(pc->parser),
+ XML_GetCurrentColumnNumber(pc->parser)));
+ parsing_abort(pc);
+ }
+
+ pc->curelem = CURELEM_MATCH;
+ /* don't bother checking if matching at lower depths failed */
+ if( pc->match_ok )
+ {
+ if( !handle_match(pc, attr) )
+ {
+ /* No match */
+ pc->match_depth_first_fail = pc->depth;
+ pc->match_ok = FALSE;
+ }
+ }
+ }
+ else if( strcmp(el, "merge")==0 )
+ {
+ if( pc->curelem!=CURELEM_DEVICE && pc->curelem!=CURELEM_MATCH )
+ {
+ LOG_ERROR(("%s:%d:%d: Element <merge> can only be inside "
+ "<device> and <match>",
+ pc->file,
+ XML_GetCurrentLineNumber(pc->parser),
+ XML_GetCurrentColumnNumber(pc->parser)));
+ parsing_abort(pc);
+ }
+
+ pc->curelem = CURELEM_MERGE;
+ if( pc->match_ok )
+ {
+ handle_merge(pc, attr);
+ }
+ else
+ {
+ LOG_INFO(("No merge!"));
+ }
+ }
+ else if( strcmp(el, "device")==0 )
+ {
+ if( pc->curelem!=CURELEM_DEVICE_INFO )
+ {
+ LOG_ERROR(("%s:%d:%d: Element <device> can only be inside "
+ "<deviceinfo>",
+ pc->file,
+ XML_GetCurrentLineNumber(pc->parser),
+ XML_GetCurrentColumnNumber(pc->parser)));
+ parsing_abort(pc);
+ }
+ pc->curelem = CURELEM_DEVICE;
+ }
+ else if( strcmp(el, "deviceinfo")==0 )
+ {
+ if( pc->curelem!=CURELEM_UNKNOWN )
+ {
+ LOG_ERROR(("%s:%d:%d: Element <deviceinfo> must be a top-level "
+ "element",
+ pc->file,
+ XML_GetCurrentLineNumber(pc->parser),
+ XML_GetCurrentColumnNumber(pc->parser)));
+ parsing_abort(pc);
+ }
+ pc->curelem = CURELEM_DEVICE_INFO;
+ }
+ else
+ {
+ LOG_ERROR(("%s:%d:%d: Unknown element <%s>",
+ pc->file,
+ XML_GetCurrentLineNumber(pc->parser),
+ XML_GetCurrentColumnNumber(pc->parser), el));
+ parsing_abort(pc);
+ }
+
+ /* Nasty hack */
+ assert( pc->depth<MAX_DEPTH );
+
+ pc->depth++;
+
+ /* store depth */
+ pc->curelem_stack[pc->depth] = pc->curelem;
+
+}
+
+/** Called by expat when an element ends.
+ *
+ * @param pc Parsing context
+ * @param el Element name
+ */
+static void end(ParsingContext* pc, const char* el)
+{
+ if( pc->aborted )
+ return;
+
+ pc->cdata_buf[pc->cdata_buf_len]='\0';
+
+ printf(" curelem=%d\n", pc->curelem);
+
+ if( pc->curelem==CURELEM_MERGE && pc->match_ok )
+ {
+ /* As soon as we are merging, we have matched the device... */
+ pc->device_matched = TRUE;
+
+ switch( pc->merge_type )
+ {
+ case DBUS_TYPE_STRING:
+ ds_property_set_string(pc->device, pc->merge_key, pc->cdata_buf);
+ break;
+
+ default:
+ LOG_ERROR(("Unknown merge_type=%d='%c'",
+ pc->merge_type, pc->merge_type));
+ break;
+ }
+ }
+
+
+ pc->cdata_buf_len = 0;
+ pc->depth--;
+
+ /* maintain curelem */
+ pc->curelem = pc->curelem_stack[pc->depth];
+
+ /* maintain pc->match_ok */
+ if( pc->depth < pc->match_depth_first_fail )
+ pc->match_ok=TRUE;
+}
+
+/** Called when there is CDATA
+ *
+ * @param pc Parsing context
+ * @param s Pointer to data
+ * @param len Length of data
+ */
+static void cdata(ParsingContext *pc, const char* s, int len)
+{
+ int bytes_left;
+ int bytes_to_copy;
+
+ if( pc->aborted )
+ return;
+
+ bytes_left = CDATA_BUF_SIZE - pc->cdata_buf_len;
+ if( len>bytes_left )
+ {
+ fprintf(stderr,
+ "libhaldeviceinfo: CDATA in element larger than %d\r\n",
+ CDATA_BUF_SIZE);
+ }
+
+ bytes_to_copy = len;
+ if( bytes_to_copy>bytes_left )
+ bytes_to_copy = bytes_left;
+
+ if( bytes_to_copy>0 )
+ memcpy(pc->cdata_buf + pc->cdata_buf_len, s, bytes_to_copy);
+
+ pc->cdata_buf_len += bytes_to_copy;
+}
+
+
+/** Process a device information info file.
+ *
+ * @param dir Directory file resides in
+ * @param filename File name
+ * @param device Device to match on
+ * @return #TRUE if file matched device and information
+ * was merged
+ */
+static dbus_bool_t process_fdi_file(const char* dir, const char* filename,
+ HalDevice* device)
+{
+ int rc;
+ char buf[512];
+ FILE* file;
+ int filesize;
+ char* filebuf;
+ dbus_bool_t device_matched;
+ XML_Parser parser;
+ ParsingContext* parsing_context;
+
+ snprintf(buf, 511, "%s/%s", dir, filename);
+
+ printf("analysing file %s\r\n", buf);
+
+ // open file and read it into a buffer; it's a small file...
+ file = fopen(buf, "r");
+ if( file==NULL )
+ {
+ perror("fopen");
+ return FALSE;
+ }
+
+ fseek(file, 0L, SEEK_END);
+ filesize = (int) ftell(file);
+ rewind(file);
+ filebuf = (char*) malloc(filesize);
+ if( filebuf==NULL )
+ {
+ perror("malloc");
+ fclose(file);
+ return FALSE;
+ }
+ fread(filebuf, sizeof(char), filesize, file);
+
+
+ // ok, now parse the file (should probably reuse parser and say we are
+ // not thread safe)
+ parser = XML_ParserCreate(NULL);
+
+ // initialize parsing context
+ parsing_context = (ParsingContext*) malloc(sizeof(ParsingContext));
+ if( parsing_context==NULL )
+ {
+ perror("malloc");
+ return FALSE;
+ }
+ parsing_context->depth = 0;
+ parsing_context->device_matched = FALSE;
+ parsing_context->match_ok = TRUE;
+ parsing_context->curelem = CURELEM_UNKNOWN;
+ parsing_context->aborted = FALSE;
+ parsing_context->file = buf;
+ parsing_context->parser = parser;
+ parsing_context->device = device;
+
+
+ XML_SetElementHandler(parser,
+ (XML_StartElementHandler) start,
+ (XML_EndElementHandler) end);
+ XML_SetCharacterDataHandler(parser,
+ (XML_CharacterDataHandler) cdata);
+ XML_SetUserData(parser, parsing_context);
+
+ rc = XML_Parse(parser, filebuf, filesize, 1);
+ printf("XML_Parse rc=%d\r\n", rc);
+
+ if( rc==0 )
+ {
+ // error parsing document
+ fprintf(stderr, "libhaldeviceinfo : Error parsing XML document %s\r\n",
+ buf);
+ fprintf(stderr, "at line %d, column %d : %s\r\n",
+ XML_GetCurrentLineNumber(parser),
+ XML_GetCurrentColumnNumber(parser),
+ XML_ErrorString(XML_GetErrorCode(parser)));
+ device_matched = FALSE;
+ }
+ else
+ {
+ // document parsed ok
+ device_matched = parsing_context->device_matched;
+ }
+
+ free(filebuf);
+ fclose(file);
+ free(parsing_context);
+
+ return device_matched;
+}
+
+
+
+/** Scan all directories and subdirectories in the given directory and
+ * process each *.fdi file
+ *
+ * @param d Device to merge information into
+ * @return #TRUE if information was merged
+ */
+static int scan_fdi_files(const char* dir, HalDevice* d)
+{
+ int i;
+ int num_entries;
+ dbus_bool_t found_fdi_file;
+ struct dirent **name_list;
+
+ found_fdi_file = 0;
+
+ LOG_INFO(("scan_fdi_files: Processing dir '%s'", dir));
+
+ num_entries = scandir(dir, &name_list, 0, alphasort);
+ if( num_entries==-1 )
+ {
+ perror("scandir");
+ return FALSE;
+ }
+
+ for(i=num_entries-1; i>=0; i--)
+ {
+ int len;
+ char* filename;
+
+ filename = name_list[i]->d_name;
+ len = strlen(filename);
+
+ if( name_list[i]->d_type==DT_REG )
+ {
+ // regular file
+
+ if( len>=5 &&
+ filename[len-4]=='.' &&
+ filename[len-3]=='f' &&
+ filename[len-2]=='d' &&
+ filename[len-1]=='i' )
+ {
+ LOG_INFO(("scan_fdi_files: Processing file '%s'", filename));
+ found_fdi_file = process_fdi_file(dir, filename, d);
+ if( found_fdi_file )
+ {
+ LOG_INFO(("*** Matched file %s/%s", dir, filename));
+ break;
+ }
+ }
+
+ }
+ else if( name_list[i]->d_type==DT_DIR &&
+ strcmp(filename, ".")!=0 && strcmp(filename, "..")!=0 )
+ {
+ int num_bytes;
+ char* dirname;
+
+ // Directory; do the recursion thingy but not for . and ..
+
+ num_bytes = len + strlen(dir) + 1 + 1;
+ dirname = (char*) malloc(num_bytes);
+ if( dirname==NULL )
+ {
+ LOG_ERROR(("couldn't allocated %d bytes\r\n", num_bytes));
+ break;
+ }
+
+ snprintf(dirname, num_bytes, "%s/%s", dir, filename);
+ found_fdi_file = scan_fdi_files(dirname, d);
+ free(dirname);
+ if( found_fdi_file )
+ break;
+ }
+
+ free(name_list[i]);
+ }
+
+ for( ;i>=0; i--)
+ {
+ free(name_list[i]);
+ }
+
+ free(name_list);
+
+ return found_fdi_file;
+}
+
+
+/** Search the device info file repository for a .fdi file to merge
+ * more information into the device object.
+ *
+ * @param d Device to merge information into
+ * @return #TRUE if information was merged
+ */
+dbus_bool_t di_search_and_merge(HalDevice* d)
+{
+ return scan_fdi_files("/home/david/xdg-hacking/hal/fdi", d);
+}
+
+/** @} */
+
diff --git a/hald/device_info.h b/hald/device_info.h
new file mode 100644
index 00000000..a848e494
--- /dev/null
+++ b/hald/device_info.h
@@ -0,0 +1,37 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * device_store.c : Search for .fdi files and merge on match
+ *
+ * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
+ *
+ * Licensed under the Academic Free License version 2.0
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ **************************************************************************/
+
+#ifndef DEVICE_INFO_H
+#define DEVICE_INFO_H
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <dbus/dbus.h>
+
+#include "device_store.h"
+
+dbus_bool_t di_search_and_merge(HalDevice* d);
+
+#endif /* DEVICE_INFO_H */
diff --git a/hald/device_store.c b/hald/device_store.c
index 1daba959..130ec3c8 100644
--- a/hald/device_store.c
+++ b/hald/device_store.c
@@ -440,7 +440,7 @@ dbus_bool_t ds_property_set_string(HalDevice* device, const char* key,
if( property_changed_cb!=NULL )
property_changed_cb(device,
key,
- device->in_gdl, FALSE);
+ device->in_gdl, FALSE, FALSE);
return TRUE;
}
}
@@ -470,7 +470,7 @@ dbus_bool_t ds_property_set_string(HalDevice* device, const char* key,
if( property_changed_cb!=NULL )
property_changed_cb(device,
prop->key,
- device->in_gdl, FALSE);
+ device->in_gdl, FALSE, TRUE);
return TRUE;
}
@@ -506,7 +506,7 @@ dbus_bool_t ds_property_set_int(HalDevice* device, const char* key,
if( property_changed_cb!=NULL )
property_changed_cb(device,
key,
- device->in_gdl, FALSE);
+ device->in_gdl, FALSE, FALSE);
return TRUE;
}
}
@@ -534,7 +534,7 @@ dbus_bool_t ds_property_set_int(HalDevice* device, const char* key,
if( property_changed_cb!=NULL )
property_changed_cb(device,
prop->key,
- device->in_gdl, FALSE);
+ device->in_gdl, FALSE, TRUE);
return TRUE;
}
@@ -570,7 +570,7 @@ dbus_bool_t ds_property_set_bool(HalDevice* device, const char* key,
if( property_changed_cb!=NULL )
property_changed_cb(device,
key,
- device->in_gdl, FALSE);
+ device->in_gdl, FALSE, FALSE);
return TRUE;
}
}
@@ -598,7 +598,7 @@ dbus_bool_t ds_property_set_bool(HalDevice* device, const char* key,
if( property_changed_cb!=NULL )
property_changed_cb(device,
prop->key,
- device->in_gdl, FALSE);
+ device->in_gdl, FALSE, TRUE);
return TRUE;
}
@@ -634,7 +634,7 @@ dbus_bool_t ds_property_set_double(HalDevice* device, const char* key,
if( property_changed_cb!=NULL )
property_changed_cb(device,
key,
- device->in_gdl, FALSE);
+ device->in_gdl, FALSE, FALSE);
return TRUE;
}
}
@@ -662,7 +662,7 @@ dbus_bool_t ds_property_set_double(HalDevice* device, const char* key,
if( property_changed_cb!=NULL )
property_changed_cb(device,
prop->key,
- device->in_gdl, FALSE);
+ device->in_gdl, FALSE, TRUE);
return TRUE;
}
@@ -718,7 +718,7 @@ dbus_bool_t ds_property_remove(HalDevice* device, const char* key)
if( property_changed_cb!=NULL )
property_changed_cb(device,
key,
- device->in_gdl, TRUE);
+ device->in_gdl, TRUE, FALSE);
return TRUE;
}
diff --git a/hald/device_store.h b/hald/device_store.h
index 23b3d2d9..b02375f0 100644
--- a/hald/device_store.h
+++ b/hald/device_store.h
@@ -89,17 +89,20 @@ typedef struct HalDeviceIterator_s
unsigned int position; /**< Which number are we iterating over */
} HalDeviceIterator;
-/** Signature for callback function when a property is changed or removed.
+/** Signature for callback function when a property is changed, added
+ * or removed.
*
* @param device A pointer to a #HalDevice object
* @param key The key of the property
* @param in_gdl Device is in global device list
- * @param removed Property is removed
+ * @param removed True iff property was removed
+ * @param added True iff property was added
*/
typedef void (*HalDevicePropertyChangedCallback)(HalDevice* device,
const char* key,
dbus_bool_t in_gdl,
- dbus_bool_t removed);
+ dbus_bool_t removed,
+ dbus_bool_t added);
void ds_init(HalDevicePropertyChangedCallback property_changed_cb);
void ds_shutdown();
diff --git a/hald/logger.h b/hald/logger.h
index 4e975c1d..30d14a0e 100644
--- a/hald/logger.h
+++ b/hald/logger.h
@@ -26,7 +26,9 @@
#ifndef LOGGER_H
#define LOGGER_H
-#define LOG_TRACE(expr) do {printf("[T] %s:%s():%d : ", __FILE__, __FUNCTION__, __LINE__); printf expr; printf("\n"); } while(0)
+/*#define LOG_TRACE(expr) do {printf("[T] %s:%s():%d : ", __FILE__, __FUNCTION__, __LINE__); printf expr; printf("\n"); } while(0)*/
+#define LOG_TRACE(expr) do {;} while(0)
+
#define LOG_DEBUG(expr) do {printf("[D] %s:%s():%d : ", __FILE__, __FUNCTION__, __LINE__); printf expr; printf("\n"); } while(0)
diff --git a/hald/main.c b/hald/main.c
index 694cb43a..c5ef51dc 100644
--- a/hald/main.c
+++ b/hald/main.c
@@ -37,6 +37,7 @@
#include "logger.h"
#include "device_store.h"
+#include "device_info.h"
/* We need somewhere to define these groups somewhere */
@@ -768,8 +769,41 @@ static DBusHandlerResult device_enable(DBusConnection* connection,
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
- /** @todo: enable device */
+ /* Now enable device */
LOG_INFO(("Enabling device %s", udi));
+
+ /* First, make sure we got an .fdi file */
+ if( (!ds_property_exists(d, "GotDeviceInfo")) ||
+ (!ds_property_get_bool(d, "GotDeviceInfo")) )
+ {
+ /* need to search for an .fdi file */
+ if( di_search_and_merge(d) )
+ {
+ /* Found .fdi file */
+
+ /** @todo Check for required properties */
+
+ ds_property_set_bool(d, "GotDeviceInfo", TRUE);
+ }
+ else
+ ds_property_set_bool(d, "GotDeviceInfo", FALSE);
+ }
+
+
+
+ if( ds_property_get_bool(d, "GotDeviceInfo") )
+ {
+ /** @todo boot device */
+ LOG_INFO(("Now booting device"));
+
+ ds_property_set_int(d, "State", HAL_STATE_ENABLED);
+ }
+ else
+ {
+ /* giving up */
+ ds_property_set_int(d, "State", HAL_STATE_NEED_DEVICE_INFO);
+ }
+
dbus_message_iter_init(reply, &iter);
dbus_message_iter_append_boolean(&iter, ok_to_enable);
@@ -1113,6 +1147,9 @@ static DBusHandlerResult agent_manager_commit_to_gdl(
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
+ /* add to the GDL */
+ ds_gdl_add(d);
+
/* Ok, send out a signal on the Manager interface that we added
* this device to the gdl */
manager_send_signal_device_added(new_udi);
@@ -1354,10 +1391,12 @@ static DBusHandlerResult filter_function(DBusConnection* connection,
DBusMessage* message,
void* user_data)
{
+/*
LOG_INFO(("obj_path=%s interface=%s method=%s",
dbus_message_get_path(message),
dbus_message_get_interface(message),
dbus_message_get_member(message)));
+*/
if( dbus_message_is_method_call(message,
"org.freedesktop.Hal.Manager",
@@ -1526,18 +1565,45 @@ static DBusHandlerResult filter_function(DBusConnection* connection,
* @param in_gdl True iff the device object in visible in the
* global device list
* @param removed True iff the property was removed
+ * @param added True iff the property was added
*/
static void property_changed(HalDevice* device,
const char* key,
dbus_bool_t in_gdl,
- dbus_bool_t removed)
+ dbus_bool_t removed,
+ dbus_bool_t added)
{
-/*
- LOG_INFO(("Invoked, udi=%s, key=%s, in_gdl=%s, removed=%s",
- ds_get_udi(device), key,
+ DBusMessage* message;
+ DBusMessageIter iter;
+ const char* signal_name;
+
+ LOG_INFO(("Entering, udi=%s, key=%s, in_gdl=%s, removed=%s added=%s",
+ device->udi, key,
in_gdl ? "true" : "false",
- removed ? "true" : "false"));
-*/
+ removed ? "true" : "false",
+ added ? "true" : "false"));
+
+ if( !in_gdl )
+ return;
+
+ if( removed )
+ signal_name = "PropertyRemoved";
+ else if( added )
+ signal_name = "PropertyAdded";
+ else
+ signal_name = "PropertyChanged";
+
+ message = dbus_message_new_signal(device->udi,
+ "org.freedesktop.Hal.Device",
+ signal_name);
+
+ dbus_message_iter_init(message, &iter);
+ dbus_message_iter_append_string(&iter, key);
+
+ if( !dbus_connection_send(dbus_connection,message, NULL) )
+ DIE(("error broadcasting message"));
+
+ dbus_message_unref(message);
}