kopia lustrzana https://github.com/espressif/esp-idf
usb: Change API and refactor tests
This commit updates the USB Host Library API in the following wasy: - usb_host_client_handle_t and usb_device_handle_t made into struct pointers to generate compiler warnings about conflicting handle types - usb_host_client_config_t changed to future proof API for Synchronous Clients - Added usb_host_lib_unblock() - Added usb_host_device_addr_list_fill() - Return of usb_host_device_free_all() updated to indicate whether there are still devices yet to be freed. - Blockg APIs are now marked explicitly - Fixed a bug in usb_host_transfer_submit_control() when checking the bEndpointAddress of a control transfer. Tests are also refactored to move some common macros into shared headers Closes https://github.com/espressif/esp-idf/issues/7786pull/6613/merge
rodzic
54b6c902d3
commit
189899180f
|
@ -27,7 +27,14 @@ extern "C" {
|
|||
|
||||
// ----------------------- Handles -------------------------
|
||||
|
||||
typedef void * usb_host_client_handle_t; /**< Handle to a client using the USB Host Library */
|
||||
/**
|
||||
* @brief Handle to a USB Host Library asynchronous client
|
||||
*
|
||||
* An asynchronous client can be registered using usb_host_client_register()
|
||||
*
|
||||
* @note Asynchronous API
|
||||
*/
|
||||
typedef struct usb_host_client_handle_s * usb_host_client_handle_t;
|
||||
|
||||
// ----------------------- Events --------------------------
|
||||
|
||||
|
@ -93,9 +100,14 @@ typedef struct {
|
|||
* Configuration structure for a USB Host Library client. Provided in usb_host_client_register()
|
||||
*/
|
||||
typedef struct {
|
||||
usb_host_client_event_cb_t client_event_callback; /**< Client's event callback function */
|
||||
void *callback_arg; /**< Event callback function argument */
|
||||
int max_num_event_msg; /**< Maximum number of event messages that can be stored (e.g., 3) */
|
||||
bool is_synchronous; /**< Whether the client is asynchronous or synchronous or not. Set to false for now. */
|
||||
int max_num_event_msg; /**< Maximum number of event messages that can be stored (e.g., 3) */
|
||||
union { //Note: Made into union or future expansion
|
||||
struct {
|
||||
usb_host_client_event_cb_t client_event_callback; /**< Client's event callback function */
|
||||
void *callback_arg; /**< Event callback function argument */
|
||||
} async;
|
||||
};
|
||||
} usb_host_client_config_t;
|
||||
|
||||
// ------------------------------------------------ Library Functions --------------------------------------------------
|
||||
|
@ -129,12 +141,22 @@ esp_err_t usb_host_uninstall(void);
|
|||
* - This function handles all of the USB Host Library's processing and should be called repeatedly in a loop
|
||||
* - Check event_flags_ret to see if an flags are set indicating particular USB Host Library events
|
||||
*
|
||||
* @note This function can block
|
||||
* @param[in] timeout_ticks Timeout in ticks to wait for an event to occur
|
||||
* @param[out] event_flags_ret Event flags that indicate what USB Host Library event occurred
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t usb_host_lib_handle_events(TickType_t timeout_ticks, uint32_t *event_flags_ret);
|
||||
|
||||
/**
|
||||
* @brief Unblock the USB Host Library handler
|
||||
*
|
||||
* - This function simply unblocks the USB Host Library event handling function (usb_host_lib_handle_events())
|
||||
*
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t usb_host_lib_unblock(void);
|
||||
|
||||
// ------------------------------------------------ Client Functions ---------------------------------------------------
|
||||
|
||||
/**
|
||||
|
@ -165,6 +187,7 @@ esp_err_t usb_host_client_deregister(usb_host_client_handle_t client_hdl);
|
|||
*
|
||||
* - This function handles all of a client's processing and should be called repeatedly in a loop
|
||||
*
|
||||
* @note This function can block
|
||||
* @param[in] client_hdl Client handle
|
||||
* @param[in] timeout_ticks Timeout in ticks to wait for an event to occur
|
||||
* @return esp_err_t
|
||||
|
@ -204,6 +227,7 @@ esp_err_t usb_host_device_open(usb_host_client_handle_t client_hdl, uint8_t dev_
|
|||
* - A client must close a device after it has finished using the device (claimed interfaces must also be released)
|
||||
* - A client must close all devices it has opened before deregistering
|
||||
*
|
||||
* @note This function can block
|
||||
* @param[in] client_hdl Client handle
|
||||
* @param[in] dev_hdl Device handle
|
||||
* @return esp_err_t
|
||||
|
@ -220,10 +244,28 @@ esp_err_t usb_host_device_close(usb_host_client_handle_t client_hdl, usb_device_
|
|||
* when all devices have been freed
|
||||
* - This function is useful when cleaning up devices before uninstalling the USB Host Library
|
||||
*
|
||||
* @return esp_err_t
|
||||
* @return
|
||||
* - 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
|
||||
* - ESP_OK: All devices already freed (i.e., there were no devices)
|
||||
* - Other: Error
|
||||
*/
|
||||
esp_err_t usb_host_device_free_all(void);
|
||||
|
||||
/**
|
||||
* @brief Fill a list of device address
|
||||
*
|
||||
* - This function fills an empty list with the address of connected devices
|
||||
* - The Device addresses can then used in usb_host_device_open()
|
||||
* - If there are more devices than the list_len, this function will only fill
|
||||
* up to list_len number of devices.
|
||||
*
|
||||
* @param[in] list_len Length of the empty list
|
||||
* @param[inout] dev_addr_list Empty list to be filled
|
||||
* @param[out] num_dev_ret Number of devices
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t usb_host_device_addr_list_fill(int list_len, uint8_t *dev_addr_list, int *num_dev_ret);
|
||||
|
||||
// ------------------------------------------------- Device Requests ---------------------------------------------------
|
||||
|
||||
// ------------------- Cached Requests ---------------------
|
||||
|
@ -234,6 +276,7 @@ esp_err_t usb_host_device_free_all(void);
|
|||
* - This function gets some basic information of a device
|
||||
* - The device must be opened first before attempting to get its information
|
||||
*
|
||||
* @note This function can block
|
||||
* @param[in] dev_hdl Device handle
|
||||
* @param[out] dev_info Device information
|
||||
* @return esp_err_t
|
||||
|
@ -265,6 +308,7 @@ esp_err_t usb_host_get_device_descriptor(usb_device_handle_t dev_hdl, const usb_
|
|||
* - No control transfer is sent. The device's active configuration descriptor is cached on enumeration
|
||||
* - This function simple returns a pointer to the cached descriptor
|
||||
*
|
||||
* @note This function can block
|
||||
* @note No control transfer is sent. A device's active configuration descriptor is cached on enumeration
|
||||
* @param[in] dev_hdl Device handle
|
||||
* @param[out] config_desc Configuration descriptor
|
||||
|
@ -280,6 +324,7 @@ esp_err_t usb_host_get_active_config_descriptor(usb_device_handle_t dev_hdl, con
|
|||
* - A client must claim a device's interface before attempting to communicate with any of its endpoints
|
||||
* - Once an interface is claimed by a client, it cannot be claimed by any other client.
|
||||
*
|
||||
* @note This function can block
|
||||
* @param[in] client_hdl Client handle
|
||||
* @param[in] dev_hdl Device handle
|
||||
* @param[in] bInterfaceNumber Interface number
|
||||
|
@ -294,6 +339,7 @@ esp_err_t usb_host_interface_claim(usb_host_client_handle_t client_hdl, usb_devi
|
|||
* - A client should release a device's interface after it no longer needs to communicate with the interface
|
||||
* - A client must release all of its interfaces of a device it has claimed before being able to close the device
|
||||
*
|
||||
* @note This function can block
|
||||
* @param[in] client_hdl Client handle
|
||||
* @param[in] dev_hdl Device handle
|
||||
* @param[in] bInterfaceNumber Interface number
|
||||
|
@ -308,6 +354,7 @@ esp_err_t usb_host_interface_release(usb_host_client_handle_t client_hdl, usb_de
|
|||
* - The endpoint must be part of an interface claimed by a client
|
||||
* - Once halted, the endpoint must be cleared using usb_host_endpoint_clear() before it can communicate again
|
||||
*
|
||||
* @note This function can block
|
||||
* @param dev_hdl Device handle
|
||||
* @param bEndpointAddress Endpoint address
|
||||
* @return esp_err_t
|
||||
|
@ -322,6 +369,7 @@ esp_err_t usb_host_endpoint_halt(usb_device_handle_t dev_hdl, uint8_t bEndpointA
|
|||
* - The endpoint must have been halted (either through a transfer error, or usb_host_endpoint_halt())
|
||||
* - Flushing an endpoint will caused an queued up transfers to be canceled
|
||||
*
|
||||
* @note This function can block
|
||||
* @param dev_hdl Device handle
|
||||
* @param bEndpointAddress Endpoint address
|
||||
* @return esp_err_t
|
||||
|
@ -336,6 +384,7 @@ esp_err_t usb_host_endpoint_flush(usb_device_handle_t dev_hdl, uint8_t bEndpoint
|
|||
* - The endpoint must have been halted (either through a transfer error, or usb_host_endpoint_halt())
|
||||
* - If the endpoint has any queued up transfers, clearing a halt will resume their execution
|
||||
*
|
||||
* @note This function can block
|
||||
* @param dev_hdl Device handle
|
||||
* @param bEndpointAddress Endpoint address
|
||||
* @return esp_err_t
|
||||
|
@ -396,17 +445,6 @@ esp_err_t usb_host_transfer_submit(usb_transfer_t *transfer);
|
|||
*/
|
||||
esp_err_t usb_host_transfer_submit_control(usb_host_client_handle_t client_hdl, usb_transfer_t *transfer);
|
||||
|
||||
/**
|
||||
* @brief Cancel a submitted transfer
|
||||
*
|
||||
* - Cancel a previously submitted transfer
|
||||
* - In its current implementation, any transfer that is already in-flight will not be canceled
|
||||
*
|
||||
* @param transfer Transfer object
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t usb_host_transfer_cancel(usb_transfer_t *transfer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -43,7 +43,7 @@ typedef enum {
|
|||
/**
|
||||
* @brief Handle of a USB Device connected to a USB Host
|
||||
*/
|
||||
typedef void * usb_device_handle_t;
|
||||
typedef struct usb_device_handle_s * usb_device_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Basic information of an enumerated device
|
||||
|
|
|
@ -119,6 +119,21 @@ esp_err_t usbh_process(void);
|
|||
|
||||
// --------------------- Device Pool -----------------------
|
||||
|
||||
/**
|
||||
* @brief Fill list with address of currently connected devices
|
||||
*
|
||||
* - This function fills the provided list with the address of current connected devices
|
||||
* - Device address can then be used in usbh_dev_open()
|
||||
* - If there are more devices than the list_len, this function will only fill
|
||||
* up to list_len number of devices.
|
||||
*
|
||||
* @param[in] list_len Length of empty list
|
||||
* @param[inout] dev_addr_list Empty list to be filled
|
||||
* @param[out] num_dev_ret Number of devices filled into list
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t usbh_dev_addr_list_fill(int list_len, uint8_t *dev_addr_list, int *num_dev_ret);
|
||||
|
||||
/**
|
||||
* @brief Open a device by address
|
||||
*
|
||||
|
@ -145,7 +160,9 @@ esp_err_t usbh_dev_close(usb_device_handle_t dev_hdl);
|
|||
*
|
||||
* A device marked as free will not be freed until the last client using the device has called usbh_dev_close()
|
||||
*
|
||||
* @return esp_err_t
|
||||
* @return
|
||||
* - ESP_OK: There were no devices to free to begin with. Current state is all free
|
||||
* - ESP_ERR_NOT_FINISHED: One or more devices still need to be freed (but have been marked "to be freed")
|
||||
*/
|
||||
esp_err_t usbh_dev_mark_all_free(void);
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "freertos/task.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "test_usb_common.h"
|
||||
#include "ctrl_client.h"
|
||||
#include "usb/usb_host.h"
|
||||
#include "unity.h"
|
||||
|
@ -32,7 +33,6 @@ Implementation of a control transfer client used for USB Host Tests.
|
|||
- Deregister control client
|
||||
*/
|
||||
|
||||
#define MAX(x,y) (((x) >= (y)) ? (x) : (y))
|
||||
#define CTRL_CLIENT_MAX_EVENT_MSGS 5
|
||||
#define NUM_TRANSFER_OBJ 3
|
||||
#define MAX_TRANSFER_BYTES 256
|
||||
|
@ -97,9 +97,12 @@ void ctrl_client_async_seq_task(void *arg)
|
|||
|
||||
//Register client
|
||||
usb_host_client_config_t client_config = {
|
||||
.client_event_callback = ctrl_client_event_cb,
|
||||
.callback_arg = (void *)&ctrl_obj,
|
||||
.is_synchronous = false,
|
||||
.max_num_event_msg = CTRL_CLIENT_MAX_EVENT_MSGS,
|
||||
.async = {
|
||||
.client_event_callback = ctrl_client_event_cb,
|
||||
.callback_arg = (void *)&ctrl_obj,
|
||||
},
|
||||
};
|
||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_register(&client_config, &ctrl_obj.client_hdl));
|
||||
|
||||
|
@ -153,7 +156,7 @@ void ctrl_client_async_seq_task(void *arg)
|
|||
usb_transfer_t *transfer = ctrl_xfer[ctrl_obj.num_xfer_sent % NUM_TRANSFER_OBJ];
|
||||
USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)transfer->data_buffer, 0, MAX_TRANSFER_BYTES);
|
||||
transfer->num_bytes = sizeof(usb_setup_packet_t) + MAX_TRANSFER_BYTES;
|
||||
transfer->bEndpointAddress = 0;
|
||||
transfer->bEndpointAddress = 0x80;
|
||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit_control(ctrl_obj.client_hdl, transfer));
|
||||
ctrl_obj.num_xfer_sent++;
|
||||
ctrl_obj.next_stage = TEST_STAGE_CTRL_XFER_WAIT;
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MSC_ASYNC_CLIENT_MAX_EVENT_MSGS 5
|
||||
|
||||
typedef struct {
|
||||
int num_sectors_to_read;
|
||||
int num_sectors_per_xfer;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/param.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_err.h"
|
||||
|
@ -35,9 +36,6 @@ Implementation of an asynchronous MSC client used for USB Host disconnection tes
|
|||
- Deregister MSC client
|
||||
*/
|
||||
|
||||
#define MAX(x,y) (((x) >= (y)) ? (x) : (y))
|
||||
#define MSC_CLIENT_MAX_EVENT_MSGS 5
|
||||
|
||||
typedef enum {
|
||||
TEST_STAGE_WAIT_CONN,
|
||||
TEST_STAGE_DEV_OPEN,
|
||||
|
@ -130,9 +128,12 @@ void msc_client_async_dconn_task(void *arg)
|
|||
|
||||
//Register client
|
||||
usb_host_client_config_t client_config = {
|
||||
.client_event_callback = msc_client_event_cb,
|
||||
.callback_arg = (void *)&msc_obj,
|
||||
.max_num_event_msg = MSC_CLIENT_MAX_EVENT_MSGS,
|
||||
.is_synchronous = false,
|
||||
.max_num_event_msg = MSC_ASYNC_CLIENT_MAX_EVENT_MSGS,
|
||||
.async = {
|
||||
.client_event_callback = msc_client_event_cb,
|
||||
.callback_arg = (void *)&msc_obj,
|
||||
},
|
||||
};
|
||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_register(&client_config, &msc_obj.client_hdl));
|
||||
|
||||
|
|
|
@ -7,10 +7,12 @@
|
|||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/param.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "test_usb_common.h"
|
||||
#include "test_usb_mock_classes.h"
|
||||
#include "msc_client.h"
|
||||
#include "usb/usb_host.h"
|
||||
|
@ -34,9 +36,6 @@ Implementation of an MSC client used for USB Host Tests
|
|||
- Deregister MSC client
|
||||
*/
|
||||
|
||||
#define MAX(x,y) (((x) >= (y)) ? (x) : (y))
|
||||
#define MSC_CLIENT_MAX_EVENT_MSGS 5
|
||||
|
||||
typedef enum {
|
||||
TEST_STAGE_WAIT_CONN,
|
||||
TEST_STAGE_DEV_OPEN,
|
||||
|
@ -130,9 +129,12 @@ void msc_client_async_seq_task(void *arg)
|
|||
|
||||
//Register client
|
||||
usb_host_client_config_t client_config = {
|
||||
.client_event_callback = msc_client_event_cb,
|
||||
.callback_arg = (void *)&msc_obj,
|
||||
.max_num_event_msg = MSC_CLIENT_MAX_EVENT_MSGS,
|
||||
.is_synchronous = false,
|
||||
.max_num_event_msg = MSC_ASYNC_CLIENT_MAX_EVENT_MSGS,
|
||||
.async = {
|
||||
.client_event_callback = msc_client_event_cb,
|
||||
.callback_arg = (void *)&msc_obj,
|
||||
},
|
||||
};
|
||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_register(&client_config, &msc_obj.client_hdl));
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ TEST_CASE("Test USB Host async (single client)", "[usb_host][ignore]")
|
|||
usb_host_lib_handle_events(portMAX_DELAY, &event_flags);
|
||||
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
|
||||
printf("No more clients\n");
|
||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_free_all());
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FINISHED, usb_host_device_free_all());
|
||||
}
|
||||
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
|
||||
break;
|
||||
|
@ -144,7 +144,7 @@ TEST_CASE("Test USB Host async (multi client)", "[usb_host][ignore]")
|
|||
usb_host_lib_handle_events(portMAX_DELAY, &event_flags);
|
||||
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
|
||||
printf("No more clients\n");
|
||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_free_all());
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FINISHED, usb_host_device_free_all());
|
||||
}
|
||||
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
|
||||
break;
|
||||
|
|
|
@ -508,6 +508,16 @@ exit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t usb_host_lib_unblock(void)
|
||||
{
|
||||
//All devices must have been freed at this point
|
||||
HOST_ENTER_CRITICAL();
|
||||
HOST_CHECK_FROM_CRIT(p_host_lib_obj != NULL, ESP_ERR_INVALID_STATE);
|
||||
_unblock_lib(false);
|
||||
HOST_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// ------------------------------------------------ Client Functions ---------------------------------------------------
|
||||
|
||||
// ----------------------- Private -------------------------
|
||||
|
@ -562,7 +572,11 @@ static void _handle_pending_ep(client_t *client_obj)
|
|||
esp_err_t usb_host_client_register(const usb_host_client_config_t *client_config, usb_host_client_handle_t *client_hdl_ret)
|
||||
{
|
||||
HOST_CHECK(client_config != NULL && client_hdl_ret != NULL, ESP_ERR_INVALID_ARG);
|
||||
HOST_CHECK(client_config->client_event_callback != NULL && client_config->max_num_event_msg > 0, ESP_ERR_INVALID_ARG);
|
||||
HOST_CHECK(client_config->max_num_event_msg > 0, ESP_ERR_INVALID_ARG);
|
||||
if (!client_config->is_synchronous) {
|
||||
//Asynchronous clients must provide a
|
||||
HOST_CHECK(client_config->async.client_event_callback != NULL, ESP_ERR_INVALID_ARG);
|
||||
}
|
||||
|
||||
esp_err_t ret;
|
||||
//Create client object
|
||||
|
@ -579,8 +593,8 @@ esp_err_t usb_host_client_register(const usb_host_client_config_t *client_config
|
|||
TAILQ_INIT(&client_obj->mux_protected.interface_tailq);
|
||||
TAILQ_INIT(&client_obj->dynamic.done_ctrl_xfer_tailq);
|
||||
client_obj->constant.event_sem = event_sem;
|
||||
client_obj->constant.event_callback = client_config->client_event_callback;
|
||||
client_obj->constant.callback_arg = client_config->callback_arg;
|
||||
client_obj->constant.event_callback = client_config->async.client_event_callback;
|
||||
client_obj->constant.callback_arg = client_config->async.callback_arg;
|
||||
client_obj->constant.event_msg_queue = event_msg_queue;
|
||||
|
||||
//Add client to the host library's list of clients
|
||||
|
@ -819,10 +833,16 @@ esp_err_t usb_host_device_free_all(void)
|
|||
HOST_EXIT_CRITICAL();
|
||||
esp_err_t ret;
|
||||
ret = usbh_dev_mark_all_free();
|
||||
//Wait for USB_HOST_LIB_EVENT_FLAGS_ALL_FREE to confirm all devices free
|
||||
//If ESP_ERR_NOT_FINISHED is returned, caller must wait for USB_HOST_LIB_EVENT_FLAGS_ALL_FREE to confirm all devices are free
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t usb_host_device_addr_list_fill(int list_len, uint8_t *dev_addr_list, int *num_dev_ret)
|
||||
{
|
||||
HOST_CHECK(dev_addr_list != NULL && num_dev_ret != NULL, ESP_ERR_INVALID_ARG);
|
||||
return usbh_dev_addr_list_fill(list_len, dev_addr_list, num_dev_ret);
|
||||
}
|
||||
|
||||
// ------------------------------------------------- Device Requests ---------------------------------------------------
|
||||
|
||||
// ------------------- Cached Requests ---------------------
|
||||
|
@ -1266,7 +1286,8 @@ esp_err_t usb_host_transfer_submit_control(usb_host_client_handle_t client_hdl,
|
|||
usb_device_info_t dev_info;
|
||||
ESP_ERROR_CHECK(usbh_dev_get_info(dev_hdl, &dev_info));
|
||||
HOST_CHECK(transfer_check(transfer, USB_TRANSFER_TYPE_CTRL, dev_info.bMaxPacketSize0, xfer_is_in), ESP_ERR_INVALID_ARG);
|
||||
HOST_CHECK(transfer->bEndpointAddress == 0, ESP_ERR_INVALID_ARG);
|
||||
//Control transfers must be targeted at EP 0
|
||||
HOST_CHECK((transfer->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK) == 0, ESP_ERR_INVALID_ARG);
|
||||
//Save client handle into URB
|
||||
urb_t *urb_obj = __containerof(transfer, urb_t, transfer);
|
||||
urb_obj->usb_host_client = (void *)client_hdl;
|
||||
|
|
|
@ -468,6 +468,36 @@ esp_err_t usbh_process(void)
|
|||
|
||||
// --------------------- Device Pool -----------------------
|
||||
|
||||
esp_err_t usbh_dev_addr_list_fill(int list_len, uint8_t *dev_addr_list, int *num_dev_ret)
|
||||
{
|
||||
USBH_CHECK(dev_addr_list != NULL && num_dev_ret != NULL, ESP_ERR_INVALID_ARG);
|
||||
USBH_ENTER_CRITICAL();
|
||||
int num_filled = 0;
|
||||
device_t *dev_obj;
|
||||
//Fill list with devices from idle tailq
|
||||
TAILQ_FOREACH(dev_obj, &p_usbh_obj->dynamic.devs_idle_tailq, dynamic.tailq_entry) {
|
||||
if (num_filled < list_len) {
|
||||
dev_addr_list[num_filled] = dev_obj->constant.address;
|
||||
num_filled++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
//Fill list with devices from pending tailq
|
||||
TAILQ_FOREACH(dev_obj, &p_usbh_obj->dynamic.devs_pending_tailq, dynamic.tailq_entry) {
|
||||
if (num_filled < list_len) {
|
||||
dev_addr_list[num_filled] = dev_obj->constant.address;
|
||||
num_filled++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
USBH_EXIT_CRITICAL();
|
||||
//Write back number of devices filled
|
||||
*num_dev_ret = num_filled;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t usbh_dev_open(uint8_t dev_addr, usb_device_handle_t *dev_hdl)
|
||||
{
|
||||
USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG);
|
||||
|
@ -547,6 +577,7 @@ esp_err_t usbh_dev_mark_all_free(void)
|
|||
Note: We manually traverse the list because we need to add/remove items while traversing
|
||||
*/
|
||||
bool call_notif_cb = false;
|
||||
bool wait_for_free = false;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
device_t *dev_obj_cur;
|
||||
device_t *dev_obj_next;
|
||||
|
@ -568,6 +599,7 @@ esp_err_t usbh_dev_mark_all_free(void)
|
|||
//Device is still opened. Just mark it as waiting to be closed
|
||||
dev_obj_cur->dynamic.flags.waiting_close = 1;
|
||||
}
|
||||
wait_for_free = true; //As long as there is still a device, we need to wait for an event indicating it is freed
|
||||
dev_obj_cur = dev_obj_next;
|
||||
}
|
||||
}
|
||||
|
@ -576,7 +608,7 @@ esp_err_t usbh_dev_mark_all_free(void)
|
|||
if (call_notif_cb) {
|
||||
p_usbh_obj->constant.notif_cb(USB_NOTIF_SOURCE_USBH, false, p_usbh_obj->constant.notif_cb_arg);
|
||||
}
|
||||
return ESP_OK;
|
||||
return (wait_for_free) ? ESP_ERR_NOT_FINISHED : ESP_OK;
|
||||
}
|
||||
|
||||
// ------------------- Single Device ----------------------
|
||||
|
|
Ładowanie…
Reference in New Issue