USB: add usbfs ioctl to retrieve the connection parameters
Recently usfbs gained availability to retrieve device speed, but there is sill no way to determine the bus number or list of ports the device is connected to when using usbfs. While this information can be obtained from sysfs, not all environments allow sysfs access. In a jailed environment a program might be simply given an opened file descriptor to usbfs device, and it is really important that all data can be gathered from said file descriptor. This patch introduces a new ioctl, USBDEVFS_CONNINFO_EX, which return extended connection information for the device, including the bus number, address, port list and speed. The API allows kernel to extend amount of data returned by the ioctl and userspace has an option of adjusting the amount of data it is willing to consume. A new capability, USBDEVFS_CAP_CONNINFO_EX, is introduced to help userspace in determining whether the kernel supports this new ioctl. Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Šī revīzija ir iekļauta:

revīziju iesūtīja
Greg Kroah-Hartman

vecāks
1a65a03561
revīzija
6d101f24f1
@@ -1308,6 +1308,39 @@ static int proc_connectinfo(struct usb_dev_state *ps, void __user *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int proc_conninfo_ex(struct usb_dev_state *ps,
|
||||
void __user *arg, size_t size)
|
||||
{
|
||||
struct usbdevfs_conninfo_ex ci;
|
||||
struct usb_device *udev = ps->dev;
|
||||
|
||||
if (size < sizeof(ci.size))
|
||||
return -EINVAL;
|
||||
|
||||
memset(&ci, 0, sizeof(ci));
|
||||
ci.size = sizeof(ci);
|
||||
ci.busnum = udev->bus->busnum;
|
||||
ci.devnum = udev->devnum;
|
||||
ci.speed = udev->speed;
|
||||
|
||||
while (udev && udev->portnum != 0) {
|
||||
if (++ci.num_ports <= ARRAY_SIZE(ci.ports))
|
||||
ci.ports[ARRAY_SIZE(ci.ports) - ci.num_ports] =
|
||||
udev->portnum;
|
||||
udev = udev->parent;
|
||||
}
|
||||
|
||||
if (ci.num_ports < ARRAY_SIZE(ci.ports))
|
||||
memmove(&ci.ports[0],
|
||||
&ci.ports[ARRAY_SIZE(ci.ports) - ci.num_ports],
|
||||
ci.num_ports);
|
||||
|
||||
if (copy_to_user(arg, &ci, min(sizeof(ci), size)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int proc_resetdevice(struct usb_dev_state *ps)
|
||||
{
|
||||
struct usb_host_config *actconfig = ps->dev->actconfig;
|
||||
@@ -2250,7 +2283,7 @@ static int proc_get_capabilities(struct usb_dev_state *ps, void __user *arg)
|
||||
|
||||
caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM |
|
||||
USBDEVFS_CAP_REAP_AFTER_DISCONNECT | USBDEVFS_CAP_MMAP |
|
||||
USBDEVFS_CAP_DROP_PRIVILEGES;
|
||||
USBDEVFS_CAP_DROP_PRIVILEGES | USBDEVFS_CAP_CONNINFO_EX;
|
||||
if (!ps->dev->bus->no_stop_on_short)
|
||||
caps |= USBDEVFS_CAP_BULK_CONTINUATION;
|
||||
if (ps->dev->bus->sg_tablesize)
|
||||
@@ -2549,6 +2582,13 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
|
||||
break;
|
||||
}
|
||||
|
||||
/* Handle variable-length commands */
|
||||
switch (cmd & ~IOCSIZE_MASK) {
|
||||
case USBDEVFS_CONNINFO_EX(0):
|
||||
ret = proc_conninfo_ex(ps, p, _IOC_SIZE(cmd));
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
usb_unlock_device(dev);
|
||||
if (ret >= 0)
|
||||
|
Atsaukties uz šo jaunā problēmā
Block a user