Add regression tests. (#126)

Add regression tests (auto triggered on PR, manually triggered in forked branch).
This commit is contained in:
CQ Xiao 2023-11-28 15:50:39 +08:00 committed by GitHub
parent 26585e42dc
commit 6ed7092b77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
549 changed files with 287858 additions and 0 deletions

61
.github/workflows/regression_test.yml vendored Normal file
View File

@ -0,0 +1,61 @@
name: USBX Regression Test
# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
workflow_dispatch:
inputs:
tests_to_run:
description: 'all, single or multiple of default_build_coverage error_check_build_full_coverage tracex_enable_build device_buffer_owner_build device_zero_copy_build nofx_build_coverage optimized_build standalone_device_build_coverage standalone_device_buffer_owner_build standalone_device_zero_copy_build standalone_host_build_coverage standalone_build_coverage generic_build otg_support_build memory_management_build_coverage msrc_rtos_build msrc_standalone_build'
required: false
default: 'default_build_coverage'
skip_coverage:
required: false
type: boolean
default: false
coverage_name:
required: false
default: 'default_build_coverage'
push:
branches: [ master ]
pull_request:
branches: [ master ]
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
manual_tests:
if: github.event_name == 'workflow_dispatch'
permissions:
contents: read
issues: read
checks: write
pull-requests: write
pages: write
id-token: write
uses: azure-rtos/threadx/.github/workflows/regression_template.yml@master
with:
cmake_path: ./test/cmake/usbx
build_script: ./scripts/build.sh ${{ inputs.tests_to_run }}
test_script: ./scripts/test.sh ${{ inputs.tests_to_run }}
coverage_name: ${{ inputs.coverage_name }}
skip_coverage: ${{ !!inputs.skip_coverage }}
auto_tests:
if: github.event_name != 'workflow_dispatch'
permissions:
contents: read
issues: read
checks: write
pull-requests: write
pages: write
id-token: write
uses: azure-rtos/threadx/.github/workflows/regression_template.yml@master
with:
cmake_path: ./test/cmake/usbx
build_script: ./scripts/build.sh default_build_coverage
test_script: ./scripts/test.sh default_build_coverage
coverage_name: default_build_coverage
skip_coverage: false

2
scripts/build.sh Executable file
View File

@ -0,0 +1,2 @@
#!/bin/bash
$(dirname `realpath $0`)/../test/cmake/usbx/run.sh build $@

25
scripts/install.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/bash
#
# Install necessary softwares for Ubuntu.
sudo apt-get update
sudo apt-get install -y \
gcc-multilib \
git \
g++ \
python3-pip \
ninja-build \
unifdef \
p7zip-full \
tofrodos \
gawk \
software-properties-common
wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | sudo apt-key add -
CODENAME=$(lsb_release -c | cut -f2 -d':' | sed 's/\t//')
sudo apt-add-repository -y "deb https://apt.kitware.com/ubuntu/ $CODENAME main"
sudo apt-get -y install cmake
python3 -m pip install --upgrade pip
pip3 install gcovr==4.1
pip3 install --upgrade cmake

2
scripts/test.sh Executable file
View File

@ -0,0 +1,2 @@
#!/bin/bash
CTEST_PARALLEL_LEVEL=4 $(dirname `realpath $0`)/../test/cmake/usbx/run.sh test $@

View File

@ -0,0 +1,37 @@
cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
project(libs LANGUAGES C)
if($ENV{ENABLE_64})
message(STATUS "Building for 64bit")
set(NX_USER_FILE ${CMAKE_CURRENT_SOURCE_DIR}/nx_user.h)
else()
add_compile_options(-m32)
add_link_options(-m32)
message(STATUS "Building for 32bit")
endif()
message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}.")
get_filename_component(externals ${CMAKE_CURRENT_SOURCE_DIR}/../../../externals
ABSOLUTE)
add_subdirectory(${externals}/threadx threadx)
add_subdirectory(${externals}/netxduo netxduo)
add_subdirectory(${externals}/filex filex)
target_compile_options(threadx PRIVATE -DTX_ENABLE_EVENT_TRACE)
if(NOT DEFINED ENV{ENABLE_IDLE})
target_compile_options(threadx PRIVATE -DTX_LINUX_NO_IDLE_ENABLE)
endif()
target_compile_options(filex PRIVATE -DFX_ENABLE_EXFAT)
target_compile_options(netxduo PRIVATE -DTX_ENABLE_EVENT_TRACE -DNX_PHYSICAL_HEADER=20)
foreach(lib threadx netxduo filex)
get_target_property(dirs ${lib} INCLUDE_DIRECTORIES)
execute_process(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/inc)
foreach(dir ${dirs})
file(GLOB header_files ${dir}/*.h)
foreach(header_file ${header_files})
execute_process(COMMAND ln -sf ${header_file} ${CMAKE_BINARY_DIR}/inc)
endforeach()
endforeach()
endforeach()

87
test/cmake/libs/nx_user.h Normal file
View File

@ -0,0 +1,87 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** NetX Component */
/** */
/** User Specific */
/** */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/* */
/* PORT SPECIFIC C INFORMATION RELEASE */
/* */
/* nx_user.h PORTABLE C */
/* 6.0 */
/* */
/* AUTHOR */
/* */
/* Yuxin Zhou, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This file contains user defines for configuring NetX in specific */
/* ways. This file will have an effect only if the application and */
/* NetX library are built with NX_INCLUDE_USER_DEFINE_FILE defined. */
/* Note that all the defines in this file may also be made on the */
/* command line when building NetX library and application objects. */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
/* */
/**************************************************************************/
#ifndef NX_USER_H
#define NX_USER_H
/* Define the extension to hold the control block for 64-bit mode. */
#define NX_THREAD_EXTENSION_PTR_SET(a, b) { \
TX_THREAD *thread_ptr; \
thread_ptr = (TX_THREAD *) (a); \
(thread_ptr -> tx_thread_extension_ptr) = (VOID *)(b); \
}
#define NX_THREAD_EXTENSION_PTR_GET(a, b, c) { \
NX_PARAMETER_NOT_USED(c); \
TX_THREAD *thread_ptr; \
thread_ptr = tx_thread_identify(); \
while(1)\
{ \
if (thread_ptr -> tx_thread_extension_ptr) \
{ \
(a) = (b *)(thread_ptr -> tx_thread_extension_ptr); \
break; \
} \
tx_thread_sleep(1); \
} \
}
#define NX_TIMER_EXTENSION_PTR_SET(a, b) { \
TX_TIMER *timer_ptr; \
timer_ptr = (TX_TIMER *) (a); \
(timer_ptr -> tx_timer_internal.tx_timer_internal_extension_ptr) = (VOID *)(b); \
}
#define NX_TIMER_EXTENSION_PTR_GET(a, b, c) { \
NX_PARAMETER_NOT_USED(c); \
if (!_tx_timer_expired_timer_ptr -> tx_timer_internal_extension_ptr) \
return; \
(a) = (b *)(_tx_timer_expired_timer_ptr -> tx_timer_internal_extension_ptr); \
}
#endif

View File

@ -0,0 +1,437 @@
cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
cmake_policy(SET CMP0054 NEW)
cmake_policy(SET CMP0057 NEW)
cmake_policy(SET CMP0077 NEW)
project(usbx_test LANGUAGES C)
# Use customized ux_user.h
set(UX_USER_FILE ${CMAKE_CURRENT_SOURCE_DIR}/ux_user.h)
# Copy files instead of using symlink
# libs/ -> ../libs/
file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/libs)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../libs/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/libs/CMakeLists.txt COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../libs/nx_user.h
${CMAKE_CURRENT_SOURCE_DIR}/libs/nx_user.h COPYONLY)
# Set build configurations
# TODO: add when available : standalone_otg_build
set(BUILD_CONFIGURATIONS
default_build_coverage
error_check_build_full_coverage
tracex_enable_build
device_buffer_owner_build
device_zero_copy_build
nofx_build_coverage
optimized_build
standalone_device_build_coverage
standalone_device_buffer_owner_build
standalone_device_zero_copy_build
standalone_host_build_coverage
standalone_build_coverage
generic_build
otg_support_build
memory_management_build_coverage
msrc_rtos_build
msrc_standalone_build
)
set(CMAKE_CONFIGURATION_TYPES
${BUILD_CONFIGURATIONS}
CACHE STRING "list of supported configuration types" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
${CMAKE_CONFIGURATION_TYPES})
list(GET CMAKE_CONFIGURATION_TYPES 0 BUILD_TYPE)
if((NOT CMAKE_BUILD_TYPE) OR (NOT ("${CMAKE_BUILD_TYPE}" IN_LIST
CMAKE_CONFIGURATION_TYPES)))
set(CMAKE_BUILD_TYPE
"${BUILD_TYPE}"
CACHE STRING "Build Type of the project" FORCE)
endif()
message(STATUS "Build for usbx")
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}.")
set(default_build_coverage
-DNX_PHYSICAL_HEADER=20
# -DUX_SLAVE_REQUEST_CONTROL_MAX_LENGTH=512
# -DUX_DEVICE_BIDIRECTIONAL_ENDPOINT_SUPPORT
# -DUX_HOST_DEVICE_CLASS_CODE_VALIDATION_ENABLE
# -DUX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT
# -DUX_HOST_CLASS_HID_INTERRUPT_OUT_SUPPORT
-DUX_DISABLE_ASSERT
##############################################FeedBack Test Start
# -DUX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT
# -DUX_MAX_DEVICE_ENDPOINTS=6
# -DUX_DEVICE_BIDIRECTIONAL_ENDPOINT_SUPPORT
# -DUX_SLAVE_REQUEST_CONTROL_MAX_LENGTH=512
##############################################FeedBack Test end
# -DUX_HOST_CLASS_AUDIO_2_SUPPORT
# -DUX_HOST_CLASS_AUDIO_FEEDBACK_SUPPORT
# -DUX_HOST_CLASS_AUDIO_DISABLE_CONTROLS
# -DUX_HOST_CLASS_AUDIO_INTERRUPT_SUPPORT
# -DUX_DEVICE_CLASS_PRINTER_WRITE_AUTO_ZLP
# -DUX_DEVICE_CLASS_CDC_ACM_WRITE_AUTO_ZLP
# -DUX_DEVICE_CLASS_AUDIO_INTERRUPT_SUPPORT
-DUX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_CONTROL=0
-DUX_DEVICE_ENABLE_GET_STRING_WITH_ZERO_LANGUAGE_ID
)
set(error_check_build_full_coverage
${default_build_coverage}
-DUX_ENABLE_ASSERT
-DUX_ENABLE_ERROR_CHECKING
-DUX_PIMA_WITH_MTP_SUPPORT
)
set(msrc_rtos_build
${error_check_build_full_coverage}
-DUX_SLAVE_REQUEST_CONTROL_MAX_LENGTH=512
-DUX_HOST_CLASS_AUDIO_2_SUPPORT
-DUX_HOST_CLASS_AUDIO_INTERRUPT_SUPPORT
)
set(msrc_standalone_build
${msrc_rtos_build}
-DUX_STANDALONE
)
set(tracex_enable_build
-DNX_PHYSICAL_HEADER=20
-DTX_ENABLE_EVENT_TRACE
-DUX_TRACE_INSERT_MACROS
)
set(device_buffer_owner_build
-DNX_PHYSICAL_HEADER=20
# -DUX_ENABLE_ASSERT
-DTX_ENABLE_EVENT_TRACE
-DUX_TRACE_INSERT_MACROS
-DUX_SLAVE_REQUEST_CONTROL_MAX_LENGTH=512
-DUX_DEVICE_ENDPOINT_BUFFER_OWNER=1
# -DUX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE
-DUX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT
-DUX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT
-DUX_DEVICE_CLASS_AUDIO_INTERRUPT_SUPPORT
)
set(device_zero_copy_build
${device_buffer_owner_build}
-DUX_DEVICE_CLASS_CDC_ACM_ZERO_COPY
-DUX_DEVICE_CLASS_CDC_ACM_WRITE_AUTO_ZLP
-DUX_DEVICE_CLASS_HID_ZERO_COPY
-DUX_DEVICE_CLASS_CDC_ECM_ZERO_COPY
-DUX_DEVICE_CLASS_RNDIS_ZERO_COPY
-DUX_DEVICE_CLASS_PRINTER_ZERO_COPY
)
set(nofx_build_coverage
-DNX_PHYSICAL_HEADER=20
-DUX_HOST_CLASS_STORAGE_NO_FILEX
)
set(standalone_build_coverage
-DNX_PHYSICAL_HEADER=20
-DUX_STANDALONE
# -DTX_ENABLE_EVENT_TRACE
)
set(standalone_device_build_coverage
-DUX_DEVICE_STANDALONE
# -DUX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT
-DUX_SLAVE_REQUEST_CONTROL_MAX_LENGTH=512
##############################################FeedBack Test Start
# -DUX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT
# -DUX_MAX_DEVICE_ENDPOINTS=6
# -DUX_DEVICE_BIDIRECTIONAL_ENDPOINT_SUPPORT
##############################################FeedBack Test End
# -DUX_DEVICE_CLASS_AUDIO_INTERRUPT_SUPPORT
-DUX_ENABLE_ERROR_CHECKING
)
set(standalone_device_buffer_owner_build
${device_buffer_owner_build}
${standalone_device_build_coverage}
)
set(standalone_device_zero_copy_build
${device_zero_copy_build}
${standalone_device_build_coverage}
)
set(standalone_host_build_coverage
-DUX_HOST_STANDALONE
# -DUX_HOST_CLASS_HID_INTERRUPT_OUT_SUPPORT
-DUX_ENABLE_ERROR_CHECKING
)
set(standalone_otg_build
-DUX_OTG_STANDALONE
)
set(optimized_build
-DNX_PHYSICAL_HEADER=20
-DUX_NAME_REFERENCED_BY_POINTER
-DUX_MAX_HCD=1
-DUX_MAX_ISO_TD=0
-DUX_MAX_TD=20
-DUX_MAX_CLASS_DRIVER=1
-DUX_MAX_DEVICES=1
-DUX_HOST_CLASS_STORAGE_MEMORY_BUFFER_SIZE=512
-DUX_HOST_CLASS_STORAGE_MAX_TRANSFER_SIZE=512
-DUX_HOST_CLASS_STORAGE_MAX_MEDIA=1
-DUX_DEVICE_INITIALIZE_FRAMEWORK_SCAN_DISABLE
-DUX_MAX_DEVICE_ENDPOINTS=2
-DUX_MAX_DEVICE_INTERFACES=1
-DUX_MAX_SLAVE_INTERFACES=1
-DUX_MAX_SLAVE_CLASS_DRIVER=1
-DUX_MAX_SLAVE_LUN=1
-DUX_SLAVE_REQUEST_DATA_MAX_LENGTH=512
-DUX_DEVICE_ALTERNATE_SETTING_SUPPORT_DISABLE
)
set(generic_build
-DUX_HCD_EHCI_SPLIT_TRANSFER_ENABLE
-DUX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT
-DUX_SLAVE_CLASS_STORAGE_INCLUDE_MMC
############################################## warning check: CDC ACM
-DUX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE
############################################## warning check: DFU
# -DUX_DEVICE_CLASS_DFU_UPLOAD_DISABLE
# -DUX_DEVICE_CLASS_DFU_ERROR_GET_ENABLE
-DUX_DEVICE_CLASS_DFU_STATUS_MODE=1 #0/1
-DUX_DEVICE_CLASS_DFU_STATUS_POLLTIMEOUT=0
# -DUX_DEVICE_CLASS_DFU_CUSTOM_REQUEST_ENABLE
-DUX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_CONTROL=1
)
set(otg_support_build
-DNX_PHYSICAL_HEADER=20
-DUX_OTG_SUPPORT=
)
set(memory_management_build_coverage
${default_build_coverage}
-DUX_ENFORCE_SAFE_ALIGNMENT
-DUX_ENABLE_MEMORY_STATISTICS
-DUX_ENABLE_MEMORY_POOL_SANITY_CHECK
)
# Control if USBX is static or shared
if($ENV{USBX_STATIC})
message(STATUS "Building STATIC usbx")
set(BUILD_SHARED_LIBS OFF)
else()
message(STATUS "Building usbx BUILD_SHARED_LIBS: ${BUILD_SHARED_LIBS}")
endif()
if(NOT BUILD_SHARED_LIBS)
if(CMAKE_BUILD_TYPE MATCHES ".*_coverage")
add_link_options(-fprofile-arcs)
add_link_options(-lgcov)
endif()
endif()
# Control if it's for 64 bit or 32 bit
if($ENV{ENABLE_64})
message(STATUS "Building for 64bit")
else()
add_compile_options(-m32)
add_link_options(-m32)
message(STATUS "Building for 32bit")
endif()
add_compile_options(
-std=c99
-ggdb
-g3
-gdwarf-2
-fdiagnostics-color
-DUX_USE_IO_INSTRUCTIONS
#-DUX_DEVICE_CLASS_DFU_CUSTOM_REQUEST_ENABLE
#-DUX_DEVICE_CLASS_DFU_STATUS_MODE=1
${${CMAKE_BUILD_TYPE}})
enable_testing()
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../../../ usbx)
if(CMAKE_BUILD_TYPE STREQUAL "generic_build")
add_test(fake_test true)
else()
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/regression regression)
endif()
# TODO: Unmask after adding sample for STANDALONE
if(NOT (CMAKE_BUILD_TYPE MATCHES "standalone.*"))
add_subdirectory(../usbx/samples samples)
endif()
# Coverage
if(CMAKE_BUILD_TYPE MATCHES ".*_coverage")
target_compile_options(usbx PRIVATE -fprofile-arcs -ftest-coverage)
target_link_options(usbx PRIVATE -fprofile-arcs -ftest-coverage)
endif()
# Build ThreadX library once
execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/run.sh build_libs)
add_custom_target(build_libs ALL COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/run.sh
build_libs)
add_dependencies(usbx build_libs)
target_include_directories(usbx PUBLIC ${CMAKE_BINARY_DIR}/../libs/inc)
add_library(threadx SHARED IMPORTED GLOBAL)
add_library("azrtos::threadx" ALIAS threadx)
set_target_properties(
threadx PROPERTIES IMPORTED_LOCATION
${CMAKE_BINARY_DIR}/../libs/threadx/libthreadx.so)
add_library(netxduo SHARED IMPORTED GLOBAL)
add_library("azrtos::netxduo" ALIAS netxduo)
set_target_properties(
netxduo PROPERTIES IMPORTED_LOCATION
${CMAKE_BINARY_DIR}/../libs/netxduo/libnetxduo.so)
add_library(filex SHARED IMPORTED GLOBAL)
add_library("azrtos::filex" ALIAS filex)
set_target_properties(
filex PROPERTIES IMPORTED_LOCATION
${CMAKE_BINARY_DIR}/../libs/filex/libfilex.so)
target_compile_options(
usbx
PRIVATE -Werror
-Wall
-Wextra
-pedantic
-fmessage-length=0
-fsigned-char
-ffunction-sections
-fdata-sections
-Wunused
-Wuninitialized
-Wmissing-declarations
-Wconversion
-Wpointer-arith
-Wshadow
-Wlogical-op
-Waggregate-return
-Wfloat-equal
-DFX_ENABLE_EXFAT)
# Remove includes and files not needed from usbx build
set(UX_STANDALONE_HOST_EXCLUDES
# ux_host_class_asix
# ux_host_class_audio
# ux_host_class_cdc_acm
# ux_host_class_cdc_ecm
# ux_host_class_gser
# ux_host_class_hid
# ux_host_class_hub
# ux_host_class_pima
# ux_host_class_printer
# ux_host_class_prolific
# ux_host_class_storage
# ux_host_class_swar
# ux_host_class_video
# ux_hcd_ehci
# ux_hcd_ohci
)
set(UX_STANDALONE_DEVICE_EXCLUDES
# ux_device_class_audio
# ux_device_class_cdc_acm
# ux_device_class_cdc_ecm
# ux_device_class_dfu
# ux_device_class_hid
# ux_device_class_pima
# ux_device_class_rndis
# ux_device_class_ccid
# ux_device_class_printer
# ux_device_class_video
)
set(UX_STANDALONE_UTILITY_EXCLUDES
# ux_utility_event
# ux_utility_delay
# ux_utility_mutex
# ux_utility_semaphore
# ux_utility_thread
# ux_utility_timer
)
set(UX_STANDALONE_PICTBRIDGE_EXCLUDES
# ux_pictbridge
)
set(UX_STANDALONE_NX_EXCLUDES
# ux_network_driver
)
set(UX_STANDALONE_FX_EXCLUDES
# ux_host_class_storage_driver_entry
usbx_ux_host_class_storage_fx_driver
)
if(CMAKE_BUILD_TYPE MATCHES "standalone.*")
get_target_property(test_utility_SOURCES_LIST test_utility SOURCES)
get_target_property(SOURCES_LIST usbx SOURCES)
get_target_property(INCLUDES_LIST usbx INCLUDE_DIRECTORIES)
if("${CMAKE_BUILD_TYPE}" STREQUAL "standalone_build_coverage")
# TODO: enable when STANDALONE implement is done
# Remove files not support STANDALONE yet
foreach(EXCLUDE_VAL ${UX_STANDALONE_HOST_EXCLUDES}
${UX_STANDALONE_DEVICE_EXCLUDES}
${UX_STANDALONE_UTILITY_EXCLUDES}
${UX_STANDALONE_PICTBRIDGE_EXCLUDES}
${UX_STANDALONE_NX_EXCLUDES}
${UX_STANDALONE_FX_EXCLUDES})
list(FILTER test_utility_SOURCES_LIST EXCLUDE REGEX ".*${EXCLUDE_VAL}.*")
list(FILTER SOURCES_LIST EXCLUDE REGEX ".*${EXCLUDE_VAL}.*")
endforeach()
# Update includes to remove TX,FX,NX libs
list(FILTER INCLUDES_LIST EXCLUDE REGEX ".*externals.*")
list(FILTER INCLUDES_LIST EXCLUDE REGEX ".*/libs/inc.*")
# Update library links to remove TX,FX,NX libs
set_target_properties(usbx PROPERTIES LINK_LIBRARIES "")
set_target_properties(usbx PROPERTIES INTERFACE_LINK_LIBRARIES "")
elseif("${CMAKE_BUILD_TYPE}" STREQUAL "standalone_device_build_coverage")
# Only device part linked with STANDALONE
# Remove files not support STANDALONE yet
foreach(EXCLUDE_VAL ${UX_STANDALONE_DEVICE_EXCLUDES})
list(FILTER SOURCES_LIST EXCLUDE REGEX ".*${EXCLUDE_VAL}.*")
list(FILTER test_utility_SOURCES_LIST EXCLUDE REGEX ".*${EXCLUDE_VAL}.*")
endforeach()
elseif("${CMAKE_BUILD_TYPE}" STREQUAL "standalone_host_build_coverage")
# Only host part linked with STANDALONE
# Remove files not support STANDALONE yet
foreach(EXCLUDE_VAL ${UX_STANDALONE_HOST_EXCLUDES})
list(FILTER SOURCES_LIST EXCLUDE REGEX ".*${EXCLUDE_VAL}.*")
list(FILTER test_utility_SOURCES_LIST EXCLUDE REGEX ".*${EXCLUDE_VAL}.*")
endforeach()
elseif("${CMAKE_BUILD_TYPE}" STREQUAL "standalone_otg_build")
# Only some stack file linked with STANDALONE
# No file list change for now
endif()
# Commit sources and includes changes
set_target_properties(test_utility PROPERTIES SOURCES "${test_utility_SOURCES_LIST}")
set_target_properties(usbx PROPERTIES SOURCES "${SOURCES_LIST}")
set_target_properties(usbx PROPERTIES INCLUDE_DIRECTORIES "${INCLUDES_LIST}")
endif()
# Remove files not compatible with optimized build
set(UX_OPTIMIZED_EXCLUDES
ux_device_class_rndis # buffer smaller than message size
)
if(CMAKE_BUILD_TYPE STREQUAL "optimized_build")
get_target_property(test_utility_SOURCES_LIST test_utility SOURCES)
get_target_property(SOURCES_LIST usbx SOURCES)
# Remove files not support STANDALONE yet
foreach(EXCLUDE_VAL ${UX_OPTIMIZED_EXCLUDES})
list(FILTER test_utility_SOURCES_LIST EXCLUDE REGEX ".*${EXCLUDE_VAL}.*")
list(FILTER SOURCES_LIST EXCLUDE REGEX ".*${EXCLUDE_VAL}.*")
endforeach()
# Commit sources and includes changes
set_target_properties(test_utility PROPERTIES SOURCES "${test_utility_SOURCES_LIST}")
set_target_properties(usbx PROPERTIES SOURCES "${SOURCES_LIST}")
endif()
# Use generic port file for generic build.
if(CMAKE_BUILD_TYPE STREQUAL "generic_build")
get_target_property(INCLUDES_LIST usbx INCLUDE_DIRECTORIES)
set(NEW_INCLUDES_LIST "")
foreach(INCLUDE_LIST ${INCLUDES_LIST})
string(REPLACE "ports/linux/gnu" "ports/generic" INCLUDE_LIST ${INCLUDE_LIST})
list(APPEND NEW_INCLUDES_LIST "${INCLUDE_LIST}")
endforeach()
set_target_properties(usbx PROPERTIES INCLUDE_DIRECTORIES "${NEW_INCLUDES_LIST}")
endif()

124
test/cmake/usbx/coverage.sh Executable file
View File

@ -0,0 +1,124 @@
#!/bin/bash
set -e
cd $(dirname $0)
root_path=$(cd ../../../common; pwd)
# Exclude strings
exclude_file_list=" $root_path/*/src/*_class_asix*"
exclude_file_list+=" $root_path/*/src/*_class_audio*"
exclude_file_list+=" $root_path/*/src/*_class_ccid*"
exclude_file_list+=" $root_path/*/src/*_class_dfu*"
exclude_file_list+=" $root_path/*/src/*_class_gser*"
exclude_file_list+=" $root_path/*/src/*_class_pima*"
exclude_file_list+=" $root_path/*/src/*_class_rndis*"
exclude_file_list+=" $root_path/*/src/*_class_printer*"
exclude_file_list+=" $root_path/*/src/*_class_prolific*"
exclude_file_list+=" $root_path/*/src/*_class_swar*"
exclude_file_list+=" $root_path/*/src/*_class_video*"
exclude_file_list+=" $root_path/*/src/*_hnp_*"
exclude_file_list+=" $root_path/*/src/*_role_*"
exclude_file_list+=" $root_path/*/src/ux_utility_set_interrupt_handler.c"
exclude_file_list+=" $root_path/*/src/*dcd_sim_slave*"
exclude_file_list+=" $root_path/*/src/*device_class_dpump*"
exclude_file_list+=" $root_path/*/src/*hcd_sim_host*"
exclude_file_list+=" $root_path/*/src/*host_class_dpump*"
exclude_file_list+=" $root_path/*/src/*ux_network_driver*"
# Device HID interrupt OUT related
exclude_file_list+=" $root_path/*/src/ux_device_class_hid_read.c"
exclude_file_list+=" $root_path/*/src/ux_device_class_hid_receiver*"
# CB/CBI related
exclude_file_list+=" $root_path/*/src/*_storage*_cb.c"
exclude_file_list+=" $root_path/*/src/*_storage*_cbi.c"
# CD/DVD related things
exclude_file_list+=" $root_path/*/src/*_storage_get_status*"
exclude_file_list+=" $root_path/*/src/*_storage_get_configuration*"
exclude_file_list+=" $root_path/*/src/*_storage_get_performance*"
exclude_file_list+=" $root_path/*/src/*_storage_read_disk_information*"
exclude_file_list+=" $root_path/*/src/*_storage_report_key*"
exclude_file_list+=" $root_path/*/src/*_storage_read_dvd*"
exclude_file_list+=" $root_path/*/src/*_storage_read_toc*"
# Obsolete
exclude_file_list+=" $root_path/*/src/ux_device_stack_interface_get.c"
exclude_file_list+=" $root_path/*/src/ux_host_stack_delay_ms.c"
# Host controllers
exclude_file_list+=" $root_path/usbx_host_controllers/src/*"
# Pictbridge related files
exclude_file_list+=" $root_path/usbx_pictbridge/src/*"
# Host related files
exclude_host_list=" $root_path/*/src/*_host_*"
# Device related files
exclude_device_list=" $root_path/*/src/*_device_*"
# RTOS related files
exclude_rtos_list=" $root_path/*/src/*_thread*"
exclude_rtos_list+=" $root_path/*/src/*_event_*"
exclude_rtos_list+=" $root_path/*/src/*_mutex_*"
exclude_rtos_list+=" $root_path/*/src/*_semaphore_*"
exclude_rtos_list+=" $root_path/*/src/*_timer_*"
exclude_rtos_list+=" $root_path/*/src/*_cdc_ecm_*"
exclude_rtos_list+=" $root_path/*/src/*_hub_*"
exclude_rtos_list+=" $root_path/*/src/*_cdc_acm_capabilities_get.c"
exclude_rtos_list+=" $root_path/*/src/*_cdc_acm_configure.c"
exclude_rtos_list+=" $root_path/*/src/*_hid_configure.c"
exclude_rtos_list+=" $root_path/*/src/*_hid_descriptor_parse.c"
exclude_rtos_list+=" $root_path/*/src/*_hid_report_descriptor_get.c"
exclude_rtos_list+=" $root_path/*/src/*_storage_configure.c"
exclude_rtos_list+=" $root_path/*/src/*_storage_media_mount.c"
exclude_rtos_list+=" $root_path/*/src/*_storage_media_open.c"
exclude_rtos_list+=" $root_path/*/src/*_storage_partition_read.c"
exclude_rtos_list+=" $root_path/*/src/*_storage_transport.c"
# Standalone related files
exclude_standalone_list=" $root_path/*/src/*_run.c"
if [[ $1 = *"_full_coverage" ]]; then
exclude_options=""
else
exclude_options=""
for f in $exclude_file_list;do
exclude_options+=" -e $f"
done
if [[ $1 = *"_device_"* ]]; then
for f in $exclude_host_list;do
exclude_options+=" -e $f"
done
fi
if [[ $1 = *"_host_"* ]]; then
for f in $exclude_device_list;do
exclude_options+=" -e $f"
done
fi
if [[ $1 = "standalone_"* ]]; then
for f in $exclude_rtos_list;do
exclude_options+=" -e $f"
done
else
for f in $exclude_standalone_list;do
exclude_options+=" -e $f"
done
fi
fi
mkdir -p coverage_report/$1
gcovr --object-directory=build/$1/usbx/CMakeFiles/usbx.dir/common -r ../../../common $exclude_options --xml-pretty --output coverage_report/$1.xml
gcovr --object-directory=build/$1/usbx/CMakeFiles/usbx.dir/common -r ../../../common $exclude_options --html --html-details --html-high-threshold 100.0 --output coverage_report/$1/index.html

View File

@ -0,0 +1,740 @@
cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
cmake_policy(SET CMP0057 NEW)
project(regression_test LANGUAGES C)
get_filename_component(SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../regression
ABSOLUTE)
set(ux_class_dfu_test_cases
${SOURCE_DIR}/usbx_device_dfu_basic_test.c
${SOURCE_DIR}/usbx_uxe_device_dfu_test.c
)
set(ux_class_hub_test_cases
${SOURCE_DIR}/usbx_host_class_hub_port_change_connection_process_coverage_test.c
${SOURCE_DIR}/usbx_ux_host_class_hub_descriptor_get_coverage_test.c
${SOURCE_DIR}/usbx_ux_host_class_hub_status_get_test.c
${SOURCE_DIR}/usbx_ux_host_class_hub_transfer_request_completed_test.c
${SOURCE_DIR}/usbx_hub_hub_status_get_invalid_length_test.c
${SOURCE_DIR}/usbx_hub_no_power_switching_test.c
${SOURCE_DIR}/usbx_hub_get_hub_status_fails_during_port_reset_test.c
${SOURCE_DIR}/usbx_hub_port_never_reset_test.c
${SOURCE_DIR}/usbx_hub_port_change_reset_test.c
${SOURCE_DIR}/usbx_hub_port_change_over_current_test.c
${SOURCE_DIR}/usbx_hub_port_change_suspend_test.c
${SOURCE_DIR}/usbx_hub_get_hub_status_fails_during_hub_device_enum_test.c
${SOURCE_DIR}/usbx_hub_basic_test.c
${SOURCE_DIR}/usbx_hub_basic_memory_test.c
${SOURCE_DIR}/usbx_hub_get_status_fails_during_configuration_test.c
${SOURCE_DIR}/usbx_hub_invalid_hub_descriptor_length_test.c
${SOURCE_DIR}/usbx_bus_powered_hub_conn_to_self_and_bus_powered_hub_test.c
${SOURCE_DIR}/usbx_hub_full_speed_hub_test.c
${SOURCE_DIR}/usbx_hub_multiple_tt_test.c
${SOURCE_DIR}/usbx_hub_invalid_device_protocol_test.c
${SOURCE_DIR}/usbx_hub_request_to_hub_itself_test.c
${SOURCE_DIR}/usbx_hub_single_tt_too_many_hub_ports_test.c
${SOURCE_DIR}/usbx_hub_multiple_tt_too_many_hub_ports_test.c
${SOURCE_DIR}/usbx_hub_no_endpoints_test.c
${SOURCE_DIR}/usbx_hub_interrupt_out_endpoint_test.c
${SOURCE_DIR}/usbx_hub_non_interrupt_in_endpoint_test.c
${SOURCE_DIR}/usbx_hub_hub_device_connect_test.c
${SOURCE_DIR}/usbx_hub_hub_device_disconnect_test.c
${SOURCE_DIR}/usbx_hub_quick_hub_device_reconnection_test.c
${SOURCE_DIR}/usbx_hub_hub_device_enumeration_keeps_failing_test.c
${SOURCE_DIR}/usbx_hub_port_reset_fails_during_hub_device_enum_test.c
${SOURCE_DIR}/usbx_hub_get_port_status_fails_during_hub_device_enum_test.c
${SOURCE_DIR}/usbx_hub_low_speed_hub_device_test.c
${SOURCE_DIR}/usbx_hub_full_speed_hub_device_test.c
${SOURCE_DIR}/usbx_hub_quick_hub_device_disconnection_test.c
${SOURCE_DIR}/usbx_hub_port_change_enable_test.c
${SOURCE_DIR}/usbx_ux_host_class_hub_entry_test.c)
set(ux_class_hub_standalone_test_cases
${SOURCE_DIR}/usbx_hub_basic_test.c
${SOURCE_DIR}/usbx_hub_basic_memory_test.c
)
set(ux_class_audio_test_cases
${SOURCE_DIR}/usbx_audio10_device_basic_test.c
${SOURCE_DIR}/usbx_audio10_device_feedback_test.c
${SOURCE_DIR}/usbx_audio10_iad_device_basic_test.c
${SOURCE_DIR}/usbx_audio10_iad_device_control_test.c
${SOURCE_DIR}/usbx_audio10_iad_device_interrupt_test.c
${SOURCE_DIR}/usbx_audio20_device_basic_test.c
${SOURCE_DIR}/usbx_audio20_device_controls_test.c
${SOURCE_DIR}/usbx_audio20_device_feedback_test.c
${SOURCE_DIR}/usbx_audio10_iad_host_basic_test.c
${SOURCE_DIR}/usbx_audio20_host_basic_test.c
${SOURCE_DIR}/usbx_uxe_device_audio_test.c
${SOURCE_DIR}/usbx_uxe_host_audio_test.c
)
set(ux_class_audio_device_standalone_test_cases
${SOURCE_DIR}/usbx_audio10_device_basic_test.c
${SOURCE_DIR}/usbx_audio20_device_basic_test.c
${SOURCE_DIR}/usbx_audio10_device_feedback_test.c
${SOURCE_DIR}/usbx_audio20_device_feedback_test.c
${SOURCE_DIR}/usbx_audio10_iad_device_interrupt_test.c
)
set(ux_class_rndis_test_cases ${SOURCE_DIR}/usbx_rndis_basic_test.c)
set(ux_class_cdc_ecm_test_cases
${SOURCE_DIR}/usbx_cdc_ecm_basic_test.c
${SOURCE_DIR}/usbx_cdc_ecm_basic_ipv6_test.c
${SOURCE_DIR}/usbx_cdc_ecm_nx_packet_chain_test.c
${SOURCE_DIR}/usbx_cdc_ecm_disconnect_and_reconnect_test.c
${SOURCE_DIR}/usbx_cdc_ecm_alternate_setting_change_to_zero_test.c
${SOURCE_DIR}/usbx_ux_host_class_cdc_ecm_transmission_callback_test.c
${SOURCE_DIR}/usbx_cdc_ecm_host_bulko_transfer_arming_during_link_dn_test.c
${SOURCE_DIR}/usbx_cdc_ecm_host_bulk_out_transfer_fail_test.c
${SOURCE_DIR}/usbx_cdc_ecm_host_bulki_arm_err_dueto_link_dn_thread_wait_test.c
${SOURCE_DIR}/usbx_cdc_ecm_host_non_ip_packet_received_test.c
${SOURCE_DIR}/usbx_cdc_ecm_host_bulk_in_transfer_fail_test.c
${SOURCE_DIR}/usbx_cdc_ecm_host_thread_link_down_before_transfer_test.c
${SOURCE_DIR}/usbx_cdc_ecm_host_thread_packet_allocate_fail_test.c
${SOURCE_DIR}/usbx_cdc_ecm_host_thread_packet_append_fail_test.c
${SOURCE_DIR}/usbx_cdc_ecm_mac_address_test.c
${SOURCE_DIR}/usbx_cdc_ecm_mac_address_invalid_length_test.c
${SOURCE_DIR}/usbx_cdc_ecm_no_functional_descriptor_test.c
${SOURCE_DIR}/usbx_ux_host_class_cdc_ecm_mac_address_get_test.c
${SOURCE_DIR}/usbx_cdc_ecm_host_bulk_in_transfer_arming_during_link_down_test.c
${SOURCE_DIR}/usbx_ux_host_class_cdc_ecm_interrupt_notification_test.c
${SOURCE_DIR}/usbx_ux_host_class_cdc_ecm_entry_test.c
${SOURCE_DIR}/usbx_cdc_ecm_host_bulk_in_transfer_arming_during_deactivate_test.c
${SOURCE_DIR}/usbx_cdc_ecm_host_first_interrupt_transfer_fail_test.c
${SOURCE_DIR}/usbx_cdc_ecm_host_packet_pool_create_fail_test.c
${SOURCE_DIR}/usbx_cdc_ecm_host_thread_create_fail_test.c
${SOURCE_DIR}/usbx_cdc_ecm_host_int_notification_semaphore_create_fail_test.c
${SOURCE_DIR}/usbx_cdc_ecm_host_bulk_out_semaphore_create_fail_test.c
${SOURCE_DIR}/usbx_cdc_ecm_host_bulk_in_semaphore_create_fail_test.c
${SOURCE_DIR}/usbx_cdc_ecm_control_interface_no_interrupt_endpoint_test.c
${SOURCE_DIR}/usbx_cdc_ecm_data_iface_non_bulko_and_non_bulki_endpt_test.c
${SOURCE_DIR}/usbx_cdc_ecm_basic_memory_test.c
${SOURCE_DIR}/usbx_cdc_ecm_data_interface_setting_select_fails_test.c
${SOURCE_DIR}/usbx_cdc_ecm_non_data_iface_after_zero_endpt_data_iface_test.c
${SOURCE_DIR}/usbx_cdc_ecm_invalid_alt_setting_after_zero_endpt_data_iface_test.c
${SOURCE_DIR}/usbx_cdc_ecm_default_data_interface_setting_with_endpoints_test.c
${SOURCE_DIR}/usbx_cdc_ecm_one_data_interface_with_no_endpoints_test.c
${SOURCE_DIR}/usbx_cdc_ecm_no_control_interface_test.c
${SOURCE_DIR}/usbx_cdc_ecm_interface_before_control_interface_test.c
${SOURCE_DIR}/usbx_cdc_ecm_data_interface_no_bulk_out_endpoint_test.c
${SOURCE_DIR}/usbx_cdc_ecm_data_interface_no_bulk_in_endpoint_test.c
${SOURCE_DIR}/usbx_cdc_ecm_link_down_while_ongoing_transfers_test.c
${SOURCE_DIR}/usbx_ux_host_class_cdc_ecm_write_test.c
${SOURCE_DIR}/usbx_ux_device_class_cdc_ecm_activate_test.c
${SOURCE_DIR}/usbx_ux_device_class_cdc_ecm_bulkin_thread_test.c
${SOURCE_DIR}/usbx_ux_device_class_cdc_ecm_bulkout_thread_test.c
${SOURCE_DIR}/usbx_ux_device_class_cdc_ecm_control_request_test.c
${SOURCE_DIR}/usbx_ux_device_class_cdc_ecm_change_test.c
${SOURCE_DIR}/usbx_ux_device_class_cdc_ecm_entry_test.c
${SOURCE_DIR}/usbx_ux_device_class_cdc_ecm_deactivate_test.c
${SOURCE_DIR}/usbx_ux_device_class_cdc_ecm_initialize_test.c
${SOURCE_DIR}/usbx_ux_device_class_cdc_ecm_interrupt_thread_test.c
${SOURCE_DIR}/usbx_ux_device_class_cdc_ecm_uninitialize_test.c)
set(ux_class_hid_test_cases
${SOURCE_DIR}/usbx_ux_device_class_hid_basic_memory_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_activate_test2.c
${SOURCE_DIR}/usbx_ux_device_class_hid_activate_test3.c
${SOURCE_DIR}/usbx_ux_device_class_hid_control_request_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_initialize_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_interrupt_thread_test2.c
${SOURCE_DIR}/usbx_ux_device_class_hid_read_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_receiver_memory_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_receiver_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_report_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_report_set_test2.c
${SOURCE_DIR}/usbx_ux_device_class_hid_idle_rate_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_wMaxPacketSize_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_client_register_test2.c
${SOURCE_DIR}/usbx_ux_host_class_hid_deactivate_test3.c
${SOURCE_DIR}/usbx_ux_host_class_hid_report_descriptor_get_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_report_descriptor_get_test4.c
${SOURCE_DIR}/usbx_ux_host_class_hid_idle_get_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_interrupt_endpoint_search_int_out_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_interrupt_endpoint_search_test2.c
${SOURCE_DIR}/usbx_ux_host_class_hid_keyboard_callback_test2.c
${SOURCE_DIR}/usbx_ux_host_class_hid_keyboard_ioctl_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_main_item_parse_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_main_item_parse_test2.c
${SOURCE_DIR}/usbx_ux_host_class_hid_mouse_entry_test2.c
${SOURCE_DIR}/usbx_ux_host_class_hid_mouse_entry_test3.c
${SOURCE_DIR}/usbx_ux_host_class_hid_periodic_report_start_test2.c
${SOURCE_DIR}/usbx_ux_host_class_hid_remote_control_activate_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_remote_control_activate_test2.c
${SOURCE_DIR}/usbx_ux_host_class_hid_remote_control_entry_test2.c
${SOURCE_DIR}/usbx_ux_host_class_hid_remote_control_entry_test3.c
${SOURCE_DIR}/usbx_ux_host_class_hid_report_get_test2.c
${SOURCE_DIR}/usbx_ux_host_class_hid_transfer_request_completed_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_deactivate_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_descriptor_parse_coverage_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_descriptor_parse_test2.c
${SOURCE_DIR}/usbx_ux_host_class_hid_descriptor_parse_test4.c
${SOURCE_DIR}/usbx_ux_host_class_hid_descriptor_parse_test5.c
${SOURCE_DIR}/usbx_hid_keyboard_extraction_test2.c
${SOURCE_DIR}/usbx_hid_mouse_extraction_test2.c
${SOURCE_DIR}/usbx_hid_remote_control_extraction_test2.c
${SOURCE_DIR}/usbx_ux_host_class_hid_keyboard_thread_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_keyboard_thread_test2.c
${SOURCE_DIR}/usbx_ux_device_class_hid_activate_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_deactivate_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_entry_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_activate_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_configure_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_descriptor_parse_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_entry_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_idle_set_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_interrupt_endpoint_search_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_keyboard_activate_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_keyboard_entry_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_local_item_parse_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_mouse_activate_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_mouse_buttons_get_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_mouse_entry_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_mouse_positions_get_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_mouse_wheel_get_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_periodic_report_start_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_periodic_report_stop_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_remote_control_entry_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_remote_control_usage_get_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_report_add_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_report_callback_register_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_report_id_get_test.c
${SOURCE_DIR}/usbx_hid_interrupt_endpoint_get_report_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_event_get_AND_set_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_client_register_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_client_search_test.c
${SOURCE_DIR}/usbx_control_transfer_stall_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_descriptor_send_test.c
${SOURCE_DIR}/usbx_hid_keyboard_key_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_interrupt_thread_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_report_set_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_report_get_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_report_set_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_report_set_int_out_test.c
${SOURCE_DIR}/usbx_hid_keyboard_key_get_test.c
${SOURCE_DIR}/usbx_hid_transfer_request_completed_decompressed_test.c
${SOURCE_DIR}/usbx_hid_transfer_request_completed_raw_test.c
${SOURCE_DIR}/usbx_hid_transfer_request_completed_test.c
${SOURCE_DIR}/usbx_hid_remote_control_extraction_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_compress_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_compress_array_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_compress_and_decompress_test.c
${SOURCE_DIR}/usbx_hid_keyboard_extraction_test.c
${SOURCE_DIR}/usbx_hid_keyboard_basic_test.c
${SOURCE_DIR}/usbx_hid_mouse_basic_test.c
${SOURCE_DIR}/usbx_hid_mouse_extraction_test.c
${SOURCE_DIR}/usbx_hid_remote_control_tests.c
${SOURCE_DIR}/usbx_hid_report_descriptor_collection_overflow_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_decompress_array_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_decompress_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_delimiter_nested_close_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_delimiter_nested_open_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_delimiter_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_delimiter_unknown_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_end_collection_error_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_example_andisplay_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_example_delimit_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_example_digit_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_example_display_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_example_joystk_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_example_keybrd_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_example_monitor_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_example_mouse_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_example_remote_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_example_tele_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_get_zero_length_item_data_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_global_item_persist_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_global_item_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_incoherent_usage_min_max_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_invalid_item_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_invalid_length_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_item_size_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_multiple_collections_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_multiple_fields_and_reports_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_multiple_fields_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_multiple_reports_feature_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_multiple_reports_input_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_multiple_reports_output_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_pop_underflow_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_push_overflow_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_push_pop_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_report_count_overflow_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_report_size_overflow_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_unknown_global_tag_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_unknown_local_tag_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_usages_min_max_test.c
${SOURCE_DIR}/usbx_hid_report_descriptor_usages_single_test.c
${SOURCE_DIR}/usbx_hid_report_multiple_reports_ids_test.c
${SOURCE_DIR}/usbx_uxe_device_hid_test.c
${SOURCE_DIR}/usbx_uxe_host_hid_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_logitech_pro_x_superlight_test.c
)
set(ux_class_hid_device_standalone_test_cases
${SOURCE_DIR}/usbx_hid_mouse_basic_test.c
${SOURCE_DIR}/usbx_hid_keyboard_basic_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_basic_memory_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_control_request_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_read_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_receiver_memory_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_receiver_test.c
${SOURCE_DIR}/usbx_uxe_device_hid_test.c
)
set(ux_class_hid_host_standalone_test_cases
${SOURCE_DIR}/usbx_class_hid_basic_test.c
${SOURCE_DIR}/usbx_class_hid_keyboard_basic_test.c
${SOURCE_DIR}/usbx_class_hid_mouse_basic_test.c
${SOURCE_DIR}/usbx_class_hid_remote_control_basic_test.c
${SOURCE_DIR}/usbx_class_hid_basic_memory_test.c
${SOURCE_DIR}/usbx_ux_host_class_hid_report_set_int_out_test.c
${SOURCE_DIR}/usbx_uxe_host_hid_test.c
)
set(ux_class_hid_standalone_test_cases
)
set(ux_class_cdc_acm_test_cases
${SOURCE_DIR}/usbx_cdc_acm_basic_test.c
${SOURCE_DIR}/usbx_cdc_acm_basic_memory_test.c
${SOURCE_DIR}/usbx_cdc_acm_configure_test.c
${SOURCE_DIR}/usbx_cdc_acm_device_dtr_rts_reset_on_disconnect_test.c
${SOURCE_DIR}/usbx_ux_device_class_cdc_acm_activate_test.c
${SOURCE_DIR}/usbx_ux_device_class_cdc_acm_deactivate_test.c
${SOURCE_DIR}/usbx_ux_device_class_cdc_acm_ioctl_test.c
${SOURCE_DIR}/usbx_ux_device_class_cdc_acm_transmission_test.c
${SOURCE_DIR}/usbx_ux_device_class_cdc_acm_write_test.c
${SOURCE_DIR}/usbx_ux_device_class_cdc_acm_timeout_test.c
${SOURCE_DIR}/usbx_ux_host_class_cdc_acm_activate_test.c
${SOURCE_DIR}/usbx_ux_host_class_cdc_acm_capabilities_get_test.c
${SOURCE_DIR}/usbx_ux_host_class_cdc_acm_deactivate_test.c
${SOURCE_DIR}/usbx_ux_host_class_cdc_acm_endpoints_get_test.c
${SOURCE_DIR}/usbx_ux_host_class_cdc_acm_entry_test.c
${SOURCE_DIR}/usbx_ux_host_class_cdc_acm_read_test.c
${SOURCE_DIR}/usbx_ux_host_class_cdc_acm_transfer_request_completed_test.c
${SOURCE_DIR}/usbx_ux_host_class_cdc_acm_write_test.c
${SOURCE_DIR}/usbx_ux_device_class_cdc_acm_bulkout_thread_test.c
)
set(ux_class_gser_test_cases
${SOURCE_DIR}/usbx_uxe_host_gser_test.c
)
set(ux_class_prolific_test_cases
${SOURCE_DIR}/usbx_uxe_host_prolific_test.c
)
set(ux_class_swar_test_cases
${SOURCE_DIR}/usbx_uxe_host_swar_test.c
)
set(ux_dpump_test_cases ${SOURCE_DIR}/usbx_dpump_basic_test.c)
set(ux_device_class_storage_tx_test_cases ${SOURCE_DIR}/usbx_storage_tests.c)
set(ux_class_storage_test_cases
${SOURCE_DIR}/usbx_host_class_storage_max_lun_get_coverage_test.c
${SOURCE_DIR}/usbx_host_class_storage_entry_coverage_test.c
${SOURCE_DIR}/usbx_storage_basic_memory_test.c
${SOURCE_DIR}/usbx_storage_multi_lun_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_request_sense_coverage_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_control_request_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_entry_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_format_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_initialize_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_inquiry_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_mode_select_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_mode_sense_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_prevent_allow_media_removal_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_read_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_request_sense_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_start_stop_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_synchronize_cache_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_test_ready_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_thread_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_uninitialize_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_verify_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_vendor_strings_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_write_test.c
${SOURCE_DIR}/usbx_ux_device_class_storage_invalid_lun_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_configure_coverage_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_request_sense_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_media_capacity_get_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_max_lun_get_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_configure_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_activate_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_device_support_check_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_device_initialize_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_media_mount_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_media_open_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_media_read_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_media_write_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_media_protection_check_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_media_recovery_sense_get_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_start_stop_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_transport_bo_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_driver_entry_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_entry_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_thread_entry_test.c
${SOURCE_DIR}/usbx_ux_host_class_storage_fats_exfat_test.c
${SOURCE_DIR}/usbx_uxe_device_storage_test.c
${SOURCE_DIR}/usbx_uxe_host_storage_test.c
)
set(ux_class_memory_management_test_cases
${SOURCE_DIR}/usbx_ux_host_device_basic_memory_tests.c
${SOURCE_DIR}/usbx_ux_utility_memory_safe_test.c
${SOURCE_DIR}/usbx_ux_utility_memory_test.c
${SOURCE_DIR}/usbx_ux_utility_basic_memory_management_test.c
${SOURCE_DIR}/usbx_hub_basic_memory_test.c
${SOURCE_DIR}/usbx_cdc_ecm_basic_memory_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_basic_memory_test.c
${SOURCE_DIR}/usbx_ux_device_class_hid_receiver_memory_test.c
${SOURCE_DIR}/usbx_class_hid_basic_memory_test.c
${SOURCE_DIR}/usbx_cdc_acm_basic_memory_test.c
${SOURCE_DIR}/usbx_storage_basic_memory_test.c
)
set(ux_class_storage_device_standalone_test_cases
${SOURCE_DIR}/usbx_standalone_device_storage_basic_test.c
${SOURCE_DIR}/usbx_standalone_device_storage_read_write_test.c
${SOURCE_DIR}/usbx_standalone_device_storage_error_cv_test.c
)
set(ux_class_storage_host_standalone_test_cases
${SOURCE_DIR}/usbx_standalone_host_storage_basic_test.c
${SOURCE_DIR}/usbx_standalone_host_storage_read_write_test.c
${SOURCE_DIR}/usbx_standalone_host_storage_insert_eject_test.c
${SOURCE_DIR}/usbx_uxe_host_storage_test.c
)
set(ux_class_storage_standalone_test_cases
)
set(ux_stack_cdc_acm_test_cases
${SOURCE_DIR}/usbx_ux_host_device_basic_tests.c
${SOURCE_DIR}/usbx_ux_host_device_basic_memory_tests.c
${SOURCE_DIR}/usbx_ux_host_device_initialize_tests.c
${SOURCE_DIR}/usbx_ux_host_stack_class_instance_verify_test.c
${SOURCE_DIR}/usbx_ux_host_stack_interface_setting_select_test.c
${SOURCE_DIR}/usbx_ux_host_stack_new_configuration_create_test.c
${SOURCE_DIR}/usbx_ux_host_stack_new_device_create_test.c
${SOURCE_DIR}/usbx_ux_host_stack_new_interface_create_test.c
${SOURCE_DIR}/usbx_ux_host_stack_rh_change_process_test.c
${SOURCE_DIR}/usbx_ux_host_stack_endpoint_reset_test.c
${SOURCE_DIR}/usbx_ux_device_stack_standard_request_tests.c
${SOURCE_DIR}/usbx_ux_device_stack_descriptor_send_test.c
${SOURCE_DIR}/usbx_ux_device_stack_remote_wakeup_test.c
${SOURCE_DIR}/usbx_ux_device_stack_vendor_request_test.c
${SOURCE_DIR}/usbx_uxe_device_cdc_acm_test.c
${SOURCE_DIR}/usbx_uxe_host_cdc_acm_test.c
)
set(ux_class_cdc_acm_device_standalone_test_cases
# ${SOURCE_DIR}/usbx_standalone_device_cdc_acm_basic_memory_test.c
${SOURCE_DIR}/usbx_standalone_cdc_acm_basic_memory_test.c
# ${SOURCE_DIR}/usbx_standalone_device_cdc_acm_basic_test.c
${SOURCE_DIR}/usbx_standalone_cdc_acm_basic_test.c
${SOURCE_DIR}/usbx_standalone_device_cdc_acm_transmission_test.c
${SOURCE_DIR}/usbx_uxe_device_cdc_acm_test.c
)
set(ux_class_cdc_acm_host_standalone_test_cases
${SOURCE_DIR}/usbx_standalone_cdc_acm_basic_memory_test.c
${SOURCE_DIR}/usbx_standalone_cdc_acm_basic_test.c
)
set(ux_stack_test_cases
${SOURCE_DIR}/usbx_host_stack_class_unregister_coverage_test.c
${SOURCE_DIR}/usbx_host_stack_new_endpoint_create_coverage_test.c
${SOURCE_DIR}/usbx_ux_host_stack_uninitialize_test.c
${SOURCE_DIR}/usbx_ux_host_stack_hcd_unregister_test.c
${SOURCE_DIR}/usbx_ux_host_stack_bandwidth_test.c
${SOURCE_DIR}/usbx_ux_host_stack_device_address_set_test.c
${SOURCE_DIR}/usbx_ux_host_stack_device_configuration_activate_test.c
${SOURCE_DIR}/usbx_ux_host_stack_device_configuration_reset_coverage_test.c
${SOURCE_DIR}/usbx_ux_host_stack_device_get_test.c
${SOURCE_DIR}/usbx_ux_host_stack_device_remove_test.c
${SOURCE_DIR}/usbx_ux_host_stack_new_device_get_test.c
${SOURCE_DIR}/usbx_ux_host_stack_class_device_scan_test.c
${SOURCE_DIR}/usbx_ux_host_stack_class_get_test.c
${SOURCE_DIR}/usbx_ux_host_stack_class_instance_destroy_test.c
${SOURCE_DIR}/usbx_ux_host_stack_class_instance_get_test.c
${SOURCE_DIR}/usbx_ux_host_stack_class_interface_scan_test.c
${SOURCE_DIR}/usbx_ux_host_stack_class_register_test.c
${SOURCE_DIR}/usbx_ux_host_stack_configuration_descriptor_parse_test.c
${SOURCE_DIR}/usbx_ux_host_stack_configuration_enumerate_test.c
${SOURCE_DIR}/usbx_ux_host_stack_configuration_instance_delete_test.c
${SOURCE_DIR}/usbx_ux_host_stack_configuration_interface_get_test.c
${SOURCE_DIR}/usbx_ux_host_stack_configuration_set_test.c
${SOURCE_DIR}/usbx_ux_host_stack_device_descriptor_read_test.c
${SOURCE_DIR}/usbx_ux_host_stack_endpoint_instance_create_test.c
${SOURCE_DIR}/usbx_ux_host_stack_endpoint_instance_test.c
${SOURCE_DIR}/usbx_ux_host_stack_hcd_register_test.c
${SOURCE_DIR}/usbx_ux_host_stack_hcd_transfer_request_test.c
${SOURCE_DIR}/usbx_ux_host_stack_interfaces_scan_test.c
${SOURCE_DIR}/usbx_ux_host_stack_interface_endpoint_get_test.c
${SOURCE_DIR}/usbx_ux_host_stack_rh_device_insertion_test.c
${SOURCE_DIR}/usbx_ux_host_stack_device_configuration_get_test.c
${SOURCE_DIR}/usbx_ux_host_stack_device_configuration_reset_select_test.c
${SOURCE_DIR}/usbx_ux_host_stack_hcd_thread_entry_test.c
${SOURCE_DIR}/usbx_ux_host_stack_transfer_request_test.c
${SOURCE_DIR}/usbx_ux_host_stack_enum_bMaxPacketSize0_test.c
${SOURCE_DIR}/usbx_ux_host_stack_enum_wMaxPacketSize_test.c
${SOURCE_DIR}/usbx_ux_host_stack_transfer_request_abort_test.c
${SOURCE_DIR}/usbx_ux_device_stack_class_register_test.c
${SOURCE_DIR}/usbx_ux_device_stack_class_unregister_test.c
${SOURCE_DIR}/usbx_ux_device_stack_set_feature_test.c
${SOURCE_DIR}/usbx_ux_device_stack_alternate_setting_get_test.c
${SOURCE_DIR}/usbx_ux_device_stack_alternate_setting_set_test.c
${SOURCE_DIR}/usbx_ux_device_stack_configuration_set_test.c
${SOURCE_DIR}/usbx_ux_device_stack_control_request_process_coverage_test.c
${SOURCE_DIR}/usbx_ux_device_stack_control_request_process_test.c
${SOURCE_DIR}/usbx_ux_device_stack_class_control_request_test.c
${SOURCE_DIR}/usbx_ux_device_stack_interface_delete_test.c
${SOURCE_DIR}/usbx_ux_device_stack_interface_set_test.c
${SOURCE_DIR}/usbx_ux_device_stack_interface_start_test.c
${SOURCE_DIR}/usbx_ux_device_stack_transfer_request_test.c
${SOURCE_DIR}/usbx_ux_device_stack_endpoint_stall_test.c
${SOURCE_DIR}/usbx_ux_device_stack_bos_test.c
${SOURCE_DIR}/usbx_ux_device_stack_initialize_test.c
${SOURCE_DIR}/usbx_ux_device_stack_clear_feature_coverage_test.c
${SOURCE_DIR}/usbx_uxe_system_test.c
${SOURCE_DIR}/usbx_uxe_device_stack_test.c
${SOURCE_DIR}/usbx_uxe_host_stack_test.c
)
set(ux_stack_test_cases_hid
${SOURCE_DIR}/usbx_ux_device_stack_get_status_test.c
${SOURCE_DIR}/usbx_ux_host_stack_class_unregister_test.c
)
set(ux_stack_test_cases_cdc
)
set(ux_utility_test_cases
${SOURCE_DIR}/usbx_ux_api_tracex_id_test.c
${SOURCE_DIR}/usbx_ux_utility_descriptor_pack_test.c
${SOURCE_DIR}/usbx_ux_utility_descriptor_parse_test.c
${SOURCE_DIR}/usbx_ux_utility_descriptor_struct_test.c
${SOURCE_DIR}/usbx_ux_utility_memory_safe_test.c
${SOURCE_DIR}/usbx_ux_utility_memory_test.c
${SOURCE_DIR}/usbx_ux_utility_pci_write_test.c
${SOURCE_DIR}/usbx_ux_utility_pci_read_test.c
${SOURCE_DIR}/usbx_ux_utility_pci_class_scan_test.c
${SOURCE_DIR}/usbx_ux_utility_physical_address_test.c
${SOURCE_DIR}/usbx_ux_utility_string_length_check_test.c
${SOURCE_DIR}/usbx_ux_utility_unicode_to_string_test.c
)
set(ux_utility_os_test_cases
${SOURCE_DIR}/usbx_ux_utility_event_flags_test.c
${SOURCE_DIR}/usbx_ux_utility_mutex_test.c
${SOURCE_DIR}/usbx_ux_utility_semaphore_test.c
${SOURCE_DIR}/usbx_ux_utility_thread_create_test.c
${SOURCE_DIR}/usbx_ux_utility_thread_schedule_other_test.c
${SOURCE_DIR}/usbx_ux_utility_thread_suspend_test.c
${SOURCE_DIR}/usbx_ux_utility_thread_identify_test.c
${SOURCE_DIR}/usbx_ux_utility_timer_test.c
)
set(ux_class_video_test_cases
${SOURCE_DIR}/usbx_ux_device_class_video_basic_tests.c
${SOURCE_DIR}/usbx_ux_host_class_video_basic_tests.c
${SOURCE_DIR}/usbx_ux_host_class_video_dwMaxPayloadTransferSize_test.c
${SOURCE_DIR}/usbx_ux_host_class_video_format_frame_based_test.c # device control buffer > 512
${SOURCE_DIR}/usbx_ux_host_class_video_format_h264_test.c # device control buffer > 512
${SOURCE_DIR}/usbx_uxe_device_video_test.c
${SOURCE_DIR}/usbx_uxe_host_video_test.c
)
set(ux_class_video_device_standalone_test_cases
${SOURCE_DIR}/usbx_ux_device_class_video_basic_tests.c
${SOURCE_DIR}/usbx_uxe_device_video_test.c
)
set(ux_class_print_test_cases
${SOURCE_DIR}/usbx_class_printer_basic_tests.c
${SOURCE_DIR}/usbx_uxe_device_printer_test.c
${SOURCE_DIR}/usbx_uxe_host_printer_test.c
)
set(ux_class_printer_device_standalone_test_cases
${SOURCE_DIR}/usbx_class_printer_device_standalone_basic_tests.c
${SOURCE_DIR}/usbx_uxe_device_printer_test.c
)
set(ux_msrc_test_cases
${SOURCE_DIR}/usbx_msrc_69702_dfu_dnload_test.c
${SOURCE_DIR}/usbx_msrc_71934_dfu_upload_test.c
)
set(ux_msrc_test_cases_rtos
${SOURCE_DIR}/usbx_msrc_66679_test.c
${SOURCE_DIR}/usbx_msrc_72427_ecm_host_mac_test.c
${SOURCE_DIR}/usbx_msrc_72525_host_pima_obj_handles_get_test.c
${SOURCE_DIR}/usbx_msrc_72619_host_pima_stor_ids_get_test.c
${SOURCE_DIR}/usbx_msrc_72526_pictbridge_dps_host_start_test.c
${SOURCE_DIR}/usbx_msrc_72227_host_pima_read_test.c
${SOURCE_DIR}/usbx_msrc_73386_host_storage_media_open_buffer_test.c
${SOURCE_DIR}/usbx_msrc_73716_cdc_ecm_mac_get_desc_check.c
${SOURCE_DIR}/usbx_msrc_73492_host_vc_header_parse.c
${SOURCE_DIR}/usbx_msrc_80947_device_cdc_ecm_rx_length_less_than_14.c
${SOURCE_DIR}/usbx_msrc_81024_host_cdc_ecm_rx_length_less_than_14.c
${SOURCE_DIR}/usbx_msrc_80991_device_rndis_rx_length_less_than_14_test.c
${SOURCE_DIR}/usbx_msrc_81251_host_hid_report_add_fail_mem_test.c
${SOURCE_DIR}/usbx_msrc_81206_81225_ecm_multiple_data_reject_test.c
${SOURCE_DIR}/usbx_msrc_81230_host_asix_inst_free_tests.c
${SOURCE_DIR}/usbx_msrc_81231_host_prolific_inst_free_tests.c
${SOURCE_DIR}/usbx_msrc_81232_host_gser_inst_free_tests.c
${SOURCE_DIR}/usbx_msrc_81233_host_swar_inst_free_tests.c
${SOURCE_DIR}/usbx_msrc_81112_host_cdc_ecm_endpoints_get_tests.c
${SOURCE_DIR}/usbx_msrc_81142_host_storage_endpoints_get_tests.c
${SOURCE_DIR}/usbx_msrc_81143_host_cdc_acm_endpoints_get_tests.c
${SOURCE_DIR}/usbx_msrc_81108_pictbridge_object_parse_test.c
${SOURCE_DIR}/usbx_msrc_81325_host_hid_remote_control_free_callback_test.c
${SOURCE_DIR}/usbx_msrc_81326_host_hid_keyboard_free_callback_test.c
${SOURCE_DIR}/usbx_msrc_81327_host_hid_mouse_free_callback_test.c
${SOURCE_DIR}/usbx_msrc_81109_pictbridge_array_element_to_hexa_test.c
${SOURCE_DIR}/usbx_msrc_81292_host_pima_deactivate_semaphore_test.c
${SOURCE_DIR}/usbx_msrc_81323_host_pima_deactivate_no_int_ep_test.c
${SOURCE_DIR}/usbx_msrc_81184_host_audio_desc_validate_test.c
${SOURCE_DIR}/usbx_msrc_81426_host_audio_type_get_fail_ac_link_test.c
${SOURCE_DIR}/usbx_msrc_81428_81429_host_audio_ac_search_test.c
)
set(ux_msrc_test_cases_standalone
${SOURCE_DIR}/usbx_msrc_81489_81570_host_cdc_acm_standalone_ac_search_test.c
${SOURCE_DIR}/usbx_msrc_81572_standalone_host_printer_allocated_enum_free_test.c
${SOURCE_DIR}/usbx_msrc_81573_standalone_host_hub_allocated_enum_free_test.c
${SOURCE_DIR}/usbx_msrc_81574_standalone_host_hid_allocated_enum_free_test.c
${SOURCE_DIR}/usbx_msrc_81575_standalone_host_cdc_acm_allocated_enum_free_test.c
${SOURCE_DIR}/usbx_msrc_81691_standalone_host_stack_enum_double_free_test.c
)
set(ux_class_ccid_test_cases
${SOURCE_DIR}/usbx_device_class_ccid_basic_tests.c
${SOURCE_DIR}/usbx_device_class_ccid_busy_abort_tests.c
${SOURCE_DIR}/usbx_uxe_device_ccid_test.c
)
set(ux_basic_test_cases
${SOURCE_DIR}/usbx_class_device_enumeration_test.c
${SOURCE_DIR}/usbx_class_interface_enumeration_test.c
${SOURCE_DIR}/usbx_class_multi_interface_enumeration_test.c
${SOURCE_DIR}/usbx_ux_host_stack_device_string_get_test.c
)
set(ux_class_pima_test_cases
${SOURCE_DIR}/usbx_pima_basic_test.c
${SOURCE_DIR}/usbx_pictbridge_basic_test.c
${SOURCE_DIR}/usbx_uxe_device_pima_test.c
${SOURCE_DIR}/usbx_uxe_host_pima_test.c
)
if("-DNX_BSD_ENABLE" IN_LIST ${CMAKE_BUILD_TYPE})
endif()
set(test_utility_files
${SOURCE_DIR}/usbxtestcontrol.c
${SOURCE_DIR}/ux_test.c
${SOURCE_DIR}/ux_host_class_dummy.c
${SOURCE_DIR}/ux_host_class_dummy.h
${SOURCE_DIR}/ux_device_class_dummy.c
${SOURCE_DIR}/ux_device_class_dummy.h
${SOURCE_DIR}/ux_device_class_dummy_hub.c
${SOURCE_DIR}/ux_device_class_dummy_hub.h
# ${SOURCE_DIR}/ux_device_class_dummy_printer.c
# ${SOURCE_DIR}/ux_device_class_dummy_printer.h
${SOURCE_DIR}/ux_test_utility_sim_no_overriding.c
${SOURCE_DIR}/ux_test_race_condition_overrides.c
${SOURCE_DIR}/ux_test_dcd_sim_slave.c
${SOURCE_DIR}/ux_test_hcd_sim_host.c
${SOURCE_DIR}/ux_test_utility_sim.c
${SOURCE_DIR}/ux_test_standalone_references.c
${SOURCE_DIR}/usbx_ux_host_class_storage_fx_driver.c)
add_library(test_utility ${test_utility_files})
target_link_libraries(test_utility PUBLIC azrtos::usbx azrtos::threadx azrtos::netxduo azrtos::filex)
target_compile_definitions(test_utility PUBLIC CTEST FX_ENABLE_EXFAT)
if (CMAKE_BUILD_TYPE MATCHES "msrc_rtos_build")
set(test_cases
${ux_msrc_test_cases}
${ux_msrc_test_cases_rtos}
)
elseif (CMAKE_BUILD_TYPE MATCHES "msrc_standalone_build")
set(test_cases
${ux_msrc_test_cases}
${ux_msrc_test_cases_standalone}
)
elseif(NOT (CMAKE_BUILD_TYPE MATCHES "standalone.*"))
if (CMAKE_BUILD_TYPE MATCHES "nofx_.*")
set(test_cases
${ux_class_storage_test_cases}
)
elseif (CMAKE_BUILD_TYPE MATCHES "memory_management_.*")
set(test_cases
${ux_class_memory_management_test_cases}
)
else()
set(test_cases
${ux_basic_test_cases}
${ux_utility_test_cases}
${ux_utility_os_test_cases}
${ux_stack_test_cases}
${ux_dpump_test_cases}
${ux_class_hub_test_cases}
${ux_device_class_storage_tx_test_cases}
${ux_class_dfu_test_cases}
${ux_class_print_test_cases}
${ux_class_ccid_test_cases}
)
if(NOT (CMAKE_BUILD_TYPE MATCHES "optimized.*"))
list(APPEND test_cases
${ux_stack_test_cases_hid}
${ux_stack_test_cases_cdc}
${ux_stack_cdc_acm_test_cases}
${ux_class_cdc_acm_test_cases}
${ux_class_audio_test_cases}
${ux_class_rndis_test_cases}
${ux_class_cdc_ecm_test_cases}
${ux_class_hid_test_cases}
${ux_class_video_test_cases}
${ux_class_storage_test_cases}
${ux_class_pima_test_cases}
${ux_class_gser_test_cases}
${ux_class_prolific_test_cases}
${ux_class_swar_test_cases}
${ux_msrc_test_cases}
)
endif()
endif()
else()
set(test_cases
${ux_basic_test_cases}
${ux_utility_test_cases}
${ux_dpump_test_cases}
)
if (CMAKE_BUILD_TYPE MATCHES "standalone_device.*")
list(APPEND test_cases
${ux_utility_os_test_cases}
${ux_class_storage_device_standalone_test_cases}
${ux_class_cdc_acm_device_standalone_test_cases}
${ux_class_video_device_standalone_test_cases}
${ux_class_hid_device_standalone_test_cases}
${ux_class_dfu_test_cases}
${ux_msrc_test_cases}
${ux_class_printer_device_standalone_test_cases}
${ux_class_audio_device_standalone_test_cases}
${ux_class_ccid_test_cases}
)
elseif (CMAKE_BUILD_TYPE MATCHES "standalone_host.*")
list(APPEND test_cases
${ux_utility_os_test_cases}
${ux_class_storage_host_standalone_test_cases}
${ux_class_cdc_acm_host_standalone_test_cases}
${ux_class_hid_host_standalone_test_cases}
${ux_class_print_test_cases}
${ux_class_hub_standalone_test_cases}
)
else ()
list(APPEND test_cases
${ux_class_dfu_test_cases}
)
endif()
endif()
foreach(test_case ${test_cases})
get_filename_component(test_name ${test_case} NAME_WE)
add_executable(${test_name} ${test_case})
target_link_libraries(${test_name} PRIVATE test_utility)
add_test(${CMAKE_BUILD_TYPE}::${test_name} ${test_name})
endforeach()

17
test/cmake/usbx/run.sh Executable file
View File

@ -0,0 +1,17 @@
#!/bin/bash
cd $(dirname $0)
# Checkout externals
[ -d externals] || mkdir ../../externals
git clone https://github.com/azure-rtos/threadx.git ../../externals/threadx
git clone https://github.com/azure-rtos/netxduo.git ../../externals/netxduo
git clone https://github.com/azure-rtos/filex.git ../../externals/filex
# Add junit output for ctest generation
if ! grep -q "\-\-output\-junit \$1.xml" ../../externals/threadx/scripts/cmake_bootstrap.sh; then
sed -i 's/ctest $parallel --timeout 1000 -O $1.txt/& --output-junit $1.xml/g' ../../externals/threadx/scripts/cmake_bootstrap.sh
fi
[ -f .run.sh ] || ln -sf ../../externals/threadx/scripts/cmake_bootstrap.sh .run.sh
./.run.sh $*

View File

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
cmake_policy(SET CMP0057 NEW)
project(samples LANGUAGES C)
set(SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../../samples)
set(sample_files
${SOURCE_DIR}/demo_usbx.c)
foreach(sample_file ${sample_files})
get_filename_component(sample_file_name ${sample_file} NAME_WE)
add_executable(${sample_file_name} ${sample_file} fake.c)
target_link_libraries(${sample_file_name} PRIVATE azrtos::usbx)
endforeach()

View File

@ -0,0 +1,11 @@
#include "ux_api.h"
UCHAR inpb(ULONG addr){return(0);}
USHORT inpw(ULONG addr){return(0);}
ULONG inpl(ULONG addr){return(0);}
UCHAR outpb(ULONG addr, UCHAR b){return(b);}
USHORT outpw(ULONG addr, USHORT w){return(w);}
ULONG outpl(ULONG addr, ULONG l){return(l);}
void ux_test_assert_hit(char* file, INT line){};

345
test/cmake/usbx/ux_user.h Normal file
View File

@ -0,0 +1,345 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** USBX Component */
/** */
/** User Specific */
/** */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/* */
/* PORT SPECIFIC C INFORMATION RELEASE */
/* */
/* ux_user.h PORTABLE C */
/* 6.x */
/* */
/* AUTHOR */
/* */
/* Chaoqiong Xiao, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This file contains user defines for configuring USBX in specific */
/* ways. This file will have an effect only if the application and */
/* USBX library are built with UX_INCLUDE_USER_DEFINE_FILE defined. */
/* Note that all the defines in this file may also be made on the */
/* command line when building USBX library and application objects. */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
/* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
/* resulting in version 6.1 */
/* xx-xx-xxxx Chaoqiong Xiao Modified comment(s), */
/* added standalone supoort, */
/* resulting in version 6.x */
/* */
/**************************************************************************/
#ifndef UX_USER_H
#define UX_USER_H
/* Define various build options for the USBX port. The application should either make changes
here by commenting or un-commenting the conditional compilation defined OR supply the defines
though the compiler's equivalent of the -D option. */
/* #define UX_THREAD_STACK_SIZE (2 * 1024) */
/* Define USBX Host Enum Thread Stack Size. The default is to use UX_THREAD_STACK_SIZE */
/*
#define UX_HOST_ENUM_THREAD_STACK_SIZE UX_THREAD_STACK_SIZE
*/
/* Define USBX Host Thread Stack Size. The default is to use UX_THREAD_STACK_SIZE */
/*
#define UX_HOST_HCD_THREAD_STACK_SIZE UX_THREAD_STACK_SIZE
*/
/* Define USBX Host HNP Polling Thread Stack Size. The default is to use UX_THREAD_STACK_SIZE */
/*
#define UX_HOST_HNP_POLLING_THREAD_STACK UX_THREAD_STACK_SIZE
*/
/* Override various options with default values already assigned in ux_api.h or ux_port.h. Please
also refer to ux_port.h for descriptions on each of these options. */
/* Defined, this value represents how many ticks per seconds for a specific hardware platform.
The default is 1000 indicating 1 tick per millisecond. */
/* #define UX_PERIODIC_RATE 1000
*/
#ifdef TX_TIMER_TICKS_PER_SECOND
#define UX_PERIODIC_RATE (TX_TIMER_TICKS_PER_SECOND)
#else
#define UX_PERIODIC_RATE (100ul)
#endif
/* Defined, this value is the maximum number of classes that can be loaded by USBX. This value
represents the class container and not the number of instances of a class. For instance, if a
particular implementation of USBX needs the hub class, the printer class, and the storage
class, then the UX_MAX_CLASSES value can be set to 3 regardless of the number of devices
that belong to these classes. */
/* #define UX_MAX_CLASSES 3
*/
/* Defined, this value is the maximum number of classes in the device stack that can be loaded by
USBX. */
/* #define UX_MAX_SLAVE_CLASS_DRIVER 1
*/
/* Defined, this value is the maximum number of interfaces in the device framework. */
/* #define UX_MAX_SLAVE_INTERFACES 16
*/
/* Defined, this value represents the number of different host controllers available in the system.
For USB 1.1 support, this value will usually be 1. For USB 2.0 support, this value can be more
than 1. This value represents the number of concurrent host controllers running at the same time.
If for instance there are two instances of OHCI running, or one EHCI and one OHCI controller
running, the UX_MAX_HCD should be set to 2. */
/* #define UX_MAX_HCD 1
*/
/* Defined, this value represents the maximum number of devices that can be attached to the USB.
Normally, the theoretical maximum number on a single USB is 127 devices. This value can be
scaled down to conserve memory. Note that this value represents the total number of devices
regardless of the number of USB buses in the system. */
/* #define UX_MAX_DEVICES 127
*/
/* Defined, this value represents the current number of SCSI logical units represented in the device
storage class driver. */
/* #define UX_MAX_SLAVE_LUN 1
*/
/* Defined, this value represents the maximum number of SCSI logical units represented in the
host storage class driver. */
#ifndef UX_MAX_HOST_LUN
#define UX_MAX_HOST_LUN 2 /* for test. */
#endif
/* Defined, this value represents the maximum number of bytes received on a control endpoint in
the device stack. The default is 256 bytes but can be reduced in memory constraint environments. */
#ifndef UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH
#define UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH 248 /* for test. */
#endif
/* Defined, this value represents the maximum number of bytes that can be received or transmitted
on any endpoint. This value cannot be less than the maximum packet size of any endpoint. The default
is 4096 bytes but can be reduced in memory constraint environments. For cd-rom support in the storage
class, this value cannot be less than 2048. */
/* #define UX_SLAVE_REQUEST_DATA_MAX_LENGTH (1024 * 2) */
/* Defined, this value includes code to handle storage Multi-Media Commands (MMC). E.g., DVD-ROM.
*/
/* #define UX_SLAVE_CLASS_STORAGE_INCLUDE_MMC */
/* Defined, this value represents the maximum number of bytes that a storage payload can send/receive.
The default is 8K bytes but can be reduced in memory constraint environments. */
/* #define UX_HOST_CLASS_STORAGE_MEMORY_BUFFER_SIZE (1024 * 8) */
/* Define USBX Mass Storage Thread Stack Size. The default is to use UX_THREAD_STACK_SIZE. */
/* #define UX_HOST_CLASS_STORAGE_THREAD_STACK_SIZE UX_THREAD_STACK_SIZE
*/
/* Defined, this value represents the maximum number of Ed, regular TDs and Isochronous TDs. These values
depend on the type of host controller and can be reduced in memory constraint environments. */
#ifndef UX_MAX_ED
#define UX_MAX_ED 80 /* for test */
#endif
#ifndef UX_MAX_TD
#define UX_MAX_TD 128 /* for test */
#endif
#ifndef UX_MAX_ISO_TD
#define UX_MAX_ISO_TD 8 /* for test */
#endif
/* Defined, this value represents the maximum size of the HID decompressed buffer. This cannot be determined
in advance so we allocate a big block, usually 4K but for simple HID devices like keyboard and mouse
it can be reduced a lot. */
/* #define UX_HOST_CLASS_HID_DECOMPRESSION_BUFFER 4096 */
/* Defined, this value represents the maximum number of HID usages for a HID device.
Default is 2048 but for simple HID devices like keyboard and mouse it can be reduced a lot. */
/* #define UX_HOST_CLASS_HID_USAGES 2048 */
/* By default, each key in each HID report from the device is reported by ux_host_class_hid_keyboard_key_get
(a HID report from the device is received whenever there is a change in a key state i.e. when a key is pressed
or released. The report contains every key that is down). There are limitations to this method such as not being
able to determine when a key has been released.
Defined, this value causes ux_host_class_hid_keyboard_key_get to only report key changes i.e. key presses
and key releases. */
/* #define UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE */
/* Works when UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE is defined.
Defined, this value causes ux_host_class_hid_keyboard_key_get to only report key pressed/down changes;
key released/up changes are not reported.
*/
/* #define UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE_REPORT_KEY_DOWN_ONLY */
/* Works when UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE is defined.
Defined, this value causes ux_host_class_hid_keyboard_key_get to report lock key (CapsLock/NumLock/ScrollLock) changes.
*/
/* #define UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE_REPORT_LOCK_KEYS */
/* Works when UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE is defined.
Defined, this value causes ux_host_class_hid_keyboard_key_get to report modifier key (Ctrl/Alt/Shift/GUI) changes.
*/
/* #define UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE_REPORT_MODIFIER_KEYS */
/* Defined, this value represents the maximum number of media for the host storage class.
Default is 8 but for memory contrained resource systems this can ne reduced to 1. */
#ifndef UX_HOST_CLASS_STORAGE_MAX_MEDIA
#define UX_HOST_CLASS_STORAGE_MAX_MEDIA 2 /* for test. */
#endif
/* Defined, this value includes code to handle storage devices that use the CB
or CBI protocol (such as floppy disks). It is off by default because these
protocols are obsolete, being superseded by the Bulk Only Transport (BOT) protocol
which virtually all modern storage devices use.
*/
/* #define UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT */
/* Defined, this value forces the memory allocation scheme to enforce alignement
of memory with the UX_SAFE_ALIGN field.
*/
/* #define UX_ENFORCE_SAFE_ALIGNMENT */
/* Defined, this value represents the number of packets in the CDC_ECM device class.
The default is 16.
*/
/* #define UX_DEVICE_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES 4 */
/* Defined, this value represents the number of packets in the CDC_ECM host class.
The default is 16.
*/
/* #define UX_HOST_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES 16 */
/* Defined, this value represents the number of milliseconds to wait for packet
allocation until invoking the application's error callback and retrying.
The default is 1000 milliseconds.
*/
/* #define UX_HOST_CLASS_CDC_ECM_PACKET_POOL_WAIT 10 */
/* Defined, this value represents the number of milliseconds to wait for packet
allocation until invoking the application's error callback and retrying.
*/
/* #define UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_WAIT 10 */
/* Defined, this value represents the the maximum length of HID reports on the
device.
*/
/* #define UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH 64 */
/* Defined, this value represents the the maximum number of HID events/reports
that can be queued at once.
*/
/* #define UX_DEVICE_CLASS_HID_MAX_EVENTS_QUEUE 8 */
/* Defined, this value will only enable the host side of usbx. */
/* #define UX_HOST_SIDE_ONLY */
/* Defined, this value will only enable the device side of usbx. */
/* #define UX_DEVICE_SIDE_ONLY */
/* Defined, this value will include the OTG polling thread. OTG can only be active if both host/device are present.
*/
#ifndef UX_HOST_SIDE_ONLY
#ifndef UX_DEVICE_SIDE_ONLY
/* #define UX_OTG_SUPPORT */
#endif
#endif
/* Defined, this value represents the maximum size of single tansfers for the SCSI data phase.
*/
/* #define UX_HOST_CLASS_STORAGE_MAX_TRANSFER_SIZE (1024 * 1) */
/* Defined, this value represents the size of the log pool.
*/
#define UX_DEBUG_LOG_SIZE (1024 * 16)
/* Defined, this disables the assert checks inside usbx. */
#ifndef UX_DISABLE_ASSERT
#define UX_ENABLE_ASSERT
#endif
/* Defined, this defines the assert action taken when failure detected. By default
it halts without any output. */
void ux_test_assert_hit(char* file, int line);
#define UX_ASSERT_FAIL ux_test_assert_hit(__FILE__, __LINE__);
/* DEBUG includes and macros for a specific platform go here. */
#ifdef UX_INCLUDE_USER_DEFINE_BSP
#include "usb_bsp.h"
#include "usbh_hcs.h"
#include "usbh_stdreq.h"
#include "usbh_core.h"
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,110 @@
/* This tests the case where a bus-powered hub is connected to a self-powered hub. */
#include "usbx_ux_test_hub.h"
static unsigned char device_framework_bus_powered[] = {
/* Device Descriptor */
0x12, /* bLength */
0x01, /* bDescriptorType */
0x00, 0x02, /* bcdUSB */
0x09, /* bDeviceClass - Hub */
0x00, /* bDeviceSubClass */
0x01, /* bDeviceProtocol */
0x40, /* bMaxPacketSize0 */
0x24, 0x04, /* idVendor */
0x12, 0x24, /* idProduct */
0xb2, 0x0b, /* bcdDevice */
0x00, /* iManufacturer */
0x00, /* iProduct */
0x00, /* iSerialNumber */
0x01, /* bNumConfigurations */
/* Configuration Descriptor */
0x09, /* bLength */
0x02, /* bDescriptorType */
0x19, 0x00, /* wTotalLength */
0x01, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
0xa0, /* bmAttributes - Bus-powered */
0x01, /* bMaxPower */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndpoints */
0x09, /* bInterfaceClass - Hub */
0x00, /* bInterfaceSubClass */
0x00, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x81, /* bEndpointAddress */
0x03, /* bmAttributes - Interrupt */
0x02, 0x00, /* wMaxPacketSize */
0x0c, /* bInterval */
};
static DEVICE_INIT_DATA device_init_data = {
.framework = device_framework_bus_powered,
.framework_length = sizeof(device_framework_bus_powered),
};
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_bus_powered_hub_connected_to_self_and_bus_powered_hub_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
#if UX_MAX_DEVICES > 1
printf("Running Hub Bus Powered Hub Connected....Test....................... ");
#else
printf("Running Hub Bus Powered Hub Connected....Skip max 1 device.......... SUCCESS!\n");
test_control_return(0);
return;
#endif
stepinfo("\n");
initialize_hub_with_device_init_data(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
#if UX_MAX_DEVICES > 1
UX_DEVICE parent;
stepinfo("test this hub connected to a self-powered hub\n");
parent.ux_device_power_source = UX_DEVICE_SELF_POWERED;
g_hub_host->ux_host_class_hub_device->ux_device_parent = &parent;
UX_TEST_CHECK_SUCCESS(_ux_host_class_hub_configure(g_hub_host));
/* Should've been null originally. */
g_hub_host->ux_host_class_hub_device->ux_device_parent = UX_NULL;
stepinfo("test this hub connected to a bus-powered hub\n");
parent.ux_device_power_source = UX_DEVICE_BUS_POWERED;
g_hub_host->ux_host_class_hub_device->ux_device_parent = &parent;
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HUB, UX_CONNECTION_INCOMPATIBLE));
UX_TEST_CHECK_NOT_SUCCESS(_ux_host_class_hub_configure(g_hub_host));
/* Should've been null originally. */
g_hub_host->ux_host_class_hub_device->ux_device_parent = UX_NULL;
#endif
}
static void post_init_device()
{
}

View File

@ -0,0 +1,854 @@
/* 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_class_cdc_acm.h"
#include "ux_device_stack.h"
#include "ux_host_class_cdc_acm.h"
#include "ux_test_dcd_sim_slave.h"
#include "ux_test_hcd_sim_host.h"
#include "ux_test_utility_sim.h"
/* Define constants. */
#define UX_DEMO_DEBUG_SIZE (4096*8)
#define UX_DEMO_STACK_SIZE 1024
#define UX_DEMO_BUFFER_SIZE (UX_SLAVE_REQUEST_DATA_MAX_LENGTH + 1)
#define UX_DEMO_XMIT_BUFFER_SIZE 512
#define UX_DEMO_RECEPTION_BUFFER_SIZE 512
#define UX_DEMO_FILE_BUFFER_SIZE 512
#define UX_DEMO_RECEPTION_BLOCK_SIZE 64
#define UX_DEMO_MEMORY_SIZE (64*1024)
#define UX_DEMO_FILE_SIZE (128 * 1024)
#define UX_RAM_DISK_MEMORY (256 * 1024)
/* Define local/extern function prototypes. */
static TX_THREAD ux_test_thread_host_simulation;
static TX_THREAD ux_test_thread_slave_simulation;
static void ux_test_thread_host_simulation_entry(ULONG);
static void ux_test_thread_slave_simulation_entry(ULONG);
static VOID test_cdc_instance_activate(VOID *cdc_instance);
static VOID test_cdc_instance_deactivate(VOID *cdc_instance);
static VOID test_cdc_instance_parameter_change(VOID *cdc_instance);
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 UX_HOST_CLASS *class_driver;
static UX_HOST_CLASS_CDC_ACM *cdc_acm_host_control;
static UX_HOST_CLASS_CDC_ACM *cdc_acm_host_data;
static UX_SLAVE_CLASS_CDC_ACM *cdc_acm_slave;
static UCHAR cdc_acm_slave_change;
static UX_SLAVE_CLASS_CDC_ACM_PARAMETER parameter;
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_cdc_sem_usage;
static ULONG rsc_cdc_sem_get_count;
static ULONG rsc_cdc_mutex_usage;
static ULONG rsc_cdc_mem_alloc_count;
static ULONG interaction_count;
static UCHAR error_callback_ignore = UX_TRUE;
static ULONG error_callback_counter;
/* Define device framework. */
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 93
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 103
#define STRING_FRAMEWORK_LENGTH 47
#define LANGUAGE_ID_FRAMEWORK_LENGTH 2
static unsigned char device_framework_full_speed[] = {
/* Device descriptor 18 bytes
0x02 bDeviceClass: CDC class code
0x00 bDeviceSubclass: CDC class sub code
0x00 bDeviceProtocol: CDC Device protocol
idVendor & idProduct - http://www.linux-usb.org/usb.ids
*/
0x12, 0x01, 0x10, 0x01,
0xEF, 0x02, 0x01,
0x08,
0x84, 0x84, 0x00, 0x00,
0x00, 0x01,
0x01, 0x02, 03,
0x01,
/* Configuration 1 descriptor 9 bytes */
0x09, 0x02, 0x4b, 0x00,
0x02, 0x01, 0x00,
0x40, 0x00,
/* Interface association descriptor. 8 bytes. */
0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
/* Communication Class Interface Descriptor Requirement. 9 bytes. */
0x09, 0x04, 0x00,
0x00,
0x01,
0x02, 0x02, 0x01,
0x00,
/* Header Functional Descriptor 5 bytes */
0x05, 0x24, 0x00,
0x10, 0x01,
/* ACM Functional Descriptor 4 bytes */
0x04, 0x24, 0x02,
0x0f,
/* Union Functional Descriptor 5 bytes */
0x05, 0x24, 0x06,
0x00, /* Master interface */
0x01, /* Slave interface */
/* Call Management Functional Descriptor 5 bytes */
0x05, 0x24, 0x01,
0x03,
0x01, /* Data interface */
/* Endpoint 0x83 descriptor 7 bytes */
0x07, 0x05, 0x83,
0x03,
0x08, 0x00,
0xFF,
/* Data Class Interface Descriptor Requirement 9 bytes */
0x09, 0x04, 0x01,
0x00,
0x02,
0x0A, 0x00, 0x00,
0x00,
/* Endpoint 0x02 descriptor 7 bytes */
0x07, 0x05, 0x02, /* @ 93 - 14 + 2 = 81 */
0x02,
0x40, 0x00,
0x00,
/* Endpoint 0x81 descriptor 7 bytes */
0x07, 0x05, 0x81, /* @ 93 - 7 + 2 = 88 */
0x02,
0x40, 0x00,
0x00,
};
#define DEVICE_FRAMEWORK_EPA_POS_1_FS (DEVICE_FRAMEWORK_LENGTH_FULL_SPEED - 14 + 2)
#define DEVICE_FRAMEWORK_EPA_POS_2_FS (DEVICE_FRAMEWORK_LENGTH_FULL_SPEED - 7 + 2)
static unsigned char device_framework_high_speed[] = {
/* Device descriptor
0x02 bDeviceClass: CDC class code
0x00 bDeviceSubclass: CDC class sub code
0x00 bDeviceProtocol: CDC Device protocol
idVendor & idProduct - http://www.linux-usb.org/usb.ids
*/
0x12, 0x01, 0x00, 0x02,
0xEF, 0x02, 0x01,
0x40,
0x84, 0x84, 0x00, 0x00,
0x00, 0x01,
0x01, 0x02, 03,
0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02,
0x02, 0x00, 0x00,
0x40,
0x01,
0x00,
/* Configuration 1 descriptor */
0x09, 0x02, 0x4b, 0x00,
0x02, 0x01, 0x00,
0x40, 0x00,
/* Interface association descriptor. */
0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
/* Communication Class Interface Descriptor Requirement */
0x09, 0x04, 0x00,
0x00,
0x01,
0x02, 0x02, 0x01,
0x00,
/* Header Functional Descriptor */
0x05, 0x24, 0x00,
0x10, 0x01,
/* ACM Functional Descriptor */
0x04, 0x24, 0x02,
0x0f,
/* Union Functional Descriptor */
0x05, 0x24, 0x06,
0x00,
0x01,
/* Call Management Functional Descriptor */
0x05, 0x24, 0x01,
0x00,
0x01,
/* Endpoint 0x83 descriptor */
0x07, 0x05, 0x83,
0x03,
0x08, 0x00,
0xFF,
/* Data Class Interface Descriptor Requirement */
0x09, 0x04, 0x01,
0x00,
0x02,
0x0A, 0x00, 0x00,
0x00,
/* Endpoint 0x02 descriptor */
0x07, 0x05, 0x02, /* @ 103 - 14 + 2 = 91 */
0x02,
0x40, 0x00,
0x00,
/* Endpoint 0x81 descriptor */
0x07, 0x05, 0x81, /* @ 103 - 7 + 2 = 98 */
0x02,
0x40, 0x00,
0x00,
};
#define DEVICE_FRAMEWORK_EPA_POS_1_HS (DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED - 14 + 2)
#define DEVICE_FRAMEWORK_EPA_POS_2_HS (DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED - 7 + 2)
static unsigned char string_framework[] = {
/* Manufacturer string descriptor : Index 1 - "Express Logic" */
0x09, 0x04, 0x01, 0x0c,
0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
0x6f, 0x67, 0x69, 0x63,
/* Product string descriptor : Index 2 - "EL Composite device" */
0x09, 0x04, 0x02, 0x13,
0x45, 0x4c, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
0x73, 0x69, 0x74, 0x65, 0x20, 0x64, 0x65, 0x76,
0x69, 0x63, 0x65,
/* Serial Number string descriptor : Index 3 - "0001" */
0x09, 0x04, 0x03, 0x04,
0x30, 0x30, 0x30, 0x31
};
/* Multiple languages are supported on the device, to add
a language besides english, the unicode language code must
be appended to the language_id_framework array and the length
adjusted accordingly. */
static unsigned char language_id_framework[] = {
/* English. */
0x09, 0x04
};
/* 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 }
};
/* 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 sleep_break_on_error(VOID)
{
if (error_callback_counter >= 3)
return error_callback_counter;
return UX_SUCCESS;
}
static UINT demo_class_cdc_acm_get(void)
{
UINT status;
UX_HOST_CLASS *class;
UX_HOST_CLASS_CDC_ACM *cdc_acm_host;
/* Find the main cdc_acm container */
status = ux_host_stack_class_get(_ux_system_host_class_cdc_acm_name, &class);
if (status != UX_SUCCESS)
return(status);
/* We get the first instance of the cdc_acm device */
do
{
status = ux_host_stack_class_instance_get(class, 0, (void **) &cdc_acm_host);
tx_thread_sleep(10);
} while (status != UX_SUCCESS);
/* We still need to wait for the cdc_acm status to be live */
while (cdc_acm_host -> ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE)
tx_thread_sleep(10);
/* Isolate both the control and data interfaces. */
if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_DATA_CLASS)
{
/* This is the data interface. */
cdc_acm_host_data = cdc_acm_host;
/* In that case, the second one should be the control interface. */
status = ux_host_stack_class_instance_get(class, 1, (void **) &cdc_acm_host);
/* Check error. */
if (status != UX_SUCCESS)
return(status);
/* Check for the control interfaces. */
if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
{
/* This is the control interface. */
cdc_acm_host_control = cdc_acm_host;
return(UX_SUCCESS);
}
}
else
{
/* Check for the control interfaces. */
if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
{
/* This is the control interface. */
cdc_acm_host_control = cdc_acm_host;
/* In that case, the second one should be the data interface. */
status = ux_host_stack_class_instance_get(class, 1, (void **) &cdc_acm_host);
/* Check error. */
if (status != UX_SUCCESS)
return(status);
/* Check for the data interface. */
if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_DATA_CLASS)
{
/* This is the data interface. */
cdc_acm_host_data = cdc_acm_host;
return(UX_SUCCESS);
}
}
}
/* Return ERROR. */
return(UX_ERROR);
}
static UINT demo_system_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
{
UX_HOST_CLASS_CDC_ACM *cdc_acm = (UX_HOST_CLASS_CDC_ACM *) inst;
switch(event)
{
case UX_DEVICE_INSERTION:
if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
cdc_acm_host_control = cdc_acm;
else
cdc_acm_host_data = cdc_acm;
break;
case UX_DEVICE_REMOVAL:
if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
cdc_acm_host_control = UX_NULL;
else
cdc_acm_host_data = UX_NULL;
break;
default:
break;
}
return 0;
}
static VOID test_cdc_instance_activate(VOID *cdc_instance)
{
/* Save the CDC instance. */
cdc_acm_slave = (UX_SLAVE_CLASS_CDC_ACM *) cdc_instance;
}
static VOID test_cdc_instance_deactivate(VOID *cdc_instance)
{
/* Reset the CDC instance. */
cdc_acm_slave = UX_NULL;
}
static VOID test_cdc_instance_parameter_change(VOID *cdc_instance)
{
/* Set CDC parameter change flag. */
cdc_acm_slave_change = UX_TRUE;
}
static VOID test_swap_framework_bulk_ep_descriptors(VOID)
{
UCHAR tmp;
tmp = device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_1_FS];
device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_1_FS] = device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_2_FS];
device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_2_FS] = tmp;
tmp = device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_1_HS];
device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_1_HS] = device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_2_HS];
device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_2_HS] = tmp;
}
static VOID test_slave_cdc_acm_transfer_disconnect(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, ULONG ep_dir)
{
UX_SLAVE_ENDPOINT *endpoint;
UX_SLAVE_DEVICE *device;
UX_SLAVE_INTERFACE *interface;
UX_SLAVE_TRANSFER *transfer_request;
/* Get the pointer to the device. */
device = &_ux_system_slave -> ux_system_slave_device;
/* This is the first time we are activated. We need the interface to the class. */
interface = cdc_acm -> ux_slave_class_cdc_acm_interface;
/* Locate the endpoints. */
endpoint = interface -> ux_slave_interface_first_endpoint;
/* Check the endpoint direction, if OUT we have the correct endpoint. */
if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != ep_dir)
{
/* So the next endpoint has to be the OUT endpoint. */
endpoint = endpoint -> ux_slave_endpoint_next_endpoint;
}
/* All CDC reading are on the endpoint OUT, from the host. */
transfer_request = &endpoint -> ux_slave_endpoint_transfer_request;
/* Continue transfer. */
transfer_request -> ux_slave_transfer_request_actual_length = endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize;
/* Change device state. */
device -> ux_slave_device_state = UX_DEVICE_ATTACHED;
/* Inform hcd. */
_ux_utility_semaphore_put(&transfer_request -> ux_slave_transfer_request_semaphore);
/* Wait a while for transfer request handling. */
tx_thread_sleep(50);
/* Change device state. */
device -> ux_slave_device_state = UX_DEVICE_CONFIGURED;
}
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_cdc_acm_basic_memory_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
/* Inform user. */
printf("Running CDC ACM Basic Memory Test................................... ");
/* 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 #1\n");
test_control_return(1);
}
/* Register the error callback. */
_ux_utility_error_callback_register(error_callback);
/* The code below is required for installing the host portion of USBX */
status = ux_host_stack_initialize(demo_system_host_change_function);
if (status != UX_SUCCESS)
{
printf("ERROR #2\n");
test_control_return(1);
}
/* Register CDC-ACM class. */
status = ux_host_stack_class_register(_ux_system_host_class_cdc_acm_name, ux_host_class_cdc_acm_entry);
if (status != UX_SUCCESS)
{
printf("ERROR #3\n");
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("ERROR #5\n");
test_control_return(1);
}
/* Set the parameters for callback when insertion/extraction of a CDC device. */
parameter.ux_slave_class_cdc_acm_instance_activate = test_cdc_instance_activate;
parameter.ux_slave_class_cdc_acm_instance_deactivate = test_cdc_instance_deactivate;
parameter.ux_slave_class_cdc_acm_parameter_change = test_cdc_instance_parameter_change;
/* Initialize the device cdc class. This class owns both interfaces starting with 0. */
status = ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
1,0, &parameter);
if(status!=UX_SUCCESS)
{
printf("ERROR #6\n");
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != TX_SUCCESS)
{
printf("ERROR #7\n");
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);
if (status != UX_SUCCESS)
{
printf("ERROR #4\n");
test_control_return(1);
}
/* Create the main host simulation thread. */
status = tx_thread_create(&ux_test_thread_host_simulation, "tx demo host simulation", ux_test_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 #8\n");
test_control_return(1);
}
/* Create the main slave simulation thread. */
status = tx_thread_create(&ux_test_thread_slave_simulation, "tx demo slave simulation", ux_test_thread_slave_simulation_entry, 0,
stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
20, 20, 1, TX_AUTO_START);
/* Check for error. */
if (status != TX_SUCCESS)
{
printf("ERROR #9\n");
test_control_return(1);
}
}
void ux_test_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_SLAVE_CLASS_CDC_ACM * cdc_acm_slave_bak;
UX_HOST_CLASS_CDC_ACM * cdc_acm_host_ctrl_bak;
UX_HOST_CLASS_CDC_ACM * cdc_acm_host_data_bak;
ULONG test_n;
ULONG mem_free;
ULONG retry;
stepinfo("\n");
/* Find the cdc_acm class and wait for the link to be up. */
status = demo_class_cdc_acm_get();
if (status != UX_SUCCESS)
{
/* CDC ACM basic test error. */
printf("ERROR #10\n");
test_control_return(1);
}
/* Save slave instance for later tests. */
cdc_acm_slave_bak = cdc_acm_slave;
/* Save host instances for later tests. */
cdc_acm_host_ctrl_bak = cdc_acm_host_control;
cdc_acm_host_data_bak = cdc_acm_host_data;
/* Test disconnect. */
ux_test_dcd_sim_slave_disconnect();
ux_test_hcd_sim_host_disconnect();
/* 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_FULL_SPEED_DEVICE);
ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
for (retry = 0; (retry < 10) && (cdc_acm_host_control == UX_NULL || cdc_acm_host_data == UX_NULL); retry ++)
tx_thread_sleep(10);
/* 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_cdc_mutex_usage = ux_test_utility_sim_mutex_create_count() - rsc_enum_mutex_usage;
rsc_cdc_sem_usage = ux_test_utility_sim_sem_create_count() - rsc_enum_sem_usage;
rsc_cdc_mem_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("cdc mem : %ld\n", rsc_cdc_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.
*/
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();
/* 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 #11.%ld: Memory level different after re-enumerations %ld <> %ld\n", 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_FULL_SPEED_DEVICE);
ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
/* Wait and break on error. */
ux_test_breakable_sleep(100, sleep_break_on_error);
/* Check */
if (!cdc_acm_host_control || !cdc_acm_host_data)
{
printf("ERROR #12.%ld: Enumeration fail\n", test_n);
test_control_return(1);
}
}
/* Simulate detach and attach for FS enumeration,
and test possible memory allocation error handlings.
*/
if (rsc_cdc_mem_alloc_count) stepinfo(">>>>>>>>>>>> Memory errors enumeration test\n");
mem_free = (~0);
for (test_n = 0; test_n < rsc_cdc_mem_alloc_count; test_n ++)
{
stepinfo("%4ld / %4ld\n", test_n, rsc_cdc_mem_alloc_count - 1);
/* Disconnect. */
ux_test_dcd_sim_slave_disconnect();
ux_test_hcd_sim_host_disconnect();
/* 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 #11.%ld: Memory level different after re-enumerations %ld <> %ld\n", 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 (cdc_acm_host_control && cdc_acm_host_data)
{
printf("ERROR #12.%ld: device detected when there is memory error\n", 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_cdc_mem_alloc_count) stepinfo("\n");
/* Finally disconnect the device. */
ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry);
/* Deinitialize the device side of usbx. */
_ux_device_stack_uninitialize();
/* And finally the usbx system resources. */
_ux_system_uninitialize();
/* Successful test. */
printf("SUCCESS!\n");
test_control_return(0);
}
void ux_test_thread_slave_simulation_entry(ULONG arg)
{
while(1)
{
/* Sleep so ThreadX on Win32 will delete this thread. */
tx_thread_sleep(10);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,860 @@
/* 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_class_cdc_acm.h"
#include "ux_device_stack.h"
#include "ux_host_class_cdc_acm.h"
#include "ux_test_dcd_sim_slave.h"
#include "ux_test_hcd_sim_host.h"
#include "ux_test_utility_sim.h"
#include "ux_host_stack.h"
/* Define constants. */
#define UX_DEMO_DEBUG_SIZE (4096*8)
#define UX_DEMO_STACK_SIZE 1024
#define UX_DEMO_BUFFER_SIZE (UX_SLAVE_REQUEST_DATA_MAX_LENGTH + 1)
#define UX_DEMO_XMIT_BUFFER_SIZE 512
#define UX_DEMO_RECEPTION_BUFFER_SIZE 512
#define UX_DEMO_FILE_BUFFER_SIZE 512
#define UX_DEMO_RECEPTION_BLOCK_SIZE 64
#define UX_DEMO_MEMORY_SIZE (64*1024)
#define UX_DEMO_FILE_SIZE (128 * 1024)
#define UX_RAM_DISK_MEMORY (256 * 1024)
/* Define local/extern function prototypes. */
static VOID test_thread_entry(ULONG);
static TX_THREAD tx_test_thread_host_simulation;
static TX_THREAD tx_test_thread_slave_simulation;
static VOID tx_test_thread_host_simulation_entry(ULONG);
static VOID tx_test_thread_slave_simulation_entry(ULONG);
static VOID test_cdc_instance_activate(VOID *cdc_instance);
static VOID test_cdc_instance_deactivate(VOID *cdc_instance);
static VOID test_cdc_instance_parameter_change(VOID *cdc_instance);
/* Define global data structures. */
UCHAR usbx_memory[UX_DEMO_MEMORY_SIZE + (UX_DEMO_STACK_SIZE * 2)];
UX_HOST_CLASS *class_driver;
UX_HOST_CLASS_CDC_ACM *cdc_acm_host_control;
UX_HOST_CLASS_CDC_ACM *cdc_acm_host_data;
UX_SLAVE_CLASS_CDC_ACM *cdc_acm_slave;
UCHAR cdc_acm_slave_change;
UX_SLAVE_CLASS_CDC_ACM_PARAMETER parameter;
ULONG error_counter;
ULONG set_cfg_counter;
ULONG rsc_mem_free_on_set_cfg;
ULONG rsc_sem_on_set_cfg;
ULONG rsc_sem_get_on_set_cfg;
ULONG rsc_mutex_on_set_cfg;
ULONG rsc_enum_sem_usage;
ULONG rsc_enum_sem_get_count;
ULONG rsc_enum_mutex_usage;
ULONG rsc_enum_mem_usage;
/* Define device framework. */
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 161
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 171
#define STRING_FRAMEWORK_LENGTH 47
#define LANGUAGE_ID_FRAMEWORK_LENGTH 2
static unsigned char device_framework_full_speed[] = {
/* Device descriptor 18 bytes
0x02 bDeviceClass: CDC class code
0x00 bDeviceSubclass: CDC class sub code
0x00 bDeviceProtocol: CDC Device protocol
idVendor & idProduct - http://www.linux-usb.org/usb.ids
*/
0x12, 0x01, 0x10, 0x01,
0xEF, 0x02, 0x01,
0x08,
0x84, 0x84, 0x00, 0x00,
0x00, 0x01,
0x01, 0x02, 03,
0x02, /* bNumConfigurations */
/* Configuration 1 descriptor 9 bytes, total 68 bytes */
0x09, 0x02, 0x44, 0x00, /* ,,wTotalLength */
0x02, 0x01, 0x00, /* ,bConfigurationValue, */
0x40, 0x00,
/* Interface association descriptor. 8 bytes. */
0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
/* Communication Class Interface Descriptor Requirement. 9 bytes. */
0x09, 0x04, 0x00, /* ,,bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
0x02, 0x02, 0x01, /* bInterfaceClass,SubClass,Protocol */
0x00,
/* Header Functional Descriptor 5 bytes */
0x05, 0x24, 0x00,
0x10, 0x01,
/* ACM Functional Descriptor 4 bytes */
0x04, 0x24, 0x02,
0x0f,
/* Union Functional Descriptor 5 bytes */
0x05, 0x24, 0x06,
0x00, /* Master interface */
0x01, /* Slave interface */
/* Call Management Functional Descriptor 5 bytes */
0x05, 0x24, 0x01,
0x03,
0x01, /* Data interface */
/* Data Class Interface Descriptor Requirement 9 bytes */
0x09, 0x04, 0x01,
0x00,
0x02,
0x0A, 0x00, 0x00,
0x00,
/* Endpoint 0x81 descriptor 7 bytes */
0x07, 0x05, 0x81,
0x02,
0x40, 0x00,
0x00,
/* Endpoint 0x02 descriptor 7 bytes */
0x07, 0x05, 0x02,
0x02,
0x40, 0x00,
0x00,
/* Configuration 2 descriptor 9 bytes, total 75 bytes */
0x09, 0x02, 0x4b, 0x00, /* ,,wTotalLength */
0x02, 0x02, 0x00, /* ,bConfigurationValue, */
0x40, 0xFA, /* bmAttributes,bMaxPower () */
/* Interface association descriptor. 8 bytes. */
0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
/* Communication Class Interface Descriptor Requirement. 9 bytes. */
0x09, 0x04, 0x00, /* ,,bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndpoints */
0x02, 0x02, 0x01, /* bInterfaceClass,SubClass,Protocol */
0x00,
/* Header Functional Descriptor 5 bytes */
0x05, 0x24, 0x00,
0x10, 0x01,
/* ACM Functional Descriptor 4 bytes */
0x04, 0x24, 0x02,
0x0f,
/* Union Functional Descriptor 5 bytes */
0x05, 0x24, 0x06,
0x00, /* Master interface */
0x01, /* Slave interface */
/* Call Management Functional Descriptor 5 bytes */
0x05, 0x24, 0x01,
0x03,
0x01, /* Data interface */
/* Endpoint 0x83 descriptor 7 bytes */
0x07, 0x05, 0x83, /* ,,bEndpointAddress */
0x03,
0x08, 0x00,
0xFF,
/* Data Class Interface Descriptor Requirement 9 bytes */
0x09, 0x04, 0x01,
0x00,
0x02,
0x0A, 0x00, 0x00,
0x00,
/* Endpoint 0x81 descriptor 7 bytes */
0x07, 0x05, 0x81,
0x02,
0x40, 0x00,
0x00,
/* Endpoint 0x02 descriptor 7 bytes */
0x07, 0x05, 0x02,
0x02,
0x40, 0x00,
0x00,
};
#define DEVICE_FRAMEWORK_EPA_POS_1_FS (DEVICE_FRAMEWORK_LENGTH_FULL_SPEED - 14 + 2)
#define DEVICE_FRAMEWORK_EPA_POS_2_FS (DEVICE_FRAMEWORK_LENGTH_FULL_SPEED - 7 + 2)
static unsigned char device_framework_high_speed[] = {
/* Device descriptor
0x02 bDeviceClass: CDC class code
0x00 bDeviceSubclass: CDC class sub code
0x00 bDeviceProtocol: CDC Device protocol
idVendor & idProduct - http://www.linux-usb.org/usb.ids
*/
0x12, 0x01, 0x00, 0x02,
0xEF, 0x02, 0x01,
0x40,
0x84, 0x84, 0x00, 0x00,
0x00, 0x01,
0x01, 0x02, 03,
0x02, /* bNumConfigurations */
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02,
0x02, 0x00, 0x00,
0x40,
0x01,
0x00,
/* Configuration 1 descriptor 9 bytes, total 68 bytes */
0x09, 0x02, 0x44, 0x00, /* ,,wTotalLength */
0x02, 0x01, 0x00, /* ,bConfigurationValue, */
0x40, 0x00,
/* Interface association descriptor. 8 bytes. */
0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
/* Communication Class Interface Descriptor Requirement. 9 bytes. */
0x09, 0x04, 0x00, /* ,,bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
0x02, 0x02, 0x01, /* bInterfaceClass,SubClass,Protocol */
0x00,
/* Header Functional Descriptor 5 bytes */
0x05, 0x24, 0x00,
0x10, 0x01,
/* ACM Functional Descriptor 4 bytes */
0x04, 0x24, 0x02,
0x0f,
/* Union Functional Descriptor 5 bytes */
0x05, 0x24, 0x06,
0x00, /* Master interface */
0x01, /* Slave interface */
/* Call Management Functional Descriptor 5 bytes */
0x05, 0x24, 0x01,
0x03,
0x01, /* Data interface */
/* Data Class Interface Descriptor Requirement 9 bytes */
0x09, 0x04, 0x01,
0x00,
0x02,
0x0A, 0x00, 0x00,
0x00,
/* Endpoint 0x81 descriptor 7 bytes */
0x07, 0x05, 0x81,
0x02,
0x40, 0x00,
0x00,
/* Endpoint 0x02 descriptor 7 bytes */
0x07, 0x05, 0x02,
0x02,
0x40, 0x00,
0x00,
/* Configuration 2 descriptor 9 bytes, total 75 bytes */
0x09, 0x02, 0x4b, 0x00, /* ,,wTotalLength */
0x02, 0x02, 0x00, /* ,bConfigurationValue, */
0x40, 0x00,
/* Interface association descriptor. 8 bytes. */
0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
/* Communication Class Interface Descriptor Requirement. 9 bytes. */
0x09, 0x04, 0x00, /* ,,bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndpoints */
0x02, 0x02, 0x01, /* bInterfaceClass,SubClass,Protocol */
0x00,
/* Header Functional Descriptor 5 bytes */
0x05, 0x24, 0x00,
0x10, 0x01,
/* ACM Functional Descriptor 4 bytes */
0x04, 0x24, 0x02,
0x0f,
/* Union Functional Descriptor 5 bytes */
0x05, 0x24, 0x06,
0x00, /* Master interface */
0x01, /* Slave interface */
/* Call Management Functional Descriptor 5 bytes */
0x05, 0x24, 0x01,
0x03,
0x01, /* Data interface */
/* Endpoint 0x83 descriptor 7 bytes */
0x07, 0x05, 0x83, /* ,,bEndpointAddress */
0x03,
0x08, 0x00,
0xFF,
/* Data Class Interface Descriptor Requirement 9 bytes */
0x09, 0x04, 0x01,
0x00,
0x02,
0x0A, 0x00, 0x00,
0x00,
/* Endpoint 0x81 descriptor 7 bytes */
0x07, 0x05, 0x81,
0x02,
0x40, 0x00,
0x00,
/* Endpoint 0x02 descriptor 7 bytes */
0x07, 0x05, 0x02,
0x02,
0x40, 0x00,
0x00,
};
#define DEVICE_FRAMEWORK_EPA_POS_1_HS (DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED - 14 + 2)
#define DEVICE_FRAMEWORK_EPA_POS_2_HS (DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED - 7 + 2)
static unsigned char string_framework[] = {
/* Manufacturer string descriptor : Index 1 - "Express Logic" */
0x09, 0x04, 0x01, 0x0c,
0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
0x6f, 0x67, 0x69, 0x63,
/* Product string descriptor : Index 2 - "EL Composite device" */
0x09, 0x04, 0x02, 0x13,
0x45, 0x4c, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
0x73, 0x69, 0x74, 0x65, 0x20, 0x64, 0x65, 0x76,
0x69, 0x63, 0x65,
/* Serial Number string descriptor : Index 3 - "0001" */
0x09, 0x04, 0x03, 0x04,
0x30, 0x30, 0x30, 0x31
};
/* Multiple languages are supported on the device, to add
a language besides english, the unicode language code must
be appended to the language_id_framework array and the length
adjusted accordingly. */
static unsigned char language_id_framework[] = {
/* English. */
0x09, 0x04
};
static UX_TEST_SETUP _SetConfigure = UX_TEST_SETUP_SetConfigure;
static UX_TEST_HCD_SIM_ACTION error_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_ERROR, UX_NULL}, /* Error */
{ 0 }
};
static UX_CONFIGURATION *cfg_2_modify;
static VOID ux_test_hcd_entry_interaction_set_cfg(UX_TEST_ACTION *action, VOID *_params)
{
if (cfg_2_modify)
cfg_2_modify -> ux_configuration_handle = 0;
}
static UX_TEST_HCD_SIM_ACTION corrupt_configuration_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_interaction_set_cfg,
UX_TRUE}, /* Go on */
{ 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 UINT test_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
{
UX_HOST_CLASS_CDC_ACM *cdc_acm = (UX_HOST_CLASS_CDC_ACM *) inst;
switch(event)
{
case UX_DEVICE_INSERTION:
if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
cdc_acm_host_control = cdc_acm;
else
cdc_acm_host_data = cdc_acm;
break;
case UX_DEVICE_REMOVAL:
if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
cdc_acm_host_control = UX_NULL;
else
cdc_acm_host_data = UX_NULL;
break;
default:
break;
}
return 0;
}
static VOID test_cdc_instance_activate(VOID *cdc_instance)
{
/* Save the CDC instance. */
cdc_acm_slave = (UX_SLAVE_CLASS_CDC_ACM *) cdc_instance;
}
static VOID test_cdc_instance_deactivate(VOID *cdc_instance)
{
/* Reset the CDC instance. */
cdc_acm_slave = UX_NULL;
}
static VOID test_cdc_instance_parameter_change(VOID *cdc_instance)
{
/* Set CDC parameter change flag. */
cdc_acm_slave_change = UX_TRUE;
}
static VOID test_ux_error_callback(UINT system_level, UINT system_context, UINT error_code)
{
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_acm_configure_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
printf("Running CDC ACM Configure Test...................................... ");
/* Reset testing counts. */
ux_test_utility_sim_mutex_create_count_reset();
ux_test_utility_sim_sem_create_count_reset();
ux_test_utility_sim_sem_get_count_reset();
/* Reset error generations */
ux_test_utility_sim_sem_error_generation_stop();
ux_test_utility_sim_mutex_error_generation_stop();
ux_test_utility_sim_sem_get_error_generation_stop();
/* Initialize the free memory pointer */
stack_pointer = (CHAR *) usbx_memory;
memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
/* Initialize USBX Memory */
status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL, 0);
/* 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(test_ux_error_callback);
/* The code below is required for installing the host portion of USBX */
status = ux_host_stack_initialize(test_host_change_function);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Register CDC ACM class */
status = ux_host_stack_class_register(_ux_system_host_class_cdc_acm_name, ux_host_class_cdc_acm_entry);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Set the parameters for callback when insertion/extraction of a CDC device. */
parameter.ux_slave_class_cdc_acm_instance_activate = test_cdc_instance_activate;
parameter.ux_slave_class_cdc_acm_instance_deactivate = test_cdc_instance_deactivate;
parameter.ux_slave_class_cdc_acm_parameter_change = test_cdc_instance_parameter_change;
/* Initialize the device cdc class. This class owns both interfaces starting with 0. */
status = ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
1,0, &parameter);
if(status!=UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_test_dcd_sim_slave_initialize();
/* Check for error. */
if (status != TX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Register HCD for test */
status = ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Create the main host simulation thread. */
status = tx_thread_create(&tx_test_thread_host_simulation, "tx test host simulation", tx_test_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);
}
/* Create the main slave simulation thread. */
status = tx_thread_create(&tx_test_thread_slave_simulation, "tx test slave simulation", tx_test_thread_slave_simulation_entry, 0,
stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
20, 20, 1, TX_AUTO_START);
/* Check for error. */
if (status != TX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
}
void tx_test_thread_host_simulation_entry(ULONG arg)
{
UINT status;
ULONG test_n;
ULONG mem_free;
UX_HOST_CLASS_COMMAND class_command;
UX_CONFIGURATION *configuration;
UX_HOST_CLASS_CDC_ACM *cdc_control;
UX_HOST_CLASS_CDC_ACM *cdc_data;
UX_DEVICE *device;
UX_DEVICE *parent_device;
UX_INTERFACE *interface;
stepinfo("\n");
/* Test connect. */
stepinfo(">>>>>>>>>>>>>>>> Test connect\n");
ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
tx_thread_sleep(100);
if (cdc_acm_host_control == UX_NULL || cdc_acm_host_data == UX_NULL || cdc_acm_slave == UX_NULL)
{
printf("ERROR #%d: connection not detected\n", __LINE__);
test_control_return(1);
}
mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
cdc_control = cdc_acm_host_control;
cdc_data = cdc_acm_host_data;
/* Test disconnect. */
stepinfo(">>>>>>>>>>>>>>>> Test disconnect\n");
ux_test_dcd_sim_slave_disconnect();
ux_test_hcd_sim_host_disconnect();
test_n = 10;
while((cdc_acm_host_control || cdc_acm_host_data || cdc_acm_slave) && test_n --)
tx_thread_sleep(10);
if (cdc_acm_host_control || cdc_acm_host_data || cdc_acm_slave)
{
printf("ERROR #%d: instance not removed when disconnect, %p %p %p\n", __LINE__, cdc_acm_host_control, cdc_acm_host_data, cdc_acm_slave);
test_control_return(1);
}
if (_ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available <= mem_free)
{
printf("ERROR #%d: memory not freed when disconnect\n", __LINE__);
test_control_return(1);
}
/* Test configure function */
stepinfo(">>>>>>>>>>>>>>>> Test Configure\n");
ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
/* Now connect, configuration stopped because power issue */
ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
tx_thread_sleep(100);
/* Find device */
status = _ux_host_stack_device_get(0, &device);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Reset configuration */
status = ux_host_stack_device_configuration_reset(device);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Find configuration */
status = _ux_host_stack_device_configuration_get(device, 0, &configuration);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Force power source */
device -> ux_device_power_source = UX_DEVICE_BUS_POWERED;
/* Activate interfaces */
class_command.ux_host_class_command_request = UX_HOST_CLASS_COMMAND_ACTIVATE;
/* Control interface */
interface = configuration -> ux_configuration_first_interface;
class_command.ux_host_class_command_container = (VOID *)interface;
class_command.ux_host_class_command_class_ptr = interface->ux_interface_class;
status = interface->ux_interface_class->ux_host_class_entry_function(&class_command);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Data interface */
interface = configuration -> ux_configuration_first_interface->ux_interface_next_interface;
class_command.ux_host_class_command_container = (VOID *)interface;
class_command.ux_host_class_command_class_ptr = interface->ux_interface_class;
status = interface->ux_interface_class->ux_host_class_entry_function(&class_command);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
stepinfo(">>>>>>>>>>>>>>>> Test Configure ERROR\n");
ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
/* Now connect, configuration stopped because power issue */
ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
tx_thread_sleep(100);
/* Find device */
status = _ux_host_stack_device_get(0, &device);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Reset configuration */
status = ux_host_stack_device_configuration_reset(device);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Find configuration */
status = _ux_host_stack_device_configuration_get(device, 0, &configuration);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
#if UX_MAX_DEVICES > 1
stepinfo(">>>>>>>>>>>>>>>> Test Configure ERROR - Parent power fail\n");
/* Get a device */
parent_device = _ux_host_stack_new_device_get();
/* Use this device as parent */
parent_device -> ux_device_power_source = UX_DEVICE_BUS_POWERED;
device -> ux_device_parent = parent_device;
/* Force power source */
device -> ux_device_power_source = UX_DEVICE_BUS_POWERED;
/* Activate interfaces */
class_command.ux_host_class_command_request = UX_HOST_CLASS_COMMAND_ACTIVATE;
/* Control interface */
interface = configuration -> ux_configuration_first_interface;
class_command.ux_host_class_command_container = (VOID *)interface;
class_command.ux_host_class_command_class_ptr = interface->ux_interface_class;
status = interface->ux_interface_class->ux_host_class_entry_function(&class_command);
if (status != UX_CONNECTION_INCOMPATIBLE)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
stepinfo(">>>>>>>>>>>>>>>> Test Configure ERROR - Configuration handler\n");
device -> ux_device_handle = 0;
status = interface->ux_interface_class->ux_host_class_entry_function(&class_command);
if (status != UX_CONFIGURATION_HANDLE_UNKNOWN)
{
printf("ERROR %d: expect UX_CONFIGURATION_HANDLE_UNKNOWN but got 0x%x\n", __LINE__, status);
test_control_return(1);
}
device -> ux_device_handle = (ULONG) (ALIGN_TYPE) device;
stepinfo(">>>>>>>>>>>>>>>> Test Configure ERROR - Parent power OK but SetConfigure error\n");
parent_device -> ux_device_power_source = UX_DEVICE_SELF_POWERED;
ux_test_hcd_sim_host_set_actions(error_on_SetCfg);
status = interface->ux_interface_class->ux_host_class_entry_function(&class_command);
if (status == UX_SUCCESS)
{
printf("ERROR %d: expect fail\n", __LINE__);
test_control_return(1);
}
#endif
stepinfo(">>>>>>>>>>>>>>>> Test Configure ERROR - Device power OK but SetConfigure error\n");
device -> ux_device_power_source = UX_DEVICE_SELF_POWERED;
ux_test_hcd_sim_host_set_actions(error_on_SetCfg);
status = interface->ux_interface_class->ux_host_class_entry_function(&class_command);
if (status == UX_SUCCESS)
{
printf("ERROR %d: expect fail\n", __LINE__);
test_control_return(1);
}
stepinfo(">>>>>>>>>>>>>>>> Test Configure ERROR - SetConfigure\n");
UX_DEVICE_PARENT_SET(device, UX_NULL);
ux_test_hcd_sim_host_set_actions(error_on_SetCfg);
status = interface->ux_interface_class->ux_host_class_entry_function(&class_command);
if (status == UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
stepinfo(">>>>>>>>>>>>>>>> Test Configure ERROR - Interface get\n");
/* Break the configuration */
cfg_2_modify = configuration;
ux_test_hcd_sim_host_set_actions(corrupt_configuration_on_SetCfg);
status = interface->ux_interface_class->ux_host_class_entry_function(&class_command);
if (status == UX_SUCCESS)
{
printf("ERROR #%d: %x\n", __LINE__, status);
test_control_return(1);
}
/* Restore */
cfg_2_modify = UX_NULL;
configuration->ux_configuration_handle = (ULONG)(ALIGN_TYPE)configuration;
/* Deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry);
/* Deinitialize the device side of usbx. */
_ux_device_stack_uninitialize();
/* And finally the usbx system resources. */
_ux_system_uninitialize();
/* Successful test. */
printf("SUCCESS!\n");
test_control_return(0);
}
void tx_test_thread_slave_simulation_entry(ULONG arg)
{
while(1)
{
/* Sleep so ThreadX on Win32 will delete this thread. */
tx_thread_sleep(10);
}
}

View File

@ -0,0 +1,526 @@
/* 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_class_cdc_acm.h"
#include "ux_device_stack.h"
#include "ux_host_class_cdc_acm.h"
#include "ux_test_dcd_sim_slave.h"
#include "ux_test.h"
/* Define constants. */
#define UX_DEMO_DEBUG_SIZE (4096*8)
#define UX_DEMO_STACK_SIZE 1024
#define UX_DEMO_BUFFER_SIZE 2048
#define UX_DEMO_XMIT_BUFFER_SIZE 512
#define UX_DEMO_RECEPTION_BUFFER_SIZE 512
#define UX_DEMO_FILE_BUFFER_SIZE 512
#define UX_DEMO_RECEPTION_BLOCK_SIZE 64
#define UX_DEMO_MEMORY_SIZE (64*1024)
#define UX_DEMO_FILE_SIZE (128 * 1024)
#define UX_RAM_DISK_MEMORY (256 * 1024)
/* Define local/extern function prototypes. */
static void demo_thread_entry(ULONG);
static TX_THREAD tx_demo_thread_host_simulation;
static TX_THREAD tx_demo_thread_slave_simulation;
static void tx_demo_thread_host_simulation_entry(ULONG);
static void tx_demo_thread_slave_simulation_entry(ULONG);
static void demo_thread_host_reception_callback(UX_HOST_CLASS_CDC_ACM *cdc_acm, UINT status, UCHAR *reception_buffer, ULONG reception_size);
static VOID demo_cdc_instance_activate(VOID *cdc_instance);
static VOID demo_cdc_instance_deactivate(VOID *cdc_instance);
static UINT demo_usbx_simulator_cdc_acm_host_send_at_command(UCHAR *string, ULONG length);
static UINT tx_demo_thread_slave_simulation_response(UCHAR *string, ULONG length);
/* Define global data structures. */
static UCHAR usbx_memory[UX_DEMO_MEMORY_SIZE + (UX_DEMO_STACK_SIZE * 2)];
static UX_HOST_CLASS *class_driver;
static UX_HOST_CLASS_CDC_ACM *cdc_acm_host_control;
static UX_HOST_CLASS_CDC_ACM *cdc_acm_host_data;
static ULONG command_received_count;
static UCHAR cdc_acm_reception_buffer[UX_DEMO_RECEPTION_BUFFER_SIZE];
static UCHAR cdc_acm_xmit_buffer[UX_DEMO_XMIT_BUFFER_SIZE];
static UX_HOST_CLASS_CDC_ACM_RECEPTION cdc_acm_reception;
static UCHAR *global_reception_buffer;
static ULONG global_reception_size;
static UX_SLAVE_CLASS_CDC_ACM *cdc_acm_slave;
static UX_SLAVE_CLASS_CDC_ACM_PARAMETER parameter;
static UCHAR buffer[UX_DEMO_BUFFER_SIZE];
static ULONG echo_mode;
static ULONG error_counter;
/* Define device framework. */
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 93
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 103
#define STRING_FRAMEWORK_LENGTH 47
#define LANGUAGE_ID_FRAMEWORK_LENGTH 2
static unsigned char device_framework_full_speed[] = {
/* Device descriptor 18 bytes
0x02 bDeviceClass: CDC class code
0x00 bDeviceSubclass: CDC class sub code
0x00 bDeviceProtocol: CDC Device protocol
idVendor & idProduct - http://www.linux-usb.org/usb.ids
*/
0x12, 0x01, 0x10, 0x01,
0xEF, 0x02, 0x01,
0x08,
0x84, 0x84, 0x00, 0x00,
0x00, 0x01,
0x01, 0x02, 03,
0x01,
/* Configuration 1 descriptor 9 bytes */
0x09, 0x02, 0x4b, 0x00,
0x02, 0x01, 0x00,
0x40, 0x00,
/* Interface association descriptor. 8 bytes. */
0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
/* Communication Class Interface Descriptor Requirement. 9 bytes. */
0x09, 0x04, 0x00,
0x00,
0x01,
0x02, 0x02, 0x01,
0x00,
/* Header Functional Descriptor 5 bytes */
0x05, 0x24, 0x00,
0x10, 0x01,
/* ACM Functional Descriptor 4 bytes */
0x04, 0x24, 0x02,
0x0f,
/* Union Functional Descriptor 5 bytes */
0x05, 0x24, 0x06,
0x00, /* Master interface */
0x01, /* Slave interface */
/* Call Management Functional Descriptor 5 bytes */
0x05, 0x24, 0x01,
0x03,
0x01, /* Data interface */
/* Endpoint 1 descriptor 7 bytes */
0x07, 0x05, 0x83,
0x03,
0x08, 0x00,
0xFF,
/* Data Class Interface Descriptor Requirement 9 bytes */
0x09, 0x04, 0x01,
0x00,
0x02,
0x0A, 0x00, 0x00,
0x00,
/* First alternate setting Endpoint 1 descriptor 7 bytes*/
0x07, 0x05, 0x02,
0x02,
0x40, 0x00,
0x00,
/* Endpoint 2 descriptor 7 bytes */
0x07, 0x05, 0x81,
0x02,
0x40, 0x00,
0x00,
};
static unsigned char device_framework_high_speed[] = {
/* Device descriptor
0x02 bDeviceClass: CDC class code
0x00 bDeviceSubclass: CDC class sub code
0x00 bDeviceProtocol: CDC Device protocol
idVendor & idProduct - http://www.linux-usb.org/usb.ids
*/
0x12, 0x01, 0x00, 0x02,
0xEF, 0x02, 0x01,
0x40,
0x84, 0x84, 0x00, 0x00,
0x00, 0x01,
0x01, 0x02, 03,
0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02,
0x02, 0x00, 0x00,
0x40,
0x01,
0x00,
/* Configuration 1 descriptor */
0x09, 0x02, 0x4b, 0x00,
0x02, 0x01, 0x00,
0x40, 0x00,
/* Interface association descriptor. */
0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
/* Communication Class Interface Descriptor Requirement */
0x09, 0x04, 0x01,
0x00,
0x01,
0x02, 0x02, 0x01,
0x00,
/* Header Functional Descriptor */
0x05, 0x24, 0x00,
0x10, 0x01,
/* ACM Functional Descriptor */
0x04, 0x24, 0x02,
0x0f,
/* Union Functional Descriptor */
0x05, 0x24, 0x06,
0x00,
0x01,
/* Call Management Functional Descriptor */
0x05, 0x24, 0x01,
0x00,
0x01,
/* Endpoint 1 descriptor */
0x07, 0x05, 0x83,
0x03,
0x08, 0x00,
0xFF,
/* Data Class Interface Descriptor Requirement */
0x09, 0x04, 0x01,
0x00,
0x02,
0x0A, 0x00, 0x00,
0x00,
/* First alternate setting Endpoint 1 descriptor */
0x07, 0x05, 0x02,
0x02,
0x40, 0x00,
0x00,
/* Endpoint 2 descriptor */
0x07, 0x05, 0x81,
0x02,
0x40, 0x00,
0x00,
};
static unsigned char string_framework[] = {
/* Manufacturer string descriptor : Index 1 - "Express Logic" */
0x09, 0x04, 0x01, 0x0c,
0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
0x6f, 0x67, 0x69, 0x63,
/* Product string descriptor : Index 2 - "EL Composite device" */
0x09, 0x04, 0x02, 0x13,
0x45, 0x4c, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
0x73, 0x69, 0x74, 0x65, 0x20, 0x64, 0x65, 0x76,
0x69, 0x63, 0x65,
/* Serial Number string descriptor : Index 3 - "0001" */
0x09, 0x04, 0x03, 0x04,
0x30, 0x30, 0x30, 0x31
};
/* Multiple languages are supported on the device, to add
a language besides english, the unicode language code must
be appended to the language_id_framework array and the length
adjusted accordingly. */
static unsigned char language_id_framework[] = {
/* English. */
0x09, 0x04
};
/* 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 UINT demo_class_cdc_acm_get(void)
{
UINT status;
UX_HOST_CLASS *class;
UX_HOST_CLASS_CDC_ACM *cdc_acm_host;
/* Find the main cdc_acm container */
status = ux_host_stack_class_get(_ux_system_host_class_cdc_acm_name, &class);
if (status != UX_SUCCESS)
return(status);
/* We get the first instance of the cdc_acm device */
do
{
status = ux_host_stack_class_instance_get(class, 0, (void **) &cdc_acm_host);
tx_thread_sleep(10);
} while (status != UX_SUCCESS);
/* We still need to wait for the cdc_acm status to be live */
while (cdc_acm_host -> ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE)
tx_thread_sleep(10);
/* Isolate both the control and data interfaces. */
if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_DATA_CLASS)
{
/* This is the data interface. */
cdc_acm_host_data = cdc_acm_host;
/* In that case, the second one should be the control interface. */
status = ux_host_stack_class_instance_get(class, 1, (void **) &cdc_acm_host);
/* Check error. */
if (status != UX_SUCCESS)
return(status);
/* Check for the control interfaces. */
if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
{
/* This is the control interface. */
cdc_acm_host_control = cdc_acm_host;
return(UX_SUCCESS);
}
}
else
{
/* Check for the control interfaces. */
if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
{
/* This is the control interface. */
cdc_acm_host_control = cdc_acm_host;
/* In that case, the second one should be the data interface. */
status = ux_host_stack_class_instance_get(class, 1, (void **) &cdc_acm_host);
/* Check error. */
if (status != UX_SUCCESS)
return(status);
/* Check for the data interface. */
if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_DATA_CLASS)
{
/* This is the data interface. */
cdc_acm_host_data = cdc_acm_host;
return(UX_SUCCESS);
}
}
}
/* Return ERROR. */
return(UX_ERROR);
}
static VOID demo_cdc_instance_activate(VOID *cdc_instance)
{
/* Save the CDC instance. */
cdc_acm_slave = (UX_SLAVE_CLASS_CDC_ACM *) cdc_instance;
}
static VOID demo_cdc_instance_deactivate(VOID *cdc_instance)
{
/* Don't Reset the CDC instance. We need to use it after disconnection to
check for the line state values. */
//cdc_acm_slave = UX_NULL;
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_acm_device_dtr_rts_reset_on_disconnect_test_application_define(void *first_unused_memory)
#endif
{
CHAR * stack_pointer;
CHAR * memory_pointer;
UINT status;
/* 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("Running CDC ACM Basic Functionality Test............................ ERROR #1\n");
test_control_return(1);
}
/* The code below is required for installing the host portion of USBX */
status = ux_host_stack_initialize(UX_NULL);
if (status != UX_SUCCESS)
{
printf("Running CDC ACM Basic Functionality Test............................ ERROR #2\n");
test_control_return(1);
}
/* Register CDC-ACM class. */
status = ux_host_stack_class_register(_ux_system_host_class_cdc_acm_name, ux_host_class_cdc_acm_entry);
if (status != UX_SUCCESS)
{
printf("Running CDC ACM Basic Functionality Test............................ ERROR #3\n");
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_hcd_sim_host_initialize,0,0);
if (status != UX_SUCCESS)
{
printf("Running CDC ACM Basic Functionality Test............................ ERROR #4\n");
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Running CDC ACM Basic Functionality Test............................ ERROR #5\n");
test_control_return(1);
}
/* Set the parameters for callback when insertion/extraction of a CDC device. */
parameter.ux_slave_class_cdc_acm_instance_activate = demo_cdc_instance_activate;
parameter.ux_slave_class_cdc_acm_instance_deactivate = demo_cdc_instance_deactivate;
/* Initialize the device cdc class. This class owns both interfaces starting with 0. */
status = ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
1,0, &parameter);
if(status!=UX_SUCCESS)
{
printf("Running CDC ACM Basic Functionality Test............................ ERROR #6\n");
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != TX_SUCCESS)
{
printf("Running CDC ACM Basic Functionality Test............................ ERROR #7\n");
test_control_return(1);
}
/* 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("Running CDC ACM Basic Functionality Test............................ ERROR #9\n");
test_control_return(1);
}
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_SLAVE_CLASS_CDC_ACM_LINE_STATE_PARAMETER line_state_slave;
/* Inform user. */
printf("Running Device CDC-ACM DTR/RTS Reset on Disconnect Test............. ");
/* Find the cdc_acm class and wait for the link to be up. */
status = demo_class_cdc_acm_get();
if (status != UX_SUCCESS)
{
/* DPUMP basic test error. */
printf("ERROR #10\n");
test_control_return(1);
}
while (!cdc_acm_slave);
/* Wait for RTS and DTR. */
do
{
UX_TEST_CHECK_SUCCESS(ux_device_class_cdc_acm_ioctl(cdc_acm_slave, UX_SLAVE_CLASS_CDC_ACM_IOCTL_GET_LINE_STATE, &line_state_slave));
}
while (line_state_slave.ux_slave_class_cdc_acm_parameter_dtr == 0 ||
line_state_slave.ux_slave_class_cdc_acm_parameter_rts == 0);
/* Now disconnect. */
ux_test_disconnect_slave();
ux_test_disconnect_host_wait_for_enum_completion();
/* Now make sure DTR and RTS are reset. */
UX_TEST_CHECK_SUCCESS(ux_device_class_cdc_acm_ioctl(cdc_acm_slave, UX_SLAVE_CLASS_CDC_ACM_IOCTL_GET_LINE_STATE, &line_state_slave));
UX_TEST_ASSERT(line_state_slave.ux_slave_class_cdc_acm_parameter_dtr == 0 &&
line_state_slave.ux_slave_class_cdc_acm_parameter_rts == 0);
/* Successful test. */
printf("SUCCESS!\n");
test_control_return(0);
}

View File

@ -0,0 +1,62 @@
/* This tests the case where the host sets the device's alternate setting to
zero. */
#include "usbx_ux_test_cdc_ecm.h"
#include "ux_host_stack.h"
static UCHAR host_ready_for_basic_test;
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_alternate_setting_change_to_zero_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC ECM Alternate Setting Change To Zero Test............... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize(first_unused_memory);
}
static void post_init_host()
{
/* Change the data interface alternate setting to zero. */
_ux_host_stack_interface_set(cdc_ecm_host->ux_host_class_cdc_ecm_interface_data);
/* Wait for the host to change settings, which means the device has too. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&cdc_ecm_host->ux_host_class_cdc_ecm_link_state, 0));
/* Change the data interface alternate setting back to one. */
_ux_host_stack_interface_set(cdc_ecm_host->ux_host_class_cdc_ecm_interface_data->ux_interface_next_interface);
/* Wait for the host to change settings, which means the device has too. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&cdc_ecm_host->ux_host_class_cdc_ecm_link_state, 1));
/* Try a basic test. */
host_ready_for_basic_test = 1;
cdc_ecm_basic_test(BASIC_TEST_HOST, BASIC_TEST_TCP);
/* Huzzah! */
/* Change the data interface alternate setting to zero again - this time, with no deactivate callback. */
cdc_ecm_device->ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_deactivate = UX_NULL;
_ux_host_stack_interface_set(cdc_ecm_host->ux_host_class_cdc_ecm_interface_data);
/* Wait for the host to change settings, which means the device has too. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&cdc_ecm_host->ux_host_class_cdc_ecm_link_state, 0));
/* Huzzah! Again! */
}
static void post_init_device()
{
/* Wait for basic test. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&host_ready_for_basic_test, 1));
cdc_ecm_basic_test(BASIC_TEST_DEVICE, BASIC_TEST_TCP);
}

View File

@ -0,0 +1,724 @@
#ifndef USBX_UX_TEST_CDC_ECM_H
#define USBX_UX_TEST_CDC_ECM_H
#include "ux_api.h"
#include "ux_system.h"
#include "ux_utility.h"
#include "ux_network_driver.h"
#include "ux_host_class_cdc_ecm.h"
#include "ux_device_class_cdc_ecm.h"
#include "ux_test_dcd_sim_slave.h"
#include "ux_test_hcd_sim_host.h"
#include "ux_test_utility_sim.h"
#include "ux_test.h"
#include "ux_test_actions.h"
//#define LOCAL_MACHINE
typedef struct DEVICE_INIT_DATA
{
UCHAR *framework;
ULONG framework_length;
UCHAR dont_register_hcd;
UCHAR *string_framework;
ULONG string_framework_length;
} DEVICE_INIT_DATA;
#define DEMO_IP_THREAD_STACK_SIZE (8*1024)
#define HOST_IP_ADDRESS IP_ADDRESS(192,168,1,176)
#define HOST_SOCKET_PORT_UDP 45054
#define HOST_SOCKET_PORT_TCP 45056
#define DEVICE_IP_ADDRESS IP_ADDRESS(192,168,1,175)
#define DEVICE_SOCKET_PORT_UDP 45055
#define DEVICE_SOCKET_PORT_TCP 45057
#define PACKET_PAYLOAD 1400
#define PACKET_POOL_SIZE (PACKET_PAYLOAD*10000)
#define ARP_MEMORY_SIZE 1024
/* Define local constants. */
#define UX_DEMO_STACK_SIZE (4*1024)
#define UX_USBX_MEMORY_SIZE (128*1024)
/* Define basic test constants. */
#define BASIC_TEST_NUM_ITERATIONS 10
#define BASIC_TEST_NUM_PACKETS_PER_ITERATION 10
#define BASIC_TEST_NUM_TOTAL_PACKETS (BASIC_TEST_NUM_ITERATIONS*BASIC_TEST_NUM_PACKETS_PER_ITERATION)
#define BASIC_TEST_HOST 0
#define BASIC_TEST_DEVICE 1
#define BASIC_TEST_TCP 0
#define BASIC_TEST_UDP 1
/* Host */
static UX_HOST_CLASS *class_driver_host;
static UX_HOST_CLASS_CDC_ECM *cdc_ecm_host;
static UX_HOST_CLASS_CDC_ECM *cdc_ecm_host_from_system_change_function;
static TX_THREAD thread_host;
static UCHAR thread_stack_host[UX_DEMO_STACK_SIZE];
static NX_IP nx_ip_host;
static NX_PACKET_POOL packet_pool_host;
static NX_PACKET_POOL *packet_pool_host_ptr = &packet_pool_host;
static NX_UDP_SOCKET udp_socket_host;
static NX_TCP_SOCKET tcp_socket_host;
static CHAR *packet_pool_memory_host;
static CHAR ip_thread_stack_host[DEMO_IP_THREAD_STACK_SIZE];
static CHAR arp_memory_host[ARP_MEMORY_SIZE];
/* Device */
static TX_THREAD thread_device;
static UX_HOST_CLASS *class_driver_device;
static UX_SLAVE_CLASS_CDC_ECM *cdc_ecm_device;
static UX_SLAVE_CLASS_CDC_ECM_PARAMETER cdc_ecm_parameter;
static UCHAR thread_stack_device[UX_DEMO_STACK_SIZE];
static NX_IP nx_ip_device;
static NX_PACKET_POOL packet_pool_device;
static NX_UDP_SOCKET udp_socket_device;
//static NX_TCP_SOCKET tcp_socket_device;
static CHAR *packet_pool_memory_device;
static CHAR ip_thread_stack_device[DEMO_IP_THREAD_STACK_SIZE];
static CHAR arp_memory_device[ARP_MEMORY_SIZE];
static UCHAR global_is_device_initialized;
static UCHAR global_host_ready_for_application;
static ULONG global_basic_test_num_writes_host;
static ULONG global_basic_test_num_reads_host;
static ULONG global_basic_test_num_writes_device;
static ULONG global_basic_test_num_reads_device;
static UCHAR device_is_finished;
NXD_ADDRESS ipv6_addr_host;
NXD_ADDRESS ipv6_addr_device;
/* Define local prototypes and definitions. */
static void thread_entry_host(ULONG arg);
static void thread_entry_device(ULONG arg);
static void post_init_host();
static void post_init_device();
#define DEFAULT_FRAMEWORK_LENGTH sizeof(default_device_framework)
static unsigned char default_device_framework[] = {
/* Device Descriptor */
0x12, /* bLength */
0x01, /* bDescriptorType */
0x10, 0x01, /* bcdUSB */
0xef, /* bDeviceClass - Depends on bDeviceSubClass */
0x02, /* bDeviceSubClass - Depends on bDeviceProtocol */
0x01, /* bDeviceProtocol - There's an IAD */
0x40, /* bMaxPacketSize0 */
0x70, 0x07, /* idVendor */
0x42, 0x10, /* idProduct */
0x00, 0x01, /* bcdDevice */
0x01, /* iManufacturer */
0x02, /* iProduct */
0x03, /* iSerialNumber */
0x01, /* bNumConfigurations */
/* Configuration Descriptor */
0x09, /* bLength */
0x02, /* bDescriptorType */
0x58, 0x00, /* wTotalLength */
0x02, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
0xc0, /* bmAttributes - Self-powered */
0x00, /* bMaxPower */
/* Interface Association Descriptor */
0x08, /* bLength */
0x0b, /* bDescriptorType */
0x00, /* bFirstInterface */
0x02, /* bInterfaceCount */
0x02, /* bFunctionClass - CDC - Communication */
0x06, /* bFunctionSubClass - ECM */
0x00, /* bFunctionProtocol - No class specific protocol required */
0x00, /* iFunction */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndpoints */
0x02, /* bInterfaceClass - CDC - Communication */
0x06, /* bInterfaceSubClass - ECM */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* CDC Header Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x00, /* bDescriptorSubType */
0x10, 0x01, /* bcdCDC */
/* CDC ECM Functional Descriptor */
0x0d, /* bLength */
0x24, /* bDescriptorType */
0x0f, /* bDescriptorSubType */
0x04, /* iMACAddress */
0x00, 0x00, 0x00, 0x00, /* bmEthernetStatistics */
0xea, 0x05, /* wMaxSegmentSize */
0x00, 0x00, /* wNumberMCFilters */
0x00, /* bNumberPowerFilters */
/* CDC Union Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x06, /* bDescriptorSubType */
0x00, /* bmMasterInterface */
0x01, /* bmSlaveInterface0 */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x83, /* bEndpointAddress */
0x03, /* bmAttributes - Interrupt */
0x08, 0x00, /* wMaxPacketSize */
0x08, /* bInterval */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x01, /* bAlternateSetting */
0x02, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x02, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x81, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
};
static unsigned char default_string_framework[] = {
/* Manufacturer string descriptor : Index 1 - "Express Logic" */
0x09, 0x04, 0x01, 0x0c,
0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x20, 0x4c,
0x6f, 0x67, 0x69, 0x63,
/* Product string descriptor : Index 2 - "EL CDCECM Device" */
0x09, 0x04, 0x02, 0x10,
0x45, 0x4c, 0x20, 0x43, 0x44, 0x43, 0x45, 0x43,
0x4d, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
/* Serial Number string descriptor : Index 3 - "0001" */
0x09, 0x04, 0x03, 0x04,
0x30, 0x30, 0x30, 0x31,
/* MAC Address string descriptor : Index 4 - "001E5841B879" */
0x09, 0x04, 0x04, 0x0C,
0x30, 0x30, 0x31, 0x45, 0x35, 0x38,
0x34, 0x31, 0x42, 0x38, 0x37, 0x39,
};
/* Multiple languages are supported on the device, to add
a language besides english, the unicode language code must
be appended to the language_id_framework array and the length
adjusted accordingly. */
static unsigned char language_id_framework[] = {
/* English. */
0x09, 0x04
};
static DEVICE_INIT_DATA default_device_init_data = {
.framework = default_device_framework,
.framework_length = sizeof(default_device_framework),
.dont_register_hcd = 0,
.string_framework = default_string_framework,
.string_framework_length = sizeof(default_string_framework)
};
static void ux_test_cdc_ecm_initialize_use_framework(void *first_unused_memory, DEVICE_INIT_DATA *device_init_data)
{
CHAR *memory_pointer = first_unused_memory;
/* Initialize possible uninitialized device init values. */
if (device_init_data->framework == NULL)
{
device_init_data->framework = default_device_framework;
device_init_data->framework_length = sizeof(default_device_framework);
}
if (device_init_data->string_framework == NULL)
{
device_init_data->string_framework = default_string_framework;
device_init_data->string_framework_length = sizeof(default_string_framework);
}
/* Initialize USBX Memory. */
ux_system_initialize(memory_pointer, UX_USBX_MEMORY_SIZE, UX_NULL, 0);
memory_pointer += UX_USBX_MEMORY_SIZE;
/* It looks weird if this doesn't have a comment! */
ux_utility_error_callback_register(ux_test_error_callback);
/* Perform the initialization of the network driver. */
UX_TEST_CHECK_SUCCESS(ux_network_driver_init());
/* Initialize the NetX system. */
nx_system_initialize();
/* Now allocate memory for the packet pools. Note that using the memory passed
to us by ThreadX is mucho bettero than putting it in global memory because
we can reuse the memory for each test. So no more having to worry about
running out of memory! */
packet_pool_memory_host = memory_pointer;
memory_pointer += PACKET_POOL_SIZE;
packet_pool_memory_device = memory_pointer;
memory_pointer += PACKET_POOL_SIZE;
/* Create the host thread. */
UX_TEST_CHECK_SUCCESS(tx_thread_create(&thread_host, "host thread", thread_entry_host, (ULONG)(ALIGN_TYPE)device_init_data,
thread_stack_host, UX_DEMO_STACK_SIZE,
30, 30, 1, TX_DONT_START));
UX_THREAD_EXTENSION_PTR_SET(&thread_host, device_init_data)
tx_thread_resume(&thread_host);
/* Create the slave thread. */
UX_TEST_CHECK_SUCCESS(tx_thread_create(&thread_device, "device thread", thread_entry_device, (ULONG)(ALIGN_TYPE)device_init_data,
thread_stack_device, UX_DEMO_STACK_SIZE,
30, 30, 1, TX_DONT_START));
UX_THREAD_EXTENSION_PTR_SET(&thread_device, device_init_data)
tx_thread_resume(&thread_device);
}
static void ux_test_cdc_ecm_initialize(void *first_unused_memory)
{
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &default_device_init_data);
}
static UINT system_change_function(ULONG event, UX_HOST_CLASS *class, VOID *instance)
{
if (event == UX_DEVICE_INSERTION)
{
cdc_ecm_host_from_system_change_function = instance;
}
else if (event == UX_DEVICE_REMOVAL)
{
cdc_ecm_host_from_system_change_function = UX_NULL;
}
return(UX_SUCCESS);
}
static void class_cdc_ecm_get_host(void)
{
UX_HOST_CLASS *class;
/* Find the main storage container */
UX_TEST_CHECK_SUCCESS(ux_host_stack_class_get(_ux_system_host_class_cdc_ecm_name, &class));
/* We get the first instance of the storage device */
UX_TEST_CHECK_SUCCESS(ux_test_host_stack_class_instance_get(class, 0, (void **) &cdc_ecm_host));
/* We still need to wait for the cdc-ecm status to be live */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uint(&cdc_ecm_host -> ux_host_class_cdc_ecm_state, UX_HOST_CLASS_INSTANCE_LIVE));
/* Now wait for the link to be up. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&cdc_ecm_host->ux_host_class_cdc_ecm_link_state, UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP));
}
static VOID demo_cdc_ecm_instance_activate(VOID *cdc_ecm_instance)
{
/* Save the CDC instance. */
cdc_ecm_device = (UX_SLAVE_CLASS_CDC_ECM *) cdc_ecm_instance;
}
static VOID demo_cdc_ecm_instance_deactivate(VOID *cdc_ecm_instance)
{
/* Reset the CDC instance. */
cdc_ecm_device = UX_NULL;
}
/* Copied and pasted from ux_device_class_cdc_ecm_change.c. */
static void ux_test_device_class_cdc_ecm_set_link_state(UX_SLAVE_CLASS_CDC_ECM *cdc_ecm, UCHAR new_link_state)
{
/* Declare the link to be down. */
cdc_ecm_device -> ux_slave_class_cdc_ecm_link_state = new_link_state;
/* We have a thread waiting for an event, we wake it up with a NETWORK NOTIFICATION CHANGE event.
In turn they will release the NetX resources used and suspend. */
UX_TEST_CHECK_SUCCESS(_ux_utility_event_flags_set(&cdc_ecm_device -> ux_slave_class_cdc_ecm_event_flags_group, UX_DEVICE_CLASS_CDC_ECM_NETWORK_NOTIFICATION_EVENT, TX_OR));
}
static void read_packet_tcp(NX_TCP_SOCKET *tcp_socket, ULONG num_reads, CHAR *name)
{
NX_PACKET *rcv_packet;
ULONG num_writes_from_peer;
#ifndef LOCAL_MACHINE
if (num_reads % 100 == 0)
#endif
stepinfo("%s reading tcp packet# %lu\n", name, num_reads);
UX_TEST_CHECK_SUCCESS(nx_tcp_socket_receive(tcp_socket, &rcv_packet, NX_WAIT_FOREVER));
num_writes_from_peer = *(ULONG *)rcv_packet->nx_packet_prepend_ptr;
UX_TEST_ASSERT(num_writes_from_peer == num_reads);
UX_TEST_CHECK_SUCCESS(nx_packet_release(rcv_packet));
}
static void write_packet_tcp(NX_TCP_SOCKET *tcp_socket, NX_PACKET_POOL *packet_pool, ULONG num_writes, CHAR *name)
{
NX_PACKET *out_packet;
UX_TEST_CHECK_SUCCESS(nx_packet_allocate(packet_pool, &out_packet, NX_TCP_PACKET, NX_WAIT_FOREVER));
*(ULONG *)out_packet->nx_packet_prepend_ptr = num_writes;
out_packet->nx_packet_length = sizeof(ULONG);
out_packet->nx_packet_append_ptr = out_packet->nx_packet_prepend_ptr + out_packet->nx_packet_length;
#ifndef LOCAL_MACHINE
if (num_writes % 100 == 0)
#endif
stepinfo("%s writing tcp packet# %lu\n", name, num_writes);
UX_TEST_CHECK_SUCCESS(nx_tcp_socket_send(tcp_socket, out_packet, NX_WAIT_FOREVER));
}
static void read_packet_udp(NX_UDP_SOCKET *udp_socket, ULONG num_reads, CHAR *name)
{
NX_PACKET *rcv_packet;
ULONG num_writes_from_peer;
#ifndef LOCAL_MACHINE
if (num_reads % 100 == 0)
#endif
stepinfo("%s reading udp packet# %lu\n", name, num_reads);
UX_TEST_CHECK_SUCCESS(nx_udp_socket_receive(udp_socket, &rcv_packet, NX_WAIT_FOREVER));
num_writes_from_peer = *(ULONG *)rcv_packet->nx_packet_prepend_ptr;
UX_TEST_ASSERT(num_writes_from_peer == num_reads);
UX_TEST_CHECK_SUCCESS(nx_packet_release(rcv_packet));
}
static void write_packet_udp(NX_UDP_SOCKET *udp_socket, NX_PACKET_POOL *packet_pool, ULONG ip_address, ULONG port, ULONG num_writes, CHAR *name)
{
NX_PACKET *out_packet;
UX_TEST_CHECK_SUCCESS(nx_packet_allocate(packet_pool, &out_packet, NX_UDP_PACKET, NX_WAIT_FOREVER));
*(ULONG *)out_packet->nx_packet_prepend_ptr = num_writes;
out_packet->nx_packet_length = sizeof(ULONG);
out_packet->nx_packet_append_ptr = out_packet->nx_packet_prepend_ptr + out_packet->nx_packet_length;
#ifndef LOCAL_MACHINE
if (num_writes % 100 == 0)
#endif
stepinfo("%s writing udp packet# %lu\n", name, num_writes);
UX_TEST_CHECK_SUCCESS(nx_udp_socket_send(udp_socket, out_packet, ip_address, port));
}
static void thread_entry_host(ULONG device_init_data_ptr)
{
DEVICE_INIT_DATA *device_init_data;
UX_THREAD_EXTENSION_PTR_GET(device_init_data, DEVICE_INIT_DATA, device_init_data_ptr);
/* Wait for device to initialize. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&global_is_device_initialized, 1));
/* Create the IP instance. */
UX_TEST_CHECK_SUCCESS(nx_packet_pool_create(&packet_pool_host, "NetX Host Packet Pool", PACKET_PAYLOAD, packet_pool_memory_host, PACKET_POOL_SIZE));
UX_TEST_CHECK_SUCCESS(nx_ip_create(&nx_ip_host, "NetX Host Thread", HOST_IP_ADDRESS, 0xFF000000UL,
&packet_pool_host, _ux_network_driver_entry, ip_thread_stack_host, DEMO_IP_THREAD_STACK_SIZE, 1));
/* Setup ARP. */
UX_TEST_CHECK_SUCCESS(nx_arp_enable(&nx_ip_host, (void *)arp_memory_host, ARP_MEMORY_SIZE));
UX_TEST_CHECK_SUCCESS(nx_arp_static_entry_create(&nx_ip_host, DEVICE_IP_ADDRESS, 0x0000001E, 0x80032CD8));
/* Setup UDP. */
UX_TEST_CHECK_SUCCESS(nx_udp_enable(&nx_ip_host));
UX_TEST_CHECK_SUCCESS(nx_udp_socket_create(&nx_ip_host, &udp_socket_host, "USB HOST UDP SOCKET", NX_IP_NORMAL, NX_DONT_FRAGMENT, 20, 20));
UX_TEST_CHECK_SUCCESS(nx_udp_socket_bind(&udp_socket_host, HOST_SOCKET_PORT_UDP, NX_NO_WAIT));
// /* Setup TCP. */
// UX_TEST_CHECK_SUCCESS(nx_tcp_enable(&nx_ip_host));
// UX_TEST_CHECK_SUCCESS(nx_tcp_socket_create(&nx_ip_host, &tcp_socket_host, "USB HOST TCP SOCKET", NX_IP_NORMAL, NX_DONT_FRAGMENT, NX_IP_TIME_TO_LIVE, 100, NX_NULL, NX_NULL));
// UX_TEST_CHECK_SUCCESS(nx_tcp_server_socket_listen(&nx_ip_host, HOST_SOCKET_PORT_TCP, &tcp_socket_host, 5, NX_NULL));
#if 1
UX_TEST_CHECK_SUCCESS(nxd_ipv6_enable(&nx_ip_host));
UX_TEST_CHECK_SUCCESS(nxd_icmp_enable(&nx_ip_host));
UX_TEST_CHECK_SUCCESS(nx_ip_raw_packet_enable(&nx_ip_host));
#endif
ipv6_addr_host.nxd_ip_version = NX_IP_VERSION_V6;
ipv6_addr_host.nxd_ip_address.v6[0] = 0x20010000;
ipv6_addr_host.nxd_ip_address.v6[1] = 0x00000000;
ipv6_addr_host.nxd_ip_address.v6[2] = 0x00000000;
ipv6_addr_host.nxd_ip_address.v6[3] = 0x00010001;
UX_TEST_CHECK_SUCCESS(nxd_ipv6_address_set(&nx_ip_host, 0, &ipv6_addr_host, 64, NX_NULL));
/* The code below is required for installing the host portion of USBX. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_initialize(system_change_function));
/* Register cdc_ecm class. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_class_register(_ux_system_host_class_cdc_ecm_name, ux_host_class_cdc_ecm_entry));
if (!device_init_data->dont_register_hcd)
{
/* Register all the USB host controllers available in this system. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
/* Find the storage class. */
class_cdc_ecm_get_host();
// /* Connect to device TCP socket. */
// UX_TEST_CHECK_SUCCESS(nx_tcp_server_socket_accept(&tcp_socket_host, NX_WAIT_FOREVER));
}
global_host_ready_for_application = 1;
/* Call test code. */
post_init_host();
/* We need to disconnect the host and device. This is because the NetX cleaning
process (in usbxtestcontrol.c) includes disconnect the device, which tries
to send a RST packet to the peer (or something). By disconnecting here,
we ensure the deactivate routines notify the network driver so that the
packet tranmissiong is stopped there. */
ux_test_disconnect_slave();
ux_test_disconnect_host_wait_for_enum_completion();
/* And finally the usbx system resources. */
_ux_system_uninitialize();
/* Successful test. */
printf("SUCCESS!\n");
test_control_return(0);
}
static void thread_entry_device(ULONG device_init_data_ptr)
{
DEVICE_INIT_DATA *device_init_data;
UX_THREAD_EXTENSION_PTR_GET(device_init_data, DEVICE_INIT_DATA, device_init_data_ptr)
/* Create the IP instance. */
UX_TEST_CHECK_SUCCESS(nx_packet_pool_create(&packet_pool_device, "NetX Device Packet Pool", PACKET_PAYLOAD, packet_pool_memory_device, PACKET_POOL_SIZE));
UX_TEST_CHECK_SUCCESS(nx_ip_create(&nx_ip_device, "NetX Device Thread", DEVICE_IP_ADDRESS, 0xFF000000L, &packet_pool_device,
_ux_network_driver_entry, ip_thread_stack_device, DEMO_IP_THREAD_STACK_SIZE, 1));
/* Setup ARP. */
UX_TEST_CHECK_SUCCESS(nx_arp_enable(&nx_ip_device, (void *)arp_memory_device, ARP_MEMORY_SIZE));
UX_TEST_CHECK_SUCCESS(nx_arp_static_entry_create(&nx_ip_device, HOST_IP_ADDRESS, 0x0000001E, 0x5841B878));
/* Setup UDP. */
UX_TEST_CHECK_SUCCESS(nx_udp_enable(&nx_ip_device));
UX_TEST_CHECK_SUCCESS(nx_udp_socket_create(&nx_ip_device, &udp_socket_device, "USB DEVICE UDP SOCKET", NX_IP_NORMAL, NX_DONT_FRAGMENT, 20, 20));
UX_TEST_CHECK_SUCCESS(nx_udp_socket_bind(&udp_socket_device, DEVICE_SOCKET_PORT_UDP, NX_NO_WAIT));
// /* Setup TCP. */
// UX_TEST_CHECK_SUCCESS(nx_tcp_enable(&nx_ip_device));
// UX_TEST_CHECK_SUCCESS(nx_tcp_socket_create(&nx_ip_device, &tcp_socket_device, "USB DEVICE TCP SOCKET", NX_IP_NORMAL, NX_DONT_FRAGMENT, NX_IP_TIME_TO_LIVE, 100, NX_NULL, NX_NULL));
// UX_TEST_CHECK_SUCCESS(nx_tcp_client_socket_bind(&tcp_socket_device, DEVICE_SOCKET_PORT_TCP, NX_WAIT_FOREVER));
#if 1
UX_TEST_CHECK_SUCCESS(nxd_ipv6_enable(&nx_ip_device));
ipv6_addr_device.nxd_ip_version = NX_IP_VERSION_V6;
ipv6_addr_device.nxd_ip_address.v6[0] = 0x20010000;
ipv6_addr_device.nxd_ip_address.v6[1] = 0x00000000;
ipv6_addr_device.nxd_ip_address.v6[2] = 0x00000000;
ipv6_addr_device.nxd_ip_address.v6[3] = 0x00010002;
UX_TEST_CHECK_SUCCESS(nxd_ipv6_address_set(&nx_ip_device, 0, &ipv6_addr_device, 64, NX_NULL));
UX_TEST_CHECK_SUCCESS(nxd_icmp_enable(&nx_ip_device));
UX_TEST_CHECK_SUCCESS(nx_ip_raw_packet_enable(&nx_ip_device));
#endif
/* The code below is required for installing the device portion of USBX.
In this demo, DFU is possible and we have a call back for state change. */
UX_TEST_CHECK_SUCCESS(ux_device_stack_initialize(device_init_data->framework, device_init_data->framework_length,
device_init_data->framework, device_init_data->framework_length,
device_init_data->string_framework, device_init_data->string_framework_length,
language_id_framework, sizeof(language_id_framework),
UX_NULL));
/* Set the parameters for callback when insertion/extraction of a CDC device. Set to NULL.*/
cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_activate = demo_cdc_ecm_instance_activate;
cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_deactivate = demo_cdc_ecm_instance_deactivate;
/* Define a NODE ID. */
cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_local_node_id[0] = 0x00;
cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_local_node_id[1] = 0x1e;
cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_local_node_id[2] = 0x58;
cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_local_node_id[3] = 0x41;
cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_local_node_id[4] = 0xb8;
cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_local_node_id[5] = 0x78;
/* Define a remote NODE ID. */
cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_remote_node_id[0] = 0x00;
cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_remote_node_id[1] = 0x1e;
cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_remote_node_id[2] = 0x58;
cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_remote_node_id[3] = 0x41;
cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_remote_node_id[4] = 0xb8;
cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_remote_node_id[5] = 0x79;
/* Initialize the device cdc_ecm class. */
UX_TEST_CHECK_SUCCESS(ux_device_stack_class_register(_ux_system_slave_class_cdc_ecm_name, ux_device_class_cdc_ecm_entry, 1, 0, &cdc_ecm_parameter));
/* Initialize the simulated device controller. */
UX_TEST_CHECK_SUCCESS(_ux_test_dcd_sim_slave_initialize());
global_is_device_initialized = UX_TRUE;
if (!device_init_data->dont_register_hcd)
{
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_non_null((VOID **)&cdc_ecm_device));
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&cdc_ecm_device->ux_slave_class_cdc_ecm_link_state, UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP));
// /* Connect to host TCP socket. */
// UX_TEST_CHECK_SUCCESS(nx_tcp_client_socket_connect(&tcp_socket_device, HOST_IP_ADDRESS, HOST_SOCKET_PORT_TCP, NX_WAIT_FOREVER));
}
/* Wait for host - believe this is so that we know host is always first... gives us some 'determinism'. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&global_host_ready_for_application, 1));
/* Call test code. */
post_init_device();
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_basic_ipv6_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC ECM Basic Functionality Test............................ ");
stepinfo("\n");
ux_test_cdc_ecm_initialize(first_unused_memory);
}
static void post_init_host()
{
UINT status;
NX_PACKET *my_packet;
ULONG value;
/* Print out test information banner. */
printf("\nNetX Test: IPv6 Raw Packet Test......................................");
tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
/* Now, pickup the three raw packets that should be queued on the other IP instance. */
UX_TEST_CHECK_SUCCESS(nx_ip_raw_packet_receive(&nx_ip_host, &my_packet, 2 * NX_IP_PERIODIC_RATE));
if(memcmp(my_packet -> nx_packet_prepend_ptr, "ABCDEFGHIJKLMNOPQRSTUVWXYZ ", 28)) {
printf("ERROR #3\n");
test_control_return(1);
}
UX_TEST_CHECK_SUCCESS(nx_packet_release(my_packet));
/* Wait for device to finish. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&device_is_finished, UX_TRUE));
/* Disconnect. */
ux_test_disconnect_slave_and_host_wait_for_enum_completion();
/* Connect with null system change function. */
_ux_system_host->ux_system_host_change_function = UX_NULL;
/* Connect. */
ux_test_connect_slave_and_host_wait_for_enum_completion();
/* We're done. */
}
static void post_init_device()
{
UINT status;
NX_PACKET *my_packet;
NXD_ADDRESS dest_addr;
ULONG value;
tx_thread_sleep(1 * NX_IP_PERIODIC_RATE);
/* Allocate a packet. */
UX_TEST_CHECK_SUCCESS(nx_packet_allocate(&packet_pool_device, &my_packet, NX_UDP_PACKET, 2 * NX_IP_PERIODIC_RATE));
/* Write ABCs into the packet payload! */
UX_TEST_CHECK_SUCCESS(nx_packet_data_append(my_packet, "ABCDEFGHIJKLMNOPQRSTUVWXYZ ", 28, &packet_pool_device, 2 * NX_IP_PERIODIC_RATE));
/* Send the raw IP packet. */
UX_TEST_CHECK_SUCCESS(nxd_ip_raw_packet_send(&nx_ip_device, my_packet, &ipv6_addr_host, NX_IP_RAW >> 16, 0x80, NX_IP_NORMAL));
device_is_finished = UX_TRUE;
}
#endif //USBX_UX_TEST_CDC_ECM_H

View File

@ -0,0 +1,354 @@
/* Include necessary system files. */
#include "usbx_ux_test_cdc_ecm.h"
/* Resource usage */
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_cdc_sem_usage;
static ULONG rsc_cdc_sem_get_count;
static ULONG rsc_cdc_mutex_usage;
static ULONG rsc_cdc_mem_alloc_count;
static ULONG rsc_cdc_mem_tx_rx_count;
static ULONG error_callback_counter;
/* Log resources usage on SetConfigure */
static UX_TEST_SETUP _SetConfigure = UX_TEST_SETUP_SetConfigure;
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();
}
static UX_TEST_HCD_SIM_ACTION log_on_SetCfg[] = {
{ .function = UX_HCD_TRANSFER_REQUEST,
.req_setup = &_SetConfigure,
.req_action = UX_TEST_SETUP_MATCH_REQ,
.action_func = ux_test_hcd_entry_set_cfg,
.no_return = UX_TRUE
}, /* Invoke callback & continue */
{ 0 }
};
static void count_error_callback(struct UX_TEST_ACTION_STRUCT *action, VOID *params)
{
UX_TEST_ERROR_CALLBACK_PARAMS *error = (UX_TEST_ERROR_CALLBACK_PARAMS *)params;
// printf("error trap: 0x%x, 0x%x, 0x%x\n", error->system_level, error->system_context, error->error_code);
error_callback_counter ++;
}
static UX_TEST_HCD_SIM_ACTION count_on_error_trap[] = {
{ .usbx_function = UX_TEST_OVERRIDE_ERROR_CALLBACK,
.action_func = count_error_callback,
},
{ 0 }
};
static UINT sleep_break_on_error(VOID)
{
if (error_callback_counter >= 3)
return error_callback_counter;
return UX_SUCCESS;
}
static UINT sleep_break_on_host_tx_or_rx_buffer_allocated(VOID)
{
UINT buffer_count = 0;
if (cdc_ecm_host == UX_NULL)
return(UX_SUCCESS);
if (cdc_ecm_host -> ux_host_class_cdc_ecm_xmit_buffer)
buffer_count ++;
if (cdc_ecm_host -> ux_host_class_cdc_ecm_receive_buffer)
buffer_count ++;
return (buffer_count);
}
static UINT sleep_break_on_host_tx_and_rx_buffer_allocated(VOID)
{
UINT buffer_count = 0;
if (cdc_ecm_host == UX_NULL)
return(UX_SUCCESS);
if (cdc_ecm_host -> ux_host_class_cdc_ecm_xmit_buffer)
buffer_count ++;
if (cdc_ecm_host -> ux_host_class_cdc_ecm_receive_buffer)
buffer_count ++;
return ((buffer_count >=2) ? buffer_count : UX_SUCCESS);
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_basic_memory_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC ECM Basic Memory Test................................... ");
stepinfo("\n");
/* Override error trap. */
ux_test_link_hooks_from_array(count_on_error_trap);
/* 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();
ux_test_cdc_ecm_initialize(first_unused_memory);
}
static void post_init_host()
{
UINT status;
ULONG mem_free;
ULONG test_n;
/* Test disconnect. */
stepinfo(">>>>>>>>>>>>>>>>>>> Test disconnect\n");
ux_test_disconnect_slave();
ux_test_disconnect_host_wait_for_enum_completion();
/* 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;
stepinfo(">>>>>>>>>>>>>>>>>>> Test connect\n");
/* Connect. */
ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
class_cdc_ecm_get_host();
/* 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_cdc_mutex_usage = ux_test_utility_sim_mutex_create_count() - rsc_enum_mutex_usage;
rsc_cdc_sem_usage = ux_test_utility_sim_sem_create_count() - rsc_enum_sem_usage;
rsc_cdc_mem_alloc_count = ux_test_utility_sim_mem_alloc_count() - rsc_enum_mem_alloc_count;
/* Some allocation does not affect enum. */
rsc_cdc_mem_tx_rx_count = 0;
if (cdc_ecm_host->ux_host_class_cdc_ecm_receive_buffer)
rsc_cdc_mem_tx_rx_count ++;
if (cdc_ecm_host->ux_host_class_cdc_ecm_xmit_buffer)
rsc_cdc_mem_tx_rx_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("cdc mem : %ld\n", rsc_cdc_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.
*/
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();
/* 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_FULL_SPEED_DEVICE);
ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
/* Wait and break on error. */
ux_test_breakable_sleep(200, sleep_break_on_error);
/* Check */
if (cdc_ecm_host_from_system_change_function == UX_NULL)
{
printf("ERROR #%d.%ld: Enumeration fail\n", __LINE__, test_n);
test_control_return(1);
}
}
/* Simulate detach and attach for FS enumeration,
and test possible memory allocation error handlings.
*/
if (rsc_cdc_mem_alloc_count) stepinfo(">>>>>>>>>>>>>>>>>>> Memory errors enumeration test\n");
mem_free = (~0);
for (test_n = 0; test_n < rsc_cdc_mem_alloc_count; test_n ++)
{
stepinfo("%4ld / %4ld\n", test_n, rsc_cdc_mem_alloc_count - 1);
/* Disconnect. */
ux_test_dcd_sim_slave_disconnect();
ux_test_hcd_sim_host_disconnect();
/* 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);
if (test_n >= rsc_cdc_mem_alloc_count - rsc_cdc_mem_tx_rx_count)
{
/* Wait and break on errors. */
ux_test_breakable_sleep(200, sleep_break_on_error);
}
else
{
/* Wait and break on errors. */
ux_test_breakable_sleep(200, sleep_break_on_error);
/* Check error */
if (cdc_ecm_host_from_system_change_function != UX_NULL)
{
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_cdc_mem_alloc_count) stepinfo("\n");
/* Test device deinit. */
stepinfo(">>>>>>>>>>>>>>>>>>> Test class deinit\n");
ux_test_disconnect_slave();
ux_test_disconnect_host_wait_for_enum_completion();
ux_device_stack_class_unregister(_ux_system_slave_class_cdc_ecm_name, ux_device_class_cdc_ecm_entry);
/* 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();
stepinfo(">>>>>>>>>>>>>>>>>>> Test class init\n");
UX_TEST_CHECK_SUCCESS(ux_device_stack_class_register(_ux_system_slave_class_cdc_ecm_name, ux_device_class_cdc_ecm_entry, 1, 0, &cdc_ecm_parameter));
/* Log create counts for further tests. */
rsc_cdc_mutex_usage = ux_test_utility_sim_mutex_create_count();
rsc_cdc_sem_usage = ux_test_utility_sim_sem_create_count();
rsc_cdc_mem_alloc_count = ux_test_utility_sim_mem_alloc_count();
/* Lock log base for tests. */
ux_test_utility_sim_mem_alloc_log_lock();
if (rsc_cdc_mem_alloc_count) stepinfo(">>>>>>>>>>>>>>>>>>> Memory errors class init test\n");
mem_free = (~0);
for (test_n = 0; test_n < rsc_cdc_mem_alloc_count; test_n ++)
{
stepinfo("%4ld / %4ld\n", test_n, rsc_cdc_mem_alloc_count - 1);
/* Deinit. */
ux_device_stack_class_unregister(_ux_system_slave_class_cdc_ecm_name, ux_device_class_cdc_ecm_entry);
/* 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-init %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);
/* Init. */
status = ux_device_stack_class_register(_ux_system_slave_class_cdc_ecm_name, ux_device_class_cdc_ecm_entry, 1, 0, &cdc_ecm_parameter);
/* Check error */
if (status != UX_MEMORY_INSUFFICIENT)
{
printf("ERROR #%d.%ld: code 0x%x\n", __LINE__, test_n, status);
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_cdc_mem_alloc_count) stepinfo("\n");
stepinfo(">>>>>>>>>>>>>>>>>>> Test connect to avoid post post operation\n");
/* Connect. */
UX_TEST_CHECK_SUCCESS(ux_device_stack_class_register(_ux_system_slave_class_cdc_ecm_name, ux_device_class_cdc_ecm_entry, 1, 0, &cdc_ecm_parameter));
ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
class_cdc_ecm_get_host();
stepinfo(">>>>>>>>>>>>>>>>>>> post_init_host done\n");
}
static void post_init_device()
{
stepinfo(">>>>>>>>>>>>>>>>>>> post_init_device empty\n");
}

View File

@ -0,0 +1,56 @@
/* Include necessary system files. */
#include "usbx_ux_test_cdc_ecm.h"
static UCHAR device_is_finished;
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_basic_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC ECM Basic Functionality Test............................ ");
stepinfo("\n");
ux_test_cdc_ecm_initialize(first_unused_memory);
}
static void post_init_host()
{
/* Running TCP test. */
stepinfo("running TCP test.\n");
cdc_ecm_basic_test(BASIC_TEST_HOST, BASIC_TEST_TCP);
/* Running UDP test. */
stepinfo("running UDP test.\n");
cdc_ecm_basic_test(BASIC_TEST_HOST, BASIC_TEST_UDP);
/* Wait for device to finish. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&device_is_finished, UX_TRUE));
/* Disconnect. */
ux_test_disconnect_slave_and_host_wait_for_enum_completion();
/* Connect with null system change function. */
_ux_system_host->ux_system_host_change_function = UX_NULL;
/* Connect. */
ux_test_connect_slave_and_host_wait_for_enum_completion();
/* We're done. */
}
static void post_init_device()
{
cdc_ecm_basic_test(BASIC_TEST_DEVICE, BASIC_TEST_TCP);
cdc_ecm_basic_test(BASIC_TEST_DEVICE, BASIC_TEST_UDP);
device_is_finished = UX_TRUE;
}

View File

@ -0,0 +1,170 @@
/* This tests the case where there is no interrupt endpoint in the CDC-ECM control
interface. Host should not report an error since this endpoint is optional. */
#include "usbx_ux_test_cdc_ecm.h"
static unsigned char no_interrupt_endpoint_configuration_descriptor[] = {
/* Device Descriptor */
0x12, /* bLength */
0x01, /* bDescriptorType */
0x10, 0x01, /* bcdUSB */
0xef, /* bDeviceClass - Depends on bDeviceSubClass */
0x02, /* bDeviceSubClass - Depends on bDeviceProtocol */
0x01, /* bDeviceProtocol - There's an IAD */
0x40, /* bMaxPacketSize0 */
0x70, 0x07, /* idVendor */
0x42, 0x10, /* idProduct */
0x00, 0x01, /* bcdDevice */
0x01, /* iManufacturer */
0x02, /* iProduct */
0x03, /* iSerialNumber */
0x01, /* bNumConfigurations */
/* Configuration Descriptor */
0x09, /* bLength */
0x02, /* bDescriptorType */
0x5f, 0x00, /* wTotalLength */
0x02, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
0xc0, /* bmAttributes - Self-powered */
0x00, /* bMaxPower */
/* Interface Association Descriptor */
0x08, /* bLength */
0x0b, /* bDescriptorType */
0x00, /* bFirstInterface */
0x02, /* bInterfaceCount */
0x02, /* bFunctionClass - CDC - Communication */
0x06, /* bFunctionSubClass - ECM */
0x00, /* bFunctionProtocol - No class specific protocol required */
0x00, /* iFunction */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x02, /* bNumEndpoints */
0x02, /* bInterfaceClass - CDC - Communication */
0x06, /* bInterfaceSubClass - ECM */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* CDC Header Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x00, /* bDescriptorSubType */
0x10, 0x01, /* bcdCDC */
/* CDC ECM Functional Descriptor */
0x0d, /* bLength */
0x24, /* bDescriptorType */
0x0f, /* bDescriptorSubType */
0x04, /* iMACAddress */
0x00, 0x00, 0x00, 0x00, /* bmEthernetStatistics */
0xea, 0x05, /* wMaxSegmentSize */
0x00, 0x00, /* wNumberMCFilters */
0x00, /* bNumberPowerFilters */
/* CDC Union Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x06, /* bDescriptorSubType */
0x00, /* bmMasterInterface */
0x01, /* bmSlaveInterface0 */
/* ??? out (to hit non-in case) */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x01, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
/* ??? in (to hit non-interrupt case) */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x82, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x01, /* bAlternateSetting */
0x02, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x03, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x84, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
};
static DEVICE_INIT_DATA device_init_data = {
.framework = no_interrupt_endpoint_configuration_descriptor,
.framework_length = sizeof(no_interrupt_endpoint_configuration_descriptor),
.dont_register_hcd = 1,
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_control_interface_no_interrupt_endpoint_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM No Interrupt Endpoint Test.......................... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
/* Enumerate. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
/* The HCD init function put()s the HCD semaphore, so we can do this here. */
ux_test_wait_for_enum_thread_completion();
}
static void post_init_device()
{
}

View File

@ -0,0 +1,177 @@
/* This tests the following cases:
1. There is an out endpoint, but not bulk.
2. There is an in endpoint, but in bulk. */
#include "usbx_ux_test_cdc_ecm.h"
static unsigned char non_bulk_out_endpoint[] = {
/* Device Descriptor */
0x12, /* bLength */
0x01, /* bDescriptorType */
0x10, 0x01, /* bcdUSB */
0xef, /* bDeviceClass - Depends on bDeviceSubClass */
0x02, /* bDeviceSubClass - Depends on bDeviceProtocol */
0x01, /* bDeviceProtocol - There's an IAD */
0x40, /* bMaxPacketSize0 */
0x70, 0x07, /* idVendor */
0x42, 0x10, /* idProduct */
0x00, 0x01, /* bcdDevice */
0x01, /* iManufacturer */
0x02, /* iProduct */
0x03, /* iSerialNumber */
0x01, /* bNumConfigurations */
/* Configuration Descriptor */
0x09, /* bLength */
0x02, /* bDescriptorType */
0x66, 0x00, /* wTotalLength */
0x02, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
0xc0, /* bmAttributes - Self-powered */
0x00, /* bMaxPower */
/* Interface Association Descriptor */
0x08, /* bLength */
0x0b, /* bDescriptorType */
0x00, /* bFirstInterface */
0x02, /* bInterfaceCount */
0x02, /* bFunctionClass - CDC - Communication */
0x06, /* bFunctionSubClass - ECM */
0x00, /* bFunctionProtocol - No class specific protocol required */
0x00, /* iFunction */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndpoints */
0x02, /* bInterfaceClass - CDC - Communication */
0x06, /* bInterfaceSubClass - ECM */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* CDC Header Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x00, /* bDescriptorSubType */
0x10, 0x01, /* bcdCDC */
/* CDC ECM Functional Descriptor */
0x0d, /* bLength */
0x24, /* bDescriptorType */
0x0f, /* bDescriptorSubType */
0x04, /* iMACAddress */
0x00, 0x00, 0x00, 0x00, /* bmEthernetStatistics */
0xea, 0x05, /* wMaxSegmentSize */
0x00, 0x00, /* wNumberMCFilters */
0x00, /* bNumberPowerFilters */
/* CDC Union Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x06, /* bDescriptorSubType */
0x00, /* bmMasterInterface */
0x01, /* bmSlaveInterface0 */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x81, /* bEndpointAddress */
0x03, /* bmAttributes - Interrupt */
0x08, 0x00, /* wMaxPacketSize */
0x08, /* bInterval */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x01, /* bAlternateSetting */
0x04, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x02, /* bEndpointAddress */
0x03, /* bmAttributes - Interrupt */
0x40, 0x00, /* wMaxPacketSize */
0x01, /* bInterval */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x83, /* bEndpointAddress */
0x03, /* bmAttributes - Interrupt */
0x40, 0x00, /* wMaxPacketSize */
0x01, /* bInterval */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x04, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x85, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
};
static DEVICE_INIT_DATA device_init_data = {
.framework = non_bulk_out_endpoint,
.framework_length = sizeof(non_bulk_out_endpoint),
.dont_register_hcd = 1,
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_data_interface_non_bulk_out_and_non_bulk_in_endpoint_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Non Bulk Out and Non Bulk In Endpoint Test.......... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
/* Enumerate. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
/* The HCD init function put()s the HCD semaphore, so we can do this here. */
ux_test_wait_for_enum_thread_completion();
}
static void post_init_device()
{
}

View File

@ -0,0 +1,177 @@
/* This tests the case where there is no bulk in endpoint in the CDC-ECM data
interface. Host should report an error.
Unfortunately, the device fails during activation if we use the 'no bulk-in
endpoint' descriptor, so we have the device use a correct descriptor, then
force the host to receive the invalid descriptor when it sends the GetDescriptor
request for the configuration descriptor. */
#include "usbx_ux_test_cdc_ecm.h"
static unsigned char no_bulk_in_endpoint_framework[] = {
/* Configuration Descriptor */
0x09, /* bLength */
0x02, /* bDescriptorType */
0x58, 0x00, /* wTotalLength */
0x02, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
0xc0, /* bmAttributes - Self-powered */
0x00, /* bMaxPower */
/* Interface Association Descriptor */
0x08, /* bLength */
0x0b, /* bDescriptorType */
0x00, /* bFirstInterface */
0x02, /* bInterfaceCount */
0x02, /* bFunctionClass - CDC - Communication */
0x06, /* bFunctionSubClass - ECM */
0x00, /* bFunctionProtocol - No class specific protocol required */
0x00, /* iFunction */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndpoints */
0x02, /* bInterfaceClass - CDC - Communication */
0x06, /* bInterfaceSubClass - ECM */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* CDC Header Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x00, /* bDescriptorSubType */
0x10, 0x01, /* bcdCDC */
/* CDC ECM Functional Descriptor */
0x0d, /* bLength */
0x24, /* bDescriptorType */
0x0f, /* bDescriptorSubType */
0x04, /* iMACAddress */
0x00, 0x00, 0x00, 0x00, /* bmEthernetStatistics */
0xea, 0x05, /* wMaxSegmentSize */
0x00, 0x00, /* wNumberMCFilters */
0x00, /* bNumberPowerFilters */
/* CDC Union Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x06, /* bDescriptorSubType */
0x00, /* bmMasterInterface */
0x01, /* bmSlaveInterface0 */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x83, /* bEndpointAddress */
0x03, /* bmAttributes - Interrupt */
0x08, 0x00, /* wMaxPacketSize */
0x08, /* bInterval */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x01, /* bAlternateSetting */
0x02, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* We use two bulk-out endpoints so that the lengths are the same (makes things easier). */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x02, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x01, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
};
static DEVICE_INIT_DATA device_init_data = {
.framework = default_device_framework,
.framework_length = sizeof(default_device_framework),
.dont_register_hcd = 1,
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_data_interface_no_bulk_in_endpoint_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM No Bulk In Endpiont Test............................ ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
int i;
/* We need to intercept the configuration descriptor. */
UX_TEST_ACTION change_config_desc_action = {0};
change_config_desc_action.usbx_function = UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY;
change_config_desc_action.function = UX_HCD_TRANSFER_REQUEST;
change_config_desc_action.req_action = UX_TEST_MATCH_REQ_LEN | UX_TEST_SIM_REQ_ANSWER;
change_config_desc_action.req_requested_len = 0x58; /* Length of config descriptor. */
change_config_desc_action.req_data = no_bulk_in_endpoint_framework;
change_config_desc_action.req_actual_len = sizeof(no_bulk_in_endpoint_framework);
change_config_desc_action.req_status = UX_SUCCESS;
change_config_desc_action.do_after = 0;
change_config_desc_action.no_return = 0;
/* We expect this to fail multiple times since enumeration tries multiple times. */
for (i = 0; i < UX_RH_ENUMERATION_RETRY; i++)
{
ux_test_add_action_to_main_list(change_config_desc_action);
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN));
}
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE));
/* Enumerate. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
/* The HCD init function put()s the HCD semaphore, so we can do this here. */
ux_test_wait_for_enum_thread_completion();
/* Enumeration should've failed. */
UX_TEST_ASSERT(ux_test_check_actions_empty());
UX_TEST_ASSERT(cdc_ecm_host_from_system_change_function == UX_NULL);
}
static void post_init_device()
{
}

View File

@ -0,0 +1,177 @@
/* This tests the case where there is no bulk out endpoint in the CDC-ECM data
interface. Host should report an error.
Unfortunately, the device fails during activation if we use the 'no bulk-out
endpoint' descriptor, so we have the device use a correct descriptor, then
force the host to receive the invalid descriptor when it sends the GetDescriptor
request for the configuration descriptor. */
#include "usbx_ux_test_cdc_ecm.h"
static unsigned char no_bulk_out_endpoint_framework[] = {
/* Configuration Descriptor */
0x09, /* bLength */
0x02, /* bDescriptorType */
0x58, 0x00, /* wTotalLength */
0x02, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
0xc0, /* bmAttributes - Self-powered */
0x00, /* bMaxPower */
/* Interface Association Descriptor */
0x08, /* bLength */
0x0b, /* bDescriptorType */
0x00, /* bFirstInterface */
0x02, /* bInterfaceCount */
0x02, /* bFunctionClass - CDC - Communication */
0x06, /* bFunctionSubClass - ECM */
0x00, /* bFunctionProtocol - No class specific protocol required */
0x00, /* iFunction */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndpoints */
0x02, /* bInterfaceClass - CDC - Communication */
0x06, /* bInterfaceSubClass - ECM */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* CDC Header Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x00, /* bDescriptorSubType */
0x10, 0x01, /* bcdCDC */
/* CDC ECM Functional Descriptor */
0x0d, /* bLength */
0x24, /* bDescriptorType */
0x0f, /* bDescriptorSubType */
0x04, /* iMACAddress */
0x00, 0x00, 0x00, 0x00, /* bmEthernetStatistics */
0xea, 0x05, /* wMaxSegmentSize */
0x00, 0x00, /* wNumberMCFilters */
0x00, /* bNumberPowerFilters */
/* CDC Union Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x06, /* bDescriptorSubType */
0x00, /* bmMasterInterface */
0x01, /* bmSlaveInterface0 */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x83, /* bEndpointAddress */
0x03, /* bmAttributes - Interrupt */
0x08, 0x00, /* wMaxPacketSize */
0x08, /* bInterval */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x01, /* bAlternateSetting */
0x02, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* We use two bulk-in endpoints so that the lengths are the same (makes things easier). */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x82, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x81, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
};
static DEVICE_INIT_DATA device_init_data = {
.framework = default_device_framework,
.framework_length = sizeof(default_device_framework),
.dont_register_hcd = 1,
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_data_interface_no_bulk_out_endpoint_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM No Bulk Out Endpoint Test........................... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
int i;
/* We need to intercept the configuration descriptor. */
UX_TEST_ACTION change_config_desc_action = {0};
change_config_desc_action.usbx_function = UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY;
change_config_desc_action.function = UX_HCD_TRANSFER_REQUEST;
change_config_desc_action.req_action = UX_TEST_MATCH_REQ_LEN | UX_TEST_SIM_REQ_ANSWER;
change_config_desc_action.req_requested_len = 0x58; /* Length of config descriptor. */
change_config_desc_action.req_data = no_bulk_out_endpoint_framework;
change_config_desc_action.req_actual_len = sizeof(no_bulk_out_endpoint_framework);
change_config_desc_action.req_status = UX_SUCCESS;
change_config_desc_action.do_after = 0;
change_config_desc_action.no_return = 0;
/* We expect this to fail multiple times since enumeration tries multiple times. */
for (i = 0; i < UX_RH_ENUMERATION_RETRY; i++)
{
ux_test_add_action_to_main_list(change_config_desc_action);
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN));
}
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE));
/* Enumerate. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
/* The HCD init function put()s the HCD semaphore, so we can do this here. */
ux_test_wait_for_enum_thread_completion();
/* Enumeration should've failed. */
UX_TEST_ASSERT(ux_test_check_actions_empty());
UX_TEST_ASSERT(cdc_ecm_host_from_system_change_function == UX_NULL);
}
static void post_init_device()
{
}

View File

@ -0,0 +1,76 @@
/* This tests the case where the setting the data interface with endpoints fails. */
#include "usbx_ux_test_cdc_ecm.h"
static DEVICE_INIT_DATA device_init_data = {
.framework = default_device_framework,
.framework_length = sizeof(default_device_framework),
.dont_register_hcd = 1,
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_data_interface_setting_select_fails_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running Data Interface Setting Select Fails Test.................... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
int i;
#if 0
/* Create a transfer_request for the SET_INTERFACE request. No data for this request */
transfer_request -> ux_transfer_request_requested_length = 0;
transfer_request -> ux_transfer_request_function = UX_SET_INTERFACE;
transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_INTERFACE;
transfer_request -> ux_transfer_request_index = (USHORT) interface -> ux_interface_descriptor.bInterfaceNumber;
transfer_request -> ux_transfer_request_value = (USHORT) interface -> ux_interface_descriptor.bAlternateSetting;
#endif
UX_TEST_SETUP alternate_setting_set_setup;
alternate_setting_set_setup.ux_test_setup_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_INTERFACE;
alternate_setting_set_setup.ux_test_setup_request = UX_SET_INTERFACE;
alternate_setting_set_setup.ux_test_setup_value = 1; /* Alternate Setting */
alternate_setting_set_setup.ux_test_setup_index = 1; /* Interface (data is 1) */
/* We need to intercept the configuration descriptor. */
UX_TEST_ACTION alternate_setting_fail_action = {0};
alternate_setting_fail_action.usbx_function = UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY;
alternate_setting_fail_action.function = UX_HCD_TRANSFER_REQUEST;
alternate_setting_fail_action.req_action = UX_TEST_SETUP_MATCH_REQUEST;
alternate_setting_fail_action.req_setup = &alternate_setting_set_setup;
alternate_setting_fail_action.status = UX_ERROR;
alternate_setting_fail_action.no_return = 0;
/* We expect this to fail multiple times since enumeration tries multiple times. */
for (i = 0; i < UX_RH_ENUMERATION_RETRY; i++)
{
ux_test_add_action_to_main_list(alternate_setting_fail_action);
}
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE));
/* Enumerate. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
/* The HCD init function put()s the HCD semaphore, so we can do this here. */
ux_test_wait_for_enum_thread_completion();
/* Enumeration should've failed. */
UX_TEST_ASSERT(ux_test_check_actions_empty());
UX_TEST_ASSERT(cdc_ecm_host_from_system_change_function == UX_NULL);
}
static void post_init_device()
{
}

View File

@ -0,0 +1,149 @@
/* This tests the case where the default data interface has endpoints - note that
this is a violation of the specification since according to it, the default
data interface should have 0 endpoints, however, our host supports it since
so many devices violate the spec! */
#include "usbx_ux_test_cdc_ecm.h"
static unsigned char device_framework_high_speed_default_data_interface_with_endpoints[] = {
/* Device Descriptor */
0x12, /* bLength */
0x01, /* bDescriptorType */
0x10, 0x01, /* bcdUSB */
0xef, /* bDeviceClass - Depends on bDeviceSubClass */
0x02, /* bDeviceSubClass - Depends on bDeviceProtocol */
0x01, /* bDeviceProtocol - There's an IAD */
0x40, /* bMaxPacketSize0 */
0x70, 0x07, /* idVendor */
0x42, 0x10, /* idProduct */
0x00, 0x01, /* bcdDevice */
0x01, /* iManufacturer */
0x02, /* iProduct */
0x03, /* iSerialNumber */
0x01, /* bNumConfigurations */
/* Configuration Descriptor */
0x09, /* bLength */
0x02, /* bDescriptorType */
0x4f, 0x00, /* wTotalLength */
0x02, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
0xc0, /* bmAttributes - Self-powered */
0x00, /* bMaxPower */
/* Interface Association Descriptor */
0x08, /* bLength */
0x0b, /* bDescriptorType */
0x00, /* bFirstInterface */
0x02, /* bInterfaceCount */
0x02, /* bFunctionClass - CDC - Communication */
0x06, /* bFunctionSubClass - ECM */
0x00, /* bFunctionProtocol - No class specific protocol required */
0x00, /* iFunction */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndpoints */
0x02, /* bInterfaceClass - CDC - Communication */
0x06, /* bInterfaceSubClass - ECM */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* CDC Header Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x00, /* bDescriptorSubType */
0x10, 0x01, /* bcdCDC */
/* CDC ECM Functional Descriptor */
0x0d, /* bLength */
0x24, /* bDescriptorType */
0x0f, /* bDescriptorSubType */
0x04, /* iMACAddress */
0x00, 0x00, 0x00, 0x00, /* bmEthernetStatistics */
0xea, 0x05, /* wMaxSegmentSize */
0x00, 0x00, /* wNumberMCFilters */
0x00, /* bNumberPowerFilters */
/* CDC Union Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x06, /* bDescriptorSubType */
0x00, /* bmMasterInterface */
0x01, /* bmSlaveInterface0 */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x83, /* bEndpointAddress */
0x03, /* bmAttributes - Interrupt */
0x08, 0x00, /* wMaxPacketSize */
0x08, /* bInterval */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x02, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x02, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x81, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
};
static DEVICE_INIT_DATA device_init_data = {
.framework = device_framework_high_speed_default_data_interface_with_endpoints,
.framework_length = sizeof(device_framework_high_speed_default_data_interface_with_endpoints),
.dont_register_hcd = 0,
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_default_data_interface_with_endpoints_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM default data interface with endpoints Test.......... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
cdc_ecm_basic_test(BASIC_TEST_HOST, BASIC_TEST_TCP);
}
static void post_init_device()
{
cdc_ecm_basic_test(BASIC_TEST_DEVICE, BASIC_TEST_TCP);
}

View File

@ -0,0 +1,53 @@
/* This test ensures everything works after a disconnection and reconnection. */
#include "usbx_ux_test_cdc_ecm.h"
static UCHAR host_ready_for_test_after_reconnection;
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_disconnect_and_reconnect_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Disconnect And Reconnect Test....................... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize(first_unused_memory);
}
static void post_init_host()
{
cdc_ecm_basic_test(BASIC_TEST_HOST, BASIC_TEST_TCP);
/* Now disconnect. */
ux_test_disconnect_host_wait_for_enum_completion();
/* Now reconnect. */
ux_test_connect_host_wait_for_enum_completion();
/* Get class instance. */
class_cdc_ecm_get_host();
/* Tell device we're ready. */
host_ready_for_test_after_reconnection = 1;
/* Now run the basic test again. */
cdc_ecm_basic_test(BASIC_TEST_HOST, BASIC_TEST_TCP);
}
static void post_init_device()
{
cdc_ecm_basic_test(BASIC_TEST_DEVICE, BASIC_TEST_TCP);
/* Now wait for the host to tell us to run the test again. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&host_ready_for_test_after_reconnection, 1));
cdc_ecm_basic_test(BASIC_TEST_DEVICE, BASIC_TEST_TCP);
}

View File

@ -0,0 +1,58 @@
/* This tests the case where the bulk in semaphore at the class level creation
fails. */
#include "usbx_ux_test_cdc_ecm.h"
static DEVICE_INIT_DATA device_init_data = {
.framework = default_device_framework,
.framework_length = sizeof(default_device_framework),
.dont_register_hcd = 1,
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_host_bulk_in_semaphore_create_fail_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Host Bulk In Semaphore Create Fail Test............. ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
int i;
UX_TEST_ACTION semaphore_create_fail_action = {0};
semaphore_create_fail_action.usbx_function = UX_TEST_OVERRIDE_TX_SEMAPHORE_CREATE;
semaphore_create_fail_action.semaphore_name = "host CDC-ECM bulk in wait semaphore";
semaphore_create_fail_action.no_return = 0;
semaphore_create_fail_action.status = UX_ERROR;
for (i = 0; i < UX_RH_ENUMERATION_RETRY; i++)
{
ux_test_add_action_to_main_list(semaphore_create_fail_action);
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_UTILITY, UX_ERROR));
}
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE));
/* Enumerate. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
/* The HCD init function put()s the HCD semaphore, so we can do this here. */
ux_test_wait_for_enum_thread_completion();
UX_TEST_ASSERT(ux_test_check_actions_empty());
UX_TEST_ASSERT(cdc_ecm_host_from_system_change_function == UX_NULL);
}
static void post_init_device()
{
}

View File

@ -0,0 +1,80 @@
/* This tests the case where there is an ongoing transfer on the bulk in endpoint
during deactivation. The deactivate routine should wait for it to finish.
We do this by having the CDC-ECM thread suspend during the transfer arm,
and then begin deactivation. We resume the CDC-ECM thread later! */
#include "usbx_ux_test_cdc_ecm.h"
static UCHAR cdc_ecm_thread_suspended;
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_host_bulk_in_transfer_arming_during_deactivate_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Host Bulk In Transfer Arming During... Test......... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize(first_unused_memory);
}
static VOID suspend_cdc_ecm_thread_action_func(UX_TEST_ACTION *action, VOID *params)
{
/* The CDC-ECM thread is calling us. */
/* Notify test thread. */
cdc_ecm_thread_suspended = 1;
/* Suspend. Test thread should wake us back up. */
tx_thread_suspend(tx_thread_identify());
}
static void post_init_host()
{
/* Right now, host CDC-ECM thread is waiting for a bulk in transfer. We
need for it to re-do a transfer so that we can get it to suspend via our
action. First, we need to create and add our actions. */
UX_TEST_ACTION bulk_in_transfer_suspend_action = {0};
bulk_in_transfer_suspend_action.usbx_function = UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY;
bulk_in_transfer_suspend_action.function = UX_HCD_TRANSFER_REQUEST;
bulk_in_transfer_suspend_action.req_action = UX_TEST_MATCH_EP;
bulk_in_transfer_suspend_action.req_ep_address = 0x81;
bulk_in_transfer_suspend_action.action_func = suspend_cdc_ecm_thread_action_func;
bulk_in_transfer_suspend_action.no_return = 1;
ux_test_add_action_to_main_list(bulk_in_transfer_suspend_action);
/* Now have the CDC-ECM thread re-do the transfer. */
write_packet_tcp(&tcp_socket_device, &packet_pool_device, 1, "device");
/* Wait for CDC-ECM thread to stall. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&cdc_ecm_thread_suspended, 1));
/* Just for the hell of it, null out the system change function so we can hit that case too. */
_ux_system_host->ux_system_host_change_function = UX_NULL;
/* Now disconnect the host. */
ux_test_disconnect_host_no_wait();
/* Now wait for deactivation to suspend, waiting for bulk in to finish. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&cdc_ecm_host -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish, UX_TRUE));
/* Now resume the CDC-ECM thread. */
tx_thread_resume(&cdc_ecm_host->ux_host_class_cdc_ecm_thread);
/* And now wait for deactivation to complete. */
ux_test_wait_for_enum_thread_completion();
/* And now wait for... wait a second, we're done! Smiley face! That was easier than I thought! I'M SO FRICKEN HAPPY RIGHT NOWWWWWW! */
}
static void post_init_device()
{
}

View File

@ -0,0 +1,80 @@
/* This tests the case where there is an ongoing transfer on the bulk in endpoint
during link down. The interrupt notification function should wait for it to finish.
We do this by having the CDC-ECM thread suspend during the transfer arm,
and then begin link down event. We resume the HCD thread later! */
#include "usbx_ux_test_cdc_ecm.h"
static UCHAR cdc_ecm_thread_suspended;
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_host_bulk_in_transfer_arming_during_link_down_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Host Bulk In Transfer Arming During... Test......... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize(first_unused_memory);
}
static VOID suspend_cdc_ecm_thread_action_func(UX_TEST_ACTION *action, VOID *params)
{
/* The CDC-ECM thread is calling us. */
/* Notify test thread. */
cdc_ecm_thread_suspended = 1;
/* Suspend. Test thread should wake us back up. */
tx_thread_suspend(tx_thread_identify());
}
static void post_init_host()
{
/* Right now, host CDC-ECM thread is waiting for a bulk in transfer. We
need for it to re-do a transfer so that we can get it to suspend via our
action. First, we need to create and add our actions. */
UX_TEST_ACTION bulk_in_transfer_suspend_action = {0};
bulk_in_transfer_suspend_action.usbx_function = UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY;
bulk_in_transfer_suspend_action.function = UX_HCD_TRANSFER_REQUEST;
bulk_in_transfer_suspend_action.req_action = UX_TEST_MATCH_EP;
bulk_in_transfer_suspend_action.req_ep_address = 0x81;
bulk_in_transfer_suspend_action.action_func = suspend_cdc_ecm_thread_action_func;
bulk_in_transfer_suspend_action.no_return = 1;
ux_test_add_action_to_main_list(bulk_in_transfer_suspend_action);
/* Now have the CDC-ECM thread re-do the transfer. */
write_packet_tcp(&tcp_socket_device, &packet_pool_device, 1, "device");
/* Wait for CDC-ECM thread to stall. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&cdc_ecm_thread_suspended, 1));
/* Just for the hell of it, null out the system change function so we can hit that case too. */
_ux_system_host->ux_system_host_change_function = UX_NULL;
/* Now change the link to down. */
ux_test_device_class_cdc_ecm_set_link_state(cdc_ecm_device, 0);
/* Now wait for interrupt notification function (AKA hcd thread) to suspend, waiting for bulk in to finish. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&cdc_ecm_host -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish, UX_TRUE));
/* Now resume the CDC-ECM thread. */
tx_thread_resume(&cdc_ecm_host->ux_host_class_cdc_ecm_thread);
/* And now wait for CDC-ECM instance to go down. */
ux_test_wait_for_value_ulong(&cdc_ecm_host->ux_host_class_cdc_ecm_link_state, 0);
/* And now wait for... wait a second, we're done! Smiley face! That was easier than I thought! I'M SO FRICKEN HAPPY RIGHT NOWWWWWW! */
}
static void post_init_device()
{
}

View File

@ -0,0 +1,65 @@
/* This tests the case where the bulk in transfer fails (in the cdc-ecm thread). */
#include "usbx_ux_test_cdc_ecm.h"
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_host_bulk_in_transfer_fail_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Host Bulk In Transfer Fail Test..................... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize(first_unused_memory);
}
static UCHAR is_cdc_ecm_thread_suspended;
static VOID suspend_cdc_ecm_thread_action_func(UX_TEST_ACTION *action, VOID *params)
{
is_cdc_ecm_thread_suspended = 1;
/* We're being called by nx_packet_allocate in cdc-ecm thread. Wait for test
thread to resume us. */
tx_thread_suspend(tx_thread_identify());
}
static void post_init_host()
{
/* Currently, the cdc-ecm thread should be waiting for a transfer to complete.
We need to create an action for having the bulk in transfer fail, add
the action, then send data to host so the cdc-ecm thread will re-arm the
transfer (which should fail). */
/* Create the action for having bulk in transfer fail. */
UX_TEST_ACTION bulk_transfer_fail_action = {0};
bulk_transfer_fail_action.usbx_function = UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY;
bulk_transfer_fail_action.function = UX_HCD_TRANSFER_REQUEST;
bulk_transfer_fail_action.req_action = UX_TEST_MATCH_EP;
bulk_transfer_fail_action.req_ep_address = 0x81;
bulk_transfer_fail_action.no_return = 0;
bulk_transfer_fail_action.status = UX_ERROR;
ux_test_add_action_to_main_list(bulk_transfer_fail_action);
/* Write to the host so the cdc-ecm thread will redo the bulk in transfer. */
write_packet_udp(&udp_socket_device, &packet_pool_device, HOST_IP_ADDRESS, HOST_SOCKET_PORT_UDP, 0, "device");
/* Wait for the arm and fail. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_empty_actions());
/* Wait for the host to re-arm and wait for the transfer. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uint(&cdc_ecm_host->ux_host_class_cdc_ecm_bulk_in_endpoint->ux_endpoint_transfer_request.ux_transfer_request_semaphore.tx_semaphore_suspended_count, 1));
/* Now we're done. */
}
static void post_init_device()
{
}

View File

@ -0,0 +1,58 @@
/* This tests the case where the bulk out semaphore at the class level creation
fails. */
#include "usbx_ux_test_cdc_ecm.h"
static DEVICE_INIT_DATA device_init_data = {
.framework = default_device_framework,
.framework_length = sizeof(default_device_framework),
.dont_register_hcd = 1,
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_host_bulk_out_semaphore_create_fail_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Host Bulk Out Semaphore Create Fail Test............ ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
int i;
UX_TEST_ACTION semaphore_create_fail_action = {0};
semaphore_create_fail_action.usbx_function = UX_TEST_OVERRIDE_TX_SEMAPHORE_CREATE;
semaphore_create_fail_action.semaphore_name = "host CDC-ECM bulk out wait semaphore";
semaphore_create_fail_action.no_return = 0;
semaphore_create_fail_action.status = UX_ERROR;
for (i = 0; i < UX_RH_ENUMERATION_RETRY; i++)
{
ux_test_add_action_to_main_list(semaphore_create_fail_action);
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_UTILITY, UX_ERROR));
}
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE));
/* Enumerate. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
/* The HCD init function put()s the HCD semaphore, so we can do this here. */
ux_test_wait_for_enum_thread_completion();
UX_TEST_ASSERT(ux_test_check_actions_empty());
UX_TEST_ASSERT(cdc_ecm_host_from_system_change_function == UX_NULL);
}
static void post_init_device()
{
}

View File

@ -0,0 +1,45 @@
/* This tests the case where the bulk out transfer fails (in the cdc_ecm_write). */
#include "usbx_ux_test_cdc_ecm.h"
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_host_bulk_out_transfer_fail_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Host Bulk Out Transfer Fail Test.................... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize(first_unused_memory);
}
static void post_init_host()
{
/* Create the action for having bulk in transfer fail. */
UX_TEST_ACTION bulk_transfer_fail_action = {0};
bulk_transfer_fail_action.usbx_function = UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY;
bulk_transfer_fail_action.function = UX_HCD_TRANSFER_REQUEST;
bulk_transfer_fail_action.req_action = UX_TEST_MATCH_EP;
bulk_transfer_fail_action.req_ep_address = 0x02;
bulk_transfer_fail_action.no_return = 0;
bulk_transfer_fail_action.status = UX_ERROR;
ux_test_add_action_to_main_list(bulk_transfer_fail_action);
/* Now send a packet so write function will run. */
write_packet_tcp(&tcp_socket_host, &packet_pool_host, 0, "host");
/* Ensure write failed. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_empty_actions());
/* Now we're done. */
}
static void post_init_device()
{
}

View File

@ -0,0 +1,83 @@
/* This tests the case where the link is down and a thread is waiting for the
bulk in transfer check-and-arm to finish. */
#include "usbx_ux_test_cdc_ecm.h"
static UCHAR cdc_ecm_thread_suspended;
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_host_bulk_in_transfer_arming_fails_due_to_link_down_and_thread_waiting_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Host Bulk In Transfer Arming During... Test......... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize(first_unused_memory);
}
static VOID suspend_cdc_ecm_thread_action_func(UX_TEST_ACTION *action, VOID *params)
{
/* The CDC-ECM thread is calling us. */
/* Notify test thread. */
cdc_ecm_thread_suspended = 1;
/* Suspend. Test thread should wake us back up. */
tx_thread_suspend(tx_thread_identify());
}
VOID cdc_ecm_thread_suspend_action_func(UX_TEST_ACTION *action, VOID *params)
{
cdc_ecm_thread_suspended = 1;
tx_thread_suspend(tx_thread_identify());
}
static void post_init_host()
{
/* Right now, host CDC-ECM thread is waiting for a bulk in transfer. We
need for it to re-do a transfer so that we can get it to suspend via our
action. First, we need to create and add our actions. */
UX_TEST_ACTION bulk_in_transfer_suspend_action = {0};
bulk_in_transfer_suspend_action.usbx_function = UX_TEST_OVERRIDE_NX_PACKET_ALLOCATE;
bulk_in_transfer_suspend_action.name_ptr = ip_pool_host_name;
bulk_in_transfer_suspend_action.action_func = cdc_ecm_thread_suspend_action_func;
ux_test_add_action_to_main_list(bulk_in_transfer_suspend_action);
/* Send data so thread does packet allocate. */
write_packet_udp(&udp_socket_device, &packet_pool_device, HOST_IP_ADDRESS, HOST_SOCKET_PORT_UDP, 0, "device");
/* Wait for the thread to be suspended. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&cdc_ecm_thread_suspended, 1));
/* Set link state to down. */
ux_test_device_class_cdc_ecm_set_link_state(cdc_ecm_device, 0);
/* Now wait for the link to be set to pending down (it won't be down since thread is suspended). */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&cdc_ecm_host->ux_host_class_cdc_ecm_link_state, UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_DOWN));
/* Make CDC-ECM thread think a thread is indeed waiting. */
cdc_ecm_host->ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish = UX_TRUE;
/* Now resume CDC-ECM thread. */
tx_thread_resume(&cdc_ecm_host->ux_host_class_cdc_ecm_thread);
/* Now wait for the semaphore to be put. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&cdc_ecm_host->ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore.tx_semaphore_count, 1));
/* Now get the semaphore so the count is okay. */
tx_semaphore_get(&cdc_ecm_host->ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore, TX_WAIT_FOREVER);
/* And now we're done. */
}
static void post_init_device()
{
}

View File

@ -0,0 +1,89 @@
/* This tests the case where there is an ongoing transfer on the bulk out endpoint
during link down. The interrupt notification function should wait for it to finish.
We do this by having the CDC-ECM thread suspend during the transfer arm,
and then begin link down event. We resume the HCD thread later! */
#include "usbx_ux_test_cdc_ecm.h"
static UCHAR write_thread_suspended;
static TX_THREAD write_thread;
static UCHAR write_thread_stack[2048];
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_host_bulk_out_transfer_arming_during_link_down_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Host Bulk Out Transfer Arming During... Test........ ");
stepinfo("\n");
ux_test_cdc_ecm_initialize(first_unused_memory);
}
static VOID suspend_write_thread_action_func(UX_TEST_ACTION *action, VOID *params)
{
/* The write thread is calling us. */
/* Notify test thread. */
write_thread_suspended = 1;
/* Suspend. Test thread should wake us back up. */
tx_thread_suspend(tx_thread_identify());
}
static void write_thread_entry(ULONG input)
{
/* Do the write. */
write_packet_tcp(&tcp_socket_host, &packet_pool_host, 0, "host");
}
static void post_init_host()
{
/* Create the thread that will do the write. */
UX_TEST_CHECK_SUCCESS(tx_thread_create(&write_thread, "write thread", write_thread_entry, 0, write_thread_stack, sizeof(write_thread_stack), 20, 20, 0, TX_DONT_START));
/* Right now, host CDC-ECM thread is waiting for a bulk out transfer. We
need for it to re-do a transfer so that we can get it to suspend via our
action. First, we need to create and add our actions. */
UX_TEST_ACTION bulk_out_transfer_suspend_action = {0};
bulk_out_transfer_suspend_action.usbx_function = UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY;
bulk_out_transfer_suspend_action.function = UX_HCD_TRANSFER_REQUEST;
bulk_out_transfer_suspend_action.req_action = UX_TEST_MATCH_EP;
bulk_out_transfer_suspend_action.req_ep_address = 0x02;
bulk_out_transfer_suspend_action.action_func = suspend_write_thread_action_func;
bulk_out_transfer_suspend_action.no_return = 1;
ux_test_add_action_to_main_list(bulk_out_transfer_suspend_action);
/* Now start the write thread. */
tx_thread_resume(&write_thread);
/* Now wait for it to be suspended. */
ux_test_wait_for_value_uchar(&write_thread_suspended, 1);
/* Now change the link to down. */
ux_test_device_class_cdc_ecm_set_link_state(cdc_ecm_device, 0);
/* Now wait for CDC-ECM thread to suspend, waiting for bulk out to finish. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&cdc_ecm_host -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish, UX_TRUE));
/* Now resume the write thread. */
tx_thread_resume(&write_thread);
/* And now wait for write instance to go down. */
ux_test_wait_for_value_ulong(&cdc_ecm_host->ux_host_class_cdc_ecm_link_state, 0);
/* And now wait for... wait a second, we're done! Smiley face! That was easier than I thought! I'M SO FRICKEN HAPPY RIGHT NOWWWWWW! */
}
static void post_init_device()
{
}

View File

@ -0,0 +1,58 @@
/* This tests the case where the CDC-ECM thread creation fails. */
#include "usbx_ux_test_cdc_ecm.h"
static DEVICE_INIT_DATA device_init_data = {
.framework = default_device_framework,
.framework_length = sizeof(default_device_framework),
.dont_register_hcd = 1,
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_host_first_interrupt_transfer_fail_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Host First Interrupt Transfer Fail Test............. ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
int i;
UX_TEST_ACTION force_interrupt_transfer_fail_action = {0};
force_interrupt_transfer_fail_action.usbx_function = UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY;
force_interrupt_transfer_fail_action.function = UX_HCD_TRANSFER_REQUEST;
force_interrupt_transfer_fail_action.req_action = UX_TEST_MATCH_EP;
force_interrupt_transfer_fail_action.req_ep_address = 0x83;
force_interrupt_transfer_fail_action.no_return = 0;
force_interrupt_transfer_fail_action.status = UX_ERROR;
for (i = 0; i < UX_RH_ENUMERATION_RETRY; i++)
{
ux_test_add_action_to_main_list(force_interrupt_transfer_fail_action);
}
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE));
/* Enumerate. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
/* The HCD init function put()s the HCD semaphore, so we can do this here. */
ux_test_wait_for_enum_thread_completion();
UX_TEST_ASSERT(ux_test_check_actions_empty());
UX_TEST_ASSERT(cdc_ecm_host_from_system_change_function == UX_NULL);
}
static void post_init_device()
{
}

View File

@ -0,0 +1,57 @@
/* This tests the case where the interrupt notification semaphore creation fails. */
#include "usbx_ux_test_cdc_ecm.h"
static DEVICE_INIT_DATA device_init_data = {
.framework = default_device_framework,
.framework_length = sizeof(default_device_framework),
.dont_register_hcd = 1,
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_host_interrupt_notification_semaphore_create_fail_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Host Interrupt Notification Semaphore Fail Test..... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
int i;
UX_TEST_ACTION semaphore_create_fail_action = {0};
semaphore_create_fail_action.usbx_function = UX_TEST_OVERRIDE_TX_SEMAPHORE_CREATE;
semaphore_create_fail_action.semaphore_name = "host CDC-ECM interrupt notification semaphore";
semaphore_create_fail_action.no_return = 0;
semaphore_create_fail_action.status = UX_ERROR;
for (i = 0; i < UX_RH_ENUMERATION_RETRY; i++)
{
ux_test_add_action_to_main_list(semaphore_create_fail_action);
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_UTILITY, UX_ERROR));
}
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE));
/* Enumerate. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
/* The HCD init function put()s the HCD semaphore, so we can do this here. */
ux_test_wait_for_enum_thread_completion();
UX_TEST_ASSERT(ux_test_check_actions_empty());
UX_TEST_ASSERT(cdc_ecm_host_from_system_change_function == UX_NULL);
}
static void post_init_device()
{
}

View File

@ -0,0 +1,63 @@
/* This tests the case where the host receives a non-IP packet. */
#include "usbx_ux_test_cdc_ecm.h"
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_host_non_ip_packet_received_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Host Non IP Packet Received Test.................... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize(first_unused_memory);
}
static void post_init_host()
{
NX_PACKET *out_packet;
/* Note that the packets we send to the host will just get released by NetX
for being invalid. */
/** Test '*(packet -> nx_packet_prepend_ptr + 12) != 0x08' **/
UX_TEST_CHECK_SUCCESS(nx_packet_allocate(&packet_pool_device, &out_packet, NX_UDP_PACKET, NX_WAIT_FOREVER));
out_packet->nx_packet_length = (ULONG)(out_packet->nx_packet_data_end - out_packet->nx_packet_prepend_ptr);
memset(out_packet->nx_packet_prepend_ptr, 'a', out_packet->nx_packet_length);
out_packet->nx_packet_prepend_ptr[12] = 0x00;
/* Now send the packet. */
_ux_device_class_cdc_ecm_write(cdc_ecm_device, out_packet);
/* Wait for host to receive it. */
tx_thread_sleep(500);
/** Test '*(packet -> nx_packet_prepend_ptr + 13) != 0' **/
UX_TEST_CHECK_SUCCESS(nx_packet_allocate(&packet_pool_device, &out_packet, NX_UDP_PACKET, NX_WAIT_FOREVER));
out_packet->nx_packet_length = (ULONG)(out_packet->nx_packet_data_end - out_packet->nx_packet_prepend_ptr);
memset(out_packet->nx_packet_prepend_ptr, 'a', out_packet->nx_packet_length);
out_packet->nx_packet_prepend_ptr[12] = 0x08;
out_packet->nx_packet_prepend_ptr[13] = 0x01;
/* Now send the packet. */
_ux_device_class_cdc_ecm_write(cdc_ecm_device, out_packet);
/* Wait for host to receive it. */
tx_thread_sleep(500);
/* We're done!? */
}
static void post_init_device()
{
}

View File

@ -0,0 +1,72 @@
/* This tests the case where the CDC-ECM thread creation fails. */
#include "usbx_ux_test_cdc_ecm.h"
static DEVICE_INIT_DATA device_init_data = {
.framework = default_device_framework,
.framework_length = sizeof(default_device_framework),
.dont_register_hcd = 1,
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_host_packet_pool_create_fail_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Host Packet Pool Create Test........................ ");
printf("Deprecated\n");
test_control_return(0);
return;
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
int i;
/* Enumerate first so we can initialize memory test. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
/* The HCD init function put()s the HCD semaphore, so we can do this here. */
ux_test_wait_for_enum_thread_completion();
/* We want at least one memory test. */
ux_test_memory_test_initialize();
/* Disconnect so we can setup test. */
ux_test_disconnect_host_wait_for_enum_completion();
UX_TEST_ACTION packet_pool_create_fail_action = {0};
packet_pool_create_fail_action.usbx_function = UX_TEST_OVERRIDE_NX_PACKET_POOL_CREATE;
packet_pool_create_fail_action.name_ptr = "host CDC-ECM packet pool";
packet_pool_create_fail_action.no_return = 0;
packet_pool_create_fail_action.status = UX_ERROR;
for (i = 0; i < UX_RH_ENUMERATION_RETRY; i++)
{
ux_test_add_action_to_main_list(packet_pool_create_fail_action);
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_ERROR));
}
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE));
/* Start enumeration. */
ux_test_connect_slave_and_host_wait_for_enum_completion();
/* Disconnect. Note that this also does the memory check. */
ux_test_disconnect_slave_and_host_wait_for_enum_completion();
UX_TEST_ASSERT(ux_test_check_actions_empty());
UX_TEST_ASSERT(cdc_ecm_host_from_system_change_function == UX_NULL);
}
static void post_init_device()
{
}

View File

@ -0,0 +1,57 @@
/* This tests the case where the CDC-ECM thread creation fails. */
#include "usbx_ux_test_cdc_ecm.h"
static DEVICE_INIT_DATA device_init_data = {
.framework = default_device_framework,
.framework_length = sizeof(default_device_framework),
.dont_register_hcd = 1,
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_host_thread_create_fail_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Host Thread Fail Test............................... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
int i;
UX_TEST_ACTION thread_create_fail_action = {0};
thread_create_fail_action.usbx_function = UX_TEST_OVERRIDE_TX_THREAD_CREATE;
thread_create_fail_action.name_ptr = "ux_host_cdc_ecm_thread";
thread_create_fail_action.no_return = 0;
thread_create_fail_action.status = UX_ERROR;
for (i = 0; i < UX_RH_ENUMERATION_RETRY; i++)
{
ux_test_add_action_to_main_list(thread_create_fail_action);
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_UTILITY, UX_ERROR));
}
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE));
/* Enumerate. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
/* The HCD init function put()s the HCD semaphore, so we can do this here. */
ux_test_wait_for_enum_thread_completion();
UX_TEST_ASSERT(ux_test_check_actions_empty());
UX_TEST_ASSERT(cdc_ecm_host_from_system_change_function == UX_NULL);
}
static void post_init_device()
{
}

View File

@ -0,0 +1,72 @@
/* This tests the case where right before the transfer is armed, the link state
is down in the cdc-ecm thread. */
#include "usbx_ux_test_cdc_ecm.h"
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_host_thread_link_down_before_transfer_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Host Thread Link Down Before Transfer Test.......... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize(first_unused_memory);
}
static UCHAR is_cdc_ecm_thread_suspended;
static VOID suspend_cdc_ecm_thread_action_func(UX_TEST_ACTION *action, VOID *params)
{
is_cdc_ecm_thread_suspended = 1;
/* We're being called by nx_packet_allocate in cdc-ecm thread. Wait for test
thread to resume us. */
tx_thread_suspend(tx_thread_identify());
}
static void post_init_host()
{
/* Currently, the cdc-ecm thread should be waiting for a transfer to complete.
We need to create an action for having the cdc-ecm thread suspend during
the packet allocate, then do a write from the device so the cdc-ecm thread
call the packet allocate, then set the link to down, then resume the thread. */
/* Create the action for having cdc-ecm thread suspend on packet allocate. */
UX_TEST_ACTION packet_allocate_suspend_action = {0};
packet_allocate_suspend_action.usbx_function = UX_TEST_OVERRIDE_NX_PACKET_ALLOCATE;
packet_allocate_suspend_action.name_ptr = ip_pool_host_name;
packet_allocate_suspend_action.action_func = suspend_cdc_ecm_thread_action_func;
ux_test_add_action_to_main_list(packet_allocate_suspend_action);
/* Write to the host so the cdc-ecm thread will redo the nx_packet_allocate. */
write_packet_udp(&udp_socket_device, &packet_pool_device, HOST_IP_ADDRESS, HOST_SOCKET_PORT_UDP, 0, "device");
/* Now wait for the cdc-ecm thread to suspend. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&is_cdc_ecm_thread_suspended, 1));
/* Now set the link state to down. */
ux_test_device_class_cdc_ecm_set_link_state(cdc_ecm_device, 0);
/* Now wait for the link to be set to pending down (it won't be down since thread is suspended). */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&cdc_ecm_host->ux_host_class_cdc_ecm_link_state, UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_DOWN));
/* Now resume the cdc-ecm thread. */
tx_thread_resume(&cdc_ecm_host->ux_host_class_cdc_ecm_thread);
/* Now wait for link to be down. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&cdc_ecm_host->ux_host_class_cdc_ecm_link_state, UX_HOST_CLASS_CDC_ECM_LINK_STATE_DOWN));
/* Now we're done. */
}
static void post_init_device()
{
}

View File

@ -0,0 +1,59 @@
/* This tests the case the nx_packet_allocate fails in the cdc-ecm thread. */
#include "usbx_ux_test_cdc_ecm.h"
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_host_thread_packet_allocate_fail_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Host Thread Packet Allocate Fail Test............... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize(first_unused_memory);
}
static void post_init_host()
{
int i;
int device_num_writes = 0;
int host_num_reads = 0;
/* Have the device send the max number of packets to the host. */
for (i = 0; i < UX_HOST_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES; i++)
{
write_packet_udp(&udp_socket_device, &packet_pool_device, HOST_IP_ADDRESS, HOST_SOCKET_PORT_UDP, device_num_writes++, "device");
}
/* Time to setup our action since we expect an error. */
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT));
/* Now send the one that should make the call overflow. */
write_packet_udp(&udp_socket_device, &packet_pool_device, HOST_IP_ADDRESS, HOST_SOCKET_PORT_UDP, device_num_writes++, "device");
/* Now wait for error to occur. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_empty_actions());
/* Let's be good sports and make sure everything else works. */
for (i = 0; i < UX_HOST_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES + 1; i++)
{
read_packet_udp(&udp_socket_host, host_num_reads++, "host");
}
/* Send one more. */
write_packet_udp(&udp_socket_device, &packet_pool_device, HOST_IP_ADDRESS, HOST_SOCKET_PORT_UDP, device_num_writes++, "device");
/* Read one more. */
read_packet_udp(&udp_socket_host, host_num_reads++, "host");
}
static void post_init_device()
{
}

View File

@ -0,0 +1,61 @@
/* This tests the case the nx_packet_allocate fails in the cdc-ecm thread. */
#define TEST_NX_PACKET_CHAIN
#include "usbx_ux_test_cdc_ecm.h"
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_host_thread_packet_allocate_fail_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Host Thread Packet Append Fail Test................. ");
stepinfo("\n");
#if (UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1) && defined(UX_DEVICE_CLASS_CDC_ECM_ZERO_COPY)
printf("Skipped\n");
return;
#endif
ux_test_cdc_ecm_initialize(first_unused_memory);
}
static void post_init_host()
{
ULONG n_available;
int i;
int device_num_writes = 0;
int host_num_reads = 0;
/* Have the device send the max number of packets to the host. */
ux_utility_delay_ms(1000);
n_available = cdc_ecm_host->ux_host_class_cdc_ecm_packet_pool->nx_packet_pool_available;
for (i = 0; i < n_available; i++)
write_udp(&udp_socket_device, &packet_pool_device, HOST_IP_ADDRESS, HOST_SOCKET_PORT_UDP, device_num_writes++, "device", 4);
ux_utility_delay_ms(1000);
/* Time to setup our action since we expect an error. */
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_ETH_PACKET_ERROR));
/* Now send the one that should make the append error (discarded). */
write_packet_udp(&udp_socket_device, &packet_pool_device, HOST_IP_ADDRESS, HOST_SOCKET_PORT_UDP, device_num_writes, "device");
/* Now wait for error to occur. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_empty_actions());
/* Let's be good sports and make sure everything else works. */
for (i = 0; i < n_available; i++)
read_packet_udp(&udp_socket_host, host_num_reads++, "host");
/* Send one more. */
write_packet_udp(&udp_socket_device, &packet_pool_device, HOST_IP_ADDRESS, HOST_SOCKET_PORT_UDP, device_num_writes++, "device");
/* Read one more. */
read_packet_udp(&udp_socket_host, host_num_reads++, "host");
}
static void post_init_device()
{
}

View File

@ -0,0 +1,189 @@
/* This test tests the case where there is an interface before the control interface. In this case, it's a storage class interface.
We do this because during activation, we need to link the the control interface into the class instance, so we need to find it. */
#include "usbx_ux_test_cdc_ecm.h"
static unsigned char interface_before_control_interface_framework[] = {
/* Device Descriptor */
0x12, /* bLength */
0x01, /* bDescriptorType */
0x10, 0x01, /* bcdUSB */
0xef, /* bDeviceClass - Depends on bDeviceSubClass */
0x02, /* bDeviceSubClass - Depends on bDeviceProtocol */
0x01, /* bDeviceProtocol - There's an IAD */
0x40, /* bMaxPacketSize0 */
0x70, 0x07, /* idVendor */
0x42, 0x10, /* idProduct */
0x00, 0x01, /* bcdDevice */
0x01, /* iManufacturer */
0x02, /* iProduct */
0x03, /* iSerialNumber */
0x01, /* bNumConfigurations */
/* Configuration Descriptor */
0x09, /* bLength */
0x02, /* bDescriptorType */
0x76, 0x00, /* wTotalLength */
0x02, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
0xc0, /* bmAttributes - Self-powered */
0x00, /* bMaxPower */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x03, /* bNumEndpoints */
0x08, /* bInterfaceClass - Mass Storage */
0x06, /* bInterfaceSubClass */
0x50, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x81, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x02, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x83, /* bEndpointAddress */
0x03, /* bmAttributes - Interrupt */
0x40, 0x00, /* wMaxPacketSize */
0x01, /* bInterval */
/* Interface Association Descriptor */
0x08, /* bLength */
0x0b, /* bDescriptorType */
0x00, /* bFirstInterface */
0x02, /* bInterfaceCount */
0x02, /* bFunctionClass - CDC - Communication */
0x06, /* bFunctionSubClass - ECM */
0x00, /* bFunctionProtocol - No class specific protocol required */
0x00, /* iFunction */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndpoints */
0x02, /* bInterfaceClass - CDC - Communication */
0x06, /* bInterfaceSubClass - ECM */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* CDC Header Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x00, /* bDescriptorSubType */
0x10, 0x01, /* bcdCDC */
/* CDC ECM Functional Descriptor */
0x0d, /* bLength */
0x24, /* bDescriptorType */
0x0f, /* bDescriptorSubType */
0x04, /* iMACAddress */
0x00, 0x00, 0x00, 0x00, /* bmEthernetStatistics */
0xea, 0x05, /* wMaxSegmentSize */
0x00, 0x00, /* wNumberMCFilters */
0x00, /* bNumberPowerFilters */
/* CDC Union Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x06, /* bDescriptorSubType */
0x00, /* bmMasterInterface */
0x01, /* bmSlaveInterface0 */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x84, /* bEndpointAddress */
0x03, /* bmAttributes - Interrupt */
0x08, 0x00, /* wMaxPacketSize */
0x08, /* bInterval */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x01, /* bAlternateSetting */
0x02, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x05, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x86, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
};
static DEVICE_INIT_DATA device_init_data = { interface_before_control_interface_framework, sizeof(interface_before_control_interface_framework) };
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_interface_before_control_interface_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running cdc_ecm interface before control interface Test............. ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
cdc_ecm_basic_test(BASIC_TEST_HOST, BASIC_TEST_TCP);
}
static void post_init_device()
{
cdc_ecm_basic_test(BASIC_TEST_DEVICE, BASIC_TEST_TCP);
}

View File

@ -0,0 +1,170 @@
/* This tests the case where the default data interface has zero endpoints, and
the interface right after is also a data interface but contains an invalid
alternate setting value. Host should report error. */
#include "usbx_ux_test_cdc_ecm.h"
static unsigned char non_data_interface_after_zero_endpoint_data_interface_framework[] = {
/* Device Descriptor */
0x12, /* bLength */
0x01, /* bDescriptorType */
0x10, 0x01, /* bcdUSB */
0xef, /* bDeviceClass - Depends on bDeviceSubClass */
0x02, /* bDeviceSubClass - Depends on bDeviceProtocol */
0x01, /* bDeviceProtocol - There's an IAD */
0x40, /* bMaxPacketSize0 */
0x70, 0x07, /* idVendor */
0x42, 0x10, /* idProduct */
0x00, 0x01, /* bcdDevice */
0x01, /* iManufacturer */
0x02, /* iProduct */
0x03, /* iSerialNumber */
0x01, /* bNumConfigurations */
/* Configuration Descriptor */
0x09, /* bLength */
0x02, /* bDescriptorType */
0x58, 0x00, /* wTotalLength */
0x02, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
0xc0, /* bmAttributes - Self-powered */
0x00, /* bMaxPower */
/* Interface Association Descriptor */
0x08, /* bLength */
0x0b, /* bDescriptorType */
0x00, /* bFirstInterface */
0x02, /* bInterfaceCount */
0x02, /* bFunctionClass - CDC - Communication */
0x06, /* bFunctionSubClass - ECM */
0x00, /* bFunctionProtocol - No class specific protocol required */
0x00, /* iFunction */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndpoints */
0x02, /* bInterfaceClass - CDC - Communication */
0x06, /* bInterfaceSubClass - ECM */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* CDC Header Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x00, /* bDescriptorSubType */
0x10, 0x01, /* bcdCDC */
/* CDC ECM Functional Descriptor */
0x0d, /* bLength */
0x24, /* bDescriptorType */
0x0f, /* bDescriptorSubType */
0x04, /* iMACAddress */
0x00, 0x00, 0x00, 0x00, /* bmEthernetStatistics */
0xea, 0x05, /* wMaxSegmentSize */
0x00, 0x00, /* wNumberMCFilters */
0x00, /* bNumberPowerFilters */
/* CDC Union Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x06, /* bDescriptorSubType */
0x00, /* bmMasterInterface */
0x01, /* bmSlaveInterface0 */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x83, /* bEndpointAddress */
0x03, /* bmAttributes - Interrupt */
0x08, 0x00, /* wMaxPacketSize */
0x08, /* bInterval */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
/* Invalid alternate setting. */
0xff, /* bAlternateSetting */
0x02, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x02, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x81, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
};
static DEVICE_INIT_DATA device_init_data = {
.framework = non_data_interface_after_zero_endpoint_data_interface_framework,
.framework_length = sizeof(non_data_interface_after_zero_endpoint_data_interface_framework),
.dont_register_hcd = 1,
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_invalid_alternate_setting_after_zero_endpoint_data_interface_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Invalid Alternate Setting After... Test............. ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
/* We expect this to fail multiple times since enumeration tries multiple times. */
ux_test_add_action_to_main_list_multiple(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED), 3);
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE));
/* Enumerate. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
/* The HCD init function put()s the HCD semaphore, so we can do this here. */
ux_test_wait_for_enum_thread_completion();
/* Enumeration should've failed. */
UX_TEST_ASSERT(ux_test_check_actions_empty());
UX_TEST_ASSERT(cdc_ecm_host_from_system_change_function == UX_NULL);
}
static void post_init_device()
{
}

View File

@ -0,0 +1,199 @@
/* This test the case where a LINK DOWN event is received while transfers are
ongoing. */
#include "usbx_ux_test_cdc_ecm.h"
#include "ux_device_stack.h"
static ULONG global_basic_test_num_writes_host;
static ULONG global_basic_test_num_reads_host;
static ULONG global_basic_test_num_writes_device;
static ULONG global_basic_test_num_reads_device;
static UCHAR host_waiting_for_link_down;
static UCHAR host_waiting_for_link_up;
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_link_down_while_ongoing_transfers_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Host Link Down While Ongoing Transfers Test......... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize(first_unused_memory);
}
static void basic_test_host()
{
UINT num_iters;
UINT i;
/*** Basic test - no transfers going on. ***/
stepinfo("Basic test - no transfers going on.\n");
/* Now wait for the link to be down. */
host_waiting_for_link_down = 1;
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&cdc_ecm_host->ux_host_class_cdc_ecm_link_state, UX_HOST_CLASS_CDC_ECM_LINK_STATE_DOWN));
/* Wait for everything to get cleaned up. */
tx_thread_sleep(MS_TO_TICK(1000));
/* Now wait for the link to be up. */
host_waiting_for_link_up = 1;
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&cdc_ecm_host->ux_host_class_cdc_ecm_link_state, UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP));
/* Run that basic test again. */
for (num_iters = 0; num_iters < 10; num_iters++)
{
for (i = 0; i < 10; i++)
write_packet_udp(&udp_socket_host, &packet_pool_host, DEVICE_IP_ADDRESS, DEVICE_SOCKET_PORT_UDP, global_basic_test_num_writes_host++, "host");
for (i = 0; i < 10; i++)
read_packet_udp(&udp_socket_host, global_basic_test_num_reads_host++, "host");
}
/* Wait for all transfers to complete. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&global_basic_test_num_reads_host, 100));
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&global_basic_test_num_reads_device, 100));
}
static void basic_test_device()
{
UINT num_iters;
UINT i;
/*** Basic test. ***/
/* Wait for host to wait for link down. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&host_waiting_for_link_down, 1));
host_waiting_for_link_down = 0;
/* Now set the link to down. */
ux_test_device_class_cdc_ecm_set_link_state(cdc_ecm_device, UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_DOWN);
/* Wait for host to wait for link up. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&host_waiting_for_link_up, 1));
host_waiting_for_link_up = 0;
/* Now set the link to up. */
ux_test_device_class_cdc_ecm_set_link_state(cdc_ecm_device, UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP);
/* Now do basic test. */
for (num_iters = 0; num_iters < 10; num_iters++)
{
for (i = 0; i < 10; i++)
write_packet_udp(&udp_socket_device, &packet_pool_device, HOST_IP_ADDRESS, HOST_SOCKET_PORT_UDP, global_basic_test_num_writes_device++, "device");
for (i = 0; i < 10; i++)
read_packet_udp(&udp_socket_device, global_basic_test_num_reads_device++, "device");
}
/* Wait for all transfers to complete. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&global_basic_test_num_reads_host, 100));
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&global_basic_test_num_reads_device, 100));
}
#define NUM_WRITES 500
#define NUM_WRITES_BEFORE_LINK_DOWN 10
#define MAX_WRITE_WHILE_LINK_DOWN (NUM_WRITES - NUM_WRITES_BEFORE_LINK_DOWN)
static void ongoing_writes_test_host()
{
UINT i;
UINT pre_write_fail_num_packet_pool_packets_available;
UINT num_writes = 0;
/*** Link down when there are queued writes, and we try to add writes. ***/
stepinfo("Ongoing writes test.\n");
pre_write_fail_num_packet_pool_packets_available = packet_pool_host.nx_packet_pool_available;
/* We expect some errors. */
UX_TEST_ACTION error_match_action = create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_CDC_ECM_LINK_STATE_DOWN_ERROR);
ux_test_add_action_to_main_list_multiple(error_match_action, MAX_WRITE_WHILE_LINK_DOWN);
/* Queue up some writes - device isn't going to read them, so they stay queued. */
for (i = 0; i < NUM_WRITES; i++)
{
/* Write packet. */
write_packet_udp(&udp_socket_host, &packet_pool_host, DEVICE_IP_ADDRESS, DEVICE_SOCKET_PORT_UDP, num_writes++, "host");
/* Have we queued 10 packets? */
if (i == NUM_WRITES_BEFORE_LINK_DOWN)
{
/* Set the link to down. The _hope_ here is to have the CDC-ECM thread
process the link down while we're still writing packets. This
should be improved in the future. I don't want to be the poor
SOB that has to do it!
We cheat here by calling a device API from the host. */
ux_test_device_class_cdc_ecm_set_link_state(cdc_ecm_device, UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_DOWN);
while (cdc_ecm_host->ux_host_class_cdc_ecm_link_state != UX_HOST_CLASS_CDC_ECM_LINK_STATE_DOWN)
tx_thread_sleep(10);
}
}
/* Make sure everything is ok. */
UX_TEST_ASSERT(cdc_ecm_host->ux_host_class_cdc_ecm_link_state == UX_HOST_CLASS_CDC_ECM_LINK_STATE_DOWN);
NX_PACKET_POOL *packet_pool_host_local = &packet_pool_host;
UX_HOST_CLASS_CDC_ECM *cdc_ecm_host_local = cdc_ecm_host;
UX_TEST_ASSERT(packet_pool_host.nx_packet_pool_available == pre_write_fail_num_packet_pool_packets_available);
/* Make sure at least one error was reported. */
UX_TEST_ASSERT(ux_test_get_num_actions_left() != 90);
/* Now clear the error match actions out. */
ux_test_clear_main_list_actions();
/* Run that basic test again. */
/* Now wait for the link to be up. */
host_waiting_for_link_up = 1;
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&cdc_ecm_host->ux_host_class_cdc_ecm_link_state, UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP));
cdc_ecm_basic_test(BASIC_TEST_HOST, BASIC_TEST_TCP);
}
static void ongoing_writes_test_device()
{
/*** Ongoing writes test. ***/
/* The host is gonna do all the work. At some point, he'll want the link back
up to run the basic test again. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&host_waiting_for_link_up, 1));
/* Set link to up. */
ux_test_device_class_cdc_ecm_set_link_state(cdc_ecm_device, UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP);
/* Now do basic test. */
cdc_ecm_basic_test(BASIC_TEST_DEVICE, BASIC_TEST_TCP);
}
static void post_init_host()
{
//basic_test_host();
ongoing_writes_test_host();
}
static void post_init_device(ULONG input)
{
//basic_test_device();
ongoing_writes_test_device();
}

View File

@ -0,0 +1,81 @@
/* This tests the case where the mac address string is too long. This is an
error. */
#include "usbx_ux_test_cdc_ecm.h"
static unsigned char invalid_mac_address_string_length[] = {
/* Manufacturer string descriptor : Index 1 - "Express Logic" */
0x09, 0x04, 0x01, 0x0c,
0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x20, 0x4c,
0x6f, 0x67, 0x69, 0x63,
/* Product string descriptor : Index 2 - "EL CDCECM Device" */
0x09, 0x04, 0x02, 0x10,
0x45, 0x4c, 0x20, 0x43, 0x44, 0x43, 0x45, 0x43,
0x4d, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
/* Serial Number string descriptor : Index 3 - "0001" */
0x09, 0x04, 0x03, 0x04,
0x30, 0x30, 0x30, 0x31,
/* MAC Address string descriptor : Index 4 - "001E5841B878" */
0x09, 0x04, 0x04,
0x1b, /* This byte is the length of the string. It just needs to be greater than 26 (look in mac_address_get.c). */
0x30, 0x30, 0x31, 0x45, 0x35, 0x38,
0x34, 0x31, 0x42, 0x38, 0x37, 0x38,
0x30, 0x30, 0x31, 0x45, 0x35, 0x38,
0x34, 0x31, 0x42, 0x38, 0x37, 0x38,
0x37, 0x38, 0x37,
};
static DEVICE_INIT_DATA device_init_data = {
.string_framework = invalid_mac_address_string_length,
.string_framework_length = sizeof(invalid_mac_address_string_length),
.dont_register_hcd = 1,
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_mac_address_invalid_length_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Mac Address Invalid Length Test..................... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
int i;
/* We expect this to fail multiple times since enumeration tries multiple times. */
for (i = 0; i < UX_RH_ENUMERATION_RETRY; i++)
{
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED));
}
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE));
/* Enumerate. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
/* The HCD init function put()s the HCD semaphore, so we can do this here. */
ux_test_wait_for_enum_thread_completion();
/* Enumeration should've failed. */
UX_TEST_ASSERT(ux_test_check_actions_empty());
UX_TEST_ASSERT(cdc_ecm_host_from_system_change_function == UX_NULL);
}
static void post_init_device()
{
}

View File

@ -0,0 +1,78 @@
/* This tests general cases in the mac address string like hexadecimal values. */
#include "usbx_ux_test_cdc_ecm.h"
static unsigned char mac_address_test_string_framework[] = {
/* Manufacturer string descriptor : Index 1 - "Express Logic" */
0x09, 0x04, 0x01, 0x0c,
0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x20, 0x4c,
0x6f, 0x67, 0x69, 0x63,
/* Product string descriptor : Index 2 - "EL CDCECM Device" */
0x09, 0x04, 0x02, 0x10,
0x45, 0x4c, 0x20, 0x43, 0x44, 0x43, 0x45, 0x43,
0x4d, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
/* Serial Number string descriptor : Index 3 - "0001" */
0x09, 0x04, 0x03, 0x04,
0x30, 0x30, 0x30, 0x31,
/* MAC Address string descriptor : Index 4 - "001E5841B878" */
0x09, 0x04, 0x04, 0x0C,
'A', 'A', /* Test capital upper and lower element. */
'0', '1',
'2', '3',
'4', 'b',
'c', 'D',
'e', 'f',
};
static DEVICE_INIT_DATA device_init_data = {
.string_framework = mac_address_test_string_framework,
.string_framework_length = sizeof(mac_address_test_string_framework),
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_mac_address_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Mac Address Test.................................... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
/* Ensure the mac address is correct. */
UX_TEST_ASSERT(cdc_ecm_host->ux_host_class_cdc_ecm_node_id[0] == 0xaa);
UX_TEST_ASSERT(cdc_ecm_host->ux_host_class_cdc_ecm_node_id[1] == 0x01);
UX_TEST_ASSERT(cdc_ecm_host->ux_host_class_cdc_ecm_node_id[2] == 0x23);
UX_TEST_ASSERT(cdc_ecm_host->ux_host_class_cdc_ecm_node_id[3] == 0x4b);
UX_TEST_ASSERT(cdc_ecm_host->ux_host_class_cdc_ecm_node_id[4] == 0xcd);
UX_TEST_ASSERT(cdc_ecm_host->ux_host_class_cdc_ecm_node_id[5] == 0xef);
/* Configuration descriptor invalid while parsing MAC address */
/* descriptor_length < 3 */
default_device_framework[18] = 0;
UX_TEST_ASSERT(UX_DESCRIPTOR_CORRUPTED == _ux_host_class_cdc_ecm_mac_address_get(cdc_ecm_host));
/* descriptor_length > total_configuration_length */
default_device_framework[18] = 0xFF;
UX_TEST_ASSERT(UX_DESCRIPTOR_CORRUPTED == _ux_host_class_cdc_ecm_mac_address_get(cdc_ecm_host));
/* Restore. */
default_device_framework[18] = 9;
UX_TEST_ASSERT(UX_SUCCESS == _ux_host_class_cdc_ecm_mac_address_get(cdc_ecm_host));
}
static void post_init_device()
{
}

View File

@ -0,0 +1,111 @@
/* This test tests the case where there is no control interface. */
#include "usbx_ux_test_cdc_ecm.h"
static unsigned char no_control_interface_framework[] = {
/* Device Descriptor */
0x12, /* bLength */
0x01, /* bDescriptorType */
0x10, 0x01, /* bcdUSB */
0xef, /* bDeviceClass - Depends on bDeviceSubClass */
0x02, /* bDeviceSubClass - Depends on bDeviceProtocol */
0x01, /* bDeviceProtocol - There's an IAD */
0x40, /* bMaxPacketSize0 */
0x70, 0x07, /* idVendor */
0x42, 0x10, /* idProduct */
0x00, 0x01, /* bcdDevice */
0x01, /* iManufacturer */
0x02, /* iProduct */
0x03, /* iSerialNumber */
0x01, /* bNumConfigurations */
/* Configuration Descriptor */
0x09, /* bLength */
0x02, /* bDescriptorType */
0x29, 0x00, /* wTotalLength */
0x02, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
0xc0, /* bmAttributes - Self-powered */
0x00, /* bMaxPower */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x01, /* bAlternateSetting */
0x02, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x05, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x86, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
};
static DEVICE_INIT_DATA device_init_data = { no_control_interface_framework, sizeof(no_control_interface_framework), .dont_register_hcd = 1 };
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_no_control_interface_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM No Control Interface Test........................... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
/* We expect this to fail multiple times since enumeration tries multiple times. */
ux_test_add_action_to_main_list_multiple(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED), 3);
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE));
/* Begin enumeration. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
/* The HCD init function put()s the HCD semaphore, so we can do this here. */
ux_test_wait_for_enum_thread_completion();
/* Enumeration should've failed. */
UX_TEST_ASSERT(ux_test_check_actions_empty());
UX_TEST_ASSERT(cdc_ecm_host_from_system_change_function == UX_NULL);
}
static void post_init_device()
{
}

View File

@ -0,0 +1,164 @@
/* This tests the case where there no functional descriptor. There should be a
functional descriptor, so this is an error. */
#include "usbx_ux_test_cdc_ecm.h"
static unsigned char no_function_descriptor_framework[] = {
/* Device Descriptor */
0x12, /* bLength */
0x01, /* bDescriptorType */
0x10, 0x01, /* bcdUSB */
0xef, /* bDeviceClass - Depends on bDeviceSubClass */
0x02, /* bDeviceSubClass - Depends on bDeviceProtocol */
0x01, /* bDeviceProtocol - There's an IAD */
0x40, /* bMaxPacketSize0 */
0x70, 0x07, /* idVendor */
0x42, 0x10, /* idProduct */
0x00, 0x01, /* bcdDevice */
0x01, /* iManufacturer */
0x02, /* iProduct */
0x03, /* iSerialNumber */
0x01, /* bNumConfigurations */
/* Configuration Descriptor */
0x09, /* bLength */
0x02, /* bDescriptorType */
0x4b, 0x00, /* wTotalLength */
0x02, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
0xc0, /* bmAttributes - Self-powered */
0x00, /* bMaxPower */
/* Interface Association Descriptor */
0x08, /* bLength */
0x0b, /* bDescriptorType */
0x00, /* bFirstInterface */
0x02, /* bInterfaceCount */
0x02, /* bFunctionClass - CDC - Communication */
0x06, /* bFunctionSubClass - ECM */
0x00, /* bFunctionProtocol - No class specific protocol required */
0x00, /* iFunction */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndpoints */
0x02, /* bInterfaceClass - CDC - Communication */
0x06, /* bInterfaceSubClass - ECM */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* CDC Header Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x00, /* bDescriptorSubType */
0x10, 0x01, /* bcdCDC */
/* CDC Union Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x06, /* bDescriptorSubType */
0x00, /* bmMasterInterface */
0x01, /* bmSlaveInterface0 */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x83, /* bEndpointAddress */
0x03, /* bmAttributes - Interrupt */
0x08, 0x00, /* wMaxPacketSize */
0x08, /* bInterval */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x01, /* bAlternateSetting */
0x02, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x02, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x81, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
};
static DEVICE_INIT_DATA device_init_data = {
.framework = no_function_descriptor_framework,
.framework_length = sizeof(no_function_descriptor_framework),
.dont_register_hcd = 1,
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_no_functional_descriptor_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM No Functional Descriptor Test....................... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
int i;
/* We expect this to fail multiple times since enumeration tries multiple times. */
for (i = 0; i < UX_RH_ENUMERATION_RETRY; i++)
{
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED));
}
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE));
/* Enumerate. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
/* The HCD init function put()s the HCD semaphore, so we can do this here. */
ux_test_wait_for_enum_thread_completion();
/* Enumeration should've failed. */
UX_TEST_ASSERT(ux_test_check_actions_empty());
UX_TEST_ASSERT(cdc_ecm_host_from_system_change_function == UX_NULL);
}
static void post_init_device()
{
}

View File

@ -0,0 +1,176 @@
/* This tests the case where the default data interface has zero endpoints, and
the interface right after it is a non-data interface. Host should report error. */
#include "usbx_ux_test_cdc_ecm.h"
static unsigned char non_data_interface_after_zero_endpoint_data_interface_framework[] = {
/* Device Descriptor */
0x12, /* bLength */
0x01, /* bDescriptorType */
0x10, 0x01, /* bcdUSB */
0xef, /* bDeviceClass - Depends on bDeviceSubClass */
0x02, /* bDeviceSubClass - Depends on bDeviceProtocol */
0x01, /* bDeviceProtocol - There's an IAD */
0x40, /* bMaxPacketSize0 */
0x70, 0x07, /* idVendor */
0x42, 0x10, /* idProduct */
0x00, 0x01, /* bcdDevice */
0x01, /* iManufacturer */
0x02, /* iProduct */
0x03, /* iSerialNumber */
0x01, /* bNumConfigurations */
/* Configuration Descriptor */
0x09, /* bLength */
0x02, /* bDescriptorType */
0x5f, 0x00, /* wTotalLength */
0x02, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
0xc0, /* bmAttributes - Self-powered */
0x00, /* bMaxPower */
/* Interface Association Descriptor */
0x08, /* bLength */
0x0b, /* bDescriptorType */
0x00, /* bFirstInterface */
0x02, /* bInterfaceCount */
0x02, /* bFunctionClass - CDC - Communication */
0x06, /* bFunctionSubClass - ECM */
0x00, /* bFunctionProtocol - No class specific protocol required */
0x00, /* iFunction */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndpoints */
0x02, /* bInterfaceClass - CDC - Communication */
0x06, /* bInterfaceSubClass - ECM */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* CDC Header Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x00, /* bDescriptorSubType */
0x10, 0x01, /* bcdCDC */
/* CDC ECM Functional Descriptor */
0x0d, /* bLength */
0x24, /* bDescriptorType */
0x0f, /* bDescriptorSubType */
0x04, /* iMACAddress */
0x00, 0x00, 0x00, 0x00, /* bmEthernetStatistics */
0xea, 0x05, /* wMaxSegmentSize */
0x00, 0x00, /* wNumberMCFilters */
0x00, /* bNumberPowerFilters */
/* CDC Union Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x06, /* bDescriptorSubType */
0x00, /* bmMasterInterface */
0x01, /* bmSlaveInterface0 */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x83, /* bEndpointAddress */
0x03, /* bmAttributes - Interrupt */
0x08, 0x00, /* wMaxPacketSize */
0x08, /* bInterval */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x03, /* bNumEndpoints */
0x08, /* bInterfaceClass - Mass Storage */
0x06, /* bInterfaceSubClass */
0x50, /* bInterfaceProtocol */
0x00, /* iInterface */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x81, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x02, /* bEndpointAddress */
0x02, /* bmAttributes - Bulk */
0x40, 0x00, /* wMaxPacketSize */
0x00, /* bInterval */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x84, /* bEndpointAddress */
0x03, /* bmAttributes - Interrupt */
0x40, 0x00, /* wMaxPacketSize */
0x01, /* bInterval */
};
static DEVICE_INIT_DATA device_init_data = {
.framework = non_data_interface_after_zero_endpoint_data_interface_framework,
.framework_length = sizeof(non_data_interface_after_zero_endpoint_data_interface_framework),
.dont_register_hcd = 1,
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_non_data_interface_after_zero_endpoint_data_interface_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM Non-Data Interface After Zero... Test............... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
/* We expect this to fail multiple times since enumeration tries multiple times. */
ux_test_add_action_to_main_list_multiple(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED), 3);
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE));
/* Enumerate. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
/* The HCD init function put()s the HCD semaphore, so we can do this here. */
ux_test_wait_for_enum_thread_completion();
/* Enumeration should've failed. */
UX_TEST_ASSERT(ux_test_check_actions_empty());
UX_TEST_ASSERT(cdc_ecm_host_from_system_change_function == UX_NULL);
}
static void post_init_device()
{
}

View File

@ -0,0 +1,77 @@
/* Include necessary system files. */
#define TEST_NX_PACKET_CHAIN
#define BASIC_TEST_NUM_ITERATIONS 5
#define BASIC_TEST_NUM_PACKETS_PER_ITERATION 5
#include "usbx_ux_test_cdc_ecm.h"
static UCHAR device_is_finished;
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_nx_packet_chain_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC ECM NX Packet Chain Test................................ ");
stepinfo("\n");
#if (UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1) && defined(UX_DEVICE_CLASS_CDC_ECM_ZERO_COPY)
printf("Skipped for Zero Copy mode\n");
#else
ux_test_cdc_ecm_initialize(first_unused_memory);
#endif
}
static void post_init_host()
{
UCHAR *temp_buf = UX_NULL;
ULONG n_available;
int i;
int device_num_writes = 0;
/*======== RX buffer allocation fail test. */
if (cdc_ecm_host->ux_host_class_cdc_ecm_receive_buffer)
temp_buf = cdc_ecm_host->ux_host_class_cdc_ecm_receive_buffer;
tx_thread_suspend(&cdc_ecm_host -> ux_host_class_cdc_ecm_thread);
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT));
ux_test_utility_sim_mem_allocate_until_flagged(UX_HOST_CLASS_CDC_ECM_NX_PAYLOAD_SIZE, UX_CACHE_SAFE_MEMORY);
cdc_ecm_host -> ux_host_class_cdc_ecm_receive_buffer = UX_NULL;
tx_thread_resume(&cdc_ecm_host -> ux_host_class_cdc_ecm_thread);
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_empty_actions());
if (temp_buf)
cdc_ecm_host -> ux_host_class_cdc_ecm_receive_buffer = temp_buf;
ux_test_utility_sim_mem_free_all_flagged(UX_CACHE_SAFE_MEMORY);
/* Running UDP test. */
stepinfo("running UDP test.\n");
cdc_ecm_basic_test(BASIC_TEST_HOST, BASIC_TEST_UDP);
/* Wait for device to finish. */
UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&device_is_finished, UX_TRUE));
/* Disconnect. */
ux_test_disconnect_slave_and_host_wait_for_enum_completion();
/* Connect with null system change function. */
_ux_system_host->ux_system_host_change_function = UX_NULL;
/* Connect. */
ux_test_connect_slave_and_host_wait_for_enum_completion();
/* We're done. */
}
static void post_init_device()
{
/* Running UDP test. */
cdc_ecm_basic_test(BASIC_TEST_DEVICE, BASIC_TEST_UDP);
device_is_finished = UX_TRUE;
}

View File

@ -0,0 +1,141 @@
/* This tests the case where there is only one default data interface and it
has no endpoints. Host should report an error. */
#include "usbx_ux_test_cdc_ecm.h"
static unsigned char one_data_interface_with_no_endpoints_framework[] = {
/* Device Descriptor */
0x12, /* bLength */
0x01, /* bDescriptorType */
0x10, 0x01, /* bcdUSB */
0xef, /* bDeviceClass - Depends on bDeviceSubClass */
0x02, /* bDeviceSubClass - Depends on bDeviceProtocol */
0x01, /* bDeviceProtocol - There's an IAD */
0x40, /* bMaxPacketSize0 */
0x70, 0x07, /* idVendor */
0x42, 0x10, /* idProduct */
0x00, 0x01, /* bcdDevice */
0x01, /* iManufacturer */
0x02, /* iProduct */
0x03, /* iSerialNumber */
0x01, /* bNumConfigurations */
/* Configuration Descriptor */
0x09, /* bLength */
0x02, /* bDescriptorType */
0x41, 0x00, /* wTotalLength */
0x02, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
0xc0, /* bmAttributes - Self-powered */
0x00, /* bMaxPower */
/* Interface Association Descriptor */
0x08, /* bLength */
0x0b, /* bDescriptorType */
0x00, /* bFirstInterface */
0x02, /* bInterfaceCount */
0x02, /* bFunctionClass - CDC - Communication */
0x06, /* bFunctionSubClass - ECM */
0x00, /* bFunctionProtocol - No class specific protocol required */
0x00, /* iFunction */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndpoints */
0x02, /* bInterfaceClass - CDC - Communication */
0x06, /* bInterfaceSubClass - ECM */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
/* CDC Header Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x00, /* bDescriptorSubType */
0x10, 0x01, /* bcdCDC */
/* CDC ECM Functional Descriptor */
0x0d, /* bLength */
0x24, /* bDescriptorType */
0x0f, /* bDescriptorSubType */
0x04, /* iMACAddress */
0x00, 0x00, 0x00, 0x00, /* bmEthernetStatistics */
0xea, 0x05, /* wMaxSegmentSize */
0x00, 0x00, /* wNumberMCFilters */
0x00, /* bNumberPowerFilters */
/* CDC Union Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptorType */
0x06, /* bDescriptorSubType */
0x00, /* bmMasterInterface */
0x01, /* bmSlaveInterface0 */
/* Endpoint Descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x83, /* bEndpointAddress */
0x03, /* bmAttributes - Interrupt */
0x08, 0x00, /* wMaxPacketSize */
0x08, /* bInterval */
/* Interface Descriptor */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x00, /* bNumEndpoints */
0x0a, /* bInterfaceClass - CDC - Data */
0x00, /* bInterfaceSubClass - Should be 0x00 */
0x00, /* bInterfaceProtocol - No class specific protocol required */
0x00, /* iInterface */
};
static DEVICE_INIT_DATA device_init_data = {
.framework = one_data_interface_with_no_endpoints_framework,
.framework_length = sizeof(one_data_interface_with_no_endpoints_framework),
.dont_register_hcd = 1,
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_cdc_ecm_one_data_interface_with_no_endpoints_test_application_define(void *first_unused_memory)
#endif
{
/* Inform user. */
printf("Running CDC-ECM One Data Interface With No Endpoints Test........... ");
stepinfo("\n");
ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &device_init_data);
}
static void post_init_host()
{
/* We expect this to fail multiple times since enumeration tries multiple times. */
ux_test_add_action_to_main_list_multiple(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED), 3);
ux_test_add_action_to_main_list(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE));
/* Enumerate. */
UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
/* The HCD init function put()s the HCD semaphore, so we can do this here. */
ux_test_wait_for_enum_thread_completion();
/* Enumeration should've failed. */
UX_TEST_ASSERT(ux_test_check_actions_empty());
UX_TEST_ASSERT(cdc_ecm_host_from_system_change_function == UX_NULL);
}
static void post_init_device()
{
}

View File

@ -0,0 +1,400 @@
/* 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 "ux_host_class_dummy.h"
#include "ux_device_class_dummy.h"
#include "ux_test.h"
/* Define USBX demo constants. */
#define UX_DEMO_STACK_SIZE 4096
#define UX_DEMO_BUFFER_SIZE 2048
#define UX_DEMO_RUN 1
#define UX_DEMO_MEMORY_SIZE (64*1024)
/* Define the counters used in the demo application... */
static ULONG thread_0_counter;
static ULONG thread_1_counter;
static ULONG error_counter;
/* Define USBX demo global variables. */
static UX_HOST_CLASS *class_driver;
static UX_HOST_CLASS_DUMMY *dummy;
static UX_DEVICE_CLASS_DUMMY *dummy_slave;
static UINT expected_error;
#define _W0(w) ( (w) & 0xFF)
#define _W1(w) (((w) >> 8) & 0xFF)
#define _DEVICE_DESCRIPTOR(cls, sub, protocol, pktsize, vid, pid, n_cfg) \
0x12, 0x01, 0x10, 0x01, \
(cls), (sub), (protocol), (pktsize), \
_W0(vid), _W1(vid), _W0(pid), _W1(pid), \
0x00, 0x00, 0x00, 0x00, 0x00, (n_cfg),
#define _QUALIFIER_DESCRIPTOR(cls, sub, protocol, n_cfg) \
0x0a, 0x06, 0x00, 0x02, \
(cls), (sub), (protocol), 0x40, (n_cfg), 0x00,
#define _CONFIGURATION_DESCRIPTOR(total_len, n_ifc, cfg_val) \
0x09, 0x02, _W0(total_len), _W1(total_len), (n_ifc), (cfg_val), \
0x00, 0xc0, 0x32,
#define _INTERFACE_DESCRIPTOR(ifc_n, alt, n_ep, cls, sub, protocol) \
0x09, 0x04, (ifc_n), (alt), (n_ep), (cls), (sub), (protocol), 0x00,
#define _ENDPOINT_DESCRIPTOR(addr, attr, pktsize, interval) \
0x07, 0x05, (addr), (attr), _W0(pktsize), _W1(pktsize), (interval),
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
static UCHAR device_framework_full_speed[] = {
_DEVICE_DESCRIPTOR(0x99, 0x99, 0x99, 8, 0x08EC, 0x0001, 1)
_CONFIGURATION_DESCRIPTOR(32, 1, 1)
_INTERFACE_DESCRIPTOR(0, 0, 2, 0x99, 0x99, 0x99)
_ENDPOINT_DESCRIPTOR(0x01, 0x02, 64, 0x00)
_ENDPOINT_DESCRIPTOR(0x82, 0x02, 64, 0x00)
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
static UCHAR device_framework_high_speed[] = {
_DEVICE_DESCRIPTOR(0x99, 0x99, 0x99, 64, 0x08EC, 0x0001, 1)
_QUALIFIER_DESCRIPTOR(0, 0, 0, 1)
_CONFIGURATION_DESCRIPTOR(32, 1, 1)
_INTERFACE_DESCRIPTOR(0, 0, 2, 0x99, 0x99, 0x99)
_ENDPOINT_DESCRIPTOR(0x01, 0x02, 512, 0x00)
_ENDPOINT_DESCRIPTOR(0x82, 0x02, 512, 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 sizeof(string_framework)
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, 0x0c,
0x44, 0x61, 0x74, 0x61, 0x50, 0x75, 0x6d, 0x70,
0x44, 0x65, 0x6d, 0x6f,
/* 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 sizeof(language_id_framework)
static UCHAR language_id_framework[] = {
/* English. */
0x09, 0x04
};
/* Define prototypes for external Host Controller's (HCDs), classes and clients. */
static VOID tx_demo_instance_activate(VOID *dummy_instance);
static VOID tx_demo_instance_deactivate(VOID *dummy_instance);
#if defined(UX_HOST_STANDALONE)
static UINT tx_demo_host_change_function(ULONG e, UX_HOST_CLASS *c, VOID *p);
#else
#define tx_demo_host_change_function UX_NULL
#endif
UINT ux_hcd_sim_initialize(UX_HCD *hcd);
static TX_THREAD tx_demo_thread_host_simulation;
static TX_THREAD tx_demo_thread_slave_simulation;
static void tx_demo_thread_host_simulation_entry(ULONG);
static void tx_demo_thread_slave_simulation_entry(ULONG);
/* 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)
{
if (expected_error == 0 || error_code != expected_error)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %x\n", __LINE__, system_level, system_context, error_code);
// test_control_return(1);
}
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_class_device_enumeration_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR *stack_pointer;
CHAR *memory_pointer;
UX_DEVICE_CLASS_DUMMY_PARAMETER parameter;
printf("Running Basic Device Class Enumeration Test......................... ");
/* Initialize the free memory pointer. */
stack_pointer = (CHAR *) first_unused_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 host portion of USBX. */
status = ux_host_stack_initialize(tx_demo_host_change_function);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Register all the host class drivers for this USBX implementation. */
status = ux_host_stack_class_register(_ux_host_class_dummy_name, _ux_host_class_dummy_device_entry);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX */
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);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Set the parameters for callback when insertion/extraction of a Data Pump device. */
_ux_utility_memory_set((void *)&parameter, 0x00, sizeof(parameter));
parameter.ux_device_class_dummy_parameter_callbacks.ux_device_class_dummy_instance_activate = tx_demo_instance_activate;
parameter.ux_device_class_dummy_parameter_callbacks.ux_device_class_dummy_instance_deactivate = tx_demo_instance_deactivate;
/* Initialize the device dpump class. The class is connected with interface 0 */
status = ux_device_stack_class_register(_ux_device_class_dummy_name, _ux_device_class_dummy_entry,
1, 0, &parameter);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
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_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 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);
}
/* Create the main demo thread. */
status = tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0,
stack_pointer + UX_DEMO_STACK_SIZE, 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_host_simulation_entry(ULONG arg)
{
UINT status;
ULONG actual_length;
UCHAR current_char;
UX_HOST_CLASS *cls;
UINT i;
stepinfo(">>>>> Dummy Class Get\n");
status = ux_host_stack_class_get(_ux_host_class_dummy_name, &cls);
if (status != UX_SUCCESS)
{
printf("ERROR #%d: 0x%x\n", __LINE__, status);
test_control_return(1);
}
stepinfo(">>>>> Dummy Class Instance Wait\n");
do
{
status = ux_host_stack_class_instance_get(cls, 0, (VOID **) &dummy);
#if defined(UX_HOST_STANDALONE)
ux_system_tasks_run();
#endif
tx_thread_relinquish();
} while (status != UX_SUCCESS);
stepinfo(">>>>> Dummy Class State Wait\n");
while(dummy -> ux_host_class_dummy_state != UX_HOST_CLASS_INSTANCE_LIVE)
{
#if defined(UX_HOST_STANDALONE)
ux_system_tasks_run();
#endif
tx_thread_relinquish();
}
expected_error = 0;
/* Sleep for a tick to make sure everything is complete. */
tx_thread_sleep(1);
/* Check for errors from other threads. */
if (error_counter)
{
/* DPUMP error. */
printf("ERROR #%d: total %ld errors\n", __LINE__, error_counter);
test_control_return(1);
}
else
{
/* Successful test. */
printf("SUCCESS!\n");
test_control_return(0);
}
}
static void tx_demo_thread_slave_simulation_entry(ULONG arg)
{
UINT status;
ULONG actual_length;
while(1)
{
#if defined(UX_DEVICE_STANDALONE)
/* Run device tasks. */
ux_system_tasks_run();
#endif
/* Increment thread counter. */
thread_1_counter++;
/* Relinquish to other thread. */
tx_thread_relinquish();
}
}
static VOID tx_demo_instance_activate(VOID *inst)
{
dummy_slave = (UX_DEVICE_CLASS_DUMMY *)inst;
}
static VOID tx_demo_instance_deactivate(VOID *inst)
{
dummy_slave = UX_NULL;
}
#if defined(UX_HOST_STANDALONE)
static UINT tx_demo_host_change_function(ULONG e, UX_HOST_CLASS *c, VOID *p)
{
if (e == UX_STANDALONE_WAIT_BACKGROUND_TASK)
{
tx_thread_relinquish();
}
}
#endif

View File

@ -0,0 +1,840 @@
/* This file tests the ux_device_class_hid API. */
#include "usbx_test_common_hid.h"
#include "ux_test_dcd_sim_slave.h"
#include "ux_test_hcd_sim_host.h"
#include "ux_test_utility_sim.h"
#include "ux_host_class_hid_mouse.h"
#include "ux_host_class_hid_keyboard.h"
#include "ux_host_class_hid_remote_control.h"
static UCHAR hid_keyboard_report[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0, // END_COLLECTION
0xa1, 0x01, // COLLECTION (Application)
0x19, 0x01, // USAGE_MINIMUM (1)
0x29, 0x04, // USAGE_MAXIMUM (4)
0x75, 0x04, // REPORT_SIZE (4)
0x95, 0x04, // REPORT_COUNT (4)
0xb1, 0x02, // FEATURE (Data,Var,Abs)
0x85, 0x02, // REPORT_ID (2)
0x19, 0x05, // USAGE_MINIMUM (5)
0x29, 0x07, // USAGE_MAXIMUM (7)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x03, // REPORT_COUNT (3)
0xb1, 0x02, // FEATURE (Data,Var,Abs)
0x85, 0x04, // REPORT_ID (4)
0x09, 0x08, // USAGE (8)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x01, // REPORT_COUNT (1)
0xb1, 0x02, // FEATURE (Data,Var,Abs)
0xc0, // END_COLLECTION
};
#define HID_KEYBOARD_REPORT_LENGTH sizeof(hid_keyboard_report)/sizeof(hid_keyboard_report[0])
static UCHAR hid_mouse_report[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x06, // INPUT (Data,Var,Rel)
0x09, 0x38, // USAGE (Mouse Wheel)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
};
#define HID_MOUSE_REPORT_LENGTH (sizeof(hid_mouse_report)/sizeof(hid_mouse_report[0]))
static UCHAR hid_remote_control_report[] = {
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x09, 0x01, // USAGE (Consumer Control)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x02, // USAGE (Numeric Key Pad)
0xa1, 0x02, // COLLECTION (Logical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x0a, // USAGE_MAXIMUM (Button 10)
0x15, 0x01, // LOGICAL_MINIMUM (1)
0x25, 0x0a, // LOGICAL_MAXIMUM (10)
0x75, 0x04, // REPORT_SIZE (4)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0, // END_COLLECTION
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x09, 0x86, // USAGE (Channel)
0x09, 0xe0, // USAGE (Volume)
0x15, 0xff, // LOGICAL_MINIMUM (-1)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x02, // REPORT_SIZE (2)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x46, // INPUT (Data,Var,Rel,Null)
0xc0 // END_COLLECTION
};
#define HID_REMOTE_CONTROL_REPORT_LENGTH (sizeof(hid_remote_control_report)/sizeof(hid_remote_control_report[0]))
/* Configuration descriptor 9 bytes */
#define CFG_DESC(wTotalLength, bNumInterfaces, bConfigurationValue)\
/* Configuration 1 descriptor 9 bytes */\
0x09, 0x02, LSB(wTotalLength), MSB(wTotalLength),\
(bNumInterfaces), (bConfigurationValue), 0x00,\
0x40, 0x00,
#define CFG_DESC_LEN (9)
/* HID Mouse/Keyboard interface descriptors 9+9+7=25 bytes */
#define HID_IFC_DESC_ALL(ifc, report_len, interrupt_epa) \
/* Interface descriptor */\
0x09, 0x04, (ifc), 0x00, 0x01, 0x03, 0x00, 0x00, 0x00,\
/* HID descriptor */\
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(report_len),\
MSB(report_len),\
/* Endpoint descriptor (Interrupt) */\
0x07, 0x05, (interrupt_epa), 0x03, 0x08, 0x00, 0x08,
#define HID_IFC_DESC_ALL_LEN (9+9+7)
static UCHAR device_framework_full_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
CFG_DESC(CFG_DESC_LEN+3*HID_IFC_DESC_ALL_LEN, 2, 1)
/* Keyboard */
HID_IFC_DESC_ALL(0, HID_KEYBOARD_REPORT_LENGTH, 0x82)
/* Mouse */
HID_IFC_DESC_ALL(1, HID_MOUSE_REPORT_LENGTH, 0x81)
/* Remote control */
HID_IFC_DESC_ALL(2, HID_REMOTE_CONTROL_REPORT_LENGTH, 0x83)
};
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
static UCHAR device_framework_high_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
CFG_DESC(CFG_DESC_LEN+3*HID_IFC_DESC_ALL_LEN, 2, 1)
/* Keyboard */
HID_IFC_DESC_ALL(0, HID_KEYBOARD_REPORT_LENGTH, 0x82)
/* Mouse */
HID_IFC_DESC_ALL(1, HID_MOUSE_REPORT_LENGTH, 0x81)
/* Remote control */
HID_IFC_DESC_ALL(2, HID_REMOTE_CONTROL_REPORT_LENGTH, 0x83)
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
/* 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
*/
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* Serial Number string descriptor : Index 3 */
0x09, 0x04, 0x03, 0x04,
0x30, 0x30, 0x30, 0x31
};
#define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
/* Multiple languages are supported on the device, to add
a language besides english, the unicode language code must
be appended to the language_id_framework array and the length
adjusted accordingly. */
static UCHAR language_id_framework[] = {
/* English. */
0x09, 0x04
};
#define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
static UX_HOST_CLASS_HID *hid = UX_NULL;
static UX_HOST_CLASS_HID_MOUSE *hid_mouse = UX_NULL;
static UX_HOST_CLASS_HID_KEYBOARD *hid_keyboard = UX_NULL;
static UX_HOST_CLASS_HID_REMOTE_CONTROL *hid_remote_control = UX_NULL;
static UX_SLAVE_CLASS_HID *hid_mouse_slave = UX_NULL;
static UX_SLAVE_CLASS_HID *hid_keyboard_slave = UX_NULL;
static UX_SLAVE_CLASS_HID *hid_remote_control_slave = UX_NULL;
static UX_SLAVE_CLASS_HID_PARAMETER hid_mouse_parameter;
static UX_SLAVE_CLASS_HID_PARAMETER hid_keyboard_parameter;
static UX_SLAVE_CLASS_HID_PARAMETER hid_remote_control_parameter;
static ULONG rsc_mem_alloc_cnt_on_set_cfg;
static ULONG rsc_enum_mem_alloc_count;
static ULONG rsc_hid_mem_alloc_count;
static ULONG error_callback_counter;
static UCHAR error_callback_ignore;
static ULONG error_counter = 0;
static UINT _is_mouse(UX_HOST_CLASS_HID_CLIENT *client)
{
return(UX_SUCCESS == _ux_utility_memory_compare(client->ux_host_class_hid_client_name,
_ux_system_host_class_hid_client_mouse_name,
_ux_utility_string_length_get(_ux_system_host_class_hid_client_mouse_name)));
}
static UINT _is_keyboard(UX_HOST_CLASS_HID_CLIENT *client)
{
return(UX_SUCCESS == _ux_utility_memory_compare(client->ux_host_class_hid_client_name,
_ux_system_host_class_hid_client_keyboard_name,
_ux_utility_string_length_get(_ux_system_host_class_hid_client_keyboard_name)));
}
static UINT ux_system_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
{
UX_HOST_CLASS_HID_CLIENT *client = (UX_HOST_CLASS_HID_CLIENT *)inst;
// if(event >= UX_HID_CLIENT_INSERTION) printf("hChg: ev %lx, cls %p, inst %p, %s\n", event, cls, inst, _is_mouse(client) ? "Mouse" : _is_keyboard(client) ? "Keyboard" : "Remote Control");
switch(event)
{
case UX_HID_CLIENT_INSERTION:
if (_is_mouse(client))
hid_mouse = (UX_HOST_CLASS_HID_MOUSE *)client->ux_host_class_hid_client_local_instance;
else
{
if (_is_keyboard(client))
hid_keyboard = (UX_HOST_CLASS_HID_KEYBOARD *)client->ux_host_class_hid_client_local_instance;
else
hid_remote_control = (UX_HOST_CLASS_HID_REMOTE_CONTROL *)client->ux_host_class_hid_client_local_instance;
}
break;
case UX_HID_CLIENT_REMOVAL:
if (_is_mouse(client))
hid_mouse = UX_NULL;
else
{
if (_is_keyboard(client))
hid_keyboard = UX_NULL;
else
hid_remote_control = UX_NULL;
}
break;
default:
break;
}
return 0;
}
static VOID mouse_instance_activate_callback(VOID *parameter)
{
// printf("dMouse: %p\n", parameter);
hid_mouse_slave = (UX_SLAVE_CLASS_HID *)parameter;
}
static VOID keyboard_instance_activate_callback(VOID *parameter)
{
// printf("dKeyboard: %p\n", parameter);
hid_keyboard_slave = (UX_SLAVE_CLASS_HID *)parameter;
}
static VOID remote_control_instance_activate_callback(VOID *parameter)
{
// printf("dKeyboard: %p\n", parameter);
hid_remote_control_slave = (UX_SLAVE_CLASS_HID *)parameter;
}
static VOID instance_deactivate_callback(VOID *parameter)
{
// printf("dRm: %p\n", parameter);
if ((VOID *)hid_mouse_slave == parameter)
hid_mouse_slave = UX_NULL;
if ((VOID *)hid_keyboard_slave == parameter)
hid_keyboard_slave = UX_NULL;
if ((VOID *)hid_remote_control_slave == parameter)
hid_remote_control_slave = UX_NULL;
}
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
if (error_code == UX_MEMORY_INSUFFICIENT)
error_callback_counter ++;
// printf("ERROR #%d: 0x%x, 0x%x, 0x%x\n", __LINE__, system_level, system_context, error_code);
}
static UINT break_on_all_activated(VOID)
{
if (hid_mouse_slave == UX_NULL)
return 0;
if (hid_keyboard_slave == UX_NULL)
return 0;
if (hid_remote_control_slave == UX_NULL)
return 0;
if (hid_mouse == UX_NULL)
return 0;
if (hid_keyboard == UX_NULL)
return 0;
if (hid_remote_control == UX_NULL)
return 0;
return 1;
}
static UINT break_on_all_removed(VOID)
{
if (hid_mouse_slave || hid_keyboard_slave || hid_remote_control_slave)
return 0;
if (hid_mouse || hid_keyboard || hid_remote_control)
return 0;
return 1;
}
static UINT sleep_break_on_error(VOID)
{
if (error_callback_counter >= 3)
return error_callback_counter;
return UX_SUCCESS;
}
static VOID ux_test_hcd_entry_set_cfg(UX_TEST_ACTION *action, VOID *_params)
{
rsc_mem_alloc_cnt_on_set_cfg = ux_test_utility_sim_mem_alloc_count();
}
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 }
};
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_ux_device_class_hid_basic_memory_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR *stack_pointer;
CHAR *memory_pointer;
ULONG mem_free;
ULONG alloc_count;
ULONG test_n;
/* Inform user. */
printf("Running UX Class HID Basic Memory test ............................. ");
stepinfo("\n");
/* Initialize memory logger. */
ux_test_utility_sim_mem_alloc_log_enable(UX_TRUE);
ux_test_utility_sim_mem_alloc_count_reset();
/* 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, code 0x%x\n", __LINE__, status);
test_control_return(1);
}
/* Register the error callback. */
_ux_utility_error_callback_register(error_callback);
/* The code below is required for installing the host portion of USBX */
status = ux_host_stack_initialize(ux_system_host_change_function);
if (status != UX_SUCCESS)
{
printf("ERROR #%d, code 0x%x\n", __LINE__, status);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("ERROR #%d, code 0x%x\n", __LINE__, status);
test_control_return(1);
}
/* Register the HID client(s). */
status |= ux_host_class_hid_client_register(_ux_system_host_class_hid_client_mouse_name, ux_host_class_hid_mouse_entry);
status |= ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
status |= ux_host_class_hid_client_register(_ux_system_host_class_hid_client_remote_control_name, ux_host_class_hid_remote_control_entry);
#if UX_MAX_SLAVE_CLASS_DRIVER > 1
if (status != UX_SUCCESS)
{
printf("ERROR #%d, code 0x%x\n", __LINE__, status);
test_control_return(1);
}
#endif
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("ERROR #%d, code 0x%x\n", __LINE__, status);
test_control_return(1);
}
/* Initialize the hid class parameters for mouse and keyboard. */
hid_mouse_parameter.ux_device_class_hid_parameter_report_address = hid_mouse_report;
hid_mouse_parameter.ux_device_class_hid_parameter_report_length = HID_MOUSE_REPORT_LENGTH;
hid_mouse_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
hid_mouse_parameter.ux_slave_class_hid_instance_activate = mouse_instance_activate_callback;
hid_mouse_parameter.ux_slave_class_hid_instance_deactivate = instance_deactivate_callback;
hid_keyboard_parameter.ux_device_class_hid_parameter_report_address = hid_keyboard_report;
hid_keyboard_parameter.ux_device_class_hid_parameter_report_length = HID_KEYBOARD_REPORT_LENGTH;
hid_keyboard_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
hid_keyboard_parameter.ux_slave_class_hid_instance_activate = keyboard_instance_activate_callback;
hid_keyboard_parameter.ux_slave_class_hid_instance_deactivate = instance_deactivate_callback;
hid_remote_control_parameter.ux_device_class_hid_parameter_report_address = hid_remote_control_report;
hid_remote_control_parameter.ux_device_class_hid_parameter_report_length = HID_REMOTE_CONTROL_REPORT_LENGTH;
hid_remote_control_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
hid_remote_control_parameter.ux_slave_class_hid_instance_activate = remote_control_instance_activate_callback;
hid_remote_control_parameter.ux_slave_class_hid_instance_deactivate = instance_deactivate_callback;
stepinfo(">>>>>>>>>> Test HID Class Initialize/deinitialize memory\n");
stepinfo(">>>>>>>>>> - Reset counts\n");
ux_test_utility_sim_mem_alloc_count_reset();
mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
stepinfo(">>>>>>>>>> - _class_register\n");
/* Initilize the device hid class. */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,1, (VOID *)&hid_mouse_parameter);
status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,0, (VOID *)&hid_keyboard_parameter);
status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_remote_control_parameter);
#if UX_MAX_SLAVE_CLASS_DRIVER > 1
if(status!=UX_SUCCESS)
{
printf("ERROR #%d, code 0x%x\n", __LINE__, status);
test_control_return(1);
}
#endif
#if 1
/* Log create counts when instances active for further tests. */
alloc_count = ux_test_utility_sim_mem_alloc_count();
/* Lock log base for tests. */
ux_test_utility_sim_mem_alloc_log_lock();
stepinfo("init & uninit alloc : %ld\n", 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);
if (alloc_count) stepinfo(">>>>>>>>>> - Init/deinit memory errors test\n");
mem_free = (~0);
for (test_n = 0; test_n < alloc_count; test_n ++)
{
stepinfo("%4ld / %4ld\n", test_n, alloc_count - 1);
/* Unregister. */
ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
/* 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);
error_counter ++;
test_control_return(1);
}
/* Set memory error generation */
ux_test_utility_sim_mem_alloc_error_generation_start(test_n);
/* Register. */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,1, (VOID *)&hid_mouse_parameter);
status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,0, (VOID *)&hid_keyboard_parameter);
status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_remote_control_parameter);
#if UX_MAX_SLAVE_CLASS_DRIVER > 1
/* Check error */
if (status == UX_SUCCESS)
{
printf("ERROR #%d.%ld: registered when there is memory error\n", __LINE__, test_n);
error_counter ++;
}
#endif
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 (alloc_count) stepinfo("\n");
/* Unregister. */
ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
/* Register. */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,1, (VOID *)&hid_mouse_parameter);
status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,0, (VOID *)&hid_keyboard_parameter);
status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_remote_control_parameter);
#if UX_MAX_SLAVE_CLASS_DRIVER > 1
if(status!=UX_SUCCESS)
{
printf("ERROR #%d, code 0x%x\n", __LINE__, status);
test_control_return(1);
}
#endif
#endif
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("ERROR #%d, code 0x%x\n", __LINE__, status);
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, code 0x%x\n", __LINE__, status);
test_control_return(1);
}
/* 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, code 0x%x\n", __LINE__, status);
test_control_return(1);
}
#if defined(UX_DEVICE_STANDALONE)
/* 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, UX_DEMO_STACK_SIZE,
20, 20, 1, TX_AUTO_START);
/* Check for error. */
if (status != TX_SUCCESS)
{
printf("ERROR #%d, code 0x%x\n", __LINE__, status);
test_control_return(1);
}
#endif
}
#if defined(UX_DEVICE_STANDALONE)
static void tx_demo_thread_device_simulation_entry(ULONG arg)
{
while(1)
{
ux_system_tasks_run();
tx_thread_relinquish();
}
}
#endif
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_DEVICE *device;
ULONG mem_free;
ULONG alloc_count;
ULONG test_n;
UX_HCD *hcd;
stepinfo(">>>>>>>>>> Thread start\n");
hcd = &_ux_system_host->ux_system_host_hcd_array[0];
ux_test_breakable_sleep(500, break_on_all_activated);
/* Get device instance. */
status = ux_host_stack_device_get(0, &device);
if (status != UX_SUCCESS)
{
printf("ERROR #%d: get_device fail, 0x%x\n", __LINE__, status);
test_control_return(1);
}
stepinfo(">>>>>>>>>> Disconnect\n");
ux_test_dcd_sim_slave_disconnect();
ux_test_hcd_sim_host_disconnect();
if (hid_keyboard || hid_mouse)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
stepinfo(">>>>>>>>>> Reset counts\n");
ux_test_utility_sim_mem_alloc_count_reset();
mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
rsc_mem_alloc_cnt_on_set_cfg = 0;
ux_test_hcd_sim_host_set_actions(log_on_SetCfg);
stepinfo(">>>>>>>>>> Connect\n");
ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
ux_test_breakable_sleep(500, break_on_all_activated);
/* Log create counts for further tests. */
rsc_enum_mem_alloc_count = rsc_mem_alloc_cnt_on_set_cfg;
/* Log create counts when instances active for further tests. */
alloc_count = ux_test_utility_sim_mem_alloc_count();
/* Lock log base for tests. */
ux_test_utility_sim_mem_alloc_log_lock();
rsc_hid_mem_alloc_count = alloc_count - rsc_enum_mem_alloc_count;
stepinfo("enum mem: %ld\n", rsc_enum_mem_alloc_count);
stepinfo("hid mem : %ld\n", rsc_hid_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);
if (hid_mouse == UX_NULL
#if UX_MAX_SLAVE_CLASS_DRIVER > 1
|| hid_keyboard == UX_NULL
#endif
)
{
printf("ERROR #%d: %p %p\n", __LINE__, hid_keyboard, hid_mouse);
test_control_return(1);
}
/* Simulate detach and attach for FS enumeration,
and test possible memory allocation error handlings.
*/
if (rsc_hid_mem_alloc_count) stepinfo(">>>>>>>>>> Memory errors enumeration test\n");
mem_free = (~0);
for (test_n = 0; test_n < rsc_hid_mem_alloc_count; test_n ++)
{
stepinfo("%4ld / %4ld\n", test_n, rsc_hid_mem_alloc_count - 1);
/* Disconnect. */
ux_test_dcd_sim_slave_disconnect();
ux_test_hcd_sim_host_disconnect();
/* Check number of devices. */
if (hcd->ux_hcd_nb_devices != 0)
{
printf("ERROR #%d.%ld: number of devices (%d) must be 0\n", __LINE__, test_n, hcd->ux_hcd_nb_devices);
error_counter ++;
}
/* 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);
error_counter ++;
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);
#if 1 /* @nick */
ux_test_hcd_sim_host_connect_no_wait(UX_FULL_SPEED_DEVICE);
/* Wait for enum thread to complete. */
ux_test_wait_for_enum_thread_completion();
#else
ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
/* Wait and break on errors. */
ux_test_breakable_sleep(400, sleep_break_on_error);
#endif
/* Check error */
if (hid_mouse && hid_keyboard && hid_mouse_slave && hid_keyboard_slave && hid_remote_control && hid_remote_control_slave)
{
printf("ERROR #%d.%ld: device detected when there is memory error\n", __LINE__, test_n);
error_counter ++;
}
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 (alloc_count) stepinfo("\n");
stepinfo(">>>>>>>>>> Test done\n");
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
/* Deinitialize the device side of usbx. */
_ux_device_stack_uninitialize();
/* And finally the usbx system resources. */
_ux_system_uninitialize();
if (error_counter)
{
printf("FAIL %ld errors!\n", error_counter);
test_control_return(1);
}
/* Successful test. */
printf("SUCCESS!\n");
test_control_return(0);
}
static UINT demo_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}

View File

@ -0,0 +1,610 @@
/* This file tests basic HID functionalities. */
#include "usbx_test_common_hid.h"
#define DUMMY_USBX_MEMORY_SIZE (64*1024)
static UCHAR dummy_usbx_memory[DUMMY_USBX_MEMORY_SIZE];
static UCHAR hid_keyboard_report[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
};
#define HID_KEYBOARD_REPORT_LENGTH sizeof(hid_keyboard_report)/sizeof(hid_keyboard_report[0])
static UCHAR hid_mouse_report[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x01, // REPORT_ID (1)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x06, // INPUT (Data,Var,Rel)
0x09, 0x38, // USAGE (Mouse Wheel)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
};
#define HID_MOUSE_REPORT_LENGTH (sizeof(hid_mouse_report)/sizeof(hid_mouse_report[0]))
static UCHAR hid_report_descriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x19, 0x01, // USAGE_MINIMUM (1)
0x29, 0x04, // USAGE_MAXIMUM (4)
0x75, 0x04, // REPORT_SIZE (4)
0x95, 0x04, // REPORT_COUNT (4)
0xb1, 0x02, // FEATURE (Data,Var,Abs)
0x85, 0x02, // REPORT_ID (2)
0x19, 0x05, // USAGE_MINIMUM (5)
0x29, 0x07, // USAGE_MAXIMUM (7)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x03, // REPORT_COUNT (3)
0xb1, 0x02, // FEATURE (Data,Var,Abs)
0x85, 0x04, // REPORT_ID (4)
0x09, 0x08, // USAGE (8)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x01, // REPORT_COUNT (1)
0xb1, 0x02, // FEATURE (Data,Var,Abs)
/* USBX requires at least one input report. */
0x09, 0x01, // USAGE (1)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* USBX expects keyboards to have at least one output report, otherwise it's an error. */
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
};
#define HID_REPORT_LENGTH sizeof(hid_report_descriptor)/sizeof(hid_report_descriptor[0])
/* Configuration descriptor 9 bytes */
#define CFG_DESC(wTotalLength, bNumInterfaces, bConfigurationValue)\
/* Configuration 1 descriptor 9 bytes */\
0x09, 0x02, LSB(wTotalLength), MSB(wTotalLength),\
(bNumInterfaces), (bConfigurationValue), 0x00,\
0x40, 0x00,
#define CFG_DESC_LEN (9)
/* HID Mouse/Keyboard interface descriptors 9+9+7=25 bytes */
#define HID_IFC_DESC_ALL(ifc, report_len, interrupt_epa) \
/* Interface descriptor */\
0x09, 0x04, (ifc), 0x00, 0x01, 0x03, 0x00, 0x00, 0x00,\
/* HID descriptor */\
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(report_len),\
MSB(report_len),\
/* Endpoint descriptor (Interrupt) */\
0x07, 0x05, (interrupt_epa), 0x03, 0x08, 0x00, 0x08,
#define HID_IFC_DESC_ALL_LEN (9+9+7)
static UCHAR device_framework_full_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
CFG_DESC(CFG_DESC_LEN+1*HID_IFC_DESC_ALL_LEN, 1, 1)
/* Keyboard */
HID_IFC_DESC_ALL(0, HID_REPORT_LENGTH, 0x81)
};
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
static UCHAR device_framework_high_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
CFG_DESC(CFG_DESC_LEN+1*HID_IFC_DESC_ALL_LEN, 1, 1)
/* Keyboard */
HID_IFC_DESC_ALL(0, HID_REPORT_LENGTH, 0x81)
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
/* 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
*/
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* Serial Number string descriptor : Index 3 */
0x09, 0x04, 0x03, 0x04,
0x30, 0x30, 0x30, 0x31
};
#define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
/* Multiple languages are supported on the device, to add
a language besides english, the unicode language code must
be appended to the language_id_framework array and the length
adjusted accordingly. */
static UCHAR language_id_framework[] = {
/* English. */
0x09, 0x04
};
#define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
UINT _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter);
static UINT ux_system_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
{
switch(event)
{
case UX_HID_CLIENT_INSERTION:
break;
case UX_HID_CLIENT_REMOVAL:
break;
#if defined(UX_HOST_STANDALONE)
case UX_STANDALONE_WAIT_BACKGROUND_TASK:
/* Let other threads to run. */
tx_thread_relinquish();
break;
#endif
default:
break;
}
return 0;
}
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_class_hid_basic_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
/* Inform user. */
printf("Running HID Class Basic Test........................................ ");
/* 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 on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Register the error callback. */
_ux_utility_error_callback_register(error_callback);
/* The code below is required for installing the host portion of USBX */
status = ux_host_stack_initialize(ux_system_host_change_function);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* No client registered, just HID. */
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Initialize the hid class parameters. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_set_callback;
hid_parameter.ux_device_class_hid_parameter_get_callback = demo_thread_hid_get_callback;
hid_parameter.ux_slave_class_hid_instance_activate = demo_device_hid_instance_activate;
hid_parameter.ux_slave_class_hid_instance_deactivate = demo_device_hid_instance_deactivate;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1, 0, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
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,
20, 20, 1, TX_AUTO_START);
/* Check for error. */
if (status != TX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
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 on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
}
static void tx_demo_thread_device_simulation_entry(ULONG arg)
{
while(1)
{
#if defined(UX_DEVICE_STANDALONE)
ux_system_tasks_run();
#else
tx_thread_suspend(&tx_demo_thread_device_simulation);
#endif
}
}
static UINT demo_wait(ULONG tick, UINT (*check)())
{
ULONG t0, t1;
UINT status;
t0 = tx_time_get();
while(1)
{
#if defined(UX_HOST_STANDALONE)
ux_system_tasks_run();
#endif
if (check)
{
status = check();
if (status == UX_SUCCESS)
break;
}
t1 = tx_time_get();
if (_ux_utility_time_elapsed(t0, t1) >= tick)
{
return(UX_TIMEOUT);
}
}
return(UX_SUCCESS);
}
static UINT demo_class_hid_wait(ULONG tick)
{
return(demo_wait(tick, demo_class_hid_get));
}
static void test_hid_idle_requests(VOID)
{
USHORT idle_time;
UINT status;
INT i;
#define N_TEST_IDLES 4
USHORT test_idles[N_TEST_IDLES] = {1, 8, 20, 0};
ULONG mem_level = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
/* Get input report. */
hid_report_id.ux_host_class_hid_report_get_report = UX_NULL;
hid_report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT;
status = _ux_host_class_hid_report_id_get(hid, &hid_report_id);
UX_TEST_ASSERT(status == UX_SUCCESS);
status = _ux_host_class_hid_idle_get(hid, &idle_time, hid_report_id.ux_host_class_hid_report_get_id);
UX_TEST_ASSERT(status == UX_SUCCESS);
test_idles[N_TEST_IDLES - 1] = idle_time;
for (i = 0; i < N_TEST_IDLES; i ++)
{
status = _ux_host_class_hid_idle_set(hid, test_idles[i], hid_report_id.ux_host_class_hid_report_get_id);
UX_TEST_ASSERT(status == UX_SUCCESS);
status = _ux_host_class_hid_idle_get(hid, &idle_time, hid_report_id.ux_host_class_hid_report_get_id);
UX_TEST_ASSERT(status == UX_SUCCESS);
UX_TEST_ASSERT(idle_time == test_idles[i]);
}
UX_TEST_ASSERT(mem_level == _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
}
static void test_hid_report_requests(VOID)
{
ULONG tmp_bytes[2];
UINT status;
INT i;
#define N_TEST_REPORT_REQS 5
ULONG mem_level = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
/* Get output report. */
hid_report_id.ux_host_class_hid_report_get_report = UX_NULL;
hid_report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_FEATURE;
status = _ux_host_class_hid_report_id_get(hid, &hid_report_id);
UX_TEST_ASSERT(status == UX_SUCCESS);
/* Memorize the report pointer. */
client_report.ux_host_class_hid_client_report = hid_report_id.ux_host_class_hid_report_get_report;
/* The report set is raw since the LEDs mask is already in the right format. */
client_report.ux_host_class_hid_client_report_flags = UX_HOST_CLASS_HID_REPORT_RAW;
/* The length of this report is 2 byte (16 bits). */
client_report.ux_host_class_hid_client_report_length = 2;
/* The output report buffer is the LED mask field. */
client_report.ux_host_class_hid_client_report_buffer = tmp_bytes;
for (i = 0; i < N_TEST_REPORT_REQS; i ++)
{
_ux_utility_memory_set(tmp_bytes, i, sizeof(tmp_bytes));
status = _ux_host_class_hid_report_set(hid, &client_report);
UX_TEST_ASSERT(status == UX_SUCCESS);
_ux_utility_memory_set(tmp_bytes, 0xFF, sizeof(tmp_bytes));
status = _ux_host_class_hid_report_get(hid, &client_report);
UX_TEST_ASSERT_MESSAGE(status == UX_SUCCESS, "0x%x\n", status);
UX_TEST_ASSERT(*(UCHAR *)tmp_bytes == i);
}
UX_TEST_ASSERT(mem_level == _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
}
static ULONG test_hid_report_callback_count = 0;
static ULONG test_hid_report_callback_wait = 0;
static VOID test_hid_report_callback(UX_HOST_CLASS_HID_REPORT_CALLBACK *callback)
{
test_hid_report_callback_count ++;
}
static UINT test_hid_report_callback_count_check(VOID)
{
return(test_hid_report_callback_count >= test_hid_report_callback_wait ?
UX_SUCCESS : UX_ERROR);
}
static void test_hid_periodic_reports(VOID)
{
UINT status;
ULONG mem_level;
/* Get input report. */
hid_report_id.ux_host_class_hid_report_get_report = UX_NULL;
hid_report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT;
status = _ux_host_class_hid_report_id_get(hid, &hid_report_id);
UX_TEST_ASSERT(status == UX_SUCCESS);
/* Initialize the report callback. */
hid_report_callback.ux_host_class_hid_report_callback_id = hid_report_id.ux_host_class_hid_report_get_id;
hid_report_callback.ux_host_class_hid_report_callback_function = test_hid_report_callback;
hid_report_callback.ux_host_class_hid_report_callback_buffer = UX_NULL;
hid_report_callback.ux_host_class_hid_report_callback_flags = UX_HOST_CLASS_HID_REPORT_RAW;
hid_report_callback.ux_host_class_hid_report_callback_length = hid_report_id.ux_host_class_hid_report_get_report->ux_host_class_hid_report_byte_length;
/* Register the report call back when data comes it on this report. */
status = _ux_host_class_hid_report_callback_register(hid, &hid_report_callback);
UX_TEST_ASSERT(status == UX_SUCCESS);
/* Start background report reading. */
_ux_host_class_hid_periodic_report_start(hid);
mem_level = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
device_hid_event.ux_device_class_hid_event_length = 4;
device_hid_event.ux_device_class_hid_event_buffer[0] = 0;
device_hid_event.ux_device_class_hid_event_buffer[1] = 0;
device_hid_event.ux_device_class_hid_event_buffer[2] = '0';
device_hid_event.ux_device_class_hid_event_buffer[3] = '1';
test_hid_report_callback_count = 0;
test_hid_report_callback_wait = 1;
_ux_device_class_hid_event_set(device_hid, &device_hid_event);
demo_wait(10, test_hid_report_callback_count_check);
UX_TEST_ASSERT(test_hid_report_callback_count == 1);
test_hid_report_callback_count = 0;
test_hid_report_callback_wait = 2;
_ux_device_class_hid_event_set(device_hid, &device_hid_event);
_ux_device_class_hid_event_set(device_hid, &device_hid_event);
demo_wait(10, test_hid_report_callback_count_check);
UX_TEST_ASSERT(test_hid_report_callback_count == 2);
UX_TEST_ASSERT(mem_level == _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
/* Find the HID class */
status = demo_class_hid_wait(100);
UX_TEST_ASSERT(status == UX_SUCCESS);
test_hid_idle_requests();
test_hid_report_requests();
test_hid_periodic_reports();
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_set_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
_ux_utility_memory_copy(&device_hid_event, event, sizeof(UX_SLAVE_CLASS_HID_EVENT));
return(UX_SUCCESS);
}
static UINT demo_thread_hid_get_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
_ux_utility_memory_copy(event, &device_hid_event, sizeof(UX_SLAVE_CLASS_HID_EVENT));
return(UX_SUCCESS);
}
static void demo_device_hid_instance_activate(VOID *inst)
{
if (device_hid == UX_NULL)
device_hid = (UX_SLAVE_CLASS_HID *)inst;
}
static void demo_device_hid_instance_deactivate(VOID *inst)
{
if (inst == (VOID *)device_hid)
device_hid = UX_NULL;
}

View File

@ -0,0 +1,493 @@
/* This file tests basic HID functionalities. */
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_keyboard.h"
#define DUMMY_USBX_MEMORY_SIZE (64*1024)
static UCHAR dummy_usbx_memory[DUMMY_USBX_MEMORY_SIZE];
static UCHAR hid_keyboard_report[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
};
#define HID_KEYBOARD_REPORT_LENGTH sizeof(hid_keyboard_report)/sizeof(hid_keyboard_report[0])
static UCHAR hid_mouse_report[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x01, // REPORT_ID (1)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x06, // INPUT (Data,Var,Rel)
0x09, 0x38, // USAGE (Mouse Wheel)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
};
#define HID_MOUSE_REPORT_LENGTH (sizeof(hid_mouse_report)/sizeof(hid_mouse_report[0]))
#define hid_report_descriptor hid_keyboard_report
#define HID_REPORT_LENGTH HID_KEYBOARD_REPORT_LENGTH
/* Configuration descriptor 9 bytes */
#define CFG_DESC(wTotalLength, bNumInterfaces, bConfigurationValue)\
/* Configuration 1 descriptor 9 bytes */\
0x09, 0x02, LSB(wTotalLength), MSB(wTotalLength),\
(bNumInterfaces), (bConfigurationValue), 0x00,\
0x40, 0x00,
#define CFG_DESC_LEN (9)
/* HID Mouse/Keyboard interface descriptors 9+9+7=25 bytes */
#define HID_IFC_DESC_ALL(ifc, report_len, interrupt_epa) \
/* Interface descriptor */\
0x09, 0x04, (ifc), 0x00, 0x01, 0x03, 0x00, 0x00, 0x00,\
/* HID descriptor */\
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(report_len),\
MSB(report_len),\
/* Endpoint descriptor (Interrupt) */\
0x07, 0x05, (interrupt_epa), 0x03, 0x08, 0x00, 0x08,
#define HID_IFC_DESC_ALL_LEN (9+9+7)
static UCHAR device_framework_full_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
CFG_DESC(CFG_DESC_LEN+1*HID_IFC_DESC_ALL_LEN, 1, 1)
/* Keyboard */
HID_IFC_DESC_ALL(0, HID_REPORT_LENGTH, 0x81)
};
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
static UCHAR device_framework_high_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
CFG_DESC(CFG_DESC_LEN+1*HID_IFC_DESC_ALL_LEN, 1, 1)
/* Keyboard */
HID_IFC_DESC_ALL(0, HID_REPORT_LENGTH, 0x81)
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
/* 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
*/
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* Serial Number string descriptor : Index 3 */
0x09, 0x04, 0x03, 0x04,
0x30, 0x30, 0x30, 0x31
};
#define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
/* Multiple languages are supported on the device, to add
a language besides english, the unicode language code must
be appended to the language_id_framework array and the length
adjusted accordingly. */
static UCHAR language_id_framework[] = {
/* English. */
0x09, 0x04
};
#define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
UINT _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter);
static UINT ux_system_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
{
switch(event)
{
case UX_HID_CLIENT_INSERTION:
break;
case UX_HID_CLIENT_REMOVAL:
break;
#if defined(UX_HOST_STANDALONE)
case UX_STANDALONE_WAIT_BACKGROUND_TASK:
/* Let other threads to run. */
tx_thread_relinquish();
break;
#endif
default:
break;
}
return 0;
}
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_class_hid_keyboard_basic_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
/* Inform user. */
printf("Running HID Class Keyboard Basic Test............................... ");
/* 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 on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Register the error callback. */
_ux_utility_error_callback_register(error_callback);
/* The code below is required for installing the host portion of USBX */
status = ux_host_stack_initialize(ux_system_host_change_function);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: 0x%x\n", __LINE__, status);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: 0x%x\n", __LINE__, status);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Initialize the hid class parameters. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_set_callback;
hid_parameter.ux_device_class_hid_parameter_get_callback = demo_thread_hid_get_callback;
hid_parameter.ux_slave_class_hid_instance_activate = demo_device_hid_instance_activate;
hid_parameter.ux_slave_class_hid_instance_deactivate = demo_device_hid_instance_deactivate;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1, 0, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
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,
20, 20, 1, TX_AUTO_START);
/* Check for error. */
if (status != TX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
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 on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
}
static void tx_demo_thread_device_simulation_entry(ULONG arg)
{
while(1)
{
#if defined(UX_DEVICE_STANDALONE)
ux_system_tasks_run();
#else
tx_thread_suspend(&tx_demo_thread_device_simulation);
#endif
}
}
static UINT demo_class_hid_wait(ULONG tick)
{
return(ux_test_sleep_break_on_success(tick, demo_class_hid_keyboard_get));
}
static UINT _wait_key(UX_HOST_CLASS_HID_KEYBOARD *keyboard, ULONG *keyboard_key, ULONG *keyboard_state)
{
UINT status;
UINT i;
for(i = 0; i < 200; i ++)
{
#if defined(UX_HOST_STANDALONE)
ux_system_tasks_run();
#endif
status = ux_host_class_hid_keyboard_key_get(keyboard, keyboard_key, keyboard_state);
if (status == UX_SUCCESS)
{
// printf("Key: %lx,%lx\n", *keyboard_key, *keyboard_state);
#if defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE_REPORT_LOCK_KEYS) || defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE_REPORT_MODIFIER_KEYS)
if (*keyboard_state & UX_HID_KEYBOARD_STATE_FUNCTION)
continue;
#endif
#if !defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE_REPORT_KEY_DOWN_ONLY)
if (*keyboard_state & UX_HID_KEYBOARD_STATE_KEY_UP)
continue;
#endif
return UX_SUCCESS;
}
_ux_utility_delay_ms(1);
}
return UX_ERROR;
}
static void test_hid_keyboard_keys(VOID)
{
UINT status;
ULONG keyboard_key;
ULONG keyboard_state;
/* Initialize key event. */
device_hid_event.ux_device_class_hid_event_length = 4;
device_hid_event.ux_device_class_hid_event_buffer[0] = 0; /* Modifier. */
device_hid_event.ux_device_class_hid_event_buffer[1] = 0; /* Reserved. */
device_hid_event.ux_device_class_hid_event_buffer[2] = 0; /* Key ...... */
device_hid_event.ux_device_class_hid_event_buffer[3] = 0; /* Key ...... */
/* Set modifier + key. */
device_hid_event.ux_device_class_hid_event_buffer[0] = 1; /* Left CTRL */
device_hid_event.ux_device_class_hid_event_buffer[2] = 4; /* a */
_ux_device_class_hid_event_set(device_hid, &device_hid_event);
status = _wait_key(hid_keyboard, &keyboard_key, &keyboard_state);
UX_TEST_ASSERT(status == UX_SUCCESS);
UX_TEST_ASSERT(keyboard_state & UX_HID_KEYBOARD_STATE_LEFT_CTRL);
UX_TEST_ASSERT(keyboard_key == 'a');
/* Set modifier + key. */
device_hid_event.ux_device_class_hid_event_buffer[0] = (1 << 5); /* Right SHIFT */
device_hid_event.ux_device_class_hid_event_buffer[2] = 5; /* b -> B */
_ux_device_class_hid_event_set(device_hid, &device_hid_event);
status = _wait_key(hid_keyboard, &keyboard_key, &keyboard_state);
UX_TEST_ASSERT(status == UX_SUCCESS);
UX_TEST_ASSERT(keyboard_state & UX_HID_KEYBOARD_STATE_RIGHT_SHIFT);
UX_TEST_ASSERT(keyboard_key == 'B');
/* Send CAPS_Lock. */
device_hid_event.ux_device_class_hid_event_buffer[0] = 0;
device_hid_event.ux_device_class_hid_event_buffer[2] = UX_HID_LED_KEY_CAPS_LOCK;
_ux_device_class_hid_event_set(device_hid, &device_hid_event);
device_hid_event.ux_device_class_hid_event_buffer[0] = 0;
device_hid_event.ux_device_class_hid_event_buffer[2] = 6; /* c -> C */
_ux_device_class_hid_event_set(device_hid, &device_hid_event);
status = _wait_key(hid_keyboard, &keyboard_key, &keyboard_state);
UX_TEST_ASSERT(status == UX_SUCCESS);
UX_TEST_ASSERT(keyboard_state & UX_HID_KEYBOARD_STATE_CAPS_LOCK);
UX_TEST_ASSERT(keyboard_key == 'C');
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
/* Find the HID class */
status = demo_class_hid_wait(100);
UX_TEST_ASSERT(status == UX_SUCCESS);
test_hid_keyboard_keys();
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_set_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
_ux_utility_memory_copy(&device_hid_event, event, sizeof(UX_SLAVE_CLASS_HID_EVENT));
return(UX_SUCCESS);
}
static UINT demo_thread_hid_get_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
_ux_utility_memory_copy(event, &device_hid_event, sizeof(UX_SLAVE_CLASS_HID_EVENT));
return(UX_SUCCESS);
}
static void demo_device_hid_instance_activate(VOID *inst)
{
if (device_hid == UX_NULL)
device_hid = (UX_SLAVE_CLASS_HID *)inst;
}
static void demo_device_hid_instance_deactivate(VOID *inst)
{
if (inst == (VOID *)device_hid)
device_hid = UX_NULL;
}

View File

@ -0,0 +1,530 @@
/* This file tests basic HID functionalities. */
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_keyboard.h"
#define DUMMY_USBX_MEMORY_SIZE (64*1024)
static UCHAR dummy_usbx_memory[DUMMY_USBX_MEMORY_SIZE];
static UCHAR hid_keyboard_report[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
};
#define HID_KEYBOARD_REPORT_LENGTH sizeof(hid_keyboard_report)/sizeof(hid_keyboard_report[0])
static UCHAR hid_mouse_report[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x06, // INPUT (Data,Var,Rel)
0x09, 0x38, // USAGE (Mouse Wheel)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
};
#define HID_MOUSE_REPORT_LENGTH (sizeof(hid_mouse_report)/sizeof(hid_mouse_report[0]))
#define hid_report_descriptor hid_mouse_report
#define HID_REPORT_LENGTH HID_MOUSE_REPORT_LENGTH
/* Configuration descriptor 9 bytes */
#define CFG_DESC(wTotalLength, bNumInterfaces, bConfigurationValue)\
/* Configuration 1 descriptor 9 bytes */\
0x09, 0x02, LSB(wTotalLength), MSB(wTotalLength),\
(bNumInterfaces), (bConfigurationValue), 0x00,\
0x40, 0x00,
#define CFG_DESC_LEN (9)
/* HID Mouse/Keyboard interface descriptors 9+9+7=25 bytes */
#define HID_IFC_DESC_ALL(ifc, report_len, interrupt_epa) \
/* Interface descriptor */\
0x09, 0x04, (ifc), 0x00, 0x01, 0x03, 0x00, 0x00, 0x00,\
/* HID descriptor */\
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(report_len),\
MSB(report_len),\
/* Endpoint descriptor (Interrupt) */\
0x07, 0x05, (interrupt_epa), 0x03, 0x08, 0x00, 0x08,
#define HID_IFC_DESC_ALL_LEN (9+9+7)
static UCHAR device_framework_full_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
CFG_DESC(CFG_DESC_LEN+1*HID_IFC_DESC_ALL_LEN, 1, 1)
/* Keyboard */
HID_IFC_DESC_ALL(0, HID_REPORT_LENGTH, 0x81)
};
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
static UCHAR device_framework_high_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
CFG_DESC(CFG_DESC_LEN+1*HID_IFC_DESC_ALL_LEN, 1, 1)
/* Keyboard */
HID_IFC_DESC_ALL(0, HID_REPORT_LENGTH, 0x81)
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
/* 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
*/
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* Serial Number string descriptor : Index 3 */
0x09, 0x04, 0x03, 0x04,
0x30, 0x30, 0x30, 0x31
};
#define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
/* Multiple languages are supported on the device, to add
a language besides english, the unicode language code must
be appended to the language_id_framework array and the length
adjusted accordingly. */
static UCHAR language_id_framework[] = {
/* English. */
0x09, 0x04
};
#define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
UINT _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter);
static UINT ux_system_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
{
switch(event)
{
case UX_HID_CLIENT_INSERTION:
break;
case UX_HID_CLIENT_REMOVAL:
break;
#if defined(UX_HOST_STANDALONE)
case UX_STANDALONE_WAIT_BACKGROUND_TASK:
/* Let other threads to run. */
tx_thread_relinquish();
break;
#endif
default:
break;
}
return 0;
}
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_class_hid_mouse_basic_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
/* Inform user. */
printf("Running HID Class Mouse Basic Test............................... ");
/* 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 on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Register the error callback. */
_ux_utility_error_callback_register(error_callback);
/* The code below is required for installing the host portion of USBX */
status = ux_host_stack_initialize(ux_system_host_change_function);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: 0x%x\n", __LINE__, status);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_mouse_name, ux_host_class_hid_mouse_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: 0x%x\n", __LINE__, status);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Initialize the hid class parameters. */
ux_utility_memory_set(&hid_parameter, 0, sizeof(hid_parameter));
hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_set_callback;
hid_parameter.ux_device_class_hid_parameter_get_callback = demo_thread_hid_get_callback;
hid_parameter.ux_slave_class_hid_instance_activate = demo_device_hid_instance_activate;
hid_parameter.ux_slave_class_hid_instance_deactivate = demo_device_hid_instance_deactivate;
/* Initialize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1, 0, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
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,
20, 20, 1, TX_AUTO_START);
/* Check for error. */
if (status != TX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
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 on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
}
static void tx_demo_thread_device_simulation_entry(ULONG arg)
{
while(1)
{
#if defined(UX_DEVICE_STANDALONE)
ux_system_tasks_run();
#else
tx_thread_suspend(&tx_demo_thread_device_simulation);
#endif
}
}
static UINT demo_class_hid_wait(ULONG tick)
{
return(ux_test_sleep_break_on_success(tick, demo_class_hid_mouse_get));
}
static UINT _wait_mouse_change(UX_HOST_CLASS_HID_MOUSE *mouse,
ULONG *buttons, SLONG *x, SLONG *y, SLONG *w)
{
UINT status;
UINT i;
ULONG buttons_bak = *buttons;
SLONG x_bak = *x, y_bak = *y;
SLONG w_bak = *w;
for (i = 0; i < 200; i ++)
{
#if defined(UX_HOST_STANDALONE)
ux_system_tasks_run();
#endif
ux_host_class_hid_mouse_buttons_get(hid_mouse, buttons);
ux_host_class_hid_mouse_position_get(hid_mouse, x, y);
ux_host_class_hid_mouse_wheel_get(hid_mouse, w);
if (buttons_bak != *buttons ||
x_bak != *x ||
y_bak != *y ||
w_bak != *w)
{
return(UX_SUCCESS);
}
tx_thread_sleep(1);
}
return(UX_ERROR);
}
static void test_hid_mouse_events(VOID)
{
UINT status;
ULONG buttons = 0;
SLONG x = 0xFF, y = 0xFF;
SLONG wheel = 0;
/* Initialize mouse event. */
device_hid_event.ux_device_class_hid_event_length = 4;
device_hid_event.ux_device_class_hid_event_buffer[0] = 0; /* ...M|R|L */
device_hid_event.ux_device_class_hid_event_buffer[1] = 0; /* X */
device_hid_event.ux_device_class_hid_event_buffer[2] = 0; /* Y */
device_hid_event.ux_device_class_hid_event_buffer[3] = 0; /* Wheel */
status = ux_host_class_hid_mouse_buttons_get(hid_mouse, &buttons);
status |= ux_host_class_hid_mouse_position_get(hid_mouse, &x, &y);
status |= ux_host_class_hid_mouse_wheel_get(hid_mouse, &wheel);
UX_ASSERT(status == UX_SUCCESS);
UX_ASSERT(buttons == 0);
UX_ASSERT(x == 0);
UX_ASSERT(y == 0);
UX_ASSERT(wheel == 0);
/* Set L click. */
device_hid_event.ux_device_class_hid_event_buffer[0] = 1; /* ...M|R|L */
_ux_device_class_hid_event_set(device_hid, &device_hid_event);
status = _wait_mouse_change(hid_mouse, &buttons, &x, &y, &wheel);
UX_ASSERT(status == UX_SUCCESS);
UX_ASSERT(buttons == 1);
UX_ASSERT(x == 0);
UX_ASSERT(y == 0);
UX_ASSERT(wheel == 0);
/* Set R click. */
device_hid_event.ux_device_class_hid_event_buffer[0] = 3; /* ...M|R|L */
_ux_device_class_hid_event_set(device_hid, &device_hid_event);
status = _wait_mouse_change(hid_mouse, &buttons, &x, &y, &wheel);
UX_ASSERT(status == UX_SUCCESS);
UX_ASSERT(buttons == 3);
UX_ASSERT(x == 0);
UX_ASSERT(y == 0);
UX_ASSERT(wheel == 0);
/* Move X. */
device_hid_event.ux_device_class_hid_event_buffer[1] = -1; /* X */
_ux_device_class_hid_event_set(device_hid, &device_hid_event);
status = _wait_mouse_change(hid_mouse, &buttons, &x, &y, &wheel);
UX_ASSERT(status == UX_SUCCESS);
UX_ASSERT(buttons == 3);
UX_ASSERT(x == -1);
UX_ASSERT(y == 0);
UX_ASSERT(wheel == 0);
/* Move X. */
device_hid_event.ux_device_class_hid_event_buffer[1] = +8; /* X */
_ux_device_class_hid_event_set(device_hid, &device_hid_event);
status = _wait_mouse_change(hid_mouse, &buttons, &x, &y, &wheel);
UX_ASSERT(status == UX_SUCCESS);
UX_ASSERT(buttons == 3);
UX_ASSERT(x == +7);
UX_ASSERT(y == 0);
UX_ASSERT(wheel == 0);
/* Move Y. */
device_hid_event.ux_device_class_hid_event_buffer[2] = +8; /* Y */
_ux_device_class_hid_event_set(device_hid, &device_hid_event);
status = _wait_mouse_change(hid_mouse, &buttons, &x, &y, &wheel);
UX_ASSERT(status == UX_SUCCESS);
UX_ASSERT(buttons == 3);
UX_ASSERT(x == 15);
UX_ASSERT(y == 8);
UX_ASSERT(wheel == 0);
/* Move Wheel. */
device_hid_event.ux_device_class_hid_event_buffer[1] = -2; /* X */
device_hid_event.ux_device_class_hid_event_buffer[2] = -5; /* Y */
device_hid_event.ux_device_class_hid_event_buffer[3] = +10; /* Wheel */
_ux_device_class_hid_event_set(device_hid, &device_hid_event);
status = _wait_mouse_change(hid_mouse, &buttons, &x, &y, &wheel);
UX_ASSERT(status == UX_SUCCESS);
UX_ASSERT(buttons == 3);
UX_ASSERT(x == 13);
UX_ASSERT(y == 3);
UX_ASSERT(wheel == 10);
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
/* Find the HID class */
status = demo_class_hid_wait(100);
UX_TEST_ASSERT(status == UX_SUCCESS);
test_hid_mouse_events();
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_set_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
_ux_utility_memory_copy(&device_hid_event, event, sizeof(UX_SLAVE_CLASS_HID_EVENT));
return(UX_SUCCESS);
}
static UINT demo_thread_hid_get_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
_ux_utility_memory_copy(event, &device_hid_event, sizeof(UX_SLAVE_CLASS_HID_EVENT));
return(UX_SUCCESS);
}
static void demo_device_hid_instance_activate(VOID *inst)
{
if (device_hid == UX_NULL)
device_hid = (UX_SLAVE_CLASS_HID *)inst;
}
static void demo_device_hid_instance_deactivate(VOID *inst)
{
if (inst == (VOID *)device_hid)
device_hid = UX_NULL;
}

View File

@ -0,0 +1,503 @@
/* This file tests basic HID functionalities. */
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_keyboard.h"
#define DUMMY_USBX_MEMORY_SIZE (64*1024)
static UCHAR dummy_usbx_memory[DUMMY_USBX_MEMORY_SIZE];
static UCHAR hid_keyboard_report[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
};
#define HID_KEYBOARD_REPORT_LENGTH sizeof(hid_keyboard_report)/sizeof(hid_keyboard_report[0])
static UCHAR hid_mouse_report[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x06, // INPUT (Data,Var,Rel)
0x09, 0x38, // USAGE (Mouse Wheel)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
};
#define HID_MOUSE_REPORT_LENGTH (sizeof(hid_mouse_report)/sizeof(hid_mouse_report[0]))
static UCHAR hid_remote_control_report[] = {
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x09, 0x01, // USAGE (Consumer Control)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x02, // USAGE (Numeric Key Pad)
0xa1, 0x02, // COLLECTION (Logical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x0a, // USAGE_MAXIMUM (Button 10)
0x15, 0x01, // LOGICAL_MINIMUM (1)
0x25, 0x0a, // LOGICAL_MAXIMUM (10)
0x75, 0x04, // REPORT_SIZE (4)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0, // END_COLLECTION
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x09, 0x86, // USAGE (Channel)
0x09, 0xe0, // USAGE (Volume)
0x15, 0xff, // LOGICAL_MINIMUM (-1)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x02, // REPORT_SIZE (2)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x46, // INPUT (Data,Var,Rel,Null)
0xc0 // END_COLLECTION
};
#define HID_REMOTE_CONTROL_REPORT_LENGTH (sizeof(hid_remote_control_report)/sizeof(hid_remote_control_report[0]))
#define hid_report_descriptor hid_remote_control_report
#define HID_REPORT_LENGTH HID_REMOTE_CONTROL_REPORT_LENGTH
/* Configuration descriptor 9 bytes */
#define CFG_DESC(wTotalLength, bNumInterfaces, bConfigurationValue)\
/* Configuration 1 descriptor 9 bytes */\
0x09, 0x02, LSB(wTotalLength), MSB(wTotalLength),\
(bNumInterfaces), (bConfigurationValue), 0x00,\
0x40, 0x00,
#define CFG_DESC_LEN (9)
/* HID Mouse/Keyboard interface descriptors 9+9+7=25 bytes */
#define HID_IFC_DESC_ALL(ifc, report_len, interrupt_epa) \
/* Interface descriptor */\
0x09, 0x04, (ifc), 0x00, 0x01, 0x03, 0x00, 0x00, 0x00,\
/* HID descriptor */\
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(report_len),\
MSB(report_len),\
/* Endpoint descriptor (Interrupt) */\
0x07, 0x05, (interrupt_epa), 0x03, 0x08, 0x00, 0x08,
#define HID_IFC_DESC_ALL_LEN (9+9+7)
static UCHAR device_framework_full_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
CFG_DESC(CFG_DESC_LEN+1*HID_IFC_DESC_ALL_LEN, 1, 1)
/* Keyboard */
HID_IFC_DESC_ALL(0, HID_REPORT_LENGTH, 0x81)
};
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
static UCHAR device_framework_high_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
CFG_DESC(CFG_DESC_LEN+1*HID_IFC_DESC_ALL_LEN, 1, 1)
/* Keyboard */
HID_IFC_DESC_ALL(0, HID_REPORT_LENGTH, 0x81)
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
/* 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
*/
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* Serial Number string descriptor : Index 3 */
0x09, 0x04, 0x03, 0x04,
0x30, 0x30, 0x30, 0x31
};
#define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
/* Multiple languages are supported on the device, to add
a language besides english, the unicode language code must
be appended to the language_id_framework array and the length
adjusted accordingly. */
static UCHAR language_id_framework[] = {
/* English. */
0x09, 0x04
};
#define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
UINT _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter);
static UINT ux_system_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
{
switch(event)
{
case UX_HID_CLIENT_INSERTION:
break;
case UX_HID_CLIENT_REMOVAL:
break;
#if defined(UX_HOST_STANDALONE)
case UX_STANDALONE_WAIT_BACKGROUND_TASK:
/* Let other threads to run. */
tx_thread_relinquish();
break;
#endif
default:
break;
}
return 0;
}
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_class_hid_remote_control_basic_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
/* Inform user. */
printf("Running HID Class Remote Control Basic Test......................... ");
/* 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 on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Register the error callback. */
_ux_utility_error_callback_register(error_callback);
/* The code below is required for installing the host portion of USBX */
status = ux_host_stack_initialize(ux_system_host_change_function);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: 0x%x\n", __LINE__, status);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_remote_control_name, ux_host_class_hid_remote_control_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: 0x%x\n", __LINE__, status);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Initialize the hid class parameters. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_set_callback;
hid_parameter.ux_device_class_hid_parameter_get_callback = demo_thread_hid_get_callback;
hid_parameter.ux_slave_class_hid_instance_activate = demo_device_hid_instance_activate;
hid_parameter.ux_slave_class_hid_instance_deactivate = demo_device_hid_instance_deactivate;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1, 0, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
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,
20, 20, 1, TX_AUTO_START);
/* Check for error. */
if (status != TX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
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 on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
}
static void tx_demo_thread_device_simulation_entry(ULONG arg)
{
while(1)
{
#if defined(UX_DEVICE_STANDALONE)
ux_system_tasks_run();
#else
tx_thread_suspend(&tx_demo_thread_device_simulation);
#endif
}
}
static UINT demo_class_hid_wait(ULONG tick)
{
return(ux_test_sleep_break_on_success(tick, demo_class_hid_remote_control_get));
}
static UINT _wait_remote_control_usage(UX_HOST_CLASS_HID_REMOTE_CONTROL *remote_control,
ULONG *usage, ULONG *value)
{
UINT status;
UINT i;
for (i = 0; i < 200; i ++)
{
#if defined(UX_HOST_STANDALONE)
ux_system_tasks_run();
#endif
status = ux_host_class_hid_remote_control_usage_get(remote_control, usage, value);
if (status == UX_SUCCESS)
return(UX_SUCCESS);
tx_thread_sleep(1);
}
return(UX_ERROR);
}
static void test_hid_remote_control_events(VOID)
{
UINT status;
ULONG usage;
ULONG value;
/* Initialize mouse event. */
device_hid_event.ux_device_class_hid_event_length = 1;
device_hid_event.ux_device_class_hid_event_buffer[0] = 0; /* CH(2)|CH(2)|Bn(4) */
device_hid_event.ux_device_class_hid_event_buffer[0] = (3 << 6) | (1 << 4) | (10); /* CH(2)|CH(2)|Bn(4) */
_ux_device_class_hid_event_set(device_hid, &device_hid_event);
status = _wait_remote_control_usage(hid_remote_control, &usage, &value);
UX_ASSERT(status == UX_SUCCESS);
UX_ASSERT(usage == (0x90000+10));
UX_ASSERT(value == 10);
status = ux_host_class_hid_remote_control_usage_get(hid_remote_control, &usage, &value);
UX_ASSERT(status == UX_SUCCESS);
UX_ASSERT(usage == 0xc0086);
UX_ASSERT(value == 1);
status = ux_host_class_hid_remote_control_usage_get(hid_remote_control, &usage, &value);
UX_ASSERT(status == UX_SUCCESS);
UX_ASSERT(usage == 0xc00e0);
UX_ASSERT(value == 3);
device_hid_event.ux_device_class_hid_event_buffer[0] = (1 << 6) | (0 << 4) | (5); /* CH(2)|CH(2)|Bn(4) */
_ux_device_class_hid_event_set(device_hid, &device_hid_event);
status = _wait_remote_control_usage(hid_remote_control, &usage, &value);
UX_ASSERT(status == UX_SUCCESS);
UX_ASSERT(usage == (0x90000+5));
UX_ASSERT(value == 5);
status = ux_host_class_hid_remote_control_usage_get(hid_remote_control, &usage, &value);
UX_ASSERT(status == UX_SUCCESS);
UX_ASSERT(usage == 0xc0086);
UX_ASSERT(value == 0);
status = ux_host_class_hid_remote_control_usage_get(hid_remote_control, &usage, &value);
UX_ASSERT(status == UX_SUCCESS);
UX_ASSERT(usage == 0xc00e0);
UX_ASSERT(value == 1);
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
/* Find the HID class */
status = demo_class_hid_wait(100);
UX_TEST_ASSERT(status == UX_SUCCESS);
test_hid_remote_control_events();
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_set_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
_ux_utility_memory_copy(&device_hid_event, event, sizeof(UX_SLAVE_CLASS_HID_EVENT));
return(UX_SUCCESS);
}
static UINT demo_thread_hid_get_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
_ux_utility_memory_copy(event, &device_hid_event, sizeof(UX_SLAVE_CLASS_HID_EVENT));
return(UX_SUCCESS);
}
static void demo_device_hid_instance_activate(VOID *inst)
{
if (device_hid == UX_NULL)
device_hid = (UX_SLAVE_CLASS_HID *)inst;
}
static void demo_device_hid_instance_deactivate(VOID *inst)
{
if (inst == (VOID *)device_hid)
device_hid = UX_NULL;
}

View File

@ -0,0 +1,516 @@
/* 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 "ux_host_class_dummy.h"
#include "ux_device_class_dummy.h"
#include "ux_test.h"
/* Define USBX demo constants. */
#define UX_DEMO_STACK_SIZE 4096
#define UX_DEMO_BUFFER_SIZE 2048
#define UX_DEMO_RUN 1
#define UX_DEMO_MEMORY_SIZE (64*1024)
/* Define the counters used in the demo application... */
static ULONG thread_0_counter;
static ULONG thread_1_counter;
static ULONG error_counter;
/* Define USBX demo global variables. */
static UX_HOST_CLASS *class_driver;
static UX_HOST_CLASS_DUMMY *dummy;
static UX_DEVICE_CLASS_DUMMY *dummy_slave;
static UINT expected_error;
#define _W0(w) ( (w) & 0xFF)
#define _W1(w) (((w) >> 8) & 0xFF)
#define _DEVICE_DESCRIPTOR(cls, sub, protocol, pktsize, vid, pid, n_cfg) \
0x12, 0x01, 0x10, 0x01, \
(cls), (sub), (protocol), (pktsize), \
_W0(vid), _W1(vid), _W0(pid), _W1(pid), \
0x00, 0x00, 0x00, 0x00, 0x00, (n_cfg),
#define _QUALIFIER_DESCRIPTOR(cls, sub, protocol, n_cfg) \
0x0a, 0x06, 0x00, 0x02, \
(cls), (sub), (protocol), 0x40, (n_cfg), 0x00,
#define _CONFIGURATION_DESCRIPTOR(total_len, n_ifc, cfg_val) \
0x09, 0x02, _W0(total_len), _W1(total_len), (n_ifc), (cfg_val), \
0x00, 0xc0, 0x32,
#define _INTERFACE_DESCRIPTOR(ifc_n, alt, n_ep, cls, sub, protocol) \
0x09, 0x04, (ifc_n), (alt), (n_ep), (cls), (sub), (protocol), 0x00,
#define _ENDPOINT_DESCRIPTOR(addr, attr, pktsize, interval) \
0x07, 0x05, (addr), (attr), _W0(pktsize), _W1(pktsize), (interval),
#define _CONFIGURATION_TOTAL_LENGTH (9+9+9+2*7)
#define _CONFIGURATION_DESCRIPTORS(hs) \
_CONFIGURATION_DESCRIPTOR(_CONFIGURATION_TOTAL_LENGTH, 1, 1) \
_INTERFACE_DESCRIPTOR(0, 0, 0, 0x99, 0x99, 0x99) \
_INTERFACE_DESCRIPTOR(0, 1, 2, 0x99, 0x99, 0x99) \
_ENDPOINT_DESCRIPTOR(0x01, 0x02, (hs) ? 512 : 64, 0x00) \
_ENDPOINT_DESCRIPTOR(0x82, 0x02, (hs) ? 512 : 64, 0x00)
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
static UCHAR device_framework_full_speed[] = {
_DEVICE_DESCRIPTOR(0x00, 0x00, 0x00, 8, 0x08EC, 0x0001, 1)
_CONFIGURATION_DESCRIPTORS(0)
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
static UCHAR device_framework_high_speed[] = {
_DEVICE_DESCRIPTOR(0x00, 0x00, 0x00, 64, 0x08EC, 0x0001, 1)
_QUALIFIER_DESCRIPTOR(0, 0, 0, 1)
_CONFIGURATION_DESCRIPTORS(1)
};
/* 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 sizeof(string_framework)
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, 0x0c,
0x44, 0x61, 0x74, 0x61, 0x50, 0x75, 0x6d, 0x70,
0x44, 0x65, 0x6d, 0x6f,
/* 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 sizeof(language_id_framework)
static UCHAR language_id_framework[] = {
/* English. */
0x09, 0x04
};
/* Define prototypes for external Host Controller's (HCDs), classes and clients. */
static VOID tx_demo_instance_activate(VOID *dummy_instance);
static VOID tx_demo_instance_deactivate(VOID *dummy_instance);
static VOID tx_demo_instance_change(UX_DEVICE_CLASS_DUMMY *dummy_instance);
#if defined(UX_HOST_STANDALONE)
static UINT tx_demo_host_change_function(ULONG e, UX_HOST_CLASS *c, VOID *p);
#else
#define tx_demo_host_change_function UX_NULL
#endif
UINT ux_hcd_sim_initialize(UX_HCD *hcd);
static TX_THREAD tx_demo_thread_host_simulation;
static TX_THREAD tx_demo_thread_slave_simulation;
static void tx_demo_thread_host_simulation_entry(ULONG);
static void tx_demo_thread_slave_simulation_entry(ULONG);
/* 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)
{
if (expected_error == 0 || error_code != expected_error)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %x\n", __LINE__, system_level, system_context, error_code);
// test_control_return(1);
}
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_class_interface_enumeration_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR *stack_pointer;
CHAR *memory_pointer;
UX_DEVICE_CLASS_DUMMY_PARAMETER parameter;
printf("Running Basic Interface Class Enumeration Test...................... ");
/* Initialize the free memory pointer. */
stack_pointer = (CHAR *) first_unused_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 host portion of USBX. */
status = ux_host_stack_initialize(tx_demo_host_change_function);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Register all the host class drivers for this USBX implementation. */
status = ux_host_stack_class_register(_ux_host_class_dummy_name, _ux_host_class_dummy_entry);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX */
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);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Set the parameters for callback when insertion/extraction of a Data Pump device. */
_ux_utility_memory_set((void *)&parameter, 0x00, sizeof(parameter));
parameter.ux_device_class_dummy_parameter_callbacks.ux_device_class_dummy_instance_activate = tx_demo_instance_activate;
parameter.ux_device_class_dummy_parameter_callbacks.ux_device_class_dummy_instance_deactivate = tx_demo_instance_deactivate;
parameter.ux_device_class_dummy_parameter_callbacks.ux_device_class_dummy_change = tx_demo_instance_change;
/* Initialize the device dpump class. The class is connected with interface 0 */
status = ux_device_stack_class_register(_ux_device_class_dummy_name, _ux_device_class_dummy_entry,
1, 0, &parameter);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
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_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 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);
}
/* Create the main demo thread. */
status = tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0,
stack_pointer + UX_DEMO_STACK_SIZE, 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 UINT ux_demo_dummy_instance_check(VOID)
{
UINT status;
UX_HOST_CLASS *cls;
status = ux_host_stack_class_get(_ux_host_class_dummy_name, &cls);
if (status != UX_SUCCESS)
return(status);
status = ux_host_stack_class_instance_get(cls, 0, (VOID **) &dummy);
if (status != UX_SUCCESS)
return(status);
if (dummy -> ux_host_class_dummy_state != UX_HOST_CLASS_INSTANCE_LIVE)
return(UX_NO_CLASS_MATCH);
return(UX_SUCCESS);
}
static UINT ux_demo_dummy_instance_connect_wait(ULONG wait_ticks)
{
ULONG t0 = tx_time_get(), t1;
while(1)
{
#if defined(UX_HOST_STANDALONE)
ux_system_tasks_run();
#endif
if (UX_SUCCESS == ux_demo_dummy_instance_check())
return(UX_SUCCESS);
tx_thread_relinquish();
/* Wait forever. */
if (wait_ticks == 0xFFFFFFFFul)
continue;
/* No wait. */
if (wait_ticks == 0)
break;
/* Check timeout. */
t1 = tx_time_get();
if (t1 >= t0)
t1 = t1 - t0;
else
t1 = 0xFFFFFFFFul - t0 + t1;
if (t1 > wait_ticks)
break;
}
return(UX_ERROR);
}
static UINT ux_demo_dummy_instance_remove_wait(ULONG wait_ticks)
{
ULONG t0 = tx_time_get(), t1;
while(1)
{
#if defined(UX_HOST_STANDALONE)
ux_system_tasks_run();
#endif
if (UX_SUCCESS != ux_demo_dummy_instance_check())
{
dummy = UX_NULL;
return(UX_SUCCESS);
}
tx_thread_relinquish();
/* Wait forever. */
if (wait_ticks == 0xFFFFFFFFul)
continue;
/* No wait. */
if (wait_ticks == 0)
break;
/* Check timeout. */
t1 = tx_time_get();
if (t1 >= t0)
t1 = t1 - t0;
else
t1 = 0xFFFFFFFFul - t0 + t1;
if (t1 > wait_ticks)
break;
}
return(UX_ERROR);
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_DEVICE *device;
UX_CONFIGURATION *configuration;
UX_INTERFACE *interface;
stepinfo(">>>> Dummy Class Connection Wait\n");
status = ux_demo_dummy_instance_connect_wait(1000);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
stepinfo(">>>> Dummy Class Configuration Deactivate\n");
interface = dummy -> ux_host_class_dummy_interface;
configuration = interface -> ux_interface_configuration;
device = configuration -> ux_configuration_device;
status = ux_host_stack_device_configuration_deactivate(device);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
status = ux_demo_dummy_instance_remove_wait(10);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
stepinfo(">>>> Dummy Class Configuration Activate\n");
status = ux_host_stack_device_configuration_activate(configuration);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
status = ux_demo_dummy_instance_connect_wait(1000);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
#if UX_TEST_MULTI_ALT_ON
stepinfo(">>>> Dummy Class Interface Change\n");
status = _ux_host_class_dummy_select_interface(dummy, 0, 1);
if (status != UX_SUCCESS)
{
printf("ERROR #%d, 0x%x\n", __LINE__, status);
test_control_return(1);
}
status = _ux_host_class_dummy_select_interface(dummy, 0, 0);
if (status != UX_SUCCESS)
{
printf("ERROR #%d, 0x%x\n", __LINE__, status);
test_control_return(1);
}
#endif
expected_error = 0;
/* Sleep for a tick to make sure everything is complete. */
tx_thread_sleep(1);
/* Check for errors from other threads. */
if (error_counter)
{
/* DPUMP error. */
printf("ERROR #%d: total %ld errors\n", __LINE__, error_counter);
test_control_return(1);
}
else
{
/* Successful test. */
printf("SUCCESS!\n");
test_control_return(0);
}
}
static void tx_demo_thread_slave_simulation_entry(ULONG arg)
{
UINT status;
ULONG actual_length;
while(1)
{
#if defined(UX_DEVICE_STANDALONE)
/* Run device tasks. */
ux_system_tasks_run();
#endif
/* Increment thread counter. */
thread_1_counter++;
/* Relinquish to other thread. */
tx_thread_relinquish();
}
}
static VOID tx_demo_instance_activate(VOID *inst)
{
dummy_slave = (UX_DEVICE_CLASS_DUMMY *)inst;
}
static VOID tx_demo_instance_deactivate(VOID *inst)
{
dummy_slave = UX_NULL;
}
static VOID tx_demo_instance_change(UX_DEVICE_CLASS_DUMMY *dummy)
{
UX_PARAMETER_NOT_USED(dummy);
}
#if defined(UX_HOST_STANDALONE)
static UINT tx_demo_host_change_function(ULONG e, UX_HOST_CLASS *c, VOID *p)
{
if (e == UX_STANDALONE_WAIT_BACKGROUND_TASK)
{
tx_thread_relinquish();
}
}
#endif

View File

@ -0,0 +1,561 @@
/* 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 "ux_host_class_dummy.h"
#include "ux_device_class_dummy.h"
#include "ux_test.h"
/* Define USBX demo constants. */
#define UX_DEMO_STACK_SIZE 4096
#define UX_DEMO_BUFFER_SIZE 2048
#define UX_DEMO_RUN 1
#define UX_DEMO_MEMORY_SIZE (64*1024)
/* Define the counters used in the demo application... */
static ULONG thread_0_counter;
static ULONG thread_1_counter;
static ULONG error_counter;
/* Define USBX demo global variables. */
static UX_HOST_CLASS *class_driver;
static UX_HOST_CLASS_DUMMY *dummy;
static UX_DEVICE_CLASS_DUMMY *dummy_slave;
static UINT expected_error;
#define _W0(w) ( (w) & 0xFF)
#define _W1(w) (((w) >> 8) & 0xFF)
#define _DEVICE_DESCRIPTOR(cls, sub, protocol, pktsize, vid, pid, n_cfg) \
0x12, 0x01, 0x10, 0x01, \
(cls), (sub), (protocol), (pktsize), \
_W0(vid), _W1(vid), _W0(pid), _W1(pid), \
0x00, 0x00, 0x00, 0x00, 0x00, (n_cfg),
#define _QUALIFIER_DESCRIPTOR(cls, sub, protocol, n_cfg) \
0x0a, 0x06, 0x00, 0x02, \
(cls), (sub), (protocol), 0x40, (n_cfg), 0x00,
#define _CONFIGURATION_DESCRIPTOR(total_len, n_ifc, cfg_val) \
0x09, 0x02, _W0(total_len), _W1(total_len), (n_ifc), (cfg_val), \
0x00, 0xc0, 0x32,
#define _INTERFACE_DESCRIPTOR(ifc_n, alt, n_ep, cls, sub, protocol) \
0x09, 0x04, (ifc_n), (alt), (n_ep), (cls), (sub), (protocol), 0x00,
#define _ENDPOINT_DESCRIPTOR(addr, attr, pktsize, interval) \
0x07, 0x05, (addr), (attr), _W0(pktsize), _W1(pktsize), (interval),
#define _CONFIGURATION_TOTAL_LENGTH (9+9*3+7*4)
#define _CONFIGURATION_DESCRIPTORS(hs) \
_CONFIGURATION_DESCRIPTOR(_CONFIGURATION_TOTAL_LENGTH, 3, 1) \
_INTERFACE_DESCRIPTOR(0, 0, 1, 0x0E, 0x00, 0x00) \
_ENDPOINT_DESCRIPTOR(0x03, 0x02, 8, 0x04) \
_INTERFACE_DESCRIPTOR(1, 0, 2, 0x99, 0x99, 0x99) \
_ENDPOINT_DESCRIPTOR(0x01, 0x02, (hs) ? 512 : 64, 0x00) \
_ENDPOINT_DESCRIPTOR(0x82, 0x02, (hs) ? 512 : 64, 0x00) \
_INTERFACE_DESCRIPTOR(2, 0, 1, 0x0E, 0x00, 0x00) \
_ENDPOINT_DESCRIPTOR(0x84, 0x02,32, 0x04)
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
static UCHAR device_framework_full_speed[] = {
_DEVICE_DESCRIPTOR(0x00, 0x00, 0x00, 8, 0x08EC, 0x0001, 1)
_CONFIGURATION_DESCRIPTORS(0)
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
static UCHAR device_framework_high_speed[] = {
_DEVICE_DESCRIPTOR(0x00, 0x00, 0x00, 64, 0x08EC, 0x0001, 1)
_QUALIFIER_DESCRIPTOR(0, 0, 0, 1)
_CONFIGURATION_DESCRIPTORS(1)
};
/* 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 sizeof(string_framework)
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, 0x0c,
0x44, 0x61, 0x74, 0x61, 0x50, 0x75, 0x6d, 0x70,
0x44, 0x65, 0x6d, 0x6f,
/* 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 sizeof(language_id_framework)
static UCHAR language_id_framework[] = {
/* English. */
0x09, 0x04
};
static UX_HOST_CLASS_DUMMY_QUERY _accept_0x99_0x99_0x99[] =
{
{.ux_host_class_query_on = UX_TRUE,
.ux_host_class_query_usage = UX_HOST_CLASS_COMMAND_USAGE_CSP,
.ux_host_class_query_class = 0x99,
.ux_host_class_query_subclass = 0x99,
.ux_host_class_query_protocol = 0x99},
{0}
};
/* Define prototypes for external Host Controller's (HCDs), classes and clients. */
static VOID tx_demo_instance_activate(VOID *dummy_instance);
static VOID tx_demo_instance_deactivate(VOID *dummy_instance);
static VOID tx_demo_instance_change(UX_DEVICE_CLASS_DUMMY *dummy_instance);
#if defined(UX_HOST_STANDALONE)
static UINT tx_demo_host_change_function(ULONG e, UX_HOST_CLASS *c, VOID *p);
#else
#define tx_demo_host_change_function UX_NULL
#endif
UINT ux_hcd_sim_initialize(UX_HCD *hcd);
static TX_THREAD tx_demo_thread_host_simulation;
static TX_THREAD tx_demo_thread_slave_simulation;
static void tx_demo_thread_host_simulation_entry(ULONG);
static void tx_demo_thread_slave_simulation_entry(ULONG);
/* 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)
{
if (expected_error == 0 || error_code != expected_error)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %x\n", __LINE__, system_level, system_context, error_code);
// test_control_return(1);
}
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_class_multi_interface_enumeration_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR *stack_pointer;
CHAR *memory_pointer;
UX_DEVICE_CLASS_DUMMY_PARAMETER parameter;
printf("Running Multiple Interface Class Enumeration Test................... ");
/* Initialize the free memory pointer. */
stack_pointer = (CHAR *) first_unused_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 host portion of USBX. */
status = ux_host_stack_initialize(tx_demo_host_change_function);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Register all the host class drivers for this USBX implementation. */
status = ux_host_stack_class_register(_ux_host_class_dummy_name, _ux_host_class_dummy_entry);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX */
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);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Set the parameters for callback when insertion/extraction of a Data Pump device. */
_ux_utility_memory_set((void *)&parameter, 0x00, sizeof(parameter));
parameter.ux_device_class_dummy_parameter_callbacks.ux_device_class_dummy_instance_activate = tx_demo_instance_activate;
parameter.ux_device_class_dummy_parameter_callbacks.ux_device_class_dummy_instance_deactivate = tx_demo_instance_deactivate;
parameter.ux_device_class_dummy_parameter_callbacks.ux_device_class_dummy_change = tx_demo_instance_change;
/* Initialize the device dpump class. The class is connected with interface 0 */
_ux_host_class_dummy_query_reject_unknown_set(UX_TRUE);
_ux_host_class_dummy_query_list_set(_accept_0x99_0x99_0x99);
status = ux_device_stack_class_register(_ux_device_class_dummy_name, _ux_device_class_dummy_entry,
1, 0, &parameter);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
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_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 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);
}
/* Create the main demo thread. */
status = tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0,
stack_pointer + UX_DEMO_STACK_SIZE, 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 UINT ux_demo_dummy_instance_check(VOID)
{
UINT status;
UX_HOST_CLASS *cls;
status = ux_host_stack_class_get(_ux_host_class_dummy_name, &cls);
if (status != UX_SUCCESS)
return(status);
status = ux_host_stack_class_instance_get(cls, 0, (VOID **) &dummy);
if (status != UX_SUCCESS)
return(status);
if (dummy -> ux_host_class_dummy_state != UX_HOST_CLASS_INSTANCE_LIVE)
return(UX_NO_CLASS_MATCH);
return(UX_SUCCESS);
}
static UINT ux_demo_dummy_instance_connect_wait(ULONG wait_ticks)
{
ULONG t0 = tx_time_get(), t1;
while(1)
{
#if defined(UX_HOST_STANDALONE)
ux_system_tasks_run();
#endif
if (UX_SUCCESS == ux_demo_dummy_instance_check())
return(UX_SUCCESS);
tx_thread_relinquish();
/* Wait forever. */
if (wait_ticks == 0xFFFFFFFFul)
continue;
/* No wait. */
if (wait_ticks == 0)
break;
/* Check timeout. */
t1 = tx_time_get();
if (t1 >= t0)
t1 = t1 - t0;
else
t1 = 0xFFFFFFFFul - t0 + t1;
if (t1 > wait_ticks)
break;
}
return(UX_ERROR);
}
static UINT ux_demo_dummy_instance_remove_wait(ULONG wait_ticks)
{
ULONG t0 = tx_time_get(), t1;
while(1)
{
#if defined(UX_HOST_STANDALONE)
ux_system_tasks_run();
#endif
if (UX_SUCCESS != ux_demo_dummy_instance_check())
{
dummy = UX_NULL;
return(UX_SUCCESS);
}
tx_thread_relinquish();
/* Wait forever. */
if (wait_ticks == 0xFFFFFFFFul)
continue;
/* No wait. */
if (wait_ticks == 0)
break;
/* Check timeout. */
t1 = tx_time_get();
if (t1 >= t0)
t1 = t1 - t0;
else
t1 = 0xFFFFFFFFul - t0 + t1;
if (t1 > wait_ticks)
break;
}
return(UX_ERROR);
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_DEVICE *device;
UX_CONFIGURATION *configuration;
UX_INTERFACE *interface_ptr;
UX_ENDPOINT *endpoint;
stepinfo(">>>> Dummy Class Connection Wait\n");
status = ux_demo_dummy_instance_connect_wait(100);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
stepinfo(">>>> Dummy Class Configuration Deactivate\n");
interface_ptr = dummy -> ux_host_class_dummy_interface;
configuration = interface_ptr -> ux_interface_configuration;
device = configuration -> ux_configuration_device;
status = ux_host_stack_device_configuration_deactivate(device);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
status = ux_demo_dummy_instance_remove_wait(10);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
stepinfo(">>>> Dummy Class Configuration Activate\n");
status = ux_host_stack_device_configuration_activate(configuration);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
status = ux_demo_dummy_instance_connect_wait(100);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
#if UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_CONTROL == UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_ALL
stepinfo(">>>> Check physical endpoints (create all)\n");
status = ux_host_stack_configuration_interface_get(configuration, 0, 0, &interface_ptr);
UX_TEST_CHECK_SUCCESS(status);
status = ux_host_stack_interface_endpoint_get(interface_ptr, 0, &endpoint);
UX_TEST_CHECK_SUCCESS(status);
UX_TEST_ASSERT(endpoint -> ux_endpoint_ed != UX_NULL);
status = ux_host_stack_configuration_interface_get(configuration, 1, 0, &interface_ptr);
UX_TEST_CHECK_SUCCESS(status);
status = ux_host_stack_interface_endpoint_get(interface_ptr, 0, &endpoint);
UX_TEST_CHECK_SUCCESS(status);
UX_TEST_ASSERT(endpoint -> ux_endpoint_ed != UX_NULL);
status = ux_host_stack_interface_endpoint_get(interface_ptr, 1, &endpoint);
UX_TEST_CHECK_SUCCESS(status);
UX_TEST_ASSERT(endpoint -> ux_endpoint_ed != UX_NULL);
status = ux_host_stack_configuration_interface_get(configuration, 2, 0, &interface_ptr);
UX_TEST_CHECK_SUCCESS(status);
UX_TEST_CHECK_SUCCESS(status);
status = ux_host_stack_interface_endpoint_get(interface_ptr, 0, &endpoint);
UX_TEST_CHECK_SUCCESS(status);
UX_TEST_ASSERT(endpoint -> ux_endpoint_ed != UX_NULL);
#elif UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_CONTROL == UX_HOST_STACK_CONFIGURATION_INSTANCE_CREATE_OWNED
stepinfo(">>>> Check physical endpoints (create owned)\n");
status = ux_host_stack_configuration_interface_get(configuration, 0, 0, &interface_ptr);
UX_TEST_CHECK_SUCCESS(status);
status = ux_host_stack_interface_endpoint_get(interface_ptr, 0, &endpoint);
UX_TEST_ASSERT(endpoint -> ux_endpoint_ed == UX_NULL);
status = ux_host_stack_configuration_interface_get(configuration, 1, 0, &interface_ptr);
UX_TEST_CHECK_SUCCESS(status);
status = ux_host_stack_interface_endpoint_get(interface_ptr, 0, &endpoint);
UX_TEST_ASSERT(endpoint -> ux_endpoint_ed != UX_NULL);
status = ux_host_stack_interface_endpoint_get(interface_ptr, 1, &endpoint);
UX_TEST_ASSERT(endpoint -> ux_endpoint_ed != UX_NULL);
status = ux_host_stack_configuration_interface_get(configuration, 2, 0, &interface_ptr);
UX_TEST_CHECK_SUCCESS(status);
status = ux_host_stack_interface_endpoint_get(interface_ptr, 0, &endpoint);
UX_TEST_ASSERT(endpoint -> ux_endpoint_ed == UX_NULL);
#endif
expected_error = 0;
/* Sleep for a tick to make sure everything is complete. */
tx_thread_sleep(1);
/* Check for errors from other threads. */
if (error_counter)
{
/* DPUMP error. */
printf("ERROR #%d: total %ld errors\n", __LINE__, error_counter);
test_control_return(1);
}
else
{
/* Successful test. */
printf("SUCCESS!\n");
test_control_return(0);
}
}
static void tx_demo_thread_slave_simulation_entry(ULONG arg)
{
UINT status;
ULONG actual_length;
while(1)
{
#if defined(UX_DEVICE_STANDALONE)
/* Run device tasks. */
ux_system_tasks_run();
#endif
/* Increment thread counter. */
thread_1_counter++;
/* Relinquish to other thread. */
tx_thread_relinquish();
}
}
static VOID tx_demo_instance_activate(VOID *inst)
{
dummy_slave = (UX_DEVICE_CLASS_DUMMY *)inst;
}
static VOID tx_demo_instance_deactivate(VOID *inst)
{
dummy_slave = UX_NULL;
}
static VOID tx_demo_instance_change(UX_DEVICE_CLASS_DUMMY *dummy)
{
UX_PARAMETER_NOT_USED(dummy);
}
#if defined(UX_HOST_STANDALONE)
static UINT tx_demo_host_change_function(ULONG e, UX_HOST_CLASS *c, VOID *p)
{
if (e == UX_STANDALONE_WAIT_BACKGROUND_TASK)
{
tx_thread_relinquish();
}
}
#endif

View File

@ -0,0 +1,852 @@
/* 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_class_printer.h"
#include "ux_device_stack.h"
#include "ux_host_class_printer.h"
#include "ux_test_dcd_sim_slave.h"
#include "ux_test_hcd_sim_host.h"
#include "ux_test_utility_sim.h"
/* Define constants. */
#define UX_DEMO_DEBUG_SIZE (4096*8)
#define UX_DEMO_STACK_SIZE 1024
#define UX_DEMO_BUFFER_SIZE (UX_SLAVE_REQUEST_DATA_MAX_LENGTH + 1)
#define UX_DEMO_XMIT_BUFFER_SIZE 512
#define UX_DEMO_RECEPTION_BUFFER_SIZE 512
#define UX_DEMO_FILE_BUFFER_SIZE 512
#define UX_DEMO_RECEPTION_BLOCK_SIZE 64
#define UX_DEMO_MEMORY_SIZE (64*1024)
#define UX_DEMO_FILE_SIZE (128 * 1024)
#define UX_RAM_DISK_MEMORY (256 * 1024)
/* Define local/extern function prototypes. */
static VOID test_thread_entry(ULONG);
static TX_THREAD tx_test_thread_host_simulation;
static TX_THREAD tx_test_thread_slave_simulation;
static VOID tx_test_thread_host_simulation_entry(ULONG);
static VOID tx_test_thread_slave_simulation_entry(ULONG);
static TX_THREAD tx_test_thread_printer_read;
static TX_THREAD tx_test_thread_printer_write;
static TX_SEMAPHORE tx_test_semaphore_printer_trigger;
static VOID tx_test_printer_read_entry(ULONG);
static VOID tx_test_printer_write_entry(ULONG);
static VOID ux_test_hcd_entry_should_not_be_called(UX_TEST_ACTION *action, VOID *params);
static VOID ux_test_hcd_entry_disconnect(UX_TEST_ACTION *action, VOID *params);
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 UX_DEVICE *device = UX_NULL;
static UX_HOST_CLASS_PRINTER *host_printer = UX_NULL;
static UCHAR host_buffer[UX_DEMO_BUFFER_SIZE * 8];
static ULONG enum_counter;
static ULONG error_counter;
static ULONG error_callback_counter;
static ULONG set_cfg_counter;
static ULONG rsc_mem_alloc_cnt_on_set_cfg;
static ULONG rsc_mem_free_on_set_cfg;
static ULONG rsc_sem_on_set_cfg;
static ULONG rsc_sem_get_on_set_cfg;
static ULONG rsc_mutex_on_set_cfg;
static ULONG rsc_enum_sem_usage;
static ULONG rsc_enum_sem_get_count;
static ULONG rsc_enum_mutex_usage;
static ULONG rsc_enum_mem_usage;
static ULONG rsc_enum_mem_alloc_count;
static ULONG rsc_test_sem_usage;
static ULONG rsc_test_sem_get_count;
static ULONG rsc_test_mutex_usage;
static ULONG rsc_test_mem_alloc_count;
static UX_DEVICE_CLASS_PRINTER *device_printer = UX_NULL;
static UX_DEVICE_CLASS_PRINTER_PARAMETER device_printer_parameter;
static UCHAR device_buffer[UX_DEMO_BUFFER_SIZE * 8];
static ULONG device_buffer_length = 0;
static UCHAR device_printer_soft_reset_count = 0;
/* Device printer device ID. */
static UCHAR printer_device_id[] =
{
" " // Will be replaced by length (big endian)
"MFG:Generic;" // manufacturer (case sensitive)
"MDL:Generic_/_Text_Only;" // model (case sensitive)
"CMD:1284.4;" // PDL command set
"CLS:PRINTER;" // class
"DES:Generic text only printer;" // description
};
/* Define device framework. */
#define _W0(w) ( (w) & 0xFF)
#define _W1(w) (((w) >> 8) & 0xFF)
#define _CONFIGURATION_DESCRIPTOR(total_len, n_ifc, cfg_val) \
0x09, 0x02, _W0(total_len), _W1(total_len), (n_ifc), (cfg_val), \
0x00, 0xc0, 0x32,
#define _INTERFACE_DESCRIPTOR(ifc_n, alt, n_ep, cls, sub, protocol) \
0x09, 0x04, (ifc_n), (alt), (n_ep), (cls), (sub), (protocol), 0x00,
#define _ENDPOINT_DESCRIPTOR(addr, attr, pktsize, interval) \
0x07, 0x05, (addr), (attr), _W0(pktsize), _W1(pktsize), (interval),
#define _CFG_TOTAL_LEN (9+9+7+7)
#define STRING_FRAMEWORK_LENGTH 47
#define LANGUAGE_ID_FRAMEWORK_LENGTH 2
static unsigned char device_framework_full_speed[] = {
/* Device descriptor 18 bytes
0xEF bDeviceClass: Composite class code
0x02 bDeviceSubclass: class sub code
0x00 bDeviceProtocol: Device protocol
idVendor & idProduct - http://www.linux-usb.org/usb.ids
*/
0x12, 0x01, 0x10, 0x01,
0x00, 0x00, 0x00,
0x08,
0x84, 0x84, 0x00, 0x00,
0x00, 0x01,
0x01, 0x02, 0x03,
0x01,
_CONFIGURATION_DESCRIPTOR(_CFG_TOTAL_LEN, 1, 1)
_INTERFACE_DESCRIPTOR(0, 0, 2, 0x07, 0x01, 0x02)
_ENDPOINT_DESCRIPTOR(0x01, 0x02, 64, 0x00)
_ENDPOINT_DESCRIPTOR(0x82, 0x02, 64, 0x00)
};
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_full_speed)
#define device_framework_high_speed device_framework_full_speed
static unsigned char string_framework[] = {
/* Manufacturer string descriptor : Index 1 - "AzureRTOS" */
0x09, 0x04, 0x01, 9,
'A','z','u','r','e','R','T','O','S',
/* Product string descriptor : Index 2 - "Printer device" */
0x09, 0x04, 0x02, 14,
'P','r','i','n','t','e','r',' ','d','e','v','i','c','e',
/* Serial Number string descriptor : Index 3 - "0001" */
0x09, 0x04, 0x03, 0x04,
0x30, 0x30, 0x30, 0x31
};
/* Multiple languages are supported on the device, to add
a language besides english, the unicode language code must
be appended to the language_id_framework array and the length
adjusted accordingly. */
static unsigned char language_id_framework[] = {
/* English. */
0x09, 0x04
};
static UX_TEST_SETUP _SetConfigure = UX_TEST_SETUP_SetConfigure;
/* Test interactions */
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 }
};
/* 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 UINT test_slave_change_function(ULONG change)
{
return 0;
}
static UINT test_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
{
UX_HOST_CLASS_PRINTER *printer_inst = (UX_HOST_CLASS_PRINTER *) inst;
switch(event)
{
case UX_DEVICE_INSERTION:
host_printer = printer_inst;
break;
case UX_DEVICE_REMOVAL:
if (host_printer == printer_inst)
host_printer = UX_NULL;
break;
case UX_DEVICE_CONNECTION:
device = (UX_DEVICE *)inst;
break;
case UX_DEVICE_DISCONNECTION:
if ((VOID *)device == inst)
device = UX_NULL;
break;
#if defined(UX_HOST_STANDALONE)
case UX_STANDALONE_WAIT_BACKGROUND_TASK:
tx_thread_relinquish();
break;
#endif
default:
break;
}
return 0;
}
static VOID test_printer_instance_activate(VOID *dummy_instance)
{
if (device_printer == UX_NULL)
device_printer = (UX_DEVICE_CLASS_PRINTER *)dummy_instance;
}
static VOID test_printer_instance_deactivate(VOID *dummy_instance)
{
if ((VOID*)device_printer == dummy_instance)
device_printer = UX_NULL;
}
static VOID test_printer_soft_reset(VOID *dummy_instance)
{
device_printer_soft_reset_count ++;
}
static VOID test_ux_error_callback(UINT system_level, UINT system_context, UINT error_code)
{
error_callback_counter ++;
}
static VOID ux_test_hcd_entry_set_cfg(UX_TEST_ACTION *action, VOID *params)
{
set_cfg_counter ++;
rsc_mem_free_on_set_cfg = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
rsc_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_enum_sem_get_count = 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_host_class_printer_basic_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
printf("Running Printer Basic Functionality Test............................ ");
/* 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 * 4);
/* 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 #1\n");
test_control_return(1);
}
/* Register the error callback. */
_ux_utility_error_callback_register(test_ux_error_callback);
/* The code below is required for installing the host portion of USBX */
status = ux_host_stack_initialize(test_host_change_function);
if (status != UX_SUCCESS)
{
printf(" ERROR #2\n");
test_control_return(1);
}
/* Register CDC-ACM class. */
status = ux_host_stack_class_register(_ux_system_host_class_printer_name, _ux_host_class_printer_entry);
if (status != UX_SUCCESS)
{
printf(" ERROR #3\n");
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,
test_slave_change_function);
if(status!=UX_SUCCESS)
{
printf(" ERROR #5\n");
test_control_return(1);
}
/* Set the parameters for callback when insertion/extraction of a printer device. */
_ux_utility_memory_set(&device_printer_parameter, 0, sizeof(device_printer_parameter));
_ux_utility_short_put_big_endian(printer_device_id, sizeof(printer_device_id));
device_printer_parameter.ux_device_class_printer_device_id = printer_device_id;
device_printer_parameter.ux_device_class_printer_instance_activate = test_printer_instance_activate;
device_printer_parameter.ux_device_class_printer_instance_deactivate = test_printer_instance_deactivate;
device_printer_parameter.ux_device_class_printer_soft_reset = test_printer_soft_reset;
/* Initialize the device cdc class. This class owns both interfaces starting with 0. */
status = ux_device_stack_class_register(_ux_system_device_class_printer_name,
ux_device_class_printer_entry,
1, 0, &device_printer_parameter);
/* Initialize the simulated device controller. */
status = _ux_test_dcd_sim_slave_initialize();
/* Check for error. */
if (status != TX_SUCCESS)
{
printf(" ERROR #8\n");
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);
if (status != UX_SUCCESS)
{
printf(" ERROR #4\n");
test_control_return(1);
}
/* Create the main host simulation thread. */
status = tx_thread_create(&tx_test_thread_host_simulation, "tx test host simulation", tx_test_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 #9\n");
test_control_return(1);
}
/* Create the main slave simulation thread. */
stack_pointer += UX_DEMO_STACK_SIZE;
status = tx_thread_create(&tx_test_thread_slave_simulation, "tx test slave simulation", tx_test_thread_slave_simulation_entry, 0,
stack_pointer, UX_DEMO_STACK_SIZE,
20, 20, 1, TX_AUTO_START);
/* Check for error. */
if (status != TX_SUCCESS)
{
printf(" ERROR #10\n");
test_control_return(1);
}
/* Create the device printer read thread. */
stack_pointer += UX_DEMO_STACK_SIZE;
status = tx_thread_create(&tx_test_thread_printer_read, "tx test printer read",
tx_test_printer_read_entry, UX_TRUE,
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);
}
/* Create the device printer write thread. */
stack_pointer += UX_DEMO_STACK_SIZE;
status = tx_thread_create(&tx_test_thread_printer_write, "tx test printer write",
tx_test_printer_write_entry, UX_FALSE,
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);
}
/* Create the device printer write trigger. */
status = tx_semaphore_create(&tx_test_semaphore_printer_trigger,
"tx test printer trigger",
0);
/* Check for error. */
if (status != TX_SUCCESS)
{
printf(" ERROR #%d\n", __LINE__);
test_control_return(1);
}
}
static UINT _test_check_host_connection_error(VOID)
{
if (device_printer && host_printer)
return(UX_SUCCESS);
if (error_callback_counter >= 3)
return(UX_SUCCESS);
return(UX_ERROR);
}
static UINT _test_check_host_connection_success(VOID)
{
if (device_printer && host_printer)
return(UX_SUCCESS);
return(UX_ERROR);
}
static UINT _test_check_host_disconnection_success(VOID)
{
if (device_printer == UX_NULL && host_printer == UX_NULL)
return(UX_SUCCESS);
return(UX_ERROR);
}
static VOID _printer_enumeration_test(VOID)
{
UINT status;
ULONG mem_free;
ULONG test_n;
stepinfo(">>>>>>>>>>>> Enumeration information collection\n");
{
/* Test disconnect. */
ux_test_dcd_sim_slave_disconnect();
ux_test_hcd_sim_host_disconnect();
/* Check connection. */
status = ux_test_sleep_break_on_success(100, _test_check_host_disconnection_success);
UX_TEST_ASSERT(status == UX_SUCCESS);
/* 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 = ux_test_sleep_break_on_success(100, _test_check_host_connection_success);
UX_TEST_ASSERT(status == UX_SUCCESS);
/* 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_test_mutex_usage = ux_test_utility_sim_mutex_create_count() - rsc_enum_mutex_usage;
rsc_test_sem_usage = ux_test_utility_sim_sem_create_count() - rsc_enum_sem_usage;
rsc_test_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("test mem : %ld\n", rsc_test_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);
}
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 */
status = ux_test_sleep_break_on_success(100, _test_check_host_disconnection_success);
if (status != 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;
status = ux_test_sleep_break_on_success(100, _test_check_host_connection_error);
/* Check */
if (status != UX_SUCCESS)
{
printf("ERROR #%d.%ld: Enumeration fail\n", __LINE__, test_n);
test_control_return(1);
}
}
stepinfo("\n");
if (rsc_test_mem_alloc_count) stepinfo(">>>>>>>>>>>> Memory errors enumeration test\n");
mem_free = (~0);
for (test_n = 0; test_n < rsc_test_mem_alloc_count; test_n ++)
{
stepinfo("%4ld / %4ld\n", test_n, rsc_test_mem_alloc_count - 1);
/* Disconnect. */
ux_test_dcd_sim_slave_disconnect();
ux_test_hcd_sim_host_disconnect();
/* Check */
status = ux_test_sleep_break_on_success(100, _test_check_host_disconnection_success);
if (status != UX_SUCCESS)
{
stepinfo("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)
{
stepinfo("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. */
status = ux_test_sleep_break_on_success(100, _test_check_host_connection_error);
/* Check error */
if (status != UX_SUCCESS)
{
/* Check error trap. */
if (error_callback_counter == 0)
{
stepinfo("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_test_mem_alloc_count) stepinfo("\n");
/* If device disconnected, re-connect. */
if (_test_check_host_connection_success() != UX_SUCCESS)
{
ux_test_dcd_sim_slave_disconnect();
ux_test_hcd_sim_host_disconnect();
ux_test_dcd_sim_slave_connect(UX_HIGH_SPEED_DEVICE);
ux_test_hcd_sim_host_connect(UX_HIGH_SPEED_DEVICE);
/* Check */
status = ux_test_sleep_break_on_success(100, _test_check_host_connection_success);
if (status != UX_SUCCESS)
{
printf("ERROR #%d: Enumeration fail\n", __LINE__);
test_control_return(1);
}
}
}
static VOID _printer_requests_test(VOID)
{
UINT status;
ULONG printer_port_status;
stepinfo(">>>>>>>>>>>>>>>> Test GET_DEVICE_ID\n");
status = ux_host_class_printer_device_id_get(host_printer, host_buffer, sizeof(host_buffer));
UX_TEST_ASSERT(status == UX_SUCCESS);
stepinfo(">>>>>>>>>>>>>>>> Test GET_PORT_STATUS\n");
ux_device_class_printer_ioctl(device_printer, UX_DEVICE_CLASS_PRINTER_IOCTL_PORT_STATUS_SET, (VOID *)0x73);
status = ux_host_class_printer_status_get(host_printer, &printer_port_status);
UX_TEST_ASSERT(status == UX_SUCCESS);
UX_TEST_ASSERT(printer_port_status == 0x73);
stepinfo(">>>>>>>>>>>>>>>> Test SOFT_RESET\n");
device_printer_soft_reset_count = 0;
status = ux_host_class_printer_soft_reset(host_printer);
UX_TEST_ASSERT(status == UX_SUCCESS);
UX_TEST_ASSERT(device_printer_soft_reset_count == 1);
}
void tx_test_printer_read_entry(ULONG arg)
{
UINT status;
ULONG actual_length;
while(1)
{
if (device_printer == UX_NULL)
{
tx_thread_sleep(10);
continue;
}
status = ux_device_class_printer_read(device_printer, device_buffer, sizeof(device_buffer), &actual_length);
/* Endpoint not ready. */
if (status == UX_TRANSFER_BUS_RESET ||
status == UX_TRANSFER_NO_ANSWER)
{
tx_thread_sleep(10);
continue;
}
device_buffer_length = actual_length;
UX_TEST_ASSERT_MESSAGE(status == UX_SUCCESS, "#%d status 0x%x\n", __LINE__, status);
}
}
void tx_test_printer_write_entry(ULONG arg)
{
UINT status;
ULONG send_total;
while(1)
{
/* Wait a trigger. */
status = tx_semaphore_get(&tx_test_semaphore_printer_trigger, TX_WAIT_FOREVER);
if (status != TX_SUCCESS || device_printer == UX_NULL)
{
tx_thread_sleep(10);
continue;
}
/* Send device_buffer_length. */
status = ux_device_class_printer_write(device_printer, device_buffer, device_buffer_length, &send_total);
UX_TEST_ASSERT(status == UX_SUCCESS);
UX_TEST_ASSERT(device_buffer_length == send_total);
}
}
static VOID _printer_read_write_test(VOID)
{
struct _TEST_DEF {
ULONG fill;
ULONG length;
ULONG zlp;
} tests[] = {
{0x5A, 1, 0},
{0x7E, 512, 1},
{0xC2, 513, 0},
{0x4C, UX_SLAVE_REQUEST_DATA_MAX_LENGTH, 1},
{0xA5, UX_SLAVE_REQUEST_DATA_MAX_LENGTH + 1, 0},
{0x3C, sizeof(device_buffer), 0},
{0xC4, sizeof(device_buffer) - 1, 0},
};
#define _TEST_N (sizeof(tests)/sizeof(struct _TEST_DEF))
INT i;
ULONG actual_length;
UINT status;
for(i = 0; i < _TEST_N; i ++)
{
stepinfo(">>>>>>>>>>>>>>>> Test Write %ld\n", tests[i].length);
device_buffer_length = 0;
ux_utility_memory_set(device_buffer, ~tests[i].fill, tests[i].length);
ux_utility_memory_set(host_buffer, tests[i].fill, tests[i].length);
status = ux_host_class_printer_write(host_printer, host_buffer, tests[i].length, &actual_length);
UX_TEST_ASSERT(status == UX_SUCCESS);
UX_TEST_ASSERT(tests[i].length == actual_length);
if (tests[i].zlp)
{
status = ux_host_class_printer_write(host_printer, host_buffer, 0, &actual_length);
UX_TEST_ASSERT(status == UX_SUCCESS);
UX_TEST_ASSERT(0 == actual_length);
}
UX_TEST_ASSERT(device_buffer_length == tests[i].length);
status = ux_utility_memory_compare(device_buffer, host_buffer, tests[i].length);
UX_TEST_ASSERT(status == UX_SUCCESS);
stepinfo(">>>>>>>>>>>>>>>> Test Read %ld\n", tests[i].length);
status = tx_semaphore_put(&tx_test_semaphore_printer_trigger);
UX_TEST_ASSERT(status == TX_SUCCESS);
ux_utility_memory_set(host_buffer, ~tests[i].fill, tests[i].length);
status = ux_host_class_printer_read(host_printer, host_buffer, tests[i].length, &actual_length);
UX_TEST_ASSERT(status == UX_SUCCESS);
UX_TEST_ASSERT(tests[i].length == actual_length);
UX_TEST_ASSERT(host_buffer[0] == tests[i].fill);
UX_TEST_ASSERT(host_buffer[tests[i].length - 1] == tests[i].fill);
#if defined(UX_DEVICE_CLASS_PRINTER_WRITE_AUTO_ZLP)
stepinfo(">>>>>>>>>>>>>>>> Test Read (Device Write) with auto ZLP %ld\n", tests[i].length);
status = tx_semaphore_put(&tx_test_semaphore_printer_trigger);
UX_TEST_CHECK_SUCCESS(status);
ux_utility_memory_set(host_buffer, ~tests[i].fill, tests[i].length);
status = ux_host_class_printer_read(host_printer, host_buffer, sizeof(host_buffer), &actual_length);
if (actual_length == 0) /* There could be ZLP. */
status = ux_host_class_printer_read(host_printer, host_buffer, sizeof(host_buffer), &actual_length);
UX_TEST_CHECK_SUCCESS(status);
UX_TEST_ASSERT(tests[i].length == actual_length);
UX_TEST_ASSERT(host_buffer[0] == tests[i].fill);
UX_TEST_ASSERT(host_buffer[tests[i].length - 1] == tests[i].fill);
#endif
}
}
void tx_test_thread_host_simulation_entry(ULONG arg)
{
UINT status;
ULONG test_n;
ULONG mem_free;
ULONG loop;
ULONG parameter_u32[64/4];
USHORT *parameter_u16 = (USHORT*)parameter_u32;
UCHAR *parameter_u8 = (UCHAR*)parameter_u32;
stepinfo("\n");
stepinfo(">>>>>>>>>>>>>>>> Test connect\n");
ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
status = ux_test_sleep_break_on_success(100, _test_check_host_connection_success);
UX_TEST_ASSERT(status == UX_SUCCESS);
_printer_enumeration_test();
_printer_requests_test();
_printer_read_write_test();
/* Test disconnect. */
stepinfo(">>>>>>>>>>>>>>>> Test disconnect\n");
ux_test_dcd_sim_slave_disconnect();
ux_test_hcd_sim_host_disconnect();
if (host_printer != UX_NULL)
{
printf("ERROR #13: instance not removed when disconnect");
test_control_return(1);
}
/* Finally disconnect the device. */
ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_device_class_printer_name, _ux_device_class_printer_entry);
/* Deinitialize the device side of usbx. */
_ux_device_stack_uninitialize();
/* And finally the usbx system resources. */
_ux_system_uninitialize();
/* Successful test. */
printf("SUCCESS!\n");
test_control_return(0);
}
void tx_test_thread_slave_simulation_entry(ULONG arg)
{
while(1)
{
#if defined(UX_DEVICE_STANDALONE)
ux_system_tasks_run();
tx_thread_relinquish();
#else
/* Sleep so ThreadX on Win32 will delete this thread. */
tx_thread_sleep(10);
#endif
}
}

View File

@ -0,0 +1,837 @@
/* 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_class_printer.h"
#include "ux_device_stack.h"
#include "ux_host_class_printer.h"
#include "ux_test_dcd_sim_slave.h"
#include "ux_test_hcd_sim_host.h"
#include "ux_test_utility_sim.h"
/* Define constants. */
#define UX_DEMO_DEBUG_SIZE (4096*8)
#define UX_DEMO_STACK_SIZE 1024
#define UX_DEMO_BUFFER_SIZE (UX_SLAVE_REQUEST_DATA_MAX_LENGTH + 1)
#define UX_DEMO_XMIT_BUFFER_SIZE 512
#define UX_DEMO_RECEPTION_BUFFER_SIZE 512
#define UX_DEMO_FILE_BUFFER_SIZE 512
#define UX_DEMO_RECEPTION_BLOCK_SIZE 64
#define UX_DEMO_MEMORY_SIZE (64*1024)
#define UX_DEMO_FILE_SIZE (128 * 1024)
#define UX_RAM_DISK_MEMORY (256 * 1024)
/* Define local/extern function prototypes. */
static VOID test_thread_entry(ULONG);
static TX_THREAD tx_test_thread_host_simulation;
static TX_THREAD tx_test_thread_slave_simulation;
static VOID tx_test_thread_host_simulation_entry(ULONG);
static VOID tx_test_thread_slave_simulation_entry(ULONG);
static VOID ux_test_hcd_entry_should_not_be_called(UX_TEST_ACTION *action, VOID *params);
static VOID ux_test_hcd_entry_disconnect(UX_TEST_ACTION *action, VOID *params);
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 UX_DEVICE *device = UX_NULL;
static UX_HOST_CLASS_PRINTER *host_printer = UX_NULL;
static UCHAR host_buffer[UX_DEMO_BUFFER_SIZE * 8];
static ULONG enum_counter;
static ULONG error_counter;
static ULONG error_callback_counter;
static ULONG set_cfg_counter;
static ULONG rsc_mem_alloc_cnt_on_set_cfg;
static ULONG rsc_mem_free_on_set_cfg;
static ULONG rsc_sem_on_set_cfg;
static ULONG rsc_sem_get_on_set_cfg;
static ULONG rsc_mutex_on_set_cfg;
static ULONG rsc_enum_sem_usage;
static ULONG rsc_enum_sem_get_count;
static ULONG rsc_enum_mutex_usage;
static ULONG rsc_enum_mem_usage;
static ULONG rsc_enum_mem_alloc_count;
static ULONG rsc_test_sem_usage;
static ULONG rsc_test_sem_get_count;
static ULONG rsc_test_mutex_usage;
static ULONG rsc_test_mem_alloc_count;
static UX_DEVICE_CLASS_PRINTER *device_printer = UX_NULL;
static UX_DEVICE_CLASS_PRINTER_PARAMETER device_printer_parameter;
static UCHAR device_buffer[UX_DEMO_BUFFER_SIZE * 8];
static ULONG device_buffer_length = 0;
static UCHAR device_printer_soft_reset_count = 0;
static ULONG device_read_length = UX_SLAVE_REQUEST_DATA_MAX_LENGTH;
UCHAR _ux_device_class_printer_name[] = "_ux_device_class_printer";
/* Device printer device ID. */
static UCHAR printer_device_id[] =
{
" " // Will be replaced by length (big endian)
"MFG:Generic;" // manufacturer (case sensitive)
"MDL:Generic_/_Text_Only;" // model (case sensitive)
"CMD:1284.4;" // PDL command set
"CLS:PRINTER;" // class
"DES:Generic text only printer;" // description
};
/* Define device framework. */
#define _W0(w) ( (w) & 0xFF)
#define _W1(w) (((w) >> 8) & 0xFF)
#define _CONFIGURATION_DESCRIPTOR(total_len, n_ifc, cfg_val) \
0x09, 0x02, _W0(total_len), _W1(total_len), (n_ifc), (cfg_val), \
0x00, 0xc0, 0x32,
#define _INTERFACE_DESCRIPTOR(ifc_n, alt, n_ep, cls, sub, protocol) \
0x09, 0x04, (ifc_n), (alt), (n_ep), (cls), (sub), (protocol), 0x00,
#define _ENDPOINT_DESCRIPTOR(addr, attr, pktsize, interval) \
0x07, 0x05, (addr), (attr), _W0(pktsize), _W1(pktsize), (interval),
#define _CFG_TOTAL_LEN (9+9+7+7)
#define STRING_FRAMEWORK_LENGTH 47
#define LANGUAGE_ID_FRAMEWORK_LENGTH 2
static unsigned char device_framework_full_speed[] = {
/* Device descriptor 18 bytes
0xEF bDeviceClass: Composite class code
0x02 bDeviceSubclass: class sub code
0x00 bDeviceProtocol: Device protocol
idVendor & idProduct - http://www.linux-usb.org/usb.ids
*/
0x12, 0x01, 0x10, 0x01,
0x00, 0x00, 0x00,
0x08,
0x84, 0x84, 0x00, 0x00,
0x00, 0x01,
0x01, 0x02, 0x03,
0x01,
_CONFIGURATION_DESCRIPTOR(_CFG_TOTAL_LEN, 1, 1)
_INTERFACE_DESCRIPTOR(0, 0, 2, 0x07, 0x01, 0x02)
_ENDPOINT_DESCRIPTOR(0x01, 0x02, 64, 0x00)
_ENDPOINT_DESCRIPTOR(0x82, 0x02, 64, 0x00)
};
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_full_speed)
#define device_framework_high_speed device_framework_full_speed
static unsigned char string_framework[] = {
/* Manufacturer string descriptor : Index 1 - "AzureRTOS" */
0x09, 0x04, 0x01, 9,
'A','z','u','r','e','R','T','O','S',
/* Product string descriptor : Index 2 - "Printer device" */
0x09, 0x04, 0x02, 14,
'P','r','i','n','t','e','r',' ','d','e','v','i','c','e',
/* Serial Number string descriptor : Index 3 - "0001" */
0x09, 0x04, 0x03, 0x04,
0x30, 0x30, 0x30, 0x31
};
/* Multiple languages are supported on the device, to add
a language besides english, the unicode language code must
be appended to the language_id_framework array and the length
adjusted accordingly. */
static unsigned char language_id_framework[] = {
/* English. */
0x09, 0x04
};
static UX_TEST_SETUP _SetConfigure = UX_TEST_SETUP_SetConfigure;
/* Test interactions */
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 }
};
/* 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 UINT test_slave_change_function(ULONG change)
{
return 0;
}
static UINT test_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
{
UX_HOST_CLASS_PRINTER *printer_inst = (UX_HOST_CLASS_PRINTER *) inst;
switch(event)
{
case UX_DEVICE_INSERTION:
host_printer = printer_inst;
break;
case UX_DEVICE_REMOVAL:
if (host_printer == printer_inst)
host_printer = UX_NULL;
break;
case UX_DEVICE_CONNECTION:
device = (UX_DEVICE *)inst;
break;
case UX_DEVICE_DISCONNECTION:
if ((VOID *)device == inst)
device = UX_NULL;
break;
#if defined(UX_HOST_STANDALONE)
case UX_STANDALONE_WAIT_BACKGROUND_TASK:
tx_thread_relinquish();
break;
#endif
default:
break;
}
return 0;
}
static VOID test_printer_instance_activate(VOID *dummy_instance)
{
if (device_printer == UX_NULL)
device_printer = (UX_DEVICE_CLASS_PRINTER *)dummy_instance;
}
static VOID test_printer_instance_deactivate(VOID *dummy_instance)
{
if ((VOID*)device_printer == dummy_instance)
device_printer = UX_NULL;
}
static VOID test_printer_soft_reset(VOID *dummy_instance)
{
device_printer_soft_reset_count ++;
}
static VOID test_ux_error_callback(UINT system_level, UINT system_context, UINT error_code)
{
error_callback_counter ++;
}
static VOID ux_test_hcd_entry_set_cfg(UX_TEST_ACTION *action, VOID *params)
{
set_cfg_counter ++;
rsc_mem_free_on_set_cfg = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
rsc_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_enum_sem_get_count = 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_class_printer_device_standalone_basic_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
printf("Running Host Class Printer Basic Functionality Test................. \n");
/* 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 * 4);
/* 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 #1\n");
test_control_return(1);
}
/* Register the error callback. */
_ux_utility_error_callback_register(test_ux_error_callback);
/* The code below is required for installing the host portion of USBX */
status = ux_host_stack_initialize(test_host_change_function);
if (status != UX_SUCCESS)
{
printf(" ERROR #2\n");
test_control_return(1);
}
/* Register CDC-ACM class. */
status = ux_host_stack_class_register(_ux_system_host_class_printer_name, ux_host_class_printer_entry);
if (status != UX_SUCCESS)
{
printf(" ERROR #3\n");
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,
test_slave_change_function);
if(status!=UX_SUCCESS)
{
printf(" ERROR #5\n");
test_control_return(1);
}
/* Set the parameters for callback when insertion/extraction of a printer device. */
_ux_utility_memory_set(&device_printer_parameter, 0, sizeof(device_printer_parameter));
_ux_utility_short_put_big_endian(printer_device_id, sizeof(printer_device_id));
device_printer_parameter.ux_device_class_printer_device_id = printer_device_id;
device_printer_parameter.ux_device_class_printer_instance_activate = test_printer_instance_activate;
device_printer_parameter.ux_device_class_printer_instance_deactivate = test_printer_instance_deactivate;
device_printer_parameter.ux_device_class_printer_soft_reset = test_printer_soft_reset;
/* Initialize the device cdc class. This class owns both interfaces starting with 0. */
status = ux_device_stack_class_register(_ux_device_class_printer_name,
_ux_device_class_printer_entry,
1, 0, &device_printer_parameter);
/* Initialize the simulated device controller. */
status = _ux_test_dcd_sim_slave_initialize();
/* Check for error. */
if (status != TX_SUCCESS)
{
printf(" ERROR #8\n");
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);
if (status != UX_SUCCESS)
{
printf(" ERROR #4\n");
test_control_return(1);
}
/* Create the main host simulation thread. */
status = tx_thread_create(&tx_test_thread_host_simulation, "tx test host simulation", tx_test_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 #9\n");
test_control_return(1);
}
/* Create the main slave simulation thread. */
stack_pointer += UX_DEMO_STACK_SIZE;
status = tx_thread_create(&tx_test_thread_slave_simulation, "tx test slave simulation", tx_test_thread_slave_simulation_entry, 0,
stack_pointer, UX_DEMO_STACK_SIZE,
20, 20, 1, TX_AUTO_START);
/* Check for error. */
if (status != TX_SUCCESS)
{
printf(" ERROR #10\n");
test_control_return(1);
}
}
static UINT _test_check_host_connection_error(VOID)
{
if (device_printer && host_printer)
return(UX_SUCCESS);
if (error_callback_counter >= 3)
return(UX_SUCCESS);
return(UX_ERROR);
}
static UINT _test_check_host_connection_success(VOID)
{
if (device_printer && host_printer)
return(UX_SUCCESS);
return(UX_ERROR);
}
static UINT _test_check_host_disconnection_success(VOID)
{
if (device_printer == UX_NULL && host_printer == UX_NULL)
return(UX_SUCCESS);
return(UX_ERROR);
}
static VOID _printer_enumeration_test(VOID)
{
UINT status;
ULONG mem_free;
ULONG test_n;
stepinfo(">>>>>>>>>>>> Enumeration information collection\n");
{
/* Test disconnect. */
ux_test_dcd_sim_slave_disconnect();
ux_test_hcd_sim_host_disconnect();
/* Check connection. */
status = ux_test_sleep_break_on_success(100, _test_check_host_disconnection_success);
UX_TEST_ASSERT(status == UX_SUCCESS);
/* 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 = ux_test_sleep_break_on_success(100, _test_check_host_connection_success);
UX_TEST_ASSERT(status == UX_SUCCESS);
/* 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_test_mutex_usage = ux_test_utility_sim_mutex_create_count() - rsc_enum_mutex_usage;
rsc_test_sem_usage = ux_test_utility_sim_sem_create_count() - rsc_enum_sem_usage;
rsc_test_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("test mem : %ld\n", rsc_test_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);
}
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 */
status = ux_test_sleep_break_on_success(100, _test_check_host_disconnection_success);
if (status != 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;
status = ux_test_sleep_break_on_success(100, _test_check_host_connection_error);
/* Check */
if (status != UX_SUCCESS)
{
printf("ERROR #%d.%ld: Enumeration fail\n", __LINE__, test_n);
test_control_return(1);
}
}
stepinfo("\n");
if (rsc_test_mem_alloc_count) stepinfo(">>>>>>>>>>>> Memory errors enumeration test\n");
mem_free = (~0);
for (test_n = 0; test_n < rsc_test_mem_alloc_count; test_n ++)
{
stepinfo("%4ld / %4ld\n", test_n, rsc_test_mem_alloc_count - 1);
/* Disconnect. */
ux_test_dcd_sim_slave_disconnect();
ux_test_hcd_sim_host_disconnect();
/* Check */
status = ux_test_sleep_break_on_success(100, _test_check_host_disconnection_success);
if (status != UX_SUCCESS)
{
stepinfo("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)
{
stepinfo("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. */
status = ux_test_sleep_break_on_success(100, _test_check_host_connection_error);
/* Check error */
if (status != UX_SUCCESS)
{
/* Check error trap. */
if (error_callback_counter == 0)
{
stepinfo("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_test_mem_alloc_count) stepinfo("\n");
/* If device disconnected, re-connect. */
if (_test_check_host_connection_success() != UX_SUCCESS)
{
ux_test_dcd_sim_slave_disconnect();
ux_test_hcd_sim_host_disconnect();
ux_test_dcd_sim_slave_connect(UX_HIGH_SPEED_DEVICE);
ux_test_hcd_sim_host_connect(UX_HIGH_SPEED_DEVICE);
/* Check */
status = ux_test_sleep_break_on_success(100, _test_check_host_connection_success);
if (status != UX_SUCCESS)
{
printf("ERROR #%d: Enumeration fail\n", __LINE__);
test_control_return(1);
}
}
}
static VOID _printer_requests_test(VOID)
{
UINT status;
ULONG printer_port_status;
stepinfo(">>>>>>>>>>>>>>>> Test GET_DEVICE_ID\n");
status = ux_host_class_printer_device_id_get(host_printer, host_buffer, sizeof(host_buffer));
UX_TEST_ASSERT(status == UX_SUCCESS);
stepinfo(">>>>>>>>>>>>>>>> Test GET_PORT_STATUS\n");
ux_device_class_printer_ioctl(device_printer, UX_DEVICE_CLASS_PRINTER_IOCTL_PORT_STATUS_SET, (VOID *)0x73);
status = ux_host_class_printer_status_get(host_printer, &printer_port_status);
UX_TEST_ASSERT(status == UX_SUCCESS);
UX_TEST_ASSERT(printer_port_status == 0x73);
stepinfo(">>>>>>>>>>>>>>>> Test SOFT_RESET\n");
device_printer_soft_reset_count = 0;
status = ux_host_class_printer_soft_reset(host_printer);
UX_TEST_ASSERT(status == UX_SUCCESS);
UX_TEST_ASSERT(device_printer_soft_reset_count == 1);
}
static VOID _printer_read_write_test(VOID)
{
struct _TEST_DEF {
ULONG fill;
ULONG length;
ULONG zlp;
} tests[] = {
{0x5A, 1, 0},
{0x7E, 512, 1},
{0xC2, 513, 0},
{0x4C, UX_SLAVE_REQUEST_DATA_MAX_LENGTH, 1},
{0xA5, UX_SLAVE_REQUEST_DATA_MAX_LENGTH + 1, 0},
{0x3C, sizeof(device_buffer), 0},
{0xC4, sizeof(device_buffer) - 1, 0},
};
#define _TEST_N (sizeof(tests)/sizeof(struct _TEST_DEF))
INT i;
ULONG actual_length;
UINT status;
for(i = 0; i < _TEST_N; i ++)
{
stepinfo(">>>>>>>>>>>>>>>> Test Write %ld\n", tests[i].length);
device_buffer_length = 0;
device_read_length = tests[i].length;
ux_utility_memory_set(device_buffer, ~tests[i].fill, tests[i].length);
ux_utility_memory_set(host_buffer, tests[i].fill, tests[i].length);
status = ux_host_class_printer_write(host_printer, host_buffer, tests[i].length, &actual_length);
UX_TEST_ASSERT(status == UX_SUCCESS);
UX_TEST_ASSERT(tests[i].length == actual_length);
if (tests[i].zlp)
{
status = ux_host_class_printer_write(host_printer, host_buffer, 0, &actual_length);
UX_TEST_ASSERT(status == UX_SUCCESS);
UX_TEST_ASSERT(0 == actual_length);
}
/* Wait a while for background reception. */
tx_thread_sleep(tests[i].length/64 + 1);
UX_TEST_ASSERT(device_buffer_length == tests[i].length);
status = ux_utility_memory_compare(device_buffer, host_buffer, tests[i].length);
UX_TEST_ASSERT(status == UX_SUCCESS);
stepinfo(">>>>>>>>>>>>>>>> Test Read %ld\n", tests[i].length);
UX_TEST_ASSERT(status == TX_SUCCESS);
ux_utility_memory_set(host_buffer, ~tests[i].fill, tests[i].length);
status = ux_host_class_printer_read(host_printer, host_buffer, tests[i].length, &actual_length);
UX_TEST_ASSERT(status == UX_SUCCESS);
UX_TEST_ASSERT(tests[i].length == actual_length);
UX_TEST_ASSERT(host_buffer[0] == tests[i].fill);
UX_TEST_ASSERT(host_buffer[tests[i].length - 1] == tests[i].fill);
}
}
void tx_test_thread_host_simulation_entry(ULONG arg)
{
UINT status;
ULONG test_n;
ULONG mem_free;
ULONG loop;
ULONG parameter_u32[64/4];
USHORT *parameter_u16 = (USHORT*)parameter_u32;
UCHAR *parameter_u8 = (UCHAR*)parameter_u32;
stepinfo("\n");
stepinfo(">>>>>>>>>>>>>>>> Test connect\n");
ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
status = ux_test_sleep_break_on_success(100, _test_check_host_connection_success);
UX_TEST_ASSERT(status == UX_SUCCESS);
// _printer_enumeration_test();
_printer_requests_test();
_printer_read_write_test();
/* Test disconnect. */
stepinfo(">>>>>>>>>>>>>>>> Test disconnect\n");
ux_test_dcd_sim_slave_disconnect();
ux_test_hcd_sim_host_disconnect();
if (host_printer != UX_NULL)
{
printf("ERROR #13: instance not removed when disconnect");
test_control_return(1);
}
/* Finally disconnect the device. */
ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_device_class_printer_name, _ux_device_class_printer_entry);
/* Deinitialize the device side of usbx. */
_ux_device_stack_uninitialize();
/* And finally the usbx system resources. */
_ux_system_uninitialize();
/* Successful test. */
printf("SUCCESS!\n");
test_control_return(0);
}
void tx_test_thread_slave_simulation_entry(ULONG arg)
{
UINT status;
ULONG actual_length;
ULONG read_length = device_read_length;
ULONG write_length, write_zlp = UX_FALSE;
#define PRINTER_DEVICE_STATE_READ UX_STATE_STEP
#define PRINTER_DEVICE_STATE_WRITE UX_STATE_STEP + 1
#define PRINTER_DEVICE_STATE_ZLP UX_STATE_STEP + 2
UINT printer_device_state = UX_STATE_RESET;
while(1)
{
ux_system_tasks_run();
/* Reset state if read length changed. */
// if (read_length != device_read_length)
// {
// printer_device_state = UX_STATE_RESET;
// read_length = device_read_length;
// }
switch(printer_device_state)
{
case UX_STATE_RESET:
if (device_printer != UX_NULL)
{
printer_device_state = PRINTER_DEVICE_STATE_READ;
}
break;
case PRINTER_DEVICE_STATE_READ:
if (device_printer == UX_NULL)
{
printer_device_state = UX_STATE_RESET;
break;
}
status = ux_device_class_printer_read_run(device_printer, device_buffer, sizeof(device_buffer), &actual_length);
if (status < UX_STATE_NEXT)
{
printf("ERROR #%d: read status 0x%x\n", __LINE__, status);
return;
}
if (status == UX_STATE_NEXT)
{
if (actual_length == 0)
{
printer_device_state = UX_STATE_RESET;
break;
}
write_length = actual_length;
printer_device_state = PRINTER_DEVICE_STATE_WRITE;
device_buffer_length = actual_length;
}
break;
case PRINTER_DEVICE_STATE_WRITE:
if (device_printer == UX_NULL)
{
printer_device_state = UX_STATE_RESET;
break;
}
status = ux_device_class_printer_write_run(device_printer, device_buffer, write_length, &actual_length);
if (status < UX_STATE_NEXT)
{
printf("ERROR #%d: write status 0x%x\n", __LINE__, status);
return;
}
if (status == UX_STATE_NEXT)
{
printer_device_state = PRINTER_DEVICE_STATE_READ;
break;
}
case PRINTER_DEVICE_STATE_ZLP:
if (device_printer == UX_NULL)
{
printer_device_state = UX_STATE_RESET;
break;
}
status = ux_device_class_printer_write_run(device_printer, device_buffer, 0, &actual_length);
if (status < UX_STATE_NEXT)
{
printf("ERROR #%d: ZLP status 0x%x\n", __LINE__, status);
return;
}
if (status == UX_STATE_NEXT)
printer_device_state = PRINTER_DEVICE_STATE_READ;
break;
default:
printer_device_state = UX_STATE_RESET;
}
/* Let other threads run. */
tx_thread_relinquish();
}
}

View File

@ -0,0 +1,377 @@
/* This tests ensures that when the device stalls the default endpoint upon an invalid request, it is unstalled after sending a valid request. */
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_keyboard.h"
#define DUMMY_USBX_MEMORY_SIZE (64*1024)
static UCHAR dummy_usbx_memory[DUMMY_USBX_MEMORY_SIZE];
static UCHAR hid_report_descriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
};
#define HID_REPORT_LENGTH sizeof(hid_report_descriptor)/sizeof(hid_report_descriptor[0])
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[DEVICE_FRAMEWORK_LENGTH_FULL_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
UINT _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter);
static UINT ux_system_host_change_function(ULONG a, UX_HOST_CLASS *b, VOID *c)
{
return 0;
}
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
if (error_code != UX_TRANSFER_STALLED)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
test_control_return(1);
}
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_control_transfer_stall_test(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
/* Inform user. */
printf("Running Control Transfer Stall test....................... ");
/* 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 on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Register the error callback. */
_ux_utility_error_callback_register(error_callback);
/* The code below is required for installing the host portion of USBX */
status = ux_host_stack_initialize(ux_system_host_change_function);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Initialize the hid class parameters. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* 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 on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_HOST_CLASS_HID_KEYBOARD *keyboard;
UX_ENDPOINT *endpoint;
UX_TRANSFER *transfer_request;
UCHAR descriptor[1024];
/* Find the HID class */
status = demo_class_hid_get();
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Get the HID client */
hid_client = hid -> ux_host_class_hid_client;
/* Check if the instance of the keyboard is live */
while (hid_client -> ux_host_class_hid_client_local_instance == UX_NULL)
tx_thread_sleep(10);
/* Get the keyboard instance */
keyboard = (UX_HOST_CLASS_HID_KEYBOARD *)hid_client -> ux_host_class_hid_client_local_instance;
/* Get default endpoint. */
endpoint = &hid->ux_host_class_hid_device->ux_device_control_endpoint;
/* Get the transfer request. */
transfer_request = &endpoint->ux_endpoint_transfer_request;
/* Stall the default endpoint by sending it an invalid request. */
/* Create a transfer request for an invalid request. */
transfer_request -> ux_transfer_request_data_pointer = descriptor;
transfer_request -> ux_transfer_request_requested_length = 0x09;
transfer_request -> ux_transfer_request_function = UX_GET_DESCRIPTOR;
transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_DEVICE;
transfer_request -> ux_transfer_request_value = 0xffff << 8;
transfer_request -> ux_transfer_request_index = 0x02;
/* Send request to HCD layer. */
status = ux_host_stack_transfer_request(transfer_request);
if (status != UX_TRANSFER_STALLED)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Now send it a valid request. */
/* Create a transfer request for a valid request. */
transfer_request -> ux_transfer_request_data_pointer = descriptor;
transfer_request -> ux_transfer_request_requested_length = UX_CONFIGURATION_DESCRIPTOR_LENGTH;
transfer_request -> ux_transfer_request_function = UX_GET_DESCRIPTOR;
transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE;
transfer_request -> ux_transfer_request_value = UX_CONFIGURATION_DESCRIPTOR_ITEM << 8;
transfer_request -> ux_transfer_request_index = 0x02;
/* Send request to HCD layer. */
status = ux_host_stack_transfer_request(transfer_request);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,900 @@
/* 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 "ux_hcd_sim_host.h"
#include "fx_api.h"
#include "ux_device_class_dfu.h"
#include "ux_device_stack.h"
#include "ux_host_stack.h"
#include "ux_test_dcd_sim_slave.h"
#include "ux_test_hcd_sim_host.h"
#include "ux_test_utility_sim.h"
#define UX_DEMO_REQUEST_MAX_LENGTH \
((UX_HCD_SIM_HOST_MAX_PAYLOAD) > (UX_SLAVE_REQUEST_DATA_MAX_LENGTH) ? \
(UX_HCD_SIM_HOST_MAX_PAYLOAD) : (UX_SLAVE_REQUEST_DATA_MAX_LENGTH))
/* Define constants. */
#define UX_DEMO_MEMORY_SIZE (128*1024)
#define UX_DEMO_STACK_SIZE (1024)
/* Define local/extern function prototypes. */
static void test_thread_entry(ULONG);
static TX_THREAD tx_test_thread_host_simulation;
static TX_THREAD tx_test_thread_slave_simulation;
static void tx_test_thread_host_simulation_entry(ULONG);
static void tx_test_thread_slave_simulation_entry(ULONG);
static VOID demo_thread_dfu_activate(VOID *dfu);
static VOID demo_thread_dfu_deactivate(VOID *dfu);
static UINT demo_thread_dfu_read(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *actual_length);
static UINT demo_thread_dfu_write(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *media_status);
static UINT demo_thread_dfu_get_status(VOID *dfu, ULONG *media_status);
static UINT demo_thread_dfu_notify(VOID *dfu, ULONG notification);
static UINT demo_thread_dfu_custom_request(VOID *dfu, UX_SLAVE_TRANSFER *transfer);
/* Define global data structures. */
static UCHAR usbx_memory[UX_DEMO_MEMORY_SIZE + (UX_DEMO_STACK_SIZE * 2)];
static ULONG error_counter;
static ULONG set_cfg_counter;
static ULONG rsc_mem_free_on_set_cfg;
static ULONG rsc_sem_on_set_cfg;
static ULONG rsc_sem_get_on_set_cfg;
static ULONG rsc_mutex_on_set_cfg;
static ULONG rsc_enum_sem_usage;
static ULONG rsc_enum_sem_get_count;
static ULONG rsc_enum_mutex_usage;
static ULONG rsc_enum_mem_usage;
static ULONG interaction_count;
static UCHAR error_callback_ignore = UX_TRUE;
static ULONG error_callback_counter;
static UX_SLAVE_CLASS_DFU_PARAMETER dfu_parameter;
static UX_DEVICE *device;
static ULONG dfu_block;
static ULONG dfu_transfer_length;
static ULONG dfu_actual_length;
static UCHAR dfu_host_buffer[UX_DEMO_REQUEST_MAX_LENGTH];
static UCHAR dfu_device_buffer[UX_DEMO_REQUEST_MAX_LENGTH];
/* Define device framework. */
/* DFU descriptor must be same for all frameworks!!! */
#define DFU_FUNCTION_DESCRIPTOR \
/* Functional descriptor for DFU. */ \
0x09, 0x21, \
0x0f, /* bmAttributes: B3 bitWillDetach */ \
/* B2 bitManifestationTolerant */ \
/* B1 bitCanUpload, B0 bitCanDnload */ \
0xE8, 0x03, /* wDetachTimeOut: 0x03E8 (1000) */ \
UX_W0(UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH), \
UX_W1(UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH), /* wTransferSize: */ \
0x00, 0x01, /* bcdDFUVersion: 0x0100 */
/* Interface descriptor for APP/DFU mode. */
#define DFU_INTERFACE_DESCRIPTOR(bInterfaceNumber, bInterfaceProtocol) \
/* Interface descriptor for DFU. */ \
0x09, 0x04, \
(bInterfaceNumber), 0x00, 0x00, \
0xFE, 0x01, (bInterfaceProtocol), \
0x00, \
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
static UCHAR device_framework_full_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x40,
0x99, 0x99, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x1b, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor for DFU (bInterfaceProtocol = 1). */
DFU_INTERFACE_DESCRIPTOR(0x00, 0x01)
DFU_FUNCTION_DESCRIPTOR
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
static UCHAR device_framework_high_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x99, 0x99, 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, 0x1b, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor for DFU (bInterfaceProtocol = 1). */
DFU_INTERFACE_DESCRIPTOR(0x00, 0x01)
DFU_FUNCTION_DESCRIPTOR
};
/* 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 sizeof(string_framework)
static UCHAR string_framework[] = {
/* Manufacturer string descriptor : Index 1 - "Microsoft AzureRTOS" */
0x09, 0x04, 0x01, 19,
'M', 'i', 'c', 'r', 'o', 's', 'o', 'f',
't', ' ', 'A', 'z', 'u', 'r', 'e', 'R',
'T', 'O', 'S',
/* Product string descriptor : Index 2 - "DFU Demo Device" */
0x09, 0x04, 0x02, 15,
'D', 'F', 'U', ' ', 'D', 'e', 'm', 'o',
' ', 'D', 'e', 'v', 'i', 'c', 'e',
/* Serial Number string descriptor : Index 3 - "0000" */
0x09, 0x04, 0x03, 0x04,
'0', '0', '0', '0'
};
/* 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 sizeof(language_id_framework)
static UCHAR language_id_framework[] = {
/* English. */
0x09, 0x04
};
#define DEVICE_FRAMEWORK_LENGTH_DFU sizeof(device_framework_dfu)
static UCHAR device_framework_dfu[] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x40,
0x99, 0x99, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x1B, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor for DFU (bInterfaceProtocol = 2). */
DFU_INTERFACE_DESCRIPTOR(0x00, 0x02)
DFU_FUNCTION_DESCRIPTOR
};
/* Define the ISR dispatch. */
extern VOID (*test_isr_dispatch)(void);
/* Prototype for test control return. */
void test_control_return(UINT status);
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
error_callback_counter ++;
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);
}
}
}
/* Define the ISR dispatch routine. */
static void test_isr(void)
{
/* For further expansion of interrupt-level testing. */
}
static UINT demo_system_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
{
if (event == UX_DEVICE_CONNECTION)
{
device = (UX_DEVICE *)inst;
}
if (event == UX_DEVICE_DISCONNECTION)
{
if ((VOID *)device == inst)
device = UX_NULL;
}
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_device_dfu_basic_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
ULONG test_n;
/* Inform user. */
printf("Running Device DFU Basic Functionality Test......................... ");
/* Reset testing counts. */
ux_test_utility_sim_mutex_create_count_reset();
ux_test_utility_sim_sem_create_count_reset();
ux_test_utility_sim_sem_get_count_reset();
/* Reset error generations */
ux_test_utility_sim_sem_error_generation_stop();
ux_test_utility_sim_mutex_error_generation_stop();
ux_test_utility_sim_sem_get_error_generation_stop();
/* Initialize the free memory pointer */
stack_pointer = (CHAR *) usbx_memory;
memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
/* Initialize USBX Memory */
status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL,0);
/* 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 host portion of USBX */
status = ux_host_stack_initialize(demo_system_host_change_function);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* There is no host class for DFU now. */
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Store the DFU parameters. */
dfu_parameter.ux_slave_class_dfu_parameter_instance_activate = demo_thread_dfu_activate;
dfu_parameter.ux_slave_class_dfu_parameter_instance_deactivate = demo_thread_dfu_deactivate;
dfu_parameter.ux_slave_class_dfu_parameter_read = demo_thread_dfu_read;
dfu_parameter.ux_slave_class_dfu_parameter_write = demo_thread_dfu_write;
dfu_parameter.ux_slave_class_dfu_parameter_get_status = demo_thread_dfu_get_status;
dfu_parameter.ux_slave_class_dfu_parameter_notify = demo_thread_dfu_notify;
#ifdef UX_DEVICE_CLASS_DFU_CUSTOM_REQUEST_ENABLE
dfu_parameter.ux_device_class_dfu_parameter_custom_request = demo_thread_dfu_custom_request;
#endif
dfu_parameter.ux_slave_class_dfu_parameter_framework = device_framework_dfu;
dfu_parameter.ux_slave_class_dfu_parameter_framework_length = DEVICE_FRAMEWORK_LENGTH_DFU;
/* Initilize the device dfu class. The class is connected with interface 1 on configuration 1. */
status = ux_device_stack_class_register(_ux_system_slave_class_dfu_name, ux_device_class_dfu_entry,
1, 0, (VOID *)&dfu_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();
/* Check for error. */
if (status != TX_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_hcd_sim_host_initialize,0,0);
if (status != UX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Create the main host simulation thread. */
status = tx_thread_create(&tx_test_thread_host_simulation, "tx demo host simulation", tx_test_thread_host_simulation_entry, 0,
stack_pointer, UX_DEMO_STACK_SIZE,
20, 20, 1, TX_AUTO_START);
/* Check for error. */
if (status != TX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
/* Create the main slave simulation thread. */
status = tx_thread_create(&tx_test_thread_slave_simulation, "tx demo slave simulation", tx_test_thread_slave_simulation_entry, 0,
stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
20, 20, 1, TX_AUTO_START);
/* Check for error. */
if (status != TX_SUCCESS)
{
printf("ERROR #%d\n", __LINE__);
test_control_return(1);
}
}
static UINT _req_DFU_LOCK(UX_TRANSFER *control_transfer)
{
UINT status;
#if defined(UX_HOST_STANDALONE)
while(1)
{
ux_system_tasks_run();
tx_thread_relinquish();
UX_ENDPOINT *endpoint = control_transfer -> ux_transfer_request_endpoint;
if (endpoint == UX_NULL || endpoint -> ux_endpoint_state != UX_ENDPOINT_RUNNING)
{
status = UX_ENDPOINT_HANDLE_UNKNOWN;
break;
}
UX_DEVICE *device = endpoint -> ux_endpoint_device;
if (device == UX_NULL || device -> ux_device_handle != (ULONG)(ALIGN_TYPE)(device))
{
status = UX_DEVICE_HANDLE_UNKNOWN;
break;
}
if ((device -> ux_device_flags & UX_DEVICE_FLAG_LOCK) == 0)
{
device -> ux_device_flags |= UX_DEVICE_FLAG_LOCK;
control_transfer -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_AUTO_DEVICE_UNLOCK;
control_transfer -> ux_transfer_request_timeout_value = UX_WAIT_FOREVER;
status = UX_SUCCESS;
break;
}
}
#else
status = _ux_utility_semaphore_get(&control_transfer->ux_transfer_request_endpoint->ux_endpoint_device->ux_device_protection_semaphore, UX_WAIT_FOREVER);
#endif
if (status != UX_SUCCESS)
{
printf("ERROR #%d: %x\n", __LINE__, status);
test_control_return(1);
}
}
static UINT _req_DFU_GETSTATE(UX_TRANSFER *control_transfer)
{
_req_DFU_LOCK(control_transfer);
control_transfer->ux_transfer_request_type = 0xA1;
control_transfer->ux_transfer_request_function = UX_SLAVE_CLASS_DFU_COMMAND_GET_STATE;
control_transfer->ux_transfer_request_index = 0;
control_transfer->ux_transfer_request_requested_length = 1;
control_transfer->ux_transfer_request_data_pointer = dfu_host_buffer;
control_transfer->ux_transfer_request_value = 0;
return ux_host_stack_transfer_request(control_transfer);
}
static UINT _req_DFU_GETSTATUS(UX_TRANSFER *control_transfer)
{
_req_DFU_LOCK(control_transfer);
control_transfer->ux_transfer_request_type = 0xA1;
control_transfer->ux_transfer_request_function = UX_SLAVE_CLASS_DFU_COMMAND_GET_STATUS;
control_transfer->ux_transfer_request_index = 0;
control_transfer->ux_transfer_request_requested_length = 6;
control_transfer->ux_transfer_request_data_pointer = dfu_host_buffer;
control_transfer->ux_transfer_request_value = 0;
return ux_host_stack_transfer_request(control_transfer);
}
static UINT _req_DFU_DETACH(UX_TRANSFER *control_transfer)
{
_req_DFU_LOCK(control_transfer);
control_transfer->ux_transfer_request_type = 0x21;
control_transfer->ux_transfer_request_function = UX_SLAVE_CLASS_DFU_COMMAND_DETACH;
control_transfer->ux_transfer_request_index = 0;
control_transfer->ux_transfer_request_value = 1000;
control_transfer->ux_transfer_request_requested_length = 0;
return ux_host_stack_transfer_request(control_transfer);
}
static UINT _req_DFU_DNLOAD_IN(UX_TRANSFER *control_transfer, ULONG block, ULONG len)
{
_req_DFU_LOCK(control_transfer);
control_transfer->ux_transfer_request_type = 0xA1;
control_transfer->ux_transfer_request_function = UX_SLAVE_CLASS_DFU_COMMAND_DOWNLOAD;
control_transfer->ux_transfer_request_index = 0;
control_transfer->ux_transfer_request_data_pointer = dfu_host_buffer;
control_transfer->ux_transfer_request_requested_length = len;
control_transfer->ux_transfer_request_value = block;
return ux_host_stack_transfer_request(control_transfer);
}
static UINT _req_DFU_DNLOAD(UX_TRANSFER *control_transfer, ULONG block, ULONG len)
{
_req_DFU_LOCK(control_transfer);
control_transfer->ux_transfer_request_type = 0x21;
control_transfer->ux_transfer_request_function = UX_SLAVE_CLASS_DFU_COMMAND_DOWNLOAD;
control_transfer->ux_transfer_request_index = 0;
control_transfer->ux_transfer_request_data_pointer = dfu_host_buffer;
control_transfer->ux_transfer_request_requested_length = len;
control_transfer->ux_transfer_request_value = block;
return ux_host_stack_transfer_request(control_transfer);
}
static UINT _req_DFU_UPLOAD(UX_TRANSFER *control_transfer, ULONG block, ULONG len)
{
_req_DFU_LOCK(control_transfer);
control_transfer->ux_transfer_request_type = 0xA1;
control_transfer->ux_transfer_request_function = UX_SLAVE_CLASS_DFU_COMMAND_UPLOAD;
control_transfer->ux_transfer_request_index = 0;
control_transfer->ux_transfer_request_data_pointer = dfu_host_buffer;
control_transfer->ux_transfer_request_requested_length = len;
control_transfer->ux_transfer_request_value = block;
return ux_host_stack_transfer_request(control_transfer);
}
static UINT _req_DFU_CLRSTATUS(UX_TRANSFER *control_transfer)
{
_req_DFU_LOCK(control_transfer);
control_transfer->ux_transfer_request_type = 0x21;
control_transfer->ux_transfer_request_function = UX_SLAVE_CLASS_DFU_COMMAND_CLEAR_STATUS;
control_transfer->ux_transfer_request_index = 0;
control_transfer->ux_transfer_request_data_pointer = UX_NULL;
control_transfer->ux_transfer_request_requested_length = 0;
control_transfer->ux_transfer_request_value = 0;
return ux_host_stack_transfer_request(control_transfer);
}
static void tx_test_thread_host_simulation_entry(ULONG arg)
{
UX_ENDPOINT *control_endpoint;
UX_TRANSFER *control_transfer;
ULONG len, trans_len, block;
INT i;
UINT status;
stepinfo("\n");
stepinfo(">>>>>>>>>>>> Test DFU connect\n");
status = ux_test_wait_for_non_null((VOID **)&device);
UX_TEST_ASSERT(status == UX_SUCCESS);
if (device -> ux_device_state == UX_DEVICE_CONFIGURED)
{
printf("ERROR #%d, device state 0x%lx\n", __LINE__, device->ux_device_state);
test_control_return(1);
}
stepinfo(">>>>>>>>>>>> Test DFU set configure\n");
status = ux_host_stack_device_configuration_select(device->ux_device_first_configuration);
UX_TEST_ASSERT(status == UX_SUCCESS);
/* Get endpoint and transfer request. */
control_endpoint = &device->ux_device_control_endpoint;
control_transfer = &control_endpoint->ux_endpoint_transfer_request;
stepinfo(">>>>>>>>>>>> Test DFU_GETSTATE\n");
status = _req_DFU_GETSTATE(control_transfer);
if (status != UX_SUCCESS)
{
printf("ERROR #%d: transfer status 0x%x\n", __LINE__, status);
test_control_return(1);
}
UX_TEST_ASSERT(dfu_host_buffer[0] == UX_SYSTEM_DFU_STATE_APP_IDLE);
stepinfo(">>>>>>>>>>>> Test DFU DETACH\n");
/* Uses DFU framework after USB reset (re-connect). */
ux_test_dcd_sim_slave_connect_framework(device_framework_dfu, DEVICE_FRAMEWORK_LENGTH_DFU);
status = _req_DFU_DETACH(control_transfer);
if (status != UX_SUCCESS)
{
printf("ERROR #%d: transfer status 0x%x\n", __LINE__, status);
test_control_return(1);
}
status = ux_test_wait_for_null((VOID **)&device);
UX_TEST_ASSERT(status == UX_SUCCESS);
status = ux_test_wait_for_non_null((VOID **)&device);
UX_TEST_ASSERT(status == UX_SUCCESS);
status = ux_host_stack_device_configuration_select(device->ux_device_first_configuration);
UX_TEST_ASSERT(status == UX_SUCCESS);
status = _req_DFU_GETSTATE(control_transfer);
if (status != UX_SUCCESS)
{
printf("ERROR #%d: transfer status 0x%x\n", __LINE__, status);
test_control_return(1);
}
UX_TEST_ASSERT(dfu_host_buffer[0] == UX_SYSTEM_DFU_STATE_DFU_IDLE);
#if defined(UX_DEVICE_CLASS_DFU_CUSTOM_REQUEST_ENABLE)
status = _req_DFU_DNLOAD(control_transfer, 0, 0);
if (status != UX_SUCCESS)
{
printf("ERROR #%d: transfer status 0x%x\n", __LINE__, status);
test_control_return(1);
}
UX_TEST_ASSERT(dfu_host_buffer[0] == UX_SYSTEM_DFU_STATE_DFU_IDLE);
#else
#endif
#if !defined(UX_DEVICE_CLASS_DFU_UPLOAD_DISABLE)
stepinfo(">>>>>>>>>>>> Test DFU UPLOAD FAIL\n");
status = _req_DFU_UPLOAD(control_transfer, 0, UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH + 1);
if (status != UX_TRANSFER_STALLED)
{
printf("ERROR #%d: UPLOAD should STALL\n", __LINE__);
test_control_return(1);
}
status = _req_DFU_CLRSTATUS(control_transfer);
if (status != UX_SUCCESS)
{
printf("ERROR #%d: CLRSTATUS error 0x%x\n", __LINE__, status);
test_control_return(1);
}
stepinfo(">>>>>>>>>>>> Test DFU UPLOAD\n");
trans_len = UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH;
for (block = 0; block < 99; block ++)
{
for (i = 0; i < trans_len; i ++)
{
dfu_device_buffer[i] = (UCHAR)(block + i);
dfu_host_buffer[i] = 0xFF;
}
dfu_actual_length = trans_len;
status = _req_DFU_UPLOAD(control_transfer, block, trans_len);
if (status != UX_SUCCESS)
{
printf("ERROR #%d(%ld, %ld): UPLOAD status 0x%x\n", __LINE__, block, trans_len, status);
test_control_return(1);
}
UX_TEST_ASSERT(dfu_transfer_length == trans_len);
UX_TEST_ASSERT(dfu_block == block);
if (ux_utility_memory_compare(dfu_host_buffer, dfu_device_buffer, trans_len) != UX_SUCCESS)
{
printf("ERROR #%d(%ld, %ld): data error\n", __LINE__, block, trans_len);
printf(" device buffer %p: %2x %2x ...\n", dfu_device_buffer, dfu_device_buffer[0], dfu_device_buffer[1]);
printf(" host buffer %p: %2x %2x ...\n", dfu_host_buffer, dfu_host_buffer[0], dfu_host_buffer[1]);
test_control_return(1);
}
}
/* Finish upload. */
dfu_actual_length = trans_len >> 1;
status = _req_DFU_UPLOAD(control_transfer, block, trans_len);
if (status != UX_SUCCESS)
{
printf("ERROR #%d: UPLOAD(0) 0x%x\n", __LINE__, status);
test_control_return(1);
}
/* Check state. */
status = _req_DFU_GETSTATE(control_transfer);
if (status != UX_SUCCESS)
{
printf("ERROR #%d: transfer status 0x%x\n", __LINE__, status);
test_control_return(1);
}
UX_TEST_ASSERT(dfu_host_buffer[0] == UX_SYSTEM_DFU_STATE_DFU_IDLE);
#endif
stepinfo(">>>>>>>>>>>> Test DFU DNLOAD error\n");
status = _req_DFU_DNLOAD_IN(control_transfer, 0, 16);
UX_TEST_CHECK_CODE(UX_TRANSFER_STALLED, status);
#if defined(UX_DEVICE_CLASS_DFU_ERROR_GET_ENABLE)
status = _req_DFU_GETSTATUS(control_transfer);
UX_TEST_CHECK_SUCCESS(status);
#endif
status = _req_DFU_CLRSTATUS(control_transfer);
UX_TEST_CHECK_SUCCESS(status);
stepinfo(">>>>>>>>>>>> Test DFU DNLOAD\n");
for (len = 1, block = 0; len < UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH * 2; len <<= 1)
{
for (i = 0; i < len; i ++)
{
dfu_host_buffer[i] = (UCHAR)(block + i);
dfu_device_buffer[i] = 0xFF;
}
trans_len = UX_MIN(len, UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH);
status = _req_DFU_DNLOAD(control_transfer, block, trans_len);
if (status != UX_SUCCESS)
{
printf("ERROR #%d(%ld, %ld): DNLOAD status 0x%x\n", __LINE__, block, trans_len, status);
test_control_return(1);
}
UX_TEST_ASSERT(dfu_transfer_length == trans_len);
UX_TEST_ASSERT(dfu_block == block);
if (ux_utility_memory_compare(dfu_host_buffer, dfu_device_buffer, trans_len) != UX_SUCCESS)
{
printf("ERROR #%d(%ld, %ld): data error\n", __LINE__, block, trans_len);
test_control_return(1);
}
status = _req_DFU_GETSTATUS(control_transfer);
if (status != UX_SUCCESS)
{
printf("ERROR #%d(%ld, %ld): GETSTATUS status 0x%x\n", __LINE__, block, trans_len, status);
test_control_return(1);
}
block ++;
}
/* Finish download. */
status = _req_DFU_DNLOAD(control_transfer, block, 0);
if (status != UX_SUCCESS)
{
printf("ERROR #%d: DNLOAD(0) 0x%x\n", __LINE__, status);
test_control_return(1);
}
/* Manifestation. */
status = _req_DFU_GETSTATE(control_transfer);
if (status != UX_SUCCESS)
{
printf("ERROR #%d: GETSTATE status 0x%x\n", __LINE__, status);
test_control_return(1);
}
UX_TEST_ASSERT(dfu_host_buffer[0] == UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST_SYNC);
/* Uses DFU framework after USB reset (re-connect). */
ux_test_dcd_sim_slave_connect_framework(UX_NULL, 0);
status = _req_DFU_GETSTATUS(control_transfer);
if (status != UX_SUCCESS)
{
printf("ERROR #%d: GETSTATUS status 0x%x\n", __LINE__, status);
test_control_return(1);
}
UX_TEST_ASSERT(dfu_host_buffer[4] == UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST_WAIT_RESET);
/* Reset */
status = ux_test_wait_for_null((VOID **)&device);
UX_TEST_ASSERT(status == UX_SUCCESS);
status = ux_test_wait_for_non_null((VOID **)&device);
UX_TEST_ASSERT(status == UX_SUCCESS);
status = ux_host_stack_device_configuration_select(device->ux_device_first_configuration);
UX_TEST_ASSERT(status == UX_SUCCESS);
status = _req_DFU_GETSTATE(control_transfer);
if (status != UX_SUCCESS)
{
printf("ERROR #%d: transfer status 0x%x\n", __LINE__, status);
test_control_return(1);
}
UX_TEST_ASSERT(dfu_host_buffer[0] == UX_SYSTEM_DFU_STATE_APP_IDLE);
stepinfo(">>>>>>>>>>>> All Done\n");
/* Finally disconnect the device. */
ux_device_stack_disconnect();
/* 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 void tx_test_thread_slave_simulation_entry(ULONG arg)
{
while(1)
{
#if defined(UX_DEVICE_STANDALONE)
ux_system_tasks_run();
tx_thread_relinquish();
#else
/* Sleep so ThreadX on Win32 will delete this thread. */
tx_thread_sleep(10);
#endif
}
}
static UINT demo_device_state_change(ULONG event)
{
return(UX_SUCCESS);
}
static VOID demo_thread_dfu_activate(VOID *dfu)
{
}
static VOID demo_thread_dfu_deactivate(VOID *dfu)
{
}
static UINT demo_thread_dfu_read(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *actual_length)
{
ULONG return_length;
stepinfo("dfuRead %ld,%ld: %2x %2x %2x %2x ... -> %p\n", block_number, length,
dfu_device_buffer[0], dfu_device_buffer[1], dfu_device_buffer[2], dfu_device_buffer[3],
data_pointer);
dfu_block = block_number;
dfu_transfer_length = length;
return_length = UX_MIN(length, sizeof(dfu_device_buffer));
return_length = UX_MIN(return_length, dfu_actual_length);
ux_utility_memory_copy(data_pointer, dfu_device_buffer, return_length);
/* Here is where the data block is read from the firmware. */
/* Some code needs to be inserted specifically for a target platform. */
*actual_length = return_length;
return(UX_SUCCESS);
}
static UINT demo_thread_dfu_write(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *media_status)
{
stepinfo("dfuWrite %ld,%ld\n", block_number, length);
dfu_block = block_number;
dfu_transfer_length = length;
ux_utility_memory_copy(dfu_device_buffer, data_pointer, UX_MIN(length, sizeof(dfu_device_buffer)));
/* Here is where the data block is coming to be written to the firmware. */
/* Some code needs to be inserted specifically for a target platform. */
/* Return media status ok. */
*media_status = UX_SLAVE_CLASS_DFU_MEDIA_STATUS_OK ;
return(UX_SUCCESS);
}
static UINT demo_thread_dfu_get_status(VOID *dfu, ULONG *media_status)
{
/* Return media status ok. */
*media_status = UX_SLAVE_CLASS_DFU_MEDIA_STATUS_OK ;
return(UX_SUCCESS);
}
static UINT demo_thread_dfu_notify(VOID *dfu, ULONG notification)
{
stepinfo("dfuNotify 0x%lx\n", notification);
switch (notification)
{
case UX_SLAVE_CLASS_DFU_NOTIFICATION_BEGIN_DOWNLOAD :
/* Begin of Download. */
break;
case UX_SLAVE_CLASS_DFU_NOTIFICATION_END_DOWNLOAD :
/* Completion of Download. */
break;
case UX_SLAVE_CLASS_DFU_NOTIFICATION_ABORT_DOWNLOAD :
/* Download was aborted. */
break;
case UX_SLAVE_CLASS_DFU_NOTIFICATION_BEGIN_UPLOAD :
/* Begin of UPLOAD. */
break;
case UX_SLAVE_CLASS_DFU_NOTIFICATION_END_UPLOAD :
/* Completion of UPLOAD. */
break;
case UX_SLAVE_CLASS_DFU_NOTIFICATION_ABORT_UPLOAD :
/* Download was aborted. */
break;
default :
/* Bad notification signal. Should never get here. */
break;
}
return(UX_SUCCESS);
}
static UINT demo_thread_dfu_custom_request(VOID *dfu, UX_SLAVE_TRANSFER *transfer)
{
UCHAR *setup;
UCHAR *buffer;
/* Check state and request to insert custom operation, before the standard
handling process.
If no standard handling process is needed, return UX_SUCCESS.
*/
/* E.g., accept DNLOAD command with wLength 0 in dfuIDLE. */
if (ux_device_class_dfu_state_get((UX_SLAVE_CLASS_DFU *)dfu) == UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_IDLE)
{
setup = transfer -> ux_slave_transfer_request_setup;
buffer = transfer -> ux_slave_transfer_request_data_pointer;
if (setup[UX_SETUP_REQUEST] == UX_SLAVE_CLASS_DFU_COMMAND_DOWNLOAD &&
setup[UX_SETUP_LENGTH] == 0 &&
setup[UX_SETUP_LENGTH + 1] == 0)
{
/* Accept the case (by default it's stalled). */
stepinfo("dfuIDLE - accept dfuDNLOAD & wLength 0\n");
/* Fill the status data payload. First with status. */
*buffer = UX_SLAVE_CLASS_DFU_STATUS_OK;
/* Poll time out value is set to 500ms. */
*(buffer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = UX_DW0(500);
*(buffer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = UX_DW1(500);
*(buffer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = UX_DW2(500);
/* Next state: still dfuIDLE. */
*(buffer + UX_SLAVE_CLASS_DFU_GET_STATUS_STATE) = (UCHAR) UX_SYSTEM_DFU_STATE_DFU_IDLE;
/* String index set to 0. */
*(buffer + UX_SLAVE_CLASS_DFU_GET_STATUS_STRING) = 0;
/* We have a request to obtain the status of the DFU instance. */
_ux_device_stack_transfer_request(transfer, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH);
/* Inform stack it's taken. */
return(UX_SUCCESS);
}
}
/* No custom request. */
return(UX_ERROR);
}

View File

@ -0,0 +1,651 @@
/* 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 "ux_host_class_dpump.h"
#include "ux_device_class_dpump.h"
/* Define USBX demo constants. */
#define UX_DEMO_STACK_SIZE 4096
#define UX_DEMO_BUFFER_SIZE 2048
#define UX_DEMO_RUN 1
#define UX_DEMO_MEMORY_SIZE (64*1024)
/* Define the counters used in the demo application... */
static ULONG thread_0_counter;
static ULONG thread_1_counter;
static ULONG error_counter;
/* Define USBX demo global variables. */
static unsigned char host_out_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE];
static unsigned char host_in_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE];
static unsigned char slave_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE];
static UX_HOST_CLASS *class_driver;
static UX_HOST_CLASS_DPUMP *dpump;
static UX_SLAVE_CLASS_DPUMP *dpump_slave;
static UINT expected_error;
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 50
static UCHAR device_framework_full_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0xec, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x00, 0x00, 0x02, 0x99, 0x99, 0x99,
0x00,
/* Endpoint descriptor (Bulk Out) */
0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00,
#ifdef UX_DEVICE_BIDIRECTIONAL_ENDPOINT_SUPPORT
/* Endpoint descriptor (Bulk In) */
0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00
#else
/* Endpoint descriptor (Bulk In) */
0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00
#endif
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 60
static UCHAR device_framework_high_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x00, 0x00, 0x02, 0x99, 0x99, 0x99,
0x00,
/* Endpoint descriptor (Bulk Out) */
0x07, 0x05, 0x01, 0x02, 0x00, 0x02, 0x00,
#ifdef UX_DEVICE_BIDIRECTIONAL_ENDPOINT_SUPPORT
/* Endpoint descriptor (Bulk In) */
0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00
#else
/* Endpoint descriptor (Bulk In) */
0x07, 0x05, 0x82, 0x02, 0x00, 0x02, 0x00
#endif
};
/* 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, 0x0c,
0x44, 0x61, 0x74, 0x61, 0x50, 0x75, 0x6d, 0x70,
0x44, 0x65, 0x6d, 0x6f,
/* 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
};
/* Define prototypes for external Host Controller's (HCDs), classes and clients. */
static VOID tx_demo_instance_activate(VOID *dpump_instance);
static VOID tx_demo_instance_deactivate(VOID *dpump_instance);
#if defined(UX_HOST_STANDALONE)
static UINT tx_demo_host_change_function(ULONG e, UX_HOST_CLASS *c, VOID *p);
#else
#define tx_demo_host_change_function UX_NULL
#endif
UINT _ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command);
UINT ux_hcd_sim_initialize(UX_HCD *hcd);
UINT _ux_host_class_dpump_write(UX_HOST_CLASS_DPUMP *dpump, UCHAR * data_pointer,
ULONG requested_length, ULONG *actual_length);
UINT _ux_host_class_dpump_read (UX_HOST_CLASS_DPUMP *dpump, UCHAR *data_pointer,
ULONG requested_length, ULONG *actual_length);
static TX_THREAD tx_demo_thread_host_simulation;
static TX_THREAD tx_demo_thread_slave_simulation;
static void tx_demo_thread_host_simulation_entry(ULONG);
static void tx_demo_thread_slave_simulation_entry(ULONG);
/* 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)
{
if (expected_error == 0 || error_code != expected_error)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %x\n", __LINE__, system_level, system_context, error_code);
// test_control_return(1);
}
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_dpump_basic_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR *stack_pointer;
CHAR *memory_pointer;
UX_SLAVE_CLASS_DPUMP_PARAMETER parameter;
/* Initialize the free memory pointer. */
stack_pointer = (CHAR *) first_unused_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("Running DPUMP Basic Functionality Test.............................. ERROR #1\n");
test_control_return(1);
}
/* Register the error callback. */
_ux_utility_error_callback_register(error_callback);
/* The code below is required for installing the host portion of USBX. */
status = ux_host_stack_initialize(tx_demo_host_change_function);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Running DPUMP Basic Functionality Test.............................. ERROR #2\n");
test_control_return(1);
}
/* Register all the host class drivers for this USBX implementation. */
status = ux_host_stack_class_register(_ux_system_host_class_dpump_name, ux_host_class_dpump_entry);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Running DPUMP Basic Functionality Test.............................. ERROR #3\n");
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX */
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);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Running DPUMP Basic Functionality Test.............................. ERROR #5\n");
test_control_return(1);
}
/* Set the parameters for callback when insertion/extraction of a Data Pump device. */
parameter.ux_slave_class_dpump_instance_activate = tx_demo_instance_activate;
parameter.ux_slave_class_dpump_instance_deactivate = tx_demo_instance_deactivate;
/* Initialize the device dpump class. The class is connected with interface 0 */
status = ux_device_stack_class_register(_ux_system_slave_class_dpump_name, _ux_device_class_dpump_entry,
1, 0, &parameter);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Running DPUMP Basic Functionality Test.............................. ERROR #6\n");
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Running DPUMP Basic Functionality Test.............................. ERROR #7\n");
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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Running DPUMP Basic Functionality Test.............................. ERROR #4\n");
test_control_return(1);
}
/* 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("Running DPUMP Basic Functionality Test.............................. ERROR #8\n");
test_control_return(1);
}
/* Create the main demo thread. */
status = tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0,
stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
20, 20, 1, TX_AUTO_START);
/* Check for error. */
if (status != TX_SUCCESS)
{
printf("Running DPUMP Basic Functionality Test.............................. ERROR #9\n");
test_control_return(1);
}
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
ULONG actual_length;
UCHAR current_char;
UX_HOST_CLASS *class;
UINT i;
#if 0
UX_ENDPOINT *endpoint;
#endif
/* Inform user. */
printf("Running DPUMP Basic Functionality Test.............................. ");
/* Find the class container with unregistered name. */
status = ux_host_stack_class_get(_ux_system_host_class_hid_name, &class);
/* Should return error. */
if (status != UX_HOST_CLASS_UNKNOWN)
{
/* DPUMP basic test error. */
printf("ERROR #10\n");
test_control_return(1);
}
/* Find the main data pump container. */
status = ux_host_stack_class_get(_ux_system_host_class_dpump_name, &class);
/* Check for error. */
if (status != UX_SUCCESS)
{
/* DPUMP basic test error. */
printf("ERROR #10\n");
test_control_return(1);
}
/* We get the first instance of the data pump device. */
do
{
status = ux_host_stack_class_instance_get(class, 0, (VOID **) &dpump);
#if defined(UX_HOST_STANDALONE)
ux_system_tasks_run();
#endif
tx_thread_relinquish();
} while (status != UX_SUCCESS);
/* We still need to wait for the data pump status to be live. */
while (dpump -> ux_host_class_dpump_state != UX_HOST_CLASS_INSTANCE_LIVE)
{
#if defined(UX_HOST_STANDALONE)
ux_system_tasks_run();
#endif
tx_thread_relinquish();
}
/* At this point, the data pump class has been found. Now use the
data pump to send and receive data between the host and device. */
/* We start with a 'A' in buffer. */
current_char = 'A';
/* Perform this test sequence 100 times. */
for (i = 0; i < 100; i++)
{
/* Increment thread counter. */
thread_0_counter++;
/* Initialize the write buffer. */
_ux_utility_memory_set(host_out_buffer, current_char, UX_HOST_CLASS_DPUMP_PACKET_SIZE);
/* Increment the character in buffer. */
current_char++;
/* Check for upper alphabet limit. */
if (current_char > 'Z')
current_char = 'A';
/* Write to the host Data Pump Bulk out endpoint. */
status = _ux_host_class_dpump_write (dpump, host_out_buffer, UX_HOST_CLASS_DPUMP_PACKET_SIZE, &actual_length);
/* Check for error. */
if (status != UX_SUCCESS)
{
/* DPUMP basic test error. */
printf("ERROR #%d: 0x%x\n", __LINE__, status);
test_control_return(1);
}
/* Verify that the status and the amount of data is correct. */
if ((status != UX_SUCCESS) || actual_length != UX_HOST_CLASS_DPUMP_PACKET_SIZE)
{
/* DPUMP basic test error. */
printf("ERROR #12\n");
test_control_return(1);
}
#if defined(UX_HOST_STANDALONE)
/* Relinquish to other thread. */
tx_thread_relinquish();
#endif
/* Read to the Data Pump Bulk out endpoint. */
status = _ux_host_class_dpump_read (dpump, host_in_buffer, UX_HOST_CLASS_DPUMP_PACKET_SIZE, &actual_length);
/* Verify that the status and the amount of data is correct. */
if ((status != UX_SUCCESS) || actual_length != UX_HOST_CLASS_DPUMP_PACKET_SIZE)
{
/* DPUMP basic test error. */
printf("ERROR #13\n");
test_control_return(1);
}
/* Relinquish to other thread. */
tx_thread_relinquish();
}
#if 0
/* Test ux_host_stack_endpoint_reset with invalid endpoint number. */
endpoint = dpump -> ux_host_class_dpump_interface -> ux_interface_first_endpoint;
endpoint -> ux_endpoint_descriptor.bEndpointAddress = 0xf;
expected_error = UX_TRANSFER_STALLED;
status = _ux_host_stack_endpoint_reset(endpoint);
/* Check for error. */
if (status == UX_SUCCESS)
{
/* DPUMP basic test error. */
printf("ERROR #14\n");
test_control_return(1);
}
#endif
expected_error = 0;
/* Sleep for a tick to make sure everything is complete. */
tx_thread_sleep(1);
/* Check for errors from other threads. */
if (error_counter)
{
/* DPUMP error. */
printf("ERROR #%d: total %ld errors\n", __LINE__, error_counter);
test_control_return(1);
}
else
{
/* Successful test. */
printf("SUCCESS!\n");
test_control_return(0);
}
}
static void tx_demo_thread_slave_simulation_entry(ULONG arg)
{
UINT status;
ULONG actual_length;
#if defined(UX_DEVICE_STANDALONE)
#define DPUMP_DEVICE_STATE_READ UX_STATE_STEP
#define DPUMP_DEVICE_STATE_WRITE UX_STATE_STEP + 1
UINT dpump_device_state = UX_STATE_RESET;
#endif
while(1)
{
#if defined(UX_DEVICE_STANDALONE)
/* Run device tasks. */
ux_system_tasks_run();
/* DPUMP echo state machine. */
switch(dpump_device_state)
{
case UX_STATE_RESET:
if (dpump_slave != UX_NULL)
/* Start reading. */
dpump_device_state = DPUMP_DEVICE_STATE_READ;
break;
case DPUMP_DEVICE_STATE_READ:
/* Read from the device data pump. */
if (dpump_slave == UX_NULL)
{
dpump_device_state = UX_STATE_RESET;
break;
}
status = ux_device_class_dpump_read_run(dpump_slave, slave_buffer, UX_HOST_CLASS_DPUMP_PACKET_SIZE, &actual_length);
if (status < UX_STATE_NEXT)
{
printf("ERROR #%d: read status 0x%x\n", __LINE__, status);
error_counter ++;
return;
}
if (status == UX_STATE_NEXT)
{
if (actual_length != UX_HOST_CLASS_DPUMP_PACKET_SIZE)
{
printf("ERROR #%d: read length %ld\n", __LINE__, actual_length);
error_counter ++;
return;
}
dpump_device_state = DPUMP_DEVICE_STATE_WRITE;
}
break;
case DPUMP_DEVICE_STATE_WRITE:
/* Now write to the device data pump. */
if (dpump_slave == UX_NULL)
{
dpump_device_state = UX_STATE_RESET;
break;
}
status = ux_device_class_dpump_write_run(dpump_slave, slave_buffer, UX_HOST_CLASS_DPUMP_PACKET_SIZE, &actual_length);
if (status < UX_STATE_NEXT)
{
printf("ERROR #%d: write status 0x%x\n", __LINE__, status);
error_counter ++;
return;
}
if (status == UX_STATE_NEXT)
dpump_device_state = DPUMP_DEVICE_STATE_READ;
break;
default:
dpump_device_state = UX_STATE_RESET;
}
/* Increment thread counter. */
thread_1_counter++;
/* Relinquish to other thread. */
tx_thread_relinquish();
#else
/* Ensure the dpump class on the device is still alive. */
while (dpump_slave != UX_NULL)
{
/* Increment thread counter. */
thread_1_counter++;
/* Read from the device data pump. */
status = _ux_device_class_dpump_read(dpump_slave, slave_buffer, UX_HOST_CLASS_DPUMP_PACKET_SIZE, &actual_length);
/* Verify that the status and the amount of data is correct. */
if ((status != UX_SUCCESS) || actual_length != UX_HOST_CLASS_DPUMP_PACKET_SIZE)
{
printf("ERROR #%d.%ld: read status 0x%x, length %ld\n", __LINE__, thread_1_counter, status, actual_length);
/* Increment error counter. */
error_counter++;
/* Return from thread. */
return;
}
/* Now write to the device data pump. */
status = _ux_device_class_dpump_write(dpump_slave, slave_buffer, UX_HOST_CLASS_DPUMP_PACKET_SIZE, &actual_length);
/* Verify that the status and the amount of data is correct. */
if ((status != UX_SUCCESS) || actual_length != UX_HOST_CLASS_DPUMP_PACKET_SIZE)
{
printf("ERROR #%d.%ld: write status 0x%x, length %ld\n", __LINE__, thread_1_counter, status, actual_length);
/* Increment error counter. */
error_counter++;
/* Return from thread. */
return;
}
}
/* Relinquish to other thread. */
tx_thread_relinquish();
#endif
}
}
static VOID tx_demo_instance_activate(VOID *dpump_instance)
{
/* Save the DPUMP instance. */
dpump_slave = (UX_SLAVE_CLASS_DPUMP *) dpump_instance;
}
static VOID tx_demo_instance_deactivate(VOID *dpump_instance)
{
/* Reset the DPUMP instance. */
dpump_slave = UX_NULL;
}
#if defined(UX_HOST_STANDALONE)
static UINT tx_demo_host_change_function(ULONG e, UX_HOST_CLASS *c, VOID *p)
{
if (e == UX_STANDALONE_WAIT_BACKGROUND_TASK)
{
tx_thread_relinquish();
}
}
#endif

View File

@ -0,0 +1,417 @@
/* This file tests retrieving an input report via the interrupt endpoint. */
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_keyboard.h"
#define DUMMY_USBX_MEMORY_SIZE (64*1024)
static UCHAR dummy_usbx_memory[DUMMY_USBX_MEMORY_SIZE];
static UCHAR buffer[1024];
static UCHAR hid_report_descriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
};
#define HID_REPORT_LENGTH sizeof(hid_report_descriptor)/sizeof(hid_report_descriptor[0])
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[DEVICE_FRAMEWORK_LENGTH_FULL_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
UINT _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter);
static UINT ux_system_host_change_function(ULONG a, UX_HOST_CLASS *b, VOID *c)
{
return 0;
}
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
/* @BUG_FIX_PENDING: ux_dcd_sim_slave_function.c doesn't support transfer aborts, which happen during device unregistration of a class. */
if (error_code != UX_FUNCTION_NOT_SUPPORTED)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
test_control_return(1);
}
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_interrupt_endpoint_get_report_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
/* Inform user. */
printf("Running HID Interrupt Endpoint Get Report Test...................... ");
/* 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 on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Register the error callback. */
_ux_utility_error_callback_register(error_callback);
/* The code below is required for installing the host portion of USBX */
status = ux_host_stack_initialize(ux_system_host_change_function);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Initialize the hid class parameters. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* 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 on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_ENDPOINT *interrupt_endpoint;
UX_TRANSFER *interrupt_endpoint_transfer_request;
ULONG report_id;
UX_SLAVE_CLASS_HID_EVENT hid_event;
UX_SLAVE_CLASS_HID *slave_hid;
UINT max_get_report_attempts = 5;
/* Find the HID class */
status = demo_class_hid_get();
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Set report id. */
report_id = 0;
/* Get the slave hid. */
slave_hid = _ux_system_slave -> ux_system_slave_device.ux_slave_device_first_interface -> ux_slave_interface_class_instance;
/* Get the endpoint and transfer request. */
interrupt_endpoint = hid -> ux_host_class_hid_interrupt_endpoint;
interrupt_endpoint_transfer_request = &interrupt_endpoint -> ux_endpoint_transfer_request;
/* Kill the periodic thread so it doesn't get the report before us. */
status = _ux_host_class_hid_periodic_report_stop(hid);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Add an event for the host to get. */
/* Set the length. */
hid_event.ux_device_class_hid_event_length = 8;
/* First byte is a modifier byte. */
hid_event.ux_device_class_hid_event_buffer[0] = 0x01;
/* Second byte is reserved. */
hid_event.ux_device_class_hid_event_buffer[1] = 0x02;
/* The 6 next bytes are keys. */
hid_event.ux_device_class_hid_event_buffer[2] = 0x03;
hid_event.ux_device_class_hid_event_buffer[3] = 0x04;
hid_event.ux_device_class_hid_event_buffer[4] = 0x05;
hid_event.ux_device_class_hid_event_buffer[5] = 0x06;
hid_event.ux_device_class_hid_event_buffer[6] = 0x07;
hid_event.ux_device_class_hid_event_buffer[7] = 0x08;
/* Add the event. */
status = ux_device_class_hid_event_set(slave_hid, &hid_event);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Create a transfer request for the GET_REPORT request. We don't need to fill in all the members
because this is not a control transfer request. */
interrupt_endpoint_transfer_request -> ux_transfer_request_data_pointer = buffer;
interrupt_endpoint_transfer_request -> ux_transfer_request_requested_length = hid_event.ux_device_class_hid_event_length;
/* Wait for the device's interrupt thread to pick up the event and send it to us. */
while (1)
{
/* Send request to HCD layer. */
status = ux_host_stack_transfer_request(interrupt_endpoint_transfer_request);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Did we receive it? */
if (buffer[0] == 0x01 &&
buffer[1] == 0x02 &&
buffer[2] == 0x03 &&
buffer[3] == 0x04 &&
buffer[4] == 0x05 &&
buffer[5] == 0x06 &&
buffer[6] == 0x07 &&
buffer[7] == 0x08)
break;
max_get_report_attempts--;
if (max_get_report_attempts == 0)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
ux_utility_thread_sleep(10);
}
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}

View File

@ -0,0 +1,582 @@
/* 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 "ux_host_class_hid.h"
#include "ux_host_class_hid_keyboard.h"
#include "ux_device_class_hid.h"
#include "ux_device_stack.h"
#include "ux_test_utility_sim.h"
#include "ux_test_hcd_sim_host.h"
/* Define constants. */
#define UX_DEMO_DEBUG_SIZE (4096*8)
#define UX_DEMO_STACK_SIZE 1024
#define UX_DEMO_BUFFER_SIZE 2048
#define UX_DEMO_RECEPTION_BUFFER_SIZE 512
#define UX_DEMO_XMIT_BUFFER_SIZE 512
#define UX_DEMO_RECEPTION_BLOCK_SIZE 64
#define UX_DEMO_MEMORY_SIZE (64*1024)
/* Define local/extern function prototypes. */
static void demo_thread_entry(ULONG);
static UINT demo_thread_hid_callback(UX_SLAVE_CLASS_HID *, UX_SLAVE_CLASS_HID_EVENT *);
static TX_THREAD tx_demo_thread_host_simulation;
static TX_THREAD tx_demo_thread_slave_simulation;
static void tx_demo_thread_host_simulation_entry(ULONG);
static void tx_demo_thread_slave_simulation_entry(ULONG);
/* Define global data structures. */
static UCHAR usbx_memory[UX_DEMO_MEMORY_SIZE + (UX_DEMO_STACK_SIZE * 2)];
static ULONG error_counter;
static TX_THREAD demo_thread;
static UX_HOST_CLASS *class_driver;
static ULONG class_driver_index;
static UX_HOST_CLASS_HID *hid;
static UX_HOST_CLASS_HID_CLIENT *hid_client;
static UX_HOST_CLASS_HID_KEYBOARD *keyboard;
static UINT status;
static UINT transfer_completed;
static ULONG requested_length;
static TX_SEMAPHORE demo_semaphore;
static ULONG keyboard_char;
static ULONG keyboard_state;
static UCHAR keyboard_queue[1024];
static ULONG keyboard_queue_index;
static UX_SLAVE_CLASS_HID_PARAMETER hid_parameter;
static UCHAR hid_keyboard_report[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
/* Modifier keys. */
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Padding. */
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
/* LEDs. */
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
/* Padding. */
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
/* Keys. */
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0, // END_COLLECTION
0xa1, 0x01, // COLLECTION (Application)
0x19, 0x01, // USAGE_MINIMUM (1)
0x29, 0x04, // USAGE_MAXIMUM (4)
0x75, 0x04, // REPORT_SIZE (4)
0x95, 0x04, // REPORT_COUNT (4)
0xb1, 0x02, // FEATURE (Data,Var,Abs)
0x85, 0x02, // REPORT_ID (2)
0x19, 0x05, // USAGE_MINIMUM (5)
0x29, 0x07, // USAGE_MAXIMUM (7)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x03, // REPORT_COUNT (3)
0xb1, 0x02, // FEATURE (Data,Var,Abs)
0x85, 0x04, // REPORT_ID (4)
0x09, 0x08, // USAGE (8)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x01, // REPORT_COUNT (1)
0xb1, 0x02, // FEATURE (Data,Var,Abs)
0xc0, // END_COLLECTION
};
#define HID_KEYBOARD_REPORT_LENGTH (sizeof(hid_keyboard_report)/sizeof(hid_keyboard_report[0]))
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, HID_KEYBOARD_REPORT_LENGTH,
0x00,
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, HID_KEYBOARD_REPORT_LENGTH,
0x00,
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
/* 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. */
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_keyboard_basic_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
/* Inform user. */
printf("Running HID Keyboard Basic Functionality Test....................... ");
/* 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 #1\n");
test_control_return(1);
}
/* Register the error callback. */
ux_utility_error_callback_register(ux_test_error_callback);
/* The code below is required for installing the host portion of USBX */
status = ux_host_stack_initialize(UX_NULL);
if (status != UX_SUCCESS)
{
printf("ERROR #2\n");
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("ERROR #3\n");
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
if (status != UX_SUCCESS)
{
printf("ERROR #4\n");
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("ERROR #6\n");
test_control_return(1);
}
/* Initialize the hid class parameters for a keyboard. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_keyboard_report;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_KEYBOARD_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("ERROR #7\n");
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("ERROR #8\n");
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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("ERROR #5\n");
test_control_return(1);
}
/* 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 #9\n");
test_control_return(1);
}
/* Create the main demo thread. */
status = tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0,
stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
20, 20, 1, TX_AUTO_START);
/* Check for error. */
if (status != TX_SUCCESS)
{
printf("ERROR #10\n");
test_control_return(1);
}
}
static UINT demo_class_hid_connect_wait(ULONG nb_loop)
{
UINT status;
UX_HOST_CLASS *class;
/* Find the main HID container */
status = ux_host_stack_class_get(_ux_system_host_class_hid_name, &class);
if (status != UX_SUCCESS)
return(status);
/* We get the first instance of the hid device */
do
{
status = ux_host_stack_class_instance_get(class, 0, (void **) &hid);
if (status == UX_SUCCESS && hid -> ux_host_class_hid_state == UX_HOST_CLASS_INSTANCE_LIVE)
return(UX_SUCCESS);
_ux_utility_delay_ms(10);
} while (nb_loop --);
return(UX_ERROR);
}
static UINT demo_class_hid_disconnect_wait(ULONG nb_loop)
{
UINT status;
UX_HOST_CLASS *class;
/* Find the main HID container */
status = ux_host_stack_class_get(_ux_system_host_class_hid_name, &class);
if (status != UX_SUCCESS)
return(status);
/* We get the first instance of the hid device */
do {
status = ux_host_stack_class_instance_get(class, 0, (void **) &hid);
if (status != UX_SUCCESS)
return(UX_SUCCESS);
_ux_utility_delay_ms(10);
} while(nb_loop --);
return(UX_ERROR);
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UINT max_hid_loop;
/* Initilize max loop value. */
max_hid_loop = 16;
/* Find the HID class */
status = demo_class_hid_connect_wait(50);
if (status != UX_SUCCESS)
{
/* HID Keyboard basic test error. */
printf("ERROR #11\n");
test_control_return(1);
}
/* Get the HID client */
hid_client = hid -> ux_host_class_hid_client;
/* Get the keyboard instance */
keyboard = (UX_HOST_CLASS_HID_KEYBOARD *)hid_client -> ux_host_class_hid_client_local_instance;
/* Init the keyboard queue index. */
keyboard_queue_index = 0;
while (max_hid_loop--)
{
/* Get a key/state from the keyboard. */
status = ux_host_class_hid_keyboard_key_get(keyboard, &keyboard_char, &keyboard_state);
/* Check if there is something. */
if (status == UX_SUCCESS)
{
/* We have a character in the queue. */
keyboard_queue[keyboard_queue_index] = (UCHAR) keyboard_char;
/* Can we accept more ? */
if(keyboard_queue_index < 1024)
keyboard_queue_index++;
}
tx_thread_sleep(10);
}
/* Simulate disconnect. */
ux_test_hcd_sim_host_disconnect();
demo_class_hid_disconnect_wait(5);
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}
static void tx_demo_thread_slave_simulation_entry(ULONG arg)
{
UX_SLAVE_DEVICE *device;
UX_SLAVE_INTERFACE *interface;
UX_SLAVE_CLASS_HID *hid;
UX_SLAVE_CLASS_HID_EVENT hid_event;
UCHAR key;
/* Get the pointer to the device. */
device = &_ux_system_slave -> ux_system_slave_device;
/* Set the first key to 'a' which is 04. */
key = 0x04;
/* reset the HID event structure. */
ux_utility_memory_set(&hid_event, 0, sizeof(UX_SLAVE_CLASS_HID_EVENT));
while(1)
{
/* Is the device configured ? */
while (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
{
#if defined(UX_DEVICE_STANDALONE)
ux_system_tasks_run();
tx_thread_relinquish();
#else
/* Then wait. */
tx_thread_sleep(10);
#endif
}
/* Until the device stays configured. */
while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED)
{
/* Get the interface. We use the first interface, this is a simple device. */
interface = device -> ux_slave_device_first_interface;
/* Form that interface, derive the HID owner. */
hid = interface -> ux_slave_interface_class_instance;
#if defined(UX_DEVICE_STANDALONE)
ULONG tick_to_wait = UX_MS_TO_TICK(2000);
ULONG tick_start = _ux_utility_time_get();
while(_ux_utility_time_elapsed(tick_start, _ux_utility_time_get()) < tick_to_wait)
{
ux_system_tasks_run();
tx_thread_relinquish();
}
#else
/* Wait for 2 seconds. */
ux_utility_thread_sleep(UX_MS_TO_TICK(2000));
#endif
/* Then insert a key into the keyboard event. Length is fixed to 8. */
hid_event.ux_device_class_hid_event_length = 8;
/* First byte is a modifier byte. */
hid_event.ux_device_class_hid_event_buffer[0] = 0;
/* Second byte is reserved. */
hid_event.ux_device_class_hid_event_buffer[1] = 0;
/* The 6 next bytes are keys. We only have one key here. */
hid_event.ux_device_class_hid_event_buffer[2] = key;
/* Set the keyboard event. */
ux_device_class_hid_event_set(hid, &hid_event);
/* Next event has the key depressed. */
hid_event.ux_device_class_hid_event_buffer[2] = 0;
/* Length is fixed to 8. */
hid_event.ux_device_class_hid_event_length = 8;
/* Set the keyboard event. */
ux_device_class_hid_event_set(hid, &hid_event);
/* Are we at the end of alphabet ? */
if (key != (0x04 + 26))
/* Next key. */
key++;
else
/* Start over again. */
key = 0x04;
}
}
}

View File

@ -0,0 +1,378 @@
/* This test concentrates on keyboard device removal. */
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_keyboard.h"
static UCHAR hid_report_descriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
/* Add a feature report to hit some code in _ux_host_class_hid_instance_clean(). */
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0xb1, 0x00, // FEATURE (Data,Ary,Abs)
0xc0 // END_COLLECTION
};
#define HID_REPORT_LENGTH sizeof(hid_report_descriptor)/sizeof(hid_report_descriptor[0])
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[DEVICE_FRAMEWORK_LENGTH_FULL_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
UINT _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter);
static UINT ux_system_host_change_function(ULONG a, UX_HOST_CLASS *b, VOID *c)
{
return 0;
}
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
test_control_return(1);
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_keyboard_extraction_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
UINT descriptor_size = HID_REPORT_LENGTH;
/* Inform user. */
printf("Running HID Device Removal Keyboard Test............................ ");
/* 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 on line %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 host portion of USBX */
status = ux_host_stack_initialize(ux_system_host_change_function);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the hid class parameters. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* 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 on line %d\n", __LINE__);
test_control_return(1);
}
}
static UINT ux_hcd_sim_host_entry_filter_device_extraction_test(UX_HCD *hcd, UINT function, VOID *parameter)
{
UINT status;
switch(function)
{
case UX_HCD_GET_PORT_STATUS:
/* No device on this port. */
status = 0;
/* This is a Full speed device. */
status |= UX_PS_DS_FS;
break;
default:
status = _ux_hcd_sim_host_entry(hcd, function, parameter);
break;
}
return status;
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_HOST_CLASS_HID_KEYBOARD *keyboard;
UX_HCD *hcd;
/* Find the HID class */
status = demo_class_hid_get();
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Get the HID client */
hid_client = hid -> ux_host_class_hid_client;
/* Check if the instance of the keyboard is live */
while (hid_client -> ux_host_class_hid_client_local_instance == UX_NULL)
tx_thread_sleep(10);
/* Get the keyboard instance */
keyboard = (UX_HOST_CLASS_HID_KEYBOARD *)hid_client -> ux_host_class_hid_client_local_instance;
hcd = UX_DEVICE_HCD_GET(hid -> ux_host_class_hid_device);
/* Change the HCD entry function to our filter function. */
hcd -> ux_hcd_entry_function = ux_hcd_sim_host_entry_filter_device_extraction_test;
/* Signal port activity to the enum thread. */
hcd -> ux_hcd_root_hub_signal[0] = 1;
/* Signal enum thread. */
_ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore);
/* Wait for hid class to shut down. */
while(hid -> ux_host_class_hid_state == UX_HOST_CLASS_INSTANCE_LIVE)
tx_thread_sleep(10);
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}

View File

@ -0,0 +1,371 @@
/* This test concentrates on keyboard device removal.
This is similar to the first extraction test, except there is no ux_system_host_change_function.
This allows us to hit the following false condition in _ux_host_class_hid_keyboard_deactivate:
if (_ux_system_host -> ux_system_host_change_function != UX_NULL) */
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_keyboard.h"
static UCHAR hid_report_descriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
/* Add a feature report to hit some code in _ux_host_class_hid_instance_clean(). */
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0xb1, 0x00, // FEATURE (Data,Ary,Abs)
0xc0 // END_COLLECTION
};
#define HID_REPORT_LENGTH sizeof(hid_report_descriptor)/sizeof(hid_report_descriptor[0])
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[DEVICE_FRAMEWORK_LENGTH_FULL_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
UINT _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter);
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
test_control_return(1);
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_keyboard_extraction_test2_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
UINT descriptor_size = HID_REPORT_LENGTH;
/* Inform user. */
printf("Running HID Device Removal Keyboard Test2........................... ");
/* 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 on line %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 host portion of USBX */
status = ux_host_stack_initialize(NULL);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the hid class parameters. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* 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 on line %d\n", __LINE__);
test_control_return(1);
}
}
static UINT ux_hcd_sim_host_entry_filter_device_extraction_test(UX_HCD *hcd, UINT function, VOID *parameter)
{
UINT status;
switch(function)
{
case UX_HCD_GET_PORT_STATUS:
/* No device on this port. */
status = 0;
/* This is a Full speed device. */
status |= UX_PS_DS_FS;
break;
default:
status = _ux_hcd_sim_host_entry(hcd, function, parameter);
break;
}
return status;
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_HCD *hcd;
/* Find the HID class */
status = demo_class_hid_get();
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Get the HID client */
hid_client = hid -> ux_host_class_hid_client;
/* Check if the instance of the keyboard is live */
while (hid_client -> ux_host_class_hid_client_local_instance == UX_NULL)
tx_thread_sleep(10);
hcd = UX_DEVICE_HCD_GET(hid -> ux_host_class_hid_device);
/* Change the HCD entry function to our filter function. */
hcd -> ux_hcd_entry_function = ux_hcd_sim_host_entry_filter_device_extraction_test;
/* Signal port activity to the enum thread. */
hcd -> ux_hcd_root_hub_signal[0] = 1;
/* Signal enum thread. */
_ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore);
/* Wait for hid class to shut down. */
while(hid -> ux_host_class_hid_state == UX_HOST_CLASS_INSTANCE_LIVE)
tx_thread_sleep(10);
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}

View File

@ -0,0 +1,558 @@
/* This test concentrates on the ux_host_class_hid_keyboard_key_get API. */
#include <stdio.h>
#include "tx_api.h"
#include "ux_api.h"
#include "ux_system.h"
#include "ux_utility.h"
#include "ux_host_class_hid.h"
#include "ux_host_class_hid_keyboard.h"
#include "ux_device_class_hid.h"
#include "ux_device_stack.h"
/* Define constants. */
#define UX_DEMO_DEBUG_SIZE (4096*8)
#define UX_DEMO_STACK_SIZE 1024
#define UX_DEMO_BUFFER_SIZE 2048
#define UX_DEMO_RECEPTION_BUFFER_SIZE 512
#define UX_DEMO_XMIT_BUFFER_SIZE 512
#define UX_DEMO_RECEPTION_BLOCK_SIZE 64
#define UX_DEMO_MEMORY_SIZE (64*1024)
/* Define local/extern function prototypes. */
static void demo_thread_entry(ULONG);
static UINT demo_thread_hid_callback(UX_SLAVE_CLASS_HID *, UX_SLAVE_CLASS_HID_EVENT *);
static TX_THREAD tx_demo_thread_host_simulation;
static TX_THREAD tx_demo_thread_slave_simulation;
static void tx_demo_thread_host_simulation_entry(ULONG);
static void tx_demo_thread_slave_simulation_entry(ULONG);
/* Define global data structures. */
static UCHAR usbx_memory[UX_DEMO_MEMORY_SIZE + (UX_DEMO_STACK_SIZE * 2)];
static ULONG error_counter;
static TX_THREAD demo_thread;
static UX_HOST_CLASS *class_driver;
static ULONG class_driver_index;
static UX_HOST_CLASS_HID *hid;
static UX_HOST_CLASS_HID_CLIENT *hid_client;
static UX_HOST_CLASS_HID_KEYBOARD *keyboard;
static UINT status;
static UINT transfer_completed;
static ULONG requested_length;
static TX_SEMAPHORE demo_semaphore;
static ULONG keyboard_char;
static ULONG keyboard_state;
static UCHAR keyboard_queue[1024];
static ULONG keyboard_queue_index;
static UX_SLAVE_CLASS_HID_PARAMETER hid_parameter;
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, 0x3f,
0x00,
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, 0x3f,
0x00,
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
#define HID_KEYBOARD_REPORT_LENGTH 63
static UCHAR hid_keyboard_report[HID_KEYBOARD_REPORT_LENGTH] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
};
/* 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)
{
/* @BUG_FIX_PENDING: ux_dcd_sim_slave_function.c doesn't support transfer aborts, which happen during device unregistration of a class. */
if (error_code != UX_FUNCTION_NOT_SUPPORTED)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
test_control_return(1);
}
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_keyboard_key_get_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
/* Inform user. */
printf("Running HID Keyboard Key Get Test................................... ");
/* 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 on line %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 host portion of USBX */
status = ux_host_stack_initialize(UX_NULL);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the hid class parameters for a keyboard. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_keyboard_report;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_KEYBOARD_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* 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 on line %d\n", __LINE__);
test_control_return(1);
}
/* Create the main demo thread. */
status = tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0,
stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
20, 20, 1, TX_AUTO_START);
/* Check for error. */
if (status != TX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
}
static UINT demo_class_hid_get(void)
{
UINT status;
UX_HOST_CLASS *class;
/* Find the main HID container */
status = ux_host_stack_class_get(_ux_system_host_class_hid_name, &class);
if (status != UX_SUCCESS)
return(status);
/* We get the first instance of the hid device */
do
{
status = ux_host_stack_class_instance_get(class, 0, (void **) &hid);
tx_thread_sleep(10);
} while (status != UX_SUCCESS);
/* We still need to wait for the hid status to be live */
while (hid -> ux_host_class_hid_state != UX_HOST_CLASS_INSTANCE_LIVE)
tx_thread_sleep(10);
return(UX_SUCCESS);
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UINT max_hid_loop;
ALIGN_TYPE tmp;
ULONG key, state;
/* Initilize max loop value. Make sure we wrap. */
max_hid_loop = 2*UX_HOST_CLASS_HID_KEYBOARD_USAGE_ARRAY_LENGTH;
/* Find the HID class */
status = demo_class_hid_get();
if (status != UX_SUCCESS)
{
/* HID Keyboard basic test error. */
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Get the HID client */
hid_client = hid -> ux_host_class_hid_client;
/* Check if the instance of the keyboard is live */
while (hid_client -> ux_host_class_hid_client_local_instance == UX_NULL)
tx_thread_sleep(10);
/* Get the keyboard instance */
keyboard = (UX_HOST_CLASS_HID_KEYBOARD *)hid_client -> ux_host_class_hid_client_local_instance;
/**************************************************/
/** Test case: _ux_host_stack_class_instance_verify() fails. **/
/**************************************************/
/* Set the keyboard's class container to NULL. */
tmp = (ALIGN_TYPE)keyboard -> ux_host_class_hid_keyboard_hid;
keyboard -> ux_host_class_hid_keyboard_hid = UX_NULL;
if(ux_host_class_hid_keyboard_key_get(keyboard, &key, &state) != UX_HOST_CLASS_INSTANCE_UNKNOWN)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Restore state for next test. */
keyboard -> ux_host_class_hid_keyboard_hid = (UX_HOST_CLASS_HID *)tmp;
/**************************************************/
/** Test case: if ((array_tail+2) >= array_end) (wraps) **/
/**************************************************/
/* Init the keyboard queue index. */
keyboard_queue_index = 0;
while (max_hid_loop--)
{
/* Get a key/state from the keyboard. */
status = ux_host_class_hid_keyboard_key_get(keyboard, &keyboard_char, &keyboard_state);
/* Check if there is something. */
if (status == UX_SUCCESS)
{
/* We have a character in the queue. */
keyboard_queue[keyboard_queue_index] = (UCHAR) keyboard_char;
/* Can we accept more ? */
if(keyboard_queue_index < 1024)
keyboard_queue_index++;
}
tx_thread_sleep(1);
}
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}
static void tx_demo_thread_slave_simulation_entry(ULONG arg)
{
UX_SLAVE_DEVICE *device;
UX_SLAVE_INTERFACE *interface;
UX_SLAVE_CLASS_HID *hid;
UX_SLAVE_CLASS_HID_EVENT hid_event;
UCHAR key;
/* Get the pointer to the device. */
device = &_ux_system_slave -> ux_system_slave_device;
/* Set the first key to 'a' which is 04. */
key = 0x04;
/* reset the HID event structure. */
ux_utility_memory_set(&hid_event, 0, sizeof(UX_SLAVE_CLASS_HID_EVENT));
while(1)
{
/* Is the device configured ? */
while (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
/* Then wait. */
tx_thread_sleep(10);
/* Until the device stays configured. */
while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED)
{
/* Get the interface. We use the first interface, this is a simple device. */
interface = device -> ux_slave_device_first_interface;
/* Form that interface, derive the HID owner. */
hid = interface -> ux_slave_interface_class_instance;
/* Wait for 2 seconds. */
ux_utility_thread_sleep(2);
/* Then insert a key into the keyboard event. Length is fixed to 8. */
hid_event.ux_device_class_hid_event_length = 8;
/* First byte is a modifier byte. */
hid_event.ux_device_class_hid_event_buffer[0] = 0;
/* Second byte is reserved. */
hid_event.ux_device_class_hid_event_buffer[1] = 0;
/* The 6 next bytes are keys. We only have one key here. */
hid_event.ux_device_class_hid_event_buffer[2] = key;
/* Set the keyboard event. */
ux_device_class_hid_event_set(hid, &hid_event);
/* Next event has the key depressed. */
hid_event.ux_device_class_hid_event_buffer[2] = 0;
/* Length is fixed to 8. */
hid_event.ux_device_class_hid_event_length = 8;
/* Set the keyboard event. */
ux_device_class_hid_event_set(hid, &hid_event);
/* Are we at the end of alphabet ? */
if (key != (0x04 + 26))
/* Next key. */
key++;
else
/* Start over again. */
key = 0x04;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,722 @@
/* This file tests that the host correctly receives the keys the device sends to it when
the report descriptor defines a non-zero report id. */
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_keyboard.h"
static UCHAR ux_host_class_hid_keyboard_regular_array[] =
{
0,0,0,0,
'a','b','c','d','e','f','g','h','i','j', 'k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'1','2','3','4','5','6','7','8','9','0',
0x0d,0x1b,0x08,0x07,0x20,'-','=','[',']',
'\\','#',';',0x27,'`',',','.','/',0xf0,
0xbb,0xbc,0xbd,0xbe,0xbf,0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,
0x00,0xf1,0x00,0xd2,0xc7,0xc9,0xd3,0xcf,0xd1,0xcd,0xcd,0xd0,0xc8,0xf2,
'/','*','-','+',
0x0d,'1','2','3','4','5','6','7','8','9','0','.','\\',0x00,0x00,'=',
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
static UCHAR ux_host_class_hid_keyboard_shift_array[] =
{
0,0,0,0,
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'!','@','#','$','%','^','&','*','(',')',
0x0d,0x1b,0x08,0x07,0x20,'_','+','{','}',
'|','~',':','"','~','<','>','?',0xf0,
0xbb,0xbc,0xbd,0xbe,0xbf,0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,
0x00,0xf1,0x00,0xd2,0xc7,0xc9,0xd3,0xcf,0xd1,0xcd,0xcd,0xd0,0xc8,0xf2,
'/','*','-','+',
0x0d,'1','2','3','4','5','6','7','8','9','0','.','\\',0x00,0x00,'=',
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
static UCHAR ux_host_class_hid_keyboard_numlock_on_array[] =
{
'/','*','-','+',
0x0d,'1','2','3','4','5','6','7','8','9','0','.','\\',0x00,0x00,'=',
};
static UCHAR ux_host_class_hid_keyboard_numlock_off_array[] =
{
'/','*','-','+',
0x0d,0xcf,0xd0,0xd1,0xcb,'5',0xcd,0xc7,0xc8,0xc9,0xd2,0xd3,'\\',0x00,0x00,'=',
};
#define DUMMY_USBX_MEMORY_SIZE (64*1024)
static UCHAR dummy_usbx_memory[DUMMY_USBX_MEMORY_SIZE];
static UCHAR hid_report_descriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x01, // REPORT_ID (1)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, ARRAY_COUNT(ux_host_class_hid_keyboard_regular_array), // LOGICAL_MAXIMUM ()
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, ARRAY_COUNT(ux_host_class_hid_keyboard_regular_array), // USAGE_MAXIMUM ()
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
};
#define HID_REPORT_LENGTH sizeof(hid_report_descriptor)/sizeof(hid_report_descriptor[0])
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[DEVICE_FRAMEWORK_LENGTH_FULL_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
UINT _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter);
static UINT ux_system_host_change_function(ULONG a, UX_HOST_CLASS *b, VOID *c)
{
return 0;
}
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
test_control_return(1);
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_keyboard_key_with_report_id_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
/* Inform user. */
printf("Running HID Keyboard Key With Report ID Test....................... ");
/* 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 on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Register the error callback. */
_ux_utility_error_callback_register(error_callback);
/* The code below is required for installing the host portion of USBX */
status = ux_host_stack_initialize(ux_system_host_change_function);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Initialize the hid class parameters. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
hid_parameter.ux_device_class_hid_parameter_report_id = 1;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* 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 on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Create the main demo thread. */
status = tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0,
stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
20, 20, 1, TX_AUTO_START);
/* Check for error. */
if (status != TX_SUCCESS)
{
printf("Running HID Keyboard Basic Functionality Test....................... ERROR #10\n");
test_control_return(1);
}
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_HOST_CLASS_HID_KEYBOARD *keyboard;
ULONG keyboard_key;
ULONG keyboard_state;
ULONG expected_key;
ULONG num_keypad_keys;
ULONG i;
/* Find the HID class */
status = demo_class_hid_get();
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Get the HID client */
hid_client = hid -> ux_host_class_hid_client;
/* Check if the instance of the keyboard is live */
while (hid_client -> ux_host_class_hid_client_local_instance == UX_NULL)
tx_thread_sleep(10);
/* Get the keyboard instance */
keyboard = (UX_HOST_CLASS_HID_KEYBOARD *)hid_client -> ux_host_class_hid_client_local_instance;
/** Test receiving maximum keys at once. **/
for (i = 4; i < 10; i++)
{
while (ux_host_class_hid_keyboard_key_get(keyboard, &keyboard_key, &keyboard_state) != UX_SUCCESS)
ux_utility_thread_sleep(1);
expected_key = ux_host_class_hid_keyboard_regular_array[i];
if (keyboard_key != expected_key)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
}
/** Test regular keys. **/
for (i = 1; i < ARRAY_COUNT(ux_host_class_hid_keyboard_regular_array); i++)
{
/* These keys change the keyboard state and are not retrievable. */
if (i == UX_HID_LED_KEY_CAPS_LOCK ||
i == UX_HID_LED_KEY_NUM_LOCK ||
i == UX_HID_LED_KEY_SCROLL_LOCK)
continue;
while (ux_host_class_hid_keyboard_key_get(keyboard, &keyboard_key, &keyboard_state) != UX_SUCCESS)
ux_utility_thread_sleep(1);
expected_key = ux_host_class_hid_keyboard_regular_array[i];
if (keyboard_key != expected_key)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
}
/** Test shift keys. **/
for (i = 1; i < ARRAY_COUNT(ux_host_class_hid_keyboard_regular_array); i++)
{
/* These keys change the keyboard state and are not retrievable. */
if (i == UX_HID_LED_KEY_CAPS_LOCK ||
i == UX_HID_LED_KEY_NUM_LOCK ||
i == UX_HID_LED_KEY_SCROLL_LOCK)
continue;
while (ux_host_class_hid_keyboard_key_get(keyboard, &keyboard_key, &keyboard_state) != UX_SUCCESS)
ux_utility_thread_sleep(1);
expected_key = ux_host_class_hid_keyboard_shift_array[i];
if (keyboard_key != expected_key)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
}
/** Test numlock on keys. **/
num_keypad_keys = (UX_HID_KEYBOARD_KEYS_KEYPAD_UPPER_RANGE - UX_HID_KEYBOARD_KEYS_KEYPAD_LOWER_RANGE) + 1;
for (i = 0; i < ARRAY_COUNT(ux_host_class_hid_keyboard_numlock_on_array); i++)
{
while (ux_host_class_hid_keyboard_key_get(keyboard, &keyboard_key, &keyboard_state) != UX_SUCCESS)
ux_utility_thread_sleep(2);
expected_key = ux_host_class_hid_keyboard_numlock_on_array[i];
if (keyboard_key != ux_host_class_hid_keyboard_numlock_on_array[i])
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
}
/** Test numlock off keys. **/
for (i = 0; i < ARRAY_COUNT(ux_host_class_hid_keyboard_numlock_off_array); i++)
{
while (ux_host_class_hid_keyboard_key_get(keyboard, &keyboard_key, &keyboard_state) != UX_SUCCESS)
ux_utility_thread_sleep(2);
expected_key = ux_host_class_hid_keyboard_numlock_off_array[i];
if (keyboard_key != ux_host_class_hid_keyboard_numlock_off_array[i])
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
}
/** Test keyboard on states. **/
while (ux_host_class_hid_keyboard_key_get(keyboard, &keyboard_key, &keyboard_state) != UX_SUCCESS)
ux_utility_thread_sleep(2);
/* Ensure every bit is enabled (represented by 0xff07 (search for "Define HID Keyboard States." in ux_host_class_hid_keyboard.h)). */
if (keyboard_state != 0xff07)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/** Test keyboard off states. **/
while (ux_host_class_hid_keyboard_key_get(keyboard, &keyboard_key, &keyboard_state) != UX_SUCCESS)
ux_utility_thread_sleep(2);
/* Ensure every bit is disabled. */
if (keyboard_state != 0x0000)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}
static void tx_demo_thread_slave_simulation_entry(ULONG arg)
{
UX_SLAVE_DEVICE *device;
UX_SLAVE_INTERFACE *interface;
UX_SLAVE_CLASS_HID *hid;
UX_SLAVE_CLASS_HID_EVENT hid_event;
UINT i;
/* Get the pointer to the device. */
device = &_ux_system_slave -> ux_system_slave_device;
/* reset the HID event structure. */
ux_utility_memory_set(&hid_event, 0, sizeof(UX_SLAVE_CLASS_HID_EVENT));
/* Is the device configured ? */
while (device->ux_slave_device_state != UX_DEVICE_CONFIGURED)
/* Then wait. */
tx_thread_sleep(10);
/* Get the interface. We use the first interface, this is a simple device. */
interface = device->ux_slave_device_first_interface;
/* Form that interface, derive the HID owner. */
hid = interface->ux_slave_interface_class_instance;
hid_event.ux_device_class_hid_event_report_id = 1;
/** Test receiving maximum keys at once. **/
hid_event.ux_device_class_hid_event_length = 8;
/* Modification byte. */
hid_event.ux_device_class_hid_event_buffer[0] = 0;
/* Reserved byte. */
hid_event.ux_device_class_hid_event_buffer[1] = 0;
/* Set keys. */
for (i = 0; i < 6; i++)
hid_event.ux_device_class_hid_event_buffer[2 + i] = 4 + i;
ux_device_class_hid_event_set(hid, &hid_event);
ux_utility_thread_sleep(2);
/** Test regular keys. Only go up to maximum value specified by report descriptor. **/
for (i = 1; i < ARRAY_COUNT(ux_host_class_hid_keyboard_regular_array); i++)
{
/* These keys change the keyboard state and are not retrievable. */
if (i == UX_HID_LED_KEY_CAPS_LOCK ||
i == UX_HID_LED_KEY_NUM_LOCK ||
i == UX_HID_LED_KEY_SCROLL_LOCK)
continue;
hid_event.ux_device_class_hid_event_length = 8;
/* Modification byte. */
hid_event.ux_device_class_hid_event_buffer[0] = 0;
/* Reserved byte. */
hid_event.ux_device_class_hid_event_buffer[1] = 0;
/* Key byte. */
hid_event.ux_device_class_hid_event_buffer[2] = i;
ux_device_class_hid_event_set(hid, &hid_event);
ux_utility_thread_sleep(2);
}
/** Test shift keys. Only go up to maximum value specified by report descriptor. **/
/* Turn CAPS LOCK on. */
hid_event.ux_device_class_hid_event_length = 8;
hid_event.ux_device_class_hid_event_buffer[0] = 0;
hid_event.ux_device_class_hid_event_buffer[1] = 0;
hid_event.ux_device_class_hid_event_buffer[2] = UX_HID_LED_KEY_CAPS_LOCK;
ux_device_class_hid_event_set(hid, &hid_event);
for (i = 1; i < ARRAY_COUNT(ux_host_class_hid_keyboard_regular_array); i++)
{
/* These keys change the keyboard state and are not retrievable. */
if (i == UX_HID_LED_KEY_CAPS_LOCK ||
i == UX_HID_LED_KEY_NUM_LOCK ||
i == UX_HID_LED_KEY_SCROLL_LOCK)
continue;
hid_event.ux_device_class_hid_event_length = 8;
/* Modification byte. */
hid_event.ux_device_class_hid_event_buffer[0] = 0;
/* Reserved byte. */
hid_event.ux_device_class_hid_event_buffer[1] = 0;
/* Key byte. */
hid_event.ux_device_class_hid_event_buffer[2] = i;
ux_device_class_hid_event_set(hid, &hid_event);
ux_utility_thread_sleep(2);
}
/* Turn CAPS LOCK off. */
hid_event.ux_device_class_hid_event_length = 8;
hid_event.ux_device_class_hid_event_buffer[0] = 0;
hid_event.ux_device_class_hid_event_buffer[1] = 0;
hid_event.ux_device_class_hid_event_buffer[2] = UX_HID_LED_KEY_CAPS_LOCK;
ux_device_class_hid_event_set(hid, &hid_event);
/** Test NUM LOCK on keys. NUM LOCK is on by default. **/
for (i = UX_HID_KEYBOARD_KEYS_KEYPAD_LOWER_RANGE; i <= UX_HID_KEYBOARD_KEYS_KEYPAD_UPPER_RANGE; i++)
{
hid_event.ux_device_class_hid_event_length = 8;
/* Modification byte. */
hid_event.ux_device_class_hid_event_buffer[0] = 0;
/* Reserved byte. */
hid_event.ux_device_class_hid_event_buffer[1] = 0;
/* Key byte. */
hid_event.ux_device_class_hid_event_buffer[2] = i;
ux_device_class_hid_event_set(hid, &hid_event);
ux_utility_thread_sleep(2);
}
/** Test NUM LOCK off keys. **/
/* Turn NUM LOCK off. */
hid_event.ux_device_class_hid_event_length = 8;
hid_event.ux_device_class_hid_event_buffer[0] = 0;
hid_event.ux_device_class_hid_event_buffer[1] = 0;
hid_event.ux_device_class_hid_event_buffer[2] = UX_HID_LED_KEY_NUM_LOCK;
ux_device_class_hid_event_set(hid, &hid_event);
for (i = UX_HID_KEYBOARD_KEYS_KEYPAD_LOWER_RANGE; i <= UX_HID_KEYBOARD_KEYS_KEYPAD_UPPER_RANGE; i++)
{
hid_event.ux_device_class_hid_event_length = 8;
/* Modification byte. */
hid_event.ux_device_class_hid_event_buffer[0] = 0;
/* Reserved byte. */
hid_event.ux_device_class_hid_event_buffer[1] = 0;
/* Key byte. */
hid_event.ux_device_class_hid_event_buffer[2] = i;
ux_device_class_hid_event_set(hid, &hid_event);
ux_utility_thread_sleep(2);
}
/* Turn NUM LOCK on. */
hid_event.ux_device_class_hid_event_length = 8;
hid_event.ux_device_class_hid_event_buffer[0] = 0;
hid_event.ux_device_class_hid_event_buffer[1] = 0;
hid_event.ux_device_class_hid_event_buffer[2] = UX_HID_LED_KEY_NUM_LOCK;
ux_device_class_hid_event_set(hid, &hid_event);
/** Test key states. **/
/* Enable every bit in key state. */
hid_event.ux_device_class_hid_event_length = 8;
hid_event.ux_device_class_hid_event_buffer[0] = 0xff;
hid_event.ux_device_class_hid_event_buffer[1] = 0;
hid_event.ux_device_class_hid_event_buffer[2] = UX_HID_LED_KEY_CAPS_LOCK;
hid_event.ux_device_class_hid_event_buffer[3] = UX_HID_LED_KEY_SCROLL_LOCK;
/* Add a key so the host can receive it, allowing checking of key state. */
hid_event.ux_device_class_hid_event_buffer[4] = 0x04;
ux_device_class_hid_event_set(hid, &hid_event);
/** Test key states. **/
/* Disable every bit in key state. */
hid_event.ux_device_class_hid_event_length = 8;
hid_event.ux_device_class_hid_event_buffer[0] = 0x00;
hid_event.ux_device_class_hid_event_buffer[1] = 0;
hid_event.ux_device_class_hid_event_buffer[2] = UX_HID_LED_KEY_CAPS_LOCK;
hid_event.ux_device_class_hid_event_buffer[3] = UX_HID_LED_KEY_SCROLL_LOCK;
hid_event.ux_device_class_hid_event_buffer[4] = UX_HID_LED_KEY_NUM_LOCK;
/* Add a key so the host can receive it, allowing checking of key state. */
hid_event.ux_device_class_hid_event_buffer[5] = 0x04;
ux_device_class_hid_event_set(hid, &hid_event);
}

View File

@ -0,0 +1,510 @@
/* This test is designed to test simple usage of the mouse class. */
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_keyboard.h"
#include "ux_host_class_hid_mouse.h"
#include "ux_test_utility_sim.h"
#include "ux_test_hcd_sim_host.h"
static UX_HOST_CLASS_HID_MOUSE *mouse;
static UCHAR has_host_received;
static UCHAR hid_mouse_report[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x06, // INPUT (Data,Var,Rel)
0x09, 0x38, // USAGE (Mouse Wheel)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
};
#define HID_MOUSE_REPORT_LENGTH (sizeof(hid_mouse_report)/sizeof(hid_mouse_report[0]))
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_MOUSE_REPORT_LENGTH),
MSB(HID_MOUSE_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_MOUSE_REPORT_LENGTH),
MSB(HID_MOUSE_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
test_control_return(1);
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_mouse_basic_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR *stack_pointer;
CHAR *memory_pointer;
/* Inform user. */
printf("Running HID Mouse Basic Functionality Test.......................... ");
/* 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 on line %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 host portion of USBX */
status = ux_host_stack_initialize(UX_NULL);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_mouse_name, ux_host_class_hid_mouse_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the hid class parameters for a mouse. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_mouse_report;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_MOUSE_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* 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 on line %d\n", __LINE__);
test_control_return(1);
}
/* Create the main demo thread. */
status = tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0,
stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
20, 20, 1, TX_AUTO_START);
/* Check for error. */
if (status != TX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
}
static UINT sleep_break_on_removed(VOID)
{
UINT status;
UX_HOST_CLASS *class;
/* Find the main HID container. */
status = ux_host_stack_class_get(_ux_system_host_class_hid_name, &class);
if (status == UX_SUCCESS)
{
/* Find the instance. */
status = ux_host_stack_class_instance_get(class, 0, (void **) &hid);
if (status != UX_SUCCESS)
return UX_TRUE;
}
return UX_FALSE;
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UINT max_num_loops;
UINT num_loops;
ULONG num_attempts;
ULONG max_attempts;
SLONG cur_mouse_wheel_movement;
SLONG next_mouse_wheel_movement;
SLONG cur_mouse_x_position;
SLONG cur_mouse_y_position;
SLONG next_mouse_x_position;
SLONG next_mouse_y_position;
ULONG cur_mouse_buttons;
UCHAR next_mouse_buttons;
/* Initilize max loop value. */
max_num_loops = 16;
/* Find the HID class */
status = demo_class_hid_get();
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Get the HID client */
hid_client = hid -> ux_host_class_hid_client;
/* Check if the instance of the keyboard is live */
while (hid_client -> ux_host_class_hid_client_local_instance == UX_NULL)
tx_thread_sleep(10);
/* Get the mouse instance */
mouse = (UX_HOST_CLASS_HID_MOUSE *)hid_client -> ux_host_class_hid_client_local_instance;
/* Set number of successful loops to execute. */
num_loops = 0;
max_num_loops = 16;
/* Set number of fails. */
num_attempts = 0;
max_attempts = 3*max_num_loops;
/* Set initial mouse button values. */
next_mouse_buttons = 0x01;
/* Set initial mouse position values. */
next_mouse_x_position = -8;
next_mouse_y_position = -8;
/* Set initial mouse wheel value. */
next_mouse_wheel_movement = -8;
while (num_loops++ != max_num_loops)
{
/* Once one works, the others should work as well. */
while (1)
{
ux_host_class_hid_mouse_buttons_get(mouse, &cur_mouse_buttons);
if (cur_mouse_buttons == next_mouse_buttons)
break;
tx_thread_sleep(10);
}
ux_host_class_hid_mouse_position_get(mouse, &cur_mouse_x_position, &cur_mouse_y_position);
ux_host_class_hid_mouse_wheel_get(mouse, &cur_mouse_wheel_movement);
/* Are these the expected values? */
UX_TEST_ASSERT(cur_mouse_buttons == next_mouse_buttons &&
cur_mouse_x_position == next_mouse_x_position &&
cur_mouse_y_position == next_mouse_y_position &&
cur_mouse_wheel_movement == next_mouse_wheel_movement);
/* Signal to device to continue. */
has_host_received = 1;
/* Increment values. */
next_mouse_buttons = 0x07 & (next_mouse_buttons + 1);
next_mouse_x_position++;
next_mouse_y_position++;
next_mouse_wheel_movement++;
}
/* Simulate detach. */
ux_test_hcd_sim_host_disconnect();
ux_test_breakable_sleep(50, sleep_break_on_removed);
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}
static void tx_demo_thread_slave_simulation_entry(ULONG arg)
{
UX_SLAVE_DEVICE *device;
UX_SLAVE_INTERFACE *interface;
UX_SLAVE_CLASS_HID *hid;
UX_SLAVE_CLASS_HID_EVENT hid_event;
/* Get the pointer to the device. */
device = &_ux_system_slave -> ux_system_slave_device;
/* reset the HID event structure. */
ux_utility_memory_set(&hid_event, 0, sizeof(UX_SLAVE_CLASS_HID_EVENT));
/* Set length of event. */
hid_event.ux_device_class_hid_event_length = 4;
/* Set initial value for buttons. The first three bits are for buttons, the rest are padding. */
hid_event.ux_device_class_hid_event_buffer[0] = 1;
/* Set initial value for x and y positions. */
hid_event.ux_device_class_hid_event_buffer[1] = -8;
hid_event.ux_device_class_hid_event_buffer[2] = -8;
/* Set initial value for mouse wheel. */
hid_event.ux_device_class_hid_event_buffer[3] = -8;
while (1)
{
/* Is the device configured ? */
while (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
{
#if defined(UX_DEVICE_STANDALONE)
ux_system_tasks_run();
tx_thread_relinquish();
#else
/* Then wait. */
tx_thread_sleep(10);
#endif
}
/* Until the device stays configured. */
while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED)
{
#if defined(UX_DEVICE_STANDALONE)
ux_system_tasks_run();
tx_thread_relinquish();
#endif
/* Get the interface. We use the first interface, this is a simple device. */
interface = device -> ux_slave_device_first_interface;
/* From that interface, derive the HID owner. */
hid = interface -> ux_slave_interface_class_instance;
/* Set the mouse event. */
ux_device_class_hid_event_set(hid, &hid_event);
/* Wait for host to receive. */
while (!has_host_received)
{
#if defined(UX_DEVICE_STANDALONE)
ux_system_tasks_run();
tx_thread_relinquish();
#else
tx_thread_sleep(10);
#endif
}
has_host_received = 0;
/* Change the buttons. */
hid_event.ux_device_class_hid_event_buffer[0] = (0x7 & hid_event.ux_device_class_hid_event_buffer[0] + 1);
/* Change the x, y, and wheel positions. These are relative values. */
hid_event.ux_device_class_hid_event_buffer[1] = 1;
hid_event.ux_device_class_hid_event_buffer[2] = 1;
hid_event.ux_device_class_hid_event_buffer[3] = 1;
}
}
}

View File

@ -0,0 +1,370 @@
/* This test is designed to test the extraction of a mouse device. */
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_mouse.h"
static UX_HOST_CLASS_HID_MOUSE *mouse;
static UCHAR hid_mouse_report[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x06, // INPUT (Data,Var,Rel)
0x09, 0x38, // USAGE (Mouse Wheel)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
};
#define HID_MOUSE_REPORT_LENGTH (sizeof(hid_mouse_report)/sizeof(hid_mouse_report[0]))
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_MOUSE_REPORT_LENGTH),
MSB(HID_MOUSE_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_MOUSE_REPORT_LENGTH),
MSB(HID_MOUSE_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
UINT _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter);
static UINT ux_system_host_change_function(ULONG a, UX_HOST_CLASS *b, VOID *c)
{
return 0;
}
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
test_control_return(1);
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_mouse_extraction_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
/* Inform user. */
printf("Running HID Mouse Extraction Test................................... ");
/* 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 on line %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 host portion of USBX */
status = ux_host_stack_initialize(ux_system_host_change_function);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_mouse_name, ux_host_class_hid_mouse_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the hid class parameters for a mouse. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_mouse_report;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_MOUSE_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* 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 on line %d\n", __LINE__);
test_control_return(1);
}
}
static UINT ux_hcd_sim_host_entry_filter_device_extraction_test(UX_HCD *hcd, UINT function, VOID *parameter)
{
UINT status;
switch(function)
{
case UX_HCD_GET_PORT_STATUS:
/* No device on this port. */
status = 0;
/* This is a Full speed device. */
status |= UX_PS_DS_FS;
break;
default:
status = _ux_hcd_sim_host_entry(hcd, function, parameter);
break;
}
return status;
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_HCD *hcd;
/* Find the HID class */
status = demo_class_hid_get();
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Get the HID client */
hid_client = hid -> ux_host_class_hid_client;
/* Check if the instance of the keyboard is live */
while (hid_client -> ux_host_class_hid_client_local_instance == UX_NULL)
tx_thread_sleep(10);
/* Get the mouse instance */
mouse = (UX_HOST_CLASS_HID_MOUSE *)hid_client -> ux_host_class_hid_client_local_instance;
hcd = UX_DEVICE_HCD_GET(hid -> ux_host_class_hid_device);
/* Change the HCD entry function to our filter function. */
hcd -> ux_hcd_entry_function = ux_hcd_sim_host_entry_filter_device_extraction_test;
/* Signal port activity to the enum thread. */
hcd -> ux_hcd_root_hub_signal[0] = 1;
/* Signal enum thread. */
_ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore);
/* Wait for hid class to shut down. */
while(hid -> ux_host_class_hid_state == UX_HOST_CLASS_INSTANCE_LIVE)
tx_thread_sleep(10);
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}

View File

@ -0,0 +1,369 @@
/* This test is designed to test the extraction of a mouse device.
This is similar to the first extraction test, except there is no ux_system_host_change_function.
This allows us to hit the following false condition in _ux_host_class_hid_mouse_deactivate:
if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
*/
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_mouse.h"
static UX_HOST_CLASS_HID_MOUSE *mouse;
static UCHAR hid_mouse_report[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x06, // INPUT (Data,Var,Rel)
0x09, 0x38, // USAGE (Mouse Wheel)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
};
#define HID_MOUSE_REPORT_LENGTH (sizeof(hid_mouse_report)/sizeof(hid_mouse_report[0]))
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_MOUSE_REPORT_LENGTH),
MSB(HID_MOUSE_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_MOUSE_REPORT_LENGTH),
MSB(HID_MOUSE_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
UINT _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter);
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
test_control_return(1);
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_mouse_extraction_test2_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
/* Inform user. */
printf("Running HID Mouse Extraction Test 2................................. ");
/* 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 on line %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 host portion of USBX */
status = ux_host_stack_initialize(NULL);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_mouse_name, ux_host_class_hid_mouse_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the hid class parameters for a mouse. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_mouse_report;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_MOUSE_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* 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 on line %d\n", __LINE__);
test_control_return(1);
}
}
static UINT ux_hcd_sim_host_entry_filter_device_extraction_test(UX_HCD *hcd, UINT function, VOID *parameter)
{
UINT status;
switch(function)
{
case UX_HCD_GET_PORT_STATUS:
/* No device on this port. */
status = 0;
/* This is a Full speed device. */
status |= UX_PS_DS_FS;
break;
default:
status = _ux_hcd_sim_host_entry(hcd, function, parameter);
break;
}
return status;
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_HCD *hcd;
/* Find the HID class */
status = demo_class_hid_get();
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Get the HID client */
hid_client = hid -> ux_host_class_hid_client;
/* Check if the instance of the keyboard is live */
while (hid_client -> ux_host_class_hid_client_local_instance == UX_NULL)
tx_thread_sleep(10);
/* Get the mouse instance */
mouse = (UX_HOST_CLASS_HID_MOUSE *)hid_client -> ux_host_class_hid_client_local_instance;
hcd = UX_DEVICE_HCD_GET(hid -> ux_host_class_hid_device);
/* Change the HCD entry function to our filter function. */
hcd -> ux_hcd_entry_function = ux_hcd_sim_host_entry_filter_device_extraction_test;
/* Signal port activity to the enum thread. */
hcd -> ux_hcd_root_hub_signal[0] = 1;
/* Signal enum thread. */
_ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore);
/* Wait for hid class to shut down. */
while(hid -> ux_host_class_hid_state == UX_HOST_CLASS_INSTANCE_LIVE)
tx_thread_sleep(10);
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}

View File

@ -0,0 +1,361 @@
/* This test is concentrates on extraction of a remote control device. */
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_remote_control.h"
static UX_HOST_CLASS_HID_REMOTE_CONTROL *remote_control;
static UCHAR hid_remote_control_report[] = {
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x09, 0x01, // USAGE (Consumer Control)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x02, // USAGE (Numeric Key Pad)
0xa1, 0x02, // COLLECTION (Logical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x0a, // USAGE_MAXIMUM (Button 10)
0x15, 0x01, // LOGICAL_MINIMUM (1)
0x25, 0x0a, // LOGICAL_MAXIMUM (10)
0x75, 0x04, // REPORT_SIZE (4)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0, // END_COLLECTION
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x09, 0x86, // USAGE (Channel)
0x09, 0xe0, // USAGE (Volume)
0x15, 0xff, // LOGICAL_MINIMUM (-1)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x02, // REPORT_SIZE (2)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x46, // INPUT (Data,Var,Rel,Null)
0xc0 // END_COLLECTION
};
#define HID_REMOTE_CONTROL_REPORT_LENGTH (sizeof(hid_remote_control_report)/sizeof(hid_remote_control_report[0]))
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REMOTE_CONTROL_REPORT_LENGTH),
MSB(HID_REMOTE_CONTROL_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REMOTE_CONTROL_REPORT_LENGTH),
MSB(HID_REMOTE_CONTROL_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
UINT _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter);
static UINT ux_system_host_change_function(ULONG a, UX_HOST_CLASS *b, VOID *c)
{
return 0;
}
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
test_control_return(1);
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_remote_control_extraction_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
/* Inform user. */
printf("Running HID Remote Control Extraction Test.......................... ");
/* 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 on line %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 host portion of USBX */
status = ux_host_stack_initialize(ux_system_host_change_function);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_remote_control_name, ux_host_class_hid_remote_control_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the hid class parameters for a mouse. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_remote_control_report;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_REMOTE_CONTROL_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* 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 on line %d\n", __LINE__);
test_control_return(1);
}
}
static UINT ux_hcd_sim_host_entry_filter_device_extraction_test(UX_HCD *hcd, UINT function, VOID *parameter)
{
UINT status;
switch(function)
{
case UX_HCD_GET_PORT_STATUS:
/* No device on this port. */
status = 0;
/* This is a Full speed device. */
status |= UX_PS_DS_FS;
break;
default:
status = _ux_hcd_sim_host_entry(hcd, function, parameter);
break;
}
return status;
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_HCD *hcd;
/* Find the HID class */
status = demo_class_hid_get();
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Get the HID client */
hid_client = hid -> ux_host_class_hid_client;
/* Check if the instance of the keyboard is live */
while (hid_client -> ux_host_class_hid_client_local_instance == UX_NULL)
tx_thread_sleep(10);
/* Get the mouse instance */
remote_control = (UX_HOST_CLASS_HID_REMOTE_CONTROL *)hid_client -> ux_host_class_hid_client_local_instance;
hcd = UX_DEVICE_HCD_GET(hid -> ux_host_class_hid_device);
/* Change the HCD entry function to our filter function. */
hcd -> ux_hcd_entry_function = ux_hcd_sim_host_entry_filter_device_extraction_test;
/* Signal port activity to the enum thread. */
hcd -> ux_hcd_root_hub_signal[0] = 1;
/* Signal enum thread. */
_ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore);
/* Wait for hid class to shut down. */
while(hid -> ux_host_class_hid_state == UX_HOST_CLASS_INSTANCE_LIVE)
tx_thread_sleep(10);
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}

View File

@ -0,0 +1,358 @@
/* This test is concentrates on extraction of a remote control device.
This is similar to the first extraction test, except there is no ux_system_host_change_function.
This allows us to hit the following false condition in _ux_host_class_hid_remote_control_deactivate:
if (_ux_system_host -> ux_system_host_change_function != UX_NULL) */
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_remote_control.h"
static UX_HOST_CLASS_HID_REMOTE_CONTROL *remote_control;
static UCHAR hid_remote_control_report[] = {
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x09, 0x01, // USAGE (Consumer Control)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x02, // USAGE (Numeric Key Pad)
0xa1, 0x02, // COLLECTION (Logical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x0a, // USAGE_MAXIMUM (Button 10)
0x15, 0x01, // LOGICAL_MINIMUM (1)
0x25, 0x0a, // LOGICAL_MAXIMUM (10)
0x75, 0x04, // REPORT_SIZE (4)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0, // END_COLLECTION
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x09, 0x86, // USAGE (Channel)
0x09, 0xe0, // USAGE (Volume)
0x15, 0xff, // LOGICAL_MINIMUM (-1)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x02, // REPORT_SIZE (2)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x46, // INPUT (Data,Var,Rel,Null)
0xc0 // END_COLLECTION
};
#define HID_REMOTE_CONTROL_REPORT_LENGTH (sizeof(hid_remote_control_report)/sizeof(hid_remote_control_report[0]))
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REMOTE_CONTROL_REPORT_LENGTH),
MSB(HID_REMOTE_CONTROL_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REMOTE_CONTROL_REPORT_LENGTH),
MSB(HID_REMOTE_CONTROL_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
UINT _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter);
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
test_control_return(1);
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_remote_control_extraction_test2_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
/* Inform user. */
printf("Running HID Remote Control Extraction Test 2........................ ");
/* 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 on line %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 host portion of USBX */
status = ux_host_stack_initialize(NULL);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_remote_control_name, ux_host_class_hid_remote_control_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the hid class parameters for a mouse. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_remote_control_report;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_REMOTE_CONTROL_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* 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 on line %d\n", __LINE__);
test_control_return(1);
}
}
static UINT ux_hcd_sim_host_entry_filter_device_extraction_test(UX_HCD *hcd, UINT function, VOID *parameter)
{
UINT status;
switch(function)
{
case UX_HCD_GET_PORT_STATUS:
/* No device on this port. */
status = 0;
/* This is a Full speed device. */
status |= UX_PS_DS_FS;
break;
default:
status = _ux_hcd_sim_host_entry(hcd, function, parameter);
break;
}
return status;
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_HCD *hcd;
/* Find the HID class */
status = demo_class_hid_get();
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Get the HID client */
hid_client = hid -> ux_host_class_hid_client;
/* Check if the instance of the keyboard is live */
while (hid_client -> ux_host_class_hid_client_local_instance == UX_NULL)
tx_thread_sleep(10);
/* Get the mouse instance */
remote_control = (UX_HOST_CLASS_HID_REMOTE_CONTROL *)hid_client -> ux_host_class_hid_client_local_instance;
hcd = UX_DEVICE_HCD_GET(hid -> ux_host_class_hid_device);
/* Change the HCD entry function to our filter function. */
hcd -> ux_hcd_entry_function = ux_hcd_sim_host_entry_filter_device_extraction_test;
/* Signal port activity to the enum thread. */
hcd -> ux_hcd_root_hub_signal[0] = 1;
/* Signal enum thread. */
_ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore);
/* Wait for hid class to shut down. */
while(hid -> ux_host_class_hid_state == UX_HOST_CLASS_INSTANCE_LIVE)
tx_thread_sleep(10);
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}

View File

@ -0,0 +1,692 @@
/* TODO: some common stuff from storage we might want to pull out:
-memory check - pretty good
-connect and disconnect
-getting class/instance
*/
#include "ux_api.h"
#include "ux_utility.h"
#include "ux_host_class_hid.h"
#include "ux_device_class_hid.h"
#include "ux_host_class_hid_remote_control.h"
#include "ux_test.h"
#include "ux_test_actions.h"
#include "ux_test_dcd_sim_slave.h"
#include "ux_test_hcd_sim_host.h"
#define LSB(x) (x & 0xff)
#define MSB(x) ((x & 0xff00) >> 8)
/* Define constants. */
#define UX_DEMO_STACK_SIZE 1024
#define UX_DEMO_MEMORY_SIZE (64*1024)
/* Define local/extern function prototypes. */
static void test_main_thread_entry(ULONG);
/* Define global data structures. */
static UCHAR usbx_memory[UX_DEMO_MEMORY_SIZE + (UX_DEMO_STACK_SIZE * 2)];
static TX_THREAD test_main_thread;
static TX_THREAD test_slave_thread;
static UCHAR test_slave_thread_stack[4096];
static UX_HOST_CLASS *global_host_hid_class;
static UX_HOST_CLASS_HID *global_host_hid;
static UX_SLAVE_CLASS_HID *global_slave_hid;
static UX_SLAVE_CLASS_HID *global_slave_hid_persistent;
static UX_HOST_CLASS_HID_CLIENT *global_host_hid_client;
static UX_HOST_CLASS_HID_REMOTE_CONTROL *global_host_remote_control;
static UX_SLAVE_CLASS_HID_PARAMETER global_slave_hid_parameter;
static UX_HCD *global_hcd;
static UCHAR hid_report_descriptor[] = {
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x09, 0x01, // USAGE (Consumer Control)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x02, // USAGE (Numeric Key Pad)
0xa1, 0x02, // COLLECTION (Logical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x0a, // USAGE_MAXIMUM (Button 10)
0x15, 0x01, // LOGICAL_MINIMUM (1)
0x25, 0x0a, // LOGICAL_MAXIMUM (10)
0x75, 0x04, // REPORT_SIZE (4)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0, // END_COLLECTION
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x09, 0x86, // USAGE (Channel)
0x09, 0xe0, // USAGE (Volume)
0x15, 0xff, // LOGICAL_MINIMUM (-1)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x02, // REPORT_SIZE (2)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x46, // INPUT (Data,Var,Rel,Null)
0xc0 // END_COLLECTION
};
static UCHAR device_framework_full_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(sizeof(hid_report_descriptor)),
MSB(sizeof(hid_report_descriptor)),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define FULL_SPEED_REPORT_DESCRIPTOR_LENGTH_LSB_POS (0x12 + 0x09 + 0x09 + 0x7)
#define FULL_SPEED_REPORT_DESCRIPTOR_LENGTH_MSB_POS (FULL_SPEED_REPORT_DESCRIPTOR_LENGTH_LSB_POS + 1)
static UCHAR device_framework_high_speed[] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(sizeof(hid_report_descriptor)),
MSB(sizeof(hid_report_descriptor)),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define HIGH_SPEED_REPORT_DESCRIPTOR_LENGTH_LSB_POS (0x12 + 0x0a + 0x09 + 0x09 + 0x7)
#define HIGH_SPEED_REPORT_DESCRIPTOR_LENGTH_MSB_POS (HIGH_SPEED_REPORT_DESCRIPTOR_LENGTH_LSB_POS + 1)
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
/* Functions from storage basic test. */
static VOID get_global_hid_values()
{
UX_TEST_CHECK_SUCCESS(ux_host_stack_class_get(_ux_system_host_class_hid_name, &global_host_hid_class));
UX_TEST_CHECK_SUCCESS(ux_host_stack_class_instance_get(global_host_hid_class, 0, (void **) &global_host_hid));
UX_TEST_ASSERT(global_host_hid -> ux_host_class_hid_state == UX_HOST_CLASS_INSTANCE_LIVE);
global_host_hid_client = global_host_hid -> ux_host_class_hid_client;
UX_TEST_ASSERT(global_host_hid_client -> ux_host_class_hid_client_local_instance != UX_NULL);
global_host_remote_control = (UX_HOST_CLASS_HID_REMOTE_CONTROL *)global_host_hid_client -> ux_host_class_hid_client_local_instance;
}
static VOID wait_for_enum_completion_and_get_global_hid_values()
{
ux_test_wait_for_enum_thread_completion();
get_global_hid_values();
}
/* Returns whether or not the enumeration succeeded. */
static VOID connect_host_and_slave()
{
ux_test_connect_slave_and_host_wait_for_enum_completion();
get_global_hid_values();
}
/* General HID utilities. */
void set_report_descriptor(UCHAR *report_descriptor, ULONG report_descriptor_length)
{
/* Should only be called if the host and slave is disconnected. */
UX_TEST_ASSERT(global_hcd->ux_hcd_nb_devices == 0);
UX_TEST_ASSERT(_ux_system_slave->ux_system_slave_device.ux_slave_device_state == UX_DEVICE_RESET);
global_slave_hid_persistent->ux_device_class_hid_report_address = report_descriptor;
global_slave_hid_persistent->ux_device_class_hid_report_length = report_descriptor_length;
device_framework_full_speed[FULL_SPEED_REPORT_DESCRIPTOR_LENGTH_LSB_POS] = LSB(report_descriptor_length);
device_framework_full_speed[FULL_SPEED_REPORT_DESCRIPTOR_LENGTH_MSB_POS] = MSB(report_descriptor_length);
device_framework_high_speed[HIGH_SPEED_REPORT_DESCRIPTOR_LENGTH_LSB_POS] = LSB(report_descriptor_length);
device_framework_high_speed[HIGH_SPEED_REPORT_DESCRIPTOR_LENGTH_MSB_POS] = MSB(report_descriptor_length);
}
UINT slave_hid_callback(UX_SLAVE_CLASS_HID *hid, UX_SLAVE_CLASS_HID_EVENT *event)
{
return 0;
}
VOID slave_class_hid_instance_activate(VOID *instance)
{
if (global_slave_hid_persistent)
UX_TEST_ASSERT(global_slave_hid_persistent == instance);
global_slave_hid_persistent = instance;
global_slave_hid = instance;
}
VOID slave_class_hid_instance_deactivate(VOID *instance)
{
global_slave_hid = UX_NULL;
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_remote_control_tests_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR *stack_pointer;
CHAR *memory_pointer;
/* Inform user. */
printf("Running HID Remote Control Tests.................................... ");
stepinfo("\n");
/* 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 on line %d\n", __LINE__);
test_control_return(1);
}
/* Register the error callback. */
_ux_utility_error_callback_register(ux_test_error_callback);
/* The code below is required for installing the host portion of USBX */
status = ux_host_stack_initialize(UX_NULL);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_remote_control_name, ux_host_class_hid_remote_control_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, sizeof(device_framework_high_speed),
device_framework_full_speed, sizeof(device_framework_full_speed),
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH, UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the hid class parameters for a mouse. */
global_slave_hid_parameter.ux_slave_class_hid_instance_activate = slave_class_hid_instance_activate;
global_slave_hid_parameter.ux_slave_class_hid_instance_deactivate = slave_class_hid_instance_deactivate;
global_slave_hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
global_slave_hid_parameter.ux_device_class_hid_parameter_report_length = sizeof(hid_report_descriptor);
global_slave_hid_parameter.ux_device_class_hid_parameter_callback = slave_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2. */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1, 2, (VOID *)&global_slave_hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
global_hcd = &_ux_system_host->ux_system_host_hcd_array[0];
/* Create the main host simulation thread. */
status = tx_thread_create(&test_main_thread, "test_main_thread", test_main_thread_entry, 0,
stack_pointer, UX_DEMO_STACK_SIZE,
20, 20, 1, TX_AUTO_START);
/* Check for error. */
if (status != TX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
}
/* basic_test resources */
static UINT basic_test_get_next_channel_volume_value(ULONG value)
{
if (value == 0x03)
return 0x00;
else if (value == 0x00)
return 0x01;
else if (value == 0x01)
return 0x03;
return 0xff;
}
static void basic_test_slave_thread_entry(ULONG arg)
{
UX_SLAVE_CLASS_HID_EVENT hid_event;
ULONG value;
UINT max_num_loops;
/* reset the HID event structure. */
ux_utility_memory_set(&hid_event, 0, sizeof(UX_SLAVE_CLASS_HID_EVENT));
/* Set length of event. */
hid_event.ux_device_class_hid_event_length = 1;
/* Set initial keypad value. */
hid_event.ux_device_class_hid_event_buffer[0] = 0x01;
/* Set initial channel value. */
hid_event.ux_device_class_hid_event_buffer[0] |= (0x03 << 4);
/* Set initial volume value. */
hid_event.ux_device_class_hid_event_buffer[0] |= (0x01 << 6);
max_num_loops = 2*UX_HOST_CLASS_HID_REMOTE_CONTROL_USAGE_ARRAY_LENGTH;
while (max_num_loops--)
{
stepinfo(" slave - max_num_loops: %d\n", max_num_loops);
/* Wait for host to receive. */
ux_utility_thread_sleep(2);
/* Set the mouse event. */
UX_TEST_CHECK_SUCCESS(ux_device_class_hid_event_set(global_slave_hid, &hid_event));
/* Change keypad value. */
value = hid_event.ux_device_class_hid_event_buffer[0] & 0x0f;
if (value >= 0x0a)
value = 0x01;
else
value++;
hid_event.ux_device_class_hid_event_buffer[0] &= 0xf0;
hid_event.ux_device_class_hid_event_buffer[0] |= value;
/* Change channel value. */
value = ((hid_event.ux_device_class_hid_event_buffer[0] & 0x30) >> 4);
hid_event.ux_device_class_hid_event_buffer[0] &= ~0x30;
hid_event.ux_device_class_hid_event_buffer[0] |= (basic_test_get_next_channel_volume_value(value) << 4);
/* Change volume value. */
value = ((hid_event.ux_device_class_hid_event_buffer[0] & 0xc0) >> 6);
hid_event.ux_device_class_hid_event_buffer[0] &= ~0xc0;
hid_event.ux_device_class_hid_event_buffer[0] |= (basic_test_get_next_channel_volume_value(value) << 6);
}
}
static void basic_test()
{
UINT max_num_loops;
ULONG usage;
ULONG value;
ULONG expected_keypad_value;
ULONG expected_channel_value;
ULONG expected_volume_value;
stepinfo("basic_test\n");
UX_TEST_CHECK_SUCCESS(tx_thread_create(&test_slave_thread, "test_slave_thread", basic_test_slave_thread_entry, 0,
test_slave_thread_stack, UX_DEMO_STACK_SIZE,
20, 20, 1, TX_AUTO_START));
/* Initialize expected values. */
expected_keypad_value = 0x01;
expected_channel_value = 0x03;
expected_volume_value = 0x01;
/* Set number of successful loops to execute. */
max_num_loops = 2*UX_HOST_CLASS_HID_REMOTE_CONTROL_USAGE_ARRAY_LENGTH;
while (max_num_loops--)
{
stepinfo(" host - max_num_loops: %d\n", max_num_loops);
/* Wait for an event from the device. Each event should have 3 usages. The first is the keypad. */
while (ux_host_class_hid_remote_control_usage_get(global_host_remote_control, &usage, &value) != UX_SUCCESS)
tx_thread_sleep(1);
if (usage != (0x00090000 | expected_keypad_value) || value != expected_keypad_value)
{
printf("Error on line %d. usage: 0x%lx, expected usage: 0x%lx, value: 0x%lx, expected_keypad_value: 0x%lx\n",
__LINE__, usage, 0x00090000 | expected_keypad_value, value, expected_keypad_value);
test_control_return(1);
}
if (++expected_keypad_value > 0x0a)
expected_keypad_value = 1;
/* Get the channel value. */
ux_host_class_hid_remote_control_usage_get(global_host_remote_control, &usage, &value);
if (usage != 0x000c0086 || value != expected_channel_value)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
expected_channel_value = basic_test_get_next_channel_volume_value(value);
/* Get the volume value. */
ux_host_class_hid_remote_control_usage_get(global_host_remote_control, &usage, &value);
if (usage != 0x000c00e0 || value != expected_volume_value)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
expected_volume_value = basic_test_get_next_channel_volume_value(value);
}
UX_TEST_CHECK_SUCCESS(tx_thread_terminate(&test_slave_thread));
UX_TEST_CHECK_SUCCESS(tx_thread_delete(&test_slave_thread));
}
/* event_overflow_test resources */
#define EBT_MAX_EVENTS ((UX_HOST_CLASS_HID_REMOTE_CONTROL_USAGE_ARRAY_LENGTH/2) - 1)
#define EBT_NUM_OVERFLOW_EVENTS 100
static TX_SEMAPHORE ebt_slave_wakes_host_semaphore;
static TX_SEMAPHORE ebt_host_wakes_slave_semaphore;
static UCHAR host_event_buffer_test_hid_report_descriptor[] = {
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x09, 0x01, // USAGE (Consumer Control)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
0x09, 0xe0, // USAGE (Volume)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0xff, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x46, // INPUT (Data,Var,Rel,Null)
0xc0 // END_COLLECTION
};
static void event_buffer_test_slave_thread_entry(ULONG arg)
{
UX_SLAVE_CLASS_HID_EVENT hid_event = { 0 };
UINT i;
/* Add the exact amount. Remember, the host's usage array consists of pairs,
hence the divide by two. */
for (i = 0; i < EBT_MAX_EVENTS; i++)
{
/* Setup and send event. */
hid_event.ux_device_class_hid_event_length = 1;
hid_event.ux_device_class_hid_event_buffer[0] = i;
UX_TEST_CHECK_SUCCESS(ux_device_class_hid_event_set(global_slave_hid, &hid_event));
/* Wait for host to receive it. */
tx_thread_sleep(2);
}
/* Wake up host test thread. */
tx_semaphore_put(&ebt_slave_wakes_host_semaphore);
/* Wait for second part of test. */
tx_semaphore_get(&ebt_host_wakes_slave_semaphore, TX_WAIT_FOREVER);
/* We expect to receive some errors. */
ux_test_add_action_to_main_list_multiple(create_error_match_action(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW), EBT_NUM_OVERFLOW_EVENTS);
for (i = 0; i < EBT_MAX_EVENTS + EBT_NUM_OVERFLOW_EVENTS; i++)
{
/* Setup and send event. */
hid_event.ux_device_class_hid_event_length = 1;
hid_event.ux_device_class_hid_event_buffer[0] = i;
UX_TEST_CHECK_SUCCESS(ux_device_class_hid_event_set(global_slave_hid, &hid_event));
/* Wait for host to receive it. */
tx_thread_sleep(2);
}
/* Ensure all of our actions are gone. */
UX_TEST_ASSERT_MESSAGE(ux_test_check_actions_empty(), "Number of actions remaining: %d\n", ux_test_get_num_actions_left());
/* Wake up host test thread. */
tx_semaphore_put(&ebt_slave_wakes_host_semaphore);
}
static void host_event_buffer_test()
{
ULONG usage;
ULONG value;
UINT i;
stepinfo("event_buffer_overflow_test\n");
ux_test_disconnect_slave_and_host_wait_for_enum_completion(global_hcd);
set_report_descriptor(host_event_buffer_test_hid_report_descriptor, sizeof(host_event_buffer_test_hid_report_descriptor));
connect_host_and_slave();
UX_TEST_CHECK_SUCCESS(tx_semaphore_create(&ebt_slave_wakes_host_semaphore, "ebt_slave_wakes_host_semaphore", 0));
UX_TEST_CHECK_SUCCESS(tx_semaphore_create(&ebt_host_wakes_slave_semaphore, "ebt_host_wakes_slave_semaphore", 0));
UX_TEST_CHECK_SUCCESS(tx_thread_create(&test_slave_thread, "test_slave_thread", event_buffer_test_slave_thread_entry, 0,
test_slave_thread_stack, UX_DEMO_STACK_SIZE,
20, 20, 1, TX_AUTO_START));
stepinfo(" exact amount\n");
/* Wait for slave to send exact amount. */
tx_semaphore_get(&ebt_slave_wakes_host_semaphore, TX_WAIT_FOREVER);
/* Ensure exact amount was sent. */
for (i = 0; i < EBT_MAX_EVENTS; i++)
{
UX_TEST_CHECK_SUCCESS(ux_host_class_hid_remote_control_usage_get(global_host_remote_control, &usage, &value));
UX_TEST_ASSERT(usage == 0x000c00e0);
UX_TEST_ASSERT(value == i);
}
/* Should be no more. */
UX_TEST_CHECK_NOT_SUCCESS(ux_host_class_hid_remote_control_usage_get(global_host_remote_control, &usage, &value));
stepinfo(" overflow\n");
/* Wake up slave. */
tx_semaphore_put(&ebt_host_wakes_slave_semaphore);
/* Wait for slave to overflow. */
tx_semaphore_get(&ebt_slave_wakes_host_semaphore, TX_WAIT_FOREVER);
/* Ensure exact amount was sent. */
for (i = 0; i < EBT_MAX_EVENTS; i++)
{
UX_TEST_CHECK_SUCCESS(ux_host_class_hid_remote_control_usage_get(global_host_remote_control, &usage, &value));
UX_TEST_ASSERT(usage == 0x000c00e0);
UX_TEST_ASSERT(value == i);
}
/* Should be no more. */
UX_TEST_CHECK_NOT_SUCCESS(ux_host_class_hid_remote_control_usage_get(global_host_remote_control, &usage, &value));
UX_TEST_CHECK_SUCCESS(tx_thread_terminate(&test_slave_thread));
UX_TEST_CHECK_SUCCESS(tx_thread_delete(&test_slave_thread));
}
static void test_main_thread_entry(ULONG arg)
{
UINT status;
UINT i;
void (*tests[])() =
{
basic_test,
host_event_buffer_test,
};
ux_test_wait_for_enum_thread_completion();
get_global_hid_values();
ux_test_memory_test_initialize();
get_global_hid_values();
/* Run tests. */
for (i = 0; i < ARRAY_COUNT(tests); i++)
{
tests[i]();
ux_test_disconnect_slave_and_host_wait_for_enum_completion(global_hcd);
set_report_descriptor(hid_report_descriptor, sizeof(hid_report_descriptor));
connect_host_and_slave();
UX_TEST_ASSERT(ux_test_check_actions_empty());
}
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}

View File

@ -0,0 +1,313 @@
/* This test ensures that the parser fails when too many collections are used. */
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_keyboard.h"
static UINT callback_error_code;
static UCHAR hid_report_descriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x02, // REPORT_SIZE (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xa1, 0x00, // COLLECTION (Physical)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x04, // REPORT_SIZE (4)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xa1, 0x00, // COLLECTION (Physical)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x06, // REPORT_SIZE (6)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xa1, 0x00, // COLLECTION (Physical)
0x95, 0x07, // REPORT_COUNT (7)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Add 5th collection (should break). */
0xa1, 0x00, // COLLECTION (Physical)
0x95, 0x07, // REPORT_COUNT (7)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
};
#define HID_REPORT_LENGTH sizeof(hid_report_descriptor)/sizeof(hid_report_descriptor[0])
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[DEVICE_FRAMEWORK_LENGTH_FULL_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
if (error_code != UX_HOST_CLASS_HID_COLLECTION_OVERFLOW &&
error_code != UX_DESCRIPTOR_CORRUPTED &&
error_code != UX_DEVICE_ENUMERATION_FAILURE)
{
/* Something went wrong. */
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_report_descriptor_collection_overflow_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
UINT descriptor_size = HID_REPORT_LENGTH;
/* Inform user. */
printf("Running HID Report Descriptor Collection Oveflow Test............... ");
/* 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 on line %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 host portion of USBX */
status = ux_host_stack_initialize(UX_NULL);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the hid class parameters. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* 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 on line %d\n", __LINE__);
test_control_return(1);
}
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
/* Find the HID class */
status = demo_class_hid_get();
if (status == UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}

View File

@ -0,0 +1,502 @@
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_keyboard.h"
static SLONG input_report_buffer_decompressed_original[1024];
static UCHAR input_report_buffer_compressed[1024];
static SLONG input_report_buffer_decompressed[1024];
static UCHAR hid_report_descriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
/* First field */
0x09, 0x01, // USAGE (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Second field */
0x19, 0x02, // USAGE_MINIMUM (2)
0x29, 0x04, // USAGE_MAXIMUM (4)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Third field */
0x0a, 0xcd, 0xab, // USAGE (0xabcd)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Fourth field */
0x19, 0x06, // USAGE_MINIMUM (6)
0x29, 0x08, // USAGE_MAXIMUM (8)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Fifth field */
0x09, 0x01, // USAGE (1)
0x75, 0x09, // REPORT_SIZE (9)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Sixth field */
0x19, 0x0a, // USAGE_MINIMUM (10)
0x29, 0x0c, // USAGE_MAXIMUM (12)
0x75, 0x09, // REPORT_SIZE (9)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Seventh field */
0x09, 0x0d, // USAGE (13)
0x75, 0x1f, // REPORT_SIZE (31)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Eigth field */
0x09, 0x0e, // USAGE (14)
0x75, 0x20, // REPORT_SIZE (32)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* USBX expects keyboards to have at least one output report, otherwise it's an error. */
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
};
#define HID_REPORT_LENGTH sizeof(hid_report_descriptor)/sizeof(hid_report_descriptor[0])
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[DEVICE_FRAMEWORK_LENGTH_FULL_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
test_control_return(1);
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_report_descriptor_compress_and_decompress_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
UINT descriptor_size = HID_REPORT_LENGTH;
/* Inform user. */
printf("Running ux_host_class_hid_report_ compress/decompress Test.......... ");
/* 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 on line %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 host portion of USBX */
status = ux_host_stack_initialize(UX_NULL);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the hid class parameters. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* 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 on line %d\n", __LINE__);
test_control_return(1);
}
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_HOST_CLASS_HID_REPORT_GET_ID report_id;
UX_HOST_CLASS_HID_CLIENT_REPORT client_report;
UX_HOST_CLASS_HID_REPORT *input_report_descriptor;
/* Find the HID class */
status = demo_class_hid_get();
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Get the first input report descriptor. */
report_id.ux_host_class_hid_report_get_report = UX_NULL;
report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT;
status = ux_host_class_hid_report_id_get(hid, &report_id);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
input_report_descriptor = report_id.ux_host_class_hid_report_get_report;
if (input_report_descriptor -> ux_host_class_hid_report_id != 0)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* First field */
input_report_buffer_decompressed_original[0] = 0x00010001;
input_report_buffer_decompressed_original[1] = 0x01;
/* Second field */
input_report_buffer_decompressed_original[2] = 0x00010002;
input_report_buffer_decompressed_original[3] = 0x01;
input_report_buffer_decompressed_original[4] = 0x00010003;
input_report_buffer_decompressed_original[5] = 0x00;
input_report_buffer_decompressed_original[6] = 0x00010004;
input_report_buffer_decompressed_original[7] = 0x01;
/* Third field */
input_report_buffer_decompressed_original[8] = 0x0001abcd;
input_report_buffer_decompressed_original[9] = 0x30;
/* Fourth field */
input_report_buffer_decompressed_original[10] = 0x00010006;
input_report_buffer_decompressed_original[11] = 0x52;
input_report_buffer_decompressed_original[12] = 0x00010007;
input_report_buffer_decompressed_original[13] = 0x74;
input_report_buffer_decompressed_original[14] = 0x00010008;
input_report_buffer_decompressed_original[15] = 0x96;
/* Fifth field */
input_report_buffer_decompressed_original[16] = 0x00010001;
input_report_buffer_decompressed_original[17] = 0x0b8;
/* Sixth field */
input_report_buffer_decompressed_original[18] = 0x0001000a;
input_report_buffer_decompressed_original[19] = 0x06d;
input_report_buffer_decompressed_original[20] = 0x0001000b;
input_report_buffer_decompressed_original[21] = 0x1bf;
input_report_buffer_decompressed_original[22] = 0x0001000c;
input_report_buffer_decompressed_original[23] = 0x003;
/* Seventh field */
input_report_buffer_decompressed_original[24] = 0x0001000d;
input_report_buffer_decompressed_original[25] = 0x09674523;
/* Eigth field */
input_report_buffer_decompressed_original[26] = 0x0001000e;
input_report_buffer_decompressed_original[27] = 0x03df9b57;
/* Fill out the request for the decompress api. */
client_report.ux_host_class_hid_client_report = input_report_descriptor;
client_report.ux_host_class_hid_client_report_buffer = input_report_buffer_decompressed_original;
client_report.ux_host_class_hid_client_report_actual_length = 0;
/* Request compression. */
status = _ux_host_class_hid_report_compress(hid, &client_report, input_report_buffer_compressed, 17);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Check output of report compression. */
if (
input_report_buffer_compressed[0] != 0x0b ||
input_report_buffer_compressed[1] != 0x23 ||
input_report_buffer_compressed[2] != 0x45 ||
input_report_buffer_compressed[3] != 0x67 ||
input_report_buffer_compressed[4] != 0x89 ||
input_report_buffer_compressed[5] != 0xab ||
input_report_buffer_compressed[6] != 0xcd ||
input_report_buffer_compressed[7] != 0xef ||
input_report_buffer_compressed[8] != 0x01 ||
input_report_buffer_compressed[9] != 0x23 ||
input_report_buffer_compressed[10] != 0x45 ||
input_report_buffer_compressed[11] != 0x67 ||
input_report_buffer_compressed[12] != 0x89 ||
input_report_buffer_compressed[13] != 0xab ||
input_report_buffer_compressed[14] != 0xcd ||
input_report_buffer_compressed[15] != 0xef ||
input_report_buffer_compressed[16] != 0x01
)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* You're gonna love this. Decompress it and make sure it matches the original! */
client_report.ux_host_class_hid_client_report_buffer = input_report_buffer_decompressed;
status = _ux_host_class_hid_report_decompress(hid, &client_report, input_report_buffer_compressed, 28);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
if (memcmp(input_report_buffer_decompressed, input_report_buffer_decompressed_original, 28))
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Decompress it with report id. */
input_report_buffer_compressed[32] = 0x01;
memcpy(&input_report_buffer_compressed[33], &input_report_buffer_compressed[0], 17);
client_report.ux_host_class_hid_client_report_buffer = input_report_buffer_decompressed;
client_report.ux_host_class_hid_client_report->ux_host_class_hid_report_id = 0x1;
status = _ux_host_class_hid_report_decompress(hid, &client_report, &input_report_buffer_compressed[32], 29);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
if (memcmp(input_report_buffer_decompressed, input_report_buffer_decompressed_original, 28))
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Told ya! */
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}

View File

@ -0,0 +1,423 @@
/* This test concentrates on the report compress api. */
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_keyboard.h"
#include "ux_test.h"
static UCHAR input_report_buffer_compressed[1024];
static SLONG input_report_buffer_decompressed_original[1024];
static UCHAR hid_report_descriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
/* Keys. */
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x01, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x01, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0, // END_COLLECTION
};
#define HID_REPORT_LENGTH sizeof(hid_report_descriptor)/sizeof(hid_report_descriptor[0])
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[DEVICE_FRAMEWORK_LENGTH_FULL_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
static UCHAR ignore_errors;
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
if (!ignore_errors)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
test_control_return(1);
}
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_report_descriptor_compress_array_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
UINT descriptor_size = HID_REPORT_LENGTH;
/* Inform user. */
printf("Running HID Report Descriptor Decompress Test....................... ");
/* 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 on line %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 host portion of USBX */
status = ux_host_stack_initialize(UX_NULL);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the hid class parameters. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* 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 on line %d\n", __LINE__);
test_control_return(1);
}
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_HOST_CLASS_HID_REPORT_GET_ID report_id;
UX_HOST_CLASS_HID_CLIENT_REPORT client_report;
UX_HOST_CLASS_HID_REPORT *input_report_descriptor;
SLONG report_buffer_decompressed[1024];
UCHAR report_buffer_compressed[1024] = {0};
/* Find the HID class */
status = demo_class_hid_get();
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/** Do basic test. **/
/* Get the first input report descriptor. */
report_id.ux_host_class_hid_report_get_report = UX_NULL;
report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT;
UX_TEST_CHECK_SUCCESS(ux_host_class_hid_report_id_get(hid, &report_id));
input_report_descriptor = report_id.ux_host_class_hid_report_get_report;
/* 1 */
report_buffer_decompressed[0] = 0x00070001;
report_buffer_decompressed[1] = 0x1;
/* 2 */
report_buffer_decompressed[2] = 0x00070002;
report_buffer_decompressed[3] = 0x2;
/* 3 */
report_buffer_decompressed[4] = 0x00070003;
report_buffer_decompressed[5] = 0x3;
/* 4 */
report_buffer_decompressed[6] = 0x00070004;
report_buffer_decompressed[7] = 0x4;
/* 5 */
report_buffer_decompressed[8] = 0x00070005;
report_buffer_decompressed[9] = 0x5;
/* 6 */
report_buffer_decompressed[10] = 0x00070006;
report_buffer_decompressed[11] = 0x6;
/* Fill out the request for the compress api. */
client_report.ux_host_class_hid_client_report = input_report_descriptor;
client_report.ux_host_class_hid_client_report_buffer = report_buffer_decompressed;
client_report.ux_host_class_hid_client_report_actual_length = 0;
/* Request compression. */
UX_TEST_CHECK_SUCCESS(_ux_host_class_hid_report_compress(hid, &client_report, report_buffer_compressed, sizeof(report_buffer_compressed)));
/* Check it. */
UX_TEST_ASSERT(report_buffer_compressed[0] == 0x1);
UX_TEST_ASSERT(report_buffer_compressed[1] == 0x2);
UX_TEST_ASSERT(report_buffer_compressed[2] == 0x3);
UX_TEST_ASSERT(report_buffer_compressed[3] == 0x4);
UX_TEST_ASSERT(report_buffer_compressed[4] == 0x5);
UX_TEST_ASSERT(report_buffer_compressed[5] == 0x6);
/** Test invalid usage page. **/
/* Get the first input report descriptor. */
report_id.ux_host_class_hid_report_get_report = UX_NULL;
report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT;
UX_TEST_CHECK_SUCCESS(ux_host_class_hid_report_id_get(hid, &report_id));
input_report_descriptor = report_id.ux_host_class_hid_report_get_report;
/* Add invalid usage page. */
report_buffer_decompressed[0] = 0x00000000;
report_buffer_decompressed[1] = 0x00;
/* Fill out the request for the compress api. */
client_report.ux_host_class_hid_client_report = input_report_descriptor;
client_report.ux_host_class_hid_client_report_buffer = report_buffer_decompressed;
client_report.ux_host_class_hid_client_report_actual_length = 0;
ignore_errors = 1;
/* Request compression. This should fail. */
UX_TEST_CHECK_NOT_SUCCESS(_ux_host_class_hid_report_compress(hid, &client_report, report_buffer_compressed, sizeof(report_buffer_compressed)));
ignore_errors = 0;
/** Test usage too large. **/
/* Get the first input report descriptor. */
report_id.ux_host_class_hid_report_get_report = UX_NULL;
report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT;
UX_TEST_CHECK_SUCCESS(ux_host_class_hid_report_id_get(hid, &report_id));
input_report_descriptor = report_id.ux_host_class_hid_report_get_report;
/* Add unknown usage. */
report_buffer_decompressed[0] = 0x00070066;
report_buffer_decompressed[1] = 0x66;
/* Fill out the request for the compress api. */
client_report.ux_host_class_hid_client_report = input_report_descriptor;
client_report.ux_host_class_hid_client_report_buffer = report_buffer_decompressed;
client_report.ux_host_class_hid_client_report_actual_length = 0;
ignore_errors = 1;
/* Request compression. This should fail. */
UX_TEST_CHECK_NOT_SUCCESS(_ux_host_class_hid_report_compress(hid, &client_report, report_buffer_compressed, sizeof(report_buffer_compressed)));
ignore_errors = 0;
/** Test usage too small. **/
/* Get the first input report descriptor. */
report_id.ux_host_class_hid_report_get_report = UX_NULL;
report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT;
UX_TEST_CHECK_SUCCESS(ux_host_class_hid_report_id_get(hid, &report_id));
input_report_descriptor = report_id.ux_host_class_hid_report_get_report;
/* Add unknown usage. */
report_buffer_decompressed[0] = 0x00070000;
report_buffer_decompressed[1] = 0x0;
/* Fill out the request for the compress api. */
client_report.ux_host_class_hid_client_report = input_report_descriptor;
client_report.ux_host_class_hid_client_report_buffer = report_buffer_decompressed;
client_report.ux_host_class_hid_client_report_actual_length = 0;
ignore_errors = 1;
/* Request compression. This should fail. */
UX_TEST_CHECK_NOT_SUCCESS(_ux_host_class_hid_report_compress(hid, &client_report, report_buffer_compressed, sizeof(report_buffer_compressed)));
ignore_errors = 0;
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}

View File

@ -0,0 +1,463 @@
/* This test concentrates on the report compress api. */
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_keyboard.h"
static UCHAR input_report_buffer_compressed[1024];
static SLONG input_report_buffer_decompressed_original[1024];
static UCHAR hid_report_descriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
/* First field */
0x09, 0x01, // USAGE (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Second field */
0x19, 0x02, // USAGE_MINIMUM (2)
0x29, 0x04, // USAGE_MAXIMUM (4)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Third field */
0x0a, 0xcd, 0xab, // USAGE (0xabcd)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Fourth field */
0x19, 0x06, // USAGE_MINIMUM (6)
0x29, 0x08, // USAGE_MAXIMUM (8)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Fifth field */
0x09, 0x01, // USAGE (1)
0x75, 0x09, // REPORT_SIZE (9)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Sixth field */
0x19, 0x0a, // USAGE_MINIMUM (10)
0x29, 0x0c, // USAGE_MAXIMUM (12)
0x75, 0x09, // REPORT_SIZE (9)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Seventh field */
0x09, 0x0d, // USAGE (13)
0x75, 0x1f, // REPORT_SIZE (31)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Eigth field */
0x09, 0x0e, // USAGE (14)
0x75, 0x20, // REPORT_SIZE (32)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* USBX expects keyboards to have at least one output report, otherwise it's an error. */
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
};
#define HID_REPORT_LENGTH sizeof(hid_report_descriptor)/sizeof(hid_report_descriptor[0])
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[DEVICE_FRAMEWORK_LENGTH_FULL_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
test_control_return(1);
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_report_descriptor_compress_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
UINT descriptor_size = HID_REPORT_LENGTH;
/* Inform user. */
printf("Running HID Report Descriptor Decompress Test....................... ");
/* 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 on line %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 host portion of USBX */
status = ux_host_stack_initialize(UX_NULL);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the hid class parameters. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* 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 on line %d\n", __LINE__);
test_control_return(1);
}
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_HOST_CLASS_HID_REPORT_GET_ID report_id;
UX_HOST_CLASS_HID_CLIENT_REPORT client_report;
UX_HOST_CLASS_HID_REPORT *input_report_descriptor;
/* Find the HID class */
status = demo_class_hid_get();
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Get the first input report descriptor. */
report_id.ux_host_class_hid_report_get_report = UX_NULL;
report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT;
status = ux_host_class_hid_report_id_get(hid, &report_id);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
input_report_descriptor = report_id.ux_host_class_hid_report_get_report;
if (input_report_descriptor -> ux_host_class_hid_report_id != 0)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* First field */
input_report_buffer_decompressed_original[0] = 0x00010001;
input_report_buffer_decompressed_original[1] = 0x01;
/* Second field */
input_report_buffer_decompressed_original[2] = 0x00010002;
input_report_buffer_decompressed_original[3] = 0x01;
input_report_buffer_decompressed_original[4] = 0x00010003;
input_report_buffer_decompressed_original[5] = 0x00;
input_report_buffer_decompressed_original[6] = 0x00010004;
input_report_buffer_decompressed_original[7] = 0x01;
/* Third field */
input_report_buffer_decompressed_original[8] = 0x0001abcd;
input_report_buffer_decompressed_original[9] = 0x30;
/* Fourth field */
input_report_buffer_decompressed_original[10] = 0x00010006;
input_report_buffer_decompressed_original[11] = 0x52;
input_report_buffer_decompressed_original[12] = 0x00010007;
input_report_buffer_decompressed_original[13] = 0x74;
input_report_buffer_decompressed_original[14] = 0x00010008;
input_report_buffer_decompressed_original[15] = 0x96;
/* Fifth field */
input_report_buffer_decompressed_original[16] = 0x00010001;
input_report_buffer_decompressed_original[17] = 0x0b8;
/* Sixth field */
input_report_buffer_decompressed_original[18] = 0x0001000a;
input_report_buffer_decompressed_original[19] = 0x06d;
input_report_buffer_decompressed_original[20] = 0x0001000b;
input_report_buffer_decompressed_original[21] = 0x1bf;
input_report_buffer_decompressed_original[22] = 0x0001000c;
input_report_buffer_decompressed_original[23] = 0x003;
/* Seventh field */
input_report_buffer_decompressed_original[24] = 0x0001000d;
input_report_buffer_decompressed_original[25] = 0x09674523;
/* Eigth field */
input_report_buffer_decompressed_original[26] = 0x0001000e;
input_report_buffer_decompressed_original[27] = 0x03df9b57;
/* Fill out the request for the decompress api. */
client_report.ux_host_class_hid_client_report = input_report_descriptor;
client_report.ux_host_class_hid_client_report_buffer = input_report_buffer_decompressed_original;
client_report.ux_host_class_hid_client_report_actual_length = 0;
/* Request compression. */
status = _ux_host_class_hid_report_compress(hid, &client_report, input_report_buffer_compressed, 17);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Check output of report compression. */
if (
input_report_buffer_compressed[0] != 0x0b ||
input_report_buffer_compressed[1] != 0x23 ||
input_report_buffer_compressed[2] != 0x45 ||
input_report_buffer_compressed[3] != 0x67 ||
input_report_buffer_compressed[4] != 0x89 ||
input_report_buffer_compressed[5] != 0xab ||
input_report_buffer_compressed[6] != 0xcd ||
input_report_buffer_compressed[7] != 0xef ||
input_report_buffer_compressed[8] != 0x01 ||
input_report_buffer_compressed[9] != 0x23 ||
input_report_buffer_compressed[10] != 0x45 ||
input_report_buffer_compressed[11] != 0x67 ||
input_report_buffer_compressed[12] != 0x89 ||
input_report_buffer_compressed[13] != 0xab ||
input_report_buffer_compressed[14] != 0xcd ||
input_report_buffer_compressed[15] != 0xef ||
input_report_buffer_compressed[16] != 0x01
)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}

View File

@ -0,0 +1,367 @@
/* This test concentrates on the report decompression api when the report contains an array item. */
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_keyboard.h"
static UCHAR report_buffer_compressed[1024];
static SLONG report_buffer_decompressed[1024];
static UCHAR hid_report_descriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x06, // REPORT_COUNT (6)
0x81, 0x00, // INPUT (Data,Ary,Abs)
/* USBX expects keyboards to have at least one output report, otherwise it's an error. */
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
};
#define HID_REPORT_LENGTH sizeof(hid_report_descriptor)/sizeof(hid_report_descriptor[0])
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[DEVICE_FRAMEWORK_LENGTH_FULL_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
test_control_return(1);
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_report_descriptor_decompress_array_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
UINT descriptor_size = HID_REPORT_LENGTH;
/* Inform user. */
printf("Running HID Report Descriptor Decompress Array Test................. ");
/* 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 on line %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 host portion of USBX */
status = ux_host_stack_initialize(UX_NULL);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the hid class parameters. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* 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 on line %d\n", __LINE__);
test_control_return(1);
}
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_HOST_CLASS_HID_REPORT_GET_ID report_id;
UX_HOST_CLASS_HID_CLIENT_REPORT input_report_request;
UX_HOST_CLASS_HID_REPORT *input_report_descriptor;
/* Find the HID class */
status = demo_class_hid_get();
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Get the first input report descriptor. */
report_id.ux_host_class_hid_report_get_report = UX_NULL;
report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT;
status = ux_host_class_hid_report_id_get(hid, &report_id);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
input_report_descriptor = report_id.ux_host_class_hid_report_get_report;
if (input_report_descriptor -> ux_host_class_hid_report_id != 0)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Fill out the request for the decompress api. */
input_report_request.ux_host_class_hid_client_report = input_report_descriptor;
input_report_request.ux_host_class_hid_client_report_buffer = report_buffer_decompressed;
input_report_request.ux_host_class_hid_client_report_length = input_report_descriptor -> ux_host_class_hid_report_byte_length;
input_report_request.ux_host_class_hid_client_report_actual_length = 0;
input_report_request.ux_host_class_hid_client_report_flags = UX_HOST_CLASS_HID_REPORT_DECOMPRESSED;
/* Fill out report. */
report_buffer_compressed[0] = 0x00;
report_buffer_compressed[1] = 0x10;
report_buffer_compressed[2] = 0x23;
report_buffer_compressed[3] = 0x37;
report_buffer_compressed[4] = 0x43;
report_buffer_compressed[5] = 0x65;
/* Request decompression. */
status = _ux_host_class_hid_report_decompress(hid, &input_report_request, report_buffer_compressed, 6);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Check output of decompression of report. */
if (
report_buffer_decompressed[0] != 0x00010000 ||
report_buffer_decompressed[1] != 0x00 ||
report_buffer_decompressed[2] != 0x00010010 ||
report_buffer_decompressed[3] != 0x10 ||
report_buffer_decompressed[4] != 0x00010023 ||
report_buffer_decompressed[5] != 0x23 ||
report_buffer_decompressed[6] != 0x00010037 ||
report_buffer_decompressed[7] != 0x37 ||
report_buffer_decompressed[8] != 0x00010043 ||
report_buffer_decompressed[9] != 0x43 ||
report_buffer_decompressed[10] != 0x00010065 ||
report_buffer_decompressed[11] != 0x65
)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}

View File

@ -0,0 +1,500 @@
/* This test concentrates on the report decompress api. */
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_keyboard.h"
static UCHAR report_buffer_compressed_original[1024];
static UCHAR report_buffer_compressed[1024];
static SLONG report_buffer_decompressed[1024];
static UCHAR hid_report_descriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
/* First field */
0x09, 0x01, // USAGE (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Second field */
0x19, 0x02, // USAGE_MINIMUM (2)
0x29, 0x04, // USAGE_MAXIMUM (4)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Third field */
0x0a, 0xcd, 0xab, // USAGE (0xabcd)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Fourth field */
0x19, 0x06, // USAGE_MINIMUM (6)
0x29, 0x08, // USAGE_MAXIMUM (8)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Fifth field */
0x09, 0x01, // USAGE (1)
0x75, 0x09, // REPORT_SIZE (9)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Sixth field */
0x19, 0x0a, // USAGE_MINIMUM (10)
0x29, 0x0c, // USAGE_MAXIMUM (12)
0x75, 0x09, // REPORT_SIZE (9)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Seventh field */
0x09, 0x0d, // USAGE (13)
0x75, 0x1f, // REPORT_SIZE (31)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* Eigth field */
0x09, 0x0e, // USAGE (14)
0x75, 0x20, // REPORT_SIZE (32)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
/* bits: 1 + 3 + 8 + 24 + 9 + 27 + 31 + 32 = 135; 17 bytes overall */
/* USBX expects keyboards to have at least one output report, otherwise it's an error. */
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
};
#define HID_REPORT_LENGTH sizeof(hid_report_descriptor)/sizeof(hid_report_descriptor[0])
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[DEVICE_FRAMEWORK_LENGTH_FULL_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
/* Failed test. */
printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
test_control_return(1);
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_report_descriptor_decompress_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
UINT descriptor_size = HID_REPORT_LENGTH;
/* Inform user. */
printf("Running HID Report Descriptor Decompress Test....................... ");
/* 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 on line %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 host portion of USBX */
status = ux_host_stack_initialize(UX_NULL);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the hid class parameters. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* 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 on line %d\n", __LINE__);
test_control_return(1);
}
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
UX_HOST_CLASS_HID_REPORT_GET_ID report_get_id;
UX_HOST_CLASS_HID_CLIENT_REPORT client_report;
UX_HOST_CLASS_HID_REPORT *hid_report;
/* Find the HID class */
status = demo_class_hid_get();
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Get the first input report descriptor. */
report_get_id.ux_host_class_hid_report_get_report = UX_NULL;
report_get_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT;
status = ux_host_class_hid_report_id_get(hid, &report_get_id);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
hid_report = report_get_id.ux_host_class_hid_report_get_report;
if (hid_report -> ux_host_class_hid_report_id != 0)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Fill out the request for the decompress api. */
client_report.ux_host_class_hid_client_report = hid_report;
client_report.ux_host_class_hid_client_report_buffer = report_buffer_decompressed;
client_report.ux_host_class_hid_client_report_length = hid_report -> ux_host_class_hid_report_byte_length;
client_report.ux_host_class_hid_client_report_actual_length = 0;
/* Fill out report. */
report_buffer_compressed_original[0] = 0x0b; // [0] bits 1-8: 0000 1011
report_buffer_compressed_original[1] = 0x23; // [1] bits 9-16: 0010 0011
report_buffer_compressed_original[2] = 0x45; // [2] bits 17-24: 0100 0101
report_buffer_compressed_original[3] = 0x67; // [3] bits 25-32: 0110 0111
report_buffer_compressed_original[4] = 0x89; // [4] bits 33-40: 1000 1001
report_buffer_compressed_original[5] = 0xab; // [5] bits 41-48: 1010 1011
report_buffer_compressed_original[6] = 0xcd; // [6] bits 49-56: 1100 1101
report_buffer_compressed_original[7] = 0xef; // [7] bits 57-64: 1110 1111
report_buffer_compressed_original[8] = 0x01; // [8] bits 65-72: 0000 0001
report_buffer_compressed_original[9] = 0x23; // [9] bits 73-80: 0010 0011
report_buffer_compressed_original[10] = 0x45; // [10] bits 81-88: 0100 0101
report_buffer_compressed_original[11] = 0x67; // [11] bits 89-96: 0110 0111
report_buffer_compressed_original[12] = 0x89; // [12] bits 97-104: 1000 1001
report_buffer_compressed_original[13] = 0xab; // [13] bits 105-112: 1010 1011
report_buffer_compressed_original[14] = 0xcd; // [14] bits 113-120: 1100 1101
report_buffer_compressed_original[15] = 0xef; // [15] bits 121-128: 1110 1111
report_buffer_compressed_original[16] = 0x01; // [16] bits 129-136: 0000 0001
/* Request decompression. */
status = _ux_host_class_hid_report_decompress(hid, &client_report, report_buffer_compressed_original, 17);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Check output of decompression of report. */
if (
/* First field */
/* bit 1 */
report_buffer_decompressed[0] != 0x00010001 ||
report_buffer_decompressed[1] != 0x01 ||
/* Second field */
/* bit 2 */
report_buffer_decompressed[2] != 0x00010002 ||
report_buffer_decompressed[3] != 0x01 ||
/* bit 3 */
report_buffer_decompressed[4] != 0x00010003 ||
report_buffer_decompressed[5] != 0x00 ||
/* bit 4 */
report_buffer_decompressed[6] != 0x00010004 ||
report_buffer_decompressed[7] != 0x01 ||
/* Third field */
/* bits 5-12 */
report_buffer_decompressed[8] != 0x0001abcd ||
report_buffer_decompressed[9] != 0x30 ||
/* Fourth field */
/* bits 13-20 */
report_buffer_decompressed[10] != 0x00010006 ||
report_buffer_decompressed[11] != 0x52 ||
/* bits 21-28 */
report_buffer_decompressed[12] != 0x00010007 ||
report_buffer_decompressed[13] != 0x74 ||
/* bits 29-36 */
report_buffer_decompressed[14] != 0x00010008 ||
report_buffer_decompressed[15] != 0x96 ||
/* Fifth field */
/* bits 37-45 */
report_buffer_decompressed[16] != 0x00010001 ||
report_buffer_decompressed[17] != 0x0b8 ||
/* Sixth field */
/* bits 46-54 - 0 0110 1101 */
report_buffer_decompressed[18] != 0x0001000a ||
report_buffer_decompressed[19] != 0x06d ||
/* bits 55-63 - 1 1011 1111 */
report_buffer_decompressed[20] != 0x0001000b ||
report_buffer_decompressed[21] != 0x1bf ||
/* bits 64-72 - 0 0000 0011 */
report_buffer_decompressed[22] != 0x0001000c ||
report_buffer_decompressed[23] != 0x003 ||
/* Seventh field */
/* bits 73-103 - 000 1001 0110 0111 0100 0101 0010 0011 */
report_buffer_decompressed[24] != 0x0001000d ||
report_buffer_decompressed[25] != 0x09674523 ||
/* Eigth field */
/* bits 104-135 - 0000 0011 1101 1111 1001 1011 0101 0111 */
report_buffer_decompressed[26] != 0x0001000e ||
report_buffer_decompressed[27] != 0x03df9b57
)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
#if 0
/* Now perform the inverse: compression. */
status = _ux_host_class_hid_report_compress(hid, &client_report, report_buffer_compressed, 28);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* These should be the same (god help us). */
if(ux_utility_memory_compare(report_buffer_compressed, report_buffer_compressed_original, 17) != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
#endif
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}

View File

@ -0,0 +1,304 @@
/* This test ensures that the parser generates an error upon encountering an invalid close delimiter tag. */
#include "usbx_test_common_hid.h"
#include "ux_host_class_hid_keyboard.h"
static UINT callback_error_code;
static UCHAR hid_report_descriptor[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0xa9, 0x01, // DELIMITER (Open)
0x0b, 0x20, 0x00, 0x05, 0x00, // USAGE (Gaming Controls:Point of View)
0x0b, 0x39, 0x00, 0x01, 0x00, // USAGE (Generic Desktop:Hat switch)
0x0b, 0x20, 0x00, 0x05, 0x00, // USAGE (Gaming Controls:Point of View)
0xa9, 0x00, // DELIMITER (Close)
/* Add an extra invalid delimiter close tag. */
0xa9, 0x00, // DELIMITER (Close)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x03, // LOGICAL_MAXIMUM (3)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0x0e, 0x01, // PHYSICAL_MAXIMUM (270)
0x65, 0x14, // UNIT (Eng Rot:Angular Pos)
0x55, 0x00, // UNIT_EXPONENT (0)
0x75, 0x04, // REPORT_SIZE (4)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0 // END_COLLECTION
};
#define HID_REPORT_LENGTH sizeof(hid_report_descriptor)/sizeof(hid_report_descriptor[0])
#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
static UCHAR device_framework_full_speed[DEVICE_FRAMEWORK_LENGTH_FULL_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
static UCHAR device_framework_high_speed[DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED] = {
/* Device descriptor */
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
0x03, 0x01,
/* Device qualifier descriptor */
0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
0x01, 0x00,
/* Configuration descriptor */
0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
0x32,
/* Interface descriptor */
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00,
/* HID descriptor */
0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
MSB(HID_REPORT_LENGTH),
/* Endpoint descriptor (Interrupt) */
0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
};
/* 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 40
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, 0x0c,
0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
0x6f, 0x61, 0x72, 0x64,
/* 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
};
static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
{
if (error_code != UX_HOST_CLASS_HID_DELIMITER_ERROR &&
error_code != UX_DESCRIPTOR_CORRUPTED &&
error_code != UX_DEVICE_ENUMERATION_FAILURE)
{
/* Something went wrong. */
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
}
/* Define what the initial system looks like. */
#ifdef CTEST
void test_application_define(void *first_unused_memory)
#else
void usbx_hid_report_descriptor_delimiter_nested_close_test_application_define(void *first_unused_memory)
#endif
{
UINT status;
CHAR * stack_pointer;
CHAR * memory_pointer;
UINT descriptor_size = HID_REPORT_LENGTH;
/* Inform user. */
printf("Running HID Report Descriptor Delimiter Nested Close Test........... ");
/* 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 on line %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 host portion of USBX */
status = ux_host_stack_initialize(UX_NULL);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Register the HID client(s). */
status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
if (status != UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* The code below is required for installing the device portion of USBX. No call back for
device status change in this example. */
status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
string_framework, STRING_FRAMEWORK_LENGTH,
language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the hid class parameters. */
hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
hid_parameter.ux_device_class_hid_parameter_report_length = HID_REPORT_LENGTH;
hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
/* Initilize the device hid class. The class is connected with interface 2 */
status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
1,2, (VOID *)&hid_parameter);
if(status!=UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* Initialize the simulated device controller. */
status = _ux_dcd_sim_slave_initialize();
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %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_hcd_sim_host_initialize,0,0);
/* Check for error. */
if (status != UX_SUCCESS)
{
printf("Error on line %d\n", __LINE__);
test_control_return(1);
}
/* 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 on line %d\n", __LINE__);
test_control_return(1);
}
}
static void tx_demo_thread_host_simulation_entry(ULONG arg)
{
UINT status;
/* Find the HID class */
status = demo_class_hid_get();
if (status == UX_SUCCESS)
{
printf("Error on line %d, error code: %d\n", __LINE__, status);
test_control_return(1);
}
/* Now disconnect the device. */
_ux_device_stack_disconnect();
/* And deinitialize the class. */
status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_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_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
{
return(UX_SUCCESS);
}

Some files were not shown because too many files have changed in this diff Show More