📄 usbs-writing.html
字号:
<!-- 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"><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+"><LINKREL="HOME"TITLE="eCos Reference Manual"HREF="ecos-ref.html"><LINKREL="UP"TITLE="eCos USB Slave Support"HREF="io-usb-slave.html"><LINKREL="PREVIOUS"TITLE="Data Endpoints"HREF="usbs-data.html"><LINKREL="NEXT"TITLE="Testing"HREF="usbs-testing.html"></HEAD><BODYCLASS="REFENTRY"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">eCos Reference Manual</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="usbs-data.html"ACCESSKEY="P">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom"></TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="usbs-testing.html"ACCESSKEY="N">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><H1><ANAME="USBS-WRITING">Writing a USB Device Driver</H1><DIVCLASS="REFNAMEDIV"><ANAME="AEN16705"></A><H2>Name</H2>Writing a USB Device Driver -- USB Device Driver Porting Guide</DIV><DIVCLASS="REFSECT1"><ANAME="AEN16708"></A><H2>Introduction</H2><P>Often the best way to write a USB device driver will be to start withan existing one and modify it as necessary. The information given hereis intended primarily as an outline rather than as a complete guide.</P><DIVCLASS="NOTE"><BLOCKQUOTECLASS="NOTE"><P><B>Note: </B>At the time of writing only one USB device driver has beenimplemented. Hence it is possible, perhaps probable, that someportability issues have not yet been addressed. One issueinvolves the different types of transfer, for example the initialtarget hardware had no support for isochronous or interrupt transfers,so additional functionality may be needed to switch between transfertypes. Another issue would be hardware where a given endpoint number,say endpoint 1, could be used for either receiving or transmittingdata, but not both because a single fifo is used. Issues like thesewill have to be resolved as and when additional USB device drivers arewritten.</P></BLOCKQUOTE></DIV></DIV><DIVCLASS="REFSECT1"><ANAME="AEN16713"></A><H2>The Control Endpoint</H2><P>A USB device driver should provide a single <AHREF="usbs-control.html"><SPANCLASS="STRUCTNAME">usbs_control_endpoint</SPAN></A>data structure for every USB device. Typical peripherals will haveonly one USB port so there will be just one such data structure in theentire system, but theoretically it is possible to have multiple USBdevices. These may all involve the same chip, in which case a singledevice driver should support multiple device instances, or they mayinvolve different chips. The name or names of these data structuresare determined by the device driver, but appropriate care should betaken to avoid name clashes. </P><P>A USB device cannot be used unless the control endpoint data structureexists. However, the presence of USB hardware in the target processoror board does not guarantee that the application will necessarily wantto use that hardware. To avoid unwanted code or data overheads, thedevice driver can provide a configuration option to determine whetheror not the endpoint 0 data structure is actually provided. A defaultvalue of <TTCLASS="LITERAL">CYGINT_IO_USB_SLAVE_CLIENTS</TT> ensures thatthe USB driver will be enabled automatically if higher-level code doesrequire USB support, while leaving ultimate control to the user.</P><P>The USB device driver is responsible for filling in the<TTCLASS="STRUCTFIELD"><I>start_fn</I></TT>,<TTCLASS="STRUCTFIELD"><I>poll_fn</I></TT> and<TTCLASS="STRUCTFIELD"><I>interrupt_vector</I></TT> fields. Usually this canbe achieved by static initialization. The driver is also largelyresponsible for maintaining the <TTCLASS="STRUCTFIELD"><I>state</I></TT>field. The <TTCLASS="STRUCTFIELD"><I>control_buffer</I></TT> array should beused to hold the first packet of a control message. The<TTCLASS="STRUCTFIELD"><I>buffer</I></TT> and other fields related to datatransfers will be managed <AHREF="usbs-control.html#AEN16615">jointly</A> by higher-level code andthe device driver. The remaining fields are generally filled in byhigher-level code, although the driver should initialize them to NULLvalues.</P><P>Hardware permitting, the USB device should be inactive until the<TTCLASS="STRUCTFIELD"><I>start_fn</I></TT> is invoked, for example bytristating the appropriate pins. This prevents the host frominteracting with the peripheral before all other parts of the systemhave initialized. It is expected that the<TTCLASS="STRUCTFIELD"><I>start_fn</I></TT> will only be invoked once, shortlyafter power-up.</P><P>Where possible the device driver should detect state changes, such aswhen the connection between host and peripheral is established, and<AHREF="usbs-control.html#AEN16552">report</A> these to higher-levelcode via the <TTCLASS="STRUCTFIELD"><I>state_change_fn</I></TT> callback, ifany. The state change to and from configured state cannot easily behandled by the device driver itself, instead higher-level code such asthe 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. Forexample, the standard set-address control message must be handledwithin 50ms. The USB specification provides more information on theseconstraints. The device driver is responsible for receiving theinitial packet of a control message. This packet will always be eightbytes and should be stored in the<TTCLASS="STRUCTFIELD"><I>control_buffer</I></TT> field. Certain standardcontrol messages should be detected and handled by the device driveritself. The most important is set-address, but usually the get-status,set-feature and clear-feature requests when applied to haltedendpoints should also be handled by the driver. Other standard controlmessages should first be passed on to the<TTCLASS="STRUCTFIELD"><I>standard_control_fn</I></TT> callback (if any), andfinally to the default handler<TTCLASS="FUNCTION">usbs_handle_standard_control</TT> provided by thecommon USB slave package. Class, vendor and reserved control messagesshould always be dispatched to the appropriate callback and there isno default handler for these.</P><P>Some control messages will involve further data transfer, not just theinitial packet. The device driver must handle this in accordance withthe USB specification and the <AHREF="usbs-control.html#AEN16615">buffer management strategy</A>. Thedriver is also responsible for keeping track of whether or not thecontrol operation has succeeded and generating an ACK or STALLhandshake. </P><P>The polling support is optional and may not be feasible on allhardware. It is only used in certain specialised environments such asRedBoot. A typical implementation of the polling function would justcheck whether or not an interrupt would have occurred and, if so, callthe same code that the interrupt handler would.</P></DIV><DIVCLASS="REFSECT1"><ANAME="AEN16741"></A><H2>Data Endpoints</H2><P>In addition to the control endpoint data structure, a USB devicedriver should also provide appropriate <AHREF="usbs-data.html">dataendpoint</A> data structures. Obviously this is only relevant ifthe USB support generally is desired, that is if the control endpoint isprovided. In addition, higher-level code may not require all theendpoints, so it may be useful to provide configuration options thatcontrol the presence of each endpoint. For example, the intendedapplication might only involve a single transmit endpoint and ofcourse control messages, so supporting receive endpoints might wastememory.</P><P>Conceptually, data endpoints are much simpler than the controlendpoint. The device driver has to supply two functions, one fordata transfers and another to control the halted condition. Theseimplement the functionality for<AHREF="usbs-start-rx.html"><TTCLASS="FUNCTION">usbs_start_rx_buffer</TT></A>,<AHREF="usbs-start-tx.html"><TTCLASS="FUNCTION">usbs_start_tx_buffer</TT></A>,<AHREF="usbs-halt.html"><TTCLASS="FUNCTION">usbs_set_rx_endpoint_halted</TT></A> and<AHREF="usbs-halt.html"><TTCLASS="FUNCTION">usbs_set_tx_endpoint_halted</TT></A>.The device driver is also responsible for maintaining the<TTCLASS="STRUCTFIELD"><I>halted</I></TT> status.</P><P>For data transfers, higher-level code will have filled in the<TTCLASS="STRUCTFIELD"><I>buffer</I></TT>,<TTCLASS="STRUCTFIELD"><I>buffer_size</I></TT>,<TTCLASS="STRUCTFIELD"><I>complete_fn</I></TT> and<TTCLASS="STRUCTFIELD"><I>complete_data</I></TT> fields. The transfer functionshould arrange for the transfer to start, allowing the host to send orreceive packets. Typically this will result in an interrupt at the endof the transfer or after each packet. Once the entire transfer hasbeen completed, the driver's interrupt handling code should invoke thecompletion function. This can happen either in DSR context or threadcontext, depending on the driver's implementation. There are a numberof special cases to consider. If the endpoint is halted when thetransfer is started then the completion function can be invokedimmediately with <TTCLASS="LITERAL">-EAGAIN</TT>. If the transfer cannot becompleted because the connection is broken then the completionfunction should be invoked with <TTCLASS="LITERAL">-EPIPE</TT>. If theendpoint is stalled during the transfer, either because of a standardcontrol message or because higher-level code calls the appropriate<TTCLASS="STRUCTFIELD"><I>set_halted_fn</I></TT>, then again the completionfunction should be invoked with <TTCLASS="LITERAL">-EAGAIN</TT>. Finally,the <<TTCLASS="FUNCTION">usbs_start_rx_endpoint_wait</TT> and<TTCLASS="FUNCTION">usbs_start_tx_endpoint_wait</TT> functions involvecalling the device driver's data transfer function with a buffer sizeof 0 bytes.</P><DIVCLASS="NOTE"><BLOCKQUOTECLASS="NOTE"><P><B>Note: </B>Giving a buffer size of 0 bytes a special meaning is problematicalbecause it prevents transfers of that size. Such transfers are allowedby the USB protocol, consisting of just headers and acknowledgementsand an empty data phase, although rarely useful. A future modificationof the device driver specification will address this issue, althoughcare has to be taken that the functionality remains accessible throughdevtab entries as well as via low-level accesses.</P></BLOCKQUOTE></DIV></DIV><DIVCLASS="REFSECT1"><ANAME="AEN16768"></A><H2>Devtab Entries</H2><P>For some applications or higher-level packages it may be moreconvenient to use traditional open/read/write I/O calls rather thanthe non-blocking USB I/O calls. To support this the device driver canprovide a devtab entry for each endpoint, for example:</P><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRECLASS="PROGRAMLISTING">#ifdef CYGVAR_DEVS_USB_SA11X0_EP1_DEVTAB_ENTRYstatic CHAR_DEVIO_TABLE(usbs_sa11x0_ep1_devtab_functions, &cyg_devio_cwrite, &usbs_devtab_cread, &cyg_devio_bwrite, &cyg_devio_bread, &cyg_devio_select, &cyg_devio_get_config, &cyg_devio_set_config);static CHAR_DEVTAB_ENTRY(usbs_sa11x0_ep1_devtab_entry, CYGDAT_DEVS_USB_SA11X0_DEVTAB_BASENAME "1r", 0, &usbs_sa11x0_ep1_devtab_functions, &usbs_sa11x0_devtab_dummy_init, 0, (void*) &usbs_sa11x0_ep1);#endif</PRE></TD
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -