diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/usb/usb_generic.c | 45 | ||||
-rw-r--r-- | sys/dev/usb/usb_ioctl.h | 12 |
2 files changed, 56 insertions, 1 deletions
diff --git a/sys/dev/usb/usb_generic.c b/sys/dev/usb/usb_generic.c index 9557686..013210a 100644 --- a/sys/dev/usb/usb_generic.c +++ b/sys/dev/usb/usb_generic.c @@ -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_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; diff --git a/sys/dev/usb/usb_ioctl.h b/sys/dev/usb/usb_ioctl.h index 979240f..4b7850a 100644 --- a/sys/dev/usb/usb_ioctl.h +++ b/sys/dev/usb/usb_ioctl.h @@ -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) |