mirror of
https://github.com/azure-rtos/usbx.git
synced 2025-01-28 07:03:07 +08:00
6ed7092b77
Add regression tests (auto triggered on PR, manually triggered in forked branch).
633 lines
21 KiB
C
633 lines
21 KiB
C
#include <stdio.h>
|
|
#include "tx_api.h"
|
|
#include "ux_api.h"
|
|
#include "ux_system.h"
|
|
#include "ux_utility.h"
|
|
#include "ux_device_stack.h"
|
|
#include "ux_host_class_hub.h"
|
|
#include "ux_host_class_dpump.h"
|
|
#include "ux_test_dcd_sim_slave.h"
|
|
#include "ux_test_hcd_sim_host.h"
|
|
#include "ux_test_utility_sim.h"
|
|
#include "ux_test.h"
|
|
#include "ux_test_actions.h"
|
|
#include "ux_device_class_dummy.h"
|
|
#include "ux_dcd_sim_slave.h"
|
|
#include "ux_device_class_dummy_hub.h"
|
|
|
|
/* Define local constants. */
|
|
|
|
#define UX_TEST_HUB_PORT_STATUS_FULL_SPEED 0x0000
|
|
|
|
#define UX_DEMO_STACK_SIZE (4*1024)
|
|
#define UX_USBX_MEMORY_SIZE (128*1024)
|
|
|
|
/* Define structs. */
|
|
|
|
typedef struct DEVICE_INIT_DATA_STRUCT
|
|
{
|
|
UCHAR *framework;
|
|
ULONG framework_length;
|
|
UCHAR *hub_descriptor;
|
|
ULONG hub_descriptor_length;
|
|
UCHAR dont_enumerate;
|
|
} DEVICE_INIT_DATA;
|
|
|
|
/* Host */
|
|
|
|
static TX_THREAD g_thread_host;
|
|
static UCHAR g_thread_stack_host[UX_DEMO_STACK_SIZE];
|
|
static UX_HOST_CLASS *g_class_driver_host;
|
|
static UX_HOST_CLASS_HUB *g_hub_host;
|
|
static UX_HOST_CLASS_HUB *g_hub_host_from_system_change_function;
|
|
static UX_HOST_CLASS_DPUMP *g_dpump_host;
|
|
static UX_HOST_CLASS_DPUMP *g_dpump_host_from_system_change_function;
|
|
|
|
static TX_THREAD g_thread_cmd;
|
|
static UCHAR g_thread_cmd_stack[UX_DEMO_STACK_SIZE];
|
|
static ULONG g_thread_cmd_cmd = 0;
|
|
#define CMD_SET_AND_SEND_PORT_EVENT_1 0 /* 1 byte port 1 change. */
|
|
#define CMD_SET_AND_SEND_PORT_EVENT_2 1 /* 2 bytes port 1 change. */
|
|
#define CMD_SET_AND_SEND_PORT_EVENT_3 2 /* 2 bytes device change | port 1 change. */
|
|
|
|
#define UX_TEST_HOST_CHANGE_LOG_N 16
|
|
static struct {
|
|
ULONG event;
|
|
UX_HOST_CLASS *class;
|
|
VOID *instance;
|
|
} g_host_change_logs[UX_TEST_HOST_CHANGE_LOG_N];
|
|
static ULONG g_host_change_count;
|
|
|
|
/* Device */
|
|
|
|
static TX_THREAD g_thread_device;
|
|
static UCHAR g_thread_stack_device[UX_DEMO_STACK_SIZE];
|
|
static UX_DEVICE_CLASS_HUB *g_hub_device;
|
|
static UX_DEVICE_CLASS_HUB_PARAMS g_hub_device_parameter;
|
|
|
|
static UCHAR g_device_can_go;
|
|
|
|
/* Define local prototypes and definitions. */
|
|
|
|
static void thread_entry_host(ULONG arg);
|
|
static void thread_entry_device(ULONG arg);
|
|
static void thread_entry_cmd(ULONG arg);
|
|
static void post_init_host();
|
|
static void post_init_device();
|
|
|
|
/* Define device framework. */
|
|
|
|
static unsigned char default_device_framework[] = {
|
|
|
|
/* Device Descriptor */
|
|
0x12, /* bLength */
|
|
0x01, /* bDescriptorType */
|
|
0x00, 0x02, /* bcdUSB */
|
|
0x09, /* bDeviceClass - Hub */
|
|
0x00, /* bDeviceSubClass */
|
|
0x01, /* bDeviceProtocol */
|
|
0x40, /* bMaxPacketSize0 */
|
|
0x24, 0x04, /* idVendor */
|
|
0x12, 0x24, /* idProduct */
|
|
0xb2, 0x0b, /* bcdDevice */
|
|
0x00, /* iManufacturer */
|
|
0x00, /* iProduct */
|
|
0x00, /* iSerialNumber */
|
|
0x01, /* bNumConfigurations */
|
|
|
|
/* Configuration Descriptor */
|
|
0x09, /* bLength */
|
|
0x02, /* bDescriptorType */
|
|
0x19, 0x00, /* wTotalLength */
|
|
0x01, /* bNumInterfaces */
|
|
0x01, /* bConfigurationValue */
|
|
0x00, /* iConfiguration */
|
|
0xe0, /* bmAttributes - Self-powered */
|
|
0x01, /* bMaxPower */
|
|
|
|
/* Interface Descriptor */
|
|
0x09, /* bLength */
|
|
0x04, /* bDescriptorType */
|
|
0x00, /* bInterfaceNumber */
|
|
0x00, /* bAlternateSetting */
|
|
0x01, /* bNumEndpoints */
|
|
0x09, /* bInterfaceClass - Hub */
|
|
0x00, /* bInterfaceSubClass */
|
|
0x00, /* bInterfaceProtocol */
|
|
0x00, /* iInterface */
|
|
|
|
/* Endpoint Descriptor */
|
|
0x07, /* bLength */
|
|
0x05, /* bDescriptorType */
|
|
0x81, /* bEndpointAddress */
|
|
0x03, /* bmAttributes - Interrupt */
|
|
0x02, 0x00, /* wMaxPacketSize */
|
|
0x0c, /* bInterval */
|
|
|
|
};
|
|
|
|
static unsigned char default_hub_descriptor[] = {
|
|
|
|
/* Hub Descriptor */
|
|
0x09, /* bLength */
|
|
0x29, /* bDescriptorType */
|
|
0x02, /* bNbrPorts */
|
|
0x09, 0x00, /* wHubCharacteristics */
|
|
0x32, /* bPwrOn2PwrGood */
|
|
0x01, /* bHubContrCurrent */
|
|
0x00, /* DeviceRemovable */
|
|
0xff, /* PortPwrCtrlMask */
|
|
|
|
};
|
|
|
|
static unsigned char string_framework[] = {
|
|
|
|
/* Manufacturer string descriptor : Index 1 - "Express Logic" */
|
|
0x09, 0x04, 0x01, 0x0c,
|
|
0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
|
|
0x6f, 0x67, 0x69, 0x63,
|
|
|
|
/* Product string descriptor : Index 2 - "EL Composite device" */
|
|
0x09, 0x04, 0x02, 0x13,
|
|
0x45, 0x4c, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
|
|
0x73, 0x69, 0x74, 0x65, 0x20, 0x64, 0x65, 0x76,
|
|
0x69, 0x63, 0x65,
|
|
|
|
/* Serial Number string descriptor : Index 3 - "0001" */
|
|
0x09, 0x04, 0x03, 0x04,
|
|
0x30, 0x30, 0x30, 0x31
|
|
};
|
|
|
|
|
|
/* Multiple languages are supported on the device, to add
|
|
a language besides english, the unicode language code must
|
|
be appended to the language_id_framework array and the length
|
|
adjusted accordingly. */
|
|
static unsigned char language_id_framework[] = {
|
|
|
|
/* English. */
|
|
0x09, 0x04
|
|
};
|
|
|
|
static UCHAR dpump_framework[] = {
|
|
|
|
/* Device descriptor */
|
|
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
|
|
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
|
|
0x03, 0x01,
|
|
|
|
/* Device qualifier descriptor */
|
|
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
|
|
0x01, 0x00,
|
|
|
|
/* Configuration descriptor */
|
|
0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xc0,
|
|
0x32,
|
|
|
|
/* Interface descriptor */
|
|
0x09, 0x04, 0x00, 0x00, 0x02, 0x99, 0x99, 0x99,
|
|
0x00,
|
|
|
|
/* Endpoint descriptor (Bulk Out) */
|
|
0x07, 0x05, 0x01, 0x02, 0x00, 0x02, 0x00,
|
|
|
|
/* Endpoint descriptor (Bulk In) */
|
|
0x07, 0x05, 0x82, 0x02, 0x00, 0x02, 0x00
|
|
};
|
|
|
|
/* This function is invoked by the simulator when the control transfer is meant
|
|
for a device on the hub. */
|
|
static UINT hub_control_request_handler(UX_SLAVE_TRANSFER *transfer_request)
|
|
{
|
|
|
|
UX_SLAVE_DCD *dcd;
|
|
UX_SLAVE_DEVICE *device;
|
|
ULONG request_type;
|
|
ULONG request;
|
|
ULONG request_value;
|
|
ULONG request_index;
|
|
ULONG request_length;
|
|
UINT status = UX_ERROR;
|
|
UCHAR *original_framework;
|
|
ULONG original_framework_length;
|
|
|
|
/* Get the pointer to the DCD. */
|
|
dcd = &_ux_system_slave -> ux_system_slave_dcd;
|
|
|
|
/* Get the pointer to the device. */
|
|
device = &_ux_system_slave -> ux_system_slave_device;
|
|
|
|
/* Ensure that the Setup request has been received correctly. */
|
|
if (transfer_request -> ux_slave_transfer_request_completion_code == UX_SUCCESS)
|
|
{
|
|
|
|
/* Seems so far, the Setup request is valid. Extract all fields of
|
|
the request. */
|
|
request_type = *transfer_request -> ux_slave_transfer_request_setup;
|
|
request = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_REQUEST);
|
|
request_value = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_VALUE);
|
|
request_index = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_INDEX);
|
|
request_length = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_LENGTH);
|
|
|
|
/* Filter for GET_DESCRIPTOR/SET_DESCRIPTOR commands. If the descriptor to be returned is not a standard descriptor,
|
|
treat the command as a CLASS command. */
|
|
if ((request == UX_GET_DESCRIPTOR || request == UX_SET_DESCRIPTOR) && (((request_value >> 8) & UX_REQUEST_TYPE) != UX_REQUEST_TYPE_STANDARD))
|
|
{
|
|
|
|
/* This request is to be handled by the class layer. */
|
|
request_type &= (UINT)~UX_REQUEST_TYPE;
|
|
request_type |= UX_REQUEST_TYPE_CLASS;
|
|
}
|
|
|
|
/* Ensure it's not vendor. */
|
|
UX_TEST_ASSERT((request_type & UX_REQUEST_TYPE) != UX_REQUEST_TYPE_VENDOR);
|
|
|
|
/* We don't support any class commands right now. */
|
|
UX_TEST_ASSERT((request_type & UX_REQUEST_TYPE) != UX_REQUEST_TYPE_CLASS);
|
|
|
|
/* Here we proceed only the standard request we know of at the device level. */
|
|
switch (request)
|
|
{
|
|
|
|
case UX_GET_STATUS:
|
|
|
|
UX_TEST_ASSERT(0);
|
|
break;
|
|
|
|
case UX_CLEAR_FEATURE:
|
|
|
|
UX_TEST_ASSERT(0);
|
|
break;
|
|
|
|
case UX_SET_FEATURE:
|
|
|
|
UX_TEST_ASSERT(0);
|
|
break;
|
|
|
|
case UX_SET_ADDRESS:
|
|
|
|
/* Don't do anything. */
|
|
break;
|
|
|
|
case UX_GET_DESCRIPTOR:
|
|
|
|
/* We need to trick USBX into sending a different framework than
|
|
the hub's. */
|
|
|
|
original_framework = _ux_system_slave->ux_system_slave_device_framework;
|
|
original_framework_length = _ux_system_slave->ux_system_slave_device_framework_length;
|
|
|
|
/* USBX sends looks here for the framework, so just change it do
|
|
our liking. */
|
|
_ux_system_slave->ux_system_slave_device_framework = dpump_framework;
|
|
_ux_system_slave->ux_system_slave_device_framework_length = sizeof(dpump_framework);
|
|
|
|
/* Kindly ask USBX to send our descriptor. */
|
|
UX_TEST_CHECK_SUCCESS(_ux_device_stack_descriptor_send(request_value, request_index, request_length));
|
|
|
|
_ux_system_slave->ux_system_slave_device_framework = original_framework;
|
|
_ux_system_slave->ux_system_slave_device_framework_length = original_framework_length;
|
|
|
|
break;
|
|
|
|
case UX_SET_DESCRIPTOR:
|
|
|
|
UX_TEST_ASSERT(0);
|
|
break;
|
|
|
|
case UX_GET_CONFIGURATION:
|
|
|
|
UX_TEST_ASSERT(0);
|
|
break;
|
|
|
|
case UX_SET_CONFIGURATION:
|
|
|
|
/* Do nothing. */
|
|
break;
|
|
|
|
case UX_GET_INTERFACE:
|
|
|
|
UX_TEST_ASSERT(0);
|
|
break;
|
|
|
|
case UX_SET_INTERFACE:
|
|
|
|
/* Do nothing. */
|
|
break;
|
|
|
|
case UX_SYNCH_FRAME:
|
|
|
|
UX_TEST_ASSERT(0);
|
|
break;
|
|
|
|
default:
|
|
|
|
UX_TEST_ASSERT(0);
|
|
return(UX_ERROR);
|
|
}
|
|
return(UX_SUCCESS);
|
|
}
|
|
return(UX_ERROR);
|
|
}
|
|
|
|
static UINT class_dpump_get(void)
|
|
{
|
|
|
|
UX_HOST_CLASS *class;
|
|
|
|
/* Find the main dpump container. */
|
|
UX_TEST_CHECK_SUCCESS(ux_host_stack_class_get(_ux_system_host_class_dpump_name, &class));
|
|
|
|
/* Get the class. */
|
|
UX_TEST_CHECK_SUCCESS(ux_test_host_stack_class_instance_get(class, 0, (void **) &g_dpump_host));
|
|
|
|
/* We still need to wait for the dpump status to be live. */
|
|
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uint(&g_dpump_host -> ux_host_class_dpump_state, UX_HOST_CLASS_INSTANCE_LIVE));
|
|
|
|
/* In virtually all cases, we want the enumeration thread to be finished. */
|
|
ux_test_wait_for_enum_thread_completion();
|
|
|
|
/* Return success. */
|
|
return(UX_SUCCESS);
|
|
}
|
|
|
|
/* Leave all the fields null. */
|
|
static DEVICE_INIT_DATA default_device_init_data;
|
|
|
|
/* Define what the initial system looks like. */
|
|
|
|
static void initialize_hub_with_device_init_data(void *first_unused_memory, DEVICE_INIT_DATA *device_init_data)
|
|
{
|
|
|
|
UCHAR *memory_pointer = (UCHAR *)first_unused_memory;
|
|
|
|
stepinfo("\n");
|
|
|
|
if (device_init_data->framework == UX_NULL)
|
|
{
|
|
device_init_data->framework = default_device_framework;
|
|
device_init_data->framework_length = sizeof(default_device_framework);
|
|
}
|
|
|
|
if (device_init_data->hub_descriptor == UX_NULL)
|
|
{
|
|
device_init_data->hub_descriptor = default_hub_descriptor;
|
|
device_init_data->hub_descriptor_length = sizeof(default_hub_descriptor);
|
|
}
|
|
|
|
/* Initialize USBX Memory. */
|
|
ux_system_initialize(memory_pointer, UX_USBX_MEMORY_SIZE, UX_NULL, 0);
|
|
memory_pointer += UX_USBX_MEMORY_SIZE;
|
|
|
|
/* It looks weird if this doesn't have a comment! */
|
|
ux_utility_error_callback_register(ux_test_error_callback);
|
|
|
|
/* Create the host thread. */
|
|
UX_TEST_CHECK_SUCCESS(tx_thread_create(&g_thread_host, "host thread", thread_entry_host, (ULONG)(ALIGN_TYPE)device_init_data,
|
|
g_thread_stack_host, UX_DEMO_STACK_SIZE,
|
|
30, 30, 1, TX_DONT_START));
|
|
UX_THREAD_EXTENSION_PTR_SET(&g_thread_host, device_init_data)
|
|
tx_thread_resume(&g_thread_host);
|
|
|
|
/* Create the slave thread. */
|
|
UX_TEST_CHECK_SUCCESS(tx_thread_create(&g_thread_device, "device thread", thread_entry_device, (ULONG)(ALIGN_TYPE)device_init_data,
|
|
g_thread_stack_device, UX_DEMO_STACK_SIZE,
|
|
30, 30, 1, TX_DONT_START));
|
|
UX_THREAD_EXTENSION_PTR_SET(&g_thread_device, device_init_data)
|
|
tx_thread_resume(&g_thread_device);
|
|
|
|
/* Create the command thread. */
|
|
UX_TEST_CHECK_SUCCESS(tx_thread_create(&g_thread_cmd, "cmd thread", thread_entry_cmd, 0,
|
|
g_thread_cmd_stack, UX_DEMO_STACK_SIZE,
|
|
30, 30, 1, TX_DONT_START));
|
|
}
|
|
|
|
static void initialize_hub(void *first_unused_memory)
|
|
{
|
|
|
|
initialize_hub_with_device_init_data(first_unused_memory, &default_device_init_data);
|
|
}
|
|
|
|
static UINT class_hub_get(void)
|
|
{
|
|
|
|
UX_HOST_CLASS *class;
|
|
|
|
|
|
/* Find the main dpump container. */
|
|
UX_TEST_CHECK_SUCCESS(ux_host_stack_class_get(_ux_system_host_class_hub_name, &class));
|
|
|
|
/* Get the class. */
|
|
UX_TEST_CHECK_SUCCESS(ux_test_host_stack_class_instance_get(class, 0, (void **) &g_hub_host));
|
|
|
|
/* We still need to wait for the dpump status to be live. */
|
|
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uint(&g_hub_host -> ux_host_class_hub_state, UX_HOST_CLASS_INSTANCE_LIVE));
|
|
|
|
/* Return success. */
|
|
return(UX_SUCCESS);
|
|
}
|
|
|
|
static VOID device_hub_instance_activate(VOID *instance)
|
|
{
|
|
g_hub_device = (UX_DEVICE_CLASS_HUB *)instance;
|
|
}
|
|
|
|
static VOID device_hub_instance_deactivate(VOID *instance)
|
|
{
|
|
g_hub_device = (UX_DEVICE_CLASS_HUB *)UX_NULL;
|
|
}
|
|
|
|
static UINT system_change_function(ULONG event, UX_HOST_CLASS *class, VOID *instance)
|
|
{
|
|
if (g_host_change_count < UX_TEST_HOST_CHANGE_LOG_N)
|
|
{
|
|
g_host_change_logs[g_host_change_count].event = event;
|
|
g_host_change_logs[g_host_change_count].class = class;
|
|
g_host_change_logs[g_host_change_count].instance = instance;
|
|
g_host_change_count ++;
|
|
}
|
|
|
|
if (class == UX_NULL)
|
|
return(UX_SUCCESS);
|
|
|
|
if (!memcmp(class->ux_host_class_name, _ux_system_host_class_hub_name, strlen(_ux_system_host_class_hub_name)))
|
|
{
|
|
if (event == UX_DEVICE_INSERTION)
|
|
{
|
|
g_hub_host_from_system_change_function = instance;
|
|
}
|
|
else if (event == UX_DEVICE_REMOVAL)
|
|
{
|
|
g_hub_host_from_system_change_function = UX_NULL;
|
|
}
|
|
}
|
|
else if (!memcmp(class->ux_host_class_name, _ux_system_host_class_dpump_name, strlen(_ux_system_host_class_dpump_name)))
|
|
{
|
|
if (event == UX_DEVICE_INSERTION)
|
|
{
|
|
g_dpump_host_from_system_change_function = instance;
|
|
}
|
|
else if (event == UX_DEVICE_REMOVAL)
|
|
{
|
|
g_dpump_host_from_system_change_function = UX_NULL;
|
|
}
|
|
}
|
|
return(UX_SUCCESS);
|
|
}
|
|
static void thread_entry_cmd(ULONG arg)
|
|
{
|
|
ULONG temp;
|
|
while(1)
|
|
{
|
|
if (g_hub_device)
|
|
{
|
|
switch(g_thread_cmd_cmd)
|
|
{
|
|
case CMD_SET_AND_SEND_PORT_EVENT_1:
|
|
_ux_device_class_hub_notify_change(g_hub_device, 1, 1);
|
|
break;
|
|
case CMD_SET_AND_SEND_PORT_EVENT_2:
|
|
_ux_device_class_hub_notify_change(g_hub_device, 1, 2);
|
|
break;
|
|
case CMD_SET_AND_SEND_PORT_EVENT_3:
|
|
temp = 0x3u;
|
|
_ux_device_class_hub_notify_changes(g_hub_device, (UCHAR*)&temp, 2);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
tx_thread_suspend(&g_thread_cmd);
|
|
}
|
|
}
|
|
static VOID set_and_send_port_event(UINT port_status, UINT port_change)
|
|
{
|
|
|
|
/* Setup the approriate fields in the hub instance. */
|
|
g_hub_device->port_status = port_status;
|
|
g_hub_device->port_change = port_change;
|
|
|
|
g_thread_cmd_cmd = CMD_SET_AND_SEND_PORT_EVENT_1;
|
|
tx_thread_resume(&g_thread_cmd);
|
|
}
|
|
|
|
static VOID connect_device_to_hub_speed(UINT speed)
|
|
{
|
|
|
|
set_and_send_port_event(speed | UX_HOST_CLASS_HUB_PORT_STATUS_CONNECTION | UX_HOST_CLASS_HUB_PORT_STATUS_POWER,
|
|
UX_HOST_CLASS_HUB_PORT_CHANGE_CONNECTION);
|
|
}
|
|
|
|
static VOID connect_device_to_hub()
|
|
{
|
|
connect_device_to_hub_speed(UX_HOST_CLASS_HUB_PORT_STATUS_HIGH_SPEED);
|
|
}
|
|
|
|
static VOID connect_device_to_hub_short_with_hub()
|
|
{
|
|
|
|
/* Setup the approriate fields in the hub instance. */
|
|
g_hub_device->port_status = UX_HOST_CLASS_HUB_PORT_STATUS_CONNECTION | UX_HOST_CLASS_HUB_PORT_STATUS_POWER;
|
|
g_hub_device->port_change = UX_HOST_CLASS_HUB_PORT_CHANGE_CONNECTION;
|
|
|
|
g_thread_cmd_cmd = CMD_SET_AND_SEND_PORT_EVENT_3;
|
|
tx_thread_resume(&g_thread_cmd);
|
|
}
|
|
|
|
static VOID disconnect_device_from_hub()
|
|
{
|
|
|
|
/* Setup the approriate fields in the hub instance. */
|
|
g_hub_device->port_status = 0; /* Make sure the connection bit is off. */
|
|
g_hub_device->port_change = UX_HOST_CLASS_HUB_PORT_CHANGE_CONNECTION;
|
|
|
|
g_thread_cmd_cmd = CMD_SET_AND_SEND_PORT_EVENT_1;
|
|
tx_thread_resume(&g_thread_cmd);
|
|
}
|
|
|
|
static void thread_entry_host(ULONG device_init_data_ptr)
|
|
{
|
|
|
|
UX_DCD_SIM_SLAVE *dcd_sim_slave;
|
|
DEVICE_INIT_DATA *device_init_data;
|
|
|
|
UX_THREAD_EXTENSION_PTR_GET(device_init_data, DEVICE_INIT_DATA, device_init_data_ptr)
|
|
|
|
/* The code below is required for installing the device portion of USBX.
|
|
In this demo, DFU is possible and we have a call back for state change. */
|
|
UX_TEST_CHECK_SUCCESS(ux_device_stack_initialize(device_init_data->framework, device_init_data->framework_length,
|
|
device_init_data->framework, device_init_data->framework_length,
|
|
string_framework, sizeof(string_framework),
|
|
language_id_framework, sizeof(language_id_framework),
|
|
UX_NULL));
|
|
|
|
g_hub_device_parameter.instance_activate = device_hub_instance_activate;
|
|
g_hub_device_parameter.instance_deactivate = device_hub_instance_deactivate;
|
|
g_hub_device_parameter.descriptor = device_init_data->hub_descriptor;
|
|
g_hub_device_parameter.descriptor_length = device_init_data->hub_descriptor_length;
|
|
|
|
/* Initialize the device hub class. */
|
|
UX_TEST_CHECK_SUCCESS(ux_device_stack_class_register(_ux_device_class_hub_name, _ux_device_class_hub_entry, 1, 0, &g_hub_device_parameter));
|
|
|
|
/* The code below is required for installing the host portion of USBX. */
|
|
UX_TEST_CHECK_SUCCESS(ux_host_stack_initialize(system_change_function));
|
|
|
|
/* Register hub class. */
|
|
UX_TEST_CHECK_SUCCESS(ux_host_stack_class_register(_ux_system_host_class_hub_name, ux_host_class_hub_entry));
|
|
|
|
#if UX_MAX_CLASS_DRIVER > 1
|
|
/* Register dpump class. */
|
|
UX_TEST_CHECK_SUCCESS(ux_host_stack_class_register(_ux_system_host_class_dpump_name, ux_host_class_dpump_entry));
|
|
#endif
|
|
|
|
/* Initialize the simulated device controller. */
|
|
UX_TEST_CHECK_SUCCESS(_ux_test_dcd_sim_slave_initialize());
|
|
|
|
/* Get the DCD sim slave. */
|
|
dcd_sim_slave = (UX_DCD_SIM_SLAVE *)_ux_system_slave->ux_system_slave_dcd.ux_slave_dcd_controller_hardware;
|
|
|
|
/* Set the hub control request handler. */
|
|
dcd_sim_slave->ux_dcd_sim_slave_dcd_control_request_process_hub = hub_control_request_handler;
|
|
|
|
if (!device_init_data->dont_enumerate)
|
|
{
|
|
|
|
/* Register all the USB host controllers available in this system. */
|
|
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
|
|
|
|
/* Sim HCD init will put() the enum thread semaphore. */
|
|
ux_test_wait_for_enum_thread_completion();
|
|
|
|
/* Get the hub instance. */
|
|
class_hub_get();
|
|
}
|
|
|
|
/* Inform device. */
|
|
g_device_can_go = 1;
|
|
|
|
/* Call application. */
|
|
post_init_host();
|
|
|
|
/* Disconnect. */
|
|
ux_test_disconnect_slave_and_host_wait_for_enum_completion();
|
|
|
|
UX_TEST_ASSERT(ux_test_check_actions_empty() == UX_TRUE);
|
|
|
|
/* And finally the usbx system resources. */
|
|
_ux_system_uninitialize();
|
|
|
|
/* Successful test. */
|
|
printf("SUCCESS!\n");
|
|
test_control_return(0);
|
|
}
|
|
|
|
static void thread_entry_device(ULONG input)
|
|
{
|
|
|
|
/* Wait for host to give us the go ahead. */
|
|
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&g_device_can_go, 1));
|
|
|
|
/* Call the application. */
|
|
post_init_device();
|
|
}
|