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

📄 usbs-writing.html

📁 ecos源代码包
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<!-- Copyright (C) 2003 Red Hat, Inc.                                -->
<!-- This material may be distributed only subject to the terms      -->
<!-- and conditions set forth in the Open Publication License, v1.0  -->
<!-- or later (the latest version is presently available at          -->
<!-- http://www.opencontent.org/openpub/).                           -->
<!-- Distribution of the work or derivative of the work in any       -->
<!-- standard (paper) book form is prohibited unless prior           -->
<!-- permission is obtained from the copyright holder.               -->
<HTML
><HEAD
><TITLE
>Writing a USB Device Driver</TITLE
><meta name="MSSmartTagsPreventParsing" content="TRUE">
<META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
"><LINK
REL="HOME"
TITLE="eCos Reference Manual"
HREF="ecos-ref.html"><LINK
REL="UP"
TITLE="eCos USB Slave Support"
HREF="io-usb-slave.html"><LINK
REL="PREVIOUS"
TITLE="Data Endpoints"
HREF="usbs-data.html"><LINK
REL="NEXT"
TITLE="Testing"
HREF="usbs-testing.html"></HEAD
><BODY
CLASS="REFENTRY"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>eCos Reference Manual</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="usbs-data.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="usbs-testing.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><H1
><A
NAME="USBS-WRITING">Writing a USB Device Driver</H1
><DIV
CLASS="REFNAMEDIV"
><A
NAME="AEN16705"
></A
><H2
>Name</H2
>Writing a USB Device Driver&nbsp;--&nbsp;USB Device Driver Porting Guide</DIV
><DIV
CLASS="REFSECT1"
><A
NAME="AEN16708"
></A
><H2
>Introduction</H2
><P
>Often the best way to write a USB device driver will be to start with
an existing one and modify it as necessary. The information given here
is intended primarily as an outline rather than as a complete guide.</P
><DIV
CLASS="NOTE"
><BLOCKQUOTE
CLASS="NOTE"
><P
><B
>Note: </B
>At the time of writing only one USB device driver has been
implemented. Hence it is possible, perhaps probable, that some
portability issues have not yet been addressed. One issue
involves the different types of transfer, for example the initial
target hardware had no support for isochronous or interrupt transfers,
so additional functionality may be needed to switch between transfer
types. Another issue would be hardware where a given endpoint number,
say endpoint 1, could be used for either receiving or transmitting
data, but not both because a single fifo is used. Issues like these
will have to be resolved as and when additional USB device drivers are
written.</P
></BLOCKQUOTE
></DIV
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="AEN16713"
></A
><H2
>The Control Endpoint</H2
><P
>A USB device driver should provide a single <A
HREF="usbs-control.html"
><SPAN
CLASS="STRUCTNAME"
>usbs_control_endpoint</SPAN
></A
>
data structure for every USB device. Typical peripherals will have
only one USB port so there will be just one such data structure in the
entire system, but theoretically it is possible to have multiple USB
devices. These may all involve the same chip, in which case a single
device driver should support multiple device instances, or they may
involve different chips. The name or names of these data structures
are determined by the device driver, but appropriate care should be
taken to avoid name clashes. </P
><P
>A USB device cannot be used unless the control endpoint data structure
exists. However, the presence of USB hardware in the target processor
or board does not guarantee that the application will necessarily want
to use that hardware. To avoid unwanted code or data overheads, the
device driver can provide a configuration option to determine whether
or not the endpoint 0 data structure is actually provided. A default
value of <TT
CLASS="LITERAL"
>CYGINT_IO_USB_SLAVE_CLIENTS</TT
> ensures that
the USB driver will be enabled automatically if higher-level code does
require USB support, while leaving ultimate control to the user.</P
><P
>The USB device driver is responsible for filling in the
<TT
CLASS="STRUCTFIELD"
><I
>start_fn</I
></TT
>,
<TT
CLASS="STRUCTFIELD"
><I
>poll_fn</I
></TT
> and
<TT
CLASS="STRUCTFIELD"
><I
>interrupt_vector</I
></TT
> fields. Usually this can
be achieved by static initialization. The driver is also largely
responsible for maintaining the <TT
CLASS="STRUCTFIELD"
><I
>state</I
></TT
>
field. The <TT
CLASS="STRUCTFIELD"
><I
>control_buffer</I
></TT
> array should be
used to hold the first packet of a control message. The
<TT
CLASS="STRUCTFIELD"
><I
>buffer</I
></TT
> and other fields related to data
transfers will be managed <A
HREF="usbs-control.html#AEN16615"
>jointly</A
> by higher-level code and
the device driver. The remaining fields are generally filled in by
higher-level code, although the driver should initialize them to NULL
values.</P
><P
>Hardware permitting, the USB device should be inactive until the
<TT
CLASS="STRUCTFIELD"
><I
>start_fn</I
></TT
> is invoked, for example by
tristating the appropriate pins. This prevents the host from
interacting with the peripheral before all other parts of the system
have initialized. It is expected that the
<TT
CLASS="STRUCTFIELD"
><I
>start_fn</I
></TT
> will only be invoked once, shortly
after power-up.</P
><P
>Where possible the device driver should detect state changes, such as
when the connection between host and peripheral is established, and
<A
HREF="usbs-control.html#AEN16552"
>report</A
> these to higher-level
code via the <TT
CLASS="STRUCTFIELD"
><I
>state_change_fn</I
></TT
> callback, if
any. The state change to and from configured state cannot easily be
handled by the device driver itself, instead higher-level code such as
the common USB slave package will take care of this.</P
><P
>Once the connection between host and peripheral has been established,
the peripheral must be ready to accept control messages at all times,
and must respond to these within certain time constraints. For
example, the standard set-address control message must be handled
within 50ms. The USB specification provides more information on these
constraints. The device driver is responsible for receiving the
initial packet of a control message. This packet will always be eight
bytes and should be stored in the
<TT
CLASS="STRUCTFIELD"
><I
>control_buffer</I
></TT
> field. Certain standard
control messages should be detected and handled by the device driver
itself. The most important is set-address, but usually the get-status,
set-feature and clear-feature requests when applied to halted
endpoints should also be handled by the driver. Other standard control
messages should first be passed on to the
<TT
CLASS="STRUCTFIELD"
><I
>standard_control_fn</I
></TT
> callback (if any), and
finally to the default handler
<TT
CLASS="FUNCTION"
>usbs_handle_standard_control</TT
> provided by the
common USB slave package. Class, vendor and reserved control messages
should always be dispatched to the appropriate callback and there is
no default handler for these.</P
><P
>Some control messages will involve further data transfer, not just the
initial packet. The device driver must handle this in accordance with
the USB specification and the <A
HREF="usbs-control.html#AEN16615"
>buffer management strategy</A
>. The
driver is also responsible for keeping track of whether or not the
control operation has succeeded and generating an ACK or STALL
handshake. </P
><P
>The polling support is optional and may not be feasible on all
hardware. It is only used in certain specialised environments such as
RedBoot. A typical implementation of the polling function would just
check whether or not an interrupt would have occurred and, if so, call
the same code that the interrupt handler would.</P
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="AEN16741"
></A
><H2
>Data Endpoints</H2
><P
>In addition to the control endpoint data structure, a USB device
driver should also provide appropriate <A
HREF="usbs-data.html"
>data
endpoint</A
> data structures. Obviously this is only relevant if
the USB support generally is desired, that is if the control endpoint is
provided. In addition, higher-level code may not require all the
endpoints, so it may be useful to provide configuration options that
control the presence of each endpoint. For example, the intended
application might only involve a single transmit endpoint and of
course control messages, so supporting receive endpoints might waste
memory.</P
><P
>Conceptually, data endpoints are much simpler than the control
endpoint. The device driver has to supply two functions, one for
data transfers and another to control the halted condition. These
implement the functionality for
<A
HREF="usbs-start-rx.html"
><TT
CLASS="FUNCTION"
>usbs_start_rx_buffer</TT
></A
>,
<A
HREF="usbs-start-tx.html"
><TT
CLASS="FUNCTION"
>usbs_start_tx_buffer</TT
></A
>,
<A
HREF="usbs-halt.html"
><TT
CLASS="FUNCTION"
>usbs_set_rx_endpoint_halted</TT
></A
> and
<A
HREF="usbs-halt.html"
><TT
CLASS="FUNCTION"
>usbs_set_tx_endpoint_halted</TT
></A
>.
The device driver is also responsible for maintaining the
<TT
CLASS="STRUCTFIELD"
><I
>halted</I
></TT
> status.</P
><P
>For data transfers, higher-level code will have filled in the
<TT
CLASS="STRUCTFIELD"
><I
>buffer</I
></TT
>,
<TT
CLASS="STRUCTFIELD"
><I
>buffer_size</I
></TT
>,
<TT
CLASS="STRUCTFIELD"
><I
>complete_fn</I
></TT
> and
<TT
CLASS="STRUCTFIELD"
><I
>complete_data</I
></TT
> fields. The transfer function
should arrange for the transfer to start, allowing the host to send or
receive packets. Typically this will result in an interrupt at the end
of the transfer or after each packet. Once the entire transfer has
been completed, the driver's interrupt handling code should invoke the
completion function. This can happen either in DSR context or thread
context, depending on the driver's implementation. There are a number
of special cases to consider. If the endpoint is halted when the
transfer is started then the completion function can be invoked
immediately with <TT
CLASS="LITERAL"
>-EAGAIN</TT
>. If the transfer cannot be
completed because the connection is broken then the completion
function should be invoked with <TT
CLASS="LITERAL"
>-EPIPE</TT
>. If the
endpoint is stalled during the transfer, either because of a standard
control message or because higher-level code calls the appropriate
<TT
CLASS="STRUCTFIELD"
><I
>set_halted_fn</I
></TT
>, then again the completion
function should be invoked with <TT
CLASS="LITERAL"
>-EAGAIN</TT
>. Finally,
the &#60;<TT
CLASS="FUNCTION"
>usbs_start_rx_endpoint_wait</TT
> and
<TT
CLASS="FUNCTION"
>usbs_start_tx_endpoint_wait</TT
> functions involve
calling the device driver's data transfer function with a buffer size
of 0 bytes.</P
><DIV
CLASS="NOTE"
><BLOCKQUOTE
CLASS="NOTE"
><P
><B
>Note: </B
>Giving a buffer size of 0 bytes a special meaning is problematical
because it prevents transfers of that size. Such transfers are allowed
by the USB protocol, consisting of just headers and acknowledgements
and an empty data phase, although rarely useful. A future modification
of the device driver specification will address this issue, although
care has to be taken that the functionality remains accessible through
devtab entries as well as via low-level accesses.</P
></BLOCKQUOTE
></DIV
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="AEN16768"
></A
><H2
>Devtab Entries</H2
><P
>For some applications or higher-level packages it may be more
convenient to use traditional open/read/write I/O calls rather than
the non-blocking USB I/O calls. To support this the device driver can
provide a devtab entry for each endpoint, for example:</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>#ifdef CYGVAR_DEVS_USB_SA11X0_EP1_DEVTAB_ENTRY

static CHAR_DEVIO_TABLE(usbs_sa11x0_ep1_devtab_functions,
                        &amp;cyg_devio_cwrite,
                        &amp;usbs_devtab_cread,
                        &amp;cyg_devio_bwrite,
                        &amp;cyg_devio_bread,
                        &amp;cyg_devio_select,
                        &amp;cyg_devio_get_config,
                        &amp;cyg_devio_set_config);

static CHAR_DEVTAB_ENTRY(usbs_sa11x0_ep1_devtab_entry,
                         CYGDAT_DEVS_USB_SA11X0_DEVTAB_BASENAME "1r",
                         0,
                         &amp;usbs_sa11x0_ep1_devtab_functions,
                         &amp;usbs_sa11x0_devtab_dummy_init,
                         0,
                         (void*) &amp;usbs_sa11x0_ep1);
#endif</PRE
></TD

⌨️ 快捷键说明

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