Index: gusb/gusb-device.c
--- gusb/gusb-device.c.orig
+++ gusb/gusb-device.c
@@ -38,6 +38,7 @@ struct _GUsbDevicePrivate
 	GUsbContext		*context;
 	libusb_device		*device;
 	libusb_device_handle	*handle;
+	GArray                  *port_numbers;
 	struct libusb_device_descriptor desc;
 };
 
@@ -84,6 +85,7 @@ g_usb_device_dispose (GObject *object)
 	GUsbDevice *device = G_USB_DEVICE (object);
 	GUsbDevicePrivate *priv = device->priv;
 
+	g_clear_pointer (&priv->port_numbers, g_array_unref);
 	g_clear_pointer (&priv->device, libusb_unref_device);
 	g_clear_object (&priv->context);
 
@@ -202,25 +204,20 @@ g_usb_device_init (GUsbDevice *device)
 	device->priv = g_usb_device_get_instance_private (device);
 }
 
-static void
-g_usb_device_build_parent_port_number (GString *str, libusb_device *dev)
-{
-	libusb_device *parent = libusb_get_parent (dev);
-	if (parent != NULL)
-		g_usb_device_build_parent_port_number (str, parent);
-	g_string_append_printf (str, "%02x:", libusb_get_port_number (dev));
-}
-
 static gchar *
-g_usb_device_build_platform_id (struct libusb_device *dev)
+g_usb_device_build_platform_id (GUsbDevice *device)
 {
+	GUsbDevicePrivate *priv = device->priv;
 	GString *platform_id;
+	guint i;
 
 	/* build a topology of the device */
-	platform_id = g_string_new ("usb:");
-	g_string_append_printf (platform_id, "%02x:", libusb_get_bus_number (dev));
-	g_usb_device_build_parent_port_number (platform_id, dev);
-	g_string_truncate (platform_id, platform_id->len - 1);
+	platform_id = g_string_new ("usb");
+	g_string_append_printf (platform_id, ":%02x",
+				libusb_get_bus_number (priv->device));
+	for (i = 0; i < priv->port_numbers->len; i++)
+		g_string_append_printf (platform_id, ":%02x",
+					g_array_index (priv->port_numbers, guint8, i));
 	return g_string_free (platform_id, FALSE);
 }
 
@@ -251,8 +248,32 @@ g_usb_device_initable_init (GInitable     *initable,
 		return FALSE;
 	}
 
+	/* Store port number values to ease parent device finding on FreeBSD.
+	 * FreeBSD's libusb requires a device to be opened before calling
+	 * libusb_get_port_numbers because it needs the fd to call ioctl. */
+#define PORT_NUMBER_MAX 64
+	priv->port_numbers = g_array_new (FALSE, FALSE, sizeof (guint8));
+#ifndef __linux__
+	g_return_val_if_fail (priv->handle == NULL, FALSE);
+	if (libusb_open (priv->device, &priv->handle) == LIBUSB_SUCCESS) {
+#endif
+		guint8 ports[PORT_NUMBER_MAX];
+		gint port_count;
+		port_count = libusb_get_port_numbers (priv->device, ports,
+						      PORT_NUMBER_MAX);
+		if (port_count > 0) {
+			g_array_set_size (priv->port_numbers, port_count);
+			memcpy (priv->port_numbers->data, ports, port_count);
+		}
+#ifndef __linux__
+		libusb_close (priv->handle);
+		priv->handle = NULL;
+	}
+#endif
+#undef PORT_NUMBER_MAX
+
 	/* this does not change on plug->unplug->plug */
-	priv->platform_id = g_usb_device_build_platform_id (priv->device);
+	priv->platform_id = g_usb_device_build_platform_id (device);
 
 	return TRUE;
 }
@@ -1608,6 +1629,41 @@ g_usb_device_get_platform_id (GUsbDevice *device)
 	return device->priv->platform_id;
 }
 
+static libusb_device *
+g_usb_device_get_parent_libusb_device (GUsbDevice *device)
+{
+#ifndef __linux__
+	GPtrArray *devices = NULL;
+	GUsbDevice *device_tmp;
+	gboolean found = FALSE;
+	guint i;
+
+	if (device->priv->port_numbers->len == 0)
+		return NULL;
+
+	devices = g_usb_context_get_devices (device->priv->context);
+	for (i = 0; devices->len; i++) {
+		device_tmp = g_ptr_array_index (devices, i);
+		if (g_usb_device_get_bus (device) ==
+		    g_usb_device_get_bus (device_tmp) &&
+		    device->priv->port_numbers->len - 1 ==
+		    device_tmp->priv->port_numbers->len &&
+		    memcmp (device->priv->port_numbers->data,
+			    device_tmp->priv->port_numbers->data,
+			    device_tmp->priv->port_numbers->len) == 0) {
+			found = TRUE;
+			break;
+		}
+	}
+
+	g_ptr_array_unref (devices);
+
+	return found ? device_tmp->priv->device : NULL;
+#else
+	return libusb_get_parent (device->priv->device);
+#endif
+}
+
 /**
  * g_usb_device_get_parent:
  * @device: a #GUsbDevice instance
@@ -1624,7 +1680,7 @@ g_usb_device_get_parent (GUsbDevice *device)
 	GUsbDevicePrivate *priv = device->priv;
 	libusb_device *parent;
 
-	parent = libusb_get_parent (priv->device);
+	parent = g_usb_device_get_parent_libusb_device (device);
 	if (parent == NULL)
 		return NULL;
 
@@ -1658,7 +1714,7 @@ g_usb_device_get_children (GUsbDevice *device)
 	devices = g_usb_context_get_devices (priv->context);
 	for (i = 0; i < devices->len; i++) {
 		device_tmp = g_ptr_array_index (devices, i);
-		if (priv->device == libusb_get_parent (device_tmp->priv->device))
+		if (priv->device == g_usb_device_get_parent_libusb_device (device_tmp))
 			g_ptr_array_add (children, g_object_ref (device_tmp));
 	}
 
@@ -1703,6 +1759,7 @@ g_usb_device_get_address (GUsbDevice *device)
 	return libusb_get_device_address (device->priv->device);
 }
 
+#ifndef __DragonFly__
 /**
  * g_usb_device_get_port_number:
  * @device: a #GUsbDevice
@@ -1719,6 +1776,7 @@ g_usb_device_get_port_number (GUsbDevice *device)
 	g_return_val_if_fail (G_USB_IS_DEVICE (device), 0);
 	return libusb_get_port_number (device->priv->device);
 }
+#endif
 
 /**
  * g_usb_device_get_vid:
