⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbs.sgml

📁 开放源码实时操作系统源码.
💻 SGML
📖 第 1 页 / 共 5 页
字号:
<structfield>alternate_setting</structfield> fields. For example,
there might be one setting which requires a bandwidth of 100K/s and
another setting that only needs 50K/s. The host can use the standard
set-interface control message to choose the most appropriate setting.
The handling of this request is the responsibility of higher-level
code, so the application may have to <link
linkend="usbs-control-standard">install</link> its own handler.
</para>
<para>
The number of endpoints used by an interface is specified in the
<structfield>number_endpoints</structfield> field. Exact details of
which endpoints are used is held in a separate array of endpoint
descriptors. The class, subclass and protocol fields are used by
host-side code to determine which host-side device driver should
handle this specific interface. Usually this is determined on a
per-peripheral basis in the
<structname>usb_device_descriptor</structname> structure, but that can
defer the details to individual interfaces. A per-interface string
is allowed as well.
</para>
<para>
For USB peripherals involving multiple configurations, the array of
<structname>usb_interface_descriptor</structname> structures should
first contain all the interfaces for the first configuration, then all
the interfaces for the second configuration, and so on.
</para>
</refsect2>

<refsect2><title id="usbs-enum-endpoint"><structname>usb_endpoint_descriptor</structname></title>
<para>
The host also needs information about which endpoint should be used
for what. This involves an array of endpoint descriptors:
</para>
<programlisting width=72>
const usb_endpoint_descriptor usb_endpoints[] = {
    {
        length:         USB_ENDPOINT_DESCRIPTOR_LENGTH,
        type:           USB_ENDPOINT_DESCRIPTOR_TYPE,
        endpoint:       USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT | 1,
        attributes:     USB_ENDPOINT_DESCRIPTOR_ATTR_BULK,
        max_packet_lo:  64,
        max_packet_hi:  0,
        interval:       0
    },
    {
        length:         USB_ENDPOINT_DESCRIPTOR_LENGTH,
        type:           USB_ENDPOINT_DESCRIPTOR_TYPE,
        endpoint:       USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN | 2,
        attributes:     USB_ENDPOINT_DESCRIPTOR_ATTR_BULK,
        max_packet_lo:  64,
        max_packet_hi:  0,
        interval:       0
    }
};

const usbs_enumeration_data usb_enum_data = {
    &hellip;
    total_number_endpoints:     2,
    endpoints:                  usb_endpoints,
    &hellip;
};
</programlisting>
<para>
As usual the values for the <structfield>length</structfield> and
<structfield>type</structfield> fields are specified by the standard.
The <structfield>endpoint</structfield> field gives both the endpoint
number and the direction, so in the above example endpoint 1 is used
for OUT (host to peripheral) transfers and endpoint 2 is used for IN
(peripheral to host) transfers. The
<structfield>attributes</structfield> field indicates the USB protocol
that should be used on this endpoint: <literal>CONTROL</literal>,
<literal>ISOCHRONOUS</literal>, <literal>BULK</literal> or
<literal>INTERRUPT</literal>. The
<structfield>max_packet</structfield> field specifies the maximum size
of a single USB packet. For bulk transfers this will typically be 64
bytes. For isochronous transfers this can be up to 1023 bytes. For
interrupt transfers it can be up to 64 bytes, although usually a
smaller value will be used. The <structfield>interval</structfield>
field is ignored for control and bulk transfers. For isochronous
transfers it should be set to 1. For interrupt transfers it can be a
value between 1 and 255, and indicates the number of milliseconds
between successive polling operations.
</para>
<para>
For USB peripherals involving multiple configurations or interfaces
the array of endpoint descriptors should be organized sequentially:
first the endpoints corresponding to the first interface of the first
configuration, then the second interface in that configuration, and so
on; then all the endpoints for all the interfaces in the second
configuration; etc.
</para>
</refsect2>

<refsect2><title id="usbs-enum-strings">Strings</title>
<para>
The enumeration data can contain a number of strings with additional
information. Unicode encoding is used for the strings, and it is
possible for a peripheral to supply a given string in multiple
languages using the appropriate characters. The first two bytes of
each string give a length and type field. The first string is special;
after the two bytes header it consists of an array of 2-byte language
id codes, indicating the supported languages. The language code
0x0409 corresponds to English (United States). 
</para>
<programlisting width=72>
const unsigned char* usb_strings[] = {
    "\004\003\011\004",
    "\020\003R\000e\000d\000 \000H\000a\000t\000"
};

const usbs_enumeration_data usb_enum_data = {
    &hellip;
    total_number_strings:       2,
    strings:                    usb_strings,
    &hellip;
};
</programlisting>
<para>
The default handler for standard control messages assumes that the
peripheral only uses a single language. If this is not the case then
higher-level code will have to handle the standard get-descriptor
control messages when a string descriptor is requested.
</para>
</refsect2>

<refsect2><title><structname>usbs_enumeration_data</structname></title>
<para>
The <structname>usbs_enumeration_data</structname> data structure
collects together all the various descriptors that make up the
enumeration data. It is the responsibility of application code to
supply a suitable data structure and install it in the control
endpoints's <structfield>enumeration_data</structfield> field before
the USB device is started.
</para>
</refsect2>

</refsect1>
</refentry>

