Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 3 May 2013 07:44:58 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r250201 - in head: lib/libusb sys/dev/usb
Message-ID:  <201305030744.r437iwXr051308@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Fri May  3 07:44:58 2013
New Revision: 250201
URL: http://svnweb.freebsd.org/changeset/base/250201

Log:
  Add new USB API to get the port path of a USB device.
  
  MFC after:	2 weeks
  Requested by:	emaste @

Modified:
  head/lib/libusb/Makefile
  head/lib/libusb/libusb20.3
  head/lib/libusb/libusb20.c
  head/lib/libusb/libusb20.h
  head/lib/libusb/libusb20_int.h
  head/lib/libusb/libusb20_ugen20.c
  head/sys/dev/usb/usb_generic.c
  head/sys/dev/usb/usb_ioctl.h

Modified: head/lib/libusb/Makefile
==============================================================================
--- head/lib/libusb/Makefile	Fri May  3 02:07:02 2013	(r250200)
+++ head/lib/libusb/Makefile	Fri May  3 07:44:58 2013	(r250201)
@@ -203,6 +203,7 @@ MLINKS += libusb20.3 libusb20_dev_reset.
 MLINKS += libusb20.3 libusb20_dev_check_connected.3
 MLINKS += libusb20.3 libusb20_dev_set_power_mode.3
 MLINKS += libusb20.3 libusb20_dev_get_power_mode.3
+MLINKS += libusb20.3 libusb20_dev_get_port_path.3
 MLINKS += libusb20.3 libusb20_dev_get_power_usage.3
 MLINKS += libusb20.3 libusb20_dev_set_alt_index.3
 MLINKS += libusb20.3 libusb20_dev_get_device_desc.3

Modified: head/lib/libusb/libusb20.3
==============================================================================
--- head/lib/libusb/libusb20.3	Fri May  3 02:07:02 2013	(r250200)
+++ head/lib/libusb/libusb20.3	Fri May  3 07:44:58 2013	(r250201)
@@ -26,7 +26,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd February 14, 2013
+.Dd May 3, 2013
 .Dt LIBUSB20 3
 .Os
 .Sh NAME
@@ -114,6 +114,8 @@ USB access library (libusb -lusb)
 .Ft const char *
 .Fn libusb20_dev_get_backend_name "struct libusb20_device *"
 .Ft int
+.Fn libusb20_dev_get_port_path "struct libusb20_device *pdev" "uint8_t *buf" "uint8_t bufsize"
+.Ft int
 .Fn libusb20_dev_get_info "struct libusb20_device *pdev" "struct usb_device_info *pinfo"
 .Ft int
 .Fn libusb20_dev_get_iface_desc "struct libusb20_device *pdev" "uint8_t iface_index" "char *buf" "uint8_t len"
@@ -552,6 +554,20 @@ returns a zero terminated string describ
 .
 .Pp
 .
+.Fn libusb20_dev_get_port_path
+retrieves the list of USB port numbers which the datastream for a given USB device follows.
+The first port number is the Root HUB port number.
+Then children port numbers follow.
+The Root HUB device itself has a port path length of zero.
+Valid port numbers start at one and range until and including 255.
+Typically there should not be more than 16 levels, due to electrical and protocol limitations.
+This functions returns the number of actual port levels upon success
+else a LIBUSB20_ERROR value is returned which are always negative.
+If the actual number of port levels is greater than the maximum
+specified, a LIBUSB20_ERROR value is returned.
+.
+.Pp
+.
 .Fn libusb20_dev_get_info
 retrieves the BSD specific usb_device_info structure into the memory location given by
 .Fa pinfo .

