usbx/test/regression/usbx_ux_device_class_video_basic_tests.c
CQ Xiao 6ed7092b77
Add regression tests. (#126)
Add regression tests (auto triggered on PR, manually triggered in forked branch).
2023-11-28 15:50:39 +08:00

1179 lines
55 KiB
C

/* This test is designed to test the simple video host/device class operation. */
#include <stdio.h>
#include "tx_api.h"
#include "ux_api.h"
#include "ux_system.h"
#include "ux_utility.h"
#include "ux_hcd_sim_host.h"
#include "fx_api.h"
#include "ux_device_class_video.h"
#include "ux_device_stack.h"
#include "ux_host_class_video.h"
#include "ux_host_class_dummy.h"
#include "ux_test_dcd_sim_slave.h"
#include "ux_test_hcd_sim_host.h"
#include "ux_test_utility_sim.h"
/* Define constants. */
#define UX_DEMO_REQUEST_MAX_LENGTH \
((UX_HCD_SIM_HOST_MAX_PAYLOAD) > (UX_SLAVE_REQUEST_DATA_MAX_LENGTH) ? \
(UX_HCD_SIM_HOST_MAX_PAYLOAD) : (UX_SLAVE_REQUEST_DATA_MAX_LENGTH))
#define UX_DEMO_DEBUG_SIZE (4096*8)
#define UX_DEMO_STACK_SIZE 1024
#define UX_DEMO_BUFFER_SIZE (UX_DEMO_REQUEST_MAX_LENGTH + 1)
#define UX_DEMO_MEMORY_SIZE (128*1024)
#define UX_DEMO_ENDPOINT_SIZE 480
#define UX_TEST_LOG_SIZE (64)
/* Define local/extern function prototypes. */
static void test_thread_entry(ULONG);
static TX_THREAD tx_test_thread_host_simulation;
static TX_THREAD tx_test_thread_slave_simulation;
static void tx_test_thread_host_simulation_entry(ULONG);
static void tx_test_thread_slave_simulation_entry(ULONG);
/* Define global data structures. */
static UCHAR usbx_memory[UX_DEMO_MEMORY_SIZE + (UX_DEMO_STACK_SIZE * 2)];
static UX_HOST_CLASS_DUMMY *dummy_control;
static UX_HOST_CLASS_DUMMY *dummy_tx;
static UX_HOST_CLASS_DUMMY *dummy_rx;
static UX_DEVICE_CLASS_VIDEO *device_video;
static UX_DEVICE_CLASS_VIDEO_STREAM *device_video_tx_stream;
static UX_DEVICE_CLASS_VIDEO_STREAM *device_video_rx_stream;
static UX_DEVICE_CLASS_VIDEO_PARAMETER device_video_parameter;
static UX_DEVICE_CLASS_VIDEO_STREAM_PARAMETER device_video_stream_parameter[2];
static UX_SLAVE_TRANSFER *device_video_tx_transfer;
static UX_SLAVE_TRANSFER *device_video_rx_transfer;
static UX_HOST_CLASS_VIDEO *video;
static ULONG error_counter;
static ULONG set_cfg_counter;
static ULONG rsc_mem_free_on_set_cfg;
static ULONG rsc_sem_on_set_cfg;
static ULONG rsc_sem_get_on_set_cfg;
static ULONG rsc_mutex_on_set_cfg;
static ULONG rsc_enum_sem_usage;
static ULONG rsc_enum_sem_get_count;
static ULONG rsc_enum_mutex_usage;
static ULONG rsc_enum_mem_usage;
static ULONG rsc_video_sem_usage;
static ULONG rsc_video_sem_get_count;
static ULONG rsc_video_mutex_usage;
static ULONG rsc_video_mem_usage;
static ULONG interaction_count;
static UCHAR error_callback_ignore = UX_TRUE;
static ULONG error_callback_counter;
static struct BUFFER_LOG_STRUCT {
ULONG length;
UCHAR data[256];
} buffer_log[UX_TEST_LOG_SIZE];
static ULONG buffer_log_count = 0;
#define SAVE_BUFFER_LOG(buf,siz) do { \
if (buffer_log_count < UX_TEST_LOG_SIZE) { \
ULONG __local_size__ = ((siz) > 256) ? 256 : (siz); \
buffer_log[buffer_log_count].length = (siz); \
_ux_utility_memory_copy(buffer_log[buffer_log_count].data, (buf), __local_size__); \
} \
buffer_log_count ++; \
} while(0)
static ULONG test_tx_ack_count = 0xFFFFFFFF;
static ULONG test_tx_ins_count = 0;
static ULONG test_tx_ins_way = 0;
static struct CALLBACK_INVOKE_LOG_STRUCT {
VOID *func;
VOID *param1;
VOID *param2;
VOID *param3;
} callback_invoke_log[UX_TEST_LOG_SIZE];
static ULONG callback_invoke_count = 0;
#define SAVE_CALLBACK_INVOKE_LOG(f,p1,p2,p3) do { \
if (callback_invoke_count < UX_TEST_LOG_SIZE) { \
callback_invoke_log[callback_invoke_count].func = (VOID *)(f); \
callback_invoke_log[callback_invoke_count].param1 = (VOID *)(p1); \
callback_invoke_log[callback_invoke_count].param2 = (VOID *)(p2); \
callback_invoke_log[callback_invoke_count].param3 = (VOID *)(p3); \
callback_invoke_count++; \
} \
} while(0)
#define RESET_CALLBACK_INVOKE_LOG() do { \
callback_invoke_count = 0; \
} while(0)
/* Define device framework. */
#define W(d) UX_DW0(d), UX_DW1(d)
#define DW(d) UX_DW0(d), UX_DW1(d), UX_DW2(d), UX_DW3(d)
#define _DEVICE_DESCRIPTOR() \
/* --------------------------------------- Device Descriptor */ \
/* 0 bLength, bDescriptorType */ 18, 0x01, \
/* 2 bcdUSB */ UX_DW0(0x200),UX_DW1(0x200), \
/* 4 bDeviceClass, bDeviceSubClass, bDeviceProtocol */ 0x00, 0x00, 0x00, \
/* 7 bMaxPacketSize0 */ 0x08, \
/* 8 idVendor, idProduct */ 0x84, 0x84, 0x01, 0x00, \
/* 12 bcdDevice */ UX_DW0(0x100),UX_DW1(0x100), \
/* 14 iManufacturer, iProduct, iSerialNumber */ 0, 0, 0, \
/* 17 bNumConfigurations */ 1,
#define _DEVICE_QUALIFIER_DESCRIPTOR() \
/* ----------------------------- Device Qualifier Descriptor */ \
/* 0 bLength, bDescriptorType */ 10, 0x06, \
/* 2 bcdUSB */ UX_DW0(0x200),UX_DW1(0x200), \
/* 4 bDeviceClass, bDeviceSubClass, bDeviceProtocol */ 0x00, 0x00, 0x00, \
/* 7 bMaxPacketSize0 */ 8, \
/* 8 bNumConfigurations */ 1, \
/* 9 bReserved */ 0,
#define _CONFIGURE_DESCRIPTOR(total_len,n_ifc,cfg_v) \
/* -------------------------------- Configuration Descriptor */ \
/* 0 bLength, bDescriptorType */ 9, 0x02, \
/* 2 wTotalLength */ UX_DW0(total_len),UX_DW1(total_len),\
/* 4 bNumInterfaces, bConfigurationValue */ (n_ifc), (cfg_v), \
/* 6 iConfiguration */ 0, \
/* 7 bmAttributes, bMaxPower */ 0x80, 50,
#define _IAD_DESCRIPTOR(ifc_0,ifc_cnt,cls,sub,protocol) \
/* ------------------------ Interface Association Descriptor */ \
/* 0 bLength, bDescriptorType */ 8, 0x0B, \
/* 2 bFirstInterface, bInterfaceCount */ (ifc_0), (ifc_cnt), \
/* 4 bFunctionClass, bFunctionSubClass, bFunctionProtocol */ (cls), (sub), (protocol), \
/* 7 iFunction */ 0,
#define _INTERFACE_DESCRIPTOR(ifc,alt,n_ep,cls,sub,protocol) \
/* ------------------------------------ Interface Descriptor */ \
/* 0 bLength, bDescriptorType */ 9, 0x04, \
/* 2 bInterfaceNumber, bAlternateSetting */ (ifc), (alt), \
/* 4 bNumEndpoints */ (n_ep), \
/* 5 bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol */ (cls), (sub), (protocol), \
/* 8 iInterface */ 0,
#define _ENDPOINT_DESCRIPTOR(addr,attr,pkt_siz,interval) \
/* ------------------------------------- Endpoint Descriptor */ \
/* 0 bLength, bDescriptorType */ 7, 0x05, \
/* 2 bEndpointAddress, bmAttributes */ (addr), (attr), \
/* 4 wMaxPacketSize, bInterval */ UX_DW0(pkt_siz),UX_DW1(pkt_siz),(interval),
#define _VC_DESCRIPTORS_LEN (14+17+9+17+9)
#define _VC_DESCRIPTORS() \
/*--------------------------- Class VC Interface Descriptor (VC_HEADER). */ \
14, 0x24, 0x01, W(0x150), \
W(_VC_DESCRIPTORS_LEN), /* wTotalLength. */ \
DW(6000000), /* dwClockFrequency. */ \
2, /* bInCollection. */ \
1, 2, /* BaInterfaceNr(2). */ \
/*--------------------------- Input Terminal (VC_INPUT_TERMINAL, Camera) */ \
17, 0x24, 0x02, \
0x01, /* bTerminalID, ITT_CAMERA */ \
W(0x201), /* wTerminalType */ \
0x00, 0x00, W(0), W(0), W(0), \
0x02, W(0), /* bControlSize, bmControls */ \
/*---------------------------- Output Terminal (VC_OUTPUT_TERMINAL, USB) */ \
9, 0x24, 0x03, \
0x02, /* bTerminalID */ \
W(0x0101), /* wTerminalType, TT_STREAMING */ \
0x00, 0x01/* bSourceID */, 0x00, \
/*--------------------------- Input Terminal (VC_INPUT_TERMINAL, USB) */ \
17, 0x24, 0x02, \
0x03, /* bTerminalID */ \
W(0x101), /* wTerminalType, TT_STREAMING */ \
0x00, 0x00, W(0), W(0), W(0), \
0x02, W(0), /* bControlSize, bmControls */ \
/*---------------------------- Output Terminal (VC_OUTPUT_TERMINAL, DISPLAY) */ \
9, 0x24, 0x03, \
0x04, /* bTerminalID */ \
W(0x0301), /* wTerminalType, OTT_DISPLAY */ \
0x00, 0x03/* bSourceID */, 0x00,
#if 0
/*--------------------------------- Processing Unit (VC_PROCESSING_UNIT) */ \
12, 0x24, 0x05, \
, /* bUnitID */ \
, /* bSourceID */ \
W(0), \
3 /* bControlSize */, 0, 0, 0 /*bmControls */, \
0x00, 0x00, \
/*--------------------------------- Processing Unit (VC_PROCESSING_UNIT) */ \
12, 0x24, 0x05, \
, /* bUnitID */ \
, /* bSourceID */ \
W(0), \
3 /* bControlSize */, 0, 0, 0 /*bmControls */, \
0x00, 0x00, \
#endif
#define _VS_IN_DESCRIPTORS_LEN (14+11+38)
#define _VS_IN_DESCRIPTORS() \
/*------------------------- Class VS Header Descriptor (VS_INPUT_HEADER) */ \
14, 0x24, 0x01, \
0X01, /* bNumFormats */ \
W(_VS_IN_DESCRIPTORS_LEN), /* wTotalLength */ \
0x81, /* bEndpointAddress */ \
0x00, \
0x02, /* bTerminalLink */ \
0x00, /* bStillCaptureMethod */ \
0x00, 0x00, /* bTriggerSupport, bTriggerUsage */ \
0x01, 0x00, /* bControlSize, bmaControls */ \
/*------------------------------- VS Format Descriptor (VS_FORMAT_MJPEG) */ \
11, 0x24, 0x06, \
0x01, /* bFormatIndex */ \
0x01, /* bNumFrameDescriptors */ \
0x01, /* bmFlags */ \
0x01, /* bDefaultFrameIndex */ \
0x00, 0x00, 0x00, 0x00, \
/*--------------------------------- VS Frame Descriptor (VS_FRAME_MJPEG) */ \
38, 0x24, 0x07, \
0x01, /* bFrameIndex */ \
0x03, /* bmCapabilities */ \
W(176), W(144), /* wWidth, wHeight */ \
DW(912384), DW(912384), /* dwMinBitRate, dwMaxBitRate */ \
DW(38016), /* dwMaxVideoFrameBufSize */ \
DW(666666), /* dwDefaultFrameInterval */ \
0x00, /* bFrameIntervalType */ \
DW(666666), DW(666666), DW(0), /* dwMinFrameInterval, dwMaxFrameInterval, dwFrameIntervalStep */
#define _VS_OUT_DESCRIPTORS_LEN (11+11+38)
#define _VS_OUT_DESCRIPTORS() \
/*------------------------- Class VS Header Descriptor (VS_OUTPUT_HEADER) */ \
11, 0x24, 0x02, \
0x01, /* bNumFormats */ \
W(_VS_OUT_DESCRIPTORS_LEN), /* wTotalLength */ \
0x02, /* bEndpointAddress */ \
0x00, \
0x03, /* bTerminalLink */ \
0x01, 0x00, /* bControlSize, bmaControls */ \
/*------------------------------- VS Format Descriptor (VS_FORMAT_MJPEG) */ \
11, 0x24, 0x06, \
0x01, /* bFormatIndex */ \
0x01, /* bNumFrameDescriptors */ \
0x01, /* bmFlags */ \
0x01, /* bDefaultFrameIndex */ \
0x00, 0x00, 0x00, 0x00, \
/*--------------------------------- VS Frame Descriptor (VS_FRAME_MJPEG) */ \
38, 0x24, 0x07, \
0x01, /* bFrameIndex */ \
0x03, /* bmCapabilities */ \
W(176), W(144), /* wWidth, wHeight */ \
DW(912384), DW(912384), /* dwMinBitRate, dwMaxBitRate */ \
DW(38016), /* dwMaxVideoFrameBufSize */ \
DW(666666), /* dwDefaultFrameInterval */ \
0x00, /* bFrameIntervalType */ \
DW(666666), DW(666666), DW(0), /* dwMinFrameInterval, dwMaxFrameInterval, dwFrameIntervalStep */
#define _CONFIGURE_DESCRIPTORS_LEN (9+ 8+ 9+_VC_DESCRIPTORS_LEN+ 9+_VS_IN_DESCRIPTORS_LEN+9+7+ 9+_VS_OUT_DESCRIPTORS_LEN+9+7)
static unsigned char device_framework_full_speed[] = {
_DEVICE_DESCRIPTOR()
_CONFIGURE_DESCRIPTOR(_CONFIGURE_DESCRIPTORS_LEN,3,1)
_IAD_DESCRIPTOR(0,3,0x0E,0x03,0x00)
_INTERFACE_DESCRIPTOR(0,0,0,0x0E,0x01,0x01)
_VC_DESCRIPTORS()
_INTERFACE_DESCRIPTOR(1,0,0,0x0E,0x02,0x00)
_VS_IN_DESCRIPTORS()
_INTERFACE_DESCRIPTOR(1,1,1,0x0E,0x02,0x00)
_ENDPOINT_DESCRIPTOR(0x81,0x05,UX_DEMO_ENDPOINT_SIZE,0x01)
_INTERFACE_DESCRIPTOR(2,0,0,0x0E,0x02,0x00)
_VS_OUT_DESCRIPTORS()
_INTERFACE_DESCRIPTOR(2,1,1,0x0E,0x02,0x00)
_ENDPOINT_DESCRIPTOR(0x02,0x05,UX_DEMO_ENDPOINT_SIZE,0x01)
};
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
static unsigned char device_framework_high_speed[] = {
_DEVICE_DESCRIPTOR()
_DEVICE_QUALIFIER_DESCRIPTOR()
_CONFIGURE_DESCRIPTOR(_CONFIGURE_DESCRIPTORS_LEN,3,1)
_IAD_DESCRIPTOR(0,3,0x0E,0x03,0x00)
_INTERFACE_DESCRIPTOR(0,0,0,0x0E,0x01,0x01)
_VC_DESCRIPTORS()
_INTERFACE_DESCRIPTOR(1,0,0,0x0E,0x02,0x00)
_VS_IN_DESCRIPTORS()
_INTERFACE_DESCRIPTOR(1,1,1,0x0E,0x02,0x00)
_ENDPOINT_DESCRIPTOR(0x81,0x05,UX_DEMO_ENDPOINT_SIZE,0x01)
_INTERFACE_DESCRIPTOR(2,0,0,0x0E,0x02,0x00)
_VS_OUT_DESCRIPTORS()
_INTERFACE_DESCRIPTOR(2,1,1,0x0E,0x02,0x00)
_ENDPOINT_DESCRIPTOR(0x02,0x05,UX_DEMO_ENDPOINT_SIZE,0x01)
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
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
};
#define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
/* 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
};
#define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
/* Setup requests */
static UX_TEST_SETUP _SetConfigure = UX_TEST_SETUP_SetConfigure;
static UX_TEST_SETUP _GetCfgDescr = UX_TEST_SETUP_GetCfgDescr;
static UX_TEST_SETUP _SetAddress = UX_TEST_SETUP_SetAddress;
static UX_TEST_SETUP _GetDeviceDescriptor = UX_TEST_SETUP_GetDevDescr;
static UX_TEST_SETUP _GetConfigDescriptor = UX_TEST_SETUP_GetCfgDescr;
/* Interaction define */
#ifndef ux_device_class_video_payload_write
static UINT ux_device_class_video_payload_write(UX_DEVICE_CLASS_VIDEO_STREAM *stream, UCHAR *payload, ULONG length)
{
UX_SLAVE_ENDPOINT *endpoint;
UX_SLAVE_DEVICE *device;
UCHAR *next_payload_buffer;
ULONG payload_buffer_size;
/* Get the pointer to the device. */
device = &_ux_system_slave -> ux_system_slave_device;
/* As long as the device is in the CONFIGURED state. */
if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
{
/* Cannot proceed with command, the interface is down. */
return(UX_CONFIGURATION_HANDLE_UNKNOWN);
}
/* Check if endpoint is available. */
endpoint = stream -> ux_device_class_video_stream_endpoint;
if (endpoint == UX_NULL)
return(UX_ERROR);
/* Check if endpoint direction is OK (IN). */
if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT)
return(UX_ERROR);
/* Check payload length. */
payload_buffer_size = stream -> ux_device_class_video_stream_payload_buffer_size;
if ((payload_buffer_size - 4) < length)
return(UX_ERROR);
/* Check overflow!! */
if (stream -> ux_device_class_video_stream_access_pos == stream -> ux_device_class_video_stream_transfer_pos &&
stream -> ux_device_class_video_stream_access_pos -> ux_device_class_video_payload_length != 0)
return(UX_BUFFER_OVERFLOW);
/* Calculate next payload buffer. */
next_payload_buffer = (UCHAR *)stream -> ux_device_class_video_stream_access_pos;
next_payload_buffer += payload_buffer_size;
if (next_payload_buffer >= stream -> ux_device_class_video_stream_buffer + stream -> ux_device_class_video_stream_buffer_size)
next_payload_buffer = stream -> ux_device_class_video_stream_buffer;
/* Copy payload. */
_ux_utility_memory_copy(stream -> ux_device_class_video_stream_access_pos -> ux_device_class_video_payload_data, payload, length); /* Use case of memcpy is verified. */
stream -> ux_device_class_video_stream_access_pos -> ux_device_class_video_payload_length = length;
/* Move payload position. */
stream -> ux_device_class_video_stream_access_pos = (UX_DEVICE_CLASS_VIDEO_PAYLOAD *)next_payload_buffer;
return(UX_SUCCESS);
}
#endif
/* Hooks define */
static VOID ux_device_class_video_tx_hook(struct UX_TEST_ACTION_STRUCT *action, VOID *params)
{
UX_TEST_OVERRIDE_UX_DCD_SIM_SLAVE_FUNCTION_PARAMS *p = (UX_TEST_OVERRIDE_UX_DCD_SIM_SLAVE_FUNCTION_PARAMS *)params;
UX_SLAVE_TRANSFER *transfer = (UX_SLAVE_TRANSFER *)p -> parameter;
UCHAR tmp[32] = {'i','n','s','e','r','t','A',0};
(void)params;
// printf("%s:%d tTX\n", UX_TEST_FILE, __LINE__);
/* Acknowledge payload sent. */
if (test_tx_ack_count)
{
SAVE_BUFFER_LOG(transfer -> ux_slave_transfer_request_data_pointer, transfer -> ux_slave_transfer_request_requested_length);
transfer -> ux_slave_transfer_request_actual_length = transfer -> ux_slave_transfer_request_requested_length;
transfer -> ux_slave_transfer_request_completion_code = UX_SUCCESS;
ux_test_dcd_sim_slave_transfer_done(transfer, UX_SUCCESS);
}
if (test_tx_ack_count != 0xFFFFFFFF && test_tx_ack_count > 0)
test_tx_ack_count --;
/* Insert payloads when sent. */
if (test_tx_ins_count)
{
tmp[6] = (test_tx_ins_count % 26) + 'A';
if (test_tx_ins_way == 0)
ux_device_class_video_payload_write(device_video_tx_stream, tmp, 32);
else
{
UCHAR *payload;
ULONG payload_length;
ux_device_class_video_write_payload_get(device_video_tx_stream, &payload, &payload_length);
_ux_utility_memory_copy(payload, tmp, 32);
ux_device_class_video_write_payload_commit(device_video_tx_stream, 32);
}
}
if (test_tx_ins_count != 0xFFFFFFFF && test_tx_ins_count > 0)
test_tx_ins_count --;
}
static VOID ux_device_class_video_rx_hook(struct UX_TEST_ACTION_STRUCT *action, VOID *params)
{
UX_TEST_OVERRIDE_UX_DCD_SIM_SLAVE_FUNCTION_PARAMS *p = (UX_TEST_OVERRIDE_UX_DCD_SIM_SLAVE_FUNCTION_PARAMS *)params;
UX_SLAVE_TRANSFER *transfer = (UX_SLAVE_TRANSFER *)p -> parameter;
(void)action;
(void)params;
(void)p;
(void)transfer;
// printf("tRX\n");
device_video_rx_transfer = transfer;
}
static VOID device_video_rx_simulate_one_payload(UCHAR *payload, ULONG payload_length)
{
UX_TEST_ASSERT(device_video_rx_transfer);
if (payload_length)
{
_ux_utility_memory_copy(device_video_rx_transfer->ux_slave_transfer_request_data_pointer, payload, payload_length);
device_video_rx_transfer->ux_slave_transfer_request_actual_length = payload_length;
device_video_rx_transfer->ux_slave_transfer_request_completion_code = UX_SUCCESS;
}
ux_test_dcd_sim_slave_transfer_done(device_video_rx_transfer, UX_SUCCESS);
_ux_utility_thread_sleep(1);
}
static UX_TEST_ACTION ux_device_class_video_transfer_hook[] =
{
{
.usbx_function = UX_TEST_OVERRIDE_UX_DCD_SIM_SLAVE_FUNCTION,
.function = UX_DCD_TRANSFER_REQUEST,
.action_func = ux_device_class_video_tx_hook,
.req_setup = UX_NULL,
.req_action = UX_TEST_MATCH_EP,
.req_ep_address = 0x81,
.do_after = UX_FALSE,
.no_return = UX_FALSE,
},
{
.usbx_function = UX_TEST_OVERRIDE_UX_DCD_SIM_SLAVE_FUNCTION,
.function = UX_DCD_TRANSFER_REQUEST,
.action_func = ux_device_class_video_rx_hook,
.req_setup = UX_NULL,
.req_action = UX_TEST_MATCH_EP,
.req_ep_address = 0x02,
.do_after = UX_FALSE,
.no_return = UX_FALSE,
},
{ 0 },
};
/* Define the ISR dispatch. */
extern VOID (*test_isr_dispatch)(void);
/* Prototype for test control return. */
void test_control_return(UINT status);
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
error_callback_counter ++;
// printf("Error #%d, system_level: %d, system_context: %d, error_code: 0x%x\n", __LINE__, system_level, system_context, error_code);
if (!error_callback_ignore)
{
{
/* Failed test. */
test_control_return(1);
}
}
}
static UINT sleep_break_on_error(VOID)
{
if (error_callback_counter >= 3)
return error_callback_counter;
return UX_SUCCESS;
}
/* Define the ISR dispatch routine. */
static void test_isr(void)
{
/* For further expansion of interrupt-level testing. */
}
static VOID device_video_activate(VOID *video_instance)
{
device_video = (UX_DEVICE_CLASS_VIDEO *)video_instance;
ux_device_class_video_stream_get(device_video, 0, &device_video_tx_stream);
ux_device_class_video_stream_get(device_video, 1, &device_video_rx_stream);
// printf("sVID:%p,%p,%p\n", video_instance, device_video_tx_stream, device_video_rx_stream);
}
static VOID device_video_deactivate(VOID *video_instance)
{
if ((VOID *)device_video == video_instance)
{
device_video = UX_NULL;
device_video_tx_stream = UX_NULL;
device_video_rx_stream = UX_NULL;
}
}
static VOID device_video_tx_stream_change(UX_DEVICE_CLASS_VIDEO_STREAM *video, ULONG alt)
{
SAVE_CALLBACK_INVOKE_LOG(device_video_tx_stream_change, video, (ALIGN_TYPE)alt, 0);
}
static VOID device_video_rx_stream_change(UX_DEVICE_CLASS_VIDEO_STREAM *video, ULONG alt)
{
SAVE_CALLBACK_INVOKE_LOG(device_video_rx_stream_change, video, (ALIGN_TYPE)alt, 0);
device_video_rx_transfer = UX_NULL;
}
static UINT device_video_vc_control_process(UX_DEVICE_CLASS_VIDEO *video, UX_SLAVE_TRANSFER *transfer)
{
SAVE_CALLBACK_INVOKE_LOG(device_video_vc_control_process, video, transfer, 0);
return(UX_ERROR);
}
static UINT device_video_vs_control_process(UX_DEVICE_CLASS_VIDEO_STREAM *video, UX_SLAVE_TRANSFER *transfer)
{
SAVE_CALLBACK_INVOKE_LOG(device_video_vs_control_process, video, transfer, 0);
return(UX_ERROR);
}
static VOID device_video_tx_done(UX_DEVICE_CLASS_VIDEO_STREAM *video, ULONG length)
{
SAVE_CALLBACK_INVOKE_LOG(device_video_tx_done, video, (ALIGN_TYPE)length, 0);
}
static VOID device_video_rx_done(UX_DEVICE_CLASS_VIDEO_STREAM *video, ULONG length)
{
SAVE_CALLBACK_INVOKE_LOG(device_video_rx_done, video, (ALIGN_TYPE)length, 0);
}
static UINT test_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
{
UX_HOST_CLASS_DUMMY *dummy = (UX_HOST_CLASS_DUMMY *) inst;
switch(event)
{
case UX_DEVICE_INSERTION:
// printf("hINS:%p,%p:%ld\n", cls, inst, dummy -> ux_host_class_dummy_interface -> ux_interface_descriptor.bInterfaceNumber);
switch(dummy -> ux_host_class_dummy_interface -> ux_interface_descriptor.bInterfaceNumber)
{
case 0: dummy_control = dummy; break;
case 1: dummy_rx = dummy; break;
case 2: dummy_tx = dummy; break;
}
break;
case UX_DEVICE_REMOVAL:
// printf("hRMV:%p,%p:%ld\n", cls, inst, dummy -> ux_host_class_dummy_interface -> ux_interface_descriptor.bInterfaceNumber);
switch(dummy -> ux_host_class_dummy_interface -> ux_interface_descriptor.bInterfaceNumber)
{
case 0: dummy_control = UX_NULL; break;
case 1: dummy_rx = UX_NULL; break;
case 2: dummy_tx = UX_NULL; break;
}
break;
default:
break;
}
return 0;
}
static VOID ux_test_hcd_entry_set_cfg(UX_TEST_ACTION *action, VOID *params)
{
set_cfg_counter ++;
rsc_mem_free_on_set_cfg = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
rsc_sem_on_set_cfg = ux_test_utility_sim_sem_create_count();
rsc_mutex_on_set_cfg = ux_test_utility_sim_mutex_create_count();
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_ux_device_video_basic_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
/* Inform user. */
printf("Running Video Device Basic Functionality Test....................... ");
#if !UX_TEST_MULTI_IFC_ON || !UX_TEST_MULTI_ALT_ON || !UX_TEST_MULTI_CLS_ON || \
(_CONFIGURE_DESCRIPTORS_LEN > UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH)
#warning Tests skipped due to compile option!
printf("SKIP SUCCESS!\n");
test_control_return(0);
return;
#endif
stepinfo("\n");
/* Reset testing counts. */
ux_test_utility_sim_mutex_create_count_reset();
ux_test_utility_sim_sem_create_count_reset();
ux_test_utility_sim_sem_get_count_reset();
/* Reset error generations */
ux_test_utility_sim_sem_error_generation_stop();
ux_test_utility_sim_mutex_error_generation_stop();
ux_test_utility_sim_sem_get_error_generation_stop();
/* Initialize the free memory pointer */
stack_pointer = (CHAR *) usbx_memory;
memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
/* Initialize USBX Memory */
status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL,0);
UX_TEST_CHECK_SUCCESS(status);
/* Register the error callback. */
_ux_utility_error_callback_register(error_callback);
/* The code below is required for installing the host portion of USBX */
status = ux_host_stack_initialize(test_host_change_function);
UX_TEST_CHECK_SUCCESS(status);
/* Register Audio class. */
status = ux_host_stack_class_register(_ux_host_class_dummy_name, _ux_host_class_dummy_entry);
UX_TEST_CHECK_SUCCESS(status);
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
UX_TEST_CHECK_SUCCESS(status);
/* Set the parameters for callback when insertion/extraction of a Video device, with IAD. */
#if defined(UX_DEVICE_STANDALONE)
device_video_stream_parameter[0].ux_device_class_video_stream_parameter_task_function = ux_device_class_video_write_task_function;
#else
device_video_stream_parameter[0].ux_device_class_video_stream_parameter_thread_entry = ux_device_class_video_write_thread_entry;
#endif
device_video_stream_parameter[0].ux_device_class_video_stream_parameter_callbacks.ux_device_class_video_stream_change = device_video_tx_stream_change;
device_video_stream_parameter[0].ux_device_class_video_stream_parameter_callbacks.ux_device_class_video_stream_payload_done = device_video_tx_done;
device_video_stream_parameter[0].ux_device_class_video_stream_parameter_callbacks.ux_device_class_video_stream_request = device_video_vs_control_process;
device_video_stream_parameter[0].ux_device_class_video_stream_parameter_max_payload_buffer_size = UX_DEMO_ENDPOINT_SIZE;
device_video_stream_parameter[0].ux_device_class_video_stream_parameter_max_payload_buffer_nb = 8;
#if defined(UX_DEVICE_STANDALONE)
device_video_stream_parameter[1].ux_device_class_video_stream_parameter_task_function = ux_device_class_video_read_task_function;
#else
device_video_stream_parameter[1].ux_device_class_video_stream_parameter_thread_entry = ux_device_class_video_read_thread_entry;
#endif
device_video_stream_parameter[1].ux_device_class_video_stream_parameter_callbacks.ux_device_class_video_stream_change = device_video_rx_stream_change;
device_video_stream_parameter[1].ux_device_class_video_stream_parameter_callbacks.ux_device_class_video_stream_payload_done = device_video_rx_done;
device_video_stream_parameter[1].ux_device_class_video_stream_parameter_callbacks.ux_device_class_video_stream_request = device_video_vs_control_process;
device_video_stream_parameter[1].ux_device_class_video_stream_parameter_max_payload_buffer_size = UX_DEMO_ENDPOINT_SIZE;
device_video_stream_parameter[1].ux_device_class_video_stream_parameter_max_payload_buffer_nb = 8;
device_video_parameter.ux_device_class_video_parameter_streams = device_video_stream_parameter;
device_video_parameter.ux_device_class_video_parameter_streams_nb = 2;
device_video_parameter.ux_device_class_video_parameter_callbacks.ux_slave_class_video_instance_activate = device_video_activate;
device_video_parameter.ux_device_class_video_parameter_callbacks.ux_slave_class_video_instance_deactivate = device_video_deactivate;
device_video_parameter.ux_device_class_video_parameter_callbacks.ux_device_class_video_request = device_video_vc_control_process;
device_video_parameter.ux_device_class_video_parameter_callbacks.ux_device_class_video_arg = UX_NULL;
#if 0
printf("Memory requirement UX_DEVICE_CLASS_:\n");
printf(" per _VIDEO: %d bytes\n", sizeof(UX_DEVICE_CLASS_VIDEO));
printf(" per _VIDEO_STREAM: %d bytes\n", sizeof(UX_DEVICE_CLASS_VIDEO_STREAM));
printf(" per _VIDEO_CONTROL: %d bytes\n", sizeof(UX_DEVICE_CLASS_VIDEO_CONTROL));
printf("Dynamic memory allocation:\n");
temp = (device_video_tx_stream_parameter.ux_device_class_video_stream_parameter_max_payload_buffer_size+8) *
device_video_tx_stream_parameter.ux_device_class_video_stream_parameter_max_payload_buffer_nb;
printf(" per _payload_buffer_size: (%ld + 8) * %ld = %ld\n",
device_video_tx_stream_parameter.ux_device_class_video_stream_parameter_max_payload_buffer_size,
device_video_tx_stream_parameter.ux_device_class_video_stream_parameter_max_payload_buffer_nb,
temp);
temp += sizeof(UX_DEVICE_CLASS_VIDEO_STREAM);
printf(" per _stream: _VIDEO_STREAM + _payload_buffer_size = %ld\n", temp);
temp += sizeof(UX_DEVICE_CLASS_VIDEO);
temp *= 2;
printf(" per _video: (_VIDEO + _stream * 1 + _CONTROL * 0) * 2 = %ld\n", temp);
#endif
/* Initialize the device Audio class. This class owns interfaces starting with 1, 2. */
status = ux_device_stack_class_register(_ux_system_device_class_video_name, ux_device_class_video_entry,
1, 0, &device_video_parameter);
UX_TEST_CHECK_SUCCESS(status);
/* Initialize the simulated device controller. */
status = _ux_test_dcd_sim_slave_initialize();
UX_TEST_CHECK_SUCCESS(status);
/* Register all the USB host controllers available in this system */
status = ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
UX_TEST_CHECK_SUCCESS(status);
/* Create the main host simulation thread. */
status = tx_thread_create(&tx_test_thread_host_simulation, "tx demo host simulation", tx_test_thread_host_simulation_entry, 0,
stack_pointer, UX_DEMO_STACK_SIZE,
20, 20, 1, TX_AUTO_START);
UX_TEST_CHECK_SUCCESS(status);
/* Create the main slave simulation thread. */
status = tx_thread_create(&tx_test_thread_slave_simulation, "tx demo slave simulation", tx_test_thread_slave_simulation_entry, 0,
stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
20, 20, 1, TX_AUTO_START);
UX_TEST_CHECK_SUCCESS(status);
}
static UINT test_wait_until_expected(VOID **ptr, ULONG loop, VOID *expected)
{
while(loop)
{
_ux_utility_delay_ms(10);
if (*ptr == expected)
return UX_SUCCESS;
}
return UX_ERROR;
}
static UINT test_wait_until_not_expected(VOID **ptr, ULONG loop, VOID *expected)
{
while(loop)
{
_ux_utility_delay_ms(10);
if (*ptr != expected)
return UX_SUCCESS;
}
return UX_ERROR;
}
#define test_wait_until_not_null(ptr, loop) test_wait_until_not_expected(ptr, loop, UX_NULL)
#define test_wait_until_null(ptr, loop) test_wait_until_expected(ptr, loop, UX_NULL)
void tx_test_thread_host_simulation_entry(ULONG arg)
{
UINT status;
ULONG test_n;
// ULONG mem_free;
UX_DEVICE *device;
UX_CONFIGURATION *configuration;
UX_INTERFACE *interface;
UX_INTERFACE *interface_inst[3][2];
// UX_ENDPOINT *control_endpoint;
// UX_TRANSFER *transfer_request;
UCHAR test_cmp[32];
ULONG temp;
UCHAR *temp_buf;
/* Test connect. */
status = test_wait_until_not_null((void**)&dummy_control, 100);
status |= test_wait_until_not_null((void**)&dummy_tx, 100);
status |= test_wait_until_not_null((void**)&dummy_rx, 100);
status |= test_wait_until_not_null((void**)&device_video, 100);
status |= test_wait_until_not_null((void**)&device_video_rx_stream, 100);
status |= test_wait_until_not_null((void**)&device_video_tx_stream, 100);
UX_TEST_CHECK_SUCCESS(status);
// /* Test disconnect. */
// ux_test_dcd_sim_slave_disconnect();
// ux_test_hcd_sim_host_disconnect();
// /* Reset testing counts. */
// ux_test_utility_sim_mutex_create_count_reset();
// ux_test_utility_sim_sem_create_count_reset();
// ux_test_hcd_sim_host_set_actions(log_on_SetCfg);
// /* Save free memory usage. */
// mem_free = _ux_system->ux_system_regular_memory_pool_free;
// ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
// ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
// tx_thread_sleep(100);
// /* Log create counts for further tests. */
// rsc_enum_mutex_usage = rsc_mutex_on_set_cfg;
// rsc_enum_sem_usage = rsc_sem_on_set_cfg;
// rsc_enum_mem_usage = mem_free - rsc_mem_free_on_set_cfg;
// /* Log create counts when instances active for further tests. */
// rsc_cdc_mutex_usage = ux_test_utility_sim_mutex_create_count() - rsc_enum_mutex_usage;
// rsc_cdc_sem_usage = ux_test_utility_sim_sem_create_count() - rsc_enum_sem_usage;
// rsc_cdc_mem_usage = rsc_mem_free_on_set_cfg - _ux_system->ux_system_regular_memory_pool_free;
// stepinfo("mem free: %ld\n", _ux_system->ux_system_regular_memory_pool_free);
/* Validate configuration descriptors. */
/* ... */
/* Get testing instances. */
status = ux_host_stack_device_get(0, &device);
UX_TEST_CHECK_SUCCESS(status);
// control_endpoint = &device->ux_device_control_endpoint;
// transfer_request = &control_endpoint->ux_endpoint_transfer_request;
status = ux_host_stack_device_configuration_get(device, 0, &configuration);
UX_TEST_CHECK_SUCCESS(status);
interface = configuration -> ux_configuration_first_interface;
while(interface)
{
// printf("Interface: %ld.%ld\n", interface -> ux_interface_descriptor.bInterfaceNumber, interface -> ux_interface_descriptor.bAlternateSetting);
interface_inst[interface -> ux_interface_descriptor.bInterfaceNumber][interface -> ux_interface_descriptor.bAlternateSetting] = interface;
interface = interface -> ux_interface_next_interface;
}
/* Test interface change. */
/* Reset log. */
RESET_CALLBACK_INVOKE_LOG();
status = ux_host_stack_interface_setting_select(interface_inst[1][1]);
status |= ux_host_stack_interface_setting_select(interface_inst[1][0]);
status |= ux_host_stack_interface_setting_select(interface_inst[1][1]);
UX_TEST_CHECK_SUCCESS(status);
UX_TEST_ASSERT(callback_invoke_count == 3);
UX_TEST_ASSERT(callback_invoke_log[0].func == device_video_tx_stream_change);
UX_TEST_ASSERT(callback_invoke_log[0].param1 == device_video_tx_stream);
UX_TEST_ASSERT(callback_invoke_log[0].param2 == (VOID*)1);
UX_TEST_ASSERT(callback_invoke_log[1].func == device_video_tx_stream_change);
UX_TEST_ASSERT(callback_invoke_log[1].param1 == device_video_tx_stream);
UX_TEST_ASSERT(callback_invoke_log[1].param2 == 0);
RESET_CALLBACK_INVOKE_LOG();
status = ux_host_stack_interface_setting_select(interface_inst[2][1]);
status |= ux_host_stack_interface_setting_select(interface_inst[2][0]);
status |= ux_host_stack_interface_setting_select(interface_inst[2][1]);
UX_TEST_CHECK_SUCCESS(status);
UX_TEST_ASSERT(callback_invoke_count == 3);
UX_TEST_ASSERT(callback_invoke_log[0].func == device_video_rx_stream_change);
UX_TEST_ASSERT(callback_invoke_log[0].param1 == device_video_rx_stream);
UX_TEST_ASSERT(callback_invoke_log[0].param2 == (VOID*)1);
UX_TEST_ASSERT(callback_invoke_log[1].func == device_video_rx_stream_change);
UX_TEST_ASSERT(callback_invoke_log[1].param1 == device_video_rx_stream);
UX_TEST_ASSERT(callback_invoke_log[1].param2 == 0);
/* Test data streaming. */
/* Wrong interface! */
status = ux_device_class_video_transmission_start(device_video_rx_stream);
status |= ux_device_class_video_reception_start(device_video_tx_stream);
UX_TEST_CHECK_NOT_SUCCESS(status);
ux_test_link_hooks_from_array(ux_device_class_video_transfer_hook);
/* ------------------ Write test. */
status = ux_device_class_video_payload_write(device_video_tx_stream, "test0", 16);
status |= ux_device_class_video_payload_write(device_video_tx_stream, "test1", 16);
status |= ux_device_class_video_payload_write(device_video_tx_stream, "test2", 16);
status |= ux_device_class_video_payload_write(device_video_tx_stream, "test3", 16);
status |= ux_device_class_video_payload_write(device_video_tx_stream, "test4", 16);
status |= ux_device_class_video_payload_write(device_video_tx_stream, "test5", 16);
status |= ux_device_class_video_payload_write(device_video_tx_stream, "test6", 16);
status |= ux_device_class_video_payload_write(device_video_tx_stream, "test7", 16);
UX_TEST_CHECK_SUCCESS(status);
error_callback_counter = 0;
status = ux_device_class_video_payload_write(device_video_tx_stream, "test8", 16);
UX_TEST_CHECK_CODE(UX_BUFFER_OVERFLOW, status);
/*
Keep sending until under-run.
No buffer appended while running.
*/
buffer_log_count = 0;
test_tx_ack_count = 10;
status = ux_device_class_video_transmission_start(device_video_tx_stream);
UX_TEST_CHECK_SUCCESS(status);
/* Delay to let thread runs. */
_ux_utility_delay_ms(100);
/* Prepare data for checking. */
_ux_utility_memory_set(test_cmp, 0, 16);
_ux_utility_memory_copy(test_cmp, "test", 4);
/* 8 frame should be available. */
for (test_n = 0; test_n < 8; test_n ++)
{
// printf("%ld: %ld: %s\n", test_n, buffer_log[test_n].length, buffer_log[test_n].data);
test_cmp[4] = (UCHAR)(test_n + '0');
UX_TEST_ASSERT(buffer_log[test_n].length == 16);
status = _ux_utility_memory_compare(buffer_log[test_n].data, test_cmp, 6);
UX_TEST_CHECK_SUCCESS(status);
}
/* Then under-run, 0 length packets. */
for(;test_n < buffer_log_count; test_n ++)
{
// printf("%ld: %ld\n", test_n, buffer_log[test_n].length);
UX_TEST_ASSERT(buffer_log[test_n].length == 0);
}
/*
Keep sending until under-run.
Specific number of buffer appended while running.
*/
for (test_tx_ins_way = 0; test_tx_ins_way < 2; test_tx_ins_way ++)
{
/* Switch interface to clean up status. */
status = ux_host_stack_interface_setting_select(interface_inst[1][0]);
status |= ux_host_stack_interface_setting_select(interface_inst[1][1]);
status = ux_device_class_video_payload_write(device_video_tx_stream, "test0", 20);
status |= ux_device_class_video_payload_write(device_video_tx_stream, "test1", 20);
status |= ux_device_class_video_payload_write(device_video_tx_stream, "test2", 20);
status |= ux_device_class_video_payload_write(device_video_tx_stream, "test3", 20);
UX_TEST_CHECK_SUCCESS(status);
test_tx_ins_count = 10;
test_tx_ack_count = 20;
buffer_log_count = 0;
status = ux_device_class_video_transmission_start(device_video_tx_stream);
UX_TEST_CHECK_SUCCESS(status);
/* Delay to let thread runs. */
_ux_utility_delay_ms(300);
/* Prepare data for checking. */
_ux_utility_memory_set(test_cmp, 0, 32);
/* 4 frame should be available. */
_ux_utility_memory_copy(test_cmp, "test", 4);
for (test_n = 0; test_n < 4; test_n ++)
{
// printf("%ld: %ld: %s\n", test_n, buffer_log[test_n].length, buffer_log[test_n].data);
test_cmp[4] = (UCHAR)(test_n + '0');
UX_TEST_ASSERT(buffer_log[test_n].length == 20);
status = _ux_utility_memory_compare(buffer_log[test_n].data, test_cmp, 6);
UX_TEST_CHECK_SUCCESS(status);
}
/* 10 more frame should be available. */
_ux_utility_memory_copy(test_cmp, "insert", 6);
for (; test_n < 14; test_n ++)
{
// printf("%ld: %ld: %s\n", test_n, buffer_log[test_n].length, buffer_log[test_n].data);
test_cmp[6] = (UCHAR)(((10 - (test_n - 4)) % 26) + 'A');
UX_TEST_ASSERT(buffer_log[test_n].length == 32);
status = _ux_utility_memory_compare(buffer_log[test_n].data, test_cmp, 8);
UX_TEST_CHECK_SUCCESS(status);
}
/* Then under-run, 0 length packets. */
for(;test_n < buffer_log_count; test_n ++)
{
// printf("%ld: %ld\n", test_n, buffer_log[test_n].length);
UX_TEST_ASSERT(buffer_log[test_n].length == 0);
}
}
UX_TEST_ASSERT(device_video_tx_stream->ux_device_class_video_stream_transfer_pos == device_video_tx_stream->ux_device_class_video_stream_access_pos);
/* ------------------ Read test. */
UX_TEST_ASSERT(device_video_rx_transfer == UX_NULL);
temp = 0;
status = ux_device_class_video_read_payload_get(device_video_rx_stream, &temp_buf, &temp);
UX_TEST_CHECK_CODE(UX_BUFFER_OVERFLOW, status);
status = ux_device_class_video_reception_start(device_video_rx_stream);
UX_TEST_CHECK_SUCCESS(status);
_ux_utility_thread_sleep(1);
UX_TEST_ASSERT(device_video_rx_transfer != UX_NULL);
status = ux_device_class_video_read_payload_get(device_video_rx_stream, &temp_buf, &temp);
UX_TEST_CHECK_CODE(UX_BUFFER_OVERFLOW, status);
RESET_CALLBACK_INVOKE_LOG();
device_video_rx_simulate_one_payload("012345", 6);
status = ux_device_class_video_read_payload_get(device_video_rx_stream, &temp_buf, &temp);
UX_TEST_CHECK_SUCCESS(status);
for (test_n = 0; test_n < 6; test_n ++)
{
UX_TEST_ASSERT(temp_buf[test_n] == (test_n + '0'));
}
ux_device_class_video_read_payload_free(device_video_rx_stream);
device_video_rx_simulate_one_payload("012345", 6);
device_video_rx_simulate_one_payload("67", 2);
device_video_rx_simulate_one_payload("89", 2);
status = ux_device_class_video_read_payload_get(device_video_rx_stream, &temp_buf, &temp);
UX_TEST_CHECK_SUCCESS(status);
UX_TEST_ASSERT(temp == 6);
for (test_n = 0; test_n < 6; test_n ++)
{
UX_TEST_ASSERT(temp_buf[test_n] == (test_n + '0'));
}
ux_device_class_video_read_payload_free(device_video_rx_stream);
status = ux_device_class_video_read_payload_get(device_video_rx_stream, &temp_buf, &temp);
UX_TEST_CHECK_SUCCESS(status);
UX_TEST_ASSERT(temp == 2);
for (; test_n < 8; test_n ++)
{
UX_TEST_ASSERT(temp_buf[test_n-6] == (test_n + '0'));
}
ux_device_class_video_read_payload_free(device_video_rx_stream);
status = ux_device_class_video_read_payload_get(device_video_rx_stream, &temp_buf, &temp);
UX_TEST_CHECK_SUCCESS(status);
UX_TEST_ASSERT(temp == 2);
for (; test_n < 10; test_n ++)
{
UX_TEST_ASSERT(temp_buf[test_n-8] == (test_n + '0'));
}
ux_device_class_video_read_payload_free(device_video_rx_stream);
UX_TEST_ASSERT(callback_invoke_count == 4);
UX_TEST_ASSERT(callback_invoke_log[0].func == device_video_rx_done);
UX_TEST_ASSERT(callback_invoke_log[0].param1 == device_video_rx_stream);
UX_TEST_ASSERT(callback_invoke_log[1].func == device_video_rx_done);
UX_TEST_ASSERT(callback_invoke_log[1].param1 == device_video_rx_stream);
UX_TEST_ASSERT(callback_invoke_log[2].func == device_video_rx_done);
UX_TEST_ASSERT(callback_invoke_log[2].param1 == device_video_rx_stream);
UX_TEST_ASSERT(callback_invoke_log[3].func == device_video_rx_done);
UX_TEST_ASSERT(callback_invoke_log[3].param1 == device_video_rx_stream);
RESET_CALLBACK_INVOKE_LOG();
error_callback_counter = 0;
for (test_n = 0; test_n < 10; test_n ++)
{
test_cmp[0] = (UCHAR)(test_n + '0');
device_video_rx_simulate_one_payload(test_cmp, 1);
}
UX_TEST_ASSERT(callback_invoke_count == 10);
UX_TEST_ASSERT(error_callback_counter == 3);
for (test_n = 0; test_n < 7; test_n ++)
{
status = ux_device_class_video_read_payload_get(device_video_rx_stream, &temp_buf, &temp);
UX_TEST_CHECK_SUCCESS(status);
UX_TEST_ASSERT(temp == 1);
UX_TEST_ASSERT(temp_buf[0] == (test_n + '0'));
ux_device_class_video_read_payload_free(device_video_rx_stream);
}
UX_TEST_CHECK_SUCCESS(ux_device_class_video_read_payload_get(device_video_rx_stream, &temp_buf, &temp));
UX_TEST_ASSERT(temp == 1);
UX_TEST_ASSERT(temp_buf[0] == '9');
ux_device_class_video_read_payload_free(device_video_rx_stream);
UX_TEST_CHECK_CODE(UX_BUFFER_OVERFLOW, ux_device_class_video_read_payload_get(device_video_rx_stream, &temp_buf, &temp));
/* Wait pending threads. */
_ux_utility_thread_sleep(1);
/* Finally disconnect the device. */
ux_device_stack_disconnect();
/* And deinitialize the class. */
ux_device_stack_class_unregister(_ux_system_device_class_video_name, ux_device_class_video_entry);
/* Deinitialize the device side of usbx. */
_ux_device_stack_uninitialize();
/* And finally the usbx system resources. */
_ux_system_uninitialize();
/* Successful test. */
printf("SUCCESS!\n");
test_control_return(0);
}
void tx_test_thread_slave_simulation_entry(ULONG arg)
{
while(1)
{
#if defined(UX_DEVICE_STANDALONE)
/* Standalone background task. */
ux_system_tasks_run();
#else
/* Sleep so ThreadX on Win32 will delete this thread. */
tx_thread_sleep(10);
#endif
}
}