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

# Programming guide

This section provides information on how to create an basic application using `lib_xud`.

## Includes

The application needs to include the header file xud.h.

## Declarations

Arrays representinge end endpoint types for both IN and OUT endpoints should be declared. These must each include one for endpoint 0, for example:

    /* Endpoint type tables */
    XUD_EpType epTypeTableOut[] = {XUD_EPTYPE_CTL | XUD_STATUS_ENABLE};
    XUD_EpType epTypeTableIn[] = {XUD_EPTYPE_CTL | XUD_STATUS_ENABLE , XUD_EPTYPE_BUL};

The endpoint types are:

- `XUD_EPTYPE_ISO`: Isochronous endpoint

- `XUD_EPTYPE_INT`: Interrupt endpoint

- `XUD_EPTYPE_BUL`: Bulk endpoint

- `XUD_EPTYPE_CTL`: Control endpoint

- `XUD_EPTYPE_DIS`: Disabled endpoint

`XUD_STATUS_ENABLE` is ORed in to the endpoints that wish to be informed of USB bus resets (see Status reporting example).

## `main()`

Within the `main()` function it is necessary to allocate the channels to connect the endpoints and then create the top-level par containing calls to `XUD_Main()`, an endpoint 0 task and any application specific endpoint tasks, for example:

    int main ()
    {
        chan c_ep_out[XUD_EP_COUNT_OUT], c_ep_in[XUD_EP_COUNT_IN];
        par
        {
            XUD_Main(c_ep_out , XUD_EP_COUNT_OUT ,
                     c_ep_in , XUD_EP_COUNT_IN ,
                     null , epTypeTableOut , epTypeTableIn ,
                     null , null , null , XUD_SPEED_HS , null);

            Endpoint0(c_ep_out[0], c_ep_in[0]);

            // Application specific endpoints
            ...
        }
    }
    return 0;

`XUD_Main()` connects to one end of every channel while the other end is passed to an endpoint (either endpoint 0 or an application specific endpoint). Application specific endpoints are connected using channel ends so the IN and OUT channel arrays need to be extended for each endpoint.

## Endpoint addresses

Endpoint 0 uses index 0 of both the endpoint type table and the channel array. The address of other endpoints must also correspond to their index in the endpoint table and the channel array.

## Sending and receiving data

An application specific endpoint can send data using `XUD_SetBuffer()` and receive data using `XUD_GetBuffer()` etc as described in Basic usage.

## Endpoint 0 implementation

It is necessary to create an implementation for endpoint 0 which takes two channels, one for IN and one for OUT. It can take an optional channel for test (see USB test modes):

A typical prototype might for such a funciton might look like the following:

    void Endpoint0(chanend chan_ep0_out , chanend chan_ep0_in , chanend ?c_usb_test)

Every endpoint must be initialized using the `XUD_InitEp()` function. For endpoint 0 this should like the following:

    XUD_ep ep0_out = XUD_InitEp(chan_ep0_out);
    XUD_ep ep0_in = XUD_InitEp(chan_ep0_in);

Typically the minimal code for endpoint 0 loops making call to `USB_GetSetupPacket()`, parses the `USB_SetupPacket_t` for any class/applicaton specific requests. Then makes a call to `USB_StandardRequests()`. And finally, calls `XUD_ResetEndpoint()` if there have been a bus-reset. For example:

    while (1)
    {
        /* Returns XUD_RES_OKAY on success, XUD_RES_RST for USB reset */
        XUD_Result_t result = USB_GetSetupPacket(ep0_out , ep0_in , sp);

        if(result == XUD_RES_OKAY)
        {
            switch(sp.bmRequestType.Type)
            {
                case BM_REQTYPE_TYPE_CLASS:
                    switch(sp.bmRequestType.Receipient)
                    {
                        case BM_REQTYPE_RECIP_INTER:
                            // Optional class specific requests
                            break;

                        ...
                    }

                    break;
                ...
            }

            result = USB_StandardRequests(ep0_out , devDesc , devDescLen , ...);
        }

        if(result == XUD_RES_RST)
            usbBusSpeed = XUD_ResetEndpoint(ep0_out , ep0_in);
    }

The code above could also over-ride any of the requests handled in `USB_StandardRequests()` for custom functionality.

Note

Class specific code should be inserted before USB_StandardRequests() is called since if USB_StandardRequests() cannot handle a request it marks the Endpoint stalled to indicate to the host that the request is not supported by the device.

`USB_StandardRequests()` takes char array parameters for device descriptors for both high and full-speed. Note, if null is passed as the full-speed descriptor the high-speed descriptor is used in full-speed mode and vice versa.

Note

On bus reset the `XUD_ResetEndpoint()` function returns the negotiated USB speed (i.e. full or high speed).

## Device descriptors

Every USB device must provide a set of descriptors. They are used to identify the USB device’s vendor ID, product ID and detail all the attributes of the advice as specified in the USB 2.0 specifications.

It is beyond the scope of this document to give details of writing a descriptor, please see the relevant USB Specification Documents.