mirror of
https://github.com/espressif/esp-idf
synced 2025-03-09 09:09:10 -04:00
feat(usb_host): Mock USB device open/close
- CMock callbacks for USB device opening and closing
This commit is contained in:
parent
cd225d0788
commit
3cef3baeba
@ -10,6 +10,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
|
#include "esp_assert.h"
|
||||||
#include "usb/usb_types_ch9.h"
|
#include "usb/usb_types_ch9.h"
|
||||||
#include "usb/usb_types_stack.h"
|
#include "usb/usb_types_stack.h"
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ typedef struct {
|
|||||||
int num_isoc_packets;
|
int num_isoc_packets;
|
||||||
usb_isoc_packet_desc_t isoc_packet_desc[0];
|
usb_isoc_packet_desc_t isoc_packet_desc[0];
|
||||||
} usb_transfer_dummy_t;
|
} usb_transfer_dummy_t;
|
||||||
_Static_assert(sizeof(usb_transfer_dummy_t) == sizeof(usb_transfer_t), "usb_transfer_dummy_t does not match usb_transfer_t");
|
ESP_STATIC_ASSERT(sizeof(usb_transfer_dummy_t) == sizeof(usb_transfer_t), "usb_transfer_dummy_t does not match usb_transfer_t");
|
||||||
|
|
||||||
struct urb_s {
|
struct urb_s {
|
||||||
TAILQ_ENTRY(urb_s) tailq_entry;
|
TAILQ_ENTRY(urb_s) tailq_entry;
|
||||||
|
@ -15,10 +15,18 @@ urb_t *urb_alloc(size_t data_buffer_size, int num_isoc_packets)
|
|||||||
if (urb == NULL || data_buffer == NULL) {
|
if (urb == NULL || data_buffer == NULL) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_LINUX
|
||||||
|
// heap_caps_get_allocated_size() return 0 on Linux target
|
||||||
|
const size_t allocated_size = data_buffer_size;
|
||||||
|
#else
|
||||||
|
const size_t allocated_size = heap_caps_get_allocated_size(data_buffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Cast as dummy transfer so that we can assign to const fields
|
// Cast as dummy transfer so that we can assign to const fields
|
||||||
usb_transfer_dummy_t *dummy_transfer = (usb_transfer_dummy_t *)&urb->transfer;
|
usb_transfer_dummy_t *dummy_transfer = (usb_transfer_dummy_t *)&urb->transfer;
|
||||||
dummy_transfer->data_buffer = data_buffer;
|
dummy_transfer->data_buffer = data_buffer;
|
||||||
dummy_transfer->data_buffer_size = heap_caps_get_allocated_size(data_buffer);
|
dummy_transfer->data_buffer_size = allocated_size;
|
||||||
dummy_transfer->num_isoc_packets = num_isoc_packets;
|
dummy_transfer->num_isoc_packets = num_isoc_packets;
|
||||||
return urb;
|
return urb;
|
||||||
err:
|
err:
|
||||||
|
@ -8,6 +8,7 @@ idf_component_mock(INCLUDE_DIRS "${original_usb_dir}/include"
|
|||||||
"${original_usb_dir}/include/esp_private"
|
"${original_usb_dir}/include/esp_private"
|
||||||
"${original_usb_dir}/include/usb"
|
"${original_usb_dir}/include/usb"
|
||||||
"${original_usb_dir}/private_include"
|
"${original_usb_dir}/private_include"
|
||||||
|
"include"
|
||||||
MOCK_HEADER_FILES ${original_usb_dir}/include/usb/usb_host.h
|
MOCK_HEADER_FILES ${original_usb_dir}/include/usb/usb_host.h
|
||||||
${original_usb_dir}/include/esp_private/usb_phy.h
|
${original_usb_dir}/include/esp_private/usb_phy.h
|
||||||
REQUIRES freertos)
|
REQUIRES freertos)
|
||||||
@ -16,3 +17,8 @@ idf_component_mock(INCLUDE_DIRS "${original_usb_dir}/include"
|
|||||||
# We do not mock usb_helpers. We use the original implementation.
|
# We do not mock usb_helpers. We use the original implementation.
|
||||||
# This way, we can test Class drivers descriptor parsing
|
# This way, we can test Class drivers descriptor parsing
|
||||||
target_sources(${COMPONENT_LIB} PRIVATE "${original_usb_dir}/usb_helpers.c")
|
target_sources(${COMPONENT_LIB} PRIVATE "${original_usb_dir}/usb_helpers.c")
|
||||||
|
# Original implementation of usb_private.c to allocate memory for transfers
|
||||||
|
target_sources(${COMPONENT_LIB} PRIVATE "${original_usb_dir}/usb_private.c")
|
||||||
|
|
||||||
|
# Add the extra src files for USB device mocking
|
||||||
|
target_sources(${COMPONENT_LIB} PRIVATE "mock_add_usb_device.c")
|
||||||
|
294
tools/mocks/usb/include/mock_add_usb_device.h
Normal file
294
tools/mocks/usb/include/mock_add_usb_device.h
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "usb_host.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add mocked USB device to device list
|
||||||
|
*
|
||||||
|
* @param[in] dev_address device address
|
||||||
|
* @param[in] dev_desc device descriptor
|
||||||
|
* @param[in] config_desc configuration descriptor
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Mocked device added successfully
|
||||||
|
* - ESP_ERR_INVALID_ARG: Invalid input argument(s)
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_mock_add_device(uint8_t dev_address, const usb_device_desc_t *dev_desc, const usb_config_desc_t *config_desc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get number of mocked USB devices in device list
|
||||||
|
*
|
||||||
|
* @return number of devices in devices list
|
||||||
|
*/
|
||||||
|
int usb_host_mock_get_devs_count(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Print mocked devices info
|
||||||
|
* @note if 0xFF is passed as dev_address, function prints all the mocked devices
|
||||||
|
*
|
||||||
|
* - printf all info about mocked device(s)
|
||||||
|
* - device handler, device address, opened status, device descriptor, configuration descriptor
|
||||||
|
*
|
||||||
|
* @param[in] dev_address device address (if 0xFF is passed as dev_address, function prints all the mocked devices)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Mocked device found and info printed
|
||||||
|
* - ESP_ERR_INVALID_SIZE: Mocked devices list empty
|
||||||
|
* - ESP_ERR_INVALID_ARG: Mocked device does not exist at the provided address
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_mock_print_mocked_devices(uint8_t dev_address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize mocked devices list before use
|
||||||
|
*/
|
||||||
|
void usb_host_mock_dev_list_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get Mocked device config descriptor by address
|
||||||
|
*
|
||||||
|
* @param[in] dev_address device address
|
||||||
|
* @param[in] config_desc configuration descriptor
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Configuration descriptor successfully provided
|
||||||
|
* - ESP_ERR_INVALID_ARG: Invalid input argument(s), or Mocked device does not exist at the provided address
|
||||||
|
* - ESP_ERR_INVALID_SIZE: Mocked devices list empty
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_mock_get_config_descriptor_by_address(uint8_t dev_address, const usb_config_desc_t **config_desc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get Mocked device device descriptor by address
|
||||||
|
*
|
||||||
|
* @param[in] dev_address device address
|
||||||
|
* @param[in] config_desc device descriptor
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Device descriptor successfully provided
|
||||||
|
* - ESP_ERR_INVALID_ARG: Invalid input argument(s), or Mocked device does not exist at the provided address
|
||||||
|
* - ESP_ERR_INVALID_SIZE: Mocked devices list empty
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_mock_get_device_descriptor_by_address(uint8_t dev_address, const usb_device_desc_t **device_desc);
|
||||||
|
|
||||||
|
// ------------------------------------------------- CMock callback functions ------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate a transfer object
|
||||||
|
* @note CMock callback function, registered to usb_host_transfer_alloc()
|
||||||
|
*
|
||||||
|
* @param[in] data_buffer_size Size of the transfer's data buffer
|
||||||
|
* @param[in] num_isoc_packets Number of isochronous packets in transfer (set to 0 for non-isochronous transfers)
|
||||||
|
* @param[out] transfer Transfer object
|
||||||
|
* @param[out] call_count Call count of the callback function (CMock mandatory argument)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Transfer object allocated successfully
|
||||||
|
* - ESP_ERR_NO_MEM: Insufficient memory
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_transfer_alloc_mock_callback(size_t data_buffer_size, int num_isoc_packets, usb_transfer_t **transfer, int call_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free a transfer object
|
||||||
|
* @note CMock callback function, registered to usb_host_transfer_free()
|
||||||
|
*
|
||||||
|
* @param[in] transfer Transfer object
|
||||||
|
* @param[out] call_count Call count of the callback function (CMock mandatory argument)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Transfer object freed successfully
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_transfer_free_mock_callback(usb_transfer_t *transfer, int call_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register Mocked USB Host client
|
||||||
|
* @note CMock callback function, registered to usb_host_client_register()
|
||||||
|
*
|
||||||
|
* @param[in] client_config USB Host client config
|
||||||
|
* @param[out] client_hdl_ret USB Host client handle
|
||||||
|
* @param[out] call_count Call count of the callback function (CMock mandatory argument)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Client registered successfully
|
||||||
|
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||||
|
* - ESP_ERR_NO_MEM: Insufficient memory
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_client_register_mock_callback(const usb_host_client_config_t *client_config, usb_host_client_handle_t *client_hdl_ret, int call_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mocked USB Host Library client processing function
|
||||||
|
* @note CMock callback function, registered to usb_host_client_handle_events()
|
||||||
|
*
|
||||||
|
* - This function just blocks indefinitely, so the cdc_acm_client_task() does not loop
|
||||||
|
* - If we only had usb_host_client_handle_events_ExpectAnyArgsAndReturn(ESP_OK) instead of this callback, the cdc_acm_client_task() would loop infinitely
|
||||||
|
* - The only event implemented (for now) is client unblock, while uninstalling CDC-ACM driver
|
||||||
|
*
|
||||||
|
* @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
|
||||||
|
* @param[out] call_count Call count of the callback function (CMock mandatory argument)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: No event to be handled
|
||||||
|
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||||
|
* - ESP_ERR_TIMEOUT: Semaphore waiting for events has timed out
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_client_handle_events_mock_callback(usb_host_client_handle_t client_hdl, TickType_t timeout_ticks, int call_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unblock a Mocked client
|
||||||
|
* @note CMock callback function, registered to usb_host_client_unblock()
|
||||||
|
*
|
||||||
|
* @param[in] client_hdl Client handle
|
||||||
|
* @param[out] call_count Call count of the callback function (CMock mandatory argument)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Client unblocked successfully
|
||||||
|
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_client_unblock_mock_callback(usb_host_client_handle_t client_hdl, int call_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deregister a Mocked client
|
||||||
|
* @note CMock callback function, registered to usb_host_client_deregister()
|
||||||
|
*
|
||||||
|
* @param[in] client_hdl Client handle
|
||||||
|
* @param[out] call_count Call count of the callback function (CMock mandatory argument)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Client deregistered successfully
|
||||||
|
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_client_deregister_mock_callback(usb_host_client_handle_t client_hdl, int call_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Open a device
|
||||||
|
* @note CMock callback function, registered to usb_host_device_open()
|
||||||
|
*
|
||||||
|
* @param[in] client_hdl Client handle
|
||||||
|
* @param[in] dev_address Device's address
|
||||||
|
* @param[out] dev_hdl_ret Device's handle
|
||||||
|
* @param[out] call_count Call count of the callback function (CMock mandatory argument)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Device opened successfully
|
||||||
|
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||||
|
* - ESP_ERR_NOT_FOUND: Device with specified dev_address not found
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_device_open_mock_callback(usb_host_client_handle_t client_hdl, uint8_t dev_address, usb_device_handle_t *dev_hdl_ret, int call_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Close a device
|
||||||
|
* @note CMock callback function, registered to usb_host_device_close()
|
||||||
|
*
|
||||||
|
* @param[in] client_hdl Client handle
|
||||||
|
* @param[in] dev_hdl Device's handle
|
||||||
|
* @param[out] call_count Call count of the callback function (CMock mandatory argument)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Device closed successfully
|
||||||
|
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||||
|
* - ESP_ERR_INVALID_STATE: Device was never opened
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_device_close_mock_callback(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, int call_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Fill a list of device address
|
||||||
|
* @note CMock callback function, registered to usb_host_device_addr_list_fill()
|
||||||
|
*
|
||||||
|
* @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
|
||||||
|
* @param[out] call_count Call count of the callback function (CMock mandatory argument)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Device list filled successfully
|
||||||
|
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_device_addr_list_fill_mock_callback(int list_len, uint8_t *dev_addr_list, int *num_dev_ret, int call_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get device's device descriptor
|
||||||
|
* @note CMock callback function, registered to usb_host_get_device_descriptor()
|
||||||
|
*
|
||||||
|
* @param[in] dev_hdl Device handle
|
||||||
|
* @param[out] device_desc Device descriptor
|
||||||
|
* @param[out] call_count Call count of the callback function (CMock mandatory argument)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Device descriptor obtained successfully
|
||||||
|
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_get_device_descriptor_mock_callback(usb_device_handle_t dev_hdl, const usb_device_desc_t **device_desc, int call_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get device's active configuration descriptor
|
||||||
|
* @note CMock callback function, registered to usb_host_get_active_config_descriptor()
|
||||||
|
*
|
||||||
|
* @param[in] dev_hdl Device handle
|
||||||
|
* @param[out] config_desc Configuration descriptor
|
||||||
|
* @param[out] call_count Call count of the callback function (CMock mandatory argument)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Active configuration descriptor obtained successfully
|
||||||
|
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_get_active_config_descriptor_mock_callback(usb_device_handle_t dev_hdl, const usb_config_desc_t **config_desc, int call_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Submit data transfer successfully
|
||||||
|
* @note CMock callback function, registered to usb_host_transfer_submit()
|
||||||
|
*
|
||||||
|
* Transfer callback is called, transfer status marked as completed, correct number of transferred bytes
|
||||||
|
*
|
||||||
|
* @param[in] transfer Pointer to USB transfer
|
||||||
|
* @param[out] call_count Call count of the callback function (CMock mandatory argument)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Transfer submitted
|
||||||
|
* - ESP_ERR_INVALID_ARG: Invalid input argument
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_transfer_submit_success_mock_callback(usb_transfer_t *transfer, int call_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Submit data transfer, but fail to deliver
|
||||||
|
* @note CMock callback function, registered to usb_host_transfer_submit()
|
||||||
|
*
|
||||||
|
* Transfer callback is called, transfer status marked as error, incorrect number of transferred bytes
|
||||||
|
*
|
||||||
|
* @param[in] transfer Pointer to USB transfer
|
||||||
|
* @param[out] call_count Call count of the callback function (CMock mandatory argument)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Transfer submitted
|
||||||
|
* - ESP_ERR_INVALID_ARG: Invalid input argument
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_transfer_submit_invalid_response_mock_callback(usb_transfer_t *transfer, int call_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Submit data transfer, time the transfer out
|
||||||
|
* @note CMock callback function, registered to usb_host_transfer_submit()
|
||||||
|
*
|
||||||
|
* Transfer callback is not called, because transfer timeout is not implemented in the USB Host Library
|
||||||
|
*
|
||||||
|
* @param[in] transfer Pointer to USB transfer
|
||||||
|
* @param[out] call_count Call count of the callback function (CMock mandatory argument)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Transfer submitted
|
||||||
|
* - ESP_ERR_INVALID_ARG: Invalid input argument
|
||||||
|
*/
|
||||||
|
esp_err_t usb_host_transfer_submit_timeout_mock_callback(usb_transfer_t *transfer, int call_count);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -5,3 +5,4 @@
|
|||||||
- return_thru_ptr
|
- return_thru_ptr
|
||||||
- ignore
|
- ignore
|
||||||
- ignore_arg
|
- ignore_arg
|
||||||
|
- callback
|
||||||
|
376
tools/mocks/usb/mock_add_usb_device.c
Normal file
376
tools/mocks/usb/mock_add_usb_device.c
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "usb_private.h"
|
||||||
|
#include "usb/usb_types_ch9.h"
|
||||||
|
#include "mock_add_usb_device.h"
|
||||||
|
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define MOCK_CHECK(cond, ret_val) ({ \
|
||||||
|
if (!(cond)) { \
|
||||||
|
return (ret_val); \
|
||||||
|
} \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define MOCK_CHECK_EMPTY_DEV_LIST ({ \
|
||||||
|
if (!mocked_devices_count) { \
|
||||||
|
ESP_LOGW(MOCK_TAG, "Mocked devices list empty"); \
|
||||||
|
return ESP_ERR_INVALID_SIZE; \
|
||||||
|
} \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define MAX_DEV_COUNT 128
|
||||||
|
#define IS_VALID_ADDRESS(address) ((address) != 0xFF)
|
||||||
|
#define IS_EMPTY_ADDRESS(address) ((address) == 0xFF)
|
||||||
|
|
||||||
|
|
||||||
|
const char *MOCK_TAG_CB = "USB MOCK CB"; // Tag for callback functions
|
||||||
|
const char *MOCK_TAG = "USB MOCK"; // Tag for the rest of the functions
|
||||||
|
|
||||||
|
typedef struct client_s client_t;
|
||||||
|
struct client_s {
|
||||||
|
struct {
|
||||||
|
SemaphoreHandle_t event_sem;
|
||||||
|
} constant;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mocked devices structure
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
int address; /*!< Device address */
|
||||||
|
unsigned opened; /*!< Device opened status */
|
||||||
|
const usb_device_desc_t *dev_desc; /*!< Device descriptor */
|
||||||
|
const usb_config_desc_t *config_desc; /*!< Config descriptor */
|
||||||
|
} device_list_t;
|
||||||
|
|
||||||
|
static device_list_t device_list[MAX_DEV_COUNT];
|
||||||
|
static unsigned mocked_devices_count = 0;
|
||||||
|
|
||||||
|
|
||||||
|
void usb_host_mock_dev_list_init(void)
|
||||||
|
{
|
||||||
|
for(int index = 0; index < MAX_DEV_COUNT; index++) {
|
||||||
|
device_list[index].address = 0xFF;
|
||||||
|
device_list[index].opened = 0;
|
||||||
|
device_list[index].dev_desc = NULL;
|
||||||
|
device_list[index].config_desc = NULL;
|
||||||
|
}
|
||||||
|
mocked_devices_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_host_mock_get_devs_count(void)
|
||||||
|
{
|
||||||
|
return mocked_devices_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t usb_host_mock_add_device(uint8_t dev_address, const usb_device_desc_t *dev_desc, const usb_config_desc_t *config_desc)
|
||||||
|
{
|
||||||
|
MOCK_CHECK(dev_address < MAX_DEV_COUNT && dev_desc != NULL && config_desc != NULL, ESP_ERR_INVALID_ARG);
|
||||||
|
|
||||||
|
// Increase mocked_devices_count, only for new device addresses
|
||||||
|
if (IS_EMPTY_ADDRESS(device_list[dev_address].address)) {
|
||||||
|
mocked_devices_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill device_list with new device parameters
|
||||||
|
device_list[dev_address].address = dev_address;
|
||||||
|
device_list[dev_address].opened = 0;
|
||||||
|
device_list[dev_address].dev_desc = dev_desc;
|
||||||
|
device_list[dev_address].config_desc = config_desc;
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Print devices from device_list by index
|
||||||
|
*
|
||||||
|
* @param[in] index device index
|
||||||
|
*/
|
||||||
|
static void _print_mocked_device(int index)
|
||||||
|
{
|
||||||
|
ESP_LOGI(MOCK_TAG, "Device handle = %p", (void*)(&device_list[index]));
|
||||||
|
ESP_LOGI(MOCK_TAG, "Device address = %d", device_list[index].address);
|
||||||
|
ESP_LOGI(MOCK_TAG, "Device opened by = %d clients", device_list[index].opened);
|
||||||
|
|
||||||
|
usb_print_device_descriptor(device_list[index].dev_desc);
|
||||||
|
usb_print_config_descriptor(device_list[index].config_desc, NULL);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t usb_host_mock_print_mocked_devices(uint8_t dev_address)
|
||||||
|
{
|
||||||
|
MOCK_CHECK_EMPTY_DEV_LIST;
|
||||||
|
|
||||||
|
// dev_address is 0xFF, print all devices from device_list
|
||||||
|
if (IS_EMPTY_ADDRESS(dev_address)) {
|
||||||
|
for(int index = 0; index < MAX_DEV_COUNT; index++) {
|
||||||
|
if(IS_VALID_ADDRESS(device_list[index].address)) {
|
||||||
|
_print_mocked_device(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Print only device at dev_address
|
||||||
|
} else {
|
||||||
|
if (IS_VALID_ADDRESS(device_list[dev_address].address)) {
|
||||||
|
_print_mocked_device(dev_address);
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(MOCK_TAG, "Mocked device at address %d does not exist", dev_address);
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t usb_host_mock_get_device_descriptor_by_address(uint8_t dev_address, const usb_device_desc_t **device_desc)
|
||||||
|
{
|
||||||
|
MOCK_CHECK(device_desc != NULL && dev_address < MAX_DEV_COUNT, ESP_ERR_INVALID_ARG);
|
||||||
|
ESP_LOGD(MOCK_TAG_CB, "Get device descriptor by device address");
|
||||||
|
MOCK_CHECK_EMPTY_DEV_LIST;
|
||||||
|
|
||||||
|
if (IS_VALID_ADDRESS(device_list[dev_address].address)) {
|
||||||
|
*device_desc = device_list[dev_address].dev_desc;
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(MOCK_TAG, "Mocked device at address %d does not exist", dev_address);
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t usb_host_mock_get_config_descriptor_by_address(uint8_t dev_address, const usb_config_desc_t **config_desc)
|
||||||
|
{
|
||||||
|
MOCK_CHECK(config_desc != NULL && dev_address < MAX_DEV_COUNT, ESP_ERR_INVALID_ARG);
|
||||||
|
ESP_LOGD(MOCK_TAG_CB, "Get configuration descriptor by device address");
|
||||||
|
MOCK_CHECK_EMPTY_DEV_LIST;
|
||||||
|
|
||||||
|
if (IS_VALID_ADDRESS(device_list[dev_address].address)) {
|
||||||
|
*config_desc = device_list[dev_address].config_desc;
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(MOCK_TAG, "Mocked device at address %d does not exist", dev_address);
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------- CMock callback functions ------------------------------------------
|
||||||
|
|
||||||
|
esp_err_t usb_host_transfer_alloc_mock_callback(size_t data_buffer_size, int num_isoc_packets, usb_transfer_t **transfer, int call_count)
|
||||||
|
{
|
||||||
|
urb_t *urb = urb_alloc(data_buffer_size, num_isoc_packets);
|
||||||
|
if (urb == NULL) {
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
*transfer = &urb->transfer;
|
||||||
|
|
||||||
|
ESP_LOGD(MOCK_TAG_CB, "New transfer allocated: %p", *transfer);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t usb_host_transfer_free_mock_callback(usb_transfer_t *transfer, int call_count)
|
||||||
|
{
|
||||||
|
if (transfer == NULL) {
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGD(MOCK_TAG_CB, "Transfer freed: %p", transfer);
|
||||||
|
urb_t *urb = __containerof(transfer, urb_t, transfer);
|
||||||
|
urb_free(urb);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t usb_host_client_register_mock_callback(const usb_host_client_config_t *client_config, usb_host_client_handle_t *client_hdl_ret, int call_count)
|
||||||
|
{
|
||||||
|
MOCK_CHECK(client_config != NULL && client_hdl_ret != NULL, ESP_ERR_INVALID_ARG);
|
||||||
|
|
||||||
|
esp_err_t ret;
|
||||||
|
// Create client object
|
||||||
|
client_t *client_obj = (client_t*)calloc(1, sizeof(client_t));
|
||||||
|
SemaphoreHandle_t event_sem = xSemaphoreCreateBinary();
|
||||||
|
if (client_obj == NULL || event_sem == NULL) {
|
||||||
|
ret = ESP_ERR_NO_MEM;
|
||||||
|
goto alloc_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
client_obj->constant.event_sem = event_sem;
|
||||||
|
|
||||||
|
ESP_LOGD(MOCK_TAG_CB, "USB Host client registered");
|
||||||
|
|
||||||
|
// Write back client handle
|
||||||
|
*client_hdl_ret = (usb_host_client_handle_t)client_obj;
|
||||||
|
ret = ESP_OK;
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
alloc_err:
|
||||||
|
if (event_sem) {
|
||||||
|
vSemaphoreDelete(event_sem);
|
||||||
|
}
|
||||||
|
free(client_obj);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t usb_host_client_handle_events_mock_callback(usb_host_client_handle_t client_hdl, TickType_t timeout_ticks, int call_count)
|
||||||
|
{
|
||||||
|
MOCK_CHECK(client_hdl != NULL, ESP_ERR_INVALID_ARG);
|
||||||
|
esp_err_t ret = (timeout_ticks == 0) ? ESP_OK : ESP_ERR_TIMEOUT; // We don't want to return ESP_ERR_TIMEOUT if we aren't blocking
|
||||||
|
client_t *client_obj = (client_t *)client_hdl;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
// Loop until there are no more events
|
||||||
|
if (xSemaphoreTake(client_obj->constant.event_sem, timeout_ticks) == pdFALSE) {
|
||||||
|
// Timed out waiting for semaphore or currently no events
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ESP_OK;
|
||||||
|
// Set timeout_ticks to 0 so that we can check for events again without blocking
|
||||||
|
timeout_ticks = 0;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t usb_host_client_unblock_mock_callback(usb_host_client_handle_t client_hdl, int call_count)
|
||||||
|
{
|
||||||
|
MOCK_CHECK(client_hdl != NULL, ESP_ERR_INVALID_ARG);
|
||||||
|
client_t *client_obj = (client_t *)client_hdl;
|
||||||
|
xSemaphoreGive(client_obj->constant.event_sem);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t usb_host_client_deregister_mock_callback(usb_host_client_handle_t client_hdl, int call_count)
|
||||||
|
{
|
||||||
|
MOCK_CHECK(client_hdl != NULL, ESP_ERR_INVALID_ARG);
|
||||||
|
client_t *client_obj = (client_t *)client_hdl;
|
||||||
|
|
||||||
|
vSemaphoreDelete(client_obj->constant.event_sem);
|
||||||
|
free(client_obj);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t usb_host_device_open_mock_callback(usb_host_client_handle_t client_hdl, uint8_t dev_address, usb_device_handle_t *dev_hdl_ret, int call_count)
|
||||||
|
{
|
||||||
|
MOCK_CHECK(dev_address < MAX_DEV_COUNT && client_hdl != NULL && dev_hdl_ret != NULL, ESP_ERR_INVALID_ARG);
|
||||||
|
// Find a device in dev_list by dev_address
|
||||||
|
for (int index = 0; index < MAX_DEV_COUNT; index++) {
|
||||||
|
if(device_list[index].address == dev_address) {
|
||||||
|
|
||||||
|
// We should check, if the device has not been opened by the same client
|
||||||
|
// But we are keeping this mock implementation simple
|
||||||
|
|
||||||
|
// Device found in dev_list
|
||||||
|
*dev_hdl_ret = (usb_device_handle_t)(&device_list[index]);
|
||||||
|
device_list[index].opened++;
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Device not found
|
||||||
|
ESP_LOGW(MOCK_TAG_CB, "Device not found: dev_address = %d", dev_address);
|
||||||
|
return ESP_ERR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t usb_host_device_close_mock_callback(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, int call_count)
|
||||||
|
{
|
||||||
|
MOCK_CHECK(dev_hdl != NULL && client_hdl != NULL, ESP_ERR_INVALID_ARG);
|
||||||
|
device_list_t* current_device = (device_list_t *) dev_hdl;
|
||||||
|
|
||||||
|
if (current_device->opened == 0) {
|
||||||
|
// Device was never opened
|
||||||
|
ESP_LOGW(MOCK_TAG_CB, "Device was never opened: dev_address = %d", current_device->address);
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should also check, if the device has been opened by this client
|
||||||
|
// But we are keeping this mock implementation simple
|
||||||
|
|
||||||
|
// Closing the device
|
||||||
|
current_device->opened--;
|
||||||
|
ESP_LOGD(MOCK_TAG_CB, "Device closed: dev_address = %d, dev_hdl = %p", current_device->address, current_device);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t usb_host_device_addr_list_fill_mock_callback(int list_len, uint8_t *dev_addr_list, int *num_dev_ret, int call_count)
|
||||||
|
{
|
||||||
|
MOCK_CHECK(dev_addr_list != NULL && num_dev_ret != NULL, ESP_ERR_INVALID_ARG);
|
||||||
|
|
||||||
|
int found_devices_count = 0;
|
||||||
|
for (int index = 0; index < MAX_DEV_COUNT; index++) {
|
||||||
|
if(IS_VALID_ADDRESS(device_list[index].address) && (found_devices_count < list_len)) {
|
||||||
|
dev_addr_list[found_devices_count++] = device_list[index].address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just print found devices
|
||||||
|
ESP_LOGD(MOCK_TAG_CB, "%d USB Devices found", found_devices_count);
|
||||||
|
for (int i = 0; i < found_devices_count; i++) {
|
||||||
|
ESP_LOGD(MOCK_TAG_CB, "dev_addr_list[%d] = %d", i, dev_addr_list[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
*num_dev_ret = found_devices_count;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t usb_host_get_device_descriptor_mock_callback(usb_device_handle_t dev_hdl, const usb_device_desc_t **device_desc, int call_count)
|
||||||
|
{
|
||||||
|
MOCK_CHECK(dev_hdl != NULL && device_desc != NULL, ESP_ERR_INVALID_ARG);
|
||||||
|
ESP_LOGD(MOCK_TAG_CB, "Get device descriptor");
|
||||||
|
|
||||||
|
const device_list_t* current_device = (const device_list_t *) dev_hdl;
|
||||||
|
*device_desc = current_device->dev_desc;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t usb_host_get_active_config_descriptor_mock_callback(usb_device_handle_t dev_hdl, const usb_config_desc_t **config_desc, int call_count)
|
||||||
|
{
|
||||||
|
MOCK_CHECK(dev_hdl != NULL && config_desc != NULL, ESP_ERR_INVALID_ARG);
|
||||||
|
ESP_LOGD(MOCK_TAG_CB, "Get active config descriptor");
|
||||||
|
|
||||||
|
const device_list_t* current_device = (const device_list_t *) dev_hdl;
|
||||||
|
*config_desc = current_device->config_desc;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t usb_host_transfer_submit_success_mock_callback(usb_transfer_t *transfer, int call_count)
|
||||||
|
{
|
||||||
|
MOCK_CHECK(transfer != NULL, ESP_ERR_INVALID_ARG);
|
||||||
|
// Check that transfer and target endpoint are valid
|
||||||
|
MOCK_CHECK(transfer->device_handle != NULL, ESP_ERR_INVALID_ARG); // Target device must be set
|
||||||
|
MOCK_CHECK((transfer->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK) != 0, ESP_ERR_INVALID_ARG);
|
||||||
|
transfer->callback(transfer);
|
||||||
|
transfer->status = USB_TRANSFER_STATUS_COMPLETED;
|
||||||
|
transfer->actual_num_bytes = transfer->num_bytes;
|
||||||
|
ESP_LOGD(MOCK_TAG_CB, "Mocked transfer submitted, buff len: %d, buff: %s", transfer->num_bytes, transfer->data_buffer);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t usb_host_transfer_submit_invalid_response_mock_callback(usb_transfer_t *transfer, int call_count)
|
||||||
|
{
|
||||||
|
MOCK_CHECK(transfer != NULL, ESP_ERR_INVALID_ARG);
|
||||||
|
// Check that transfer and target endpoint are valid
|
||||||
|
MOCK_CHECK(transfer->device_handle != NULL, ESP_ERR_INVALID_ARG); // Target device must be set
|
||||||
|
MOCK_CHECK((transfer->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK) != 0, ESP_ERR_INVALID_ARG);
|
||||||
|
transfer->callback(transfer);
|
||||||
|
transfer->status = USB_TRANSFER_STATUS_ERROR;
|
||||||
|
transfer->actual_num_bytes = 0;
|
||||||
|
ESP_LOGD(MOCK_TAG_CB, "Mocked transfer submitted, buff len: %d, buff: %s", transfer->num_bytes, transfer->data_buffer);
|
||||||
|
ESP_LOGW(MOCK_TAG_CB, "Mocked transfer error");
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t usb_host_transfer_submit_timeout_mock_callback(usb_transfer_t *transfer, int call_count)
|
||||||
|
{
|
||||||
|
MOCK_CHECK(transfer != NULL, ESP_ERR_INVALID_ARG);
|
||||||
|
// Check that transfer and target endpoint are valid
|
||||||
|
MOCK_CHECK(transfer->device_handle != NULL, ESP_ERR_INVALID_ARG); // Target device must be set
|
||||||
|
MOCK_CHECK((transfer->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK) != 0, ESP_ERR_INVALID_ARG);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user