📄 usbs-control.html
字号:
></TD></TR></TABLE><P>When a USB peripheral is connected to the host it must always respondto control messages sent to endpoint 0. Control messages alwaysconsist of an initial eight-byte header, containing fields such as arequest type. This may be followed by a further data transfer, eitherfrom host to peripheral or from peripheral to host. The way this ishandled is described in the <AHREF="usbs-control.html#AEN16615">Buffer Management</A> section below.</P><P>The USB device driver will always accept the initial eight-byteheader, storing it in the <TTCLASS="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 isdescribed in the section <AHREF="usbs-control.html#AEN16607">OtherControl Messages</A>. Somestandard control messages will be handled by the device driver itself;typically the <SPANCLASS="emphasis"><ICLASS="EMPHASIS">set-address</I></SPAN> request and the<SPANCLASS="emphasis"><ICLASS="EMPHASIS">get-status</I></SPAN>, <SPANCLASS="emphasis"><ICLASS="EMPHASIS">set-feature</I></SPAN> and<SPANCLASS="emphasis"><ICLASS="EMPHASIS">clear-feature</I></SPAN> requests when applied to endpoints.</P><P>If a standard control message cannot be handled by the device driveritself, the driver checks the<TTCLASS="STRUCTFIELD"><I>standard_control_fn</I></TT> field in the controlendpoint data structure. If higher-level code has installed a suitablecallback function then this will be invoked with two argument, thecontrol endpoint data structure itself and the<TTCLASS="STRUCTFIELD"><I>standard_control_data</I></TT> field. The latterallows the higher level code to associate arbitrary data with thecontrol endpoint. The callback function can return one of threevalues: <SPANCLASS="emphasis"><ICLASS="EMPHASIS">HANDLED</I></SPAN> to indicate that the request hasbeen processed; <SPANCLASS="emphasis"><ICLASS="EMPHASIS">UNKNOWN</I></SPAN> if the message should behandled by the default code; or <SPANCLASS="emphasis"><ICLASS="EMPHASIS">STALL</I></SPAN> to indicatean error condition. If higher level code has not installed a callbackfunction or if the callback function has returned<SPANCLASS="emphasis"><ICLASS="EMPHASIS">UNKNOWN</I></SPAN> then the device driver will invoke adefault handler, <TTCLASS="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 messagesfor a simple USB peripheral. However, if the peripheral involvesmultiple configurations, multiple interfaces in a configuration, oralternate settings for an interface, then this cannot be handled bygeneric code. For example, a multimedia peripheral may support variousalternate settings for a given data source with different bandwidthrequirements, and the host can select a setting that takes intoaccount the current load. Clearly higher-level code needs to be awarewhen the host changes the current setting, so that it can adjust therate at which data is fed to or retrieved from the host. Therefore thehigher-level code needs to install its own standard control callbackand process appropriate messages, rather than leaving these to thedefault handler.</P><P>The default handler will take care of the<SPANCLASS="emphasis"><ICLASS="EMPHASIS">get-descriptor</I></SPAN> request used to obtain theenumeration data. It has support for string descriptors but ignoreslanguage encoding issues. If language encoding is important for theperipheral then this will have to be handled by anapplication-specific standard control handler.</P><P>The header file <TTCLASS="FILENAME"><cyg/io/usb/usb.h></TT> defines variousconstants related to control messages, for example the function codescorresponding to the standard request types. This header file isprovided by the common USB package, not by the USB slave package,since the information is also relevant to USB hosts.</P></DIV><DIVCLASS="REFSECT2"><ANAME="AEN16607"></A><H3>Other Control Messages</H3><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRECLASS="PROGRAMLISTING">typedef struct usbs_control_endpoint { … 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; …} usbs_control_endpoint;</PRE></TD></TR></TABLE><P>Non-standard control messages always have to be processed byhigher-level code. This could be class-specific packages. For example,the USB-ethernet package will handle requests for getting the MACaddress and for enabling or disabling promiscuous mode. In all casesthe device driver will store the initial request in the<TTCLASS="STRUCTFIELD"><I>control_buffer</I></TT> field, check for anappropriate handler, and invoke it with details of the controlendpoint and any handler-specific data that has been installedalongside the handler itself. The handler should return either<TTCLASS="LITERAL">USBS_CONTROL_RETURN_HANDLED</TT> to report success or<TTCLASS="LITERAL">USBS_CONTROL_RETURN_STALL</TT> to report failure. Thedevice driver will report this to the host.</P><P>If there are multiple parties interested in a particular type ofcontrol messages, it is the responsibility of application code toinstall an appropriate handler and process the requests appropriately. </P></DIV><DIVCLASS="REFSECT2"><ANAME="AEN16615"></A><H3>Buffer Management</H3><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRECLASS="PROGRAMLISTING">typedef struct usbs_control_endpoint { … 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); …} usbs_control_endpoint;</PRE></TD></TR></TABLE><P>Many USB control messages involve transferring more data than just theinitial eight-byte header. The header indicates the direction of thetransfer, OUT for host to peripheral or IN for peripheral to host.It also specifies a length field, which is exact for an OUT transferor an upper bound for an IN transfer. Control message handlers canmanipulate six fields within the control endpoint data structure toensure that the transfer happens correctly.</P><P>For an OUT transfer, the handler should examine the length field inthe header and provide a single buffer for all the data. Aclass-specific protocol would typically impose an upper bound on theamount of data, allowing the buffer to be allocated statically.The handler should update the <TTCLASS="STRUCTFIELD"><I>buffer</I></TT> and<TTCLASS="STRUCTFIELD"><I>complete_fn</I></TT> fields. When all the data hasbeen transferred the completion callback will be invoked, and itsreturn value determines the response sent back to the host. The USBstandard allows for a new control message to be sent before thecurrent transfer has completed, effectively cancelling the currentoperation. When this happens the completion function will also beinvoked. The second argument to the completion function specifies whathas happened, with a value of 0 indicating success and an error codesuch as <TTCLASS="LITERAL">-EPIPE</TT> or <TTCLASS="LITERAL">-EIO</TT>indicating that the current transfer has been cancelled.</P><P>IN transfers are a little bit more complicated. The requiredinformation, for example the enumeration data, may not be in a singlecontiguous buffer. Instead a mechanism is provided by which the buffercan be refilled, thus allowing the transfer to move from one record tothe next. Essentially, the transfer operates as follows:</P><P></P><OLTYPE="1"><LI><P>When the host requests another chunk of data (typically eight bytes),the USB device driver will examine the<TTCLASS="STRUCTFIELD"><I>buffer_size</I></TT> field. If non-zero then<TTCLASS="STRUCTFIELD"><I>buffer</I></TT> contains at least one more byte ofdata, and then <TTCLASS="STRUCTFIELD"><I>buffer_size</I></TT> is decremented.</P></LI><LI><P>When <TTCLASS="STRUCTFIELD"><I>buffer_size</I></TT> has dropped to 0, the<TTCLASS="STRUCTFIELD"><I>fill_buffer_fn</I></TT> field will be examined. Ifnon-null it will be invoked to refill the buffer.</P></LI><LI><P>The <TTCLASS="STRUCTFIELD"><I>fill_data</I></TT> and<TTCLASS="STRUCTFIELD"><I>fill_index</I></TT> fields are not used by thedevice driver. Instead these fields are available to the refillfunction to keep track of the current state of the transfer.</P></LI><LI><P>When <TTCLASS="STRUCTFIELD"><I>buffer_size</I></TT> is 0 and<TTCLASS="STRUCTFIELD"><I>fill_buffer_fn</I></TT> is NULL, no more data isavailable and the transfer has completed.</P></LI><LI><P>Optionally a completion function can be installed. This will beinvoked with 0 if the transfer completes successfully, or with anerror code if the transfer is cancelled because of another controlmesssage. </P></LI></OL><P>If the requested data is contiguous then the only fields that needto be manipulated are <TTCLASS="STRUCTFIELD"><I>buffer</I></TT> and<TTCLASS="STRUCTFIELD"><I>buffer_size</I></TT>, and optionally<TTCLASS="STRUCTFIELD"><I>complete_fn</I></TT>. If the requested data is notcontiguous then the initial control message handler should update<TTCLASS="STRUCTFIELD"><I>fill_buffer_fn</I></TT> and some or all of the otherfields, as required. An example of this is the handling of thestandard <SPANCLASS="emphasis"><ICLASS="EMPHASIS">get-descriptor</I></SPAN> control message by<TTCLASS="FUNCTION">usbs_handle_standard_control</TT>.</P></DIV><DIVCLASS="REFSECT2"><ANAME="AEN16652"></A><H3>Polling Support</H3><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRECLASS="PROGRAMLISTING">typedef struct usbs_control_endpoint { void (*poll_fn)(struct usbs_control_endpoint*); int interrupt_vector; …} 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 polledoperation may be appropriate. If the device driver can operate inpolled mode then it will provide a suitable function via the<TTCLASS="STRUCTFIELD"><I>poll_fn</I></TT> field, and higher-level code caninvoke this regularly. This polling function will take care of allendpoints associated with the device, not just the control endpoint.If the USB hardware involves a single interrupt vector then this willbe identified in the data structure as well.</P></DIV></DIV><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLESUMMARY="Footer navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><AHREF="usbs-halt.html"ACCESSKEY="P">Prev</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="ecos-ref.html"ACCESSKEY="H">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><AHREF="usbs-data.html"ACCESSKEY="N">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Halted Endpoints</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="io-usb-slave.html"ACCESSKEY="U">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Data Endpoints</TD></TR></TABLE></DIV></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -