diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | hald/Makefile.am | 1 | ||||
-rw-r--r-- | hald/linux/linux_class_i2c_adapter.c | 236 | ||||
-rw-r--r-- | hald/linux/linux_class_i2c_adapter.h | 39 | ||||
-rw-r--r-- | hald/linux/linux_osspec.c | 38 | ||||
-rw-r--r-- | tools/device-manager/Const.py.in | 1 |
6 files changed, 321 insertions, 7 deletions
@@ -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", |