The usbfs interface does not provide any way for the user to learn the
speed at which a device is connected.  The current API includes a
USBDEVFS_CONNECTINFO ioctl, but all it provides is the device's
address and a one-bit value indicating whether the connection is low
speed.  That may have sufficed in the era of USB-1.1, but it isn't
good enough today.

This patch introduces a new ioctl, USBDEVFS_GET_SPEED, which returns a
numeric value indicating the speed of the connection: unknown, low,
full, high, wireless, super, or super-plus.

Similar information (not exactly the same) is available through sysfs,
but it seems reasonable to provide the actual value in usbfs.

Signed-off-by: Alan Stern <st...@rowland.harvard.edu>
Reported-by: Reinhard Huck <reinhard.h...@thesycon.de>

---


[as1832]


 drivers/usb/core/devio.c          |   24 ++++++++++++++++++++++++
 include/uapi/linux/usbdevice_fs.h |   10 ++++++++++
 2 files changed, 34 insertions(+)

Index: usb-4.x/drivers/usb/core/devio.c
===================================================================
--- usb-4.x.orig/drivers/usb/core/devio.c
+++ usb-4.x/drivers/usb/core/devio.c
@@ -1322,6 +1322,27 @@ static int proc_connectinfo(struct usb_d
        return 0;
 }
 
+static int proc_get_speed(struct usb_dev_state *ps)
+{
+       switch (ps->dev->speed) {
+       case USB_SPEED_UNKNOWN:
+               return USBDEVFS_SPEED_UNKNOWN;
+       case USB_SPEED_LOW:
+               return USBDEVFS_SPEED_LOW;
+       case USB_SPEED_FULL:
+               return USBDEVFS_SPEED_FULL;
+       case USB_SPEED_HIGH:
+               return USBDEVFS_SPEED_HIGH;
+       case USB_SPEED_WIRELESS:
+               return USBDEVFS_SPEED_WIRELESS;
+       case USB_SPEED_SUPER:
+               return USBDEVFS_SPEED_SUPER;
+       case USB_SPEED_SUPER_PLUS:
+               return USBDEVFS_SPEED_SUPER_PLUS;
+       }
+       return -ERANGE;
+}
+
 static int proc_resetdevice(struct usb_dev_state *ps)
 {
        struct usb_host_config *actconfig = ps->dev->actconfig;
@@ -2537,6 +2558,9 @@ static long usbdev_do_ioctl(struct file
        case USBDEVFS_DROP_PRIVILEGES:
                ret = proc_drop_privileges(ps, p);
                break;
+       case USBDEVFS_GET_SPEED:
+               ret = proc_get_speed(ps);
+               break;
        }
 
  done:
Index: usb-4.x/include/uapi/linux/usbdevice_fs.h
===================================================================
--- usb-4.x.orig/include/uapi/linux/usbdevice_fs.h
+++ usb-4.x/include/uapi/linux/usbdevice_fs.h
@@ -156,6 +156,15 @@ struct usbdevfs_streams {
        unsigned char eps[0];
 };
 
+/* connection speed values used by USBDEVFS_GET_SPEED */
+#define USBDEVFS_SPEED_UNKNOWN         0
+#define USBDEVFS_SPEED_LOW             1
+#define USBDEVFS_SPEED_FULL            2
+#define USBDEVFS_SPEED_HIGH            3
+#define USBDEVFS_SPEED_WIRELESS                4
+#define USBDEVFS_SPEED_SUPER           5
+#define USBDEVFS_SPEED_SUPER_PLUS      6
+
 #define USBDEVFS_CONTROL           _IOWR('U', 0, struct usbdevfs_ctrltransfer)
 #define USBDEVFS_CONTROL32           _IOWR('U', 0, struct 
usbdevfs_ctrltransfer32)
 #define USBDEVFS_BULK              _IOWR('U', 2, struct usbdevfs_bulktransfer)
@@ -190,5 +199,6 @@ struct usbdevfs_streams {
 #define USBDEVFS_ALLOC_STREAMS     _IOR('U', 28, struct usbdevfs_streams)
 #define USBDEVFS_FREE_STREAMS      _IOR('U', 29, struct usbdevfs_streams)
 #define USBDEVFS_DROP_PRIVILEGES   _IOW('U', 30, __u32)
+#define USBDEVFS_GET_SPEED         _IO('U', 31)
 
 #endif /* _UAPI_LINUX_USBDEVICE_FS_H */

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to