Hide navigation sidebar
Hide table of contents sidebar
Skip to content
Back to top
Toggle table of contents sidebar

# 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 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.