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