hal: Branch 'master' - 15 commits

Joe Marcus Clarke marcus at kemper.freedesktop.org
Tue Aug 18 10:17:39 PDT 2009


 configure.in                                |   32 ++
 hald/freebsd/Makefile.am                    |    7 
 hald/freebsd/addons/Makefile.am             |   10 
 hald/freebsd/addons/addon-mouse.c           |  371 ++++++++++++++++++++++++++++
 hald/freebsd/addons/addon-storage.c         |  246 +++++++++++++++---
 hald/freebsd/hf-acpi.c                      |   40 ++-
 hald/freebsd/hf-computer.c                  |    9 
 hald/freebsd/hf-devd.c                      |   17 +
 hald/freebsd/hf-devtree.c                   |   33 ++
 hald/freebsd/hf-storage.c                   |   96 ++++++-
 hald/freebsd/hf-storage.h                   |    2 
 hald/freebsd/hf-usb.c                       |  120 +++++----
 hald/freebsd/hf-usb.h                       |    3 
 hald/freebsd/hf-usb2.c                      |  287 +++++++++++++++++++++
 hald/freebsd/hf-usb2.h                      |   37 ++
 hald/freebsd/hf-volume.c                    |   72 +++++
 hald/freebsd/libprobe/hfp.c                 |   32 +-
 hald/freebsd/libprobe/hfp.h                 |   14 -
 hald/freebsd/osspec.c                       |    9 
 hald/freebsd/probing/Makefile.am            |   35 ++
 hald/freebsd/probing/probe-hiddev.c         |   14 +
 hald/freebsd/probing/probe-mouse.c          |  312 +++++++++++++++++++++++
 hald/freebsd/probing/probe-storage.c        |   23 +
 hald/freebsd/probing/probe-usb2-device.c    |  208 +++++++++++++++
 hald/freebsd/probing/probe-usb2-interface.c |  140 ++++++++++
 hald/freebsd/probing/probe-volume.c         |   42 +++
 26 files changed, 2065 insertions(+), 146 deletions(-)

New commits:
commit f14c71d9b70df8787d77da7b9671f9fcdbf0cd63
Author: Joe Marcus Clarke <marcus at FreeBSD.org>
Date:   Tue Aug 18 13:16:24 2009 -0400

    update time handling functions
    
    Opt to use timespec rather than timeval in the probe time handling
    functions.

diff --git a/hald/freebsd/libprobe/hfp.c b/hald/freebsd/libprobe/hfp.c
index 7d16bae..3c34b75 100644
--- a/hald/freebsd/libprobe/hfp.c
+++ b/hald/freebsd/libprobe/hfp.c
@@ -216,55 +216,59 @@ hfp_getenv_bool (const char *variable)
 }
 
 void
-hfp_gettimeofday (struct timeval *t)
+hfp_clock_gettime (struct timespec *t)
 {
   int status;
 
   assert(t != NULL);
 
-  status = gettimeofday(t, NULL);
+#ifdef CLOCK_MONOTONIC_FAST
+  status = clock_gettime(CLOCK_MONOTONIC_FAST, t);
+#else
+  status = clock_gettime(CLOCK_MONOTONIC, t);
+#endif
   assert(status == 0);
 }
 
-/* timeval functions from sys/kern/kern_time.c */
+/* timespec functions from sys/kern/kern_time.c */
 
 static void
-hfp_timevalfix (struct timeval *t)
+hfp_timespecfix (struct timespec *t)
 {
   assert(t != NULL);
 
-  if (t->tv_usec < 0)
+  if (t->tv_nsec < 0)
     {
       t->tv_sec--;
-      t->tv_usec += 1000000;
+      t->tv_nsec += 1000000000;
     }
-  if (t->tv_usec >= 1000000)
+  if (t->tv_nsec >= 1000000000)
     {
       t->tv_sec++;
-      t->tv_usec -= 1000000;
+      t->tv_nsec -= 1000000000;
     }
 }
 
 void
-hfp_timevaladd (struct timeval *t1, const struct timeval *t2)
+hfp_timespecadd (struct timespec *t1, const struct timespec *t2)
 {
   assert(t1 != NULL);
   assert(t2 != NULL);
 
   t1->tv_sec += t2->tv_sec;
-  t1->tv_usec += t2->tv_usec;
+  t1->tv_nsec += t2->tv_nsec;
 
-  hfp_timevalfix(t1);
+  hfp_timespecfix(t1);
 }
 
 void
-hfp_timevalsub (struct timeval *t1, const struct timeval *t2)
+hfp_timespecsub (struct timespec *t1, const struct timespec *t2)
 {
   assert(t1 != NULL);
   assert(t2 != NULL);
 
   t1->tv_sec -= t2->tv_sec;
-  t1->tv_usec -= t2->tv_usec;
+  t1->tv_nsec -= t2->tv_nsec;
 
-  hfp_timevalfix(t1);
+  hfp_timespecfix(t1);
 }
diff --git a/hald/freebsd/libprobe/hfp.h b/hald/freebsd/libprobe/hfp.h
index 1d95811..2332588 100644
--- a/hald/freebsd/libprobe/hfp.h
+++ b/hald/freebsd/libprobe/hfp.h
@@ -29,8 +29,12 @@
 #endif
 
 #include <stdarg.h>
+#include <time.h>
 #include <sys/types.h>
+#include <sys/param.h>
+#if __FreeBSD_version < 600000
 #include <sys/time.h>
+#endif
 
 #include "libhal/libhal.h"
 
@@ -84,14 +88,14 @@ void volume_id_log (const char *format, ...) HFP_GNUC_PRINTF(1, 2);
 
 boolean hfp_getenv_bool (const char *variable);
 
-void hfp_gettimeofday (struct timeval *t);
-void hfp_timevaladd (struct timeval *t1, const struct timeval *t2);
-void hfp_timevalsub (struct timeval *t1, const struct timeval *t2);
+void hfp_clock_gettime (struct timespec *t);
+void hfp_timespecadd (struct timespec *t1, const struct timespec *t2);
+void hfp_timespecsub (struct timespec *t1, const struct timespec *t2);
 
 /* from sys/time.h (_KERNEL) */
-#define hfp_timevalcmp(t1, t2, cmp) \
+#define hfp_timespeccmp(t1, t2, cmp) \
   (((t1)->tv_sec == (t2)->tv_sec	\
-    ? ((t1)->tv_usec cmp (t2)->tv_usec)	\
+    ? ((t1)->tv_nsec cmp (t2)->tv_nsec)	\
     : ((t1)->tv_sec cmp (t2)->tv_sec)))
 
 #endif /* _HFP_H */
commit 4043c559e75d24735d4b25170fa7d03f7c949148
Author: Joe Marcus Clarke <marcus at FreeBSD.org>
Date:   Tue Aug 18 13:14:40 2009 -0400

    add locking support to the storage addon
    
    Sync a lot of ideas from the Linux backend so that the FreeBSD storage
    addon honors device locking.  Additionally, add the ability to forcibly
    unmount a volume if its media is removed (but only on recent -CURRENT).

diff --git a/hald/freebsd/addons/addon-storage.c b/hald/freebsd/addons/addon-storage.c
index dcd9cdc..3125037 100644
--- a/hald/freebsd/addons/addon-storage.c
+++ b/hald/freebsd/addons/addon-storage.c
@@ -36,17 +36,24 @@
 #include "../libprobe/hfp.h"
 #include "../libprobe/hfp-cdrom.h"
 
+static boolean is_locked_by_hal = FALSE;
+static boolean check_lock_state = TRUE;
+static boolean polling_disabled = FALSE;
+
 static struct
 {
-  const struct timeval	update_interval;
+  const struct timespec	update_interval;
   char			*device_file;
   char			*parent;
   boolean		is_cdrom;
   boolean		is_scsi_removable;
   boolean		had_media;
-  struct timeval	next_update;
+  struct timespec	next_update;
 } addon = { { 2, 0 } };
 
+static void update_proc_title (const char *device);
+static void unmount_volumes (void);
+
 /* see MMC-3 Working Draft Revision 10 */
 static boolean
 hf_addon_storage_cdrom_eject_pressed (HFPCDROM *cdrom)
@@ -144,18 +151,148 @@ hf_addon_storage_update (void)
 	}
     }
 
-  hfp_gettimeofday(&addon.next_update);
-  hfp_timevaladd(&addon.next_update, &addon.update_interval);
-
   return has_media;
 }
 
+static void
+unmount_volumes (void)
+{
+  int num_volumes;
+  char **volumes;
+
+  if ((volumes = libhal_manager_find_device_string_match(hfp_ctx,
+                                                         "block.storage_device",
+							 hfp_udi,
+							 &num_volumes,
+							 &hfp_error)) != NULL)
+    {
+      int i;
+
+      dbus_error_free(&hfp_error);
+
+      for (i = 0; i < num_volumes; i++)
+        {
+          char *vol_udi;
+
+	  vol_udi = volumes[i];
+
+	  if (libhal_device_get_property_bool(hfp_ctx, vol_udi, "volume.is_mounted", &hfp_error))
+            {
+              DBusMessage *msg = NULL;
+	      DBusMessage *reply = NULL;
+	      DBusConnection *dbus_connection;
+	      unsigned int num_options = 0;
+	      char **options = NULL;
+	      char *devfile;
+
+	      dbus_error_free(&hfp_error);
+              hfp_info("Forcing unmount of volume '%s'", vol_udi);
+
+	      dbus_connection = libhal_ctx_get_dbus_connection(hfp_ctx);
+	      msg = dbus_message_new_method_call("org.freedesktop.Hal", vol_udi,
+                                                 "org.freedesktop.Hal.Device.Volume",
+						 "Unmount");
+	      if (msg == NULL)
+                {
+                  hfp_warning("Could not create dbus message for %s", vol_udi);
+		  continue;
+		}
+
+	      options = calloc(1, sizeof (char *));
+	      if (options == NULL)
+                {
+                  hfp_warning("Could not allocation memory for options");
+		  dbus_message_unref(msg);
+		  continue;
+		}
+
+	      options[0] = "force";
+	      num_options = 1;
+
+	      devfile = libhal_device_get_property_string(hfp_ctx, vol_udi, "block.device", NULL);
+	      if (devfile != NULL)
+                {
+                  hfp_info("Forcibly attempting to unmount %s as media was removed", devfile);
+		  libhal_free_string(devfile);
+		}
+
+	      if (! dbus_message_append_args(msg, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, num_options, DBUS_TYPE_INVALID))
+                 {
+                   hfp_warning("Could not append args to dbus message for %s", vol_udi);
+		   free(options);
+		   dbus_message_unref(msg);
+		   continue;
+		 }
+
+	      if (! (reply = dbus_connection_send_with_reply_and_block(dbus_connection, msg, -1, &hfp_error)))
+                {
+                  hfp_warning("Unmount failed for %s: %s: %s", vol_udi, hfp_error.name, hfp_error.message);
+		  dbus_error_free(&hfp_error);
+		  free(options);
+		  dbus_message_unref(msg);
+		  continue;
+		}
+
+	      if (dbus_error_is_set(&hfp_error))
+                {
+                  hfp_warning("Unmount failed for %s: %s : %s", vol_udi, hfp_error.name, hfp_error.message);
+		  dbus_error_free(&hfp_error);
+		  free(options);
+		  dbus_message_unref(msg);
+		  dbus_message_unref(reply);
+		  continue;
+		}
+
+	      hfp_info("Successfully unmounted udi '%s'", vol_udi);
+	      free(options);
+              dbus_message_unref(msg);
+              dbus_message_unref(reply);
+	    }
+	}
+      libhal_free_string_array(volumes);
+    }
+}
+
 static boolean
-poll_for_media (void)
+poll_for_media (boolean check_only, boolean force)
 {
   boolean has_media;
 
+  if (check_lock_state)
+    {
+      boolean should_poll;
+
+      check_lock_state = FALSE;
+
+      hfp_info("Checking whether device %s is locked by HAL", addon.device_file);
+      if (libhal_device_is_locked_by_others(hfp_ctx, hfp_udi, "org.freedesktop.Hal.Device.Storage", &hfp_error))
+        {
+          hfp_info("... device %s is locked by HAL", addon.device_file);
+	  dbus_error_free(&hfp_error);
+	  is_locked_by_hal = TRUE;
+	  update_proc_title(addon.device_file);
+	  goto skip_check;
+	}
+      else
+        {
+          hfp_info("... device %s is not locked by HAL", addon.device_file);
+	  is_locked_by_hal = FALSE;
+	}
+      dbus_error_free(&hfp_error);
+
+      should_poll = libhal_device_get_property_bool(hfp_ctx, hfp_udi, "storage.media_check_enabled", &hfp_error);
+      dbus_error_free(&hfp_error);
+      polling_disabled = ! should_poll;
+      update_proc_title(addon.device_file);
+    }
+
+  if (! force && polling_disabled)
+    goto skip_check;
+
   has_media = hf_addon_storage_update();
+  if (check_only)
+    return has_media;
+
   if (has_media != addon.had_media)
     {
       /*
@@ -168,6 +305,14 @@ poll_for_media (void)
        * then hung while rebooting and did not unmount my other
        * filesystems.
        */
+#if __FreeBSD_version >= 800066
+      /*
+       * With newusb, it is safe to force unmount volumes.  This may be
+       * safe on newer versions of the old USB stack, but we'll be
+       * extra cautious.
+       */
+      unmount_volumes();
+#endif
 
       libhal_device_rescan(hfp_ctx, hfp_udi, &hfp_error);
       dbus_error_free(&hfp_error);
@@ -175,20 +320,33 @@ poll_for_media (void)
 
       return TRUE;
     }
+
+skip_check:
+
   return FALSE;
 }
 
 static void