Modified: head/lib/libusb/libusb20.c
==============================================================================
--- head/lib/libusb/libusb20.c	Fri May  3 02:07:02 2013	(r250200)
+++ head/lib/libusb/libusb20.c	Fri May  3 07:44:58 2013	(r250201)
@@ -75,6 +75,7 @@ dummy_callback(struct libusb20_transfer 
 #define	dummy_check_connected (void *)dummy_int
 #define	dummy_set_power_mode (void *)dummy_int
 #define	dummy_get_power_mode (void *)dummy_int
+#define	dummy_get_port_path (void *)dummy_int
 #define	dummy_get_power_usage (void *)dummy_int
 #define	dummy_kernel_driver_active (void *)dummy_int
 #define	dummy_detach_kernel_driver (void *)dummy_int
@@ -722,6 +723,12 @@ libusb20_dev_get_power_mode(struct libus
 	return (power_mode);
 }
 
+int
+libusb20_dev_get_port_path(struct libusb20_device *pdev, uint8_t *buf, uint8_t bufsize)
+{
+	return (pdev->methods->get_port_path(pdev, buf, bufsize));
+}
+
 uint16_t
 libusb20_dev_get_power_usage(struct libusb20_device *pdev)
 {

Modified: head/lib/libusb/libusb20.h
==============================================================================
--- head/lib/libusb/libusb20.h	Fri May  3 02:07:02 2013	(r250200)
+++ head/lib/libusb/libusb20.h	Fri May  3 07:44:58 2013	(r250201)
@@ -251,6 +251,7 @@ int	libusb20_dev_reset(struct libusb20_d
 int	libusb20_dev_check_connected(struct libusb20_device *pdev);
 int	libusb20_dev_set_power_mode(struct libusb20_device *pdev, uint8_t power_mode);
 uint8_t	libusb20_dev_get_power_mode(struct libusb20_device *pdev);
+int	libusb20_dev_get_port_path(struct libusb20_device *pdev, uint8_t *buf, uint8_t bufsize);
 uint16_t	libusb20_dev_get_power_usage(struct libusb20_device *pdev);
 int	libusb20_dev_set_alt_index(struct libusb20_device *pdev, uint8_t iface_index, uint8_t alt_index);
 int	libusb20_dev_get_info(struct libusb20_device *pdev, struct usb_device_info *pinfo);

Modified: head/lib/libusb/libusb20_int.h
==============================================================================
--- head/lib/libusb/libusb20_int.h	Fri May  3 02:07:02 2013	(r250200)
+++ head/lib/libusb/libusb20_int.h	Fri May  3 07:44:58 2013	(r250201)
@@ -105,6 +105,7 @@ typedef int (libusb20_process_t)(struct 
 typedef int (libusb20_reset_device_t)(struct libusb20_device *pdev);
 typedef int (libusb20_set_power_mode_t)(struct libusb20_device *pdev, uint8_t power_mode);
 typedef int (libusb20_get_power_mode_t)(struct libusb20_device *pdev, uint8_t *power_mode);
+typedef int (libusb20_get_port_path_t)(struct libusb20_device *pdev, uint8_t *buf, uint8_t bufsize);
 typedef int (libusb20_get_power_usage_t)(struct libusb20_device *pdev, uint16_t *power_usage);
 typedef int (libusb20_set_alt_index_t)(struct libusb20_device *pdev, uint8_t iface_index, uint8_t alt_index);
 typedef int (libusb20_set_config_index_t)(struct libusb20_device *pdev, uint8_t index);
@@ -128,6 +129,7 @@ typedef void (libusb20_tr_cancel_async_t
   m(n, check_connected) \
   m(n, set_power_mode) \
   m(n, get_power_mode) \
+  m(n, get_port_path) \
   m(n, get_power_usage) \
   m(n, set_alt_index) \
   m(n, set_config_index) \

Modified: head/lib/libusb/libusb20_ugen20.c
==============================================================================
--- head/lib/libusb/libusb20_ugen20.c	Fri May  3 02:07:02 2013	(r250200)
+++ head/lib/libusb/libusb20_ugen20.c	Fri May  3 07:44:58 2013	(r250201)
@@ -73,6 +73,7 @@ static libusb20_reset_device_t ugen20_re
 static libusb20_check_connected_t ugen20_check_connected;
 static libusb20_set_power_mode_t ugen20_set_power_mode;
 static libusb20_get_power_mode_t ugen20_get_power_mode;
+static libusb20_get_port_path_t ugen20_get_port_path;
 static libusb20_get_power_usage_t ugen20_get_power_usage;
 static libusb20_kernel_driver_active_t ugen20_kernel_driver_active;
 static libusb20_detach_kernel_driver_t ugen20_detach_kernel_driver;
@@ -644,6 +645,22 @@ ugen20_get_power_mode(struct libusb20_de
 }
 
 static int
+ugen20_get_port_path(struct libusb20_device *pdev, uint8_t *buf, uint8_t bufsize)
+{
+	struct usb_device_port_path udpp;
+
+	if (ioctl(pdev->file_ctrl, USB_GET_DEV_PORT_PATH, &udpp))
+		return (LIBUSB20_ERROR_OTHER);
+
+	if (udpp.udp_port_level > bufsize)
+		return (LIBUSB20_ERROR_OVERFLOW);
+
+	memcpy(buf, udpp.udp_port_no, udpp.udp_port_level);
+
+	return (udpp.udp_port_level);	/* success */
+}
+
+static int
 ugen20_get_power_usage(struct libusb20_device *pdev, uint16_t *power_usage)
 {
 	int temp;

Modified: head/sys/dev/usb/usb_generic.c
==============================================================================
--- head/sys/dev/usb/usb_generic.c	Fri May  3 02:07:02 2013	(r250200)
+++ head/sys/dev/usb/usb_generic.c	Fri May  3 07:44:58 2013	(r250201)
@@ -1841,6 +1841,46 @@ ugen_get_power_mode(struct usb_fifo *f)
 }
 
 static int
+ugen_get_port_path(struct usb_fifo *f, struct usb_device_port_path *dpp)
+{
+	struct usb_device *udev = f->udev;
+	struct usb_device *next;
+	unsigned int nlevel = 0;
+
+	if (udev == NULL)
+		goto error;
+
+	dpp->udp_bus = device_get_unit(udev->bus->bdev);
+	dpp->udp_index = udev->device_index;
+
+	/* count port levels */
+	next = udev;
+	while (next->parent_hub != NULL) {
+		nlevel++;
+		next = next->parent_hub;
+	}
+
+	/* check if too many levels */
+	if (nlevel > USB_DEVICE_PORT_PATH_MAX)
+		goto error;
+
+	/* store port index array */
+	next = udev;
+	while (next->parent_hub != NULL) {
+		nlevel--;
+
+		dpp->udp_port_no[nlevel] = next->port_no;
+		dpp->udp_port_level = nlevel;
+
+		next = next->parent_hub;
+	}
+	return (0);	/* success */
+
+error:
+	return (EINVAL);	/* failure */
+}
+
+static int
 ugen_get_power_usage(struct usb_fifo *f)
 {
 	struct usb_device *udev = f->udev;
@@ -2041,6 +2081,7 @@ ugen_ioctl_post(struct usb_fifo *f, u_lo
 		struct usb_device_stats *stat;
 		struct usb_fs_init *pinit;
 		struct usb_fs_uninit *puninit;
+		struct usb_device_port_path *dpp;
 		uint32_t *ptime;
 		void   *addr;
 		int    *pint;
@@ -2213,6 +2254,10 @@ ugen_ioctl_post(struct usb_fifo *f, u_lo
 		*u.pint = ugen_get_power_mode(f);
 		break;
 
+	case USB_GET_DEV_PORT_PATH:
+		error = ugen_get_port_path(f, u.dpp);
+		break;
+
 	case USB_GET_POWER_USAGE:
 		*u.pint = ugen_get_power_usage(f);
 		break;

Modified: head/sys/dev/usb/usb_ioctl.h
==============================================================================
--- head/sys/dev/usb/usb_ioctl.h	Fri May  3 02:07:02 2013	(r250200)
+++ head/sys/dev/usb/usb_ioctl.h	Fri May  3 07:44:58 2013	(r250201)
@@ -131,6 +131,15 @@ struct usb_device_info {
 	char	udi_release[8];
 };
 
+#define	USB_DEVICE_PORT_PATH_MAX 32
+
+struct usb_device_port_path {
+	uint8_t udp_bus;		/* which bus we are on */
+	uint8_t udp_index;		/* which device index */
+	uint8_t udp_port_level;		/* how many levels: 0, 1, 2 ... */
+	uint8_t udp_port_no[USB_DEVICE_PORT_PATH_MAX];
+};
+
 struct usb_device_stats {
 	uint32_t uds_requests_ok[4];	/* Indexed by transfer type UE_XXX */
 	uint32_t uds_requests_fail[4];	/* Indexed by transfer type UE_XXX */
@@ -277,7 +286,8 @@ struct usb_gen_quirk {
 #define	USB_IFACE_DRIVER_DETACH	_IOW ('U', 125, int)
 #define	USB_GET_PLUGTIME	_IOR ('U', 126, uint32_t)
 #define	USB_READ_DIR		_IOW ('U', 127, struct usb_read_dir)
-/* 128 - 134 unused */
+/* 128 - 133 unused */
+#define	USB_GET_DEV_PORT_PATH	_IOR ('U', 134, struct usb_device_port_path)
 #define	USB_GET_POWER_USAGE	_IOR ('U', 135, int)
 #define	USB_SET_TX_FORCE_SHORT	_IOW ('U', 136, int)
 #define	USB_SET_TX_TIMEOUT	_IOW ('U', 137, int)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201305030744.r437iwXr051308>