Add new USB API to get the port path of a USB device.
MFC after: 2 weeks Requested by: emaste @
This commit is contained in:
parent
3b48e348d5
commit
c77a24c24a
@ -203,6 +203,7 @@ MLINKS += libusb20.3 libusb20_dev_reset.3
|
||||
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
|
||||
|
@ -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 describing the backend used.
|
||||
.
|
||||
.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 .
|
||||
|
@ -75,6 +75,7 @@ dummy_callback(struct libusb20_transfer *xfer)
|
||||
#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 libusb20_device *pdev)
|
||||
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)
|
||||
{
|
||||
|
@ -251,6 +251,7 @@ int libusb20_dev_reset(struct libusb20_device *pdev);
|
||||
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);
|
||||
|
@ -105,6 +105,7 @@ typedef int (libusb20_process_t)(struct libusb20_device *pdev);
|
||||
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)(struct libusb20_transfer *xfer);
|
||||
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) \
|
||||
|
@ -73,6 +73,7 @@ static libusb20_reset_device_t ugen20_reset_device;
|
||||
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;
|
||||
@ -643,6 +644,22 @@ ugen20_get_power_mode(struct libusb20_device *pdev, uint8_t *power_mode)
|
||||
return (0); /* success */
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -1840,6 +1840,46 @@ ugen_get_power_mode(struct usb_fifo *f)
|
||||
return (udev->power_mode);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -2041,6 +2081,7 @@ ugen_ioctl_post(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
|
||||
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_long cmd, void *addr, int fflags)
|
||||
*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;
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user