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 <stdint.h>
14 #include "esp_err.h"
15 #include "usb/usb_types_stack.h"
16 #include "usb/usb_types_ch9.h"
17 
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 // ---------------------------------------- Configuration Descriptor Parsing -------------------------------------------
23 
24 /**
25  * @brief Get the next descriptor
26  *
27  * Given a particular descriptor within a full configuration descriptor, get the next descriptor within the
28  * configuration descriptor. This is a convenience function that can be used to walk each individual descriptor within
29  * a full configuration descriptor.
30  *
31  * @param[in] cur_desc Current descriptor
32  * @param[in] wTotalLength Total length of the configuration descriptor
33  * @param[inout] offset Byte offset relative to the start of the configuration descriptor. On input, it is the offset of
34  *                      the current descriptor. On output, it is the offset of the returned descriptor.
35  * @return usb_standard_desc_t* Next descriptor, NULL if end of configuration descriptor reached
36  */
37 const usb_standard_desc_t *usb_parse_next_descriptor(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, int *offset);
38 
39 /**
40  * @brief Get the next descriptor of a particular type
41  *
42  * Given a particular descriptor within a full configuration descriptor, get the next descriptor of a particular type
43  * (i.e., using the bDescriptorType value) within the configuration descriptor.
44  *
45  * @param[in] cur_desc Current descriptor
46  * @param[in] wTotalLength Total length of the configuration descriptor
47  * @param[in] bDescriptorType Type of the next descriptor to get
48  * @param[inout] offset Byte offset relative to the start of the configuration descriptor. On input, it is the offset of
49  *                      the current descriptor. On output, it is the offset of the returned descriptor.
50  * @return usb_standard_desc_t* Next descriptor, NULL if end descriptor is not found or configuration descriptor reached
51  */
52 const usb_standard_desc_t *usb_parse_next_descriptor_of_type(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, uint8_t bDescriptorType, int *offset);
53 
54 /**
55  * @brief Get the number of alternate settings for a bInterfaceNumber
56  *
57  * Given a particular configuration descriptor, for a particular bInterfaceNumber, get the number of alternate settings
58  * available for that interface (i.e., the max possible value of bAlternateSetting for that bInterfaceNumber).
59  *
60  * @param[in] config_desc Pointer to the start of a full configuration descriptor
61  * @param[in] bInterfaceNumber Interface number
62  * @return int The number of alternate settings that the interface has, -1 if bInterfaceNumber not found
63  */
64 int usb_parse_interface_number_of_alternate(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber);
65 
66 /**
67  * @brief Get a particular interface descriptor (using bInterfaceNumber and bAlternateSetting)
68  *
69  * Given a full configuration descriptor, get a particular interface descriptor.
70  *
71  * @note To get the number of alternate settings for a particular bInterfaceNumber, call
72  *       usb_parse_interface_number_of_alternate()
73  *
74  * @param[in] config_desc Pointer to the start of a full configuration descriptor
75  * @param[in] bInterfaceNumber Interface number
76  * @param[in] bAlternateSetting Alternate setting number
77  * @param[out] offset Byte offset of the interface descriptor relative to the start of the configuration descriptor. Can be NULL.
78  * @return const usb_intf_desc_t* Pointer to interface descriptor, NULL if not found.
79  */
80 const usb_intf_desc_t *usb_parse_interface_descriptor(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, int *offset);
81 
82 /**
83  * @brief Get an endpoint descriptor within an interface descriptor
84  *
85  * Given an interface descriptor, get the Nth endpoint descriptor of the interface. The number of endpoints in an
86  * interface is indicated by the bNumEndpoints field of the interface descriptor.
87  *
88  * @note If bNumEndpoints is 0, it means the interface uses the default endpoint only
89  *
90  * @param[in] intf_desc Pointer to thee start of an interface descriptor
91  * @param[in] index Endpoint index
92  * @param[in] wTotalLength Total length of the containing configuration descriptor
93  * @param[inout] offset Byte offset relative to the start of the configuration descriptor. On input, it is the offset
94  *                      of the interface descriptor. On output, it is the offset of the endpoint descriptor.
95  * @return const usb_ep_desc_t* Pointer to endpoint descriptor, NULL if not found.
96  */
97 const usb_ep_desc_t *usb_parse_endpoint_descriptor_by_index(const usb_intf_desc_t *intf_desc, int index, uint16_t wTotalLength, int *offset);
98 
99 /**
100  * @brief Get an endpoint descriptor based on an endpoint's address
101  *
102  * Given a configuration descriptor, get an endpoint descriptor based on it's bEndpointAddress, bAlternateSetting, and
103  * bInterfaceNumber.
104  *
105  * @param[in] config_desc Pointer to the start of a full configuration descriptor
106  * @param[in] bInterfaceNumber Interface number
107  * @param[in] bAlternateSetting Alternate setting number
108  * @param[in] bEndpointAddress Endpoint address
109  * @param[out] offset Byte offset of the endpoint descriptor relative to the start of the configuration descriptor. Can be NULL
110  * @return const usb_ep_desc_t* Pointer to endpoint descriptor, NULL if not found.
111  */
112 const usb_ep_desc_t *usb_parse_endpoint_descriptor_by_address(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, uint8_t bEndpointAddress, int *offset);
113 
114 // ----------------------------------------------- Descriptor Printing -------------------------------------------------
115 
116 /**
117  * @brief Print class specific descriptor callback
118  *
119  * Optional callback to be provided to usb_print_config_descriptor() function.
120  * The callback is called when when a non-standard descriptor is encountered.
121  * The callback should decode the descriptor as print it.
122  */
123 typedef void (*print_class_descriptor_cb)(const usb_standard_desc_t *);
124 
125 /**
126  * @brief Print device descriptor
127  *
128  * @param devc_desc Device descriptor
129  */
130 void usb_print_device_descriptor(const usb_device_desc_t *devc_desc);
131 
132 /**
133  * @brief Print configuration descriptor
134  *
135  * - This function prints the full contents of a configuration descriptor (including interface and endpoint descriptors)
136  * - When a non-standard descriptor is encountered, this function will call the class_specific_cb if it is provided
137  *
138  * @param cfg_desc Configuration descriptor
139  * @param class_specific_cb Class specific descriptor callback. Can be NULL
140  */
141 void usb_print_config_descriptor(const usb_config_desc_t *cfg_desc, print_class_descriptor_cb class_specific_cb);
142 
143 /**
144  * @brief Print a string descriptor
145  *
146  * This funciton will only print ASCII characters of the UTF-16 encoded string
147  *
148  * @param str_desc String descriptor
149  */
150 void usb_print_string_descriptor(const usb_str_desc_t *str_desc);
151 
152 // ------------------------------------------------------ Misc ---------------------------------------------------------
153 
154 /**
155  * @brief Round up to an integer multiple of endpoint's MPS
156  *
157  * This is a convenience function to round up a size/length to an endpoint's MPS (Maximum packet size). This is useful
158  * when calculating transfer or buffer lengths of IN endpoints.
159  * - If MPS <= 0, this function will return 0
160  * - If num_bytes <= 0, this function will return 0
161  *
162  * @param[in] num_bytes Number of bytes
163  * @param[in] mps MPS
164  * @return int Round up integer multiple of MPS
165  */
usb_round_up_to_mps(int num_bytes,int mps)166 static inline int usb_round_up_to_mps(int num_bytes, int mps)
167 {
168     if (num_bytes <= 0 || mps <= 0) {    //MPS can never be zero
169         return 0;
170     }
171     return ((num_bytes + mps - 1) / mps) * mps;
172 }
173 
174 #ifdef __cplusplus
175 }
176 #endif
177