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

  • spUSB_SetupPacket_t (passed by ref) in which the setup data is returned

  • usbBusSpeed – 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 (using XUD_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 by SET_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 by SET_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.