2.7.2.3.3 Endpoint Management

Unlike standard USB function drivers, such as CDC, MSD, Audio, and HID, the Device Layer does not automatically manage endpoints for a Generic USB Device interface. This means that the application must maintain all endpoint that belong to a Generic USB Device Interface. Maintaining the endpoint involves the following:

  • Enabling the endpoints for the desired transfer type when the host sets the configuration.
  • Disabling the endpoint when the device receives a USB reset or when the Host changes the configuration.
  • Enabling and clearing endpoint stall conditions.
Warning: The application should never access Endpoint 0 directly. Doing so may cause the Device Stack to malfunction, which could cause the USB device to be non-compliant.

Endpoints can be enabled or disabled with the USB_DEVICE_EndpointEnable and USB_DEVICE_EndpointDisable functions. The USB_DEVICE_EndpointIsEnabled function can be used to check if an endpoint is enabled. The application should enable the endpoint when host sets the configuration which contains interfaces that use the endpoint. The endpoints should otherwise be disabled. The endpoint function should not be called in the Device Layer event handler. Instead, they should be called in the application task routine. The following code shows an example of how an endpoint is enabled.

/* The following code shows an example of how the endpoint enable functions
 * are called to enabled a Receive and Transmit Bulk endpoints. Note that the size
 * of the endpoint must be specified and this size should match the endpoint size
 * mentioned in the endpoint descriptor */
if (USB_DEVICE_EndpointIsEnabled(appData.usbDevHandle, appData.endpointRx) == false )
{
    /* Enable Read Endpoint */
    USB_DEVICE_EndpointEnable(appData.usbDevHandle, 0, appData.endpointRx,
                            USB_TRANSFER_TYPE_BULK, sizeof(receivedDataBuffer));
}
if (USB_DEVICE_EndpointIsEnabled(appData.usbDevHandle, appData.endpointTx) == false )
{
    /* Enable Write Endpoint */
    USB_DEVICE_EndpointEnable(appData.usbDevHandle, 0, appData.endpointTx,
                           USB_TRANSFER_TYPE_BULK, sizeof(transmitDataBuffer));
}

An endpoint should be disabled when the host has changed the device configuration and the new configuration does not contain any interfaces that use this endpoint. The endpoint can also be disabled when the application receives USB_DEVICE_EVENT_RESET or when the USB_DEVICE_EVENT_DECONFIGURED event has occurred. The following code shows an example of disabling the endpoint.

/* In this example, the endpoints are disabled when
 * when the device has is not configured. This can happen
 * if the configuration set is 0 or if the device is reset. */
if(!appData.deviceIsConfigured)
{
    /* This means the device got deconfigured. Change the
     * application state back to waiting for configuration. */
    appData.state = APP_STATE_WAIT_FOR_CONFIGURATION;

    /* Disable the endpoint*/
    USB_DEVICE_EndpointDisable(appData.usbDevHandle, appData.endpointRx);
    USB_DEVICE_EndpointDisable(appData.usbDevHandle, appData.endpointTx);
    appData.epDataReadPending = false;
    appData.epDataWritePending = false;
}

The application can use the USB_DEVICE_EndpointStall and USB_DEVICE_EndpointStallClear functions to enable stall and clear the stall on endpoints. The USB_DEVICE_EndpointIsStalled function can be called to check stall status of the endpoint.