-update_proc_title (const char *device, boolean polling_enabled)
+update_proc_title (const char *device)
 {
-  if (polling_enabled)
-    setproctitle("%s", device);
-  else
+  if (polling_disabled)
     setproctitle("no polling on %s because it is explicitly disabled", device);
+  else if (is_locked_by_hal)
+    setproctitle("no polling on %s because it is locked by HAL", device);
+  else
+    setproctitle("%s", device);
 }
 
 static DBusHandlerResult
-filter_function (DBusConnection *connection, DBusMessage *message, void *user_data)
+dbus_filter_function (DBusConnection *connection, DBusMessage *message, void *user_data)
+{
+  check_lock_state = TRUE;
+
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+direct_filter_function (DBusConnection *connection, DBusMessage *message, void *user_data)
 {
   if (dbus_message_is_method_call(message,
 			  	  "org.freedesktop.Hal.Device.Storage.Removable",
@@ -199,7 +357,7 @@ filter_function (DBusConnection *connection, DBusMessage *message, void *user_da
 
       hfp_info("Forcing poll for media becusse CheckForMedia() was called");
 
-      had_effect = poll_for_media();
+      had_effect = poll_for_media(FALSE, TRUE);
 
       reply = dbus_message_new_method_return (message);
       dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &had_effect, DBUS_TYPE_INVALID);
@@ -217,8 +375,9 @@ main (int argc, char **argv)
   char *removable;
   char *bus;
   char *driver;
-  boolean should_poll;
+  char *filter_str;
   DBusConnection *connection;
+  DBusConnection *syscon;
 
   if (! hfp_init(argc, argv))
     goto end;
@@ -251,16 +410,41 @@ main (int argc, char **argv)
   addon.is_scsi_removable = (! strcmp(bus, "scsi") ||
     (! strcmp(bus, "usb") && (! strcmp(driver, "da") || ! strcmp(driver, "sa") ||
     ! strcmp(driver, "cd")))) && ! strcmp(removable, "true");
-  addon.had_media = hf_addon_storage_update();
+  addon.had_media = poll_for_media(TRUE, FALSE);
 
   if (! libhal_device_addon_is_ready(hfp_ctx, hfp_udi, &hfp_error))
     goto end;
   dbus_error_free(&hfp_error);
 
+  syscon = dbus_bus_get(DBUS_BUS_SYSTEM, &hfp_error);
+  dbus_error_free(&hfp_error);
+  assert(syscon != NULL);
+  dbus_connection_set_exit_on_disconnect(syscon, 0);
+
+  dbus_bus_add_match(syscon,
+		     "type='signal'"
+		     ",interface='org.freedesktop.Hal.Manager'"
+		     ",sender='org.freedesktop.Hal'",
+		     NULL);
+  dbus_bus_add_match(syscon,
+		     "type='signal'"
+		     ",interface='org.freedesktop.Hal.Manager'"
+		     ",sender='org.freedesktop.Hal'",
+		     NULL);
+  filter_str = hfp_strdup_printf("type='signal'"
+		  	       ",interface='org.freedesktop.Hal.Device'"
+			       ",sender='org.freedesktop.Hal'"
+			       ",path='%s'",
+			       hfp_udi);
+  dbus_bus_add_match(syscon, filter_str, NULL);
+  hfp_free(filter_str);
+
+  dbus_connection_add_filter(syscon, dbus_filter_function, NULL, NULL);
+
   connection = libhal_ctx_get_dbus_connection(hfp_ctx);
   assert(connection != NULL);
   dbus_connection_set_exit_on_disconnect(connection, 0);
-  dbus_connection_add_filter(connection, filter_function, NULL, NULL);
+  dbus_connection_add_filter(connection, direct_filter_function, NULL, NULL);
 
   if (! libhal_device_claim_interface(hfp_ctx,
 			 	      hfp_udi,
@@ -280,40 +464,32 @@ main (int argc, char **argv)
       /* process dbus traffic until update interval has elapsed */
       while (TRUE)
 	{
-	  struct timeval now;
+	  struct timespec now;
 
-	  hfp_gettimeofday(&now);
-	  if (hfp_timevalcmp(&now, &addon.next_update, <))
+	  hfp_clock_gettime(&now);
+	  if (hfp_timespeccmp(&now, &addon.next_update, <))
 	    {
-	      struct timeval timeout;
+	      struct timespec timeout;
 
 	      timeout = addon.next_update;
-	      hfp_timevalsub(&timeout, &now);
+	      hfp_timespecsub(&timeout, &now);
 
 	      if (timeout.tv_sec < 0) /* current time went backwards */
 		timeout = addon.update_interval;
 
-	      dbus_connection_read_write_dispatch(connection, timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
-	      if (! dbus_connection_get_is_connected(connection))
+	      dbus_connection_read_write_dispatch(connection, (int) ((timeout.tv_sec * 1000 + timeout.tv_nsec / 1000000) / 2));
+	      dbus_connection_read_write_dispatch(syscon, (int) ((timeout.tv_sec * 1000 + timeout.tv_nsec / 1000000) / 2));
+	      if (! dbus_connection_get_is_connected(connection) ||
+		  ! dbus_connection_get_is_connected(syscon))
 		goto end;
 	    }
 	  else
 	    break;
 	}
 
-      should_poll = libhal_device_get_property_bool(hfp_ctx, hfp_udi, "storage.media_check_enabled", &hfp_error);
-      dbus_error_free(&hfp_error);
-      update_proc_title(addon.device_file, should_poll);
-
-      if (should_poll)
-        {
-          poll_for_media();
-        }
-      else
-        {
-          hfp_gettimeofday(&addon.next_update);
-	  hfp_timevaladd(&addon.next_update, &addon.update_interval);
-	}
+      poll_for_media(FALSE, FALSE);
+      hfp_clock_gettime(&addon.next_update);
+      hfp_timespecadd(&addon.next_update, &addon.update_interval);
     }
 
  end:
commit 47a90727d13549fa1eea34dc9d13f75784bd3fb6
Author: Joe Marcus Clarke <marcus at FreeBSD.org>
Date:   Tue Aug 18 13:13:35 2009 -0400

    add missing LDADD and CFLAGS for addon-mouse.c
    
    The mouse addon requires Glib.  Add the necessary CFLAGS and LDADD
    statements.

diff --git a/hald/freebsd/addons/Makefile.am b/hald/freebsd/addons/Makefile.am
index d82cad0..c2a68ba 100644
--- a/hald/freebsd/addons/Makefile.am
+++ b/hald/freebsd/addons/Makefile.am
@@ -17,6 +17,8 @@ hald_addon_storage_LDADD = \
 	$(top_builddir)/hald/freebsd/libprobe/libhald_freebsd_probe.la
 
 hald_addon_mouse_sysmouse_SOURCES = addon-mouse.c
+hald_addon_mouse_sysmouse_CFLAGS = $(AM_CPPFLAGS) @GLIB_CFLAGS@
 hald_addon_mouse_sysmouse_LDADD = \
+	@GLIB_LIBS@		  \
 	-lutil			  \
 	$(top_builddir)/hald/freebsd/libprobe/libhald_freebsd_probe.la
commit f7527830532bd9269825f543cc16878b7b474f92
Author: Joe Marcus Clarke <marcus at FreeBSD.org>
Date:   Tue Aug 18 13:11:45 2009 -0400

    add support for polling of mouse devices
    
    When a mouse device is inserted, watch it with an addon to see if the
    owner changes from X to sysmouse or vice versa.

diff --git a/hald/freebsd/addons/Makefile.am b/hald/freebsd/addons/Makefile.am
index 25cf0df..d82cad0 100644
--- a/hald/freebsd/addons/Makefile.am
+++ b/hald/freebsd/addons/Makefile.am
@@ -8,9 +8,15 @@ AM_CPPFLAGS = \
 	@DBUS_CFLAGS@
 
 if HALD_COMPILE_FREEBSD
-libexec_PROGRAMS = hald-addon-storage
+libexec_PROGRAMS = hald-addon-storage \
+		   hald-addon-mouse-sysmouse
 endif
 
 hald_addon_storage_SOURCES = addon-storage.c
 hald_addon_storage_LDADD = \
 	$(top_builddir)/hald/freebsd/libprobe/libhald_freebsd_probe.la
+
+hald_addon_mouse_sysmouse_SOURCES = addon-mouse.c
+hald_addon_mouse_sysmouse_LDADD = \
+	-lutil			  \
+	$(top_builddir)/hald/freebsd/libprobe/libhald_freebsd_probe.la
diff --git a/hald/freebsd/addons/addon-mouse.c b/hald/freebsd/addons/addon-mouse.c
new file mode 100644
index 0000000..51194ca
--- /dev/null
+++ b/hald/freebsd/addons/addon-mouse.c
@@ -0,0 +1,371 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * addon-mouse.c : poll mice to disable moused(8) owned devices
+ *
+ * Copyright (C) 2008 Joe Marcus Clarke
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#if __FreeBSD_version >= 800058
+#include <sys/types.h>
+#include <sys/user.h>
+#include <sys/sysctl.h>
+#include <libutil.h>
+#endif
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <unistd.h>
+#include <glib.h>
+
+#include "libhal/libhal.h"
+
+#include "../libprobe/hfp.h"
+
+#if __FreeBSD_version < 800058
+#define CMD "/usr/bin/fstat %s"
+#endif
+
+#define MOUSED_DEVICE "/dev/sysmouse"
+#define MOUSED_PROC_NAME "moused"
+#define XORG_PROC_NAME "Xorg"
+#define NO_PID -1
+
+static struct
+{
+  const struct timespec        update_interval;
+  char                        *device_file;
+  struct timespec              next_update;
+} addon = { { 2, 0 } };
+
+static int kd = -1;
+
+#if __FreeBSD_version >= 800058
+static struct kinfo_proc *
+hfp_kinfo_getproc (int *cntp)
+{
+  int mib[3];
+  int error;
+  int cnt;
+  size_t len;
+  char *buf, *bp, *eb;
+  struct kinfo_proc *kip, *kp, *ki;
+
+  *cntp = 0;
+
+  len = 0;
+  mib[0] = CTL_KERN;
+  mib[1] = KERN_PROC;
+  mib[2] = KERN_PROC_PROC;
+
+  error = sysctl(mib, 3, NULL, &len, NULL, 0);
+  if (error)
+    return NULL;
+
+  len = len * 4 / 3;
+  buf = (char *) g_malloc(len);
+  if (buf == NULL)
+    return NULL;
+
+  error = sysctl(mib, 3, buf, &len, NULL, 0);
+  if (error)
+    {
+      g_free(buf);
+      return NULL;
+    }
+
+  cnt = 0;
+  bp = buf;
+  eb = buf + len;
+  while (bp < eb)
+    {
+      ki =  (struct kinfo_proc *) (uintptr_t) bp;
+      bp += ki->ki_structsize;
+      cnt++;
+    }
+
+  kip = calloc(cnt, sizeof (*kip));
+  if (kip == NULL)
+    {
+      g_free(buf);
+      return NULL;
+    }
+
+  bp = buf;
+  eb = buf + len;
+  kp = kip;
+  while (bp < eb)
+    {
+      ki = (struct kinfo_proc *) (uintptr_t) bp;
+      memcpy(kp, ki, ki->ki_structsize);
+      bp += ki->ki_structsize;
+      kp->ki_structsize = sizeof(*kp);
+      kp++;
+    }
+
+  g_free(buf);
+  *cntp = cnt;
+  return kip;
+}
+
+static gboolean
+device_opened_by_proc (const char *device, const char *proc, pid_t *pid)
+{
+  struct kinfo_proc *kip, *pfreep;
+  int cnt, i;
+
+  *pid = NO_PID;
+
+  pfreep = hfp_kinfo_getproc(&cnt);
+  if (pfreep == NULL)
+    return FALSE;
+
+  for (i = 0; i < cnt; i++)
+    {
+      kip = &pfreep[i];
+
+      if (! strcmp(kip->ki_comm, proc))
+        {
+          struct kinfo_file *kif, *ffreep;
+          int fcnt, j;
+
+          ffreep = kinfo_getfile(kip->ki_pid, &fcnt);
+          if (ffreep == NULL)
+                  continue;
+          for (j = 0; j < fcnt; j++)
+            {
+              kif = &ffreep[j];
+
+              if (kif->kf_type == KF_TYPE_VNODE &&
+                  ! strcmp(kif->kf_path, device))
+                {
+		  *pid = kip->ki_pid;
+                  g_free(ffreep);
+                  g_free(pfreep);
+                  return TRUE;
+                }
+            }
+          g_free(ffreep);
+        }
+    }
+  g_free(pfreep);
+
+  return FALSE;
+}
+#else
+static gboolean
+device_opened_by_proc (const char *device, const char *proc, pid_t *pid)
+{
+  char **lines;
+  char *output = NULL;
+  char *cmd;
+  int i;
+  gboolean found = FALSE;
+
+  cmd = g_strdup_printf(CMD, device);
+  *pid = NO_PID;
+
+  if (! g_spawn_command_line_sync(cmd, &output, NULL, NULL, NULL))
+    {
+      g_free(cmd);
+      goto done;
+    }
+  g_free(cmd);
+
+  if (! output || strlen(output) == 0)
+    goto done;
+
+  lines = g_strsplit(output, "\n", 0);
+  if (g_strv_length(lines) < 2)
+    {
+      g_strfreev(lines);
+      goto done;
+    }
+
+  for (i = 1; lines[i]; i++)
+    {
+      char **fields;
+      guint len;
+      guint j;
+
+      fields = g_strsplit_set(lines[i], " ", 0);
+      len = g_strv_length(fields);
+      if (len < 3)
+        {
+          g_strfreev(fields);
+          continue;
+        }
+      for (j = 1; j < len && fields[j] && *fields[j] == '\0'; j++)
+        ;
+      if (j < len && fields[j] && ! strcmp(fields[j], proc))
+        {
+          found = TRUE;
+	  for (++j; j < len && fields[j] && *fields[j] == '\0'; j++)
+	    ;
+	  if (j < len && fields[j])
+	    *pid = atoi(fields[j]);
+          g_strfreev(fields);
+          break;
+        }
+      g_strfreev(fields);
+    }
+
+  g_strfreev(lines);
+
+done:
+  g_free(output);
+
+  return found;
+}
+#endif
+
+static const char *
+get_mouse_device (const char *device, pid_t *pid)
+{
+  if (device_opened_by_proc(device, MOUSED_PROC_NAME, pid))
+    return MOUSED_DEVICE;
+
+  return device;
+}
+
+static void
+poll_for_moused (void)
+{
+  struct kevent ev;
+  const char *device;
+  gboolean found;
+  pid_t pid;
+  char *owner = NULL;
+  char *prev_owner = NULL;
+
+again:
+  device = get_mouse_device(addon.device_file, &pid);
+  if (pid != NO_PID)
+    {
+      EV_SET(&ev, pid, EVFILT_PROC, EV_ADD | EV_ENABLE, NOTE_EXIT, 0, NULL);
+      if (kevent(kd, &ev, 1, NULL, 0, NULL) < 0)
+        return;
+      g_free(owner);
+      owner = g_strdup(MOUSED_PROC_NAME);
+    }
+  else
+    {
+      found = device_opened_by_proc(device, XORG_PROC_NAME, &pid);
+      if (found && pid != NO_PID)
+        {
+          EV_SET(&ev, pid, EVFILT_PROC, EV_ADD | EV_ENABLE, NOTE_EXIT, 0, NULL);
+	  if (kevent(kd, &ev, 1, NULL, 0, NULL) < 0)
+            return;
+          g_free(owner);
+	  owner = g_strdup(XORG_PROC_NAME);
+	}
+      else
+        goto out;
+    }
+
+  if (owner && prev_owner && strcmp(owner, prev_owner))
+    goto out;
+
+  if (kevent(kd, NULL, 0, &ev, 1, NULL) < 0)
+    return;
+
+  sleep(3);
+  g_free(prev_owner);
+  prev_owner = NULL;
+  if (owner)
+    prev_owner = g_strdup(owner);
+  goto again;
+
+out:
+  if (owner)
+    {
+      libhal_device_reprobe(hfp_ctx, hfp_udi, &hfp_error);
+      dbus_error_free(&hfp_error);
+    }
+  g_free(owner);
+  g_free(prev_owner);
+}
+
+int
+main (int argc, char **argv)
+{
+  DBusConnection *connection;
+
+  if (! hfp_init(argc, argv))
+    goto end;
+
+  addon.device_file = getenv("HAL_PROP_FREEBSD_DEVICE_FILE");
+  if (! addon.device_file)
+    goto end;
+
+  setproctitle("%s", addon.device_file);
+
+  if (! libhal_device_addon_is_ready(hfp_ctx, hfp_udi, &hfp_error))
+    goto end;
+  dbus_error_free(&hfp_error);
+
+  connection = libhal_ctx_get_dbus_connection(hfp_ctx);
+  assert(connection != NULL);
+
+  kd = kqueue();
+  assert(kd > -1);
+
+  while (TRUE)
+    {
+      /* process dbus traffic until update interval has elapsed */
+      while (TRUE)
+        {
+          struct timespec now;
+
+          hfp_clock_gettime(&now);
+          if (hfp_timespeccmp(&now, &addon.next_update, <))
+            {
+              struct timespec timeout;
+
+              timeout = addon.next_update;
+              hfp_timespecsub(&timeout, &now);
+
+              if (timeout.tv_sec < 0) /* current time went backwards */
+                timeout = addon.update_interval;
+
+              dbus_connection_read_write_dispatch(connection, timeout.tv_sec * 1000 + timeout.tv_nsec / 1000000);
+              if (! dbus_connection_get_is_connected(connection))
+                goto end;
+            }
+          else
+            break;
+        }
+
+      poll_for_moused();
+
+      hfp_clock_gettime(&addon.next_update);
+      hfp_timespecadd(&addon.next_update, &addon.update_interval);
+    }
+
+ end:
+  return 0;
+}
commit 6623b1cfcae1d52b3ccb45689dbcd0a655de1fdf
Author: Joe Marcus Clarke <marcus at FreeBSD.org>
Date:   Tue Aug 18 13:08:50 2009 -0400

    add support for newer GEOM types
    
    Add support for newer GEOM kernel modules, and make polling for new
    disks more efficient.

diff --git a/hald/freebsd/hf-storage.c b/hald/freebsd/hf-storage.c
index b901d9d..3bc5ab9 100644
--- a/hald/freebsd/hf-storage.c
+++ b/hald/freebsd/hf-storage.c
@@ -30,6 +30,7 @@
 #include <limits.h>
 #include <inttypes.h>
 #include <string.h>
+#include <sys/param.h>
 #include <sys/types.h>
 #include <sys/disklabel.h>
 
@@ -38,6 +39,7 @@
 
 #include "hf-storage.h"
 #include "hf-block.h"
+#include "hf-devd.h"
 #include "hf-devtree.h"
 #include "hf-volume.h"
 #include "hf-util.h"
@@ -64,7 +66,7 @@ typedef struct
 static GNode *hf_storage_geom_tree = NULL;
 static GHashTable *hf_storage_geom_hash = NULL;
 
-static void hf_storage_init_geom (void);
+static void hf_storage_init_geom (gboolean force);
 static gboolean hf_storage_device_has_addon (HalDevice *device);
 
 static void
@@ -104,6 +106,8 @@ hf_storage_class_is_partitionable (const char *geom_class)
 {
   return (! strcmp(geom_class, "MBR") ||
           ! strcmp(geom_class, "MBREXT") ||
+	  ! strcmp(geom_class, "PART") ||
+	  ! strcmp(geom_class, "JOURNAL") ||
 	  ! strcmp(geom_class, "GPT") ||
           ! strcmp(geom_class, "APPLE") || ! strcmp(geom_class, "SUN"));
 }
@@ -117,6 +121,7 @@ hf_storage_geom_has_partitions (const Geom_Object *geom_obj, GNode *node)
   if (g_node_n_children(node) > 0)
     return TRUE;
 
+  /*
   if (hf_storage_class_is_partitionable(geom_obj->class) &&
       g_node_next_sibling(node) != NULL)
     {
@@ -135,6 +140,7 @@ hf_storage_geom_has_partitions (const Geom_Object *geom_obj, GNode *node)
             return TRUE;
         }
     }
+    */
 
   return FALSE;
 }
@@ -294,7 +300,7 @@ hf_storage_device_probe (HalDevice *device, gboolean only_media)
 {
   g_return_if_fail(HAL_IS_DEVICE(device));
 
-  hf_storage_init_geom();
+  hf_storage_init_geom(TRUE);
 
   if (hf_runner_run_sync(device, 0, "hald-probe-storage",
 			 "HF_HAS_CHILDREN", HF_BOOL_TO_STRING(hf_storage_device_has_partitions(device)),
@@ -403,13 +409,20 @@ hf_storage_parse_conftxt (const char *conftxt)
           continue;
 	}
 
+      depth = atoi(fields[0]);
+      hash = g_str_hash(fields[2]);
+      if (g_hash_table_lookup(table, GUINT_TO_POINTER(hash)) != NULL)
+        {
+          g_strfreev(fields);
+	  curr_depth = depth;
+	  continue;
+	}
+
       geom_obj = g_new0(Geom_Object, 1);
 
-      depth = atoi(fields[0]);
       geom_obj->class = g_strdup(fields[1]);
       geom_obj->dev = g_strdup(fields[2]);
       geom_obj->type = -1;	/* We use -1 here to denote a missing type. */
-      hash = g_str_hash(geom_obj->dev);
       geom_obj->hash = hash;
 
       if (g_strv_length(fields) >= 5)
@@ -433,6 +446,30 @@ hf_storage_parse_conftxt (const char *conftxt)
               if (! strcmp (geom_obj->class, "GPT") ||
                   ! strcmp (geom_obj->class, "APPLE"))
                 geom_obj->str_type = g_strdup(fields[10]);
+	      else if (! strcmp (geom_obj->class, "PART"))
+                {
+		  geom_obj->str_type = g_strdup(fields[10]);
+                  if (g_strv_length(fields) >= 15)
+                    {
+                      if (! strcmp(fields[13], "xt"))
+                        {
+                          geom_obj->type = atoi(fields[14]);
+			  if (! strcmp(fields[11], "xs"))
+                            {
+                              g_free(geom_obj->class);
+			      geom_obj->class = g_strdup(fields[12]);
+			    }
+			}
+		    }
+		}
+	      else if (fields[10][0] == '!')
+                {
+                  char *nottype;
+
+		  nottype = fields[10];
+		  nottype++;
+                  geom_obj->type = atoi(nottype);
+		}
 	      else
                 geom_obj->type = atoi(fields[10]);
 	    }
@@ -541,15 +578,20 @@ hf_storage_device_rescan_real (HalDevice *device)
 }
 
 static gboolean
-hf_storage_conftxt_timeout_cb (gpointer data)
+hf_storage_devd_notify (const char *system,
+		        const char *subsystem,
+			const char *type,
+			const char *data)
 {
   static GSList *disks = NULL;
   static gboolean first = TRUE;
+  gboolean handled = FALSE;
   char *conftxt;
   GSList *new_disks;
 
-  if (hf_is_waiting)
-    return TRUE;
+  if (strcmp(system, "DEVFS") || strcmp(subsystem, "CDEV") ||
+      (strcmp(type, "CREATE") && strcmp(type, "DESTROY")))
+    return FALSE;
 
   conftxt = hf_get_string_sysctl(NULL, "kern.geom.conftxt");
   new_disks = hf_storage_parse_conftxt(conftxt);
@@ -572,6 +614,7 @@ hf_storage_conftxt_timeout_cb (gpointer data)
 	  if (! hf_storage_find_disk(disks, disk->name))
 	    {
 	      osspec_probe();	/* catch new disk(s) */
+	      handled = TRUE;
 	      break;
 	    }
 	}
@@ -593,7 +636,10 @@ hf_storage_conftxt_timeout_cb (gpointer data)
 		  device = hf_devtree_find_from_name(hald_get_gdl(), disk->name);
 		  if (device && hal_device_has_capability(device, "storage") &&
 		      ! hf_storage_device_has_addon(device))
-		    hf_storage_device_rescan_real(device);
+		    {
+		      hf_storage_device_rescan_real(device);
+		      handled = TRUE;
+		    }
 		}
 	    }
 	  else
@@ -601,7 +647,10 @@ hf_storage_conftxt_timeout_cb (gpointer data)
 	      /* disk removed */
 	      device = hf_devtree_find_from_name(hald_get_gdl(), disk->name);
 	      if (device && hal_device_has_capability(device, "storage"))
-	        hf_device_remove_tree(device);
+		{
+	          hf_device_remove_tree(device);
+		  handled = TRUE;
+		}
 	    }
 	}
     }
