.. _sec_programming:

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.