diff --git a/etc/devd.conf b/etc/devd.conf
index 696ac7c5f1aa..8827e3b4e035 100644
--- a/etc/devd.conf
+++ b/etc/devd.conf
@@ -138,12 +138,14 @@ attach 100 {
 # This entry starts the ColdSync tool in daemon mode. Make sure you have an up
 # to date /usr/local/etc/palms. We override the 'listen' settings for port and
 # type in /usr/local/etc/coldsync.conf.
-attach 100 {
-	device-name "ugen[0-9]+";
-	match "vendor" "0x082d";
-	match "product" "0x0100";
-	match "release" "0x0100";
-	action "/usr/local/bin/coldsync -md -p /dev/$device-name -t usb";
+notify 100 {
+	match "system"		"USB";
+	match "subsystem"	"DEVICE";
+	match "type"		"ATTACH";
+	match "vendor"		"0x082d";
+	match "product"		"0x0100";
+	match "release"		"0x0100";
+	action "/usr/local/bin/coldsync -md -p /dev/$cdev -t usb";
 };
 
 #
diff --git a/etc/devd/uath.conf b/etc/devd/uath.conf
index 33bee69bb176..dc4019cefbc3 100644
--- a/etc/devd/uath.conf
+++ b/etc/devd/uath.conf
@@ -4,117 +4,143 @@
 
 # Accton
 #   SMCWUSB-G and SMCWUSBT-G2
-attach 100 {
-	device-name "ugen[0-9.]+";
-	match "vendor" "0x083a";
-	match "product" "(0x4505|0x4507)";
-	action "/usr/sbin/uathload -d /dev/$device-name";
+notify 100 {
+	match "system"		"USB";
+	match "subsystem"	"DEVICE";
+	match "type"		"ATTACH";
+	match "vendor"		"0x083a";
+	match "product"		"(0x4505|0x4507)";
+	action "/usr/sbin/uathload -d /dev/$cdev";
 };
 
 # Atheros Communications
 #   AR5523
-attach 100 {
-	device-name "ugen[0-9.]+";
-	match "vendor" "0x168c";
-	match "product" "0x0002";
-	action "/usr/sbin/uathload -d /dev/$device-name";
+notify 100 {
+	match "system"		"USB";
+	match "subsystem"	"DEVICE";
+	match "type"		"ATTACH";
+	match "vendor"		"0x168c";
+	match "product"		"0x0002";
+	action "/usr/sbin/uathload -d /dev/$cdev";
 };
 
 # Atheros Communications
 #   AR5523
-attach 100 {
-	device-name "ugen[0-9.]+";
-	match "vendor" "0x0cf3";
-	match "product" "(0x0002|0x0004|0x0006)";
-	action "/usr/sbin/uathload -d /dev/$device-name";
+notify 100 {
+	match "system"		"USB";
+	match "subsystem"	"DEVICE";
+	match "type"		"ATTACH";
+	match "vendor"		"0x0cf3";
+	match "product"		"(0x0002|0x0004|0x0006)";
+	action "/usr/sbin/uathload -d /dev/$cdev";
 };
 
 # Conceptronic
 #   AR5523
-attach 100 {
-	device-name "ugen[0-9.]+";
-	match "vendor" "0x0d8e";
-	match "product" "(0x7802|0x7812)";
-	action "/usr/sbin/uathload -d /dev/$device-name";
+notify 100 {
+	match "system"		"USB";
+	match "subsystem"	"DEVICE";
+	match "type"		"ATTACH";
+	match "vendor"		"0x0d8e";
+	match "product"		"(0x7802|0x7812)";
+	action "/usr/sbin/uathload -d /dev/$cdev";
 };
 
 # D-Link
 #   DWL-AG132, DWL-G132 and DWL-AG122
-attach 100 {
-	device-name "ugen[0-9.]+";
-	match "vendor" "0x2001";
-	match "product" "(0x3a01|0x3a03|0x3a05)";
-	action "/usr/sbin/uathload -d /dev/$device-name";
+notify 100 {
+	match "system"		"USB";
+	match "subsystem"	"DEVICE";
+	match "type"		"ATTACH";
+	match "vendor"		"0x2001";
+	match "product"		"(0x3a01|0x3a03|0x3a05)";
+	action "/usr/sbin/uathload -d /dev/$cdev";
 };
 
 # D-Link
 #  DWA-120
-attach 100 {
-	device-name "ugen[0-9.]+";
-	match "vendor" "0x07d1";
-	match "product" "0x3a0c";
-	action "/usr/sbin/uathload -d /dev/$device-name";
+notify 100 {
+	match "system"		"USB";
+	match "subsystem"	"DEVICE";
+	match "type"		"ATTACH";
+	match "vendor"		"0x07d1";
+	match "product"		"0x3a0c";
+	action "/usr/sbin/uathload -d /dev/$cdev";
 };
 
 # Gigaset
 #   SMCWUSBT-G
-attach 100 {
-	device-name "ugen[0-9.]+";
-	match "vendor" "0x1690";
-	match "product" "(0x0711|0x0713)";
-	action "/usr/sbin/uathload -d /dev/$device-name";
+notify 100 {
+	match "system"		"USB";
+	match "subsystem"	"DEVICE";
+	match "type"		"ATTACH";
+	match "vendor"		"0x1690";
+	match "product"		"(0x0711|0x0713)";
+	action "/usr/sbin/uathload -d /dev/$cdev";
 };
 
 # Global Sun Technology
 #   AR5523
-attach 100 {
-	device-name "ugen[0-9.]+";
-	match "vendor" "0x16ab";
-	match "product" "(0x7802|0x7812)";
-	action "/usr/sbin/uathload -d /dev/$device-name";
+notify 100 {
+	match "system"		"USB";
+	match "subsystem"	"DEVICE";
+	match "type"		"ATTACH";
+	match "vendor"		"0x16ab";
+	match "product"		"(0x7802|0x7812)";
+	action "/usr/sbin/uathload -d /dev/$cdev";
 };
 
 # BayNETGEAR
 #   WG111U
-attach 100 {
-	device-name "ugen[0-9.]+";
-	match "vendor" "0x0846";
-	match "product" "0x4301";
-	action "/usr/sbin/uathload -d /dev/$device-name";
+notify 100 {
+	match "system"		"USB";
+	match "subsystem"	"DEVICE";
+	match "type"		"ATTACH";
+	match "vendor"		"0x0846";
+	match "product"		"0x4301";
+	action "/usr/sbin/uathload -d /dev/$cdev";
 };
 
 # Netgear
 #   WG111T and WPN111
-attach 100 {
-	device-name "ugen[0-9.]+";
-	match "vendor" "0x1385";
-	match "product" "(0x4251|0x5f01)";
-	action "/usr/sbin/uathload -d /dev/$device-name";
+notify 100 {
+	match "system"		"USB";
+	match "subsystem"	"DEVICE";
+	match "type"		"ATTACH";
+	match "vendor"		"0x1385";
+	match "product"		"(0x4251|0x5f01)";
+	action "/usr/sbin/uathload -d /dev/$cdev";
 };
 
 # U-MEDIA Communications
 #   TEW-444UB and AR5523
-attach 100 {
-	device-name "ugen[0-9.]+";
-	match "vendor" "0x157e";
-	match "product" "(0x3007|0x3206)";
-	action "/usr/sbin/uathload -d /dev/$device-name";
+notify 100 {
+	match "system"		"USB";
+	match "subsystem"	"DEVICE";
+	match "type"		"ATTACH";
+	match "vendor"		"0x157e";
+	match "product"		"(0x3007|0x3206)";
+	action "/usr/sbin/uathload -d /dev/$cdev";
 };
 
 # Wistron NeWeb
 #   AR5523
-attach 100 {
-	device-name "ugen[0-9.]+";
-	match "vendor" "0x1435";
-	match "product" "(0x0827|0x0829)";
-	action "/usr/sbin/uathload -d /dev/$device-name";
+notify 100 {
+	match "system"		"USB";
+	match "subsystem"	"DEVICE";
+	match "type"		"ATTACH";
+	match "vendor"		"0x1435";
+	match "product"		"(0x0827|0x0829)";
+	action "/usr/sbin/uathload -d /dev/$cdev";
 };
 
 # Z-Com
 #   AR5523
-attach 100 {
-	device-name "ugen[0-9.]+";
-	match "vendor" "0x0cde";
-	match "product" "0x0013";
-	action "/usr/sbin/uathload -d /dev/$device-name";
+notify 100 {
+	match "system"		"USB";
+	match "subsystem"	"DEVICE";
+	match "type"		"ATTACH";
+	match "vendor"		"0x0cde";
+	match "product"		"0x0013";
+	action "/usr/sbin/uathload -d /dev/$cdev";
 };
diff --git a/sbin/devd/devd.conf.5 b/sbin/devd/devd.conf.5
index f7efefb20eb6..17c5e099b56d 100644
--- a/sbin/devd/devd.conf.5
+++ b/sbin/devd/devd.conf.5
@@ -250,18 +250,40 @@ CIS-vendor.
 Device class.
 .It Li device
 Device ID.
+.It Li devclass
+Device Class (USB)
+.It Li devsubclass
+Device Sub-class (USB)
 .It Li device-name
 Name of attached/detached device.
+.It Li endpoints
+Endpoint count (USB)
 .It Li function
 Card functions.
+.It Li interface
+Interface ID (USB)
+.It Li intclass
+Interface Class (USB)
+.It Li intprotocol
+Interface Protocol  (USB)
+.It Li intsubclass
+Interface Sub-class (USB)
 .It Li manufacturer
 Manufacturer ID (pccard).
+.It Li mode
+Peripheral mode (USB)
 .It Li notify
 Match the value of the
 .Dq Li notify
 variable.
+.It Li parent
+Parent device
+.It Li port
+Hub port number (USB)
 .It Li product
-Product ID (pccard).
+Product ID (pccard/USB).
+.It Li release
+Hardware revision (USB)
 .It Li serial
 Serial Number (USB).
 .It Li slot
@@ -342,6 +364,27 @@ The
 node is destroyed.
 .El
 .El
+.It Li USB
+Events related to the USB subsystem.
+.Bl -tag -width ".Sy Subsystem" -compact
+.It Sy Subsystem
+.It Li DEVICE
+.Bl -tag -width ".Li DETACH" -compact
+.It Sy Type
+.It Li ATTACH
+USB device is attached to the system.
+.It Li DETACH
+USB device is detached from the system.
+.El
+.It Li INTERFACE
+.Bl -tag -width ".Li DETACH" -compact
+.It Sy Type
+.It Li ATTACH
+USB interface is attached from a device.
+.It Li DETACH
+USB interface is detached from a device.
+.El
+.El
 .It Li coretemp
 Events related to the
 .Xr coretemp 4
@@ -460,6 +503,17 @@ notify 0 {
 	action "logger Lid opened, the sleeper must awaken!";
 };
 
+#
+# Match a USB device type
+#
+notify 0 {
+	match "system"			"USB";
+	match "subsystem"		"INTERFACE";
+	match "type"			"ATTACH";
+	match "intclass"		"0x0e";
+	action "logger USB video device attached";
+};
+
 #
 # Try to configure ath and wi devices with pccard_ether
 # as they are attached.
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
index d7f0c31c8d34..2f3a402d4acd 100644
--- a/sys/dev/usb/usb_device.c
+++ b/sys/dev/usb/usb_device.c
@@ -45,6 +45,7 @@
 #include <sys/priv.h>
 #include <sys/conf.h>
 #include <sys/fcntl.h>
+#include <sys/sbuf.h>
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
@@ -1834,7 +1835,7 @@ config_done:
 	printf("%s: <%s> at %s\n", udev->ugen_name, udev->manufacturer,
 	    device_get_nameunit(udev->bus->bdev));
 
-	usb_notify_addq("+", udev);
+	usb_notify_addq("ATTACH", udev);
 #endif
 done:
 	if (err) {
@@ -1980,7 +1981,7 @@ usb_free_device(struct usb_device *udev, uint8_t flag)
 	usb_set_device_state(udev, USB_STATE_DETACHED);
 
 #if USB_HAVE_UGEN
-	usb_notify_addq("-", udev);
+	usb_notify_addq("DETACH", udev);
 
 	printf("%s: <%s> at %s (disconnected)\n", udev->ugen_name,
 	    udev->manufacturer, device_get_nameunit(bus->bdev));
@@ -2347,13 +2348,23 @@ usbd_get_device_index(struct usb_device *udev)
  *
  * This function will generate events for dev.
  *------------------------------------------------------------------------*/
+#ifndef BURN_BRIDGES
 static void
-usb_notify_addq(const char *type, struct usb_device *udev)
+usb_notify_addq_compat(const char *type, struct usb_device *udev)
 {
 	char *data = NULL;
+	const char *ntype;
 	struct malloc_type *mt;
 	const size_t buf_size = 512;
 
+	/* Convert notify type */
+	if (strcmp(type, "ATTACH") == 0)
+		ntype = "+";
+	else if (strcmp(type, "DETACH") == 0)
+		ntype = "-";
+	else
+		return;
+
 	mtx_lock(&malloc_mtx);
 	mt = malloc_desc2type("bus");	/* XXX M_BUS */
 	mtx_unlock(&malloc_mtx);
@@ -2378,7 +2389,7 @@ usb_notify_addq(const char *type, struct usb_device *udev)
 	    "port=%u "
 	    "on "
 	    "%s\n",
-	    type,
+	    ntype,
 	    udev->ugen_name,
 	    UGETW(udev->ddesc.idVendor),
 	    UGETW(udev->ddesc.idProduct),
@@ -2393,6 +2404,89 @@ usb_notify_addq(const char *type, struct usb_device *udev)
 
 	devctl_queue_data(data);
 }
+#endif
+
+static void
+usb_notify_addq(const char *type, struct usb_device *udev)
+{
+	struct usb_interface *iface;
+	struct sbuf *sb;
+	int i;
+
+#ifndef BURN_BRIDGES
+	usb_notify_addq_compat(type, udev);
+#endif
+
+	/* announce the device */
+	sb = sbuf_new_auto();
+	sbuf_printf(sb,
+	    "cdev=%s "
+	    "vendor=0x%04x "
+	    "product=0x%04x "
+	    "devclass=0x%02x "
+	    "devsubclass=0x%02x "
+	    "sernum=\"%s\" "
+	    "release=0x%04x "
+	    "mode=%s "
+	    "port=%u "
+	    "parent=%s\n",
+	    udev->ugen_name,
+	    UGETW(udev->ddesc.idVendor),
+	    UGETW(udev->ddesc.idProduct),
+	    udev->ddesc.bDeviceClass,
+	    udev->ddesc.bDeviceSubClass,
+	    udev->serial,
+	    UGETW(udev->ddesc.bcdDevice),
+	    (udev->flags.usb_mode == USB_MODE_HOST) ? "host" : "device",
+	    udev->port_no,
+	    udev->parent_hub != NULL ?
+	    udev->parent_hub->ugen_name :
+	    device_get_nameunit(device_get_parent(udev->bus->bdev)));
+	sbuf_finish(sb);
+	devctl_notify("USB", "DEVICE", type, sbuf_data(sb));
+	sbuf_delete(sb);
+
+	/* announce each interface */
+	for (i = 0; i < USB_IFACE_MAX; i++) {
+		iface = usbd_get_iface(udev, i);
+		if (iface == NULL)
+			break;		/* end of interfaces */
+		if (iface->idesc == NULL)
+			continue;	/* no interface descriptor */
+
+		sb = sbuf_new_auto();
+		sbuf_printf(sb,
+		    "cdev=%s "
+		    "vendor=0x%04x "
+		    "product=0x%04x "
+		    "devclass=0x%02x "
+		    "devsubclass=0x%02x "
+		    "sernum=\"%s\" "
+		    "release=0x%04x "
+		    "mode=%s "
+		    "interface=%d "
+		    "endpoints=%d "
+		    "intclass=0x%02x "
+		    "intsubclass=0x%02x "
+		    "intprotocol=0x%02x\n",
+		    udev->ugen_name,
+		    UGETW(udev->ddesc.idVendor),
+		    UGETW(udev->ddesc.idProduct),
+		    udev->ddesc.bDeviceClass,
+		    udev->ddesc.bDeviceSubClass,
+		    udev->serial,
+		    UGETW(udev->ddesc.bcdDevice),
+		    (udev->flags.usb_mode == USB_MODE_HOST) ? "host" : "device",
+		    iface->idesc->bInterfaceNumber,
+		    iface->idesc->bNumEndpoints,
+		    iface->idesc->bInterfaceClass,
+		    iface->idesc->bInterfaceSubClass,
+		    iface->idesc->bInterfaceProtocol);
+		sbuf_finish(sb);
+		devctl_notify("USB", "INTERFACE", type, sbuf_data(sb));
+		sbuf_delete(sb);
+	}
+}
 
 /*------------------------------------------------------------------------*
  *	usb_fifo_free_wrap