@@ -610,17 +659,30 @@ hf_storage_conftxt_timeout_cb (gpointer data)
   g_slist_free(disks);
   disks = new_disks;
 
+  return handled;
+}
+
+#if __FreeBSD_version < 700110
+static gboolean
+hf_storage_conftxt_timeout_cb (gpointer data)
+{
+  if (hf_is_waiting)
+    return TRUE;
+
+  hf_storage_devd_notify("DEVFS", "CDEV", "CREATE", NULL);
+
   return TRUE;
 }
+#endif
 
 static void
-hf_storage_init_geom (void)
+hf_storage_init_geom (gboolean force)
 {
   char *conftxt;
   static gboolean inited = FALSE;
   GSList *disks;
 
-  if (inited)
+  if (inited && ! force)
     return;
 
   conftxt = hf_get_string_sysctl(NULL, "kern.geom.conftxt");
@@ -636,8 +698,10 @@ hf_storage_init_geom (void)
 static void
 hf_storage_init (void)
 {
-  hf_storage_init_geom();
+  hf_storage_init_geom(FALSE);
+#if __FreeBSD_version < 700110
   g_timeout_add(3000, hf_storage_conftxt_timeout_cb, NULL);
+#endif
 }
 
 void
@@ -719,8 +783,6 @@ hf_storage_device_add (HalDevice *device)
 {
   g_return_if_fail(HAL_IS_DEVICE(device));
 
-  hf_storage_init_geom();
-
   if (hf_device_preprobe(device))
     {
       hf_storage_device_probe(device, FALSE);
@@ -738,7 +800,7 @@ hf_storage_get_geoms (const char *devname)
 
   g_return_val_if_fail(devname != NULL, NULL);
 
-  hf_storage_init_geom();
+  hf_storage_init_geom(FALSE);
 
   hash = g_str_hash(devname);
   node = g_node_find(hf_storage_geom_tree, G_PRE_ORDER, G_TRAVERSE_ALL,
@@ -801,3 +863,7 @@ HFHandler hf_storage_handler = {
   .probe =		hf_storage_probe,
   .device_rescan =	hf_storage_device_rescan
 };
+
+HFDevdHandler hf_storage_devd_handler = {
+  .notify =	hf_storage_devd_notify
+};
commit 0cc145355e980d62ebe81a6c6075a534308a0479
Author: Joe Marcus Clarke <marcus at FreeBSD.org>
Date:   Tue Aug 18 13:07:20 2009 -0400

    add support for Fuse mounts
    
    Add support for mounting Fuse volumes in the FreeBSD backend.

diff --git a/hald/freebsd/hf-volume.c b/hald/freebsd/hf-volume.c
index 3512a8a..249d2bd 100644
--- a/hald/freebsd/hf-volume.c
+++ b/hald/freebsd/hf-volume.c
@@ -45,6 +45,7 @@
 #include "hf-util.h"
 
 #define PROBE_VOLUME_TIMEOUT		(HAL_HELPER_TIMEOUT * 6)
+#define HF_VOLUME_FUSE_DB		"/tmp/.fuse-mnts"
 
 static void
 hf_volume_get_mounts (struct statfs **mounts, int *n_mounts)
@@ -60,6 +61,55 @@ hf_volume_get_mounts (struct statfs **mounts, int *n_mounts)
     }
 }
 
+static char *
+hf_volume_resolve_fuse (const char *special)
+{
+  gchar *contents;
+  gchar **lines;
+  gsize len;
+  int i;
+
+  g_return_val_if_fail(special != NULL, NULL);
+
+  if (! g_file_get_contents(HF_VOLUME_FUSE_DB, &contents, &len, NULL))
+    return g_strdup(special);
+
+  lines = g_strsplit(contents, "\n", 0);
+  g_free(contents);
+
+  for (i = 0; lines && lines[i]; i++)
+    {
+      gchar **fields;
+
+      fields = g_strsplit(lines[i], "=", 2);
+      if (fields && g_strv_length(fields) == 2)
+        {
+          if (strcmp(fields[0], special) == 0)
+	    {
+	      g_strfreev(fields);
+	      g_strfreev(lines);
+	      return g_strdup(fields[1]);
+	    }
+	}
+      g_strfreev(fields);
+    }
+
+    g_strfreev(lines);
+
+    return g_strdup(special);
+}
+
+static char *
+hf_volume_resolve_special (const char *special)
+{
+  g_return_val_if_fail(special != NULL, NULL);
+
+  if (strstr(special, "fuse"))
+    return hf_volume_resolve_fuse(special);
+
+  return g_strdup(special);
+}
+
 static const struct statfs *
 hf_volume_mounts_find (const struct statfs *mounts,
 		       int n_mounts,
@@ -71,8 +121,18 @@ hf_volume_mounts_find (const struct statfs *mounts,
   g_return_val_if_fail(special != NULL, NULL);
 
   for (i = 0; i < n_mounts; i++)
-    if (! strcmp(mounts[i].f_mntfromname, special))
-      return &mounts[i];
+    {
+      char *resolved;
+
+      resolved = hf_volume_resolve_special(mounts[i].f_mntfromname);
+      if (! strcmp(resolved, special))
+        {
+	  g_free(resolved);
+          return &mounts[i];
+	}
+
+      g_free(resolved);
+    }
 
   return NULL;
 }
@@ -92,7 +152,13 @@ hf_volume_device_update_mount_properties (HalDevice *device,
 
       special = hal_device_property_get_string(device, "block.device");
       if (special)
-	mount = hf_volume_mounts_find(mounts, n_mounts, special);
+	{
+	  mount = hf_volume_mounts_find(mounts, n_mounts, special);
+          if (mount && strcmp(special, mount->f_mntfromname))
+            hal_device_property_set_string(device, "volume.freebsd.real_mounted_device", mount->f_mntfromname);
+	  else
+	    hal_device_property_remove(device, "volume.freebsd.real_mounted_device");
+	}
     }
 
   hal_device_property_set_bool(device, "volume.is_mounted", mount != NULL);
commit 4d92b1ca4f9343d62641c37f366e46e900a3aed3
Author: Joe Marcus Clarke <marcus at FreeBSD.org>
Date:   Tue Aug 18 13:05:39 2009 -0400

    add support for mouse device probing
    
    Newer versions of X rely on hal to provide input device details.  Add
    support for probing mouse devices in order to determine if they are
    controlled by sysmouse, or standalone.

diff --git a/hald/freebsd/hf-devtree.c b/hald/freebsd/hf-devtree.c
index 01203f0..410f3c6 100644
--- a/hald/freebsd/hf-devtree.c
+++ b/hald/freebsd/hf-devtree.c
@@ -86,7 +86,11 @@ hf_devtree_cpu_can_throttle (int cpu)
   gboolean can = FALSE;
   char *levels;
 
+#ifdef notyet
   levels = hf_get_string_sysctl(NULL, "dev.cpu.%i.freq_levels", cpu);
+#else
+  levels = hf_get_string_sysctl(NULL, "dev.cpu.0.freq_levels");
+#endif
   if (levels)
     {
       char **toks;
@@ -109,7 +113,11 @@ hf_devtree_cpu_get_maxfreq (int cpu)
   char *levels;
   int freq = -1;
 
+#ifdef notyet
   levels = hf_get_string_sysctl(NULL, "dev.cpu.%i.freq_levels", cpu);
+#else
+  levels = hf_get_string_sysctl(NULL, "dev.cpu.0.freq_levels");
+#endif
   if (levels)
     {
       sscanf(levels, "%i/", &freq);
@@ -379,7 +387,8 @@ static Handler handlers[] = {
   { "pcm",		NULL					},
   { "psm",		hf_devtree_psm_set_properties		},
   { "sio",		NULL					},
-  { "speaker",		NULL					}
+  { "speaker",		NULL					},
+  { "usbus",		NULL					}
 };
 
 static void
@@ -426,7 +435,13 @@ hf_devtree_probe (void)
 	  HalDevice *device;
 
 	  device = hf_devtree_device_new(parent, info->handler, info->unit);
-	  hf_device_preprobe_and_add(device);
+	  if (hf_device_preprobe(device))
+            {
+              if (hal_device_has_capability(device, "input.mouse"))
+                hf_runner_run_sync(device, 0, "hald-probe-mouse", NULL);
+
+	      hf_device_add(device);
+	    }
 	}
 
       devices = g_slist_delete_link(devices, root);
@@ -434,6 +449,17 @@ hf_devtree_probe (void)
     }
 }
 
+static gboolean
+hf_devtree_rescan (HalDevice *device)
+{
+  if (hal_device_has_capability(device, "input.mouse"))
+    {
+      hf_runner_run_sync(device, 0, "hald-probe-mouse", NULL);
+      return TRUE;
+    }
+  return FALSE;
+}
+
 HalDevice *
 hf_devtree_find_from_name (HalDeviceStore *store, const char *name)
 {
@@ -597,5 +623,6 @@ hf_devtree_is_driver (const char *name, const char *driver)
 }
 
 HFHandler hf_devtree_handler = {
-  .probe = hf_devtree_probe
+  .probe = hf_devtree_probe,
+  .device_rescan = hf_devtree_rescan
 };
diff --git a/hald/freebsd/probing/probe-mouse.c b/hald/freebsd/probing/probe-mouse.c
new file mode 100644
index 0000000..a2cffc1
--- /dev/null
+++ b/hald/freebsd/probing/probe-mouse.c
@@ -0,0 +1,312 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * probe-hiddev.c : Mouse prober
+ *
+ * Copyright (C) 2008 Joe Marcus Clarke <marcus at FreeBSD.org>
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/param.h>
+#if __FreeBSD_version >= 800058
+#include <sys/types.h>
+#include <sys/user.h>
+#include <sys/sysctl.h>
+#include <libutil.h>
+#endif
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <glib.h>
+
+#include "../libprobe/hfp.h"
+
+#if __FreeBSD_version < 800058
+#define CMD "/usr/bin/fstat %s"
+#endif
+
+#define MOUSE_DRIVER "mouse"
+#define MOUSED_DEVICE "/dev/sysmouse"
+#define MOUSED_PROC_NAME "moused"
+#define XORG_PROC_NAME "Xorg"
+
+#if __FreeBSD_version >= 800058
+static struct kinfo_proc *
+hfp_kinfo_getproc (int *cntp)
+{
+  int mib[3];
+  int error;
+  int cnt;
+  size_t len;
+  char *buf, *bp, *eb;
+  struct kinfo_proc *kip, *kp, *ki;
+
+  *cntp = 0;
+
+  len = 0;
+  mib[0] = CTL_KERN;
+  mib[1] = KERN_PROC;
+  mib[2] = KERN_PROC_PROC;
+
+  error = sysctl(mib, 3, NULL, &len, NULL, 0);
+  if (error)
+    return NULL;
+
+  len = len * 4 / 3;
+  buf = (char *) g_malloc(len);
+  if (buf == NULL)
+    return NULL;
+
+  error = sysctl(mib, 3, buf, &len, NULL, 0);
+  if (error)
+    {
+      g_free(buf);
+      return NULL;
+    }
+
+  cnt = 0;
+  bp = buf;
+  eb = buf + len;
+  while (bp < eb)
+    {
+      ki =  (struct kinfo_proc *) (uintptr_t) bp;
+      bp += ki->ki_structsize;
+      cnt++;
+    }
+
+  kip = calloc(cnt, sizeof (*kip));
+  if (kip == NULL)
+    {
+      g_free(buf);
+      return NULL;
+    }
+
+  bp = buf;
+  eb = buf + len;
+  kp = kip;
+  while (bp < eb)
+    {
+      ki = (struct kinfo_proc *) (uintptr_t) bp;
+      memcpy(kp, ki, ki->ki_structsize);
+      bp += ki->ki_structsize;
+      kp->ki_structsize = sizeof(*kp);
+      kp++;
+    }
+
+  g_free(buf);
+  *cntp = cnt;
+  return kip;
+}
+
+static gboolean
+device_opened_by_proc (const char *device, const char *proc)
+{
+  struct kinfo_proc *kip, *pfreep;
+  int cnt, i;
+
+  pfreep = hfp_kinfo_getproc(&cnt);
+  if (pfreep == NULL)
+    return FALSE;
+
+  for (i = 0; i < cnt; i++)
+    {
+      kip = &pfreep[i];
+
+      if (! strcmp(kip->ki_comm, proc))
+        {
+          struct kinfo_file *kif, *ffreep;
+          int fcnt, j;
+
+          ffreep = kinfo_getfile(kip->ki_pid, &fcnt);
+          if (ffreep == NULL)
+                  continue;
+          for (j = 0; j < fcnt; j++)
+            {
+              kif = &ffreep[j];
+
+              if (kif->kf_type == KF_TYPE_VNODE &&
+                  ! strcmp(kif->kf_path, device))
+                {
+                  g_free(ffreep);
+                  g_free(pfreep);
+                  return TRUE;
+                }
+            }
+          g_free(ffreep);
+        }
+    }
+  g_free(pfreep);
+
+  return FALSE;
+}
+#else
+static gboolean
+device_opened_by_proc (const char *device, const char *proc)
+{
+  char **lines;
+  char *output = NULL;
+  char *cmd;
+  int i;
+  gboolean found = FALSE;
+
+  cmd = g_strdup_printf(CMD, device);
+
+  if (! g_spawn_command_line_sync(cmd, &output, NULL, NULL, NULL))
+    {
+      g_free(cmd);
+      goto done;
+    }
+  g_free(cmd);
+
+  if (! output || strlen(output) == 0)
+    goto done;
+
+  lines = g_strsplit(output, "\n", 0);
+  if (g_strv_length(lines) < 2)
+    {
+      g_strfreev(lines);
+      goto done;
+    }
+
+  for (i = 1; lines[i]; i++)
+    {
+      char **fields;
+      guint len;
+      guint j;
+
+      fields = g_strsplit_set(lines[i], " ", 0);
+      len = g_strv_length(fields);
+      if (len < 3)
+        {
+          g_strfreev(fields);
+          continue;
+        }
+      for (j = 1; j < len && fields[j] && *fields[j] == '\0'; j++)
+        ;
+      if (j < len && fields[j] && ! strcmp(fields[j], proc))
+        {
+          found = TRUE;
+          g_strfreev(fields);
+          break;
+        }
+      g_strfreev(fields);
+    }
+
+  g_strfreev(lines);
+
+done:
+  g_free(output);
+
+  return found;
+}
+#endif
+
+static void
+probe_mouse (const char *device_file)
+{
+  gboolean found;
+  char **udis;
+  char *driver;
+  int num_udis;
+
+  driver = libhal_device_get_property_string(hfp_ctx, hfp_udi,
+                                             "input.x11_driver", &hfp_error);
+  dbus_error_free(&hfp_error);
+
+  found = device_opened_by_proc(device_file, XORG_PROC_NAME);
+  if (found)
+    {
+      if (driver)
+        {
+          libhal_device_remove_property(hfp_ctx, hfp_udi, "input.x11_driver",
+                                        &hfp_error);
+	  dbus_error_free(&hfp_error);
+	  g_free(driver);
+	}
+      return;
+    }
+
+  found = device_opened_by_proc(device_file, MOUSED_PROC_NAME);
+  if (found)
+    {
+      libhal_device_set_property_string(hfp_ctx, hfp_udi, "input.device",
+                                        MOUSED_DEVICE, &hfp_error);
+      dbus_error_free(&hfp_error);
+      found = device_opened_by_proc(MOUSED_DEVICE, XORG_PROC_NAME);
+      if (! found)
+        {
+	  udis = libhal_manager_find_device_string_match(hfp_ctx,
+							 "input.device",
+							 MOUSED_DEVICE,
+							 &num_udis,
+							 &hfp_error);
+	  dbus_error_free(&hfp_error);
+	  if (num_udis > 0 && udis != NULL && !strcmp(udis[0], hfp_udi)) {
+	    libhal_device_set_property_string(hfp_ctx, hfp_udi,
+					      "input.x11_driver",
+					      MOUSE_DRIVER, &hfp_error);
+	    dbus_error_free(&hfp_error);
+	    libhal_free_string_array(udis);
+	  }
+	}
+      else if (driver)
+        {
+          libhal_device_remove_property(hfp_ctx, hfp_udi, "input.x11_driver",
+                                        &hfp_error);
+	  dbus_error_free(&hfp_error);
+	}
+    }
+  else
+    {
+      libhal_device_set_property_string(hfp_ctx, hfp_udi, "input.device",
+                                        device_file, &hfp_error);
+      dbus_error_free(&hfp_error);
+      libhal_device_set_property_string(hfp_ctx, hfp_udi, "input.x11_driver",
+                                        MOUSE_DRIVER, &hfp_error);
+      dbus_error_free(&hfp_error);
+    }
+
+  g_free(driver);
+}
+
+int
+main (int argc, char **argv)
+{
+  char *device_file;
+
+  if (! hfp_init(argc, argv))
+    goto end;
+
+  device_file = getenv("HAL_PROP_FREEBSD_DEVICE_FILE");
+  if (! device_file)
+    goto end;
+
+  /* give a meaningful process title for ps(1) */
+  setproctitle("%s", device_file);
+
+  /* Sleep for a second to give moused a chance to connect. */
+  sleep(1);
+  probe_mouse(device_file);
+
+ end:
+  return 0;
+}
commit 407103432cec837cc21397c499630ad3b077e984
Author: Joe Marcus Clarke <marcus at FreeBSD.org>
Date:   Tue Aug 18 13:05:10 2009 -0400

    add USB2 support
    
    Add support for the new USB infrastructure in FreeBSD -CURRENT.

diff --git a/hald/freebsd/probing/probe-hiddev.c b/hald/freebsd/probing/probe-hiddev.c
index e9b5016..916ae09 100644
--- a/hald/freebsd/probing/probe-hiddev.c
+++ b/hald/freebsd/probing/probe-hiddev.c
@@ -25,12 +25,21 @@
 #  include <config.h>
 #endif
 
+#include <sys/param.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <fcntl.h>
+#ifndef HAVE_LIBUSB20
 #include <sys/ioctl.h>
 #include <dev/usb/usb.h>
 #include <dev/usb/usbhid.h>
+#else
+#if __FreeBSD_version >= 800064
+#include <dev/usb/usbhid.h>
+#else
+#include <dev/usb2/include/usb2_hid.h>
+#endif
+#endif
 #include <usbhid.h>
 
 #include "../libprobe/hfp.h"
@@ -65,7 +74,12 @@ main (int argc, char **argv)
   /* give a meaningful process title for ps(1) */
   setproctitle("%s", device_file);
 
+#ifdef HAVE_LIBUSB20
+  report_id = hid_get_report_id(fd);
+  if (report_id == -1)
+#else
   if (ioctl(fd, USB_GET_REPORT_ID, &report_id) < 0)
+#endif
     goto end;
 
   hid_init(NULL);
commit f5ec8489f71052742a40ca139229a092130d473d
Author: Joe Marcus Clarke <marcus at FreeBSD.org>
Date:   Tue Aug 18 13:01:52 2009 -0400

    fix a problem building the FreeBSD backend
    
    Update the FreeBSD backend for the recent computer-related prioperty
    changes.

diff --git a/hald/freebsd/hf-computer.c b/hald/freebsd/hf-computer.c
index 7e9b9de..e0e53ec 100644
--- a/hald/freebsd/hf-computer.c
+++ b/hald/freebsd/hf-computer.c
@@ -26,6 +26,7 @@
 #  include <config.h>
 #endif
 
+#include <stdio.h>
 #include <string.h>
 #include <sys/utsname.h>
 
@@ -133,11 +134,11 @@ hf_computer_device_add (void)
   if (PACKAGE_VERSION) {
       int major, minor, micro;
 
-      hal_device_property_set_string (root, "org.freedesktop.Hal.version", PACKAGE_VERSION);
+      hal_device_property_set_string (device, "org.freedesktop.Hal.version", PACKAGE_VERSION);
       if ( sscanf( PACKAGE_VERSION, "%d.%d.%d", &major, &minor, &micro ) == 3 ) {
-	hal_device_property_set_int (root, "org.freedesktop.Hal.version.major", major);
-        hal_device_property_set_int (root, "org.freedesktop.Hal.version.minor", minor);
-        hal_device_property_set_int (root, "org.freedesktop.Hal.version.micro", micro);
+	hal_device_property_set_int (device, "org.freedesktop.Hal.version.major", major);
+        hal_device_property_set_int (device, "org.freedesktop.Hal.version.minor", minor);
+        hal_device_property_set_int (device, "org.freedesktop.Hal.version.micro", micro);
       }
   }
 
commit 2ae3e727601a7553c02337dbe2f15b43d2fff585
Author: Joe Marcus Clarke <marcus at FreeBSD.org>
Date:   Tue Aug 18 13:00:38 2009 -0400

    fix support for power and brightness management
    
    There were some issues reading battery and brightness levels on
    some laptops.  This particularly affected IBM/Lenovo machines.

diff --git a/hald/freebsd/hf-acpi.c b/hald/freebsd/hf-acpi.c
index 89243df..023a4fe 100644
--- a/hald/freebsd/hf-acpi.c
+++ b/hald/freebsd/hf-acpi.c
@@ -54,6 +54,7 @@
 static const struct laptop_panel_type {
   char *access;
   char *name;
+  char *get_sysctl;
   char *max_sysctl;
   int max_levels;
 #define HF_ACPI_IBM_MAX_LEVELS		8
@@ -64,17 +65,29 @@ static const struct laptop_panel_type {
 #define HF_ACPI_FUJITSU_MAX_LEVELS	8
   /* NOTE: Each new type must also be added to hf-devtree.c */
 } laptop_panel_types[] = {
-  { "ibm",		"IBM",		NULL,
+  { "ibm",		"IBM",
+    "dev.acpi_ibm.0.lcd_brightness",
+    NULL,
     HF_ACPI_IBM_MAX_LEVELS },
-  { "toshiba",		"Toshiba",	NULL,
+  { "toshiba",		"Toshiba",
+    "hw.acpi.toshiba.lcd_brightness",
+    NULL,
     HF_ACPI_TOSHIBA_MAX_LEVELS },
-  { "sony",		"Sony",		NULL,
+  { "sony",		"Sony",
+    "dev.acpi_sony.0.brightness",
+    NULL,
     HF_ACPI_SONY_MAX_LEVELS },
-  { "panasonic",	"Panasonic",	"hw.acpi.panasonic.lcd_brightness_max",
+  { "panasonic",	"Panasonic",
+    "hw.acpi.panasonic.lcd_brightness",
+    "hw.acpi.panasonic.lcd_brightness_max",
     HF_ACPI_PANASONIC_MAX_LEVELS },
-  { "asus",		"Asus",		NULL,
+  { "asus",		"Asus",
+    "hw.acpi.asus.lcd_brightness",
+    NULL,
     HF_ACPI_ASUS_MAX_LEVELS },
-  { "fujitsu",		"Fujitsu",	NULL,
+  { "fujitsu",		"Fujitsu",
+    "hw.acpi.fujitsu.lcd_brightness",
+    NULL,
     HF_ACPI_FUJITSU_MAX_LEVELS }
 };
 
@@ -105,6 +118,9 @@ hf_acpi_poll_batt (HalDevice *device)
   gboolean ispresent;
   union acpi_battery_ioctl_arg battif, battst, battinfo;
 
+  if (! hf_has_sysctl("hw.acpi.battery.units"))
+    return;
+
   battif.unit = battst.unit = battinfo.unit =
     hal_device_property_get_int(device, "freebsd.unit");
 
@@ -497,13 +513,15 @@ hf_acpi_video_device_new (HalDevice *parent, const char *type)
 
 static HalDevice *
 hf_acpi_laptop_panel_new (HalDevice *parent, int max_levels,
-                          const char *max_sysctl, const char *access,
-                          const char *name)
+                          const char *get_sysctl, const char *max_sysctl,
+                          const char *access, const char *name)
 {
   HalDevice *device;
 
   g_return_val_if_fail(HAL_IS_DEVICE(parent), NULL);
 
+  if (get_sysctl == NULL || ! hf_has_sysctl(get_sysctl))
+    return NULL;
   device = hf_device_new(parent);
 
   hf_device_property_set_string_printf(device, "info.product", "Laptop Panel (%s)", name);
@@ -593,11 +611,13 @@ hf_acpi_probe (void)
               HalDevice *panel_device;
 
 	      panel_device = hf_acpi_laptop_panel_new(parent,
-                                                      laptop_panel_types[i].max_levels,
+						      laptop_panel_types[i].max_levels,
+						      laptop_panel_types[i].get_sysctl,
 						      laptop_panel_types[i].max_sysctl,
 						      laptop_panel_types[i].access,
 						      laptop_panel_types[i].name);
-	      hf_device_preprobe_and_add(panel_device);
+	      if (panel_device)
+		hf_device_preprobe_and_add(panel_device);
 	    }
 	}
     }
commit bf600b0de6d905e41d911f602f4610fa41d89bab
Author: Joe Marcus Clarke <marcus at FreeBSD.org>
Date:   Tue Aug 18 12:59:28 2009 -0400

    add USB2 support
    
    Add support for the new USB infrastructure used in FreeBSD -CURRENT.

diff --git a/hald/freebsd/hf-usb2.c b/hald/freebsd/hf-usb2.c
new file mode 100644
index 0000000..fff49e0
--- /dev/null
+++ b/hald/freebsd/hf-usb2.c
@@ -0,0 +1,287 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * hf-usb.c : USB support
+ *
+ * Copyright (C) 2009 Joe Marcus Clarke <marcus at FreeBSD.org>
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <libusb20.h>
+
+#include "../logger.h"
+#include "../osspec.h"
+
+#include "hf-usb.h"
+#include "hf-usb2.h"
+#include "hf-devtree.h"
+#include "hf-util.h"
+
+static struct libusb20_backend *hf_usb2_be = NULL;
+
+static void
+hf_usb2_copy_parent (HalDevice *parent,
+		     const char *key,
+		     gpointer user_data)
+{
+  HalDevice *device;
+
+  g_return_if_fail(HAL_IS_DEVICE(parent));
+  g_return_if_fail(HAL_IS_DEVICE(user_data));
+
+  device = HAL_DEVICE(user_data);
+
+  if (! strncmp(key, "usb_device.", strlen("usb_device.")))
+    hal_device_copy_property(parent, key, device, key);
+}
+
+static void
+hf_usb2_probe_interfaces(HalDevice *parent)
+{
+  int num_interfaces;
+  int i;
+
+  g_return_if_fail(HAL_IS_DEVICE(parent));
+
+  if (hal_device_property_get_bool(parent, "info.ignore"))
+    return;
+
+  num_interfaces = hal_device_property_get_int(parent,
+    "usb_device.num_interfaces");
+
+  for (i = 0; i < num_interfaces; i++)
+    {
+      HalDevice *device;
+
+      device = hf_device_new(parent);
+
+      hal_device_property_set_string(device, "info.subsystem", "usb");
+      hal_device_property_set_int(device, "usb.interface.number", i);
+      hal_device_property_foreach(parent, hf_usb2_copy_parent, device);
+      hal_device_copy_property(parent, "info.product", device, "info.product");
+      hal_device_copy_property(parent, "info.vendor", device, "info.vendor");
+
+      if (hf_device_preprobe(device))
+        {
+          const char *driver, *devname;
+
+          hf_runner_run_sync(device, 0, "hald-probe-usb2-interface", NULL);
+
+	  devname = hal_device_property_get_string(device,
+            "usb.freebsd.devname");
+	  if (devname)
+            hf_devtree_device_set_name(device, devname);
+
+	  driver = hal_device_property_get_string(device, "freebsd.driver");
+	  if (driver)
+            {
+	      if (! strcmp(driver, "ukbd"))
+                hf_device_set_input(device, "keyboard", NULL);
+	      else if (! strcmp(driver, "ums"))
+                {
+                  hf_device_set_input(device, "mouse", devname);
+	          hf_runner_run_sync(device, 0, "hald-probe-mouse", NULL);
+	        }
+	      else if (! strcmp(driver, "uhid"))
+                {
+                  hal_device_property_set_string(device, "info.category",
+                    "hiddev");
+	          hal_device_add_capability(device, "hiddev");
+	          hf_device_property_set_string_printf(device, "hiddev.device",
+                    "/dev/%s", devname);
+	          hal_device_copy_property(device, "info.product", device,
+                    "hiddev.product");
+	          hf_runner_run_sync(device, 0, "hald-probe-hiddev", NULL);
+	        }
+	      else if (! strcmp(driver, "ldev"))
+                {
+                  /* Linux driver (webcam) */
+
+	          /*
+                   * XXX This is a hack.  Currently, all ldev devices are
+		   * webcams.  That may not always be the case.  Hopefully,
+		   * when other Linux driver support is added, there will be
+		   * a sysctl or some other way to determine device class.
+	           */
+                  hf_usb_add_webcam_properties(device);
+	        }
+	      else if (! strcmp(driver, "pwc"))
+                {
+                  /* Phillips Web Cam */
+                  hf_usb_add_webcam_properties(device);
+	        }
+	    }
+
+	  hf_usb_device_compute_udi(device);
+	  hf_device_add(device);
+	}
+    }
+}
+
+static void
+hf_usb2_probe_device (HalDevice *parent, int bus, int addr)
+{
+  HalDevice *device;
+
+  g_return_if_fail(HAL_IS_DEVICE(parent));
+
+  device = hf_device_new(parent);
+
+  hal_device_property_set_string(device, "info.subsystem", "usb_device");
+  hal_device_property_set_int(device, "usb_device.bus_number", bus);
+  hal_device_property_set_int(device, "usb_device.level_number", addr - 1);
+  hal_device_property_set_int(device, "usb_device.port_number", addr);
+
+  if (hf_device_preprobe(device))
+    {
+      hf_runner_run_sync(device, 0, "hald-probe-usb2-device", NULL);
+      hf_usb_device_compute_udi(device);
+
+      hf_device_add(device);
+    }
+  else
+    return;
+
+  hf_usb2_probe_interfaces(device);
+}
+
+static void
+hf_usb2_privileged_init (void)
+{
+  hf_usb2_be = libusb20_be_alloc_default();
+  if (hf_usb2_be == NULL)
+    HAL_INFO(("unable to open USB backend: %s", g_strerror(errno)));
+}
+
+static void
+hf_usb2_probe (void)
+{
+  struct libusb20_device *pdev = NULL;
+
+  if (hf_usb2_be == NULL)
+    return;
+
+  while ((pdev = libusb20_be_device_foreach(hf_usb2_be, pdev)))
+    {
+      HalDevice *parent;
+      int bus, addr;
+
+      bus = libusb20_dev_get_bus_number(pdev);
+      addr = libusb20_dev_get_address(pdev);
+
+      if (addr == 1)
+        parent = hf_devtree_find_parent_from_info(hald_get_gdl(), "usbus", bus);
+      else
+        parent = hf_device_store_match(hald_get_gdl(), "usb_device.bus_number",
+          HAL_PROPERTY_TYPE_INT32, bus, "usb_device.port_number",
+	  HAL_PROPERTY_TYPE_INT32, addr - 1, NULL);
+      if (! parent || hal_device_property_get_bool(parent, "info.ignore"))
+        continue;
+
+      hf_usb2_probe_device(parent, bus, addr);
+    }
+
+  libusb20_be_free(hf_usb2_be);
+  hf_usb2_be = NULL;
+}
+
+static gboolean
+hf_usb2_devd_add (const char *name,
+		  GHashTable *params,
+		  GHashTable *at,
+		  const char *parent)
+{
+  HalDevice *parent_device;
+  int bus, addr, pbus, paddr;
+
+  if (strncmp(name, "ugen", strlen("ugen")))
+    return FALSE;
+  else if (strncmp(parent, "ugen", strlen("ugen")))
+    return TRUE;
+
+  if (sscanf(name, "ugen%i.%i", &bus, &addr) != 2)
+    return FALSE;
+
+  if (sscanf(parent, "ugen%i.%i", &pbus, &paddr) != 2)
+    return FALSE;
+
+  HAL_INFO(("received devd add event for device '%s' with parent '%s'",
+           name, parent));
+
+  parent_device = hf_device_store_match(hald_get_gdl(),
+    "usb_device.bus_number", HAL_PROPERTY_TYPE_INT32, pbus,
+    "usb_device.port_number", HAL_PROPERTY_TYPE_INT32, paddr, NULL);
+
+  if (parent_device && ! hal_device_property_get_bool(parent_device,
+      "info.ignore"))
+    {
+      hf_usb2_probe_device(parent_device, bus, addr);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static gboolean
+hf_usb2_devd_remove (const char *name,
+		     GHashTable *params,
+		     GHashTable *at,
+		     const char *parent)
+{
+  HalDevice *device;
+  int bus, addr;
+
+  if (strncmp(name, "ugen", strlen("ugen")))
+    return FALSE;
+  else if (strncmp(parent, "ugen", strlen("ugen")))
+    return TRUE;
+
+  if (sscanf(name, "ugen%i.%i", &bus, &addr) != 2)
+    return FALSE;
+
+  HAL_INFO(("received devd remove event, device %s", name));
+
+  device = hf_device_store_match(hald_get_gdl(), "usb_device.bus_number",
+    HAL_PROPERTY_TYPE_INT32, bus, "usb_device.port_number",
+    HAL_PROPERTY_TYPE_INT32, addr, NULL);
+
+  if (device)
+    {
+      hf_device_remove_tree(device);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+HFHandler hf_usb2_handler = {
+  .privileged_init	= hf_usb2_privileged_init,
+  .probe		= hf_usb2_probe
+};
+
+HFDevdHandler hf_usb2_devd_handler = {
+  .add =	hf_usb2_devd_add,
+  .remove =	hf_usb2_devd_remove
+};
diff --git a/hald/freebsd/hf-usb2.h b/hald/freebsd/hf-usb2.h
new file mode 100644
index 0000000..0c2c03b
--- /dev/null
+++ b/hald/freebsd/hf-usb2.h
@@ -0,0 +1,37 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * hf-usb.h : USB support
+ *
+ * Copyright (C) 2009 Joe Marcus Clarke <marcus at FreeBSD.org>
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ **************************************************************************/
+
+#ifndef _HF_USB2_H
+#define _HF_USB2_H
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include "hf-osspec.h"
+#include "hf-devd.h"
+
+extern HFHandler hf_usb2_handler;
+extern HFDevdHandler hf_usb2_devd_handler;
+
+#endif /* _HF_USB2_H */
commit 04d3f5eff66d53b3b60396f46216cf6e5bd21552
Author: Joe Marcus Clarke <marcus at FreeBSD.org>
Date:   Tue Aug 18 12:58:38 2009 -0400

    add some missing storage properties
    
    Add some missing storage properties which are needed for burning media.

diff --git a/hald/freebsd/probing/probe-storage.c b/hald/freebsd/probing/probe-storage.c
index b9498c4..a0e7f77 100644
--- a/hald/freebsd/probing/probe-storage.c
+++ b/hald/freebsd/probing/probe-storage.c
@@ -31,6 +31,8 @@
 #include <unistd.h>
 #include <errno.h>
 #include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/disk.h>
 #include <netinet/in.h>
 #include <glib.h>
 #include <libvolume_id.h>
@@ -211,7 +213,26 @@ main (int argc, char **argv)
 	goto end;
 
       if (hfp_cdrom_test_unit_ready(cdrom))
-	ret = 2;		/* has media */
+        {
+	  int fd;
+	  off_t size;
+
+          libhal_device_set_property_bool(hfp_ctx, hfp_udi, "storage.removable.media_available", TRUE, &hfp_error);
+	  fd = open(device_file, O_RDONLY | O_NONBLOCK);
+	  if (fd > -1)
+            {
+              if (ioctl (fd, DIOCGMEDIASIZE, &size) == 0)
+                {
+                  libhal_device_set_property_uint64(hfp_ctx, hfp_udi, "storage.removable.media_size", size, &hfp_error);
+		}
+	      close(fd);
+	    }
+	  ret = 2;		/* has media */
+	}
+      else
+        {
+          libhal_device_set_property_bool(hfp_ctx, hfp_udi, "storage.removable.media_available", FALSE, &hfp_error);
+	}
 
       hfp_cdrom_free(cdrom);
     }
commit d3aeab79ada75e4a6ef245f4f915317fbcea8918
Author: Joe Marcus Clarke <marcus at FreeBSD.org>
Date:   Tue Aug 18 12:57:34 2009 -0400

    add support for reading ufsids
    
    Fix a problem where duplicate volumes may get mounted by teaching hal
    how to read and check for unique ufsids.

diff --git a/hald/freebsd/probing/probe-volume.c b/hald/freebsd/probing/probe-volume.c
index ee01927..40e6180 100644
--- a/hald/freebsd/probing/probe-volume.c
+++ b/hald/freebsd/probing/probe-volume.c
@@ -36,7 +36,12 @@
 #include <sys/disk.h>
 #include <sys/cdio.h>
 #include <sys/param.h>
+#include <sys/mount.h>
 #include <sys/types.h>
+#include <ufs/ufs/ufsmount.h>
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+#include <libufs.h>
 #include <isofs/cd9660/iso.h>
 #include <glib.h>
 #include <libvolume_id.h>
@@ -502,7 +507,8 @@ main (int argc, char **argv)
 	  hfp_cdrom_free(cdrom);
 	}
 
-      if (has_data)
+      if (has_data && vid && (! strcmp(vid->type, "iso9660") ||
+          ! strcmp(vid->type, "udf")))
         hf_probe_volume_advanced_disc_detect(fd);
     }
   else
@@ -555,6 +561,40 @@ main (int argc, char **argv)
 
   libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.ignore", has_children || is_swap, &hfp_error);
 
+  if (vid && ! strcmp (vid->type, "ufs"))
+    {
+      struct uufsd ufsdisk;
+
+      if (ufs_disk_fillout(&ufsdisk, device_file) == 0)
+        {
+	  char ufsid[64];
+	  char **ufs_devs;
+	  int num_udis;
+	  int i;
+
+	  snprintf(ufsid, sizeof(ufsid), "%08x%08x", ufsdisk.d_fs.fs_id[0], ufsdisk.d_fs.fs_id[1]);
+	  libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.freebsd.ufsid", ufsid, &hfp_error);
+	  ufs_devs = libhal_manager_find_device_string_match(hfp_ctx,
+			  				     "volume.freebsd.ufsid",
+							     ufsid,
+							     &num_udis,
+							     &hfp_error);
+	  dbus_error_free(&hfp_error);
+	  for (i = 0; i < num_udis; i++)
+            {
+              if (ufs_devs[i] != NULL)
+                {
+                  gboolean mounted;
+
+		  mounted = libhal_device_get_property_bool(hfp_ctx, ufs_devs[i], "volume.is_mounted", &hfp_error);
+		  if (mounted)
+                    libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.ignore", TRUE, &hfp_error);
+		}
+	    }
+	  ufs_disk_close(&ufsdisk);
+	}
+    }
+
   if (has_children)
     usage = "partitiontable";
   else if (is_swap)
commit 40893583b27eb45c93204d6d3769a39c23c1af7d
Author: Joe Marcus Clarke <marcus at FreeBSD.org>
Date:   Tue Aug 18 12:56:16 2009 -0400

    add USB2 support to the FreeBSD backend
    
    Add support for the new USB framework found in FreeBSD -CURRENT.

diff --git a/configure.in b/configure.in
index 890bba3..e8aa021 100644
--- a/configure.in
+++ b/configure.in
@@ -479,6 +479,9 @@ if test "x$with_libpci" != xno ; then
 fi 
 AM_CONDITIONAL([HAVE_LIBPCI], [test "x$USE_LIBPCI" = "xyes"])
 
+USE_LIBUSB20=no
+USE_LIBUSB=no
+LIBUSB20_LIBS=""
 AC_ARG_WITH([backend],
 	    AS_HELP_STRING([--with-backend=<name>],
 	                   [backend to use (linux/solaris/freebsd/dummy)]),
@@ -506,6 +509,22 @@ AM_CONDITIONAL(HALD_COMPILE_LINUX, [test x$HALD_BACKEND = xlinux], [Compiling fo
 AM_CONDITIONAL(HALD_COMPILE_FREEBSD, [test x$HALD_BACKEND = xfreebsd], [Compiling for FreeBSD])
 AM_CONDITIONAL(HALD_COMPILE_SOLARIS, [test x$HALD_BACKEND = xsolaris], [Compiling for Solaris])
 AC_SUBST(HALD_BACKEND)
+if test "x$HALD_BACKEND" = "xfreebsd"; then
+    AC_CHECK_LIB([usb20], [libusb20_dev_get_info], [USE_LIBUSB20=yes], [USE_LIBUSB20=no])
+fi
+if test "x$USE_LIBUSB20" = "xno"; then
+    AC_CHECK_LIB([usb], [libusb20_dev_get_info], [USE_LIBUSB=yes], [USE_LIBUSB=no])
+fi
+AM_CONDITIONAL([HAVE_LIBUSB20],[test "x$USE_LIBUSB20" = "xyes"])
+AM_CONDITIONAL([HAVE_LIBUSB20],[test "x$USE_LIBUSB" = "xyes"])
+if test "x$USE_LIBUSB20" = "xyes"; then
+    AC_DEFINE(HAVE_LIBUSB20, 1, [Set if we need libusb20])
+    LIBUSB20_LIBS="-lusb20"
+elif test "x$USE_LIBUSB" = "xyes"; then
+    AC_DEFINE(HAVE_LIBUSB20, 1, [Set if we need libsub20])
+    LIBUSB20_LIBS="-lusb"
+fi
+AC_SUBST(LIBUSB20_LIBS)
 
 dnl DBUS API is subject to changes
 AC_DEFINE_UNQUOTED(DBUS_API_SUBJECT_TO_CHANGE, [], [DBUS API is subject to change])
diff --git a/hald/freebsd/Makefile.am b/hald/freebsd/Makefile.am
index 95d40d4..d3aff6e 100644
--- a/hald/freebsd/Makefile.am
+++ b/hald/freebsd/Makefile.am
@@ -54,4 +54,11 @@ libhald_freebsd_la_SOURCES = 	\
 
 libhald_freebsd_la_LDFLAGS = -lcam
 
+if HAVE_LIBUSB20
+libhald_freebsd_la_SOURCES += 	\
+	hf-usb2.c		\
+	hf-usb2.h
+libhald_freebsd_la_LDFLAGS += @LIBUSB20_LIBS@
+endif
+
 EXTRA_DIST = README TODO
diff --git a/hald/freebsd/hf-devd.c b/hald/freebsd/hf-devd.c
index d878a45..dbf0202 100644
--- a/hald/freebsd/hf-devd.c
+++ b/hald/freebsd/hf-devd.c
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <errno.h>
 #include <unistd.h>
+#include <sys/param.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -40,7 +41,11 @@
 #include "hf-acpi.h"
 #include "hf-net.h"
 #include "hf-pcmcia.h"
+#include "hf-storage.h"
 #include "hf-usb.h"
+#ifdef HAVE_LIBUSB20
+#include "hf-usb2.h"
+#endif
 #include "hf-util.h"
 
 #define HF_DEVD_SOCK_PATH		"/var/run/devd.pipe"
@@ -51,10 +56,16 @@
 #define HF_DEVD_EVENT_NOMATCH		'?'
 
 static HFDevdHandler *handlers[] = {
+#ifdef HAVE_LIBUSB20
+  &hf_usb2_devd_handler,
+#endif
+#if __FreeBSD_version < 800092
   &hf_usb_devd_handler,
+#endif
   &hf_net_devd_handler,
   &hf_acpi_devd_handler,
-  &hf_pcmcia_devd_handler
+  &hf_pcmcia_devd_handler,
+  &hf_storage_devd_handler
 };
 
 static gboolean hf_devd_inited = FALSE;
@@ -381,13 +392,13 @@ hf_devd_event_cb (GIOChannel *source, GIOCondition condition,
 
   status = g_io_channel_read_line(source, &event, NULL, &terminator, NULL);
 
-  if (status != G_IO_STATUS_NORMAL)
+  if (status == G_IO_STATUS_NORMAL)
     {
       event[terminator] = 0;
       hf_devd_process_event(event);
       g_free(event);
     }
-  else if (status != G_IO_STATUS_AGAIN)
+  else if (status == G_IO_STATUS_AGAIN)
     {
       hf_devd_init();
       if (hf_devd_inited)
diff --git a/hald/freebsd/hf-storage.h b/hald/freebsd/hf-storage.h
index d8b2ff0..0915f1f 100644
--- a/hald/freebsd/hf-storage.h
+++ b/hald/freebsd/hf-storage.h
@@ -29,8 +29,10 @@
 #endif
 
 #include "hf-osspec.h"
+#include "hf-devd.h"
 
 extern HFHandler hf_storage_handler;
+extern HFDevdHandler hf_storage_devd_handler;
 
 void hf_storage_device_enable (HalDevice *device);
 void hf_storage_device_enable_tape (HalDevice *device);
diff --git a/hald/freebsd/hf-usb.c b/hald/freebsd/hf-usb.c
index d04f7f2..9bb6f3c 100644
--- a/hald/freebsd/hf-usb.c
+++ b/hald/freebsd/hf-usb.c
@@ -25,13 +25,20 @@
 #  include <config.h>
 #endif
 
+#include <sys/param.h>
 #include <string.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include <unistd.h>
+#if __FreeBSD_version < 800092
+#if __FreeBSD_version >= 800064
+#include <legacy/dev/usb/usb.h>
+#else
 #include <dev/usb/usb.h>
+#endif
+#endif
 
 #include "../logger.h"
 #include "../osspec.h"
@@ -40,7 +47,13 @@
 #include "hf-devtree.h"
 #include "hf-util.h"
 
+#if __FreeBSD_version < 800092
 #define HF_USB_DEVICE			"/dev/usb"
+#if __FreeBSD_version < 800066
+#define HF_USB2_DEVICE			"/dev/usb "
+#else
+#define HF_USB2_DEVICE			"/dev/usbctl"
+#endif
 
 typedef struct
 {
@@ -227,51 +240,6 @@ hf_usb_get_full_config_descriptor (int fd,
   return NULL;
 }
 
-/*
- * Adapted from usb_compute_udi() in linux2/physdev.c and
- * usbclass_compute_udi() in linux2/classdev.c.
- */
-static void
-hf_usb_device_compute_udi (HalDevice *device)
-{
-  g_return_if_fail(HAL_IS_DEVICE(device));
-
-  if (hal_device_has_capability(device, "hiddev"))
-    hf_device_set_full_udi(device, "%s_hiddev",
-			   hal_device_property_get_string(device, "info.parent"));
-  else if (hal_device_has_capability(device, "video4linux"))
-    hf_device_set_full_udi(device, "%s_video4linux",
-		    	   hal_device_property_get_string(device, "info.parent"));
-  else if (hal_device_has_property(device, "usb.interface.number"))
-    hf_device_set_full_udi(device, "%s_if%i",
-			   hal_device_property_get_string(device, "info.parent"),
-			   hal_device_property_get_int(device, "usb.interface.number"));
-  else
-    hf_device_set_udi(device, "usb_device_%x_%x_%s",
-		      hal_device_property_get_int(device, "usb_device.vendor_id"),
-		      hal_device_property_get_int(device, "usb_device.product_id"),
-		      hal_device_has_property(device, "usb_device.serial")
-		      ? hal_device_property_get_string(device, "usb_device.serial")
-		      : "noserial");
-}
-
-static void
-hf_usb_add_webcam_properties (HalDevice *device)
-{
-  int unit;
-
-  g_return_if_fail(HAL_IS_DEVICE(device));
-
-  unit = hal_device_property_get_int(device, "freebsd.unit");
-  if (unit < 0)
-    unit = 0;
-
-  hal_device_property_set_string(device, "info.category", "video4linux");
-  hal_device_add_capability(device, "video4linux");
-  hf_device_property_set_string_printf(device, "video4linux.device", "/dev/video%i", unit);
-  hal_device_property_set_string(device, "info.product", "Video Device");
-}
-
 /* adapted from usbif_set_name() in linux2/physdev.c */
 static const char *
 hf_usb_get_interface_name (const usb_interface_descriptor_t *desc)
@@ -424,7 +392,7 @@ hf_usb_device_new (HalDevice *parent,
     hf_devtree_device_set_name(device, di->udi_devnames[0]);
 
   if ((devname = hf_usb_get_devname(di, "ukbd")))	/* USB keyboard */
-    hf_device_set_input(device, "keyboard", devname);
+    hf_device_set_input(device, "keyboard", NULL);
   else if ((devname = hf_usb_get_devname(di, "ums")))	/* USB mouse */
     hf_device_set_input(device, "mouse", devname);
   else if ((devname = hf_usb_get_devname(di, "uhid")))	/* UHID device */
@@ -575,6 +543,8 @@ hf_usb_probe_device (HalDevice *parent,
     {
       if (hal_device_has_capability(device, "hiddev"))
 	hf_runner_run_sync(device, 0, "hald-probe-hiddev", NULL);
+      if (hal_device_has_capability(device, "input.mouse"))
+        hf_runner_run_sync(device, 0, "hald-probe-mouse", NULL);
 
       hf_device_add(device);
     }
@@ -633,9 +603,18 @@ hf_usb_privileged_init (void)
 {
   int i;
 
+  if (g_file_test(HF_USB2_DEVICE, G_FILE_TEST_EXISTS))
+    {
+      hf_usb_fd = -1;
+      return;
+    }
+
   hf_usb_fd = open(HF_USB_DEVICE, O_RDONLY);
   if (hf_usb_fd < 0)
-    HAL_INFO(("unable to open %s: %s", HF_USB_DEVICE, g_strerror(errno)));
+    {
+      HAL_INFO(("unable to open %s: %s", HF_USB_DEVICE, g_strerror(errno)));
+      return;
+    }
 
   for (i = 0; i < 16; i++)
     {
@@ -885,3 +864,50 @@ HFDevdHandler hf_usb_devd_handler = {
   .add =	hf_usb_devd_add,
   .remove =	hf_usb_devd_remove
 };
+#endif
+
+/*
+ * Adapted from usb_compute_udi() in linux2/physdev.c and
+ * usbclass_compute_udi() in linux2/classdev.c.
+ */
+void
+hf_usb_device_compute_udi (HalDevice *device)
+{
+  g_return_if_fail(HAL_IS_DEVICE(device));
+
+  if (hal_device_has_capability(device, "hiddev"))
+    hf_device_set_full_udi(device, "%s_hiddev",
+			   hal_device_property_get_string(device, "info.parent"));
+  else if (hal_device_has_capability(device, "video4linux"))
+    hf_device_set_full_udi(device, "%s_video4linux",
+		    	   hal_device_property_get_string(device, "info.parent"));
+  else if (hal_device_has_property(device, "usb.interface.number"))
+    hf_device_set_full_udi(device, "%s_if%i",
+			   hal_device_property_get_string(device, "info.parent"),
+			   hal_device_property_get_int(device, "usb.interface.number"));
+  else
+    hf_device_set_udi(device, "usb_device_%x_%x_%s",
+		      hal_device_property_get_int(device, "usb_device.vendor_id"),
+		      hal_device_property_get_int(device, "usb_device.product_id"),
+		      (hal_device_has_property(device, "usb_device.serial") &&
+		       strcmp(hal_device_property_get_string(device, "usb_device.serial"), ""))
+		      ? hal_device_property_get_string(device, "usb_device.serial")
+		      : "noserial");
+}
+
+void
+hf_usb_add_webcam_properties (HalDevice *device)
+{
+  int unit;
+
+  g_return_if_fail(HAL_IS_DEVICE(device));
+
+  unit = hal_device_property_get_int(device, "freebsd.unit");
+  if (unit < 0)
+    unit = 0;
+
+  hal_device_property_set_string(device, "info.category", "video4linux");
+  hal_device_add_capability(device, "video4linux");
+  hf_device_property_set_string_printf(device, "video4linux.device", "/dev/video%i", unit);
+  hal_device_property_set_string(device, "info.product", "Video Device");
+}
diff --git a/hald/freebsd/hf-usb.h b/hald/freebsd/hf-usb.h
index edc9c6c..37acedc 100644
--- a/hald/freebsd/hf-usb.h
+++ b/hald/freebsd/hf-usb.h
@@ -34,4 +34,7 @@
 extern HFHandler hf_usb_handler;
 extern HFDevdHandler hf_usb_devd_handler;
 
+void hf_usb_device_compute_udi(HalDevice *device);
+void hf_usb_add_webcam_properties(HalDevice *device);
+
 #endif /* _HF_USB_H */
diff --git a/hald/freebsd/osspec.c b/hald/freebsd/osspec.c
index 38ab181..0d35ac5 100644
--- a/hald/freebsd/osspec.c
+++ b/hald/freebsd/osspec.c
@@ -25,6 +25,7 @@
 #  include <config.h>
 #endif
 
+#include <sys/param.h>
 #include <string.h>
 
 #include "../ids.h"
@@ -46,13 +47,21 @@
 #include "hf-sound.h"
 #include "hf-storage.h"
 #include "hf-usb.h"
+#ifdef HAVE_LIBUSB20
+#include "hf-usb2.h"
+#endif
 #include "hf-volume.h"
 
 /* the order matters: PCI devices must be created before their children, etc */
 static HFHandler *handlers[] = {
   &hf_pci_handler,
   &hf_devtree_handler,
+#if __FreeBSD_version < 800092
   &hf_usb_handler,
+#endif
+#ifdef HAVE_LIBUSB20
+  &hf_usb2_handler,
+#endif
   &hf_ata_handler,
   &hf_scsi_handler,
   &hf_storage_handler,
diff --git a/hald/freebsd/probing/Makefile.am b/hald/freebsd/probing/Makefile.am
index fdba1eb..3e439b5 100644
--- a/hald/freebsd/probing/Makefile.am
+++ b/hald/freebsd/probing/Makefile.am
@@ -9,11 +9,18 @@ AM_CPPFLAGS = \
 
 if HALD_COMPILE_FREEBSD
 libexec_PROGRAMS = \
-	hald-probe-hiddev	\
-	hald-probe-scsi		\
-	hald-probe-smbios	\
-	hald-probe-storage	\
+	hald-probe-hiddev		\
+	hald-probe-mouse		\
+	hald-probe-scsi			\
+	hald-probe-smbios		\
+	hald-probe-storage		\
 	hald-probe-volume
+
+if HAVE_LIBUSB20
+libexec_PROGRAMS += \
+	hald-probe-usb2-device		\
+	hald-probe-usb2-interface
+endif
 endif
 
 hald_probe_hiddev_SOURCES = probe-hiddev.c
@@ -21,6 +28,25 @@ hald_probe_hiddev_LDADD = \
 	$(top_builddir)/hald/freebsd/libprobe/libhald_freebsd_probe.la	\
 	-lusbhid
 
+if HAVE_LIBUSB20
+hald_probe_usb2_device_SOURCES = probe-usb2-device.c
+hald_probe_usb2_device_LDADD = \
+	$(top_builddir)/hald/freebsd/libprobe/libhald_freebsd_probe.la  \
+	@LIBUSB20_LIBS@
+
+hald_probe_usb2_interface_SOURCES = probe-usb2-interface.c
+hald_probe_usb2_interface_LDADD = \
+	$(top_builddir)/hald/freebsd/libprobe/libhald_freebsd_probe.la  \
+	@LIBUSB20_LIBS@
+endif
+
+hald_probe_mouse_SOURCES = probe-mouse.c
+hald_probe_mouse_CPPFLAGS = $(AM_CPPFLAGS) @GLIB_CFLAGS@
+hald_probe_mouse_LDADD = \
+	@GLIB_LIBS@	\
+	$(top_builddir)/hald/freebsd/libprobe/libhald_freebsd_probe.la \
+	-lutil
+
 hald_probe_smbios_SOURCES = probe-smbios.c
 hald_probe_smbios_LDADD = \
 	$(top_builddir)/hald/freebsd/libprobe/libhald_freebsd_probe.la
@@ -41,4 +67,5 @@ hald_probe_volume_CPPFLAGS = $(AM_CPPFLAGS) @GLIB_CFLAGS@ @VOLUME_ID_CFLAGS@
 hald_probe_volume_LDADD = \
 	@GLIB_LIBS@							\
 	@VOLUME_ID_LIBS@						\
+	-lufs								\
 	$(top_builddir)/hald/freebsd/libprobe/libhald_freebsd_probe.la
diff --git a/hald/freebsd/probing/probe-usb2-device.c b/hald/freebsd/probing/probe-usb2-device.c
new file mode 100644
index 0000000..129a1b1
--- /dev/null
+++ b/hald/freebsd/probing/probe-usb2-device.c
@@ -0,0 +1,208 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * probe-usb2-device.c : USB2 Device poller
+ *
+ * Copyright (C) 2009 Joe Marcus Clarke <marcus at FreeBSD.org>
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libusb20_desc.h>
+#include <libusb20.h>
+#if __FreeBSD_version >= 800064
+#include <dev/usb/usb_ioctl.h>
+#else
+#include <dev/usb2/include/usb2_standard.h>
+#include <dev/usb2/include/usb2_ioctl.h>
+#endif
+
+#include "../libprobe/hfp.h"
+
+int
+main(int argc, char **argv)
+{
+  struct libusb20_backend *pbe = NULL;
+  struct libusb20_device *pdev = NULL;
+  char *busstr, *addrstr;
+  int bus, addr;
+
+  if (! hfp_init(argc, argv))
+    goto end;
+
+  pbe = libusb20_be_alloc_default();
+  if (pbe == NULL)
+    goto end;
+
+  busstr = getenv("HAL_PROP_USB_DEVICE_BUS_NUMBER");
+  if (! busstr)
+    goto end;
+
+  addrstr = getenv("HAL_PROP_USB_DEVICE_PORT_NUMBER");
+  if (! addrstr)
+    goto end;
+
+  bus = atoi(busstr);
+  addr = atoi(addrstr);
+
+  while ((pdev = libusb20_be_device_foreach(pbe, pdev)))
+    {
+      struct LIBUSB20_DEVICE_DESC_DECODED *ddesc;
+      struct LIBUSB20_CONFIG_DESC_DECODED *cdesc;
+#if __FreeBSD_version >= 800092
+      struct usb_device_info di;
+#else
+      struct usb2_device_info di;
+#endif
+      struct libusb20_config *pcfg = NULL;
+      int curr_config;
+      int bcdspeed = 0;
+      uint8_t temp_string[256];
+      double speed = 0.0;
+      double version = 1.0;
+
+      if (libusb20_dev_get_bus_number(pdev) != bus ||
+          libusb20_dev_get_address(pdev) != addr)
+        continue;
+
+      if (libusb20_dev_open(pdev, 0))
+        continue;
+
+      ddesc = libusb20_dev_get_device_desc(pdev);
+      curr_config = libusb20_dev_get_config_index(pdev);
+      pcfg = libusb20_dev_alloc_config(pdev, curr_config);
+      cdesc = &(pcfg->desc);
+
+      if (pcfg == NULL || libusb20_dev_get_info(pdev, &di))
+        {
+          free(pcfg);
+	  continue;
+	}
+
+      memset(temp_string, 0, sizeof(temp_string));
+
+      if (cdesc->iConfiguration !=0)
+        libusb20_dev_req_string_simple_sync(pdev, cdesc->iConfiguration,
+          temp_string, sizeof(temp_string));
+
+      libhal_device_set_property_string(hfp_ctx, hfp_udi,
+        "usb_device.configuration", (char *) temp_string, &hfp_error);
+      libhal_device_set_property_int(hfp_ctx, hfp_udi,
+        "usb_device.configuration_value", cdesc->bConfigurationValue,
+	&hfp_error);
+      libhal_device_set_property_int(hfp_ctx, hfp_udi,
+        "usb_device.num_configurations", ddesc->bNumConfigurations,
+	&hfp_error);
+      libhal_device_set_property_int(hfp_ctx, hfp_udi,
+        "usb_device.device_class", di.udi_class, &hfp_error);
+      libhal_device_set_property_int(hfp_ctx, hfp_udi,
+        "usb_device.device_subclass", di.udi_subclass, &hfp_error);
+      libhal_device_set_property_int(hfp_ctx, hfp_udi,
+        "usb_device.device_protocol", di.udi_protocol, &hfp_error);
+      libhal_device_set_property_bool(hfp_ctx, hfp_udi,
+        "usb_device.is_self_powered",
+	di.udi_power == 0 ? TRUE : FALSE, &hfp_error);
+      libhal_device_set_property_bool(hfp_ctx, hfp_udi,
+        "usb_device.can_wake_up",
+	(cdesc->bmAttributes & UC_REMOTE_WAKEUP) != 0 ? TRUE : FALSE,
+	&hfp_error);
+      libhal_device_set_property_int(hfp_ctx, hfp_udi,
+        "usb_device.max_power", di.udi_power, &hfp_error);
+      libhal_device_set_property_int(hfp_ctx, hfp_udi,
+        "usb_device.num_interfaces", pcfg->num_interface, &hfp_error);
+      libhal_device_set_property_int(hfp_ctx, hfp_udi,
+        "usb_device.num_ports", di.udi_nports, &hfp_error);
+
+      switch (libusb20_dev_get_speed(pdev))
+        {
+          case LIBUSB20_SPEED_LOW:
+            speed = 1.5;
+	    bcdspeed = 0x00150;
+	    break;
+	  case LIBUSB20_SPEED_FULL:
+	    speed = 12.0;
+	    bcdspeed = 0x01200;
+	    break;
+	  case LIBUSB20_SPEED_HIGH:
+	    speed = 480.0;
+	    bcdspeed = 0x48000;
+	    break;
+	  case LIBUSB20_SPEED_SUPER:
+	    speed = 4800.0;
+	    bcdspeed = 0x480000;
+	    break;
+	  default:
+	    ;
+	}
+
+      libhal_device_set_property_double(hfp_ctx, hfp_udi, "usb_device.speed",
+        speed, &hfp_error);
+      libhal_device_set_property_int(hfp_ctx, hfp_udi, "usb_device.speed_bcd",
+        bcdspeed, &hfp_error);
+
+      switch (ddesc->bcdUSB)
+        {
+          case UD_USB_2_0:
+            version = 2.0;
+	    break;
+	  case UD_USB_3_0:
+	    version = 3.0;
+	    break;
+	  default:
+	    version = 1.0;
+	    break;
+	}
+
+      libhal_device_set_property_double(hfp_ctx, hfp_udi,
+        "usb_device.version", version, &hfp_error);
+      libhal_device_set_property_int(hfp_ctx, hfp_udi,
+        "usb_device.product_id", di.udi_productNo, &hfp_error);
+      libhal_device_set_property_int(hfp_ctx, hfp_udi,
+        "usb_device.vendor_id", di.udi_vendorNo, &hfp_error);
+      libhal_device_set_property_int(hfp_ctx, hfp_udi,
+        "usb_device.device_revision_bcd", ddesc->bcdUSB, &hfp_error);
+      libhal_device_set_property_string(hfp_ctx, hfp_udi,
+        "usb_device.serial", di.udi_serial, &hfp_error);
+      libhal_device_set_property_string(hfp_ctx, hfp_udi,
+        "usb_device.product", di.udi_product, &hfp_error);
+      libhal_device_set_property_string(hfp_ctx, hfp_udi,
+        "usb_device.vendor", di.udi_vendor, &hfp_error);
+
+      libhal_device_set_property_string(hfp_ctx, hfp_udi,
+        "info.product", di.udi_product, &hfp_error);
+      libhal_device_set_property_string(hfp_ctx, hfp_udi,
+        "info.vendor", di.udi_vendor, &hfp_error);
+
+      libusb20_dev_close(pdev);
+      free(pcfg);
+    }
+end:
+  if (pbe)
+    libusb20_be_free(pbe);
+
+  return 0;
+}
diff --git a/hald/freebsd/probing/probe-usb2-interface.c b/hald/freebsd/probing/probe-usb2-interface.c
new file mode 100644
index 0000000..f57bb77
--- /dev/null
+++ b/hald/freebsd/probing/probe-usb2-interface.c
@@ -0,0 +1,140 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * probe-usb2-interface.c : USB2 Interface poller
+ *
+ * Copyright (C) 2009 Joe Marcus Clarke <marcus at FreeBSD.org>
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libusb20_desc.h>
+#include <libusb20.h>
+#if __FreeBSD_version >= 800064
+#include <dev/usb/usb_ioctl.h>
+#else
+#include <dev/usb2/include/usb2_standard.h>
+#include <dev/usb2/include/usb2_ioctl.h>
+#endif
+
+#include "../libprobe/hfp.h"
+
+int
+main(int argc, char **argv)
+{
+  struct libusb20_backend *pbe = NULL;
+  struct libusb20_device *pdev = NULL;
+  char *busstr, *addrstr, *ifacestr;
+  int bus, addr, iface;
+
+  if (! hfp_init(argc, argv))
+    goto end;
+
+  pbe = libusb20_be_alloc_default();
+  if (pbe == NULL)
+    goto end;
+
+  busstr = getenv("HAL_PROP_USB_DEVICE_BUS_NUMBER");
+  if (! busstr)
+    goto end;
+
+  addrstr = getenv("HAL_PROP_USB_DEVICE_PORT_NUMBER");
+  if (! addrstr)
+    goto end;
+
+  ifacestr = getenv("HAL_PROP_USB_INTERFACE_NUMBER");
+  if (! ifacestr)
+    goto end;
+
+  bus = atoi(busstr);
+  addr = atoi(addrstr);
+  iface = atoi(ifacestr);
+
+  while ((pdev = libusb20_be_device_foreach(pbe, pdev)))
+    {
+      struct LIBUSB20_INTERFACE_DESC_DECODED *idesc;
+      struct libusb20_config *pcfg = NULL;
+      struct libusb20_interface *pif;
+      uint8_t temp_string[256];
+      char ifdrv[128];
+      int curr_config;
+
+      if (libusb20_dev_get_bus_number(pdev) != bus ||
+          libusb20_dev_get_address(pdev) != addr)
+        continue;
+
+      if (libusb20_dev_open(pdev, 0))
+        continue;
+
+      curr_config = libusb20_dev_get_config_index(pdev);
+      pcfg = libusb20_dev_alloc_config(pdev, curr_config);
+      if (! pcfg)
+        continue;
+
+      pif = pcfg->interface + iface;
+
+      idesc = &pif->desc;
+
+      libhal_device_set_property_int(hfp_ctx, hfp_udi,
+        "usb.interface.class", idesc->bInterfaceClass, &hfp_error);
+      libhal_device_set_property_int(hfp_ctx, hfp_udi,
+        "usb.interface.subclass", idesc->bInterfaceSubClass, &hfp_error);
+      libhal_device_set_property_int(hfp_ctx, hfp_udi,
+        "usb.interface.protocol", idesc->bInterfaceProtocol, &hfp_error);
+
+      memset(temp_string, 0, sizeof(temp_string));
+      if (idesc->iInterface != 0)
+        libusb20_dev_req_string_simple_sync(pdev, idesc->iInterface,
+          temp_string, sizeof(temp_string));
+
+      libhal_device_set_property_string(hfp_ctx, hfp_udi,
+        "usb.interface.description", (char *) temp_string, &hfp_error);
+
+      memset(ifdrv, 0, sizeof(ifdrv));
+      libusb20_dev_get_iface_desc(pdev, iface, ifdrv, sizeof(ifdrv));
+      if (ifdrv[0] != '\0')
+        {
+          char *ifdesc;
+
+	  ifdesc = strchr(ifdrv, ':');
+	  if (ifdesc)
+            {
+              *ifdesc = '\0';
+	      libhal_device_set_property_string(hfp_ctx, hfp_udi,
+                "usb.freebsd.devname", ifdrv, &hfp_error);
+	    }
+	}
+
+      free(pcfg);
+    }
+
+end:
+  if (pbe)
+    libusb20_be_free(pbe);
+
+  return 0;
+}
commit 64c6ff319640e2420a533ca40d8f2b0622c4b0b0
Author: Joe Marcus Clarke <marcus at FreeBSD.org>
Date:   Tue Aug 18 12:48:09 2009 -0400

    re-enable libvolume_id support for FreeBSD
    
    FreeBSD's backend still requires libvolume_id.  Add it back until a
    better solution can be found.

diff --git a/configure.in b/configure.in
index 2e947a7..890bba3 100644
--- a/configure.in
+++ b/configure.in
@@ -15,6 +15,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 glib_module="glib-2.0 >= 2.10.0 gobject-2.0 > 2.10.0 dbus-glib-1 >= 0.61"
 dbus_module="dbus-1 >= 0.61"
 blkid_module="blkid >= 2.15"
+volume_id_module="libvolume_id >= 0.77"
 polkit_module="polkit >= 0.5"
 
 # libtool versioning - this applies to libhal and libhal-storage
@@ -686,8 +687,20 @@ else
 fi
 AC_MSG_RESULT($have_glib_2_14)
 
+case "$host" in
+    *-*-freebsd*)
+        PKG_CHECK_MODULES(VOLUME_ID, [$volume_id_module])
+	AC_SUBST(VOLUME_ID_CFLAGS)
+	AC_SUBST(VOLUME_ID_LIBS)
+	;;
+    *)
+        ;;
+esac
+
 # blkid (util-linux-ng)
 case "$host" in
+*-*-freebsd*)
+        ;;
 *-*-solaris*)
 	;;
 *)


More information about the hal-commit mailing list