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