📄 usb.tmpl
字号:
<sect1> <title>What files are in "usbfs"?</title> <para>Conventionally mounted at <filename>/proc/bus/usb</filename>, usbfs features include: <itemizedlist> <listitem><para><filename>/proc/bus/usb/devices</filename> ... a text file showing each of the USB devices on known to the kernel, and their configuration descriptors. You can also poll() this to learn about new devices. </para></listitem> <listitem><para><filename>/proc/bus/usb/BBB/DDD</filename> ... magic files exposing the each device's configuration descriptors, and supporting a series of ioctls for making device requests, including I/O to devices. (Purely for access by programs.) </para></listitem> </itemizedlist> </para> <para> Each bus is given a number (BBB) based on when it was enumerated; within each bus, each device is given a similar number (DDD). Those BBB/DDD paths are not "stable" identifiers; expect them to change even if you always leave the devices plugged in to the same hub port. <emphasis>Don't even think of saving these in application configuration files.</emphasis> Stable identifiers are available, for user mode applications that want to use them. HID and networking devices expose these stable IDs, so that for example you can be sure that you told the right UPS to power down its second server. "usbfs" doesn't (yet) expose those IDs. </para> </sect1> <sect1> <title>Mounting and Access Control</title> <para>There are a number of mount options for usbfs, which will be of most interest to you if you need to override the default access control policy. That policy is that only root may read or write device files (<filename>/proc/bus/BBB/DDD</filename>) although anyone may read the <filename>devices</filename> or <filename>drivers</filename> files. I/O requests to the device also need the CAP_SYS_RAWIO capability, </para> <para>The significance of that is that by default, all user mode device drivers need super-user privileges. You can change modes or ownership in a driver setup when the device hotplugs, or maye just start the driver right then, as a privileged server (or some activity within one). That's the most secure approach for multi-user systems, but for single user systems ("trusted" by that user) it's more convenient just to grant everyone all access (using the <emphasis>devmode=0666</emphasis> option) so the driver can start whenever it's needed. </para> <para>The mount options for usbfs, usable in /etc/fstab or in command line invocations of <emphasis>mount</emphasis>, are: <variablelist> <varlistentry> <term><emphasis>busgid</emphasis>=NNNNN</term> <listitem><para>Controls the GID used for the /proc/bus/usb/BBB directories. (Default: 0)</para></listitem></varlistentry> <varlistentry><term><emphasis>busmode</emphasis>=MMM</term> <listitem><para>Controls the file mode used for the /proc/bus/usb/BBB directories. (Default: 0555) </para></listitem></varlistentry> <varlistentry><term><emphasis>busuid</emphasis>=NNNNN</term> <listitem><para>Controls the UID used for the /proc/bus/usb/BBB directories. (Default: 0)</para></listitem></varlistentry> <varlistentry><term><emphasis>devgid</emphasis>=NNNNN</term> <listitem><para>Controls the GID used for the /proc/bus/usb/BBB/DDD files. (Default: 0)</para></listitem></varlistentry> <varlistentry><term><emphasis>devmode</emphasis>=MMM</term> <listitem><para>Controls the file mode used for the /proc/bus/usb/BBB/DDD files. (Default: 0644)</para></listitem></varlistentry> <varlistentry><term><emphasis>devuid</emphasis>=NNNNN</term> <listitem><para>Controls the UID used for the /proc/bus/usb/BBB/DDD files. (Default: 0)</para></listitem></varlistentry> <varlistentry><term><emphasis>listgid</emphasis>=NNNNN</term> <listitem><para>Controls the GID used for the /proc/bus/usb/devices and drivers files. (Default: 0)</para></listitem></varlistentry> <varlistentry><term><emphasis>listmode</emphasis>=MMM</term> <listitem><para>Controls the file mode used for the /proc/bus/usb/devices and drivers files. (Default: 0444)</para></listitem></varlistentry> <varlistentry><term><emphasis>listuid</emphasis>=NNNNN</term> <listitem><para>Controls the UID used for the /proc/bus/usb/devices and drivers files. (Default: 0)</para></listitem></varlistentry> </variablelist> </para> <para>Note that many Linux distributions hard-wire the mount options for usbfs in their init scripts, such as <filename>/etc/rc.d/rc.sysinit</filename>, rather than making it easy to set this per-system policy in <filename>/etc/fstab</filename>. </para> </sect1> <sect1> <title>/proc/bus/usb/devices</title> <para>This file is handy for status viewing tools in user mode, which can scan the text format and ignore most of it. More detailed device status (including class and vendor status) is available from device-specific files. For information about the current format of this file, see the <filename>Documentation/usb/proc_usb_info.txt</filename> file in your Linux kernel sources. </para> <para>Otherwise the main use for this file from programs is to poll() it to get notifications of usb devices as they're plugged or unplugged. To see what changed, you'd need to read the file and compare "before" and "after" contents, scan the filesystem, or see its hotplug event. </para> </sect1> <sect1> <title>/proc/bus/usb/BBB/DDD</title> <para>Use these files in one of these basic ways: </para> <para><emphasis>They can be read,</emphasis> producing first the device descriptor (18 bytes) and then the descriptors for the current configuration. See the USB 2.0 spec for details about those binary data formats. You'll need to convert most multibyte values from little endian format to your native host byte order, although a few of the fields in the device descriptor (both of the BCD-encoded fields, and the vendor and product IDs) will be byteswapped for you. Note that configuration descriptors include descriptors for interfaces, altsettings, endpoints, and maybe additional class descriptors. </para> <para><emphasis>Perform USB operations</emphasis> using <emphasis>ioctl()</emphasis> requests to make endpoint I/O requests (synchronously or asynchronously) or manage the device. These requests need the CAP_SYS_RAWIO capability, as well as filesystem access permissions. Only one ioctl request can be made on one of these device files at a time. This means that if you are synchronously reading an endpoint from one thread, you won't be able to write to a different endpoint from another thread until the read completes. This works for <emphasis>half duplex</emphasis> protocols, but otherwise you'd use asynchronous i/o requests. </para> </sect1> <sect1> <title>Life Cycle of User Mode Drivers</title> <para>Such a driver first needs to find a device file for a device it knows how to handle. Maybe it was told about it because a <filename>/sbin/hotplug</filename> event handling agent chose that driver to handle the new device. Or maybe it's an application that scans all the /proc/bus/usb device files, and ignores most devices. In either case, it should <function>read()</function> all the descriptors from the device file, and check them against what it knows how to handle. It might just reject everything except a particular vendor and product ID, or need a more complex policy. </para> <para>Never assume there will only be one such device on the system at a time! If your code can't handle more than one device at a time, at least detect when there's more than one, and have your users choose which device to use. </para> <para>Once your user mode driver knows what device to use, it interacts with it in either of two styles. The simple style is to make only control requests; some devices don't need more complex interactions than those. (An example might be software using vendor-specific control requests for some initialization or configuration tasks, with a kernel driver for the rest.) </para> <para>More likely, you need a more complex style driver: one using non-control endpoints, reading or writing data and claiming exclusive use of an interface. <emphasis>Bulk</emphasis> transfers are easiest to use, but only their sibling <emphasis>interrupt</emphasis> transfers work with low speed devices. Both interrupt and <emphasis>isochronous</emphasis> transfers offer service guarantees because their bandwidth is reserved. Such "periodic" transfers are awkward to use through usbfs, unless you're using the asynchronous calls. However, interrupt transfers can also be used in a synchronous "one shot" style. </para> <para>Your user-mode driver should never need to worry about cleaning up request state when the device is disconnected, although it should close its open file descriptors as soon as it starts seeing the ENODEV errors. </para> </sect1> <sect1><title>The ioctl() Requests</title> <para>To use these ioctls, you need to include the following headers in your userspace program:<programlisting>#include <linux/usb.h>#include <linux/usbdevice_fs.h>#include <asm/byteorder.h></programlisting> The standard USB device model requests, from "Chapter 9" of the USB 2.0 specification, are automatically included from the <filename><linux/usb_ch9.h></filename> header. </para> <para>Unless noted otherwise, the ioctl requests described here will update the modification time on the usbfs file to which they are applied (unless they fail). A return of zero indicates success; otherwise, a standard USB error code is returned. (These are documented in <filename>Documentation/usb/error-codes.txt</filename> in your kernel sources.) </para> <para>Each of these files multiplexes access to several I/O streams, one per endpoint. Each device has one control endpoint (endpoint zero) which supports a limited RPC style RPC access. Devices are configured by khubd (in the kernel) setting a device-wide <emphasis>configuration</emphasis> that affects things like power consumption and basic functionality. The endpoints are part of USB <emphasis>interfaces</emphasis>, which may have <emphasis>altsettings</emphasis> affecting things like which endpoints are available. Many devices only have a single configuration and interface, so drivers for them will ignore configurations and altsettings. </para> <sect2> <title>Management/Status Requests</title> <para>A number of usbfs requests don't deal very directly with device I/O. They mostly relate to device management and status. These are all synchronous requests. </para> <variablelist> <varlistentry><term>USBDEVFS_CLAIMINTERFACE</term> <listitem><para>This is used to force usbfs to claim a specific interface, which has not previously been claimed by usbfs or any other kernel driver. The ioctl parameter is an integer holding the number of the interface (bInterfaceNumber from descriptor). </para><para> Note that if your driver doesn't claim an interface before trying to use one of its endpoints, and no other driver has bound to it, then the interface is automatically claimed by usbfs. </para><para> This claim will be released by a RELEASEINTERFACE ioctl, or by closing the file descriptor. File modification time is not updated by this request. </para></listitem></varlistentry> <varlistentry><term>USBDEVFS_CONNECTINFO</term> <listitem><para>Says whether the device is lowspeed. The ioctl parameter points to a structure like this:<programlisting>struct usbdevfs_connectinfo { unsigned int devnum; unsigned char slow;}; </programlisting> File modification time is not updated by this request. </para><para> <emphasis>You can't tell whether a "not slow" device is connected at high speed (480 MBit/sec) or just full speed (12 MBit/sec).</emphasis> You should know the devnum value already, it's the DDD value of the device file name. </para></listitem></varlistentry> <varlistentry><term>USBDEVFS_GETDRIVER</term> <listitem><para>Returns the name of the kernel driver bound to a given interface (a string). Parameter is a pointer to this structure, which is modified:<programlisting>struct usbdevfs_getdriver {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -