summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--hald/Makefile.am1
-rw-r--r--hald/linux/linux_class_i2c_adapter.c236
-rw-r--r--hald/linux/linux_class_i2c_adapter.h39
-rw-r--r--hald/linux/linux_osspec.c38
-rw-r--r--tools/device-manager/Const.py.in1
6 files changed, 321 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index b7e1b714..376efeff 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2004-01-13 Matthew Mastracci <matt@aclaro.com>
+
+ * tools/device-manager/Const.py.in (BUS_NAMES): add i2c_adapter
+
+ * hald/linux/linux_osspec.c (visit_class_device): add support for
+ i2c-adapter
+ (visit_device): add support for i2c and i2c-adapter
+ (handle_hotplug): hotplug support for i2c and i2c-adapter
+
+ * hald/Makefile.am (hald_SOURCES): Add linux_class_i2c_adapter.[ch]
+
+ * hald/linux/linux_class_i2c_adapter.[ch]: new files
+
2004-01-12 David Zeuthen <david@fubar.dk>
* hald/linux/linux_class_block.c
diff --git a/hald/Makefile.am b/hald/Makefile.am
index a9638c11..0e245ec5 100644
--- a/hald/Makefile.am
+++ b/hald/Makefile.am
@@ -28,6 +28,7 @@ hald_SOURCES += \
linux/linux_class_block.h linux/linux_class_block.c \
linux/linux_class_scsi.h linux/linux_class_scsi.c \
linux/linux_class_net.h linux/linux_class_net.c \
+ linux/linux_class_i2c_adapter.h linux/linux_class_i2c_adapter.c \
linux/linux_class_input.h linux/linux_class_input.c
hald_SOURCES += \
diff --git a/hald/linux/linux_class_i2c_adapter.c b/hald/linux/linux_class_i2c_adapter.c
new file mode 100644
index 00000000..7fa5636a
--- /dev/null
+++ b/hald/linux/linux_class_i2c_adapter.c
@@ -0,0 +1,236 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * linux_class_i2c_adapter.c : I2C functions for sysfs-agent on Linux 2.6
+ *
+ * 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 <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include "../logger.h"
+#include "../device_store.h"
+#include "linux_class_i2c_adapter.h"
+
+/**
+ * @defgroup HalDaemonLinuxI2cAdapter I2C adapter class
+ * @ingroup HalDaemonLinux
+ * @brief I2C adapter class
+ * @{
+ */
+
+
+/** This function will compute the device uid based on other properties
+ * of the device. For I2C adapters it is the adapter number.
+ *
+ * @param d HalDevice object
+ * @param append_num Number to append to name if not -1
+ * @return New unique device id; only good until the
+ * next invocation of this function
+ */
+static char* i2c_adapter_compute_udi(HalDevice* d, int append_num)
+{
+ const char* format;
+ static char buf[256];
+
+ if( append_num==-1 )
+ format = "/org/freedesktop/Hal/devices/i2c_adapter_%d";
+ else
+ format = "/org/freedesktop/Hal/devices/i2c_adapter_%d-%d";
+
+ snprintf(buf, 256, format,
+ ds_property_get_int(d, "i2c_adapter.adapter"),
+ append_num);
+
+ return buf;
+}
+
+
+/* fwd decl */
+static void visit_class_device_i2c_adapter_got_parent(HalDevice* parent,
+ void* data1, void* data2);
+
+/** Visitor function for I2C adapter.
+ *
+ * This function parses the attributes present and creates a new HAL
+ * device based on this information.
+ *
+ * @param path Sysfs-path for device
+ * @param device libsysfs object for device
+ */
+void visit_class_device_i2c_adapter(const char* path,
+ struct sysfs_class_device* class_device)
+{
+ HalDevice* d;
+ struct sysfs_attribute* cur;
+ char* parent_sysfs_path;
+ char* product_name;
+ char attr_name[SYSFS_NAME_LEN];
+ const char* last_elem;
+ int adapter_num;
+ int len;
+ int i;
+
+ if( class_device->sysdevice==NULL )
+ {
+ HAL_INFO(("Skipping virtual class device at path %s\n", path));
+ return;
+ }
+
+ HAL_INFO(("i2c_adapter: sysdevice_path=%s, path=%s\n", class_device->sysdevice->path, path));
+
+ /** @todo: see if we already got this device */
+
+ d = ds_device_new();
+ ds_property_set_string(d, "info.bus", "i2c_adapter");
+ ds_property_set_string(d, "linux.sysfs_path", path);
+ ds_property_set_string(d, "linux.sysfs_path_device",
+ class_device->sysdevice->path);
+
+ /* Sets last_elem to i2c-2 in path=/sys/class/i2c-adapter/i2c-2 */
+ last_elem = get_last_element(path);
+ sscanf(last_elem, "i2c-%d", &adapter_num);
+ ds_property_set_int(d, "i2c_adapter.adapter", adapter_num);
+
+ /* guestimate product name */
+ dlist_for_each_data(sysfs_get_device_attributes(class_device->sysdevice), cur,
+ struct sysfs_attribute)
+ {
+
+ if( sysfs_get_name_from_path(cur->path,
+ attr_name, SYSFS_NAME_LEN) != 0 )
+ continue;
+
+ /* strip whitespace */
+ len = strlen(cur->value);
+ for(i=len-1; isspace(cur->value[i]); --i)
+ cur->value[i] = '\0';
+
+ /*printf("attr_name=%s -> '%s'\n", attr_name, cur->value);*/
+
+ if( strcmp(attr_name, "name")==0 )
+ product_name = cur->value;
+ }
+
+ ds_property_set_string(d, "info.product", "I2C Adapter Interface");
+ if ( product_name==NULL )
+ ds_property_set_string(d, "i2c_adapter.name", "I2C Adapter Interface");
+ else
+ ds_property_set_string(d, "i2c_adapter.name", product_name);
+
+ parent_sysfs_path = get_parent_sysfs_path(class_device->sysdevice->path);
+
+ /* Find parent; this happens asynchronously as our parent might
+ * be added later. If we are probing this can't happen so the
+ * timeout is set to zero in that event..
+ */
+ ds_device_async_find_by_key_value_string(
+ "linux.sysfs_path_device",
+ parent_sysfs_path,
+ TRUE,
+ visit_class_device_i2c_adapter_got_parent,
+ (void*) d, NULL,
+ is_probing ? 0 :
+ HAL_LINUX_HOTPLUG_TIMEOUT);
+
+ free(parent_sysfs_path);
+}
+
+/** Callback when the parent is found or if there is no parent.. This is
+ * where we get added to the GDL..
+ *
+ * @param parent Async Return value from the find call
+ * @param data1 User data
+ * @param data2 User data
+ */
+static void visit_class_device_i2c_adapter_got_parent(HalDevice* parent,
+ void* data1, void* data2)
+{
+ char* new_udi = NULL;
+ HalDevice* new_d = NULL;
+ HalDevice* d = (HalDevice*) data1;
+
+ /*printf("parent=0x%08x\n", parent);*/
+
+ if( parent!=NULL )
+ {
+ ds_property_set_string(d, "info.parent", parent->udi);
+ find_and_set_physical_device(d);
+ ds_property_set_bool(d, "info.virtual", TRUE);
+ }
+ else
+ {
+ HAL_ERROR(("No parent for I2C adapter device!"));
+ ds_device_destroy(d);
+ return;
+ }
+
+ /* Add the i2c_adapter capability to our parent device */
+ ds_add_capability(parent, "i2c_adapter");
+
+ /* Compute a proper UDI (unique device id) and try to locate a persistent
+ * unplugged device or simple add this new device...
+ */
+ new_udi = rename_and_merge(d, i2c_adapter_compute_udi, "i2c_adapter");
+ if( new_udi!=NULL )
+ {
+ new_d = ds_device_find(new_udi);
+ if( new_d!=NULL )
+ {
+ ds_gdl_add(new_d);
+ }
+ }
+}
+
+
+/** Init function for I2C adapter class handling
+ *
+ */
+void linux_class_i2c_adapter_init()
+{
+}
+
+/** This function is called when all device detection on startup is done
+ * in order to perform optional batch processing on devices
+ *
+ */
+void linux_class_i2c_adapter_detection_done()
+{
+}
+
+/** Shutdown function for I2C adapter class handling
+ *
+ */
+void linux_class_i2c_adapter_shutdown()
+{
+}
+
+/** @} */
diff --git a/hald/linux/linux_class_i2c_adapter.h b/hald/linux/linux_class_i2c_adapter.h
new file mode 100644
index 00000000..395cadf8
--- /dev/null
+++ b/hald/linux/linux_class_i2c_adapter.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * linux_class_i2c_adapter.h : I2C device handling on Linux 2.6
+ *
+ * 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 LINUX_CLASS_I2C_ADAPTER_H
+#define LINUX_CLASS_I2C_ADAPTER_H
+
+#include "linux_common.h"
+
+void visit_class_device_i2c_adapter(const char* path,
+ struct sysfs_class_device *class_device);
+
+
+void linux_class_i2c_adapter_init();
+void linux_class_i2c_adapter_detection_done();
+void linux_class_i2c_adapter_shutdown();
+
+#endif /* LINUX_CLASS_I2C_ADAPTER_H */
diff --git a/hald/linux/linux_osspec.c b/hald/linux/linux_osspec.c
index 44382e86..82873fc0 100644
--- a/hald/linux/linux_osspec.c
+++ b/hald/linux/linux_osspec.c
@@ -48,6 +48,7 @@
#include "linux_ide.h"
#include "linux_class_block.h"
#include "linux_class_scsi.h"
+#include "linux_class_i2c_adapter.h"
#include "linux_class_net.h"
#include "linux_class_input.h"
@@ -100,6 +101,8 @@ static void visit_class_device(const char* path, dbus_bool_t visit_children)
visit_class_device_scsi_host(path, class_device);
else if( strcmp(class_device->classname, "scsi_device")==0 )
visit_class_device_scsi_device(path, class_device);
+ else if( strcmp(class_device->classname, "i2c-adapter")==0 )
+ visit_class_device_i2c_adapter(path, class_device);
else if( strcmp(class_device->classname, "block")==0 )
visit_class_device_block(path, class_device);
else if( strcmp(class_device->classname, "net")==0 )
@@ -170,6 +173,8 @@ static void visit_device(const char* path, dbus_bool_t visit_children)
{
struct sysfs_device* device;
struct sysfs_directory* subdir;
+ struct sysfs_class* cls;
+ struct sysfs_class_device* class_device;
device = sysfs_open_device(path);
if( device==NULL )
@@ -192,12 +197,29 @@ static void visit_device(const char* path, dbus_bool_t visit_children)
/** @todo This is a hack; is there such a thing as an ide_host? */
else if( strncmp(device->bus_id, "ide", 3)==0 )
visit_device_ide_host(path, device);
- /* Hmm only works on some boxes?? So we have to do hack below
else if( strcmp(device->bus, "i2c")==0 )
- visit_device_i2c(path, device);*/
- else if( strncmp(device->bus_id, "i2c", 3)==0 )
- visit_device_i2c(path, device);
- else
+ visit_device_i2c(path, device);
+ else if( strncmp(device->bus_id, "i2c", 3)==0 )
+ {
+ /* @todo FIXME we need to add the i2c-adapter class
+ * devices here, otherwise the I2C devices have nowhere to
+ * go
+ */
+ cls = sysfs_open_class("i2c-adapter");
+ if (cls != NULL)
+ {
+ if( cls->devices!=NULL )
+ {
+ dlist_for_each_data(cls->devices, class_device, struct sysfs_class_device)
+ {
+ printf("device->bus_id = %s, cls->name = %s\n", device->bus_id, class_device->name);
+ if ( strcmp(device->bus_id, class_device->name) == 0 )
+ visit_class_device_i2c_adapter(path, class_device);
+ }
+ }
+ sysfs_close_class(cls);
+ }
+ }
{
/*printf("bus=%s path=%s\n", device->bus, path);*/
}
@@ -412,7 +434,8 @@ static DBusHandlerResult handle_hotplug(DBusConnection* connection,
if( sysfs_devpath[0]!='\0' &&
(strcmp(subsystem, "usb")==0 ||
- strcmp(subsystem, "pci")==0) )
+ strcmp(subsystem, "pci")==0 ||
+ strcmp(subsystem, "i2c")==0))
{
if( is_add )
@@ -461,7 +484,8 @@ static DBusHandlerResult handle_hotplug(DBusConnection* connection,
(strcmp(subsystem, "net")==0 ||
strcmp(subsystem, "block")==0 ||
strcmp(subsystem, "scsi_host")==0 ||
- strcmp(subsystem, "scsi_device")==0) )
+ strcmp(subsystem, "scsi_device")==0 ||
+ strcmp(subsystem, "i2c-adapter")==0) )
{
if( is_add )
{
diff --git a/tools/device-manager/Const.py.in b/tools/device-manager/Const.py.in
index 616b7c9b..d15cae71 100644
--- a/tools/device-manager/Const.py.in
+++ b/tools/device-manager/Const.py.in
@@ -20,6 +20,7 @@ BUS_NAMES = {"usb" : "USB",
"usbif" : "USB Interface",
"pci" : "PCI",
"i2c" : "I2C",
+ "i2c_adapter" : "I2C adapter",
"scsi_host" : "SCSI Host",
"scsi_device" : "SCSI",
"block" : "Block",