<!-- }}} -->
<!-- {{{ usbs_start()                   -->

<refentry id="usbs-start">
<refmeta>
<refentrytitle>Starting up a USB Device</refentrytitle>
</refmeta>
<refnamediv>
<refname><function>usbs_start</function></refname>
<refpurpose>Starting up a USB Device</refpurpose>
</refnamediv>

<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>
#include &lt;cyg/io/usb/usbs.h&gt;
</funcsynopsisinfo>
<funcprototype>
<funcdef>void <function>usbs_start</function></funcdef>
<paramdef>usbs_control_endpoint* <parameter>ep0</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>

<refsect1><title>Description</title>
<para>
Initializing a USB device requires some support from higher-level
code, typically the application, in the form of enumeration data.
Hence it is not possible for the low-level USB driver to activate a
USB device itself. Instead the higher-level code has to take care of
this by invoking <function>usbs_start</function>. This function takes
a pointer to a USB control endpoint data structure. USB device drivers
should provide exactly one such data structure for every USB device,
so the pointer uniquely identifies the device.
</para>
<programlisting width=72>
const usbs_enumeration_data usb_enum_data = {
    &hellip;
};

int
main(int argc, char** argv)
{
    usbs_sa11x0_ep0.enumeration_data = &amp;usb_enum_data;
    &hellip;
    usbs_start(&amp;usbs_sa11x0_ep0);
    &hellip;
}
</programlisting>
<para>
The exact behaviour of <function>usbs_start</function> depends on the
USB hardware and the device driver. A typical implementation would
change the USB data pins from tristated to active. If the peripheral
is already plugged into a host then the latter should detect this
change and start interacting with the peripheral, including requesting
the enumeration data. Some of this may happen before
<function>usbs_start</function> returns, but given that multiple
interactions between USB host and peripheral are required it is likely
that the function will return before the peripheral is fully
configured. Control endpoints provide a <link
linkend="usbs-control-state">mechanism</link> for informing
higher-level code of USB state changes.
<function>usbs_start</function> will return even if the peripheral is
not currently connected to a host: it will not block until the
connection is established.
</para>
<para>
<function>usbs_start</function> should only be called once for a given
USB device. There are no defined error conditions. Note that the
function affects the entire USB device and not just the control
endpoint: there is no need to start any data endpoints as well.
</para>
</refsect1>
</refentry>

<!-- }}} -->
<!-- {{{ Devtab Entries                 -->

<refentry id="usbs-devtab">
<refmeta>
<refentrytitle>Devtab Entries</refentrytitle>
</refmeta>
<refnamediv>
<refname>Devtab Entries</refname>
<refpurpose>Data endpoint data structure</refpurpose>
</refnamediv>

<refsynopsisdiv>
<synopsis>
/dev/usb0c
/dev/usb1r
/dev/usb2w
</synopsis>
</refsynopsisdiv>

<refsect1><title>Devtab Entries</title>
<para>
USB device drivers provide two ways of transferring data between host
and peripheral. The first involves USB-specific functionality such as
<link
linkend="usbs-start-rx"><function>usbs_start_rx_buffer</function></link>.
This provides non-blocking I/O: a transfer is started, and some time
later the device driver will call a supplied completion function. The
second uses the conventional I/O model: there are entries in the
device table corresponding to the various endpoints. Standard calls
such as <function>open</function> can then be used to get a suitable
handle. Actual I/O happens via blocking <function>read</function> and
<function>write</function> calls. In practice the blocking operations
are simply implemented using the underlying non-blocking
functionality.
</para>
<para>
Each endpoint will have its own devtab entry. The exact names are
controlled by the device driver package, but typically the root will
be <literal>/dev/usb</literal>. This is followed by one or more
decimal digits giving the endpoint number, followed by
<literal>c</literal> for a control endpoint, <literal>r</literal> for
a receive endpoint (host to peripheral), and <literal>w</literal> for
a transmit endpoint (peripheral to host). If the target hardware
involves more than one USB device then different roots should be used,
for example <literal>/dev/usb0c</literal> and
<literal>/dev/usb1_0c</literal>. This may require explicit
manipulation of device driver configuration options by the application
developer.
</para>
<para>
At present the devtab entry for a control endpoint does not support
any I/O operations. 
</para>

<refsect2><title><function>write</function> operations</title>
<para>
<function>cyg_io_write</function> and similar functions in
higher-level packages can be used to perform a transfer from
peripheral to host. Successive write operations will not be coalesced.
For example, when doing a 1000 byte write to an endpoint that uses the
bulk transfer protocol this will involve 15 full-size 64-byte packets
and a terminating 40-byte packet. USB device drivers are not expected
to do any locking, and if higher-level code performs multiple
concurrent write operations on a single endpoint then the resulting
behaviour is undefined.
</para>
<para>
A USB <function>write</function> operation will never transfer less
data than specified. It is the responsibility of higher-level code to
ensure that the amount of data being transferred is acceptable to the
host-side code. Usually this will be defined by a higher-level
protocol. If an attempt is made to transfer more data than the host
expects then the resulting behaviour is undefined.
</para>
<para>
There are two likely error conditions. <literal>EPIPE</literal>
indicates that the connection between host and target has been broken.
<literal>EAGAIN</literal> indicates that the endpoint has been
stalled, either at the request of the host or by other activity
inside the peripheral.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -