Control Endpoints#
lib_xud
provides helper functions that provide a set of standard functionality to aid the
creation of USB devices.
Control transfers are typically used for command and status operations. They are essential to set up a USB device with all enumeration functions being performed using Control transfers. Control transfers are characterised by the use of a SETUP transaction.
USB devices must provide an implementation of a control endpoint at endpoint 0. Endpoint 0 must deal with enumeration and configuration requests from the host. Many enumeration requests are compulsory and common to all devices, with most of them being requests for mandatory descriptors (Configuration, Device, String, etc).
Since these requests are common across most (if not all) devices, some useful functions are provided to deal with them.
Helper Functions#
Firstly, the function USB_GetSetupPacket()
is provided. This makes a call to the low-level
XUD function XUD_GetSetupBuffer()
with the 8 byte Setup packet which it parses into a
USB_SetupPacket_t
structure for further inspection. The USB_SetupPacket_t
structure passed
by reference to USB_GetSetupPacket()
is populated by the function.
At this point the request is in a good state to be parsed by endpoint 0. Please see Universal Serial Bus 2.0 specification for full details of Setup packet and request structure.
A USB_StandardRequests()
function provides a bare-minimum implementation of the mandatory
requests required to be implemented by a USB device.
The function inspects this USB_SetupPacket_t
structure and includes a minimum implementation
of the Standard Device requests. The rest of this section documents the requests handled and lists
the basic functionality associated with the request.
It is not intended that this replace a good knowledge of the requests required, since
USB_StandardRequests()
has no knowledge about the specific class that is implemented, and hence
does not guarantee a fully USB compliant device.
Each request could well be required to be over-ridden for a device implementation. For example,a USB Audio device could well require a specialised version of SET_INTERFACE since this could mean that audio streaming will commence imminently.
The USB_StandardRequests()
function takes as parameters arrays representing the device
descriptor, configuration descriptor, and a string table as well as a USB_SetupPacket_t
and
the current bus-speed.
Note
USB_StandardRequests()
takes two references for device and configuration descriptors - this
allows for different functionality based on bus-speed. USB_StandardRequests()
forms valid
Device Qualifier and Other Speed Configuration descriptors from these arrays.
USB_SetupPacket_t
#
This structure closely matches the structure defined in the USB 2.0 Specification:
typedef struct USB_SetupPacket
{
USB_BmRequestType_t bmRequestType; /* (1 byte) Specifies direction of dataflow,
type of rquest and recipient */
unsigned char bRequest; /* Specifies the request */
unsigned short wValue; /* Host can use this to pass info to the
device in its own way */
unsigned short wIndex; /* Typically used to pass index/offset such
as interface or EP no */
unsigned short wLength; /* Number of data bytes in the data stage
(for Host -> Device this this is exact
count, for Dev->Host is a max. */
} USB_SetupPacket_t;
USB_GetSetupPacket()
#
-
XUD_Result_t USB_GetSetupPacket(XUD_ep ep_out, XUD_ep ep_in, REFERENCE_PARAM(USB_SetupPacket_t, sp))#
Receives a Setup data packet and parses it into the passed USB_SetupPacket_t structure.
- Parameters:
ep_out – OUT endpint from XUD
ep_in – IN endpoint to XUD
sp – SetupPacket structure to be filled in (passed by ref)
- Returns:
Returns XUD_RES_OKAY on success, XUD_RES_RST on bus reset
USB_StandardRequests()
#
This function takes a populated USB_SetupPacket_t
structure as an argument.
-
XUD_Result_t USB_StandardRequests(XUD_ep ep_out, XUD_ep ep_in, NULLABLE_ARRAY_OF(unsigned char, devDesc_hs), int devDescLength_hs, NULLABLE_ARRAY_OF(unsigned char, cfgDesc_hs), int cfgDescLength_hs, NULLABLE_ARRAY_OF(unsigned char, devDesc_fs), int devDescLength_fs, NULLABLE_ARRAY_OF(unsigned char, cfgDesc_fs), int cfgDescLength_fs, char *strDescs[], int strDescsLength, REFERENCE_PARAM(USB_SetupPacket_t, sp), XUD_BusSpeed_t usbBusSpeed)#
This function deals with common requests This includes Standard Device Requests listed in table 9-3 of the USB 2.0 Spec all devices must respond to these requests, in some cases a bare minimum implementation is provided and should be extended in the devices EP0 code It handles the following standard requests appropriately using values passed to it:
Get Device Descriptor (using devDesc_hs/devDesc_fs arguments)
Get Configuration Descriptor (using cfgDesc_hs/cfgDesc_fs arguments)
String requests (using strDesc argument)
Get Device_Qualifier Descriptor
Get Other-Speed Configuration Descriptor
Set/Clear Feature (Endpoint Halt)
Get/Set Interface
Set Configuration
If the request is not recognised the endpoint is marked STALLED
- Parameters:
ep_out – Endpoint from XUD (ep 0)
ep_in – Endpoint from XUD (ep 0)
devDesc_hs – The Device descriptor to use, encoded according to the USB standard
devDescLength_hs – Length of device descriptor in bytes
cfgDesc_hs – Configuration descriptor
cfgDescLength_hs – Length of config descriptor in bytes
devDesc_fs – The Device descriptor to use, encoded according to the USB standard
devDescLength_fs – Length of device descriptor in bytes. If 0 the HS device descriptor is used.
cfgDesc_fs – Configuration descriptor
cfgDescLength_fs – Length of config descriptor in bytes. If 0 the HS config descriptor is used.
strDescs –
strDescsLength –
sp –
USB_SetupPacket_t
(passed by ref) in which the setup data is returnedusbBusSpeed – The current bus speed (XUD_SPEED_HS or XUD_SPEED_FS)
- Returns:
Returns XUD_RES_OKAY on success.
This section now details the actual requests handled by this function.
If parsing the request does not result in a match, the request is not handled, the Endpoint is
marked “Halted” (Using XUD_SetStall_Out()
and XUD_SetStall_In()
) and the function returns
XUD_RES_ERR
. The function returns XUD_RES_OKAY
if a request was handled without error
(See also Status reporting example).
USB_StandardRequests()
: Standard Device Requests#
The USB_StandardRequests()
function handles the following Standard Device Requests:
SET_ADDRESS
: The device address is set in XUD (usingXUD_SetDevAddr()
).
SET_CONFIGURATION
: A global variable is updated with the given configuration value.
GET_STATUS
: The status of the device is returned. This uses the device Configuration descriptor to return if the device is bus powered or not.
SET_CONFIGURATION
: A global variable is returned with the current configuration last set bySET_CONFIGURATION
.
GET_DESCRIPTOR
: Returns the relevant descriptors. Note, some changes of returned descriptor will occur based on the current bus speed the device is running.
DEVICE
CONFIGURATION
DEVICE_QUALIFIER
OTHER_SPEED_CONFIGURATION
STRING
In addition the following test mode requests are dealt with (with the correct test mode set in XUD):
SET_FEATURE
TEST_J
TEST_K
TEST_SE0_NAK
TEST_PACKET
FORCE_ENABLE
USB_StandardRequests()
: Standard Interface Requests#
The USB_StandardRequests()
function handles the following Standard Interface Requests:
SET_INTERFACE
: A global variable is maintained for each interface. This is updated by a SET_INTERFACE. Some basic range checking is included using the value numInterfaces from the Configuration Descriptor.
GET_INTERFACE
: Returns the value written bySET_INTERFACE
.
USB_StandardRequests()
: Standard Endpoint Requests#
The USB_StandardRequests()
function handles the following Standard Endpoint Requests:
SET_FEATURE
CLEAR_FEATURE
GET_STATUS
Control Endpoint Example#
The code listing below shows a simple example of a endpoint 0 implementation showing the use of
USB_SetupPacket_t
, USB_SetSetupPacket()
and USBStandardRequests()
:
void Endpoint0(chanend c_ep0_out, chanend c_ep0_in)
{
USB_SetupPacket_t sp;
XUD_BusSpeed_t usbBusSpeed;
XUD_ep ep0_out = XUD_InitEp(c_ep0_out);
XUD_ep ep0_in = XUD_InitEp(c_ep0_in);
while(1)
{
XUD_Result_t result = USB_GetSetupPacket(ep0_out, ep0_in, sp);
if(result == XUD_RES_OKAY)
{
result = USB_StandardRequests(ep0_out, ep0_in,
devDesc_HS, sizeof(devDesc_HS),
cfgDesc_HS, sizeof(cfgDesc_HS),
devDesc_FS, sizeof(devDesc_FS),
cfgDesc_FS, sizeof(cfgDesc_FS),
stringTable, sizeof(stringTable),
sp, usbBusSpeed);
}
/* USB bus reset detected, reset EP and get new bus speed */
if(result == XUD_RES_RST)
{
usbBusSpeed = XUD_ResetEndpoint(ep0_out, ep0_in);
}
}
}
Note
For conciseness the declarations of the arrays representing the device and configuration descriptors and the string table are not shown.