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).
2965 lines
103 KiB
C
2965 lines
103 KiB
C
/* This test is designed to test the simple dpump host/device class operation. */
|
|
|
|
#include <stdio.h>
|
|
#include "tx_api.h"
|
|
#include "ux_api.h"
|
|
#include "ux_system.h"
|
|
#include "ux_utility.h"
|
|
|
|
#include "fx_api.h"
|
|
|
|
#include "ux_device_stack.h"
|
|
#include "ux_device_class_storage.h"
|
|
|
|
#include "ux_host_stack.h"
|
|
#include "ux_host_class_storage.h"
|
|
|
|
#include "ux_test_dcd_sim_slave.h"
|
|
#include "ux_test_hcd_sim_host.h"
|
|
#include "ux_test_utility_sim.h"
|
|
|
|
#define _storage_media_is_mounted() (global_storage_media->ux_host_class_storage_media_status == UX_HOST_CLASS_STORAGE_MEDIA_MOUNTED)
|
|
#if defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
|
|
FX_MEDIA *_ux_host_class_storage_driver_media(INT i);
|
|
VOID _ux_host_class_storage_driver_entry(FX_MEDIA *media);
|
|
VOID _ux_host_class_storage_media_insert(UX_HOST_CLASS_STORAGE_MEDIA *storage_media, ULONG format_open);
|
|
VOID _ux_host_class_storage_media_remove(UX_HOST_CLASS_STORAGE_MEDIA *storage_media);
|
|
INT _ux_host_class_storage_media_index(UX_HOST_CLASS_STORAGE_MEDIA *storage_media);
|
|
FX_MEDIA *_ux_host_class_storage_media_fx_media(UX_HOST_CLASS_STORAGE_MEDIA *storage_media);
|
|
UCHAR *_ux_host_class_storage_media_fx_media_memory(UX_HOST_CLASS_STORAGE_MEDIA *storage_media);
|
|
|
|
#endif
|
|
|
|
/* Define constants. */
|
|
#define UX_DEMO_STACK_SIZE 2048
|
|
#define UX_DEMO_MEMORY_SIZE (256*1024)
|
|
#define UX_DEMO_BUFFER_SIZE (UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE * 3)
|
|
|
|
#define UX_RAM_DISK_SIZE (200 * 1024)
|
|
#define UX_RAM_DISK_LAST_LBA ((UX_RAM_DISK_SIZE / 512) -1)
|
|
|
|
/* Define local/extern function prototypes. */
|
|
VOID _fx_ram_driver(FX_MEDIA *media_ptr);
|
|
|
|
static void demo_thread_entry(ULONG);
|
|
static TX_THREAD tx_demo_thread_host_simulation;
|
|
static TX_THREAD tx_demo_thread_device_simulation;
|
|
static void tx_demo_thread_host_simulation_entry(ULONG);
|
|
static void tx_demo_thread_device_simulation_entry(ULONG);
|
|
|
|
static UINT ux_test_system_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst);
|
|
|
|
static UINT demo_media_read(VOID *storage, ULONG lun, UCHAR * data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status);
|
|
static UINT demo_media_write(VOID *storage, ULONG lun, UCHAR * data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status);
|
|
static UINT demo_media_status(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status);
|
|
static UINT demo_media_flush(VOID *storage, ULONG lun, ULONG number_blocks, ULONG lba, ULONG *media_status);
|
|
|
|
static VOID ux_test_hcd_entry_set_cfg(UX_TEST_ACTION *action, VOID *params);
|
|
|
|
/* Define global data structures. */
|
|
|
|
static UCHAR usbx_memory[UX_DEMO_MEMORY_SIZE + (UX_DEMO_STACK_SIZE * 2)];
|
|
static UCHAR buffer[UX_DEMO_BUFFER_SIZE];
|
|
|
|
static ULONG error_counter;
|
|
|
|
static UX_HOST_CLASS_STORAGE *storage;
|
|
static UX_HOST_CLASS_STORAGE_MEDIA *storage_media;
|
|
static FX_MEDIA *media;
|
|
static UX_SLAVE_CLASS_STORAGE_PARAMETER global_storage_parameter;
|
|
|
|
static FX_MEDIA ram_disk1;
|
|
static FX_MEDIA ram_disk2;
|
|
static CHAR ram_disk_memory1[UX_RAM_DISK_SIZE];
|
|
static CHAR ram_disk_memory2[UX_RAM_DISK_SIZE];
|
|
static UCHAR buffer1[512];
|
|
static UCHAR buffer2[512];
|
|
|
|
static FX_MEDIA *ram_disks[] = {&ram_disk1, &ram_disk2};
|
|
static UCHAR *buffers[] = {buffer1, buffer2};
|
|
static CHAR *ram_disk_memory[] = { ram_disk_memory1, ram_disk_memory2 };
|
|
|
|
static UINT ram_disk_status = UX_SUCCESS;
|
|
static ULONG ram_disk_media_status = 0;
|
|
static CHAR ram_disk_status_sent = 0;
|
|
|
|
static ULONG ram_disk_rw_fail_mode = 0; /* 1: BulkIN, 2: BulkOUT, 0: DISK. 0x80: once */
|
|
#define ram_disk_rw_fail_mode_bulk_in() ((ram_disk_rw_fail_mode & 0x7F) == 1)
|
|
#define ram_disk_rw_fail_mode_bulk_out() ((ram_disk_rw_fail_mode & 0x7F) == 2)
|
|
#define ram_disk_rw_fail_mode_disk() ((ram_disk_rw_fail_mode & 0x7F) == 0)
|
|
#define ram_disk_rw_fail_mode_one_shot() ((ram_disk_rw_fail_mode & 0x80) > 0)
|
|
static ULONG ram_disk_rw_fail_after = 0xFFFFFFFFu;
|
|
static ULONG ram_disk_rw_count = 0;
|
|
static ULONG ram_disk_rw_wait_delay = 0;
|
|
static ULONG ram_disk_rw_wait_start = 0;
|
|
static UCHAR ram_disk_rw_wait_state = 0;/* 0: idle, 1: wait */
|
|
|
|
static CHAR ram_disk_flush = 0;
|
|
static UINT ram_disk_flush_status = UX_STATE_NEXT;
|
|
|
|
static ULONG set_cfg_counter;
|
|
|
|
static ULONG rsc_mem_alloc_cnt_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_alloc_count;
|
|
|
|
static ULONG rsc_storage_sem_usage;
|
|
static ULONG rsc_storage_sem_get_count;
|
|
static ULONG rsc_storage_mutex_usage;
|
|
static ULONG rsc_storage_mem_alloc_count;
|
|
|
|
static ULONG interaction_count;
|
|
|
|
static UCHAR error_callback_ignore = UX_TRUE;
|
|
static ULONG error_callback_counter;
|
|
|
|
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 50
|
|
static UCHAR device_framework_full_speed[] = {
|
|
|
|
/* Device descriptor */
|
|
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
|
|
0x81, 0x07, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
|
|
0x03, 0x01,
|
|
|
|
/* Configuration descriptor */
|
|
0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xc0,
|
|
0x32,
|
|
|
|
/* Interface descriptor */
|
|
0x09, 0x04, 0x00, 0x00, 0x02, 0x08, 0x06, 0x50,
|
|
0x00,
|
|
|
|
/* Endpoint descriptor (Bulk In) */
|
|
0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00,
|
|
|
|
/* Endpoint descriptor (Bulk Out) */
|
|
0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00
|
|
|
|
};
|
|
|
|
|
|
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 60
|
|
static UCHAR device_framework_high_speed[] = {
|
|
|
|
/* Device descriptor */
|
|
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
|
|
0x81, 0x07, 0x00, 0x00, 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, 0x08, 0x06, 0x50,
|
|
0x00,
|
|
|
|
/* Endpoint descriptor (Bulk In) */
|
|
0x07, 0x05, 0x81, 0x02, 0x00, 0x02, 0x00,
|
|
|
|
/* Endpoint descriptor (Bulk Out) */
|
|
0x07, 0x05, 0x02, 0x02, 0x00, 0x02, 0x00
|
|
|
|
};
|
|
|
|
|
|
/* String Device Framework :
|
|
Byte 0 and 1 : Word containing the language ID : 0x0904 for US
|
|
Byte 2 : Byte containing the index of the descriptor
|
|
Byte 3 : Byte containing the length of the descriptor string
|
|
*/
|
|
|
|
#define STRING_FRAMEWORK_LENGTH 38
|
|
static UCHAR string_framework[] = {
|
|
|
|
/* Manufacturer string descriptor : Index 1 */
|
|
0x09, 0x04, 0x01, 0x0c,
|
|
0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
|
|
0x6f, 0x67, 0x69, 0x63,
|
|
|
|
/* Product string descriptor : Index 2 */
|
|
0x09, 0x04, 0x02, 0x0a,
|
|
0x46, 0x6c, 0x61, 0x73, 0x68, 0x20, 0x44, 0x69,
|
|
0x73, 0x6b,
|
|
|
|
/* Serial Number string descriptor : Index 3 */
|
|
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. */
|
|
#define LANGUAGE_ID_FRAMEWORK_LENGTH 2
|
|
static UCHAR language_id_framework[] = {
|
|
|
|
/* English. */
|
|
0x09, 0x04
|
|
};
|
|
|
|
|
|
/* Setup requests */
|
|
|
|
static UX_TEST_SETUP _SetConfigure = UX_TEST_SETUP_SetConfigure;
|
|
|
|
static UX_TEST_HCD_SIM_ACTION log_on_SetCfg[] = {
|
|
/* function, request to match,
|
|
port action, port status,
|
|
request action, request EP, request data, request actual length, request status,
|
|
status, additional callback,
|
|
no_return */
|
|
{ UX_HCD_TRANSFER_REQUEST, &_SetConfigure,
|
|
UX_FALSE, UX_TEST_PORT_STATUS_DISC,
|
|
UX_TEST_SETUP_MATCH_REQ, 0, UX_NULL, 0, 0,
|
|
UX_SUCCESS, ux_test_hcd_entry_set_cfg,
|
|
UX_TRUE}, /* Invoke callback & continue */
|
|
{ 0 }
|
|
};
|
|
|
|
|
|
static UX_TEST_HCD_SIM_ACTION fail_on_bulkin[] = {
|
|
/* function, request to match,
|
|
port action, port status,
|
|
request action, request EP, request data, request actual length, request status,
|
|
status, additional callback,
|
|
no_return */
|
|
{ UX_DCD_TRANSFER_REQUEST, UX_NULL,
|
|
UX_FALSE, UX_TEST_PORT_STATUS_DISC,
|
|
UX_TEST_MATCH_EP, 0x81, UX_NULL, 0, UX_ERROR,
|
|
UX_STATE_ERROR, UX_NULL,
|
|
UX_FALSE}, /* Invoke callback & no continue */
|
|
{ 0 }
|
|
};
|
|
|
|
|
|
static UX_TEST_HCD_SIM_ACTION fail_on_bulkout[] = {
|
|
/* function, request to match,
|
|
port action, port status,
|
|
request action, request EP, request data, request actual length, request status,
|
|
status, additional callback,
|
|
no_return */
|
|
{ UX_DCD_TRANSFER_REQUEST, UX_NULL,
|
|
UX_FALSE, UX_TEST_PORT_STATUS_DISC,
|
|
UX_TEST_MATCH_EP, 0x02, UX_NULL, 0, UX_ERROR,
|
|
UX_STATE_ERROR, UX_NULL,
|
|
UX_FALSE}, /* Invoke callback & no continue */
|
|
{ 0 }
|
|
};
|
|
|
|
|
|
/* Define the ISR dispatch. */
|
|
|
|
extern VOID (*test_isr_dispatch)(void);
|
|
|
|
|
|
/* Prototype for test control return. */
|
|
|
|
void test_control_return(UINT status);
|
|
|
|
|
|
/* Define the ISR dispatch routine. */
|
|
|
|
static void test_isr(void)
|
|
{
|
|
|
|
/* For further expansion of interrupt-level testing. */
|
|
}
|
|
|
|
|
|
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
|
|
{
|
|
|
|
error_callback_counter ++;
|
|
|
|
if (!error_callback_ignore)
|
|
{
|
|
{
|
|
/* Failed test. */
|
|
printf("Error #%d, system_level: %d, system_context: %d, error_code: 0x%x\n", __LINE__, system_level, system_context, error_code);
|
|
test_control_return(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
static UINT host_storage_instance_get(ULONG timeout_x10ms)
|
|
{
|
|
|
|
UINT status;
|
|
UX_HOST_CLASS *class;
|
|
|
|
|
|
#if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
|
|
storage_media = UX_NULL;
|
|
media = UX_NULL;
|
|
#endif
|
|
|
|
/* Find the main storage container */
|
|
status = ux_host_stack_class_get(_ux_system_host_class_storage_name, &class);
|
|
if (status != UX_SUCCESS)
|
|
return(status);
|
|
|
|
/* Get storage instance, wait it to be live and media attached. */
|
|
do
|
|
{
|
|
if (timeout_x10ms)
|
|
{
|
|
tx_thread_sleep(UX_MS_TO_TICK_NON_ZERO(10));
|
|
if (timeout_x10ms != 0xFFFFFFFF)
|
|
timeout_x10ms --;
|
|
}
|
|
|
|
status = ux_host_stack_class_instance_get(class, 0, (void **) &storage);
|
|
if (status == UX_SUCCESS)
|
|
{
|
|
#if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
|
|
storage_media = (UX_HOST_CLASS_STORAGE_MEDIA *) class -> ux_host_class_media;
|
|
media = &storage_media -> ux_host_class_storage_media;
|
|
#endif
|
|
if (storage -> ux_host_class_storage_state == UX_HOST_CLASS_INSTANCE_LIVE &&
|
|
class -> ux_host_class_ext != UX_NULL &&
|
|
class -> ux_host_class_media != UX_NULL)
|
|
{
|
|
return(UX_SUCCESS);
|
|
}
|
|
}
|
|
|
|
} while(timeout_x10ms > 0);
|
|
|
|
return(UX_ERROR);
|
|
}
|
|
|
|
static UINT sleep_break_on_error(VOID)
|
|
{
|
|
|
|
if (error_callback_counter >= 3)
|
|
return error_callback_counter;
|
|
|
|
return UX_SUCCESS;
|
|
}
|
|
|
|
static UINT sleep_break_on_connect(VOID)
|
|
{
|
|
if (host_storage_instance_get(0) == UX_SUCCESS)
|
|
return(1);
|
|
if (error_callback_counter >= 3)
|
|
return(1);
|
|
return(0);
|
|
}
|
|
|
|
static VOID ux_test_hcd_entry_set_cfg(UX_TEST_ACTION *action, VOID *_params)
|
|
{
|
|
|
|
set_cfg_counter ++;
|
|
|
|
rsc_mem_alloc_cnt_on_set_cfg = ux_test_utility_sim_mem_alloc_count();
|
|
|
|
rsc_sem_on_set_cfg = ux_test_utility_sim_sem_create_count();
|
|
rsc_sem_get_on_set_cfg = ux_test_utility_sim_sem_get_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_device_storage_basic_standalone_test_application_define(void *first_unused_memory)
|
|
#endif
|
|
{
|
|
|
|
UINT status;
|
|
CHAR * stack_pointer;
|
|
CHAR * memory_pointer;
|
|
ULONG mem_free;
|
|
ULONG test_n;
|
|
|
|
|
|
/* Inform user. */
|
|
printf("Running STANDALONE Device Storage Basic Test........................ ");
|
|
#ifndef UX_DEVICE_STANDALONE
|
|
printf("Skip\n");
|
|
test_control_return(0);
|
|
#endif
|
|
|
|
stepinfo("\n");
|
|
|
|
/* Initialize FileX. */
|
|
fx_system_initialize();
|
|
|
|
/* Reset ram disks memory. */
|
|
ux_utility_memory_set(ram_disk_memory1, 0, UX_RAM_DISK_SIZE);
|
|
ux_utility_memory_set(ram_disk_memory2, 0, UX_RAM_DISK_SIZE);
|
|
|
|
/* Format the ram drive. */
|
|
status = fx_media_format(&ram_disk1, _fx_ram_driver, ram_disk_memory1, buffer1, 512, "RAM DISK1", 2, 512, 0, UX_RAM_DISK_SIZE/512, 512, 4, 1, 1);
|
|
status |= fx_media_format(&ram_disk2, _fx_ram_driver, ram_disk_memory2, buffer2, 512, "RAM DISK2", 2, 512, 0, UX_RAM_DISK_SIZE/512, 512, 4, 1, 1);
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
|
|
/* Storage basic test error. */
|
|
printf("ERROR #8\n");
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Open the ram_disk. */
|
|
status = fx_media_open(&ram_disk1, "RAM DISK1", _fx_ram_driver, ram_disk_memory1, buffer1, 512);
|
|
status |= fx_media_open(&ram_disk2, "RAM DISK2", _fx_ram_driver, ram_disk_memory2, buffer2, 512);
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
|
|
/* Storage basic test error. */
|
|
printf("ERROR %d\n", __LINE__);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Reset testing counts. */
|
|
ux_test_utility_sim_mem_alloc_log_enable(UX_TRUE);
|
|
ux_test_utility_sim_mem_alloc_count_reset();
|
|
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);
|
|
|
|
/* Check for error. */
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d\n", __LINE__);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Register the error callback. */
|
|
_ux_utility_error_callback_register(error_callback);
|
|
|
|
/* 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. */
|
|
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);
|
|
if(status!=UX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d\n", __LINE__);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Store the number of LUN in this device storage instance. */
|
|
global_storage_parameter.ux_slave_class_storage_parameter_number_lun = 2;
|
|
|
|
/* Initialize the storage class parameters for reading/writing to the first Flash Disk. */
|
|
global_storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_last_lba = UX_RAM_DISK_LAST_LBA;
|
|
global_storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_block_length = 512;
|
|
global_storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_type = 0;
|
|
global_storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_removable_flag = 0x80;
|
|
global_storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_read = demo_media_read;
|
|
global_storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_write = demo_media_write;
|
|
global_storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_status = demo_media_status;
|
|
global_storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_flush = demo_media_flush;
|
|
|
|
/* Initialize the storage class parameters for reading/writing to the second Flash Disk. */
|
|
global_storage_parameter.ux_slave_class_storage_parameter_lun[1].ux_slave_class_storage_media_last_lba = UX_RAM_DISK_LAST_LBA;
|
|
global_storage_parameter.ux_slave_class_storage_parameter_lun[1].ux_slave_class_storage_media_block_length = 512;
|
|
global_storage_parameter.ux_slave_class_storage_parameter_lun[1].ux_slave_class_storage_media_type = 0;
|
|
global_storage_parameter.ux_slave_class_storage_parameter_lun[1].ux_slave_class_storage_media_removable_flag = 0x80;
|
|
global_storage_parameter.ux_slave_class_storage_parameter_lun[1].ux_slave_class_storage_media_read = demo_media_read;
|
|
global_storage_parameter.ux_slave_class_storage_parameter_lun[1].ux_slave_class_storage_media_write = demo_media_write;
|
|
global_storage_parameter.ux_slave_class_storage_parameter_lun[1].ux_slave_class_storage_media_status = demo_media_status;
|
|
global_storage_parameter.ux_slave_class_storage_parameter_lun[1].ux_slave_class_storage_media_flush = demo_media_flush;
|
|
|
|
/* Initialize the device storage class. The class is connected with interface 0 on configuration 1. */
|
|
status = ux_device_stack_class_register(_ux_system_slave_class_storage_name, ux_device_class_storage_entry,
|
|
1, 0, (VOID *)&global_storage_parameter);
|
|
if(status!=UX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d\n", __LINE__);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Initialize the simulated device controller. */
|
|
// status = _ux_dcd_sim_slave_initialize();
|
|
status = _ux_test_dcd_sim_slave_initialize();
|
|
|
|
/* Check for error. */
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d\n", __LINE__);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* The code below is required for installing the host portion of USBX */
|
|
status = ux_host_stack_initialize(ux_test_system_host_change_function);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d\n", __LINE__);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Register storage class. */
|
|
status = ux_host_stack_class_register(_ux_system_host_class_storage_name, ux_host_class_storage_entry);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d\n", __LINE__);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* 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);
|
|
|
|
/* Check for error. */
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d\n", __LINE__);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Create the main device simulation thread. */
|
|
status = tx_thread_create(&tx_demo_thread_device_simulation, "tx demo device simulation", tx_demo_thread_device_simulation_entry, 0,
|
|
stack_pointer, UX_DEMO_STACK_SIZE,
|
|
21, 21, 1, TX_AUTO_START);
|
|
|
|
/* Check for error. */
|
|
if (status != TX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d\n", __LINE__);
|
|
test_control_return(1);
|
|
}
|
|
stack_pointer += UX_DEMO_STACK_SIZE;
|
|
|
|
/* Create the main host simulation thread. */
|
|
status = tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
|
|
stack_pointer, UX_DEMO_STACK_SIZE,
|
|
20, 20, 1, TX_AUTO_START);
|
|
|
|
/* Check for error. */
|
|
if (status != TX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d\n", __LINE__);
|
|
test_control_return(1);
|
|
}
|
|
|
|
}
|
|
|
|
static void tx_demo_thread_device_simulation_entry(ULONG arg)
|
|
{
|
|
while(1)
|
|
{
|
|
|
|
/* Run device tasks. */
|
|
ux_system_tasks_run();
|
|
|
|
/* Relinquish to other thread. */
|
|
tx_thread_relinquish();
|
|
}
|
|
}
|
|
|
|
static ULONG _test_dw_minus(ULONG d0, ULONG d1)
|
|
{
|
|
if (d0 >= d1)
|
|
return(d0 - d1);
|
|
return(d0 + (0xFFFFFFFF - d1));
|
|
}
|
|
|
|
static UINT _media_driver_read(FX_MEDIA *media,
|
|
VOID (*_media_driver)(FX_MEDIA *),
|
|
UCHAR *buffer, ULONG lba, ULONG n_lb)
|
|
{
|
|
UINT status;
|
|
|
|
if (lba == 0)
|
|
{
|
|
media->fx_media_driver_logical_sector = lba;
|
|
media->fx_media_driver_sectors = n_lb;
|
|
media->fx_media_driver_request = FX_DRIVER_BOOT_READ;
|
|
media->fx_media_driver_buffer = buffer;
|
|
_media_driver(media);
|
|
*(buffer) = 0xeb;
|
|
*(buffer+1) = 0x3c;
|
|
*(buffer+2) = 0x90;
|
|
*(buffer+21) = 0xF8;
|
|
|
|
*(buffer+24) = 0x01;
|
|
*(buffer+26) = 0x10;
|
|
*(buffer+28) = 0x01;
|
|
|
|
*(buffer+510) = 0x55;
|
|
*(buffer+511) = 0xaa;
|
|
ux_utility_memory_copy(buffer+0x36,"FAT12",5);
|
|
|
|
if (media->fx_media_driver_status != FX_SUCCESS)
|
|
{
|
|
printf("%s:%d: FX error 0x%x\n", __FILE__, __LINE__, media->fx_media_driver_status);
|
|
return(UX_ERROR);
|
|
}
|
|
|
|
lba++;
|
|
n_lb --;
|
|
buffer += 512;
|
|
}
|
|
media->fx_media_driver_logical_sector = lba;
|
|
media->fx_media_driver_sectors = n_lb;
|
|
media->fx_media_driver_request = FX_DRIVER_READ;
|
|
media->fx_media_driver_buffer = buffer;
|
|
_media_driver(media);
|
|
if (media->fx_media_driver_status != FX_SUCCESS)
|
|
{
|
|
stepinfo("%s:%d: FX error 0x%x\n", __FILE__, __LINE__, media->fx_media_driver_status);
|
|
return(UX_ERROR);
|
|
}
|
|
return(UX_SUCCESS);
|
|
}
|
|
|
|
static UINT _media_driver_write(FX_MEDIA *media,
|
|
VOID (*_media_driver)(FX_MEDIA *),
|
|
UCHAR *buffer, ULONG lba, ULONG n_lb)
|
|
{
|
|
UINT status;
|
|
|
|
if (lba == 0)
|
|
{
|
|
media -> fx_media_driver_logical_sector = 0;
|
|
media -> fx_media_driver_sectors = 1;
|
|
media -> fx_media_driver_request = FX_DRIVER_BOOT_WRITE;
|
|
media -> fx_media_driver_buffer = buffer;
|
|
_media_driver(media);
|
|
|
|
if (media->fx_media_driver_status != FX_SUCCESS)
|
|
{
|
|
printf("%s:%d: FX error 0x%x\n", __FILE__, __LINE__, media->fx_media_driver_status);
|
|
return(UX_ERROR);
|
|
}
|
|
|
|
lba ++;
|
|
n_lb --;
|
|
buffer += 512;
|
|
}
|
|
if (n_lb)
|
|
{
|
|
media -> fx_media_driver_logical_sector = lba;
|
|
media -> fx_media_driver_sectors = n_lb;
|
|
media -> fx_media_driver_request = FX_DRIVER_WRITE;
|
|
media -> fx_media_driver_buffer = buffer;
|
|
_media_driver(media);
|
|
|
|
if (media->fx_media_driver_status != FX_SUCCESS)
|
|
{
|
|
printf("%s:%d: FX error 0x%x\n", __FILE__, __LINE__, media->fx_media_driver_status);
|
|
return(UX_ERROR);
|
|
}
|
|
}
|
|
return(UX_SUCCESS);
|
|
}
|
|
|
|
static UINT _test_host_class_storage_inquiry(UX_HOST_CLASS_STORAGE *storage,
|
|
UCHAR flags, ULONG data_length, ULONG cb_length,
|
|
UCHAR page_code, UCHAR *response, ULONG response_length)
|
|
{
|
|
UINT status;
|
|
UCHAR *cbw;
|
|
UINT command_length;
|
|
|
|
/* Use a pointer for the cbw, easier to manipulate. */
|
|
cbw = (UCHAR *) storage -> ux_host_class_storage_cbw;
|
|
|
|
/* Initialize the CBW for this command. */
|
|
_ux_host_class_storage_cbw_initialize(storage, flags, data_length, cb_length);
|
|
|
|
/* Prepare the INQUIRY command block. */
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_INQUIRY_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_INQUIRY;
|
|
|
|
/* Store the page code. */
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_INQUIRY_PAGE_CODE) = page_code;
|
|
|
|
/* Store the length of the Inquiry Response. */
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_INQUIRY_ALLOCATION_LENGTH) = (UCHAR)response_length;
|
|
|
|
/* Send the command to transport layer. */
|
|
status = _ux_host_class_storage_transport(storage, response);
|
|
|
|
/* Return completion status. */
|
|
return(status);
|
|
}
|
|
static UINT test_host_class_storage_inquiry(UX_HOST_CLASS_STORAGE *storage, UCHAR page_code, UCHAR *response, ULONG response_length)
|
|
{
|
|
_test_host_class_storage_inquiry(storage,
|
|
UX_HOST_CLASS_STORAGE_DATA_IN,
|
|
UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH,
|
|
UX_HOST_CLASS_STORAGE_INQUIRY_COMMAND_LENGTH_SBC,
|
|
page_code, response, response_length);
|
|
}
|
|
|
|
static UINT _test_send_cbw_EX(int __line__, ULONG length)
|
|
{
|
|
|
|
UX_TRANSFER *transfer_request;
|
|
UINT status;
|
|
UCHAR *cbw;
|
|
|
|
stepinfo(">>>>> %d.%d: CBW\n", __LINE__, __line__);
|
|
transfer_request = &storage -> ux_host_class_storage_bulk_out_endpoint -> ux_endpoint_transfer_request;
|
|
cbw = (UCHAR *) storage -> ux_host_class_storage_cbw;
|
|
|
|
transfer_request -> ux_transfer_request_data_pointer = cbw;
|
|
transfer_request -> ux_transfer_request_requested_length = length;
|
|
status = ux_host_stack_transfer_request(transfer_request);
|
|
|
|
/* There is error, return the error code. */
|
|
if (status != UX_SUCCESS)
|
|
return(status);
|
|
|
|
/* Wait transfer done. */
|
|
status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT));
|
|
|
|
/* No error, it's done. */
|
|
if (status == UX_SUCCESS)
|
|
return(transfer_request->ux_transfer_request_completion_code);
|
|
|
|
/* All transfers pending need to abort. There may have been a partial transfer. */
|
|
ux_host_stack_transfer_request_abort(transfer_request);
|
|
|
|
/* Set the completion code. */
|
|
transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT;
|
|
|
|
/* There was an error, return to the caller. */
|
|
return(UX_TRANSFER_TIMEOUT);
|
|
}
|
|
static UINT _test_send_cbw(int __line__)
|
|
{
|
|
_test_send_cbw_EX(__line__, UX_HOST_CLASS_STORAGE_CBW_LENGTH);
|
|
}
|
|
|
|
static UINT _test_transfer_data(int __line__, UCHAR *data, ULONG size, UCHAR do_read)
|
|
{
|
|
|
|
UX_TRANSFER *transfer_request;
|
|
UINT status;
|
|
|
|
|
|
stepinfo(">>>>> %d.%d: DATA\n", __LINE__, __line__);
|
|
transfer_request = do_read ?
|
|
&storage -> ux_host_class_storage_bulk_in_endpoint -> ux_endpoint_transfer_request :
|
|
&storage -> ux_host_class_storage_bulk_out_endpoint -> ux_endpoint_transfer_request;
|
|
transfer_request -> ux_transfer_request_data_pointer = data;
|
|
transfer_request -> ux_transfer_request_requested_length = size;
|
|
|
|
status = ux_host_stack_transfer_request(transfer_request);
|
|
|
|
/* There is error, return the error code. */
|
|
if (status != UX_SUCCESS)
|
|
return(status);
|
|
|
|
/* Wait transfer done. */
|
|
status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT));
|
|
|
|
/* No error, it's done. */
|
|
if (status == UX_SUCCESS)
|
|
return(transfer_request->ux_transfer_request_completion_code);
|
|
|
|
/* All transfers pending need to abort. There may have been a partial transfer. */
|
|
ux_host_stack_transfer_request_abort(transfer_request);
|
|
|
|
/* Set the completion code. */
|
|
transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT;
|
|
|
|
/* There was an error, return to the caller. */
|
|
return(UX_TRANSFER_TIMEOUT);
|
|
}
|
|
|
|
static UINT _test_wait_csw_EX(int __line__)
|
|
{
|
|
|
|
UX_TRANSFER *transfer_request;
|
|
UINT status;
|
|
|
|
|
|
stepinfo(">>>>> %d.%d: CSW_Ex\n", __LINE__, __line__);
|
|
|
|
/* Get the pointer to the transfer request, on the bulk in endpoint. */
|
|
transfer_request = &storage -> ux_host_class_storage_bulk_in_endpoint -> ux_endpoint_transfer_request;
|
|
|
|
/* Fill in the transfer_request parameters. */
|
|
transfer_request -> ux_transfer_request_data_pointer = (UCHAR *) &storage -> ux_host_class_storage_csw;
|
|
transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_STORAGE_CSW_LENGTH;
|
|
|
|
/* Get the CSW on the bulk in endpoint. */
|
|
status = ux_host_stack_transfer_request(transfer_request);
|
|
if (status != UX_SUCCESS)
|
|
return(status);
|
|
|
|
/* Wait for the completion of the transfer request. */
|
|
status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT));
|
|
|
|
/* If OK, we are done. */
|
|
if (status == UX_SUCCESS)
|
|
return(transfer_request->ux_transfer_request_completion_code);
|
|
|
|
/* All transfers pending need to abort. There may have been a partial transfer. */
|
|
ux_host_stack_transfer_request_abort(transfer_request);
|
|
|
|
/* Set the completion code. */
|
|
transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT;
|
|
|
|
/* There was an error, return to the caller. */
|
|
return(UX_TRANSFER_TIMEOUT);
|
|
}
|
|
|
|
static VOID _test_clear_stall(UCHAR clear_read_stall)
|
|
{
|
|
|
|
UX_ENDPOINT *endpoint;
|
|
|
|
|
|
endpoint = clear_read_stall ?
|
|
storage -> ux_host_class_storage_bulk_in_endpoint :
|
|
storage -> ux_host_class_storage_bulk_out_endpoint;
|
|
_ux_host_stack_endpoint_reset(endpoint);
|
|
}
|
|
|
|
static UINT _test_wait_csw(int __line__)
|
|
{
|
|
UINT status;
|
|
|
|
stepinfo(">>>>> %d.%d: CSW\n", __LINE__, __line__);
|
|
status = _test_wait_csw_EX(__LINE__);
|
|
if (status == UX_TRANSFER_STALLED)
|
|
{
|
|
_test_clear_stall(UX_TRUE);
|
|
status = _test_wait_csw_EX(__LINE__);
|
|
}
|
|
return(status);
|
|
}
|
|
|
|
static UINT _test_request_sense(void)
|
|
{
|
|
|
|
UINT status;
|
|
UX_TRANSFER *transfer_request;
|
|
UCHAR *cbw;
|
|
UCHAR *request_sense_response;
|
|
ULONG sense_code;
|
|
UINT command_length = UX_HOST_CLASS_STORAGE_REQUEST_SENSE_COMMAND_LENGTH_SBC;
|
|
|
|
|
|
transfer_request = &storage -> ux_host_class_storage_bulk_out_endpoint -> ux_endpoint_transfer_request;
|
|
cbw = (UCHAR *) storage -> ux_host_class_storage_cbw;
|
|
|
|
_ux_utility_memory_copy(storage -> ux_host_class_storage_saved_cbw, storage -> ux_host_class_storage_cbw, UX_HOST_CLASS_STORAGE_CBW_LENGTH);
|
|
_ux_host_class_storage_cbw_initialize(storage, UX_HOST_CLASS_STORAGE_DATA_IN, UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH, command_length);
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_REQUEST_SENSE;
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_ALLOCATION_LENGTH) = UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH;
|
|
request_sense_response = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH);
|
|
if (request_sense_response == UX_NULL)
|
|
return(UX_MEMORY_INSUFFICIENT);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status == UX_SUCCESS)
|
|
{
|
|
status = _test_transfer_data(__LINE__, request_sense_response, UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH, UX_TRUE);
|
|
if (status == UX_SUCCESS)
|
|
{
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status == UX_SUCCESS)
|
|
{
|
|
|
|
sense_code = (((ULONG) *(request_sense_response + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_SENSE_KEY)) & 0x0f) << 16;
|
|
sense_code |= ((ULONG) *(request_sense_response + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE)) << 8;
|
|
sense_code |= (ULONG) *(request_sense_response + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE_QUALIFIER);
|
|
|
|
storage -> ux_host_class_storage_sense_code = sense_code;
|
|
}
|
|
}
|
|
}
|
|
_ux_utility_memory_free(request_sense_response);
|
|
_ux_utility_memory_copy(storage -> ux_host_class_storage_cbw, storage -> ux_host_class_storage_saved_cbw, UX_HOST_CLASS_STORAGE_CBW_LENGTH);
|
|
return(status);
|
|
}
|
|
|
|
typedef struct cbw_read_struct
|
|
{
|
|
UCHAR flags_pos;
|
|
UCHAR lba_pos;
|
|
UCHAR lba_size;
|
|
UCHAR len_pos;
|
|
UCHAR len_size;
|
|
} cbw_read_struct_t;
|
|
static cbw_read_struct_t cbw_READ_info[] =
|
|
{
|
|
{ 1, 2, 2, 4, 1},
|
|
{ 1, 2, 4, 7, 2},
|
|
{ 1, 2, 4, 6, 4},
|
|
{ 1, 2, 8, 10, 4},
|
|
{10, 12, 8, 28, 4}
|
|
};
|
|
static UCHAR _read_op(UCHAR op_code)
|
|
{
|
|
switch(op_code)
|
|
{
|
|
case 0x28: return 1;
|
|
case 0xA8: return 2;
|
|
case 0x88: return 3;
|
|
case 0x7F: return 4;
|
|
case 0x08: return 0;
|
|
default: return 0xFF;
|
|
}
|
|
}
|
|
static void _test_init_cbw_READ_EX(
|
|
UCHAR flags, ULONG data_length,
|
|
UCHAR op6_10_12_16_32, ULONG lba, ULONG len)
|
|
{
|
|
UCHAR *cbw;
|
|
UINT command_length;
|
|
UCHAR op = _read_op(op6_10_12_16_32);
|
|
UINT i;
|
|
|
|
|
|
if (op >= 5)
|
|
return;
|
|
|
|
cbw = (UCHAR *) storage -> ux_host_class_storage_cbw;
|
|
command_length = UX_HOST_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_SBC;
|
|
_ux_host_class_storage_cbw_initialize(storage, flags, data_length, command_length);
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + 0) = op6_10_12_16_32;
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + cbw_READ_info[op].flags_pos) = 0;
|
|
for (i = cbw_READ_info[op].lba_pos + cbw_READ_info[op].lba_size - 1; i >= cbw_READ_info[op].lba_pos; i --)
|
|
{
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + i) = (UCHAR)lba;
|
|
lba >>= 8;
|
|
}
|
|
for (i = cbw_READ_info[op].len_pos + cbw_READ_info[op].len_size - 1; i >= cbw_READ_info[op].len_size; i --)
|
|
{
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + i) = (UCHAR)len;
|
|
len >>= 8;
|
|
}
|
|
}
|
|
static void _test_init_cbw_READ(UCHAR op6_10_12_16_32, ULONG lba, ULONG len)
|
|
{
|
|
_test_init_cbw_READ_EX(0x80, len * 512, op6_10_12_16_32, lba, len);
|
|
}
|
|
|
|
typedef struct cbw_write_struct
|
|
{
|
|
UCHAR flags_pos;
|
|
UCHAR lba_pos;
|
|
UCHAR lba_size;
|
|
UCHAR len_pos;
|
|
UCHAR len_size;
|
|
} cbw_write_struct_t;
|
|
static cbw_write_struct_t cbw_WRITE_info[] =
|
|
{
|
|
{ 1, 2, 2, 4, 1},
|
|
{ 1, 2, 4, 7, 2},
|
|
{ 1, 2, 4, 6, 4},
|
|
{ 1, 2, 8, 10, 4},
|
|
{10, 12, 8, 28, 4}
|
|
};
|
|
static UCHAR _write_op(UCHAR op_code)
|
|
{
|
|
switch(op_code)
|
|
{
|
|
case 0x2A: return 1;
|
|
case 0xAA: return 2;
|
|
case 0x8A: return 3;
|
|
case 0x7F: return 4;
|
|
case 0x0A: return 0;
|
|
default: return 0xFF;
|
|
}
|
|
}
|
|
static void _test_init_cbw_WRITE_EX(UCHAR flags, ULONG data_length,
|
|
UCHAR op6_10_12_16_32, ULONG lba, ULONG len)
|
|
{
|
|
|
|
UCHAR *cbw;
|
|
UINT command_length;
|
|
UCHAR op = _write_op(op6_10_12_16_32);
|
|
UINT i;
|
|
|
|
|
|
if (op >= 5)
|
|
return;
|
|
|
|
cbw = (UCHAR *) storage -> ux_host_class_storage_cbw;
|
|
command_length = UX_HOST_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_SBC;
|
|
_ux_host_class_storage_cbw_initialize(storage, flags, data_length, command_length);
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + 0) = op6_10_12_16_32;
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + cbw_WRITE_info[op].flags_pos) = 0;
|
|
for (i = cbw_WRITE_info[op].lba_pos + cbw_WRITE_info[op].lba_size - 1; i >= cbw_WRITE_info[op].lba_pos; i --)
|
|
{
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + i) = (UCHAR)lba;
|
|
lba >>= 8;
|
|
}
|
|
for (i = cbw_WRITE_info[op].len_pos + cbw_WRITE_info[op].len_size - 1; i >= cbw_WRITE_info[op].len_size; i --)
|
|
{
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + i) = (UCHAR)len;
|
|
len >>= 8;
|
|
}
|
|
}
|
|
static void _test_init_cbw_WRITE(UCHAR op6_10_12_16_32, ULONG lba, ULONG len)
|
|
{
|
|
_test_init_cbw_WRITE_EX(0x00, len * 512, op6_10_12_16_32, lba, len);
|
|
}
|
|
|
|
static void _test_init_cbw_REQUEST_SENSE(ULONG data_length)
|
|
{
|
|
|
|
UCHAR *cbw;
|
|
UINT command_length;
|
|
|
|
|
|
cbw = (UCHAR *) storage -> ux_host_class_storage_cbw;
|
|
command_length = UX_HOST_CLASS_STORAGE_REQUEST_SENSE_COMMAND_LENGTH_SBC;
|
|
_ux_host_class_storage_cbw_initialize(storage, 0x80, data_length, command_length);
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + 0) = UX_SLAVE_CLASS_STORAGE_SCSI_REQUEST_SENSE;
|
|
}
|
|
|
|
static void _test_init_cbw_TEST_READY(ULONG data_length)
|
|
{
|
|
|
|
UCHAR *cbw;
|
|
UINT command_length;
|
|
|
|
|
|
cbw = (UCHAR *) storage -> ux_host_class_storage_cbw;
|
|
command_length = UX_HOST_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_SBC;
|
|
_ux_host_class_storage_cbw_initialize(storage, 0x00, data_length, command_length);
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + 0) = UX_SLAVE_CLASS_STORAGE_SCSI_TEST_READY;
|
|
}
|
|
|
|
static void _test_init_cbw_FORMAT_UNIT(void)
|
|
{
|
|
|
|
UCHAR *cbw;
|
|
UINT command_length;
|
|
|
|
|
|
cbw = (UCHAR *) storage -> ux_host_class_storage_cbw;
|
|
command_length = UX_HOST_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_SBC;
|
|
_ux_host_class_storage_cbw_initialize(storage, 0, 0, command_length);
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + 0) = UX_SLAVE_CLASS_STORAGE_SCSI_FORMAT;
|
|
}
|
|
|
|
static void _test_init_cbw_START_STOP(void)
|
|
{
|
|
|
|
UCHAR *cbw;
|
|
UINT command_length;
|
|
|
|
|
|
cbw = (UCHAR *) storage -> ux_host_class_storage_cbw;
|
|
command_length = UX_HOST_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_SBC;
|
|
_ux_host_class_storage_cbw_initialize(storage, 0, 0, command_length);
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + 0) = UX_SLAVE_CLASS_STORAGE_SCSI_START_STOP;
|
|
}
|
|
|
|
static void _test_init_cbw_VERIFY(void)
|
|
{
|
|
|
|
UCHAR *cbw;
|
|
UINT command_length;
|
|
|
|
|
|
cbw = (UCHAR *) storage -> ux_host_class_storage_cbw;
|
|
command_length = UX_HOST_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_SBC;
|
|
_ux_host_class_storage_cbw_initialize(storage, 0, 0, command_length);
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + 0) = UX_SLAVE_CLASS_STORAGE_SCSI_VERIFY;
|
|
}
|
|
|
|
static void _test_init_cbw_MODE_SELECT(ULONG data_length)
|
|
{
|
|
|
|
UCHAR *cbw;
|
|
UINT command_length;
|
|
|
|
|
|
cbw = (UCHAR *) storage -> ux_host_class_storage_cbw;
|
|
command_length = UX_HOST_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_SBC;
|
|
_ux_host_class_storage_cbw_initialize(storage, 0, data_length, command_length);
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + 0) = UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SELECT;
|
|
}
|
|
|
|
static void _test_init_cbw_MODE_SENSE(UCHAR op6, UCHAR page_code, ULONG buffer_length)
|
|
{
|
|
|
|
UCHAR *cbw;
|
|
UINT command_length;
|
|
|
|
|
|
cbw = (UCHAR *) storage -> ux_host_class_storage_cbw;
|
|
command_length = UX_HOST_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_SBC;
|
|
_ux_host_class_storage_cbw_initialize(storage, 0x80, buffer_length, command_length);
|
|
if (op6)
|
|
{
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + 0) = UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE_SHORT;
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_SLAVE_CLASS_STORAGE_MODE_SENSE_PARAMETER_LIST_LENGTH_6) = (UCHAR)buffer_length;
|
|
}
|
|
else
|
|
{
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + 0) = UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE;
|
|
_ux_utility_short_put_big_endian(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_SLAVE_CLASS_STORAGE_MODE_SENSE_PARAMETER_LIST_LENGTH_10, (USHORT)buffer_length);
|
|
}
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_SLAVE_CLASS_STORAGE_MODE_SENSE_PC_PAGE_CODE) = page_code;
|
|
}
|
|
|
|
static void _test_init_cbw_SYNCHRONIZE_CACHE(UCHAR op16, UCHAR immed, ULONG lba, ULONG nb_blocks)
|
|
{
|
|
|
|
UCHAR *cbw;
|
|
UINT command_length;
|
|
|
|
|
|
(void)op16;
|
|
|
|
cbw = (UCHAR *) storage -> ux_host_class_storage_cbw;
|
|
command_length = UX_HOST_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_SBC;
|
|
_ux_host_class_storage_cbw_initialize(storage, 0, 0, command_length);
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + 0) = UX_SLAVE_CLASS_STORAGE_SCSI_SYNCHRONIZE_CACHE;
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_FLAGS) = immed ? UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_FLAGS_IMMED : 0;
|
|
_ux_utility_long_put_big_endian(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_LBA, lba);
|
|
_ux_utility_short_put_big_endian(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_NUMBER_OF_BLOCKS, (USHORT)nb_blocks);
|
|
}
|
|
|
|
static void _test_init_cbw_PREVENT_ALLOW_MEDIA_REMOVAL(void)
|
|
{
|
|
|
|
UCHAR *cbw;
|
|
UINT command_length;
|
|
|
|
|
|
cbw = (UCHAR *) storage -> ux_host_class_storage_cbw;
|
|
command_length = UX_HOST_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_SBC;
|
|
_ux_host_class_storage_cbw_initialize(storage, 0, 0, command_length);
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + 0) = UX_SLAVE_CLASS_STORAGE_SCSI_PREVENT_ALLOW_MEDIA_REMOVAL;
|
|
}
|
|
|
|
|
|
static void _msc_cbw_fail_cases_test(const char* __file__, int __line__)
|
|
{
|
|
UINT status;
|
|
UCHAR *cbw;
|
|
|
|
cbw = (UCHAR *) storage -> ux_host_class_storage_cbw;
|
|
|
|
stepinfo("\n%s:%d:MSC CBW fail tests\n", __file__, __line__);
|
|
|
|
stepinfo(">>>>>>>>>>>>>>>> Test VERIFY CBW length error\n");
|
|
_test_init_cbw_VERIFY();
|
|
status = _test_send_cbw_EX(__LINE__, UX_HOST_CLASS_STORAGE_CBW_LENGTH - 1);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 128, UX_TRUE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 128, UX_FALSE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
_ux_host_class_storage_device_reset(storage);
|
|
|
|
stepinfo(">>>>>>>>>>>>>>>> Test VERIFY CBW LUN error\n");
|
|
_test_init_cbw_VERIFY();
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_LUN + 0) = 0xFF;
|
|
status = _test_send_cbw_EX(__LINE__, UX_HOST_CLASS_STORAGE_CBW_LENGTH);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 128, UX_TRUE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 128, UX_FALSE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
_ux_host_class_storage_device_reset(storage);
|
|
|
|
stepinfo(">>>>>>>>>>>>>>>> Test VERIFY CBW Signature error\n");
|
|
_test_init_cbw_VERIFY();
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_SIGNATURE + 0) = 0xFF;
|
|
status = _test_send_cbw_EX(__LINE__, UX_HOST_CLASS_STORAGE_CBW_LENGTH);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 128, UX_TRUE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 128, UX_FALSE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
_ux_host_class_storage_device_reset(storage);
|
|
|
|
stepinfo(">>>>>>>>>>>>>>>> Test VERIFY CBW CBW_CB length error\n");
|
|
_test_init_cbw_VERIFY();
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB_LENGTH + 0) = 0;
|
|
status = _test_send_cbw_EX(__LINE__, UX_HOST_CLASS_STORAGE_CBW_LENGTH);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 128, UX_TRUE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 128, UX_FALSE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
_test_clear_stall(UX_FALSE);
|
|
_test_clear_stall(UX_TRUE);
|
|
_test_init_cbw_VERIFY();
|
|
status = _test_send_cbw_EX(__LINE__, UX_HOST_CLASS_STORAGE_CBW_LENGTH);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
_ux_host_class_storage_device_reset(storage);
|
|
|
|
stepinfo(">>>>>>>>>>>>>>>> Test CBW CMD unknown error\n");
|
|
_test_init_cbw_VERIFY();
|
|
*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + 0) = 0xFF;
|
|
status = _test_send_cbw_EX(__LINE__, UX_HOST_CLASS_STORAGE_CBW_LENGTH);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
_ux_host_class_storage_device_reset(storage);
|
|
}
|
|
|
|
|
|
static void _msc_get_max_lun_cases_test(const char* __file__, int __line__)
|
|
{
|
|
UINT status;
|
|
UX_DEVICE *device;
|
|
UX_ENDPOINT *control_endpoint;
|
|
UX_TRANSFER *transfer_request;
|
|
|
|
stepinfo("\n%s:%d:MSC GET_MAX_LUN tests\n", __file__, __line__);
|
|
|
|
status = ux_host_stack_device_get(0, &device);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: device_get fail\n", __LINE__, __line__);
|
|
test_control_return(1);
|
|
}
|
|
control_endpoint = &device->ux_device_control_endpoint;
|
|
transfer_request = &control_endpoint->ux_endpoint_transfer_request;
|
|
|
|
/* Send transfer request - GetMaxLun. */
|
|
transfer_request -> ux_transfer_request_data_pointer = UX_NULL;
|
|
transfer_request -> ux_transfer_request_requested_length = 0;
|
|
transfer_request -> ux_transfer_request_function = UX_SLAVE_CLASS_STORAGE_GET_MAX_LUN;
|
|
transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
|
|
transfer_request -> ux_transfer_request_value = 0;
|
|
transfer_request -> ux_transfer_request_index = storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceNumber;
|
|
status = ux_host_stack_transfer_request(transfer_request);
|
|
if (status != UX_SUCCESS && status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Invalid wValue. */
|
|
transfer_request -> ux_transfer_request_value = 1;
|
|
transfer_request -> ux_transfer_request_index = storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceNumber;
|
|
status = ux_host_stack_transfer_request(transfer_request);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Invalid wIndex. */
|
|
transfer_request -> ux_transfer_request_value = 0;
|
|
transfer_request -> ux_transfer_request_index = storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceNumber + 1;
|
|
status = ux_host_stack_transfer_request(transfer_request);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Send transfer request - UX_SLAVE_CLASS_STORAGE_RESET. */
|
|
transfer_request -> ux_transfer_request_function = UX_SLAVE_CLASS_STORAGE_RESET;
|
|
|
|
/* Invalid wValue. */
|
|
transfer_request -> ux_transfer_request_value = 1;
|
|
transfer_request -> ux_transfer_request_index = storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceNumber;
|
|
status = ux_host_stack_transfer_request(transfer_request);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Invalid wIndex. */
|
|
transfer_request -> ux_transfer_request_value = 0;
|
|
transfer_request -> ux_transfer_request_index = storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceNumber + 1;
|
|
status = ux_host_stack_transfer_request(transfer_request);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Invalid wLength. */
|
|
transfer_request -> ux_transfer_request_data_pointer = (UCHAR*)&status;
|
|
transfer_request -> ux_transfer_request_value = 0;
|
|
transfer_request -> ux_transfer_request_index = storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceNumber;
|
|
transfer_request -> ux_transfer_request_requested_length = 1;
|
|
status = ux_host_stack_transfer_request(transfer_request);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
}
|
|
|
|
static void _msc_inquiry_cases_test(const char* __file__, int __line__)
|
|
{
|
|
UINT status;
|
|
UX_SLAVE_DEVICE *slave_device;
|
|
UX_SLAVE_CLASS *slave_class;
|
|
UX_SLAVE_CLASS_STORAGE *slave_storage;
|
|
|
|
stepinfo("\n%s:%d:MSC INQUIRY tests\n", __file__, __line__);
|
|
|
|
stepinfo(">>>>>>>>>>>>>>>> Test INQUIRY(standard)\n");
|
|
status = test_host_class_storage_inquiry(storage, 0x00, buffer, 64);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>>>>>> Test INQUIRY(standard, UX_SLAVE_CLASS_STORAGE_MEDIA_CDROM)\n");
|
|
slave_device = &_ux_system_slave->ux_system_slave_device;
|
|
slave_class = _ux_system_slave->ux_system_slave_interface_class_array[0];
|
|
slave_storage = (UX_SLAVE_CLASS_STORAGE *)slave_class->ux_slave_class_instance;
|
|
slave_storage -> ux_slave_class_storage_lun[0].ux_slave_class_storage_media_type = UX_SLAVE_CLASS_STORAGE_MEDIA_CDROM;
|
|
status = test_host_class_storage_inquiry(storage, 0x00, buffer, 64);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>>>>>> Test INQUIRY(unknown page code)\n");
|
|
status = test_host_class_storage_inquiry(storage, 0xEF, buffer, 64);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>>>>>> Test INQUIRY(big buffer)\n");
|
|
status = _test_host_class_storage_inquiry(storage, 0x80,
|
|
64,
|
|
UX_HOST_CLASS_STORAGE_INQUIRY_COMMAND_LENGTH_SBC,
|
|
0x00, buffer, 64);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>>>>>> Test INQUIRY(Hi <> Do)\n");
|
|
status = _test_host_class_storage_inquiry(storage, 0x00,
|
|
UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH,
|
|
UX_HOST_CLASS_STORAGE_INQUIRY_COMMAND_LENGTH_SBC,
|
|
0x00, buffer, UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>>>>>> Test INQUIRY(Hi <> Do)\n");
|
|
status = _test_host_class_storage_inquiry(storage, 0x00,
|
|
0,
|
|
UX_HOST_CLASS_STORAGE_INQUIRY_COMMAND_LENGTH_SBC,
|
|
0x00, buffer, UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
}
|
|
|
|
static void _msc_read_cases_test(const char* __file__, int __line__)
|
|
{
|
|
UINT status;
|
|
|
|
stepinfo("\n%s:%d:MSC READ tests\n", __file__, __line__);
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_READ32 - success\n");
|
|
_test_init_cbw_READ(UX_SLAVE_CLASS_STORAGE_SCSI_READ32, 0, 1);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 512, UX_TRUE);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_READ16 - status fail\n");
|
|
ram_disk_status = UX_ERROR;
|
|
_test_init_cbw_READ(UX_SLAVE_CLASS_STORAGE_SCSI_READ16, 0, 1);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 512, UX_TRUE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
ram_disk_status = UX_SUCCESS;
|
|
_test_clear_stall(UX_TRUE);
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_READ16 - transfer fail\n");
|
|
_test_init_cbw_READ(UX_SLAVE_CLASS_STORAGE_SCSI_READ16, 0, 1);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
ux_test_dcd_sim_slave_set_actions(fail_on_bulkin);
|
|
status = _test_transfer_data(__LINE__, buffer, 512, UX_TRUE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
_test_clear_stall(UX_TRUE);
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_READ16 - Case(7) Hi < Di\n");
|
|
_test_init_cbw_READ_EX(0x80, 0, UX_SLAVE_CLASS_STORAGE_SCSI_READ16, 0, 1);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 512, UX_TRUE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
_test_clear_stall(UX_TRUE);
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
_ux_host_class_storage_device_reset(storage);
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_READ16 - Case(8) Hi <> Do\n");
|
|
_test_init_cbw_READ_EX(0x00, 512, UX_SLAVE_CLASS_STORAGE_SCSI_READ16, 0, 1);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 512, UX_FALSE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
_test_clear_stall(UX_FALSE);
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
_ux_host_class_storage_device_reset(storage);
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_READ16 - Case(5) Hi > Di\n");
|
|
_test_init_cbw_READ_EX(0x80, 1024, UX_SLAVE_CLASS_STORAGE_SCSI_READ16, 0, 1);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 1024, UX_TRUE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
_test_clear_stall(UX_TRUE);
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
_ux_host_class_storage_device_reset(storage);
|
|
}
|
|
|
|
static void _msc_write_cases_test(const char* __file__, int __line__)
|
|
{
|
|
UINT status;
|
|
UX_SLAVE_DEVICE *slave_device;
|
|
UX_SLAVE_CLASS *slave_class;
|
|
UX_SLAVE_CLASS_STORAGE *slave_storage;
|
|
|
|
stepinfo("\n%s:%d:MSC WRITE tests\n", __file__, __line__);
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32 - success\n");
|
|
_test_init_cbw_WRITE(UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32, 0, 1);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 512, UX_FALSE);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16 - status fail\n");
|
|
ram_disk_status = UX_ERROR;
|
|
_test_init_cbw_WRITE(UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16, 0, 1);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 512, UX_FALSE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
ram_disk_status = UX_SUCCESS;
|
|
_test_clear_stall(UX_FALSE);
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16 - transfer fail\n");
|
|
_test_init_cbw_WRITE(UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16, 0, 1);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
ux_test_dcd_sim_slave_set_actions(fail_on_bulkout);
|
|
status = _test_transfer_data(__LINE__, buffer, 512, UX_FALSE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
_test_clear_stall(UX_FALSE);
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16 - WP fail\n");
|
|
slave_device = &_ux_system_slave->ux_system_slave_device;
|
|
slave_class = _ux_system_slave->ux_system_slave_interface_class_array[0];
|
|
slave_storage = (UX_SLAVE_CLASS_STORAGE *)slave_class->ux_slave_class_instance;
|
|
slave_storage->ux_slave_class_storage_lun[0].ux_slave_class_storage_media_read_only_flag = UX_TRUE;
|
|
_test_init_cbw_WRITE(UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16, 0, 1);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 512, UX_FALSE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
_test_clear_stall(UX_FALSE);
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
slave_storage->ux_slave_class_storage_lun[0].ux_slave_class_storage_media_read_only_flag = UX_FALSE;
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16 - Case (3) Hn < Do\n");
|
|
_test_init_cbw_WRITE_EX(0x00, 0, UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16, 0, 1);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
#if 0 /* Host expect no data. */
|
|
status = _test_transfer_data(__LINE__, buffer, 512, UX_FALSE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
_test_clear_stall(UX_FALSE);
|
|
#endif
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
_ux_host_class_storage_device_reset(storage);
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16 - Case (8) Hi <> Do\n");
|
|
_test_init_cbw_WRITE_EX(0x80, 512, UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16, 0, 1);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 512, UX_TRUE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
_test_clear_stall(UX_TRUE);
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
_ux_host_class_storage_device_reset(storage);
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16 - Case (9) Ho > Do\n");
|
|
_test_init_cbw_WRITE_EX(0x00, 1024, UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16, 0, 1);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 1024, UX_FALSE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
_test_clear_stall(UX_FALSE);
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
_ux_host_class_storage_device_reset(storage);
|
|
}
|
|
|
|
static void _msc_request_sense_cases_test(const char* __file__, int __line__)
|
|
{
|
|
UINT status;
|
|
|
|
stepinfo("\n%s:%d:MSC REQUEST_SENSE tests\n", __file__, __line__);
|
|
|
|
_test_init_cbw_REQUEST_SENSE(64);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 64, UX_TRUE);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
_test_clear_stall(UX_TRUE);
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
_ux_host_class_storage_device_reset(storage);
|
|
}
|
|
|
|
static void _msc_test_ready_cases_test(const char* __file__, int __line__)
|
|
{
|
|
UINT status;
|
|
|
|
stepinfo("\n%s:%d:MSC UNIT_READY tests\n", __file__, __line__);
|
|
|
|
_test_init_cbw_TEST_READY(64);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 64, UX_FALSE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
_test_clear_stall(UX_FALSE);
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d.%d: code 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
_ux_host_class_storage_device_reset(storage);
|
|
}
|
|
|
|
static void _msc_format_unit_cases_test(const char* __file__, int __line__)
|
|
{
|
|
UINT status;
|
|
|
|
stepinfo("\n%s:%d:MSC FORMAT_UNIT tests\n", __file__, __line__);
|
|
|
|
_test_init_cbw_FORMAT_UNIT();
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
#if 0 /* Host expects no data. */
|
|
status = _test_transfer_data(__LINE__, "test dead beef", 15, UX_FALSE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
_test_clear_stall(UX_FALSE);
|
|
#endif
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_request_sense();
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
}
|
|
|
|
static void _msc_start_stop_cases_test(const char* __file__, int __line__)
|
|
{
|
|
UINT status;
|
|
|
|
stepinfo("\n%s:%d:MSC START_STOP tests\n", __file__, __line__);
|
|
|
|
_test_init_cbw_START_STOP();
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
}
|
|
|
|
static void _msc_verify_cases_test(const char* __file__, int __line__)
|
|
{
|
|
UINT status;
|
|
|
|
stepinfo("\n%s:%d:MSC VERIFY tests\n", __file__, __line__);
|
|
|
|
_test_init_cbw_VERIFY();
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
}
|
|
|
|
static void _msc_mode_sense_cases_test(const char* __file__, int __line__)
|
|
{
|
|
UINT status;
|
|
UX_SLAVE_DEVICE *slave_device;
|
|
UX_SLAVE_CLASS *slave_class;
|
|
UX_SLAVE_CLASS_STORAGE *slave_storage;
|
|
|
|
stepinfo("\n%s:%d:MSC MODE_SENSE tests\n", __file__, __line__);
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE(PAGE_CODE_CDROM):\n");
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE(PAGE_CODE_CDROM) - 128B\n");
|
|
_test_init_cbw_MODE_SENSE(UX_FALSE, UX_SLAVE_CLASS_STORAGE_MMC2_PAGE_CODE_CDROM, 128);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 128, UX_TRUE);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE(PAGE_CODE_CDROM) - 74B\n");
|
|
_test_init_cbw_MODE_SENSE(UX_TRUE, UX_SLAVE_CLASS_STORAGE_MMC2_PAGE_CODE_CDROM, 74);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 74, UX_TRUE);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Change read_only_flag */
|
|
slave_device = &_ux_system_slave->ux_system_slave_device;
|
|
slave_class = _ux_system_slave->ux_system_slave_interface_class_array[0];
|
|
slave_storage = (UX_SLAVE_CLASS_STORAGE *)slave_class->ux_slave_class_instance;
|
|
slave_storage->ux_slave_class_storage_lun[0].ux_slave_class_storage_media_read_only_flag = UX_TRUE;
|
|
|
|
/************ UX_SLAVE_CLASS_STORAGE_PAGE_CODE_CACHE ****************/
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE(PAGE_CODE_CACHE):\n");
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE(PAGE_CODE_CACHE) - 128B\n");
|
|
_test_init_cbw_MODE_SENSE(UX_FALSE, UX_SLAVE_CLASS_STORAGE_PAGE_CODE_CACHE, 128);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 128, UX_TRUE);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE(PAGE_CODE_CACHE) - 24B\n");
|
|
_test_init_cbw_MODE_SENSE(UX_TRUE, UX_SLAVE_CLASS_STORAGE_PAGE_CODE_CACHE, 24);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 24, UX_TRUE);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE(PAGE_CODE_CACHE) - 24B\n");
|
|
slave_storage->ux_slave_class_storage_lun[0].ux_slave_class_storage_media_flush = demo_media_flush;
|
|
_test_init_cbw_MODE_SENSE(UX_TRUE, UX_SLAVE_CLASS_STORAGE_PAGE_CODE_CACHE, 24);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 24, UX_TRUE);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/************ UX_SLAVE_CLASS_STORAGE_PAGE_CODE_IEC ****************/
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE(PAGE_CODE_IEC) - 128B\n");
|
|
_test_init_cbw_MODE_SENSE(UX_FALSE, UX_SLAVE_CLASS_STORAGE_PAGE_CODE_IEC, 128);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 128, UX_TRUE);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE(PAGE_CODE_IEC) - 16B\n");
|
|
_test_init_cbw_MODE_SENSE(UX_TRUE, UX_SLAVE_CLASS_STORAGE_PAGE_CODE_IEC, 16);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 16, UX_TRUE);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/************ 0x3F ****************/
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE(0x3F) - 128B\n");
|
|
_test_init_cbw_MODE_SENSE(UX_FALSE, 0x3F, 128);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 128, UX_TRUE);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/************ 0x3F ****************/
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE(0x3F) - %dB\n",
|
|
UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE + 8);
|
|
_test_init_cbw_MODE_SENSE(UX_FALSE, 0x3F, UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE + 8);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, buffer, 128, UX_TRUE);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
}
|
|
|
|
static void _msc_mode_select_cases_test(const char* __file__, int __line__)
|
|
{
|
|
UINT status;
|
|
|
|
stepinfo("\n%s:%d:MSC MODE_SELECT tests\n", __file__, __line__);
|
|
|
|
_test_init_cbw_MODE_SELECT(15);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_transfer_data(__LINE__, "test dead beef", 15, UX_FALSE);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
_test_clear_stall(UX_FALSE);
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_request_sense();
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
}
|
|
|
|
static void _msc_synchronous_cache_cases_test(const char* __file__, int __line__)
|
|
{
|
|
UINT status;
|
|
UX_SLAVE_DEVICE *slave_device;
|
|
UX_SLAVE_CLASS *slave_class;
|
|
UX_SLAVE_CLASS_STORAGE *slave_storage;
|
|
|
|
stepinfo("\n%s:%d:MSC SYNCHRONOUS_CACHE tests\n", __file__, __line__);
|
|
|
|
slave_device = &_ux_system_slave->ux_system_slave_device;
|
|
slave_class = _ux_system_slave->ux_system_slave_interface_class_array[0];
|
|
slave_storage = (UX_SLAVE_CLASS_STORAGE *)slave_class->ux_slave_class_instance;
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_SYNCHRONIZE_CACHE no CB - success\n");
|
|
slave_storage->ux_slave_class_storage_lun[0].ux_slave_class_storage_media_flush = UX_NULL;
|
|
slave_storage->ux_slave_class_storage_lun[1].ux_slave_class_storage_media_flush = UX_NULL;
|
|
_test_init_cbw_SYNCHRONIZE_CACHE(UX_FALSE, UX_FALSE, 0, 1);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_SYNCHRONIZE_CACHE - success\n");
|
|
slave_storage->ux_slave_class_storage_lun[0].ux_slave_class_storage_media_flush = demo_media_flush;
|
|
slave_storage->ux_slave_class_storage_lun[1].ux_slave_class_storage_media_flush = demo_media_flush;
|
|
_test_init_cbw_SYNCHRONIZE_CACHE(UX_FALSE, UX_FALSE, 0, 1);
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_SYNCHRONIZE_CACHE - status fail\n");
|
|
_test_init_cbw_SYNCHRONIZE_CACHE(UX_FALSE, UX_FALSE, 0, 1);
|
|
ram_disk_status = UX_ERROR;
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw_EX(__LINE__);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
_test_clear_stall(UX_TRUE);
|
|
status = _test_wait_csw_EX(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_request_sense();
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
ram_disk_status = UX_SUCCESS;
|
|
|
|
stepinfo(">>>>>>>>>>>>>>> UX_SLAVE_CLASS_STORAGE_SCSI_SYNCHRONIZE_CACHE - flush fail\n");
|
|
_test_init_cbw_SYNCHRONIZE_CACHE(UX_FALSE, UX_FALSE, 0, 1);
|
|
ram_disk_flush_status = UX_STATE_ERROR;
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw_EX(__LINE__);
|
|
if (status != UX_TRANSFER_STALLED)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
_test_clear_stall(UX_TRUE);
|
|
status = _test_wait_csw_EX(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
ram_disk_flush_status = UX_STATE_NEXT;
|
|
}
|
|
|
|
static void _msc_prevent_allow_removal_cases_test(const char* __file__, int __line__)
|
|
{
|
|
UINT status;
|
|
|
|
stepinfo("\n%s:%d:MSC PREVENT_ALLOW_MEDIA_REMOVAL tests\n", __file__, __line__);
|
|
|
|
_test_init_cbw_PREVENT_ALLOW_MEDIA_REMOVAL();
|
|
status = _test_send_cbw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
status = _test_wait_csw(__LINE__);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR #%d: code 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
}
|
|
|
|
|
|
static void _msc_media_read_test(const char* __file__, int __line__)
|
|
{
|
|
UINT status;
|
|
ULONG test_n;
|
|
ULONG test_size[] = {
|
|
UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE * 2 / 512,
|
|
UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE * 3 / 512,
|
|
UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE * 2 / 512 + 1};
|
|
|
|
stepinfo("\n%s:%d:MSC Media Read tests\n", __file__, __line__);
|
|
|
|
if (media == UX_NULL || media -> fx_media_id == 0)
|
|
{
|
|
printf("ERROR %d: media error\n", __LINE__);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>> Disk read(1) test\n");
|
|
{
|
|
status = fx_media_read(media, 48, buffer);
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
printf("ERROR %d: 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
}
|
|
|
|
/* Disk read multiple test. */
|
|
for (test_n = 0; test_n < sizeof(test_size)/sizeof(test_size[0]); test_n ++)
|
|
{
|
|
|
|
stepinfo(">>>>>>>>>>>> Disk read(%d) test\n", test_size[test_n]);
|
|
status = _media_driver_read(media, _ux_host_class_storage_driver_entry,
|
|
buffer, 0, test_size[test_n]);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR %d.%ld: 0x%x\n", __LINE__, test_n, status);
|
|
test_control_return(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void _msc_media_write_read_test(const char* __file__, int __line__)
|
|
{
|
|
UINT status;
|
|
ULONG test_n;
|
|
INT i;
|
|
ULONG test_size[] = {
|
|
UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE * 2 / 512,
|
|
UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE * 3 / 512,
|
|
UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE * 2 / 512 + 1};
|
|
|
|
stepinfo("\n%s:%d:MSC Media Write & Read tests\n", __file__, __line__);
|
|
|
|
/* Check if media still available. */
|
|
if (media == UX_NULL || media -> fx_media_id == 0)
|
|
{
|
|
printf("ERROR %d: media error\n", __LINE__);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>> Disk write(1)/read(1) test\n");
|
|
{
|
|
for(i = 0; i < 512; i ++)
|
|
buffer[i] = i;
|
|
status = fx_media_write(media, 48, buffer);
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
printf("ERROR %d: 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
_ux_utility_memory_set(buffer, 0x00, 512);
|
|
status = fx_media_read(media, 48, buffer);
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
printf("ERROR %d: 0x%x\n", __LINE__, status);
|
|
test_control_return(1);
|
|
}
|
|
for (i = 0; i < 512; i ++)
|
|
{
|
|
if (buffer[i] != (UCHAR)i)
|
|
{
|
|
printf("ERROR %d: %d <> %d\n", __LINE__, i, buffer[i]);
|
|
test_control_return(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Disk write/read multiple test. */
|
|
for (test_n = 0; test_n < sizeof(test_size)/sizeof(test_size[0]); test_n ++)
|
|
{
|
|
stepinfo(">>>>>>>>>>>> Disk write(%ld)/read(%ld) test\n",
|
|
test_size[test_n], test_size[test_n]);
|
|
|
|
for(i = 0; i < test_size[test_n] * 512; i ++)
|
|
buffer[i] = (UCHAR)(i + (i >> 8));
|
|
status = _media_driver_write(media, _ux_host_class_storage_driver_entry,
|
|
buffer, 48, test_size[test_n]);
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
printf("ERROR %d.%ld: 0x%x\n", __LINE__, test_n, status);
|
|
test_control_return(1);
|
|
}
|
|
_ux_utility_memory_set(buffer, 0x00, test_size[test_n] * 512);
|
|
status = _media_driver_read(media, _ux_host_class_storage_driver_entry,
|
|
buffer, 48, test_size[test_n]);
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
printf("ERROR %d.%ld: 0x%x\n", __LINE__, test_n, status);
|
|
test_control_return(1);
|
|
}
|
|
for (i = 0; i < 512; i ++)
|
|
{
|
|
if (buffer[i] != (UCHAR)(i + (i >> 8)))
|
|
{
|
|
printf("ERROR %d: %d <> %d\n", __LINE__, i, buffer[i]);
|
|
test_control_return(1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void _msc_enumeration_test(const char* __file__, int __line__, unsigned option)
|
|
{
|
|
UINT status;
|
|
ULONG mem_free;
|
|
ULONG test_n;
|
|
|
|
stepinfo("\n%s:%d:MSC Enumeration tests\n", __file__, __line__);
|
|
|
|
stepinfo(">>>>>>>>>>>> Enumeration information collection\n");
|
|
{
|
|
|
|
/* Test disconnect. */
|
|
ux_test_dcd_sim_slave_disconnect();
|
|
ux_test_hcd_sim_host_disconnect();
|
|
|
|
/* Check connection. */
|
|
status = host_storage_instance_get(0);
|
|
if (status == UX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d\n", __LINE__);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Reset testing counts. */
|
|
ux_test_utility_sim_mem_alloc_count_reset();
|
|
ux_test_utility_sim_mutex_create_count_reset();
|
|
ux_test_utility_sim_sem_create_count_reset();
|
|
ux_test_utility_sim_sem_get_count_reset();
|
|
ux_test_hcd_sim_host_set_actions(log_on_SetCfg);
|
|
|
|
/* Save free memory usage. */
|
|
mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
|
|
ux_test_dcd_sim_slave_connect(UX_HIGH_SPEED_DEVICE);
|
|
ux_test_hcd_sim_host_connect(UX_HIGH_SPEED_DEVICE);
|
|
|
|
/* Check connection. */
|
|
status = host_storage_instance_get(50);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d\n", __LINE__);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* 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_alloc_count = rsc_mem_alloc_cnt_on_set_cfg;
|
|
/* Log create counts when instances active for further tests. */
|
|
rsc_storage_mutex_usage = ux_test_utility_sim_mutex_create_count() - rsc_enum_mutex_usage;
|
|
rsc_storage_sem_usage = ux_test_utility_sim_sem_create_count() - rsc_enum_sem_usage;
|
|
rsc_storage_mem_alloc_count = ux_test_utility_sim_mem_alloc_count() - rsc_enum_mem_alloc_count;
|
|
|
|
/* Lock log base for tests. */
|
|
ux_test_utility_sim_mem_alloc_log_lock();
|
|
|
|
stepinfo("enum mem: %ld\n", rsc_enum_mem_alloc_count);
|
|
stepinfo("storage mem : %ld\n", rsc_storage_mem_alloc_count);
|
|
stepinfo("mem free: %ld, %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available, _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] -> ux_byte_pool_available);
|
|
}
|
|
|
|
/* Simulate detach and attach for FS enumeration,
|
|
and check if there is memory error in normal enumeration.
|
|
*/
|
|
if (option & (1u))
|
|
{
|
|
stepinfo(">>>>>>>>>>>> Enumeration test\n");
|
|
mem_free = (~0);
|
|
for (test_n = 0; test_n < 3; test_n++)
|
|
{
|
|
stepinfo("%4ld / 2\n", test_n);
|
|
|
|
/* Disconnect. */
|
|
ux_test_dcd_sim_slave_disconnect();
|
|
ux_test_hcd_sim_host_disconnect();
|
|
|
|
/* Check */
|
|
if (host_storage_instance_get(0) == UX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d.%ld: Disconnect fail\n", __LINE__, test_n);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Update memory free level (disconnect) */
|
|
if (mem_free == (~0))
|
|
mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
|
|
else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
|
|
{
|
|
|
|
printf("ERROR #%d.%ld: Memory level different after re-enumerations %ld <> %ld\n", __LINE__, test_n, mem_free, _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Connect. */
|
|
error_callback_counter = 0;
|
|
ux_test_dcd_sim_slave_connect(UX_HIGH_SPEED_DEVICE);
|
|
ux_test_hcd_sim_host_connect(UX_HIGH_SPEED_DEVICE);
|
|
|
|
/* Wait and break on error. */
|
|
error_callback_counter = 0;
|
|
ux_test_breakable_sleep(
|
|
(UX_MS_TO_TICK_NON_ZERO(UX_RH_ENUMERATION_RETRY_DELAY) +
|
|
UX_MS_TO_TICK_NON_ZERO(UX_HOST_CLASS_STORAGE_DEVICE_INIT_DELAY)) *
|
|
3,
|
|
sleep_break_on_connect);
|
|
|
|
/* Check */
|
|
if (host_storage_instance_get(0) != UX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d.%ld: Enumeration fail\n", __LINE__, test_n);
|
|
test_control_return(1);
|
|
}
|
|
}
|
|
stepinfo("\n");
|
|
}
|
|
|
|
/* Simulate detach and attach for FS enumeration,
|
|
and test possible memory allocation error handlings.
|
|
*/
|
|
if (option & (2u))
|
|
{
|
|
if (rsc_storage_mem_alloc_count) stepinfo(">>>>>>>>>>>> Memory errors enumeration test\n");
|
|
mem_free = (~0);
|
|
for (test_n = 0; test_n < rsc_storage_mem_alloc_count; test_n ++)
|
|
{
|
|
|
|
stepinfo("%4ld / %4ld\n", test_n, rsc_storage_mem_alloc_count - 1);
|
|
|
|
/* Disconnect. */
|
|
ux_test_dcd_sim_slave_disconnect();
|
|
ux_test_hcd_sim_host_disconnect();
|
|
|
|
/* Check */
|
|
if (host_storage_instance_get(0) == UX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d.%ld: Disconnect fail\n", __LINE__, test_n);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Update memory free level (disconnect) */
|
|
if (mem_free == (~0))
|
|
mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
|
|
else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
|
|
{
|
|
|
|
printf("ERROR #%d.%ld: Memory level different after re-enumerations %ld <> %ld\n", __LINE__, test_n, mem_free, _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Set memory error generation */
|
|
ux_test_utility_sim_mem_alloc_error_generation_start(test_n + rsc_enum_mem_alloc_count);
|
|
|
|
/* Connect. */
|
|
error_callback_counter = 0;
|
|
ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
|
|
ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
|
|
|
|
/* Wait and break on errors. */
|
|
ux_test_breakable_sleep(100, sleep_break_on_error);
|
|
|
|
/* Check error */
|
|
if (host_storage_instance_get(0) == UX_SUCCESS)
|
|
{
|
|
|
|
/* Could be media errors,
|
|
in this case instance is ready,
|
|
check error trap. */
|
|
if (error_callback_counter == 0)
|
|
{
|
|
printf("ERROR #%d.%ld: device detected when there is memory error\n", __LINE__, test_n);
|
|
test_control_return(1);
|
|
}
|
|
}
|
|
stepinfo("mem free: %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
|
|
}
|
|
ux_test_utility_sim_mem_alloc_error_generation_stop();
|
|
if (rsc_storage_mem_alloc_count) stepinfo("\n");
|
|
}
|
|
}
|
|
|
|
static void _msc_media_write_read_misc_test(const char* __file__, int __line__)
|
|
{
|
|
UINT status;
|
|
UINT test_size = UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE * 3 / 512;
|
|
UINT test_n;
|
|
ULONG test_start;
|
|
ULONG test_ticks;
|
|
INT i;
|
|
|
|
stepinfo("\n%s:%d:MSC Media Read tests\n", __file__, __line__);
|
|
|
|
if (media == UX_NULL || media -> fx_media_id == 0)
|
|
{
|
|
printf("ERROR %d.%d: media error\n", __LINE__, __line__);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>> Disk read(%d) test - tick obtain\n", test_size);
|
|
test_start = tx_time_get();
|
|
status = _media_driver_read(media, _ux_host_class_storage_driver_entry,
|
|
buffer, 0, test_size);
|
|
test_ticks = _test_dw_minus(tx_time_get(), test_start);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
printf("ERROR %d.%d: 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
test_ticks /= 3;
|
|
stepinfo(" :: Buffer XFR time: %ld ticks\n", test_ticks);
|
|
|
|
stepinfo(">>>>>>>>>>>> Disk write/read(%d) test - slow disk write/read\n", test_size);
|
|
ram_disk_rw_wait_delay = ((test_ticks + 1) >> 1) + 1;
|
|
for(test_n = 0; test_n < 4; test_n ++)
|
|
{
|
|
stepinfo(">>>>>>>>>>>> Disk write/read(%d) test - disk write/read wait %ld\n",
|
|
test_size, ram_disk_rw_wait_delay);
|
|
for(i = 0; i < test_size * 512; i ++)
|
|
buffer[i] = (UCHAR)(i + (i >> 8));
|
|
ram_disk_rw_wait_start = tx_time_get();
|
|
status = _media_driver_write(media, _ux_host_class_storage_driver_entry,
|
|
buffer, 48, test_size);
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
printf("ERROR %d.%d.%d: 0x%x\n", __LINE__, __line__, test_n, status);
|
|
test_control_return(1);
|
|
}
|
|
_ux_utility_memory_set(buffer, 0x00, test_size * 512);
|
|
ram_disk_rw_wait_start = tx_time_get();
|
|
status = _media_driver_read(media, _ux_host_class_storage_driver_entry,
|
|
buffer, 48, test_size);
|
|
if (status != FX_SUCCESS)
|
|
{
|
|
printf("ERROR %d.%d.%d: 0x%x\n", __LINE__, __line__, test_n, status);
|
|
test_control_return(1);
|
|
}
|
|
for (i = 0; i < 512; i ++)
|
|
{
|
|
if (buffer[i] != (UCHAR)(i + (i >> 8)))
|
|
{
|
|
printf("ERROR %d.%d.%d: %d <> %d\n", __LINE__, __line__, test_n, i, buffer[i]);
|
|
test_control_return(1);
|
|
}
|
|
}
|
|
ram_disk_rw_wait_delay <<= 1;
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>> Disk read(%d) test - USB fail while disk waiting\n", test_size);
|
|
ram_disk_rw_wait_start = tx_time_get();
|
|
ram_disk_rw_count = 0;
|
|
ram_disk_rw_fail_mode = 0x81;
|
|
ram_disk_rw_fail_after = 1;
|
|
status = _media_driver_read(media, _ux_host_class_storage_driver_entry,
|
|
buffer, 48, test_size);
|
|
if (status == UX_SUCCESS)
|
|
{
|
|
printf("ERROR %d.%d: 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>> Disk write(%d) test - USB fail while disk waiting\n", test_size);
|
|
ram_disk_rw_wait_start = tx_time_get();
|
|
ram_disk_rw_count = 0;
|
|
ram_disk_rw_fail_mode = 0x82;
|
|
ram_disk_rw_fail_after = 0;
|
|
status = _media_driver_write(media, _ux_host_class_storage_driver_entry,
|
|
buffer, 48, test_size);
|
|
if (0 /*status == UX_SUCCESS*/)
|
|
{
|
|
printf("ERROR %d.%d: 0x%x\n", __LINE__, __line__, status);
|
|
test_control_return(1);
|
|
}
|
|
|
|
/* Restore: no disk wait delay. */
|
|
ram_disk_rw_fail_after = 0xFFFFFFFF;
|
|
ram_disk_rw_wait_delay = 0;
|
|
}
|
|
|
|
|
|
static void tx_demo_thread_host_simulation_entry(ULONG arg)
|
|
{
|
|
|
|
UINT status;
|
|
|
|
|
|
/* Find the storage class. */
|
|
status = host_storage_instance_get(800);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
|
|
printf("ERROR #%d\n", __LINE__);
|
|
test_control_return(1);
|
|
}
|
|
|
|
stepinfo(">>>>>>>>>>>> MSC Basic test\n");
|
|
|
|
_msc_media_read_test(__FILE__, __LINE__);
|
|
_msc_enumeration_test(__FILE__, __LINE__, 3);
|
|
#if 0 /* Moved to read write test. */
|
|
_msc_media_write_read_test(__FILE__, __LINE__);
|
|
_msc_media_write_read_misc_test(__FILE__, __LINE__);
|
|
#endif
|
|
#if 0 /* Moved to CV test. */
|
|
stepinfo(">>>>>>>>>>>> MSC Error & CV cases test\n");
|
|
|
|
#ifndef UX_STANDALONE
|
|
/* Pause the class driver thread. */
|
|
_ux_utility_thread_suspend(&((UX_HOST_CLASS_STORAGE_EXT*)storage->ux_host_class_storage_class->ux_host_class_ext)->ux_host_class_thread);
|
|
#endif
|
|
|
|
_msc_cbw_fail_cases_test(__FILE__, __LINE__);
|
|
|
|
_msc_get_max_lun_cases_test(__FILE__, __LINE__);
|
|
_msc_inquiry_cases_test(__FILE__, __LINE__);
|
|
_msc_read_cases_test(__FILE__, __LINE__);
|
|
_msc_write_cases_test(__FILE__, __LINE__);
|
|
_msc_request_sense_cases_test(__FILE__, __LINE__);
|
|
_msc_test_ready_cases_test(__FILE__, __LINE__);
|
|
_msc_format_unit_cases_test(__FILE__, __LINE__);
|
|
_msc_start_stop_cases_test(__FILE__, __LINE__);
|
|
_msc_verify_cases_test(__FILE__, __LINE__);
|
|
_msc_mode_sense_cases_test(__FILE__, __LINE__);
|
|
_msc_mode_select_cases_test(__FILE__, __LINE__);
|
|
_msc_synchronous_cache_cases_test(__FILE__, __LINE__);
|
|
_msc_prevent_allow_removal_cases_test(__FILE__, __LINE__);
|
|
|
|
#ifndef UX_STANDALONE
|
|
/* Resume the class driver thread. */
|
|
_ux_utility_thread_resume(&((UX_HOST_CLASS_STORAGE_EXT*)storage->ux_host_class_storage_class->ux_host_class_ext)->ux_host_class_thread);
|
|
#endif
|
|
#endif
|
|
|
|
/* Finally disconnect the device. */
|
|
ux_device_stack_disconnect();
|
|
|
|
/* And deinitialize the class. */
|
|
status = ux_device_stack_class_unregister(_ux_system_slave_class_storage_name, ux_device_class_storage_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);
|
|
}
|
|
|
|
|
|
static UINT demo_media_status(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status)
|
|
{
|
|
|
|
static UCHAR lun_init_done[2] = {0, 0};
|
|
UINT status;
|
|
ULONG mstatus = UX_SLAVE_CLASS_STORAGE_SENSE_KEY_NO_SENSE;
|
|
|
|
|
|
(void)storage;
|
|
(void)media_id;
|
|
|
|
if (ram_disk_status)
|
|
{
|
|
status = ram_disk_status;
|
|
if (media_status)
|
|
*media_status = ram_disk_media_status;
|
|
ram_disk_status = UX_SUCCESS;
|
|
ram_disk_status_sent = UX_TRUE;
|
|
return(status);
|
|
}
|
|
|
|
if (lun > 1)
|
|
status = (UX_ERROR);
|
|
else if (lun_init_done[lun] > 0)
|
|
status = (UX_SUCCESS);
|
|
else
|
|
{
|
|
lun_init_done[lun] ++;
|
|
mstatus = UX_SLAVE_CLASS_STORAGE_SENSE_KEY_UNIT_ATTENTION | (0x28 << 8);
|
|
status = (UX_ERROR);
|
|
}
|
|
|
|
if (media_status)
|
|
*media_status = mstatus;
|
|
|
|
return status;
|
|
}
|
|
|
|
static UINT demo_media_read(VOID *storage, ULONG lun, UCHAR * data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status)
|
|
{
|
|
|
|
UINT status = 0;
|
|
|
|
/* Abort. */
|
|
if (data_pointer == UX_NULL)
|
|
{
|
|
ram_disk_rw_wait_state = 0;
|
|
return(UX_STATE_NEXT);
|
|
}
|
|
|
|
/* Media RW fail simulation. */
|
|
if (ram_disk_rw_fail_after < 0xFFFFFFFF)
|
|
{
|
|
ram_disk_rw_count ++;
|
|
if (ram_disk_rw_count >= ram_disk_rw_fail_after)
|
|
{
|
|
if (ram_disk_rw_fail_mode_one_shot())
|
|
{
|
|
ram_disk_rw_fail_after = 0xFFFFFFFF;
|
|
ram_disk_rw_count = 0;
|
|
}
|
|
if (ram_disk_rw_fail_mode_bulk_in())
|
|
ux_test_dcd_sim_slave_set_actions(fail_on_bulkin);
|
|
else if (ram_disk_rw_fail_mode_bulk_out())
|
|
ux_test_dcd_sim_slave_set_actions(fail_on_bulkout);
|
|
else if (ram_disk_rw_fail_mode_disk())
|
|
{
|
|
*media_status = UX_DEVICE_CLASS_STORAGE_SENSE_STATUS(0x02,0x54,0x00);
|
|
return(UX_STATE_ERROR);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Media RW wait simulation. */
|
|
if (ram_disk_rw_wait_delay)
|
|
{
|
|
if (_test_dw_minus(tx_time_get(), ram_disk_rw_wait_start) < ram_disk_rw_wait_delay)
|
|
{
|
|
ram_disk_rw_wait_state = 1;
|
|
return(UX_STATE_WAIT);
|
|
}
|
|
ram_disk_rw_wait_state = 0;
|
|
ram_disk_rw_wait_start = tx_time_get();
|
|
}
|
|
|
|
status = _media_driver_read(ram_disks[lun], _fx_ram_driver, data_pointer, lba, number_blocks);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
*media_status = UX_DEVICE_CLASS_STORAGE_SENSE_STATUS(0x02,0x54,0x00);
|
|
return(UX_STATE_ERROR);
|
|
}
|
|
return(UX_STATE_NEXT);
|
|
}
|
|
|
|
static UINT demo_media_write(VOID *storage, ULONG lun, UCHAR * data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status)
|
|
{
|
|
|
|
UINT status = 0;
|
|
|
|
/* Abort. */
|
|
if (data_pointer == UX_NULL)
|
|
{
|
|
ram_disk_rw_wait_state = 0;
|
|
return(UX_STATE_NEXT);
|
|
}
|
|
|
|
/* Media RW fail simulation. */
|
|
if (ram_disk_rw_fail_after < 0xFFFFFFFF)
|
|
{
|
|
ram_disk_rw_count ++;
|
|
if (ram_disk_rw_count >= ram_disk_rw_fail_after)
|
|
{
|
|
if (ram_disk_rw_fail_mode_one_shot())
|
|
{
|
|
ram_disk_rw_fail_after = 0xFFFFFFFF;
|
|
ram_disk_rw_count = 0;
|
|
}
|
|
if (ram_disk_rw_fail_mode_bulk_in())
|
|
ux_test_dcd_sim_slave_set_actions(fail_on_bulkin);
|
|
else if (ram_disk_rw_fail_mode_bulk_out())
|
|
ux_test_dcd_sim_slave_set_actions(fail_on_bulkout);
|
|
else if (ram_disk_rw_fail_mode_disk())
|
|
{
|
|
*media_status = UX_DEVICE_CLASS_STORAGE_SENSE_STATUS(0x02,0x54,0x00);
|
|
return(UX_STATE_ERROR);
|
|
}
|
|
}
|
|
}
|
|
/* Media RW wait simulation. */
|
|
if (ram_disk_rw_wait_delay)
|
|
{
|
|
if (_test_dw_minus(tx_time_get(), ram_disk_rw_wait_start) < ram_disk_rw_wait_delay)
|
|
{
|
|
ram_disk_rw_wait_state = 1;
|
|
return(UX_STATE_WAIT);
|
|
}
|
|
ram_disk_rw_wait_state = 0;
|
|
ram_disk_rw_wait_start = tx_time_get();
|
|
}
|
|
|
|
status = _media_driver_write(ram_disks[lun], _fx_ram_driver, data_pointer, lba, number_blocks);
|
|
if (status != UX_SUCCESS)
|
|
{
|
|
*media_status = UX_DEVICE_CLASS_STORAGE_SENSE_STATUS(0x02,0x54,0x00);
|
|
return(UX_STATE_ERROR);
|
|
}
|
|
return(UX_STATE_NEXT);
|
|
}
|
|
|
|
static UINT demo_media_flush(VOID *storage, ULONG lun, ULONG number_blocks, ULONG lba, ULONG *media_status)
|
|
{
|
|
(void)storage;
|
|
(void)number_blocks;
|
|
(void)lba;
|
|
(void)media_status;
|
|
|
|
if (lun > 1)
|
|
return UX_STATE_ERROR;
|
|
|
|
ram_disk_flush = UX_TRUE;
|
|
return ram_disk_flush_status;
|
|
}
|
|
|
|
static UINT ux_test_system_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
|
|
{
|
|
|
|
switch(event)
|
|
{
|
|
|
|
case UX_DEVICE_INSERTION:
|
|
break;
|
|
|
|
case UX_DEVICE_REMOVAL:
|
|
break;
|
|
|
|
#if defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
|
|
case UX_STORAGE_MEDIA_INSERTION:
|
|
/* keep using first media. */
|
|
if (_ux_host_class_storage_media_index((UX_HOST_CLASS_STORAGE_MEDIA*)inst) == 0)
|
|
{
|
|
_ux_host_class_storage_media_insert((UX_HOST_CLASS_STORAGE_MEDIA*)inst, 1);
|
|
storage_media = (UX_HOST_CLASS_STORAGE_MEDIA*)inst;
|
|
media = _ux_host_class_storage_media_fx_media((UX_HOST_CLASS_STORAGE_MEDIA*)inst);
|
|
}
|
|
break;
|
|
|
|
case UX_STORAGE_MEDIA_REMOVAL:
|
|
if (_ux_host_class_storage_media_index((UX_HOST_CLASS_STORAGE_MEDIA*)inst) == 0)
|
|
{
|
|
_ux_host_class_storage_media_remove((UX_HOST_CLASS_STORAGE_MEDIA*)inst);
|
|
storage_media = UX_NULL;
|
|
media = UX_NULL;
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|