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

📄 usbs-control.html

📁 ecos 文档
💻 HTML
📖 第 1 页 / 共 2 页
字号:
></TD
></TR
></TABLE
><P
>When a USB peripheral is connected to the host it must always respond
to control messages sent to endpoint 0. Control messages always
consist of an initial eight-byte header, containing fields such as a
request type. This may be followed by a further data transfer, either
from host to peripheral or from peripheral to host. The way this is
handled is described in the <A
HREF="usbs-control.html#AEN16619"
>Buffer Management</A
> section below.</P
><P
>The USB device driver will always accept the initial eight-byte
header, storing it in the <TT
CLASS="STRUCTFIELD"
><I
>control_buffer</I
></TT
>
field. Then it determines the request type: standard, class, vendor,
or reserved. The way in which the last three of these are processed is
described in the section <A
HREF="usbs-control.html#AEN16611"
>Other
Control Messages</A
>. Some
standard control messages will be handled by the device driver itself;
typically the <SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>set-address</I
></SPAN
> request and the
<SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>get-status</I
></SPAN
>, <SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>set-feature</I
></SPAN
> and
<SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>clear-feature</I
></SPAN
> requests when applied to endpoints.</P
><P
>If a standard control message cannot be handled by the device driver
itself, the driver checks the
<TT
CLASS="STRUCTFIELD"
><I
>standard_control_fn</I
></TT
> field in the control
endpoint data structure. If higher-level code has installed a suitable
callback function then this will be invoked with two argument, the
control endpoint data structure itself and the
<TT
CLASS="STRUCTFIELD"
><I
>standard_control_data</I
></TT
> field. The latter
allows the higher level code to associate arbitrary data with the
control endpoint. The callback function can return one of three
values: <SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>HANDLED</I
></SPAN
> to indicate that the request has
been processed; <SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>UNKNOWN</I
></SPAN
> if the message should be
handled by the default code; or <SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>STALL</I
></SPAN
> to indicate
an error condition. If higher level code has not installed a callback
function or if the callback function has returned
<SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>UNKNOWN</I
></SPAN
> then the device driver will invoke a
default handler, <TT
CLASS="FUNCTION"
>usbs_handle_standard_control</TT
>
provided by the common USB slave package.</P
><P
>The default handler can cope with all of the standard control messages
for a simple USB peripheral. However, if the peripheral involves
multiple configurations, multiple interfaces in a configuration, or
alternate settings for an interface, then this cannot be handled by
generic code. For example, a multimedia peripheral may support various
alternate settings for a given data source with different bandwidth
requirements, and the host can select a setting that takes into
account the current load. Clearly higher-level code needs to be aware
when the host changes the current setting, so that it can adjust the
rate at which data is fed to or retrieved from the host. Therefore the
higher-level code needs to install its own standard control callback
and process appropriate messages, rather than leaving these to the
default handler.</P
><P
>The default handler will take care of the
<SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>get-descriptor</I
></SPAN
> request used to obtain the
enumeration data. It has support for string descriptors but ignores
language encoding issues. If language encoding is important for the
peripheral then this will have to be handled by an
application-specific standard control handler.</P
><P
>The header file <TT
CLASS="FILENAME"
>&lt;cyg/io/usb/usb.h&gt;</TT
> defines various
constants related to control messages, for example the function codes
corresponding to the standard request types. This header file is
provided by the common USB package, not by the USB slave package,
since the information is also relevant to USB hosts.</P
></DIV
><DIV
CLASS="REFSECT2"
><A
NAME="AEN16611"
></A
><H3
>Other Control Messages</H3
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>typedef struct usbs_control_endpoint {
    &#8230;
    usbs_control_return (*class_control_fn)(struct usbs_control_endpoint*, void*);
    void*               class_control_data;
    usbs_control_return (*vendor_control_fn)(struct usbs_control_endpoint*, void*);
    void*               vendor_control_data;
    usbs_control_return (*reserved_control_fn)(struct usbs_control_endpoint*, void*);
    void*               reserved_control_data;
    &#8230;
} usbs_control_endpoint;</PRE
></TD
></TR
></TABLE
><P
>Non-standard control messages always have to be processed by
higher-level code. This could be class-specific packages. For example,
the USB-ethernet package will handle requests for getting the MAC
address and for enabling or disabling promiscuous mode. In all cases
the device driver will store the initial request in the
<TT
CLASS="STRUCTFIELD"
><I
>control_buffer</I
></TT
> field, check for an
appropriate handler, and invoke it with details of the control
endpoint and any handler-specific data that has been installed
alongside the handler itself. The handler should return either
<TT
CLASS="LITERAL"
>USBS_CONTROL_RETURN_HANDLED</TT
> to report success or
<TT
CLASS="LITERAL"
>USBS_CONTROL_RETURN_STALL</TT
> to report failure. The
device driver will report this to the host.</P
><P
>If there are multiple parties interested in a particular type of
control messages, it is the responsibility of application code to
install an appropriate handler and process the requests appropriately. </P
></DIV
><DIV
CLASS="REFSECT2"
><A
NAME="AEN16619"
></A
><H3
>Buffer Management</H3
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>typedef struct usbs_control_endpoint {
    &#8230;
    unsigned char*      buffer;
    int                 buffer_size;
    void                (*fill_buffer_fn)(struct usbs_control_endpoint*);
    void*               fill_data;
    int                 fill_index;
    usbs_control_return (*complete_fn)(struct usbs_control_endpoint*, int);
    &#8230;
} usbs_control_endpoint;</PRE
></TD
></TR
></TABLE
><P
>Many USB control messages involve transferring more data than just the
initial eight-byte header. The header indicates the direction of the
transfer, OUT for host to peripheral or IN for peripheral to host.
It also specifies a length field, which is exact for an OUT transfer
or an upper bound for an IN transfer. Control message handlers can
manipulate six fields within the control endpoint data structure to
ensure that the transfer happens correctly.</P
><P
>For an OUT transfer, the handler should examine the length field in
the header and provide a single buffer for all the data. A
class-specific protocol would typically impose an upper bound on the
amount of data, allowing the buffer to be allocated statically.
The handler should update the <TT
CLASS="STRUCTFIELD"
><I
>buffer</I
></TT
> and
<TT
CLASS="STRUCTFIELD"
><I
>complete_fn</I
></TT
> fields. When all the data has
been transferred the completion callback will be invoked, and its
return value determines the response sent back to the host. The USB
standard allows for a new control message to be sent before the
current transfer has completed, effectively cancelling the current
operation. When this happens the completion function will also be
invoked. The second argument to the completion function specifies what
has happened, with a value of 0 indicating success and an error code
such as <TT
CLASS="LITERAL"
>-EPIPE</TT
> or <TT
CLASS="LITERAL"
>-EIO</TT
>
indicating that the current transfer has been cancelled.</P
><P
>IN transfers are a little bit more complicated. The required
information, for example the enumeration data, may not be in a single
contiguous buffer. Instead a mechanism is provided by which the buffer
can be refilled, thus allowing the transfer to move from one record to
the next. Essentially, the transfer operates as follows:</P
><P
></P
><OL
TYPE="1"
><LI
><P
>When the host requests another chunk of data (typically eight bytes),
the USB device driver will examine the
<TT
CLASS="STRUCTFIELD"
><I
>buffer_size</I
></TT
> field. If non-zero then
<TT
CLASS="STRUCTFIELD"
><I
>buffer</I
></TT
> contains at least one more byte of
data, and then <TT
CLASS="STRUCTFIELD"
><I
>buffer_size</I
></TT
> is decremented.</P
></LI
><LI
><P
>When <TT
CLASS="STRUCTFIELD"
><I
>buffer_size</I
></TT
> has dropped to 0, the
<TT
CLASS="STRUCTFIELD"
><I
>fill_buffer_fn</I
></TT
> field will be examined. If
non-null it will be invoked to refill the buffer.</P
></LI
><LI
><P
>The <TT
CLASS="STRUCTFIELD"
><I
>fill_data</I
></TT
> and
<TT
CLASS="STRUCTFIELD"
><I
>fill_index</I
></TT
> fields are not used by the
device driver. Instead these fields are available to the refill
function to keep track of the current state of the transfer.</P
></LI
><LI
><P
>When <TT
CLASS="STRUCTFIELD"
><I
>buffer_size</I
></TT
> is 0 and
<TT
CLASS="STRUCTFIELD"
><I
>fill_buffer_fn</I
></TT
> is NULL, no more data is
available and the transfer has completed.</P
></LI
><LI
><P
>Optionally a completion function can be installed. This will be
invoked with 0 if the transfer completes successfully, or with an
error code if the transfer is cancelled because of another control
messsage. </P
></LI
></OL
><P
>If the requested data is contiguous then the only fields that need
to be manipulated are <TT
CLASS="STRUCTFIELD"
><I
>buffer</I
></TT
> and
<TT
CLASS="STRUCTFIELD"
><I
>buffer_size</I
></TT
>, and optionally
<TT
CLASS="STRUCTFIELD"
><I
>complete_fn</I
></TT
>. If the requested data is not
contiguous then the initial control message handler should update
<TT
CLASS="STRUCTFIELD"
><I
>fill_buffer_fn</I
></TT
> and some or all of the other
fields, as required. An example of this is the handling of the
standard <SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>get-descriptor</I
></SPAN
> control message by
<TT
CLASS="FUNCTION"
>usbs_handle_standard_control</TT
>.</P
></DIV
><DIV
CLASS="REFSECT2"
><A
NAME="AEN16656"
></A
><H3
>Polling Support</H3
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>typedef struct usbs_control_endpoint {
    void                (*poll_fn)(struct usbs_control_endpoint*);
    int                 interrupt_vector;
    &#8230;
} usbs_control_endpoint;</PRE
></TD
></TR
></TABLE
><P
>In nearly all circumstances USB I/O should be interrupt-driven.
However, there are special environments such as RedBoot where polled
operation may be appropriate. If the device driver can operate in
polled mode then it will provide a suitable function via the
<TT
CLASS="STRUCTFIELD"
><I
>poll_fn</I
></TT
> field, and higher-level code can
invoke this regularly. This polling function will take care of all
endpoints associated with the device, not just the control endpoint.
If the USB hardware involves a single interrupt vector then this will
be identified in the data structure as well.</P
></DIV
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="usbs-halt.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="ecos-ref.html"
ACCESSKEY="H"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="usbs-data.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Halted Endpoints</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="io-usb-slave.html"
ACCESSKEY="U"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Data Endpoints</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>

⌨️ 快捷键说明

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