1 /*
2  * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /*
8 Warning: The USB Host Library API is still a beta version and may be subject to change
9 */
10 
11 #pragma once
12 
13 #include "usb/usb_types_ch9.h"
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 // ------------------------------------------------ Protocol Standard --------------------------------------------------
20 
21 /**
22  * @brief USB Standard Speeds
23  */
24 typedef enum {
25     USB_SPEED_LOW = 0,                  /**< USB Low Speed (1.5 Mbit/s) */
26     USB_SPEED_FULL,                     /**< USB Full Speed (12 Mbit/s) */
27 } usb_speed_t;
28 
29 /**
30  * @brief The type of USB transfer
31  *
32  * @note The enum values need to match the bmAttributes field of an EP descriptor
33  */
34 typedef enum {
35     USB_TRANSFER_TYPE_CTRL = 0,
36     USB_TRANSFER_TYPE_ISOCHRONOUS,
37     USB_TRANSFER_TYPE_BULK,
38     USB_TRANSFER_TYPE_INTR,
39 } usb_transfer_type_t;
40 
41 // ------------------------------------------------- Device Related ----------------------------------------------------
42 
43 /**
44  * @brief Handle of a USB Device connected to a USB Host
45  */
46 typedef struct usb_device_handle_s * usb_device_handle_t;
47 
48 /**
49  * @brief Basic information of an enumerated device
50  */
51 typedef struct {
52     usb_speed_t speed;                              /**< Device's speed */
53     uint8_t dev_addr;                               /**< Device's address */
54     uint8_t bMaxPacketSize0;                        /**< The maximum packet size of the device's default endpoint */
55     uint8_t bConfigurationValue;                    /**< Device's current configuration number */
56     const usb_str_desc_t *str_desc_manufacturer;    /**< Pointer to Manufacturer string descriptor (can be NULL) */
57     const usb_str_desc_t *str_desc_product;         /**< Pointer to Product string descriptor (can be NULL) */
58     const usb_str_desc_t *str_desc_serial_num;      /**< Pointer to Serial Number string descriptor (can be NULL) */
59 } usb_device_info_t;
60 
61 // ------------------------------------------------ Transfer Related ---------------------------------------------------
62 
63 /**
64  * @brief The status of a particular transfer
65  */
66 typedef enum {
67     USB_TRANSFER_STATUS_COMPLETED,      /**< The transfer was successful (but may be short) */
68     USB_TRANSFER_STATUS_ERROR,          /**< The transfer failed because due to excessive errors (e.g. no response or CRC error) */
69     USB_TRANSFER_STATUS_TIMED_OUT,      /**< The transfer failed due to a time out */
70     USB_TRANSFER_STATUS_CANCELED,       /**< The transfer was canceled */
71     USB_TRANSFER_STATUS_STALL,          /**< The transfer was stalled */
72     USB_TRANSFER_STATUS_OVERFLOW,       /**< The transfer as more data was sent than was requested */
73     USB_TRANSFER_STATUS_SKIPPED,        /**< ISOC packets only. The packet was skipped due to system latency or bus overload */
74     USB_TRANSFER_STATUS_NO_DEVICE,      /**< The transfer failed because the target device is gone */
75 } usb_transfer_status_t;
76 
77 /**
78  * @brief Isochronous packet descriptor
79  *
80  * If the number of bytes in an Isochronous transfer is larger than the MPS of the endpoint, the transfer is split
81  * into multiple packets transmitted at the endpoint's specified interval. An array of Isochronous packet descriptors
82  * describes how an Isochronous transfer should be split into multiple packets.
83  */
84 typedef struct {
85     int num_bytes;                                  /**< Number of bytes to transmit/receive in the packet. IN packets should be integer multiple of MPS */
86     int actual_num_bytes;                           /**< Actual number of bytes transmitted/received in the packet */
87     usb_transfer_status_t status;                   /**< Status of the packet */
88 } usb_isoc_packet_desc_t;
89 
90 /**
91  * @brief USB transfer structure
92  *
93  * This structure is used to represent a transfer from a software client to an endpoint over the USB bus. Some of the
94  * fields are made const on purpose as they are fixed on allocation. Users should call the appropriate USB Host Library
95  * function to allocate a USB transfer structure instead of allocating this structure themselves.
96  *
97  * The transfer type is inferred from the endpoint this transfer is sent to. Depending on the transfer type, users
98  * should note the following:
99  *
100  * - Bulk: This structure represents a single bulk transfer. If the number of bytes exceeds the endpoint's MPS, the
101  *         transfer will be split into multiple MPS sized packets followed by a short packet.
102  * - Control: This structure represents a single control transfer. This first 8 bytes of the data_buffer must be filled
103  *            with the setup packet (see usb_setup_packet_t). The num_bytes field should be the total size of the
104  *            transfer (i.e., size of setup packet + wLength).
105  * - Interrupt: Represents an interrupt transfer. If num_bytes exceeds the MPS of the endpoint, the transfer will be
106  *              split into multiple packets, and each packet is transferred at the endpoint's specified interval.
107  * - Isochronous: Represents a stream of bytes that should be transferred to an endpoint at a fixed rate. The transfer
108  *                is split into packets according to the each isoc_packet_desc. A packet is transferred at each interval
109  *                of the endpoint. If an entire ISOC URB was transferred without error (skipped packets do not count as
110  *                errors), the URB's overall status and the status of each packet descriptor will be updated, and the
111  *                actual_num_bytes reflects the total bytes transferred over all packets. If the ISOC URB encounters an
112  *                error, the entire URB is considered erroneous so only the overall status will updated.
113  *
114  * @note For Bulk/Control/Interrupt IN transfers, the num_bytes must be a integer multiple of the endpoint's MPS
115  * @note This structure should be allocated via usb_host_transfer_alloc()
116  * @note Once the transfer has be submitted, users should not modify the structure until the transfer has completed
117  */
118 typedef struct usb_transfer_s usb_transfer_t;
119 
120 /**
121  * @brief USB transfer completion callback
122  */
123 typedef void (*usb_transfer_cb_t)(usb_transfer_t *transfer);
124 
125 struct usb_transfer_s{
126     uint8_t *const data_buffer;                     /**< Pointer to data buffer */
127     const size_t data_buffer_size;                  /**< Size of the data buffer in bytes */
128     int num_bytes;                                  /**< Number of bytes to transfer.
129                                                          Control transfers should include the size of the setup packet.
130                                                          Isochronous transfer should be the total transfer size of all packets.
131                                                          For non-control IN transfers, num_bytes should be an integer multiple of MPS. */
132     int actual_num_bytes;                           /**< Actual number of bytes transferred */
133     uint32_t flags;                                 /**< Transfer flags */
134     usb_device_handle_t device_handle;              /**< Device handle */
135     uint8_t bEndpointAddress;                       /**< Endpoint Address */
136     usb_transfer_status_t status;                   /**< Status of the transfer */
137     uint32_t timeout_ms;                            /**< Timeout (in milliseconds) of the packet (currently not supported yet) */
138     usb_transfer_cb_t callback;                     /**< Transfer callback */
139     void *context;                                  /**< Context variable for transfer to associate transfer with something */
140     const int num_isoc_packets;                     /**< Only relevant to Isochronous. Number of service periods (i.e., intervals) to transfer data buffer over. */
141     usb_isoc_packet_desc_t isoc_packet_desc[];      /**< Descriptors for each Isochronous packet */
142 };
143 
144 /**
145  * @brief Terminate Bulk/Interrupt OUT transfer with a zero length packet
146  *
147  * OUT transfers normally terminate when the Host has transferred the exact amount of data it needs to the device.
148  * However, for bulk and interrupt OUT transfers, if the transfer size just happened to be a multiple of MPS, it will be
149  * impossible to know the boundary between two consecutive transfers to the same endpoint.
150  *
151  * Therefore, this flag will cause the transfer to automatically add a zero length packet (ZLP) at the end of the
152  * transfer if the following conditions are met:
153  * - The target endpoint is a Bulk/Interrupt OUT endpoint (Host to device)
154  * - The transfer's length (i.e., transfer.num_bytes) is a multiple of the endpoint's MPS
155  *
156  * Otherwise, this flag has no effect.
157  *
158  * Users should check whether their target device's class requires a ZLP, as not all Bulk/Interrupt OUT endpoints
159  * require them. For example:
160  * - For MSC Bulk Only Transport class, the Host MUST NEVER send a ZLP. Bulk transfer boundaries are determined by the CBW and CSW instead
161  * - For CDC Ethernet, the Host MUST ALWAYS send a ZLP if a segment (i.e., a transfer) is a multiple of MPS (See 3.3.1 Segment Delineation)
162  *
163  * @note See USB2.0 specification 5.7.3 and 5.8.3 for more details
164  * @note IN transfers normally terminate when the Host as receive the exact amount of data it needs (must be multiple of MPS)
165  *       or the endpoint sends a short packet to the Host
166  */
167 #define USB_TRANSFER_FLAG_ZERO_PACK  0x01           /**< (For bulk OUT only). Indicates that a bulk OUT transfers should always terminate with a short packet, even if it means adding an extra zero length packet */
168 
169 #ifdef __cplusplus
170 }
171 #endif
172