Data endpoints – Comtrol eCos User Manual
Page 712

Writing a USB Device Driver
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.
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
control_buffer
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
standard_control_fn
callback (if any), and
finally to the default handler
usbs_handle_standard_control
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.
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
. The driver is also responsible for
keeping track of whether or not the control operation has succeeded and generating an ACK or STALL handshake.
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.
Data Endpoints
In addition to the control endpoint data structure, a USB device driver should also provide appropriate
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.
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
,
,
and
. The device driver is also responsible for maintaining the
halted
status.
For data transfers, higher-level code will have filled in the
buffer
,
buffer_size
,
complete_fn
and
com-
plete_data
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
-EAGAIN
. If the transfer cannot be completed because the connection is broken
then the completion function should be invoked with
-EPIPE
. If the endpoint is stalled during the transfer, either
because of a standard control message or because higher-level code calls the appropriate
set_halted_fn
, then
again the completion function should be invoked with
-EAGAIN
. Finally, the <
usbs_start_rx_endpoint_wait
and
usbs_start_tx_endpoint_wait
functions involve calling the device driver’s data transfer function with a
buffer size of 0 bytes.
608