mirror of https://github.com/ARMmbed/mbed-os.git
663 lines
25 KiB
C++
663 lines
25 KiB
C++
/*
|
|
* Copyright (c) 2018-2018, ARM Limited, All Rights Reserved
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
* not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "mbed.h"
|
|
#include "greentea-client/test_env.h"
|
|
#include "unity/unity.h"
|
|
#include "utest/utest.h"
|
|
|
|
#include "USBTester.h"
|
|
#include "USBEndpointTester.h"
|
|
#include "usb_phy_api.h"
|
|
|
|
// TODO
|
|
// suspend resume test: implement host side USB suspend/resume
|
|
// sync frame test: add test on isochronous endpoint
|
|
|
|
// Uncomment/remove this when host suspend_resume_test part will be implemented
|
|
//#define SUSPEND_RESUME_TEST_SUPPORTED
|
|
|
|
// If disconnect() + connect() occur too fast the reset event will be dropped.
|
|
// At a minimum there should be a 200us delay between disconnect and connect.
|
|
// To be on the safe side I would recommend a 1ms delay, so the host controller
|
|
// has an entire USB frame to detect the disconnect.
|
|
#define MIN_DISCONNECT_TIME_US 1000
|
|
|
|
#if !defined(DEVICE_USBDEVICE) || !DEVICE_USBDEVICE
|
|
#error [NOT_SUPPORTED] USB Device not supported for this target
|
|
#else
|
|
|
|
|
|
using namespace utest::v1;
|
|
|
|
// Print callback counters for endpoint tests
|
|
#define EP_DBG 0
|
|
|
|
static USBPhy *get_phy()
|
|
{
|
|
return get_usb_phy();
|
|
}
|
|
|
|
|
|
/** Control basic tests
|
|
|
|
Test device configuration/deconfiguration
|
|
Given an initialized USB (HOST <---> DUT connection established)
|
|
When device configuration is checked just after initialization
|
|
Then get_configuration returns 1 (default configuration is set)
|
|
When device is deconfigured
|
|
Then get_configuration returns 0 (no configuration is set)
|
|
When each from supported configurations is set
|
|
Then the configuration is set correctly
|
|
|
|
Test device interface setting
|
|
Given an initialized USB (HOST <---> DUT connection established)
|
|
When each altsetting from every supported configuration is set
|
|
Then the interface altsetting is set correctly
|
|
|
|
Test device/interface/endpoint status
|
|
Given an initialized USB (HOST <---> DUT connection established)
|
|
When device status is checked
|
|
Then status is within allowed values (see status bits description below)
|
|
When control endpoint status is checked
|
|
Then control endpoint status is 0
|
|
When status of each interface from every supported configuration is checked
|
|
Then interface status is 0
|
|
When status of each endpoint in every allowed device interface/configuration combination is checked
|
|
Then endpoint status is 0 (not halted)
|
|
|
|
Test set/clear feature on device/interface/endpoint
|
|
Given an initialized USB (HOST <---> DUT connection established)
|
|
When for each endpoint in every allowed interface/configuration combination the feature is set and then cleared
|
|
Then selected feature is set/cleared accordingly
|
|
|
|
Test device/configuration/interface/endpoint descriptors
|
|
Given an initialized USB (HOST <---> DUT connection established)
|
|
When device descriptor is read
|
|
Then the descriptor content is valid
|
|
When configuration descriptor is read
|
|
Then the descriptor content is valid
|
|
When interface descriptor is read
|
|
Then the error is thrown since it is not directly accessible
|
|
When endpoint descriptor is read
|
|
Then the error is thrown since it is not directly accessible
|
|
|
|
Test descriptor setting
|
|
Given an initialized USB (HOST <---> DUT connection established)
|
|
When device descriptor is to be set
|
|
Then error is thrown since descriptor setting command is not supported by Mbed
|
|
*/
|
|
void control_basic_test()
|
|
{
|
|
uint16_t vendor_id = 0x0d28;
|
|
uint16_t product_id = 0x0205;
|
|
uint16_t product_release = 0x0001;
|
|
char _key[11] = {};
|
|
char _value[128] = {};
|
|
char str[128] = {};
|
|
|
|
{
|
|
USBTester serial(get_phy(), vendor_id, product_id, product_release);
|
|
sprintf(str, "%s %d %d", serial.get_serial_desc_string(), vendor_id, product_id);
|
|
greentea_send_kv("control_basic_test", str);
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
}
|
|
}
|
|
|
|
|
|
/** Test control endpoint stall on invalid request
|
|
|
|
Given an initialized USB (HOST <---> DUT connection established)
|
|
When unsupported request to control endpoint is to be sent
|
|
Then the endpoint is stalled and error is thrown
|
|
|
|
*/
|
|
void control_stall_test()
|
|
{
|
|
uint16_t vendor_id = 0x0d28;
|
|
uint16_t product_id = 0x0205;
|
|
uint16_t product_release = 0x0001;
|
|
char _key[11] = {};
|
|
char _value[128] = {};
|
|
|
|
{
|
|
USBTester serial(get_phy(), vendor_id, product_id, product_release);
|
|
greentea_send_kv("control_stall_test", serial.get_serial_desc_string());
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
}
|
|
}
|
|
|
|
|
|
/** Test various data sizes in control transfer
|
|
|
|
Given an initialized USB (HOST <---> DUT connection established)
|
|
When control data in each tested size is sent
|
|
Then read data should match sent data
|
|
|
|
*/
|
|
void control_sizes_test()
|
|
{
|
|
uint16_t vendor_id = 0x0d28;
|
|
uint16_t product_id = 0x0205;
|
|
uint16_t product_release = 0x0001;
|
|
char _key[11] = {};
|
|
char _value[128] = {};
|
|
|
|
{
|
|
USBTester serial(get_phy(), vendor_id, product_id, product_release);
|
|
greentea_send_kv("control_sizes_test", serial.get_serial_desc_string());
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
}
|
|
}
|
|
|
|
|
|
/** Test various patterns of control transfers
|
|
|
|
Given an initialized USB (HOST <---> DUT connection established)
|
|
When stress control transfer with a data in stage is performed
|
|
Then transfer ends with success
|
|
When stress control transfer with a data out stage followed by a control transfer with a data in stage is performed
|
|
Then transfer ends with success
|
|
When stress control transfer with a data out stage is performed
|
|
Then transfer ends with success
|
|
|
|
*/
|
|
void control_stress_test()
|
|
{
|
|
uint16_t vendor_id = 0x0d28;
|
|
uint16_t product_id = 0x0205;
|
|
uint16_t product_release = 0x0001;
|
|
char _key[11] = {};
|
|
char _value[128] = {};
|
|
|
|
{
|
|
USBTester serial(get_phy(), vendor_id, product_id, product_release);
|
|
greentea_send_kv("control_stress_test", serial.get_serial_desc_string());
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
}
|
|
}
|
|
|
|
/** Test data correctness for every OUT/IN endpoint pair
|
|
*
|
|
* Given a USB device with multiple OUT/IN endpoint pairs
|
|
* When the host sends random payloads up to wMaxPacketSize in size
|
|
* to an OUT endpoint of the device,
|
|
* and then the device sends data back to host using an IN endpoint
|
|
* Then data sent and received by host is equal for every endpoint pair
|
|
*/
|
|
void ep_test_data_correctness()
|
|
{
|
|
uint16_t vendor_id = 0x0d28;
|
|
// Use a product ID different than that used in other tests,
|
|
// to help Windows hosts use the correct configuration descriptor.
|
|
uint16_t product_id = 0x0206;
|
|
uint16_t product_release = 0x0001;
|
|
char _key[11] = { };
|
|
char _value[128] = { };
|
|
|
|
{
|
|
USBEndpointTester serial(get_phy(), vendor_id, product_id, product_release, false);
|
|
greentea_send_kv("ep_test_data_correctness", serial.get_serial_desc_string());
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
#if EP_DBG
|
|
wait_ms(100);
|
|
printf("cnt_cb_set_conf = %lu\r\n", serial.get_cnt_cb_set_conf());
|
|
printf("cnt_cb_set_intf = %lu\r\n", serial.get_cnt_cb_set_intf());
|
|
printf("cnt_cb_bulk_out = %lu\r\n", serial.get_cnt_cb_bulk_out());
|
|
printf("cnt_cb_bulk_in = %lu\r\n", serial.get_cnt_cb_bulk_in());
|
|
printf("cnt_cb_int_out = %lu\r\n", serial.get_cnt_cb_int_out());
|
|
printf("cnt_cb_int_in = %lu\r\n", serial.get_cnt_cb_int_in());
|
|
printf("cnt_cb_iso_out = %lu\r\n", serial.get_cnt_cb_iso_out());
|
|
printf("cnt_cb_iso_in = %lu\r\n", serial.get_cnt_cb_iso_in());
|
|
#endif
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
}
|
|
}
|
|
|
|
/** Test endpoint halt for every OUT/IN endpoint pair
|
|
*
|
|
* Given a USB device with multiple OUT/IN endpoint pairs
|
|
* When the host issues an endpoint halt control request at a random point
|
|
* of OUT or IN transfer
|
|
* Then the endpoint is stalled and all further transfers fail
|
|
*/
|
|
void ep_test_halt()
|
|
{
|
|
uint16_t vendor_id = 0x0d28;
|
|
// Use a product ID different than that used in other tests,
|
|
// to help Windows hosts use the correct configuration descriptor.
|
|
uint16_t product_id = 0x0206;
|
|
uint16_t product_release = 0x0001;
|
|
char _key[11] = { };
|
|
char _value[128] = { };
|
|
|
|
{
|
|
USBEndpointTester serial(get_phy(), vendor_id, product_id, product_release, false);
|
|
greentea_send_kv("ep_test_halt", serial.get_serial_desc_string());
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
#if EP_DBG
|
|
wait_ms(100);
|
|
printf("cnt_cb_set_conf = %lu\r\n", serial.get_cnt_cb_set_conf());
|
|
printf("cnt_cb_set_intf = %lu\r\n", serial.get_cnt_cb_set_intf());
|
|
printf("cnt_cb_bulk_out = %lu\r\n", serial.get_cnt_cb_bulk_out());
|
|
printf("cnt_cb_bulk_in = %lu\r\n", serial.get_cnt_cb_bulk_in());
|
|
printf("cnt_cb_int_out = %lu\r\n", serial.get_cnt_cb_int_out());
|
|
printf("cnt_cb_int_in = %lu\r\n", serial.get_cnt_cb_int_in());
|
|
printf("cnt_cb_iso_out = %lu\r\n", serial.get_cnt_cb_iso_out());
|
|
printf("cnt_cb_iso_in = %lu\r\n", serial.get_cnt_cb_iso_in());
|
|
#endif
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
}
|
|
}
|
|
|
|
/** Test simultaneous data transfers for multiple OUT/IN endpoint pairs
|
|
*
|
|
* Given a USB device with multiple OUT/IN endpoint pairs
|
|
* When multiple OUT and IN endpoints are used to transfer random data in parallel
|
|
* Then all transfers succeed
|
|
* and for every endpoint pair, data received by host equals data sent by host
|
|
*/
|
|
void ep_test_parallel_transfers()
|
|
{
|
|
uint16_t vendor_id = 0x0d28;
|
|
// Use a product ID different than that used in other tests,
|
|
// to help Windows hosts use the correct configuration descriptor.
|
|
uint16_t product_id = 0x0206;
|
|
uint16_t product_release = 0x0001;
|
|
char _key[11] = { };
|
|
char _value[128] = { };
|
|
|
|
{
|
|
USBEndpointTester serial(get_phy(), vendor_id, product_id, product_release, false);
|
|
greentea_send_kv("ep_test_parallel_transfers", serial.get_serial_desc_string());
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
#if EP_DBG
|
|
wait_ms(100);
|
|
printf("cnt_cb_set_conf = %lu\r\n", serial.get_cnt_cb_set_conf());
|
|
printf("cnt_cb_set_intf = %lu\r\n", serial.get_cnt_cb_set_intf());
|
|
printf("cnt_cb_bulk_out = %lu\r\n", serial.get_cnt_cb_bulk_out());
|
|
printf("cnt_cb_bulk_in = %lu\r\n", serial.get_cnt_cb_bulk_in());
|
|
printf("cnt_cb_int_out = %lu\r\n", serial.get_cnt_cb_int_out());
|
|
printf("cnt_cb_int_in = %lu\r\n", serial.get_cnt_cb_int_in());
|
|
printf("cnt_cb_iso_out = %lu\r\n", serial.get_cnt_cb_iso_out());
|
|
printf("cnt_cb_iso_in = %lu\r\n", serial.get_cnt_cb_iso_in());
|
|
#endif
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
}
|
|
}
|
|
|
|
/** Test simultaneous data transfers in parallel with control transfers
|
|
*
|
|
* Given a USB device with multiple OUT/IN endpoint pairs
|
|
* When multiple OUT and IN endpoints are used to transfer random data
|
|
* and control requests are processed in parallel
|
|
* Then all transfers succeed
|
|
* and for every endpoint pair, data received by host equals data sent by host
|
|
*/
|
|
void ep_test_parallel_transfers_ctrl()
|
|
{
|
|
uint16_t vendor_id = 0x0d28;
|
|
// Use a product ID different than that used in other tests,
|
|
// to help Windows hosts use the correct configuration descriptor.
|
|
uint16_t product_id = 0x0206;
|
|
uint16_t product_release = 0x0001;
|
|
char _key[11] = { };
|
|
char _value[128] = { };
|
|
|
|
{
|
|
USBEndpointTester serial(get_phy(), vendor_id, product_id, product_release, false);
|
|
greentea_send_kv("ep_test_parallel_transfers_ctrl", serial.get_serial_desc_string());
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
#if EP_DBG
|
|
wait_ms(100);
|
|
printf("cnt_cb_set_conf = %lu\r\n", serial.get_cnt_cb_set_conf());
|
|
printf("cnt_cb_set_intf = %lu\r\n", serial.get_cnt_cb_set_intf());
|
|
printf("cnt_cb_bulk_out = %lu\r\n", serial.get_cnt_cb_bulk_out());
|
|
printf("cnt_cb_bulk_in = %lu\r\n", serial.get_cnt_cb_bulk_in());
|
|
printf("cnt_cb_int_out = %lu\r\n", serial.get_cnt_cb_int_out());
|
|
printf("cnt_cb_int_in = %lu\r\n", serial.get_cnt_cb_int_in());
|
|
printf("cnt_cb_iso_out = %lu\r\n", serial.get_cnt_cb_iso_out());
|
|
printf("cnt_cb_iso_in = %lu\r\n", serial.get_cnt_cb_iso_in());
|
|
#endif
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
}
|
|
}
|
|
|
|
/** Test aborting data transfer for every OUT/IN endpoint pair
|
|
*
|
|
* Given a USB device with multiple OUT/IN endpoint pairs
|
|
* When a device aborts an in progress data transfer
|
|
* Then no more data is transmitted
|
|
* and endpoint buffer is correctly released on the device end
|
|
*/
|
|
void ep_test_abort()
|
|
{
|
|
uint16_t vendor_id = 0x0d28;
|
|
// Use a product ID different than that used in other tests,
|
|
// to help Windows hosts use the correct configuration descriptor.
|
|
uint16_t product_id = 0x0206;
|
|
uint16_t product_release = 0x0001;
|
|
char _key[11] = { };
|
|
char _value[128] = { };
|
|
|
|
{
|
|
USBEndpointTester serial(get_phy(), vendor_id, product_id, product_release, true);
|
|
greentea_send_kv("ep_test_abort", serial.get_serial_desc_string());
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
#if EP_DBG
|
|
wait_ms(100);
|
|
printf("cnt_cb_set_conf = %lu\r\n", serial.get_cnt_cb_set_conf());
|
|
printf("cnt_cb_set_intf = %lu\r\n", serial.get_cnt_cb_set_intf());
|
|
printf("cnt_cb_bulk_out = %lu\r\n", serial.get_cnt_cb_bulk_out());
|
|
printf("cnt_cb_bulk_in = %lu\r\n", serial.get_cnt_cb_bulk_in());
|
|
printf("cnt_cb_int_out = %lu\r\n", serial.get_cnt_cb_int_out());
|
|
printf("cnt_cb_int_in = %lu\r\n", serial.get_cnt_cb_int_in());
|
|
printf("cnt_cb_iso_out = %lu\r\n", serial.get_cnt_cb_iso_out());
|
|
printf("cnt_cb_iso_in = %lu\r\n", serial.get_cnt_cb_iso_in());
|
|
#endif
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
}
|
|
}
|
|
|
|
/** Test data toggle reset for bulk OUT/IN endpoint pairs
|
|
*
|
|
* Given a USB device
|
|
* When an interface is set
|
|
* Then the data toggle bits for all endpoints are reset to DATA0
|
|
* When clear feature is called for an endpoint that *IS NOT* stalled
|
|
* Then the data toggle is reset to DATA0 for that endpoint
|
|
* When clear halt is called for an endpoint that *IS* stalled
|
|
* Then the data toggle is reset to DATA0 for that endpoint
|
|
*/
|
|
void ep_test_data_toggle()
|
|
{
|
|
uint16_t vendor_id = 0x0d28;
|
|
// Use a product ID different than that used in other tests,
|
|
// to help Windows hosts use the correct configuration descriptor.
|
|
uint16_t product_id = 0x0206;
|
|
uint16_t product_release = 0x0001;
|
|
char _key[11] = { };
|
|
char _value[128] = { };
|
|
|
|
{
|
|
USBEndpointTester serial(get_phy(), vendor_id, product_id, product_release, false);
|
|
greentea_send_kv("ep_test_data_toggle", serial.get_serial_desc_string());
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
#if EP_DBG
|
|
wait_ms(100);
|
|
printf("cnt_cb_set_conf = %lu\r\n", serial.get_cnt_cb_set_conf());
|
|
printf("cnt_cb_set_intf = %lu\r\n", serial.get_cnt_cb_set_intf());
|
|
printf("cnt_cb_bulk_out = %lu\r\n", serial.get_cnt_cb_bulk_out());
|
|
printf("cnt_cb_bulk_in = %lu\r\n", serial.get_cnt_cb_bulk_in());
|
|
printf("cnt_cb_int_out = %lu\r\n", serial.get_cnt_cb_int_out());
|
|
printf("cnt_cb_int_in = %lu\r\n", serial.get_cnt_cb_int_in());
|
|
printf("cnt_cb_iso_out = %lu\r\n", serial.get_cnt_cb_iso_out());
|
|
printf("cnt_cb_iso_in = %lu\r\n", serial.get_cnt_cb_iso_in());
|
|
#endif
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
}
|
|
}
|
|
|
|
/** Test USB implementation against repeated reset
|
|
|
|
Given an initialized USB (HOST <---> DUT connection established)
|
|
When USB device is reset repeatedly
|
|
Then the USB is operational with no errors
|
|
|
|
*/
|
|
void device_reset_test()
|
|
{
|
|
uint16_t vendor_id = 0x0d28;
|
|
uint16_t product_id = 0x0205;
|
|
uint16_t product_release = 0x0001;
|
|
char _key[11] = {};
|
|
char _value[128] = {};
|
|
|
|
greentea_send_kv("reset_support", 0);
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
if (strcmp(_value, "false") != 0) {
|
|
|
|
USBTester serial(get_phy(), vendor_id, product_id, product_release);
|
|
serial.clear_reset_count();
|
|
greentea_send_kv("device_reset_test", serial.get_serial_desc_string());
|
|
while (serial.get_reset_count() == 0);
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
|
|
while (!serial.configured());
|
|
|
|
serial.clear_reset_count();
|
|
greentea_send_kv("device_reset_test", serial.get_serial_desc_string());
|
|
while (serial.get_reset_count() == 0);
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
|
|
while (!serial.configured());
|
|
|
|
serial.clear_reset_count();
|
|
greentea_send_kv("device_reset_test", serial.get_serial_desc_string());
|
|
while (serial.get_reset_count() == 0);
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
|
|
while (!serial.configured());
|
|
|
|
greentea_send_kv("device_reset_test", serial.get_serial_desc_string());
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
}
|
|
}
|
|
|
|
|
|
/** Test USB implementation against repeated reconnection
|
|
|
|
Given an initialized USB (HOST <---> DUT connection established)
|
|
When USB device is disconnected and then connected repeatedly
|
|
Then the USB is operational with no errors
|
|
|
|
*/
|
|
void device_soft_reconnection_test()
|
|
{
|
|
uint16_t vendor_id = 0x0d28;
|
|
uint16_t product_id = 0x0205;
|
|
uint16_t product_release = 0x0001;
|
|
char _key[11] = {};
|
|
char _value[128] = {};
|
|
const uint32_t reconnect_try_count = 3;
|
|
|
|
{
|
|
USBTester serial(get_phy(), vendor_id, product_id, product_release);
|
|
|
|
greentea_send_kv("device_soft_reconnection_test", serial.get_serial_desc_string());
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
|
|
for (int i = 0; i < reconnect_try_count; i++) {
|
|
serial.disconnect();
|
|
wait_us(MIN_DISCONNECT_TIME_US);
|
|
serial.connect();
|
|
greentea_send_kv("device_soft_reconnection_test", serial.get_serial_desc_string());
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
}
|
|
|
|
serial.disconnect();
|
|
wait_us(MIN_DISCONNECT_TIME_US);
|
|
serial.connect();
|
|
serial.disconnect();
|
|
wait_us(MIN_DISCONNECT_TIME_US);
|
|
serial.connect();
|
|
serial.disconnect();
|
|
wait_us(MIN_DISCONNECT_TIME_US);
|
|
serial.connect();
|
|
greentea_send_kv("device_soft_reconnection_test", serial.get_serial_desc_string());
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
}
|
|
}
|
|
|
|
|
|
#if SUSPEND_RESUME_TEST_SUPPORTED
|
|
/** Test USB implementation against repeated suspend and resume
|
|
|
|
Given an initialized USB (HOST <---> DUT connection established)
|
|
When USB device is suspended and then resumed repeatedly
|
|
Then the USB is operational with no errors
|
|
|
|
*/
|
|
void device_suspend_resume_test()
|
|
{
|
|
uint16_t vendor_id = 0x0d28;
|
|
uint16_t product_id = 0x0205;
|
|
uint16_t product_release = 0x0001;
|
|
char _key[11] = {};
|
|
char _value[128] = {};
|
|
|
|
{
|
|
USBTester serial(get_phy(), vendor_id, product_id, product_release);
|
|
greentea_send_kv("device_suspend_resume_test", serial.get_serial_desc_string());
|
|
printf("[1] suspend_count: %d resume_count: %d\n", serial.get_suspend_count(), serial.get_resume_count());
|
|
serial.clear_suspend_count();
|
|
serial.clear_resume_count();
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
printf("[2] suspend_count: %d resume_count: %d\n", serial.get_suspend_count(), serial.get_resume_count());
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
wait_ms(5000);
|
|
printf("[3] suspend_count: %d resume_count: %d\n", serial.get_suspend_count(), serial.get_resume_count());
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
/** Test USB implementation against repeated initialization and deinitialization
|
|
|
|
Given an initialized USB (HOST <---> DUT connection established)
|
|
When USB device is deinitialized and then initialized repeatedly
|
|
Then the USB is operational with no errors
|
|
|
|
*/
|
|
void repeated_construction_destruction_test()
|
|
{
|
|
uint16_t vendor_id = 0x0d28;
|
|
uint16_t product_id = 0x0205;
|
|
uint16_t product_release = 0x0001;
|
|
char _key[11] = {};
|
|
char _value[128] = {};
|
|
|
|
{
|
|
USBTester serial(get_phy(), vendor_id, product_id, product_release);
|
|
TEST_ASSERT_EQUAL(true, serial.configured());
|
|
}
|
|
|
|
wait_us(MIN_DISCONNECT_TIME_US);
|
|
{
|
|
USBTester serial(get_phy(), vendor_id, product_id, product_release);
|
|
TEST_ASSERT_EQUAL(true, serial.configured());
|
|
}
|
|
|
|
wait_us(MIN_DISCONNECT_TIME_US);
|
|
{
|
|
USBTester serial(get_phy(), vendor_id, product_id, product_release);
|
|
TEST_ASSERT_EQUAL(true, serial.configured());
|
|
}
|
|
|
|
wait_us(MIN_DISCONNECT_TIME_US);
|
|
{
|
|
USBTester serial(get_phy(), vendor_id, product_id, product_release);
|
|
TEST_ASSERT_EQUAL(true, serial.configured());
|
|
greentea_send_kv("repeated_construction_destruction_test", serial.get_serial_desc_string());
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
}
|
|
|
|
wait_us(MIN_DISCONNECT_TIME_US);
|
|
{
|
|
USBTester serial(get_phy(), vendor_id, product_id, product_release);
|
|
TEST_ASSERT_EQUAL(true, serial.configured());
|
|
greentea_send_kv("repeated_construction_destruction_test", serial.get_serial_desc_string());
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
}
|
|
|
|
wait_us(MIN_DISCONNECT_TIME_US);
|
|
{
|
|
USBTester serial(get_phy(), vendor_id, product_id, product_release);
|
|
TEST_ASSERT_EQUAL(true, serial.configured());
|
|
greentea_send_kv("repeated_construction_destruction_test", serial.get_serial_desc_string());
|
|
// Wait for host before terminating
|
|
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
|
TEST_ASSERT_EQUAL_STRING("pass", _key);
|
|
}
|
|
}
|
|
|
|
Case cases[] = {
|
|
Case("usb control basic test", control_basic_test),
|
|
Case("usb control stall test", control_stall_test),
|
|
Case("usb control sizes test", control_sizes_test),
|
|
Case("usb control stress test", control_stress_test),
|
|
Case("usb device reset test", device_reset_test),
|
|
Case("usb soft reconnection test", device_soft_reconnection_test),
|
|
#if SUSPEND_RESUME_TEST_SUPPORTED
|
|
Case("usb device suspend/resume test", device_suspend_resume_test),
|
|
#endif
|
|
Case("usb repeated construction destruction test", repeated_construction_destruction_test),
|
|
Case("endpoint test data correctness", ep_test_data_correctness),
|
|
Case("endpoint test halt", ep_test_halt),
|
|
Case("endpoint test parallel transfers", ep_test_parallel_transfers),
|
|
Case("endpoint test parallel transfers ctrl", ep_test_parallel_transfers_ctrl),
|
|
Case("endpoint test abort", ep_test_abort),
|
|
Case("endpoint test data toggle reset", ep_test_data_toggle)
|
|
};
|
|
|
|
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
|
|
{
|
|
GREENTEA_SETUP(180, "pyusb_basic");
|
|
return greentea_test_setup_handler(number_of_cases);
|
|
}
|
|
|
|
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
|
|
|
|
int main()
|
|
{
|
|
Harness::run(specification);
|
|
}
|
|
|
|
#endif // !defined(DEVICE_USBDEVICE) || !DEVICE_USBDEVICE
|