hal: Branch 'master'

David Zeuthen david at kemper.freedesktop.org
Thu Feb 22 18:09:13 PST 2007


 hald/linux/device.c |  352 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 352 insertions(+)

New commits:
diff-tree 7b8f3a460d2a898b322369f8e578b4a45b3d7a12 (from f734a4ff07fd26f762f36e5a3b98816ba354b380)
Author: David Zeuthen <davidz at redhat.com>
Date:   Thu Feb 22 21:01:59 2007 -0500

    add support for new Firewire stack on Linux
    
    Introduces a few new properties and a new capability
    ieee1394_unit. Part of this code written by Kristian Hogsberg
    <krh at redhat.com>.

diff --git a/hald/linux/device.c b/hald/linux/device.c
index da76ef0..909d74c 100644
--- a/hald/linux/device.c
+++ b/hald/linux/device.c
@@ -36,6 +36,8 @@
 #include <stdint.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <asm/byteorder.h>
+#include <fcntl.h>
 
 #include <dbus/dbus.h>
 #include <dbus/dbus-glib.h>
@@ -1968,6 +1970,347 @@ ieee1394_compute_udi (HalDevice *d)
 
 /*--------------------------------------------------------------------------------------------------------------*/
 
+#define CSR_OFFSET	0x40
+#define CSR_LEAF	0x80
+#define CSR_DIRECTORY	0xc0
+
+#define CSR_DESCRIPTOR		0x01
+#define CSR_VENDOR		0x03
+#define CSR_HARDWARE_VERSION	0x04
+#define CSR_NODE_CAPABILITIES	0x0c
+#define CSR_UNIT		0x11
+#define CSR_SPECIFIER_ID	0x12
+#define CSR_VERSION		0x13
+#define CSR_DEPENDENT_INFO	0x14
+#define CSR_MODEL		0x17
+#define CSR_INSTANCE		0x18
+
+#define SBP2_COMMAND_SET_SPECIFIER	0x38
+#define SBP2_COMMAND_SET		0x39
+#define SBP2_COMMAND_SET_REVISION	0x3b
+#define SBP2_FIRMWARE_REVISION		0x3c
+
+static char *
+decode_textual_descriptor(uint32_t *block, char *buffer, size_t size)
+{
+	unsigned int length;
+	uint32_t *p, *end;
+	
+	length = block[0] >> 16;
+	if (block[1] != 0 || block[2] != 0) {
+		snprintf(buffer, length, "unknown encoding/language: 0x%08x/0x%08x\n",
+			 buffer[1], buffer[2]);
+		return buffer;
+	}
+	
+	p = &block[3];
+	memset(buffer, 0, size);
+	if (length - 2 > size / 4)
+		end = &block[3 + size / 4];
+	else
+		end = &block[length + 1];
+	
+	while (p < end) {
+		* (uint32_t *) buffer = __cpu_to_be32(*p);
+		buffer += 4;
+		p++;
+	}
+	
+	return buffer;
+}
+
+#define ARRAY_LENGTH(a) (sizeof(a)/sizeof((a)[0]))
+
+
+struct csr_iterator {
+	uint32_t *p;
+	uint32_t *end;
+};
+
+static void
+csr_iterator_init(struct csr_iterator *ci, uint32_t *p)
+{
+	ci->p = p + 1;
+	ci->end = ci->p + (p[0] >> 16);
+}
+
+static int
+csr_iterator_next(struct csr_iterator *ci, int *key, int *value)
+{
+	*key = *ci->p >> 24;
+	*value = *ci->p & 0xffffff;
+
+	return ci->p++ < ci->end;
+}
+
+static void
+firewire_parse_config_rom (HalDevice *d, uint32_t *rom)
+{
+	struct csr_iterator ci;
+	int key, value, last_key = 0, vendor = 0, model = 0;
+	uint64_t guid;
+	char buffer[256];
+	
+	guid = ((__u64)rom[3] << 32) | rom[4];
+	hal_device_property_set_uint64 (d, "ieee1394.guid", guid);
+	
+	csr_iterator_init(&ci, rom + 5);
+	while (csr_iterator_next(&ci, &key, &value)) {
+		switch (key) {
+		case CSR_VENDOR:
+			vendor = value;
+			hal_device_property_set_int (d, "ieee1394.vendor_id", vendor);
+			break;
+		case CSR_MODEL:
+			model = value;
+			hal_device_property_set_int (d, "ieee1394.product_id", vendor);
+			break;
+		case CSR_DESCRIPTOR | CSR_LEAF:
+			if (last_key == CSR_VENDOR) {
+				decode_textual_descriptor(ci.p - 1 + value,
+							  buffer, sizeof buffer);
+				hal_device_property_set_string (d, "ieee1394.vendor", buffer);
+			} else if (last_key == CSR_MODEL) {
+				decode_textual_descriptor(ci.p - 1 + value,
+							  buffer, sizeof buffer);
+				hal_device_property_set_string (d, "ieee1394.product", buffer);
+			}
+			break;
+		case CSR_HARDWARE_VERSION:
+			hal_device_property_set_int (d, "ieee1394.hardware_version", value);
+			break;
+			
+		}
+
+		last_key = key;
+	}
+}
+
+
+static void
+decode_sbp2_entry (HalDevice *d, int key, int value)
+{
+	switch (key) {
+	case SBP2_FIRMWARE_REVISION:
+		hal_device_property_set_int (d, "ieee1394_unit.sbp2.firmware_revision", value);
+		break;
+	}
+}
+
+struct specifier {
+	int specifier_id;
+	int version;
+	void (*decode_entry) (HalDevice *d, int key, int value);
+} specifiers[] = {
+	{
+		0x00609e,
+		0x010483,
+		decode_sbp2_entry
+	}
+};
+
+static void
+firewire_unit_parse_config_rom (HalDevice *d, uint32_t *rom, int index)
+{
+	struct csr_iterator ci;
+	unsigned int i;
+	int key;
+	int value;
+	int specifier_id = 0;
+	int version = 0;
+	
+	csr_iterator_init(&ci, rom + index);
+	while (csr_iterator_next(&ci, &key, &value)) {
+		switch (key) {
+		case CSR_SPECIFIER_ID:
+			specifier_id = value;
+			hal_device_property_set_int (d, "ieee1394_unit.specifier_id", specifier_id);
+			break;
+		case CSR_VERSION:
+			version = value;
+			hal_device_property_set_int (d, "ieee1394_unit.version", version);
+			break;
+			
+		default:
+			if (key < 0x38)
+				break;
+			
+			/* Specifier dependent key/value pair. */
+			for (i = 0; i < ARRAY_LENGTH(specifiers); i++) {
+				if (specifiers[i].specifier_id == specifier_id &&
+				    specifiers[i].version == version) {
+					specifiers[i].decode_entry (d, key, value);
+					break;
+				}
+			}
+		}
+	}
+	
+	if (specifier_id == 0x00609e && version == 0x010483) {
+		hal_device_add_capability (d, "ieee1394_unit.sbp2");
+	} else if (specifier_id == 0x00a02d) {
+		if ((version & 0xffff00) == 0x000100)
+			hal_device_add_capability (d, "ieee1394_unit.iidc");
+		if ((version & 0xff0001) == 0x010001)
+			hal_device_add_capability (d, "ieee1394_unit.avc");
+		if ((version & 0xff0002) == 0x010002)
+			hal_device_add_capability (d, "ieee1394_unit.cal");
+		if ((version & 0xff0004) == 0x010004)
+			hal_device_add_capability (d, "ieee1394_unit.ehs");
+		if ((version & 0xff0004) == 0x010008)
+			hal_device_add_capability (d, "ieee1394_unit.havi");
+	} else if (specifier_id == 0x000b09d && version == 0x800002) {
+		/* Workaround for pointgrey cameras taken from libdc1394 */
+		hal_device_add_capability (d, "ieee1394_unit.iidc");
+	}
+
+#if 0
+	/* TODO */
+
+	/* In the AV/C case we should send a unit info command to the
+	 * device to see what kind of AV/C device it is (audio, camcorder,
+	 * etc).  We might want to do this in a helper app.  And we need
+	 * the device file for this...  This will be another 200 lines of
+	 * code.
+	 */
+	if (specifier_id == 0x00a02d && (version & 0xff0001) == 0x010001) {
+		query_unit_info("/dev/fw1.0");
+	}
+#endif
+}
+
+
+static HalDevice *
+firewire_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *parent_dev, const gchar *parent_path)
+{
+	HalDevice *d;
+	int device_id;
+	int unit_id;
+	const char *bus_id;
+	gboolean is_device = FALSE;
+	gboolean is_unit = FALSE;
+	char rom[256];
+	ssize_t rom_size;
+	char *str;
+	int fd;
+
+	d = NULL;
+
+	if (parent_dev == NULL)
+		goto out;
+
+	bus_id = hal_util_get_last_element (sysfs_path);
+
+	if (sscanf (bus_id, "fw%d.%d", &device_id, &unit_id) == 2 ) {
+		is_unit = TRUE;
+	} else if (sscanf (bus_id, "fw%d", &device_id) == 1) {
+		is_device = TRUE;
+	} else {
+		goto out;
+	}
+
+	if (is_device) {
+
+		if (device_file == NULL)
+			goto out;
+
+		str = g_strdup_printf ("%s/config_rom", sysfs_path);
+		fd = open (str, O_RDONLY);
+		if (fd < 0) {
+			HAL_ERROR (("Cannot open firewire config rom at %s", str));
+			g_free (str);
+			goto out;
+		}
+		if ((rom_size = read (fd, rom, sizeof (rom))) < 0) {
+			HAL_ERROR (("Cannot read firewire config rom at %s", str));
+			g_free (str);
+			close (fd);
+			goto out;
+		}
+		g_free (str);
+		close (fd);
+
+		HAL_INFO (("firewire config rom is %d bytes", rom_size));
+
+		d = hal_device_new ();
+		hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+		hal_device_property_set_string (d, "info.subsystem", "ieee1394");
+		hal_device_property_set_string (d, "info.bus", "ieee1394");
+		hal_device_property_set_string (d, "info.parent", hal_device_get_udi (parent_dev));
+		hal_device_add_capability (d, "ieee1394");
+		hal_device_property_set_string (d, "ieee1394.device", device_file);
+		hal_util_set_driver (d, "info.linux.driver", sysfs_path);
+
+		firewire_parse_config_rom (d, (uint32_t *) rom);
+	} else {
+		int rom_index;
+
+		str = g_strdup_printf ("%s/../config_rom", sysfs_path);
+		fd = open (str, O_RDONLY);
+		if (fd < 0) {
+			HAL_ERROR (("Cannot open firewire config rom at %s", str));
+			g_free (str);
+			goto out;
+		}
+		if ((rom_size = read (fd, rom, sizeof (rom))) < 0) {
+			HAL_ERROR (("Cannot read firewire config rom at %s", str));
+			g_free (str);
+			close (fd);
+			goto out;
+		}
+		g_free (str);
+		close (fd);
+
+		if (!hal_util_get_int_from_file (sysfs_path, "rom_index", &rom_index, 0)) {
+			HAL_ERROR (("Cannot read get %s/rom_index", sysfs_path));
+			goto out;
+		}
+
+		HAL_INFO (("firewire config rom is %d bytes - unit rom index is %d", rom_size, rom_index));
+
+		d = hal_device_new ();
+		hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+		hal_device_property_set_string (d, "info.subsystem", "ieee1394_unit");
+		hal_device_property_set_string (d, "info.bus", "ieee1394_unit");
+		hal_device_property_set_string (d, "info.parent", hal_device_get_udi (parent_dev));
+		hal_device_property_set_string (d, "ieee1394_unit.originating_device", 
+						hal_device_get_udi (parent_dev));
+		hal_device_property_set_int (d, "ieee1394_unit.unit_index", unit_id);
+		hal_device_add_capability (d, "ieee1394_unit");
+		hal_util_set_driver (d, "info.linux.driver", sysfs_path);
+
+		firewire_unit_parse_config_rom (d, (uint32_t *) rom, rom_index);
+	}
+
+
+out:
+	return d;
+}
+
+static gboolean
+firewire_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	if (hal_device_has_capability (d, "ieee1394")) {
+		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+				      "/org/freedesktop/Hal/devices/ieee1394_guid%0llx",
+				      hal_device_property_get_uint64 (d, "ieee1394.guid"));
+	} else {
+		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+				      "%s_unit%d",
+				      hal_device_property_get_string (d, "ieee1394_unit.originating_device"),
+				      hal_device_property_get_int (d, "ieee1394_unit.unit_index"));
+	}
+
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
 static inline void
 ccw_add_dasd_properties (HalDevice *d, const gchar *sysfs_path)
 {
@@ -2641,6 +2984,14 @@ static DevHandler dev_handler_ieee1394 =
 	.remove      = dev_remove
 };
 
+/* krh's new firewire stack */
+static DevHandler dev_handler_firewire = { 
+	.subsystem   = "firewire",
+	.add         = firewire_add,
+	.compute_udi = firewire_compute_udi,
+	.remove      = dev_remove
+};
+
 static DevHandler dev_handler_xen = {
 	.subsystem   = "xen",
 	.add         = xen_add,
@@ -2719,6 +3070,7 @@ static DevHandler *dev_handlers[] = {
 	&dev_handler_tape390,
 	&dev_handler_mmc_host,
 	&dev_handler_backlight,
+	&dev_handler_firewire,
 	NULL
 };
 


More information about the hal-commit mailing list