From d8ee2b087fe13fc0b11113a19cf35fbe31a89e21 Mon Sep 17 00:00:00 2001 From: Adrian Bradianu Date: Wed, 1 Jun 2016 14:22:40 +0300 Subject: [PATCH] usb: Add ReST documentation file Change-Id: I955bad3c560d8e0026d671dadf6004edb94559e4 Signed-off-by: Adrian Bradianu Signed-off-by: Jesus Sanchez-Palencia Signed-off-by: Jithu Joseph --- doc/subsystems/subsystems.rst | 1 + doc/subsystems/usb/usb.rst | 527 ++++++++++++++++++++++++++++++++++ 2 files changed, 528 insertions(+) create mode 100644 doc/subsystems/usb/usb.rst diff --git a/doc/subsystems/subsystems.rst b/doc/subsystems/subsystems.rst index e5fbec7e5fc..b2843beed10 100644 --- a/doc/subsystems/subsystems.rst +++ b/doc/subsystems/subsystems.rst @@ -11,5 +11,6 @@ to applications. networking/networking.rst bluetooth/bluetooth.rst + usb/usb.rst sensor power_management.rst diff --git a/doc/subsystems/usb/usb.rst b/doc/subsystems/usb/usb.rst new file mode 100644 index 00000000000..5d783887958 --- /dev/null +++ b/doc/subsystems/usb/usb.rst @@ -0,0 +1,527 @@ +USB device stack +################ + +The USB device stack is split into three layers: + * USB Device Controller drivers (hardware dependent) + * USB device core driver (hardware independent) + * USB device class drivers (hardware independent) + +USB device controller drivers +***************************** + +The Device Controller Driver Layer implements the low level control routines +to deal directly with the hardware. All device controller drivers should +implement the APIs described in file usb_dc.h. This allows the integration of +new USB device controllers to be done without changing the upper layers. +For now only Quark SE USB device controller (Designware IP) is supported. + +Structures +========== + +.. code-block:: c + + struct usb_dc_ep_cfg_data { + uint8_t ep_addr; + uint16_t ep_mps; + enum usb_dc_ep_type ep_type; + }; + +Structure containing the USB endpoint configuration. + * ep_addr: endpoint address, the number associated with the EP in the device + configuration structure. + IN EP = 0x80 | . OUT EP = 0x00 | + * ep_mps: Endpoint max packet size. + * ep_type: Endpoint type, may be Bulk, Interrupt or Control. Isochronous + endpoints are not supported for now. + +.. code-block:: c + + enum usb_dc_status_code { + USB_DC_ERROR, + USB_DC_RESET, + USB_DC_CONNECTED, + USB_DC_CONFIGURED, + USB_DC_DISCONNECTED, + USB_DC_SUSPEND, + USB_DC_RESUME, + USB_DC_UNKNOWN + }; + +Status codes reported by the registered device status callback. + * USB_DC_ERROR: USB error reported by the controller. + * USB_DC_RESET: USB reset. + * USB_DC_CONNECTED: USB connection established - hardware enumeration is completed. + * USB_DC_CONFIGURED: USB configuration done. + * USB_DC_DISCONNECTED: USB connection lost. + * USB_DC_SUSPEND: USB connection suspended by the HOST. + * USB_DC_RESUME: USB connection resumed by the HOST. + * USB_DC_UNKNOWN: Initial USB connection status. + +.. code-block:: c + + enum usb_dc_ep_cb_status_code { + USB_DC_EP_SETUP, + USB_DC_EP_DATA_OUT, + USB_DC_EP_DATA_IN, + }; + +Status Codes reported by the registered endpoint callback. + * USB_DC_EP_SETUP: SETUP packet received. + * USB_DC_EP_DATA_OUT: Out transaction on this endpoint. Data is available + for read. + * USB_DC_EP_DATA_IN: In transaction done on this endpoint. + +APIs +==== + +The following APIs are provided by the device controller driver: + +:c:func:`usb_dc_attach()` + This function attaches USB for device connection. Upon success, the USB PLL + is enabled, and the USB device is now capable of transmitting and receiving + on the USB bus and of generating interrupts. + +:c:func:`usb_dc_detach()` + This function detaches the USB device. Upon success the USB hardware PLL is + powered down and USB communication is disabled. + +:c:func:`usb_dc_reset()` + This function returns the USB device to it's initial state. + +:c:func:`usb_dc_set_address()` + This function sets USB device address. + +:c:func:`usb_dc_set_status_callback()` + This function sets USB device controller status callback. The registered + callback is used to report changes in the status of the device controller. + The status code are described by the usb_dc_status_code enumeration. + +:c:func:`usb_dc_ep_configure()` + This function configures an endpoint. usb_dc_ep_cfg_data structure provides + the endpoint configuration parameters: endpoint address, endpoint maximum + packet size and endpoint type. + +:c:func:`usb_dc_ep_set_stall()` + This function sets stall condition for the selected endpoint. + +:c:func:`usb_dc_ep_clear_stall()` + This functions clears stall condition for the selected endpoint + +:c:func:`usb_dc_ep_is_stalled()` + This function check if selected endpoint is stalled. + +:c:func:`usb_dc_ep_halt()` + This function halts the selected endpoint + +:c:func:`usb_dc_ep_enable()` + This function enables the selected endpoint. Upon success interrupts are + enabled for the corresponding endpoint and the endpoint is ready for + transmitting/receiving data. + +:c:func:`usb_dc_ep_disable()` + This function disables the selected endpoint. Upon success interrupts are + disabled for the corresponding endpoint and the endpoint is no longer able + for transmitting/receiving data. + +:c:func:`usb_dc_ep_flush()` + This function flushes the FIFOs for the selected endpoint. + +:c:func:`usb_dc_ep_write()` + This function writes data to the specified endpoint. The supplied + usb_ep_callback function will be called when data is transmitted out. + +:c:func:`usb_dc_ep_read()` + This function is called by the Endpoint handler function, after an OUT + interrupt has been received for that EP. The application must only call this + function through the supplied usb_ep_callback function. + +:c:func:`usb_dc_ep_set_callback()` + This function sets callback function for notification of data received + and available to application or transmit done on the selected endpoint. + The callback status code is described by usb_dc_ep_cb_status_code. + +USB device core layer +********************* + +The USB Device core layer is a hardware independent interface between USB +device controller driver and USB device class drivers or customer applications. +It's a port of the LPCUSB device stack. It provides the following +functionalities: + + * Responds to standard device requests and returns standard descriptors, + essentially handling 'Chapter 9' processing, specifically the standard + device requests in table 9-3 from the universal serial bus specification + revision 2.0. + * Provides a programming interface to be used by USB device classes or + customer applications. The APIs are described in the usb_device.h file. + * Uses the APIs provided by the device controller drivers to interact with + the USB device controller. + +Structures +========== + +.. code-block:: c + + typedef void (*usb_status_callback)(enum usb_dc_status_code status_code); + +Callback function signature for the device status. + +.. code-block:: c + + typedef void (*usb_ep_callback)(uint8_t ep, + enum usb_dc_ep_cb_status_code cb_status); + +Callback function signature for the USB Endpoint. + +.. code-block:: c + + typedef int (*usb_request_handler) (struct usb_setup_packet *setup, + int *transfer_len, uint8_t **payload_data); + +Callback function signature for class specific requests. For host to device +direction the 'len' and 'payload_data' contain the length of the received data +and the pointer to the received data respectively. For device to host class +requests, 'len' and 'payload_data' should be set by the callback function +with the length and the address of the data to be transmitted buffer +respectively. + +.. code-block:: c + + struct usb_ep_cfg_data { + usb_ep_callback ep_cb; + uint8_t ep_addr; + }; + +This structure contains configuration for a certain endpoint. + * ep_cb: callback function for notification of data received and available + to application or transmit done, NULL if callback not required by + application code. + * ep_addr: endpoint address. The number associated with the EP in the device + configuration structure. + +.. code-block:: c + + struct usb_interface_cfg_data { + usb_request_handler class_handler; + usb_request_handler custom_handler; + uint8_t *payload_data; + }; + +This structure contains USB interface configuration. + * class_handler: handler for USB Class specific Control (EP 0) + communications. + * custom_handler: the custom request handler gets a first + chance at handling the request before it is handed over to the + 'chapter 9' request handler. + * payload_data: this data area, allocated by the application, is used to + store class specific command data and must be large enough to store the + largest payload associated with the largest supported Class' command set. + +.. code-block:: c + + struct usb_cfg_data { + const uint8_t *usb_device_description; + usb_status_callback cb_usb_status; + struct usb_interface_cfg_data interface; + uint8_t num_endpoints; + struct usb_ep_cfg_data *endpoint; + }; + +This structure contains USB device configuration. + * usb_device_description: USB device description, see + http://www.beyondlogic.org/usbnutshell/usb5.shtml#DeviceDescriptors + * cb_usb_status: callback to be notified on USB connection status change + * interface: USB class handlers and storage space. + * num_endpoints: number of individual endpoints in the device configuration + * endpoint: pointer to an array of endpoint configuration structures + (usb_cfg_data) of length equal to the number of EP associated with the + device description, not including control endpoints. + +The class drivers instantiates this with given parameters using the +"usb_set_config" function. + +APIs +==== + +:c:func:`usb_set_config()` + This function configures USB device. + +:c:func:`usb_deconfig()` + This function returns the USB device back to it's initial state + +:c:func:`usb_enable()` + This function enable USB for host/device connection. Upon success, the USB + module is no longer clock gated in hardware, it is now capable of + transmitting and receiving on the USB bus and of generating interrupts. + +:c:func:`usb_disable()` + This function disables the USB device. Upon success, the USB module clock + is gated in hardware and it is no longer capable of generating interrupts. + +:c:func:`usb_write()` + write data to the specified endpoint. The supplied usb_ep_callback will be + called when transmission is done. + +:c:func:`usb_read()` + This function is called by the endpoint handler function after an OUT + interrupt has been received for that EP. The application must only call + this function through the supplied usb_ep_callback function. + + +USB device class drivers +************************ + +To initialize the device class driver instance the USB device class driver +should call usb_set_config() passing as parameter the instance's configuration +structure. + +For example, for CDC_ACM sample application: + +.. code-block:: c + + static const uint8_t cdc_acm_usb_description[] = { + /* Device descriptor */ + USB_DEVICE_DESC_SIZE, /* Descriptor size */ + USB_DEVICE_DESC, /* Descriptor type */ + LOW_BYTE(USB_1_1), + HIGH_BYTE(USB_1_1), /* USB version in BCD format */ + COMMUNICATION_DEVICE_CLASS, /* Class */ + 0x00, /* SubClass - Interface specific */ + 0x00, /* Protocol - Interface specific */ + MAX_PACKET_SIZE_EP0, /* Max Packet Size */ + LOW_BYTE(VENDOR_ID), + HIGH_BYTE(VENDOR_ID), /* Vendor Id */ + LOW_BYTE(CDC_PRODUCT_ID), + HIGH_BYTE(CDC_PRODUCT_ID), /* Product Id */ + LOW_BYTE(BCDDEVICE_RELNUM), + HIGH_BYTE(BCDDEVICE_RELNUM), /* Device Release Number */ + 0x01, /* Index of Manufacturer String Descriptor */ + 0x02, /* Index of Product String Descriptor */ + 0x03, /* Index of Serial Number String Descriptor */ + CDC_NUM_CONF, /* Number of Possible Configuration */ + + /* Configuration descriptor */ + USB_CONFIGURATION_DESC_SIZE, /* Descriptor size */ + USB_CONFIGURATION_DESC, /* Descriptor type */ + LOW_BYTE(CDC_CONF_SIZE), + HIGH_BYTE(CDC_CONF_SIZE), /* Total length in bytes of data returned */ + CDC_NUM_ITF, /* Number of interfaces */ + 0x01, /* Configuration value */ + 0x00, /* Index of the Configuration string */ + USB_CONFIGURATION_ATTRIBUTES, /* Attributes */ + MAX_LOW_POWER, /* Max power consumption */ + + /* Interface descriptor */ + USB_INTERFACE_DESC_SIZE, /* Descriptor size */ + USB_INTERFACE_DESC, /* Descriptor type */ + 0x00, /* Interface index */ + 0x00, /* Alternate setting */ + CDC1_NUM_EP, /* Number of Endpoints */ + COMMUNICATION_DEVICE_CLASS, /* Class */ + ACM_SUBCLASS, /* SubClass */ + V25TER_PROTOCOL, /* Protocol */ + 0x00, /* Index of the Interface String Descriptor */ + + /* Header Functional Descriptor */ + USB_HFUNC_DESC_SIZE, /* Descriptor size */ + CS_INTERFACE, /* Descriptor type */ + USB_HFUNC_SUBDESC, /* Descriptor SubType */ + LOW_BYTE(USB_1_1), + HIGH_BYTE(USB_1_1), /* CDC Device Release Number */ + + /* Call Management Functional Descriptor */ + USB_CMFUNC_DESC_SIZE, /* Descriptor size */ + CS_INTERFACE, /* Descriptor type */ + USB_CMFUNC_SUBDESC, /* Descriptor SubType */ + 0x00, /* Capabilities */ + 0x01, /* Data Interface */ + + /* ACM Functional Descriptor */ + USB_ACMFUNC_DESC_SIZE, /* Descriptor size */ + CS_INTERFACE, /* Descriptor type */ + USB_ACMFUNC_SUBDESC, /* Descriptor SubType */ + /* Capabilities - Device supports the request combination of: + * Set_Line_Coding, + * Set_Control_Line_State, + * Get_Line_Coding + * and the notification Serial_State + */ + 0x02, + + /* Union Functional Descriptor */ + USB_UFUNC_DESC_SIZE, /* Descriptor size */ + CS_INTERFACE, /* Descriptor type */ + USB_UFUNC_SUBDESC, /* Descriptor SubType */ + 0x00, /* Master Interface */ + 0x01, /* Slave Interface */ + + /* Endpoint INT */ + USB_ENDPOINT_DESC_SIZE, /* Descriptor size */ + USB_ENDPOINT_DESC, /* Descriptor type */ + CDC_ENDP_INT, /* Endpoint address */ + USB_DC_EP_INTERRUPT, /* Attributes */ + LOW_BYTE(CDC_INTERRUPT_EP_MPS), + HIGH_BYTE(CDC_INTERRUPT_EP_MPS),/* Max packet size */ + 0x0A, /* Interval */ + + /* Interface descriptor */ + USB_INTERFACE_DESC_SIZE, /* Descriptor size */ + USB_INTERFACE_DESC, /* Descriptor type */ + 0x01, /* Interface index */ + 0x00, /* Alternate setting */ + CDC2_NUM_EP, /* Number of Endpoints */ + COMMUNICATION_DEVICE_CLASS_DATA,/* Class */ + 0x00, /* SubClass */ + 0x00, /* Protocol */ + 0x00, /* Index of the Interface String Descriptor */ + + /* First Endpoint IN */ + USB_ENDPOINT_DESC_SIZE, /* Descriptor size */ + USB_ENDPOINT_DESC, /* Descriptor type */ + CDC_ENDP_IN, /* Endpoint address */ + USB_DC_EP_BULK, /* Attributes */ + LOW_BYTE(CDC_BULK_EP_MPS), + HIGH_BYTE(CDC_BULK_EP_MPS), /* Max packet size */ + 0x00, /* Interval */ + + /* Second Endpoint OUT */ + USB_ENDPOINT_DESC_SIZE, /* Descriptor size */ + USB_ENDPOINT_DESC, /* Descriptor type */ + CDC_ENDP_OUT, /* Endpoint address */ + USB_DC_EP_BULK, /* Attributes */ + LOW_BYTE(CDC_BULK_EP_MPS), + HIGH_BYTE(CDC_BULK_EP_MPS), /* Max packet size */ + 0x00, /* Interval */ + + /* String descriptor language, only one, so min size 4 bytes. + * 0x0409 English(US) language code used + */ + USB_STRING_DESC_SIZE, /* Descriptor size */ + USB_STRING_DESC, /* Descriptor type */ + 0x09, + 0x04, + /* Manufacturer String Descriptor "Intel" */ + 0x0C, + USB_STRING_DESC, + 'I', 0, 'n', 0, 't', 0, 'e', 0, 'l', 0, + /* Product String Descriptor "CDC-ACM" */ + 0x10, + USB_STRING_DESC, + 'C', 0, 'D', 0, 'C', 0, '-', 0, 'A', 0, 'C', 0, 'M', 0, + /* Serial Number String Descriptor "00.01" */ + 0x0C, + USB_STRING_DESC, + '0', 0, '0', 0, '.', 0, '0', 0, '1', 0, + }; + +.. code-block:: c + + static struct usb_ep_cfg_data cdc_acm_ep_data[] = { + { + .ep_cb = cdc_acm_int_in, + .ep_addr = CDC_ENDP_INT + }, + { + .ep_cb = cdc_acm_bulk_out, + .ep_addr = CDC_ENDP_OUT + }, + { + .ep_cb = cdc_acm_bulk_in, + .ep_addr = CDC_ENDP_IN + } + }; + +.. code-block:: c + + static struct usb_cfg_data cdc_acm_config = { + .usb_device_description = cdc_acm_usb_description, + .cb_usb_status = cdc_acm_dev_status_cb, + .interface = { + .class_handler = cdc_acm_class_handle_req, + .custom_handler = NULL, + .payload_data = NULL, + }, + .num_endpoints = CDC1_NUM_EP + CDC2_NUM_EP, + .endpoint = cdc_acm_ep_data + }; + +.. code-block:: c + + ret = usb_set_config(&cdc_acm_config); + if (ret < 0) { + DBG("Failed to config USB\n"); + return ret; + } + +To enable the USB device for host/device connection: + +.. code-block:: c + + ret = usb_enable(&cdc_acm_config); + if (ret < 0) { + DBG("Failed to enable USB\n"); + return ret; + } + +The class device requests are forwarded by the USB stack core driver to the +class driver through the registered class handler. +For the CDC ACM sample class driver, 'cdc_acm_class_handle_req' processes +the SET_LINE_CODING, CDC_SET_CONTROL_LINE_STATE and CDC_GET_LINE_CODING +class requests: + +.. code-block:: c + + int cdc_acm_class_handle_req(struct usb_setup_packet *pSetup, + int32_t *len, uint8_t **data) + { + struct cdc_acm_dev_data_t * const dev_data = DEV_DATA(cdc_acm_dev); + + switch (pSetup->bRequest) { + case CDC_SET_LINE_CODING: + memcpy(&dev_data->line_coding, *data, sizeof(dev_data->line_coding)); + DBG("\nCDC_SET_LINE_CODING %d %d %d %d\n", + sys_le32_to_cpu(dev_data->line_coding.dwDTERate), + dev_data->line_coding.bCharFormat, + dev_data->line_coding.bParityType, + dev_data->line_coding.bDataBits); + break; + + case CDC_SET_CONTROL_LINE_STATE: + dev_data->line_state = (uint8_t)sys_le16_to_cpu(pSetup->wValue); + DBG("CDC_SET_CONTROL_LINE_STATE 0x%x\n", dev_data->line_state); + break; + + case CDC_GET_LINE_CODING: + *data = (uint8_t *)(&dev_data->line_coding); + *len = sizeof(dev_data->line_coding); + DBG("\nCDC_GET_LINE_CODING %d %d %d %d\n", + sys_le32_to_cpu(dev_data->line_coding.dwDTERate), + dev_data->line_coding.bCharFormat, + dev_data->line_coding.bParityType, + dev_data->line_coding.bDataBits); + break; + + default: + DBG("CDC ACM request 0x%x, value 0x%x\n", + pSetup->bRequest, pSetup->wValue); + return -EINVAL; + } + + return 0; + } + +The class driver should wait for the USB_DC_CONFIGURED device status code +before transmitting any data. + +To transmit data to the host, the class driver should call usb_write(). +Upon completion the registered endpoint callback will be called. Before +sending another packet the class driver should wait for the completion of +the previous transfer. + +When data is received, the registered endpoint callback is called. +usb_read() should be used for retrieving the received data. It must +always be called through the registered endpoint callback. For CDC ACM +sample driver this happens via the OUT bulk endpoint handler (cdc_acm_bulk_out) +mentioned in the endpoint array (cdc_acm_ep_data). + +Only CDC ACM and DFU class driver examples are provided for now.