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 "freertos/FreeRTOS.h"
15 #include "esp_err.h"
16 #include "esp_intr_alloc.h"
17 //Include the other USB Host Library headers as well
18 #include "usb/usb_helpers.h"
19 #include "usb/usb_types_ch9.h"
20 #include "usb/usb_types_stack.h"
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 // ------------------------------------------------- Macros and Types --------------------------------------------------
27 
28 // ----------------------- Handles -------------------------
29 
30 /**
31  * @brief Handle to a USB Host Library asynchronous client
32  *
33  * An asynchronous client can be registered using usb_host_client_register()
34  *
35  * @note Asynchronous API
36  */
37 typedef struct usb_host_client_handle_s * usb_host_client_handle_t;
38 
39 // ----------------------- Events --------------------------
40 
41 #define USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS     0x01    /**< All clients have been deregistered from the USB Host Library */
42 #define USB_HOST_LIB_EVENT_FLAGS_ALL_FREE       0x02    /**< The USB Host Library has freed all devices */
43 
44 /**
45  * @brief The type event in a client event message
46  */
47 typedef enum {
48     USB_HOST_CLIENT_EVENT_NEW_DEV,                  /**< A new device has been enumerated and added to the USB Host Library */
49     USB_HOST_CLIENT_EVENT_DEV_GONE,                 /**< A device opened by the client is now gone */
50 } usb_host_client_event_t;
51 
52 /**
53  * @brief Client event message
54  *
55  * Client event messages are sent to each client of the USB Host Library in order to notify them of various
56  * USB Host Library events such as:
57  * - Addition of new devices
58  * - Removal of existing devices
59  *
60  * @note The event message structure has a union with members corresponding to each particular event. Based on the event
61  *       type, only the relevant member field should be accessed.
62  */
63 typedef struct {
64     usb_host_client_event_t event;              /**< Type of event */
65     union {
66         struct {
67             uint8_t address;                    /**< New device's address */
68         } new_dev;
69         struct {
70             usb_device_handle_t dev_hdl;        /**< The handle of the device that was gone */
71         } dev_gone;
72     };
73 } usb_host_client_event_msg_t;
74 
75 // ------------------------ Info ---------------------------
76 
77 /**
78  * @brief Current information about the USB Host Library obtained via usb_host_lib_info()
79  */
80 typedef struct {
81     int num_devices;    /**< Current number of connected (and enumerated) devices */
82     int num_clients;    /**< Current number of registered clients */
83 } usb_host_lib_info_t;
84 
85 // ---------------------- Callbacks ------------------------
86 
87 /**
88  * @brief Client event callback
89  *
90  * - Each client of the USB Host Library must register an event callback to receive event messages from the USB Host
91  *   Library.
92  * - The client event callback is run from the context of the clients usb_host_client_handle_events() function
93  */
94 typedef void (*usb_host_client_event_cb_t)(const usb_host_client_event_msg_t *event_msg, void *arg);
95 
96 // -------------------- Configurations ---------------------
97 
98 /**
99  * @brief USB Host Library configuration
100  *
101  * Configuration structure of the USB Host Library. Provided in the usb_host_install() function
102  */
103 typedef struct {
104     bool skip_phy_setup;        /**< If set, the USB Host Library will not configure the USB PHY thus allowing the user
105                                      to manually configure the USB PHY before calling usb_host_install(). Users should
106                                      set this if they want to use an external USB PHY. Otherwise, the USB Host Library
107                                      will automatically configure the internal USB PHY */
108     int intr_flags;             /**< Interrupt flags for the underlying ISR used by the USB Host stack */
109 } usb_host_config_t;
110 
111 /**
112  * @brief USB Host Library Client configuration
113  *
114  * Configuration structure for a USB Host Library client. Provided in usb_host_client_register()
115  */
116 typedef struct {
117     bool is_synchronous;        /**< Whether the client is asynchronous or synchronous or not. Set to false for now. */
118     int max_num_event_msg;      /**< Maximum number of event messages that can be stored (e.g., 3) */
119     union {     //Note: Made into union or future expansion
120         struct {
121             usb_host_client_event_cb_t client_event_callback;   /**< Client's event callback function */
122             void *callback_arg;                                 /**< Event callback function argument */
123         } async;
124     };
125 } usb_host_client_config_t;
126 
127 // ------------------------------------------------ Library Functions --------------------------------------------------
128 
129 /**
130  * @brief Install the USB Host Library
131  *
132  * - This function should only once to install the USB Host Library
133  * - This function should be called before any other USB Host Library functions are called
134  *
135  * @note If skip_phy_setup is set in the install configuration, the user is responsible for ensuring that the underlying
136  *       Host Controller is enabled and the USB PHY (internal or external) is already setup before this function is
137  *       called.
138  * @param[in] config USB Host Library configuration
139  * @return esp_err_t
140  */
141 esp_err_t usb_host_install(const usb_host_config_t *config);
142 
143 /**
144  * @brief Uninstall the USB Host Library
145  *
146  * - This function should be called to uninstall the USB Host Library, thereby freeing its resources
147  * - All clients must have been deregistered before calling this function
148  * - All devices must have been freed by calling usb_host_device_free_all() and receiving the
149  *   USB_HOST_LIB_EVENT_FLAGS_ALL_FREE event flag
150  *
151  * @note If skip_phy_setup was set when the Host Library was installed, the user is responsible for disabling the
152  *       underlying Host Controller and USB PHY (internal or external).
153  * @return esp_err_t
154  */
155 esp_err_t usb_host_uninstall(void);
156 
157 /**
158  * @brief Handle USB Host Library events
159  *
160  * - This function handles all of the USB Host Library's processing and should be called repeatedly in a loop
161  * - Check event_flags_ret to see if an flags are set indicating particular USB Host Library events
162  * - This function should never be called by multiple threads simultaneously
163  *
164  * @note This function can block
165  * @param[in] timeout_ticks Timeout in ticks to wait for an event to occur
166  * @param[out] event_flags_ret Event flags that indicate what USB Host Library event occurred.
167  * @return esp_err_t
168  */
169 esp_err_t usb_host_lib_handle_events(TickType_t timeout_ticks, uint32_t *event_flags_ret);
170 
171 /**
172  * @brief Unblock the USB Host Library handler
173  *
174  * - This function simply unblocks the USB Host Library event handling function (usb_host_lib_handle_events())
175  *
176  * @return esp_err_t
177  */
178 esp_err_t usb_host_lib_unblock(void);
179 
180 /**
181  * @brief Get current information about the USB Host Library
182  *
183  * @param[out] info_ret USB Host Library Information
184  * @return esp_err_t
185  */
186 esp_err_t usb_host_lib_info(usb_host_lib_info_t *info_ret);
187 
188 // ------------------------------------------------ Client Functions ---------------------------------------------------
189 
190 /**
191  * @brief Register a client of the USB Host Library
192  *
193  * - This function registers a client of the USB Host Library
194  * - Once a client is registered, its processing function usb_host_client_handle_events() should be called repeatedly
195  *
196  * @param[in] client_config Client configuration
197  * @param[out] client_hdl_ret Client handle
198  * @return esp_err_t
199  */
200 esp_err_t usb_host_client_register(const usb_host_client_config_t *client_config, usb_host_client_handle_t *client_hdl_ret);
201 
202 /**
203  * @brief Deregister a USB Host Library client
204  *
205  * - This function deregisters a client of the USB Host Library
206  * - The client must have closed all previously opened devices before attempting to deregister
207  *
208  * @param[in] client_hdl Client handle
209  * @return esp_err_t
210  */
211 esp_err_t usb_host_client_deregister(usb_host_client_handle_t client_hdl);
212 
213 /**
214  * @brief USB Host Library client processing function
215  *
216  * - This function handles all of a client's processing and should be called repeatedly in a loop
217  * - For a particular client, this function should never be called by multiple threads simultaneously
218  *
219  * @note This function can block
220  * @param[in] client_hdl Client handle
221  * @param[in] timeout_ticks Timeout in ticks to wait for an event to occur
222  * @return esp_err_t
223  */
224 esp_err_t usb_host_client_handle_events(usb_host_client_handle_t client_hdl, TickType_t timeout_ticks);
225 
226 /**
227  * @brief Unblock a client
228  *
229  * - This function simply unblocks a client if it is blocked on the usb_host_client_handle_events() function.
230  * - This function is useful when need to unblock a client in order to deregister it.
231  *
232  * @param[in] client_hdl Client handle
233  * @return esp_err_t
234  */
235 esp_err_t usb_host_client_unblock(usb_host_client_handle_t client_hdl);
236 
237 // ------------------------------------------------- Device Handling ---------------------------------------------------
238 
239 /**
240  * @brief Open a device
241  *
242  * - This function allows a client to open a device
243  * - A client must open a device first before attempting to use it (e.g., sending transfers, device requests etc.)
244  *
245  * @param[in] client_hdl Client handle
246  * @param[in] dev_addr Device's address
247  * @param[out] dev_hdl_ret Device's handle
248  * @return esp_err_t
249  */
250 esp_err_t usb_host_device_open(usb_host_client_handle_t client_hdl, uint8_t dev_addr, usb_device_handle_t *dev_hdl_ret);
251 
252 /**
253  * @brief Close a device
254  *
255  * - This function allows a client to close a device
256  * - A client must close a device after it has finished using the device (claimed interfaces must also be released)
257  * - A client must close all devices it has opened before deregistering
258  *
259  * @note This function can block
260  * @param[in] client_hdl Client handle
261  * @param[in] dev_hdl Device handle
262  * @return esp_err_t
263  */
264 esp_err_t usb_host_device_close(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl);
265 
266 /**
267  * @brief Indicate that all devices can be freed when possible
268  *
269  * - This function marks all devices as waiting to be freed
270  * - If a device is not opened by any clients, it will be freed immediately
271  * - If a device is opened by at least one client, the device will be free when the last client closes that device.
272  * - Wait for the USB_HOST_LIB_EVENT_FLAGS_ALL_FREE flag to be set by usb_host_lib_handle_events() in order to know
273  *   when all devices have been freed
274  * - This function is useful when cleaning up devices before uninstalling the USB Host Library
275  *
276  * @return
277  *  - ESP_ERR_NOT_FINISHED: There are one or more devices that still need to be freed. Wait for USB_HOST_LIB_EVENT_FLAGS_ALL_FREE event
278  *  - ESP_OK: All devices already freed (i.e., there were no devices)
279  *  - Other: Error
280  */
281 esp_err_t usb_host_device_free_all(void);
282 
283 /**
284  * @brief Fill a list of device address
285  *
286  * - This function fills an empty list with the address of connected devices
287  * - The Device addresses can then used in usb_host_device_open()
288  * - If there are more devices than the list_len, this function will only fill up to list_len number of devices.
289  *
290  * @param[in] list_len Length of the empty list
291  * @param[inout] dev_addr_list Empty list to be filled
292  * @param[out] num_dev_ret Number of devices
293  * @return esp_err_t
294  */
295 esp_err_t usb_host_device_addr_list_fill(int list_len, uint8_t *dev_addr_list, int *num_dev_ret);
296 
297 // ------------------------------------------------- Device Requests ---------------------------------------------------
298 
299 // ------------------- Cached Requests ---------------------
300 
301 /**
302  * @brief Get device's information
303  *
304  * - This function gets some basic information of a device
305  * - The device must be opened first before attempting to get its information
306  *
307  * @note This function can block
308  * @param[in] dev_hdl Device handle
309  * @param[out] dev_info Device information
310  * @return esp_err_t
311  */
312 esp_err_t usb_host_device_info(usb_device_handle_t dev_hdl, usb_device_info_t *dev_info);
313 
314 // ----------------------------------------------- Descriptor Requests -------------------------------------------------
315 
316 // ----------------- Cached Descriptors --------------------
317 
318 /**
319  * @brief Get device's device descriptor
320  *
321  * - A client must call usb_host_device_open() first
322  * - No control transfer is sent. The device's descriptor is cached on enumeration
323  * - This function simple returns a pointer to the cached descriptor
324  *
325  * @note No control transfer is sent. The device's descriptor is cached on enumeration
326  * @param[in] dev_hdl Device handle
327  * @param[out] device_desc Device descriptor
328  * @return esp_err_t
329  */
330 esp_err_t usb_host_get_device_descriptor(usb_device_handle_t dev_hdl, const usb_device_desc_t **device_desc);
331 
332 /**
333  * @brief Get device's active configuration descriptor
334  *
335  * - A client must call usb_host_device_open() first
336  * - No control transfer is sent. The device's active configuration descriptor is cached on enumeration
337  * - This function simple returns a pointer to the cached descriptor
338  *
339  * @note This function can block
340  * @note No control transfer is sent. A device's active configuration descriptor is cached on enumeration
341  * @param[in] dev_hdl Device handle
342  * @param[out] config_desc Configuration descriptor
343  * @return esp_err_t
344  */
345 esp_err_t usb_host_get_active_config_descriptor(usb_device_handle_t dev_hdl, const usb_config_desc_t **config_desc);
346 
347 // ----------------------------------------------- Interface Functions -------------------------------------------------
348 
349 /**
350  * @brief Function for a client to claim a device's interface
351  *
352  * - A client must claim a device's interface before attempting to communicate with any of its endpoints
353  * - Once an interface is claimed by a client, it cannot be claimed by any other client.
354  *
355  * @note This function can block
356  * @param[in] client_hdl Client handle
357  * @param[in] dev_hdl Device handle
358  * @param[in] bInterfaceNumber Interface number
359  * @param[in] bAlternateSetting Interface alternate setting number
360  * @return esp_err_t
361  */
362 esp_err_t usb_host_interface_claim(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber, uint8_t bAlternateSetting);
363 
364 /**
365  * @brief Function for a client to release a previously claimed interface
366  *
367  * - A client should release a device's interface after it no longer needs to communicate with the interface
368  * - A client must release all of its interfaces of a device it has claimed before being able to close the device
369  *
370  * @note This function can block
371  * @param[in] client_hdl Client handle
372  * @param[in] dev_hdl Device handle
373  * @param[in] bInterfaceNumber Interface number
374  * @return esp_err_t
375  */
376 esp_err_t usb_host_interface_release(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber);
377 
378 /**
379  * @brief Halt a particular endpoint
380  *
381  * - The device must have been opened by a client
382  * - The endpoint must be part of an interface claimed by a client
383  * - Once halted, the endpoint must be cleared using usb_host_endpoint_clear() before it can communicate again
384  *
385  * @note This function can block
386  * @param dev_hdl Device handle
387  * @param bEndpointAddress Endpoint address
388  * @return esp_err_t
389  */
390 esp_err_t usb_host_endpoint_halt(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress);
391 
392 /**
393  * @brief Flush a particular endpoint
394  *
395  * - The device must have been opened by a client
396  * - The endpoint must be part of an interface claimed by a client
397  * - The endpoint must have been halted (either through a transfer error, or usb_host_endpoint_halt())
398  * - Flushing an endpoint will caused an queued up transfers to be canceled
399  *
400  * @note This function can block
401  * @param dev_hdl Device handle
402  * @param bEndpointAddress Endpoint address
403  * @return esp_err_t
404  */
405 esp_err_t usb_host_endpoint_flush(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress);
406 
407 /**
408  * @brief Clear a halt on a particular endpoint
409  *
410  * - The device must have been opened by a client
411  * - The endpoint must be part of an interface claimed by a client
412  * - The endpoint must have been halted (either through a transfer error, or usb_host_endpoint_halt())
413  * - If the endpoint has any queued up transfers, clearing a halt will resume their execution
414  *
415  * @note This function can block
416  * @param dev_hdl Device handle
417  * @param bEndpointAddress Endpoint address
418  * @return esp_err_t
419  */
420 esp_err_t usb_host_endpoint_clear(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress);
421 
422 // ------------------------------------------------ Asynchronous I/O ---------------------------------------------------
423 
424 /**
425  * @brief Allocate a transfer object
426  *
427  * - This function allocates a transfer object
428  * - Each transfer object has a fixed sized buffer specified on allocation
429  * - A transfer object can be re-used indefinitely
430  * - A transfer can be submitted using usb_host_transfer_submit() or usb_host_transfer_submit_control()
431  *
432  * @param[in] data_buffer_size Size of the transfer's data buffer
433  * @param[in] num_isoc_packets Number of isochronous packets in transfer (set to 0 for non-isochronous transfers)
434  * @param[out] transfer Transfer object
435  * @return esp_err_t
436  */
437 esp_err_t usb_host_transfer_alloc(size_t data_buffer_size, int num_isoc_packets, usb_transfer_t **transfer);
438 
439 /**
440  * @brief Free a transfer object
441  *
442  * - Free a transfer object previously allocated using usb_host_transfer_alloc()
443  * - The transfer must not be in-flight when attempting to free it
444  * - If a NULL pointer is passed, this function will simply return ESP_OK
445  *
446  * @param[in] transfer Transfer object
447  * @return esp_err_t
448  */
449 esp_err_t usb_host_transfer_free(usb_transfer_t *transfer);
450 
451 /**
452  * @brief Submit a non-control transfer
453  *
454  * - Submit a transfer to a particular endpoint. The device and endpoint number is specified inside the transfer
455  * - The transfer must be properly initialized before submitting
456  * - On completion, the transfer's callback will be called from the client's usb_host_client_handle_events() function.
457  *
458  * @param[in] transfer Initialized transfer object
459  * @return esp_err_t
460  */
461 esp_err_t usb_host_transfer_submit(usb_transfer_t *transfer);
462 
463 /**
464  * @brief Submit a control transfer
465  *
466  * - Submit a control transfer to a particular device. The client must have opened the device first
467  * - The transfer must be properly initialized before submitting. The first 8 bytes of the transfer's data buffer should
468  *   contain the control transfer setup packet
469  * - On completion, the transfer's callback will be called from the client's usb_host_client_handle_events() function.
470  *
471  * @param[in] client_hdl Client handle
472  * @param[in] transfer Initialized transfer object
473  * @return esp_err_t
474  */
475 esp_err_t usb_host_transfer_submit_control(usb_host_client_handle_t client_hdl, usb_transfer_t *transfer);
476 
477 #ifdef __cplusplus
478 }
479 #endif
480