mirror of
https://github.com/azure-rtos/usbx.git
synced 2025-01-28 07:03:07 +08:00
292 lines
7.7 KiB
C
292 lines
7.7 KiB
C
|
/* This test simulator is designed to simulate ux_hcd_ APIs for test. */
|
||
|
|
||
|
#include "tx_api.h"
|
||
|
#include "tx_thread.h"
|
||
|
|
||
|
#include "ux_api.h"
|
||
|
#include "ux_hcd_sim_host.h"
|
||
|
|
||
|
#include "ux_test_utility_sim.h"
|
||
|
#include "ux_test_hcd_sim_host.h"
|
||
|
|
||
|
void test_control_return(UINT status);
|
||
|
|
||
|
ULONG ux_test_port_status = UX_PS_CCS | UX_PS_DS_FS;
|
||
|
|
||
|
/* We have a no wait version because in a real world scenario, there is no waiting. */
|
||
|
VOID ux_test_hcd_sim_host_disconnect_no_wait(VOID)
|
||
|
{
|
||
|
|
||
|
UINT status;
|
||
|
UX_HCD *hcd = &_ux_system_host -> ux_system_host_hcd_array[0];
|
||
|
UX_HCD_SIM_HOST *hcd_sim_host = hcd -> ux_hcd_controller_hardware;
|
||
|
|
||
|
|
||
|
/* Port is disconnected. */
|
||
|
ux_test_port_status = 0;
|
||
|
if (hcd_sim_host != UX_NULL)
|
||
|
{
|
||
|
#if !defined(UX_HOST_STANDALONE)
|
||
|
/* Don't let the timer function run, or else the HCD thread will perform transfer requests. */
|
||
|
status = tx_timer_deactivate(&hcd_sim_host -> ux_hcd_sim_host_timer);
|
||
|
if (status != TX_SUCCESS)
|
||
|
{
|
||
|
|
||
|
printf("test_hcd_sim_host #%d, error: %d\n", __LINE__, status);
|
||
|
test_control_return(1);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
/* Signal change on the port (HCD0.RH.PORT0). */
|
||
|
hcd -> ux_hcd_root_hub_signal[0] = 1;
|
||
|
/* Signal detach to host enum thread. */
|
||
|
_ux_host_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore);
|
||
|
}
|
||
|
|
||
|
VOID ux_test_hcd_sim_host_disconnect(VOID)
|
||
|
{
|
||
|
|
||
|
ux_test_hcd_sim_host_disconnect_no_wait();
|
||
|
|
||
|
#if defined(UX_HOST_STANDALONE)
|
||
|
{
|
||
|
UX_HCD *hcd = &_ux_system_host -> ux_system_host_hcd_array[0];
|
||
|
ULONG n_device = hcd -> ux_hcd_nb_devices;
|
||
|
for (unsigned i = 0; i < 20000; i ++)
|
||
|
{
|
||
|
ux_system_tasks_run();
|
||
|
if (hcd -> ux_hcd_nb_devices == 0 ||
|
||
|
hcd -> ux_hcd_nb_devices < n_device)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
#else
|
||
|
|
||
|
/* Sleep current thread for enum thread to run. */
|
||
|
tx_thread_sleep(100);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
VOID ux_test_hcd_sim_host_connect_no_wait(ULONG speed)
|
||
|
{
|
||
|
|
||
|
UINT status;
|
||
|
UX_HCD *hcd = &_ux_system_host -> ux_system_host_hcd_array[0];
|
||
|
UX_HCD_SIM_HOST *hcd_sim_host = hcd -> ux_hcd_controller_hardware;
|
||
|
|
||
|
|
||
|
/* Connect with specific speed. */
|
||
|
switch(speed)
|
||
|
{
|
||
|
case UX_LOW_SPEED_DEVICE:
|
||
|
|
||
|
ux_test_port_status = UX_PS_CCS | UX_PS_DS_LS;
|
||
|
break;
|
||
|
|
||
|
case UX_FULL_SPEED_DEVICE:
|
||
|
|
||
|
ux_test_port_status = UX_PS_CCS | UX_PS_DS_FS;
|
||
|
break;
|
||
|
|
||
|
case UX_HIGH_SPEED_DEVICE:
|
||
|
|
||
|
ux_test_port_status = UX_PS_CCS | UX_PS_DS_HS;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
#if !defined(UX_HOST_STANDALONE)
|
||
|
/* Allow the timer function to run, or else the HCD thread won't perform transfer requests. */
|
||
|
status = tx_timer_activate(&hcd_sim_host -> ux_hcd_sim_host_timer);
|
||
|
if (status != TX_SUCCESS &&
|
||
|
/* Was the timer already active? */
|
||
|
status != TX_ACTIVATE_ERROR)
|
||
|
{
|
||
|
|
||
|
printf("test_hcd_sim_host #%d, error code: %d\n", __LINE__, status);
|
||
|
test_control_return(1);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/* Signal change on the port (HCD0.RH.PORT0). */
|
||
|
_ux_system_host -> ux_system_host_hcd_array -> ux_hcd_root_hub_signal[0] = 1;
|
||
|
/* Signal detach to host enum thread. */
|
||
|
_ux_host_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore);
|
||
|
}
|
||
|
|
||
|
VOID ux_test_hcd_sim_host_connect(ULONG speed)
|
||
|
{
|
||
|
|
||
|
ux_test_hcd_sim_host_connect_no_wait(speed);
|
||
|
|
||
|
/* Sleep current thread for enum thread to run. */
|
||
|
tx_thread_sleep(100);
|
||
|
}
|
||
|
|
||
|
/* Fork and modify _ux_hcd_sim_host_port_status_get. */
|
||
|
|
||
|
ULONG _ux_hcd_sim_host_port_status_get(UX_HCD_SIM_HOST *hcd_sim_host, ULONG port_index)
|
||
|
{
|
||
|
|
||
|
/* Check to see if this port is valid on this controller. */
|
||
|
if (hcd_sim_host -> ux_hcd_sim_host_nb_root_hubs < port_index)
|
||
|
{
|
||
|
|
||
|
/* Error trap. */
|
||
|
_ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_PORT_INDEX_UNKNOWN);
|
||
|
|
||
|
/* If trace is enabled, insert this event into the trace buffer. */
|
||
|
UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_PORT_INDEX_UNKNOWN, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0)
|
||
|
|
||
|
return(UX_PORT_INDEX_UNKNOWN);
|
||
|
}
|
||
|
|
||
|
/* Return port status. */
|
||
|
return(ux_test_port_status);
|
||
|
}
|
||
|
|
||
|
static UINT last_function = 0;
|
||
|
static char *_func_name[] = {
|
||
|
"",
|
||
|
"DISABLE_CONTROLLER",
|
||
|
"GET_PORT_STATUS",
|
||
|
"ENABLE_PORT",
|
||
|
"DISABLE_PORT",
|
||
|
"POWER_ON_PORT",
|
||
|
"POWER_DOWN_PORT",
|
||
|
"SUSPEND_PORT",
|
||
|
"RESUME_PORT",
|
||
|
"RESET_PORT",
|
||
|
"GET_FRAME_NUMBER",
|
||
|
"SET_FRAME_NUMBER",
|
||
|
"TRANSFER_REQUEST",
|
||
|
"TRANSFER_ABORT",
|
||
|
"CREATE_ENDPOINT",
|
||
|
"DESTROY_ENDPOINT",
|
||
|
"RESET_ENDPOINT",
|
||
|
"PROCESS_DONE_QUEUE"
|
||
|
};
|
||
|
|
||
|
#if 0 /* Not sure what the purpose of this is. -Nick */
|
||
|
UINT _ux_test_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter)
|
||
|
{
|
||
|
|
||
|
UINT status;
|
||
|
UCHAR act = 0;
|
||
|
UX_TRANSFER *req;
|
||
|
UX_ENDPOINT *ep;
|
||
|
TX_THREAD *this_thread;
|
||
|
UINT i;
|
||
|
UCHAR action_matched;
|
||
|
|
||
|
|
||
|
#if 0 /* TODO: Enable/disable HCD entry call display */
|
||
|
if (function != last_function)
|
||
|
{
|
||
|
last_function = function;
|
||
|
printf("\n_H %2d(%s) ", function, _func_name[function]);
|
||
|
}
|
||
|
else
|
||
|
printf(".");
|
||
|
#endif
|
||
|
|
||
|
status = ux_test_cd_handle_action(action, hcd, UX_TEST_CD_TYPE_HCD, function, parameter, &action_matched);
|
||
|
if (action_matched)
|
||
|
{
|
||
|
/* Proceed to next action */
|
||
|
action++;
|
||
|
if (action->function == 0)
|
||
|
action = UX_NULL;
|
||
|
}
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
UINT _ux_test_hcd_sim_host_dummy_entry(UX_HCD *hcd, UINT function, VOID *parameter)
|
||
|
{
|
||
|
if (function == UX_HCD_GET_PORT_STATUS)
|
||
|
/* Never connected. */
|
||
|
return 0;
|
||
|
|
||
|
return _ux_hcd_sim_host_entry(hcd, function, parameter);
|
||
|
}
|
||
|
|
||
|
UINT _ux_test_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter)
|
||
|
{
|
||
|
|
||
|
UINT status;
|
||
|
UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY_PARAMS params = { hcd, function, parameter };
|
||
|
UX_TEST_ACTION action;
|
||
|
ULONG action_taken;
|
||
|
|
||
|
/* Perform hooked callbacks. */
|
||
|
action_taken = ux_test_do_hooks_before(UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY, ¶ms);
|
||
|
if (action_taken & 0x80000000u) /* The hook breaks normal process. */
|
||
|
return(action.status);
|
||
|
|
||
|
action = ux_test_action_handler(UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY, ¶ms);
|
||
|
ux_test_do_action_before(&action, ¶ms);
|
||
|
|
||
|
if (ux_test_is_expedient_on())
|
||
|
{
|
||
|
if (action.matched && !action.do_after)
|
||
|
{
|
||
|
if (!action.no_return)
|
||
|
{
|
||
|
return action.status;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
status = _ux_hcd_sim_host_entry(hcd, function, parameter);
|
||
|
|
||
|
ux_test_do_action_after(&action, ¶ms);
|
||
|
|
||
|
if (ux_test_is_expedient_on())
|
||
|
{
|
||
|
if (action.matched && action.do_after)
|
||
|
{
|
||
|
if (!action.no_return)
|
||
|
{
|
||
|
return action.status;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Perform hooked callbacks. */
|
||
|
ux_test_do_hooks_after(UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY, ¶ms);
|
||
|
|
||
|
/* Return completion status. */
|
||
|
return(status);
|
||
|
}
|
||
|
|
||
|
UINT _ux_test_hcd_sim_host_initialize(UX_HCD *hcd)
|
||
|
{
|
||
|
UINT status;
|
||
|
|
||
|
if (ux_utility_name_match((UCHAR*)"dummy", hcd->ux_hcd_name, 5))
|
||
|
{
|
||
|
/* Use dummy halted */
|
||
|
hcd -> ux_hcd_status = UX_HCD_STATUS_DEAD; /* Must not be UX_UNUSED == UX_HCD_STATUS_HALTED */
|
||
|
hcd -> ux_hcd_entry_function = _ux_test_hcd_sim_host_dummy_entry;
|
||
|
return UX_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/* Use hcd sim host */
|
||
|
status = _ux_hcd_sim_host_initialize(hcd);
|
||
|
|
||
|
/* Redirect the entry function */
|
||
|
hcd -> ux_hcd_entry_function = _ux_test_hcd_sim_host_entry;
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
VOID ux_test_hcd_sim_host_cleanup(VOID)
|
||
|
{
|
||
|
|
||
|
ux_test_port_status = UX_PS_CCS | UX_PS_DS_FS;
|
||
|
}
|