mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/usb_v5_update' into 'master'
usb: Run usb_host tests in CI See merge request espressif/esp-idf!19468
This commit is contained in:
commit
7ae5705977
@ -235,7 +235,7 @@
|
||||
- "components/driver/**/*"
|
||||
- "components/sdmmc/**/*"
|
||||
|
||||
# for jobs: example_test_pytest_esp32s3_usb_device and test_app_test_pytest_esp32s2_usb_host:
|
||||
# for jobs: USB host and device examples
|
||||
.patterns-example_test-usb: &patterns-example_test-usb
|
||||
- "components/hal/usb*.c"
|
||||
- "components/hal/esp32s*/include/hal/usb*.h"
|
||||
@ -243,6 +243,12 @@
|
||||
- "examples/peripherals/usb/host/**/**/**/*"
|
||||
- "examples/peripherals/usb/device/**/**/*"
|
||||
|
||||
# for jobs: USB component (Host) pytest test_app
|
||||
.patterns-component_ut-usb: &patterns-component_ut-usb
|
||||
- "components/hal/usb*.c"
|
||||
- "components/hal/esp32s*/include/hal/usb*.h"
|
||||
- "components/usb/**/*"
|
||||
|
||||
# for jobs: component_ut_pytest_esp32x_adc:
|
||||
.patterns-component_ut-adc: &patterns-component_ut-adc
|
||||
- "components/esp_adc/**/*"
|
||||
@ -546,6 +552,8 @@
|
||||
changes: *patterns-component_ut
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-adc
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-usb
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-downloadable-tools
|
||||
- <<: *if-dev-push
|
||||
@ -573,6 +581,8 @@
|
||||
changes: *patterns-component_ut
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-adc
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-usb
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-downloadable-tools
|
||||
- <<: *if-dev-push
|
||||
@ -599,6 +609,8 @@
|
||||
changes: *patterns-component_ut
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-adc
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-usb
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-downloadable-tools
|
||||
- <<: *if-dev-push
|
||||
@ -625,6 +637,8 @@
|
||||
changes: *patterns-component_ut
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-adc
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-usb
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-downloadable-tools
|
||||
- <<: *if-dev-push
|
||||
@ -651,6 +665,8 @@
|
||||
changes: *patterns-component_ut
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-adc
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-usb
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-downloadable-tools
|
||||
- <<: *if-dev-push
|
||||
@ -677,6 +693,8 @@
|
||||
changes: *patterns-component_ut
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-adc
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-usb
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-downloadable-tools
|
||||
- <<: *if-dev-push
|
||||
@ -703,6 +721,8 @@
|
||||
changes: *patterns-component_ut
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-adc
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-usb
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-downloadable-tools
|
||||
- <<: *if-dev-push
|
||||
@ -729,6 +749,8 @@
|
||||
changes: *patterns-component_ut
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-adc
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-usb
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-downloadable-tools
|
||||
- <<: *if-dev-push
|
||||
@ -1285,6 +1307,8 @@
|
||||
changes: *patterns-component_ut
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-adc
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-usb
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-custom_test
|
||||
- <<: *if-dev-push
|
||||
@ -1712,6 +1736,19 @@
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-adc
|
||||
|
||||
.rules:test:component_ut-esp32s3-usb:
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected
|
||||
- <<: *if-label-build-only
|
||||
when: never
|
||||
- <<: *if-label-component_ut
|
||||
- <<: *if-label-component_ut_esp32s3
|
||||
- <<: *if-label-target_test
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-component_ut-usb
|
||||
|
||||
.rules:test:custom_test-esp32:
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
|
@ -640,6 +640,14 @@ example_test_pytest_openthread_br:
|
||||
- esp32h4
|
||||
- i154_multi_dut
|
||||
|
||||
component_ut_pytest_esp32s3_usb_host:
|
||||
extends:
|
||||
- .pytest_components_dir_template
|
||||
- .rules:test:component_ut-esp32s3-usb
|
||||
needs:
|
||||
- build_pytest_components_esp32s3
|
||||
tags: [ esp32s3, usb_host_flash_disk ]
|
||||
|
||||
.pytest_test_apps_dir_template:
|
||||
extends: .pytest_template
|
||||
variables:
|
||||
|
5
components/usb/.build-test-rules.yml
Normal file
5
components/usb/.build-test-rules.yml
Normal file
@ -0,0 +1,5 @@
|
||||
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
|
||||
|
||||
components/usb/test_apps:
|
||||
enable:
|
||||
- if: SOC_USB_OTG_SUPPORTED == 1
|
@ -1,12 +0,0 @@
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
||||
#USB Host is currently only supported on ESP32-S2, ESP32S3 chips
|
||||
if(NOT "${target}" MATCHES "^esp32s[2-3]")
|
||||
return()
|
||||
endif()
|
||||
|
||||
idf_component_register(
|
||||
SRC_DIRS "common" "hcd" "usb_host"
|
||||
PRIV_INCLUDE_DIRS "../private_include" "common" "hcd" "usb_host"
|
||||
PRIV_REQUIRES cmock usb test_utils
|
||||
)
|
@ -1,132 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include "usb/usb_types_ch9.h"
|
||||
#include "test_usb_mock_classes.h"
|
||||
|
||||
// ---------------------------------------------------- MSC SCSI -------------------------------------------------------
|
||||
|
||||
const char *MSC_CLIENT_TAG = "MSC Client";
|
||||
|
||||
const uint8_t mock_msc_scsi_dev_desc[] = {
|
||||
0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x5F, 0x12, 0x8A, 0xC0, 0x00, 0x01, 0x01, 0x02, 0x03, 0x01,
|
||||
};
|
||||
|
||||
const uint8_t mock_msc_scsi_config_desc[] = {
|
||||
0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0xF0, 0x09, 0x04, 0x00, 0x00, 0x02, 0x08, 0x06, 0x50, 0x00, 0x07,
|
||||
0x05, 0x01, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x01,
|
||||
};
|
||||
|
||||
|
||||
const uint8_t mock_msc_scsi_str_desc_manu[] = {
|
||||
0x0c, 0x03, 0x41, 0x00, 0x44, 0x00, 0x41, 0x00, 0x54, 0x00, 0x41, 0x00,
|
||||
};
|
||||
|
||||
const uint8_t mock_msc_scsi_str_desc_prod[] = {
|
||||
0x2c, 0x03, 0x41, 0x00, 0x44, 0x00, 0x41, 0x00, 0x54, 0x00, 0x41, 0x00, 0x20, 0x00, 0x55, 0x00, 0x53, 0x00, 0x42,
|
||||
0x00, 0x20, 0x00, 0x46, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x73, 0x00, 0x68, 0x00, 0x20, 0x00, 0x44, 0x00, 0x72, 0x00,
|
||||
0x69, 0x00, 0x76, 0x00, 0x65, 0x00,
|
||||
};
|
||||
|
||||
const uint8_t mock_msc_scsi_str_desc_ser_num[] = {
|
||||
0x22, 0x03, 0x31, 0x00, 0x33, 0x00, 0x43, 0x00, 0x32, 0x00, 0x38, 0x00, 0x31, 0x00, 0x36, 0x00, 0x35, 0x00, 0x38,
|
||||
0x00, 0x32, 0x00, 0x31, 0x00, 0x38, 0x00, 0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x45, 0x00,
|
||||
};
|
||||
|
||||
const usb_ep_desc_t mock_msc_scsi_bulk_out_ep_desc = {
|
||||
.bLength = sizeof(usb_ep_desc_t),
|
||||
.bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT,
|
||||
.bEndpointAddress = 0x01, //EP 1 OUT
|
||||
.bmAttributes = USB_BM_ATTRIBUTES_XFER_BULK,
|
||||
.wMaxPacketSize = 64, //MPS of 64 bytes
|
||||
.bInterval = 1,
|
||||
};
|
||||
|
||||
const usb_ep_desc_t mock_msc_scsi_bulk_in_ep_desc = {
|
||||
.bLength = sizeof(usb_ep_desc_t),
|
||||
.bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT,
|
||||
.bEndpointAddress = 0x82, //EP 2 IN
|
||||
.bmAttributes = USB_BM_ATTRIBUTES_XFER_BULK,
|
||||
.wMaxPacketSize = 64, //MPS of 64 bytes
|
||||
.bInterval = 1,
|
||||
};
|
||||
|
||||
void mock_msc_scsi_init_cbw(mock_msc_bulk_cbw_t *cbw, bool is_read, int offset, int num_sectors, uint32_t tag)
|
||||
{
|
||||
cbw->dCBWSignature = 0x43425355; //Fixed value
|
||||
cbw->dCBWTag = tag; //Random value that is echoed back
|
||||
cbw->dCBWDataTransferLength = num_sectors * MOCK_MSC_SCSI_SECTOR_SIZE;
|
||||
cbw->bmCBWFlags = (is_read) ? (1 << 7) : 0; //If this is a read, set the direction flag
|
||||
cbw->bCBWLUN = MOCK_MSC_SCSI_LUN;
|
||||
cbw->bCBWCBLength = 10; //The length of the SCSI command
|
||||
//Initialize SCSI CMD as READ10 or WRITE 10
|
||||
cbw->CBWCB.opcode = (is_read) ? 0x28 : 0x2A; //SCSI CMD READ10 or WRITE10
|
||||
cbw->CBWCB.flags = 0;
|
||||
cbw->CBWCB.lba_3 = (offset >> 24);
|
||||
cbw->CBWCB.lba_2 = (offset >> 16);
|
||||
cbw->CBWCB.lba_1 = (offset >> 8);
|
||||
cbw->CBWCB.lba_0 = (offset >> 0);
|
||||
cbw->CBWCB.group = 0;
|
||||
cbw->CBWCB.len_1 = (num_sectors >> 8);
|
||||
cbw->CBWCB.len_0 = (num_sectors >> 0);
|
||||
cbw->CBWCB.control = 0;
|
||||
}
|
||||
|
||||
bool mock_msc_scsi_check_csw(mock_msc_bulk_csw_t *csw, uint32_t tag_expect)
|
||||
{
|
||||
bool no_issues = true;
|
||||
if (csw->dCSWSignature != 0x53425355) {
|
||||
no_issues = false;
|
||||
printf("Warning: csw signature corrupt (0x%"PRIX32")\n", csw->dCSWSignature);
|
||||
}
|
||||
if (csw->dCSWTag != tag_expect) {
|
||||
no_issues = false;
|
||||
printf("Warning: csw tag unexpected! Expected %"PRIu32" got %"PRIu32"\n", tag_expect, csw->dCSWTag);
|
||||
}
|
||||
if (csw->dCSWDataResidue) {
|
||||
no_issues = false;
|
||||
printf("Warning: csw indicates data residue of %"PRIu32" bytes!\n", csw->dCSWDataResidue);
|
||||
}
|
||||
if (csw->bCSWStatus) {
|
||||
no_issues = false;
|
||||
printf("Warning: csw indicates non-good status %d!\n", csw->bCSWStatus);
|
||||
}
|
||||
return no_issues;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------- HID Mouse ------------------------------------------------------
|
||||
|
||||
const usb_ep_desc_t mock_hid_mouse_in_ep_desc = {
|
||||
.bLength = sizeof(usb_ep_desc_t),
|
||||
.bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT,
|
||||
.bEndpointAddress = 0x81, //EP 1 IN
|
||||
.bmAttributes = USB_BM_ATTRIBUTES_XFER_INT,
|
||||
.wMaxPacketSize = 4, //MPS of 4 bytes
|
||||
.bInterval = 10, //Interval of 10ms
|
||||
};
|
||||
|
||||
void mock_hid_process_report(mock_hid_mouse_report_t *report, int iter)
|
||||
{
|
||||
static int x_pos = 0;
|
||||
static int y_pos = 0;
|
||||
//Update X position
|
||||
if (report->x_movement & 0x80) { //Positive movement
|
||||
x_pos += report->x_movement & 0x7F;
|
||||
} else { //Negative movement
|
||||
x_pos -= report->x_movement & 0x7F;
|
||||
}
|
||||
//Update Y position
|
||||
if (report->y_movement & 0x80) { //Positive movement
|
||||
y_pos += report->y_movement & 0x7F;
|
||||
} else { //Negative movement
|
||||
y_pos -= report->y_movement & 0x7F;
|
||||
}
|
||||
printf("\rX:%d\tY:%d\tIter: %d\n", x_pos, y_pos, iter);
|
||||
}
|
@ -1,290 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
This header contains bare-bone mock implementations of some device classes in order to test various layers of the USB
|
||||
Host stack.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_assert.h"
|
||||
#include "usb/usb_types_ch9.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------- MSC SCSI -------------------------------------------------------
|
||||
|
||||
extern const char *MSC_CLIENT_TAG;
|
||||
|
||||
/*
|
||||
Note: The mock MSC SCSI tests requires that USB flash drive be connected. The flash drive should...
|
||||
|
||||
- Be implement the Mass Storage class supporting BULK only transfers using SCSI commands
|
||||
- It's configuration 1 should have the following endpoints
|
||||
|
||||
Device Descriptor:
|
||||
bLength 18
|
||||
bDescriptorType 1
|
||||
bcdUSB 2.00
|
||||
bDeviceClass 0
|
||||
bDeviceSubClass 0
|
||||
bDeviceProtocol 0
|
||||
bMaxPacketSize0 64
|
||||
idVendor 0x125f
|
||||
idProduct 0xc08a
|
||||
bcdDevice 1.00
|
||||
iManufacturer 1
|
||||
iProduct 2
|
||||
iSerial 3
|
||||
bNumConfigurations 1
|
||||
Configuration Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 2
|
||||
wTotalLength 0x0020
|
||||
bNumInterfaces 1
|
||||
bConfigurationValue 1
|
||||
iConfiguration 0
|
||||
bmAttributes 0x80
|
||||
(Bus Powered)
|
||||
MaxPower 480mA
|
||||
Interface Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 4
|
||||
bInterfaceNumber 0
|
||||
bAlternateSetting 0
|
||||
bNumEndpoints 2
|
||||
bInterfaceClass 8 Mass Storage
|
||||
bInterfaceSubClass 6 SCSI
|
||||
bInterfaceProtocol 80 Bulk-Only
|
||||
iInterface 0
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x01 EP 1 OUT
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0040 1x 64 bytes
|
||||
bInterval 1
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x82 EP 2 IN
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0040 1x 64 bytes
|
||||
bInterval 1
|
||||
|
||||
If you're using a flash driver with different endpoints, modify the endpoint descriptors below.
|
||||
*/
|
||||
|
||||
//Constant descriptors
|
||||
extern const uint8_t mock_msc_scsi_dev_desc[];
|
||||
extern const uint8_t mock_msc_scsi_config_desc[];
|
||||
extern const uint8_t mock_msc_scsi_str_desc_manu[];
|
||||
extern const uint8_t mock_msc_scsi_str_desc_prod[];
|
||||
extern const uint8_t mock_msc_scsi_str_desc_ser_num[];
|
||||
extern const usb_ep_desc_t mock_msc_scsi_bulk_out_ep_desc;
|
||||
extern const usb_ep_desc_t mock_msc_scsi_bulk_in_ep_desc;
|
||||
|
||||
#define MOCK_MSC_SCSI_DEV_ID_VENDOR 0x125F
|
||||
#define MOCK_MSC_SCSI_DEV_ID_PRODUCT 0xc08A
|
||||
#define MOCK_MSC_SCSI_DEV_DFLT_EP_MPS 64
|
||||
#define MOCK_MSC_SCSI_SECTOR_SIZE 512
|
||||
#define MOCK_MSC_SCSI_LUN 0
|
||||
#define MOCK_MSC_SCSI_INTF_NUMBER 0
|
||||
#define MOCK_MSC_SCSI_INTF_ALT_SETTING 0
|
||||
#define MOCK_MSC_SCSI_BULK_OUT_EP_ADDR 0x01
|
||||
#define MOCK_MSC_SCSI_BULK_IN_EP_ADDR 0x82
|
||||
#define MOCK_MSC_SCSI_BULK_EP_MPS 64
|
||||
|
||||
#define MOCK_MSC_SCSI_REQ_INIT_RESET(setup_pkt_ptr, intf_num) ({ \
|
||||
(setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT | USB_BM_REQUEST_TYPE_TYPE_CLASS | USB_BM_REQUEST_TYPE_RECIP_INTERFACE; \
|
||||
(setup_pkt_ptr)->bRequest = 0xFF; \
|
||||
(setup_pkt_ptr)->wValue = 0; \
|
||||
(setup_pkt_ptr)->wIndex = (intf_num); \
|
||||
(setup_pkt_ptr)->wLength = 0; \
|
||||
})
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t opcode; //0x28 = read(10), 0x2A=write(10)
|
||||
uint8_t flags;
|
||||
uint8_t lba_3;
|
||||
uint8_t lba_2;
|
||||
uint8_t lba_1;
|
||||
uint8_t lba_0;
|
||||
uint8_t group;
|
||||
uint8_t len_1;
|
||||
uint8_t len_0;
|
||||
uint8_t control;
|
||||
} mock_scsi_cmd10_t;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t dCBWSignature;
|
||||
uint32_t dCBWTag;
|
||||
uint32_t dCBWDataTransferLength;
|
||||
uint8_t bmCBWFlags;
|
||||
uint8_t bCBWLUN;
|
||||
uint8_t bCBWCBLength;
|
||||
mock_scsi_cmd10_t CBWCB;
|
||||
uint8_t padding[6];
|
||||
} mock_msc_bulk_cbw_t;
|
||||
|
||||
// USB Bulk Transfer Command Status Wrapper data
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t dCSWSignature;
|
||||
uint32_t dCSWTag;
|
||||
uint32_t dCSWDataResidue;
|
||||
uint8_t bCSWStatus;
|
||||
} mock_msc_bulk_csw_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize a MSC Command Block Wrapper (CBW) as an SCSI command
|
||||
*
|
||||
* @param cbw CBW structure
|
||||
* @param is_read Is a read command
|
||||
* @param offset Block offset
|
||||
* @param num_sectors Number of sectors to read
|
||||
* @param tag Tag (this is simply echoed back
|
||||
*/
|
||||
void mock_msc_scsi_init_cbw(mock_msc_bulk_cbw_t *cbw, bool is_read, int offset, int num_sectors, uint32_t tag);
|
||||
|
||||
/**
|
||||
* @brief Check that returned Command Status Wrapper (CSW) is valid
|
||||
*
|
||||
* @param csw CSW structure
|
||||
* @param tag_expect Expected tag
|
||||
* @return true CSW is valid
|
||||
* @return false CSW is not valid
|
||||
*/
|
||||
bool mock_msc_scsi_check_csw(mock_msc_bulk_csw_t *csw, uint32_t tag_expect);
|
||||
|
||||
// ---------------------------------------------------- HID Mouse ------------------------------------------------------
|
||||
|
||||
|
||||
/*
|
||||
Note: The mock HID mouse tests require that USB low speed mouse be connected. The mouse should...
|
||||
|
||||
- Be implement the HID with standard report format used by mice
|
||||
- It's configuration 1 should have the following endpoint
|
||||
|
||||
Device Descriptor:
|
||||
bLength 18
|
||||
bDescriptorType 1
|
||||
bcdUSB 2.00
|
||||
bDeviceClass 0
|
||||
bDeviceSubClass 0
|
||||
bDeviceProtocol 0
|
||||
bMaxPacketSize0 8
|
||||
idVendor 0x413c Dell Computer Corp.
|
||||
idProduct 0x301a
|
||||
bcdDevice 1.00
|
||||
iManufacturer 1
|
||||
iProduct 2
|
||||
iSerial 0
|
||||
bNumConfigurations 1
|
||||
Configuration Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 2
|
||||
wTotalLength 0x0022
|
||||
bNumInterfaces 1
|
||||
bConfigurationValue 1
|
||||
iConfiguration 0
|
||||
bmAttributes 0xa0
|
||||
(Bus Powered)
|
||||
Remote Wakeup
|
||||
MaxPower 100mA
|
||||
Interface Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 4
|
||||
bInterfaceNumber 0
|
||||
bAlternateSetting 0
|
||||
bNumEndpoints 1
|
||||
bInterfaceClass 3 Human Interface Device
|
||||
bInterfaceSubClass 1 Boot Interface Subclass
|
||||
bInterfaceProtocol 2 Mouse
|
||||
iInterface 0
|
||||
HID Device Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 33
|
||||
bcdHID 1.11
|
||||
bCountryCode 0 Not supported
|
||||
bNumDescriptors 1
|
||||
bDescriptorType 34 Report
|
||||
wDescriptorLength 46
|
||||
Report Descriptors:
|
||||
** UNAVAILABLE **
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x81 EP 1 IN
|
||||
bmAttributes 3
|
||||
Transfer Type Interrupt
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0004 1x 4 bytes
|
||||
bInterval 10
|
||||
|
||||
If you're using another mice with different endpoints, modify the endpoint descriptor below
|
||||
*/
|
||||
|
||||
extern const usb_ep_desc_t mock_hid_mouse_in_ep_desc;
|
||||
|
||||
#define MOCK_HID_MOUSE_DEV_ID_VENDOR 0x413C
|
||||
#define MOCK_HID_MOUSE_DEV_ID_PRODUCT 0x301A
|
||||
#define MOCK_HID_MOUSE_DEV_DFLT_EP_MPS 8
|
||||
#define MOCK_HID_MOUSE_INTF_NUMBER 0
|
||||
#define MOCK_HID_MOUSE_INTF_ALT_SETTING 0
|
||||
#define MOCK_HID_MOUSE_INTR_IN_EP_ADDR 0x81
|
||||
#define MOCK_HID_MOUSE_INTR_IN_MPS 0x04
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t left_button: 1;
|
||||
uint32_t right_button: 1;
|
||||
uint32_t middle_button: 1;
|
||||
uint32_t reserved5: 5;
|
||||
uint8_t x_movement;
|
||||
uint8_t y_movement;
|
||||
} __attribute__((packed));
|
||||
uint8_t val[3];
|
||||
} mock_hid_mouse_report_t;
|
||||
ESP_STATIC_ASSERT(sizeof(mock_hid_mouse_report_t) == 3, "Size of HID mouse report incorrect");
|
||||
|
||||
void mock_hid_process_report(mock_hid_mouse_report_t *report, int iter);
|
||||
|
||||
// ---------------------------------------------------- Mock ISOC ------------------------------------------------------
|
||||
|
||||
/*
|
||||
Note: ISOC test rely on communicating with a non existent endpoint using ISOC OUT transfers. Since no ACK is given for
|
||||
ISOC, transferring to a non-existent endpoint should work. The non-existent endpoint descriptor is described below:
|
||||
*/
|
||||
|
||||
#define MOCK_ISOC_EP_NUM 2
|
||||
#define MOCK_ISOC_EP_MPS 512
|
||||
|
||||
|
||||
static const usb_ep_desc_t mock_isoc_out_ep_desc = {
|
||||
.bLength = sizeof(usb_ep_desc_t),
|
||||
.bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT,
|
||||
.bEndpointAddress = MOCK_ISOC_EP_NUM,
|
||||
.bmAttributes = USB_BM_ATTRIBUTES_XFER_ISOC,
|
||||
.wMaxPacketSize = MOCK_ISOC_EP_MPS, //MPS of 512 bytes
|
||||
.bInterval = 1, //Isoc interval is (2 ^ (bInterval - 1)) which means an interval of 1ms
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
3
components/usb/test_apps/common/CMakeLists.txt
Normal file
3
components/usb/test_apps/common/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
idf_component_register(SRCS "test_usb_common.c" "test_usb_mock_msc.c" "test_usb_mock_hid.c"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES usb unity)
|
@ -11,6 +11,7 @@
|
||||
#include "hal/usb_phy_types.h"
|
||||
#include "esp_private/usb_phy.h"
|
||||
#include "test_usb_common.h"
|
||||
#include "unity.h"
|
||||
|
||||
static usb_phy_handle_t phy_hdl = NULL;
|
||||
|
||||
@ -25,13 +26,13 @@ void test_usb_init_phy(void)
|
||||
.ext_io_conf = NULL,
|
||||
.otg_io_conf = NULL,
|
||||
};
|
||||
ESP_ERROR_CHECK(usb_new_phy(&phy_config, &phy_hdl));
|
||||
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_new_phy(&phy_config, &phy_hdl), "Failed to init USB PHY");
|
||||
}
|
||||
|
||||
void test_usb_deinit_phy(void)
|
||||
{
|
||||
//Deinitialize the internal USB PHY
|
||||
ESP_ERROR_CHECK(usb_del_phy(phy_hdl));
|
||||
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_del_phy(phy_hdl), "Failed to delete PHY");
|
||||
phy_hdl = NULL;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
void test_usb_init_phy(void);
|
||||
|
||||
/**
|
||||
* @brief Deinitalize the internal USB PHY and USB Controller after USB Host testing
|
||||
* @brief Deinitialize the internal USB PHY and USB Controller after USB Host testing
|
||||
*/
|
||||
void test_usb_deinit_phy(void);
|
||||
|
42
components/usb/test_apps/common/test_usb_mock_hid.c
Normal file
42
components/usb/test_apps/common/test_usb_mock_hid.c
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "usb/usb_types_ch9.h"
|
||||
#include "test_usb_mock_hid.h"
|
||||
|
||||
// ---------------------------------------------------- HID Mouse ------------------------------------------------------
|
||||
|
||||
const usb_ep_desc_t mock_hid_mouse_in_ep_desc = {
|
||||
.bLength = sizeof(usb_ep_desc_t),
|
||||
.bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT,
|
||||
.bEndpointAddress = MOCK_HID_MOUSE_INTR_IN_EP_ADDR, //EP 1 IN
|
||||
.bmAttributes = USB_BM_ATTRIBUTES_XFER_INT,
|
||||
.wMaxPacketSize = MOCK_HID_MOUSE_INTR_IN_MPS,
|
||||
.bInterval = 10, //Interval of 10ms
|
||||
};
|
||||
|
||||
void mock_hid_process_report(mock_hid_mouse_report_t *report, int iter)
|
||||
{
|
||||
static int x_pos = 0;
|
||||
static int y_pos = 0;
|
||||
//Update X position
|
||||
if (report->x_movement & 0x80) { //Positive movement
|
||||
x_pos += report->x_movement & 0x7F;
|
||||
} else { //Negative movement
|
||||
x_pos -= report->x_movement & 0x7F;
|
||||
}
|
||||
//Update Y position
|
||||
if (report->y_movement & 0x80) { //Positive movement
|
||||
y_pos += report->y_movement & 0x7F;
|
||||
} else { //Negative movement
|
||||
y_pos -= report->y_movement & 0x7F;
|
||||
}
|
||||
printf("\rX:%d\tY:%d\tIter: %d\n", x_pos, y_pos, iter);
|
||||
}
|
113
components/usb/test_apps/common/test_usb_mock_hid.h
Normal file
113
components/usb/test_apps/common/test_usb_mock_hid.h
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
This header contains bare-bone mock implementations of some device classes in order to test various layers of the USB
|
||||
Host stack.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_assert.h"
|
||||
#include "usb/usb_types_ch9.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------- HID Mouse ------------------------------------------------------
|
||||
|
||||
|
||||
/*
|
||||
Note: The mock HID mouse tests require that USB low speed mouse be connected. The mouse should...
|
||||
|
||||
- Be implement the HID with standard report format used by mice
|
||||
- It's configuration 1 should have the following endpoint
|
||||
|
||||
------------------ Configuration Descriptor -------------------
|
||||
bLength : 0x09 (9 bytes)
|
||||
bDescriptorType : 0x02 (Configuration Descriptor)
|
||||
wTotalLength : 0x003B (59 bytes)
|
||||
bNumInterfaces : 0x02 (2 Interfaces)
|
||||
bConfigurationValue : 0x01 (Configuration 1)
|
||||
iConfiguration : 0x00 (No String Descriptor)
|
||||
bmAttributes : 0xA0
|
||||
D7: Reserved, set 1 : 0x01
|
||||
D6: Self Powered : 0x00 (no)
|
||||
D5: Remote Wakeup : 0x01 (yes)
|
||||
D4..0: Reserved, set 0 : 0x00
|
||||
MaxPower : 0x32 (100 mA)
|
||||
Data (HexDump) : 09 02 3B 00 02 01 00 A0 32 09 04 00 00 01 03 01
|
||||
02 00 09 21 00 02 00 01 22 4D 00 07 05 81 03 08
|
||||
00 0A 09 04 01 00 01 03 01 01 00 09 21 00 02 00
|
||||
01 22 31 00 07 05 82 03 08 00 0A
|
||||
|
||||
---------------- Interface Descriptor -----------------
|
||||
bLength : 0x09 (9 bytes)
|
||||
bDescriptorType : 0x04 (Interface Descriptor)
|
||||
bInterfaceNumber : 0x00
|
||||
bAlternateSetting : 0x00
|
||||
bNumEndpoints : 0x01 (1 Endpoint)
|
||||
bInterfaceClass : 0x03 (HID - Human Interface Device)
|
||||
bInterfaceSubClass : 0x01 (Boot Interface)
|
||||
bInterfaceProtocol : 0x02 (Mouse)
|
||||
iInterface : 0x00 (No String Descriptor)
|
||||
Data (HexDump) : 09 04 00 00 01 03 01 02 00
|
||||
|
||||
------------------- HID Descriptor --------------------
|
||||
bLength : 0x09 (9 bytes)
|
||||
bDescriptorType : 0x21 (HID Descriptor)
|
||||
bcdHID : 0x0200 (HID Version 2.00)
|
||||
bCountryCode : 0x00 (00 = not localized)
|
||||
bNumDescriptors : 0x01
|
||||
Data (HexDump) : 09 21 00 02 00 01 22 4D 00
|
||||
Descriptor 1:
|
||||
bDescriptorType : 0x22 (Class=Report)
|
||||
wDescriptorLength : 0x004D (77 bytes)
|
||||
Error reading descriptor : ERROR_INVALID_PARAMETER (due to a obscure limitation of the Win32 USB API, see UsbTreeView.txt)
|
||||
|
||||
----------------- Endpoint Descriptor -----------------
|
||||
bLength : 0x07 (7 bytes)
|
||||
bDescriptorType : 0x05 (Endpoint Descriptor)
|
||||
bEndpointAddress : 0x81 (Direction=IN EndpointID=1)
|
||||
bmAttributes : 0x03 (TransferType=Interrupt)
|
||||
wMaxPacketSize : 0x0008
|
||||
bInterval : 0x0A (10 ms)
|
||||
Data (HexDump) : 07 05 81 03 08 00 0A
|
||||
|
||||
If you're using another mice with different endpoints, modify the endpoint descriptor below
|
||||
*/
|
||||
|
||||
extern const usb_ep_desc_t mock_hid_mouse_in_ep_desc;
|
||||
|
||||
#define MOCK_HID_MOUSE_DEV_ID_VENDOR 0x03F0
|
||||
#define MOCK_HID_MOUSE_DEV_ID_PRODUCT 0x1198
|
||||
#define MOCK_HID_MOUSE_DEV_DFLT_EP_MPS 8
|
||||
#define MOCK_HID_MOUSE_INTF_NUMBER 0
|
||||
#define MOCK_HID_MOUSE_INTF_ALT_SETTING 0
|
||||
#define MOCK_HID_MOUSE_INTR_IN_EP_ADDR 0x81
|
||||
#define MOCK_HID_MOUSE_INTR_IN_MPS 8
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t left_button: 1;
|
||||
uint32_t right_button: 1;
|
||||
uint32_t middle_button: 1;
|
||||
uint32_t reserved5: 5;
|
||||
uint8_t x_movement;
|
||||
uint8_t y_movement;
|
||||
} __attribute__((packed));
|
||||
uint8_t val[3];
|
||||
} mock_hid_mouse_report_t;
|
||||
ESP_STATIC_ASSERT(sizeof(mock_hid_mouse_report_t) == 3, "Size of HID mouse report incorrect");
|
||||
|
||||
void mock_hid_process_report(mock_hid_mouse_report_t *report, int iter);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
158
components/usb/test_apps/common/test_usb_mock_msc.c
Normal file
158
components/usb/test_apps/common/test_usb_mock_msc.c
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "usb/usb_types_ch9.h"
|
||||
#include "test_usb_mock_msc.h"
|
||||
|
||||
// ---------------------------------------------------- MSC SCSI -------------------------------------------------------
|
||||
|
||||
const char *MSC_CLIENT_TAG = "MSC Client";
|
||||
|
||||
const usb_device_desc_t mock_msc_scsi_dev_desc = {
|
||||
.bLength = USB_DEVICE_DESC_SIZE,
|
||||
.bDescriptorType = USB_B_DESCRIPTOR_TYPE_DEVICE,
|
||||
.bcdUSB = MOCK_MSC_SCSI_USB_VERSION,
|
||||
.bDeviceClass = USB_CLASS_PER_INTERFACE,
|
||||
.bDeviceSubClass = 0,
|
||||
.bDeviceProtocol = 0,
|
||||
.bMaxPacketSize0 = MOCK_MSC_SCSI_DEV_DFLT_EP_MPS,
|
||||
.idVendor = MOCK_MSC_SCSI_DEV_ID_VENDOR,
|
||||
.idProduct = MOCK_MSC_SCSI_DEV_ID_PRODUCT,
|
||||
.bcdDevice = MOCK_MSC_SCSI_DEV_VERSION,
|
||||
.iManufacturer = 1,
|
||||
.iProduct = 2,
|
||||
.iSerialNumber = 3,
|
||||
.bNumConfigurations = 1,
|
||||
};
|
||||
|
||||
#define MOCK_MSC_SCSI_WTOTALLENGTH (USB_CONFIG_DESC_SIZE + USB_INTF_DESC_SIZE + 2*USB_EP_DESC_SIZE)
|
||||
static const usb_config_desc_t mock_msc_config_desc = {
|
||||
.bLength = USB_CONFIG_DESC_SIZE,
|
||||
.bDescriptorType = USB_B_DESCRIPTOR_TYPE_CONFIGURATION,
|
||||
.wTotalLength = MOCK_MSC_SCSI_WTOTALLENGTH,
|
||||
.bNumInterfaces = 1,
|
||||
.bConfigurationValue = 1,
|
||||
.iConfiguration = 0,
|
||||
.bmAttributes = 0x80,
|
||||
.bMaxPower = 0x70, //224mA
|
||||
};
|
||||
|
||||
static const usb_intf_desc_t mock_msc_intf_desc = {
|
||||
.bLength = USB_INTF_DESC_SIZE,
|
||||
.bDescriptorType = USB_B_DESCRIPTOR_TYPE_INTERFACE,
|
||||
.bInterfaceNumber = MOCK_MSC_SCSI_INTF_NUMBER,
|
||||
.bAlternateSetting = MOCK_MSC_SCSI_INTF_ALT_SETTING,
|
||||
.bNumEndpoints = 2,
|
||||
.bInterfaceClass = USB_CLASS_MASS_STORAGE,
|
||||
.bInterfaceSubClass = 0x06, //SCSI
|
||||
.bInterfaceProtocol = 0x50, //Bulk only
|
||||
.iInterface = 0,
|
||||
};
|
||||
|
||||
uint8_t mock_msc_scsi_config_desc[255];
|
||||
uint16_t mock_msc_scsi_str_desc_manu[128];
|
||||
uint16_t mock_msc_scsi_str_desc_prod[128];
|
||||
uint16_t mock_msc_scsi_str_desc_ser_num[128];
|
||||
|
||||
const usb_ep_desc_t mock_msc_scsi_bulk_out_ep_desc = {
|
||||
.bLength = sizeof(usb_ep_desc_t),
|
||||
.bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT,
|
||||
.bEndpointAddress = MOCK_MSC_SCSI_BULK_OUT_EP_ADDR, //EP 1 OUT
|
||||
.bmAttributes = USB_BM_ATTRIBUTES_XFER_BULK,
|
||||
.wMaxPacketSize = MOCK_MSC_SCSI_BULK_EP_MPS, //MPS of 64 bytes
|
||||
.bInterval = 0,
|
||||
};
|
||||
|
||||
const usb_ep_desc_t mock_msc_scsi_bulk_in_ep_desc = {
|
||||
.bLength = sizeof(usb_ep_desc_t),
|
||||
.bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT,
|
||||
.bEndpointAddress = MOCK_MSC_SCSI_BULK_IN_EP_ADDR,
|
||||
.bmAttributes = USB_BM_ATTRIBUTES_XFER_BULK,
|
||||
.wMaxPacketSize = MOCK_MSC_SCSI_BULK_EP_MPS, //MPS of 64 bytes
|
||||
.bInterval = 0,
|
||||
};
|
||||
|
||||
void mock_msc_scsi_init_cbw(mock_msc_bulk_cbw_t *cbw, bool is_read, int offset, int num_sectors, uint32_t tag)
|
||||
{
|
||||
cbw->dCBWSignature = 0x43425355; //Fixed value
|
||||
cbw->dCBWTag = tag; //Random value that is echoed back
|
||||
cbw->dCBWDataTransferLength = num_sectors * MOCK_MSC_SCSI_SECTOR_SIZE;
|
||||
cbw->bmCBWFlags = (is_read) ? (1 << 7) : 0; //If this is a read, set the direction flag
|
||||
cbw->bCBWLUN = MOCK_MSC_SCSI_LUN;
|
||||
cbw->bCBWCBLength = 10; //The length of the SCSI command
|
||||
//Initialize SCSI CMD as READ10 or WRITE 10
|
||||
cbw->CBWCB.opcode = (is_read) ? 0x28 : 0x2A; //SCSI CMD READ10 or WRITE10
|
||||
cbw->CBWCB.flags = 0;
|
||||
cbw->CBWCB.lba_3 = (offset >> 24);
|
||||
cbw->CBWCB.lba_2 = (offset >> 16);
|
||||
cbw->CBWCB.lba_1 = (offset >> 8);
|
||||
cbw->CBWCB.lba_0 = (offset >> 0);
|
||||
cbw->CBWCB.group = 0;
|
||||
cbw->CBWCB.len_1 = (num_sectors >> 8);
|
||||
cbw->CBWCB.len_0 = (num_sectors >> 0);
|
||||
cbw->CBWCB.control = 0;
|
||||
}
|
||||
|
||||
bool mock_msc_scsi_check_csw(mock_msc_bulk_csw_t *csw, uint32_t tag_expect)
|
||||
{
|
||||
bool no_issues = true;
|
||||
if (csw->dCSWSignature != 0x53425355) {
|
||||
no_issues = false;
|
||||
printf("Warning: csw signature corrupt (0x%"PRIX32")\n", csw->dCSWSignature);
|
||||
}
|
||||
if (csw->dCSWTag != tag_expect) {
|
||||
no_issues = false;
|
||||
printf("Warning: csw tag unexpected! Expected %"PRIu32" got %"PRIu32"\n", tag_expect, csw->dCSWTag);
|
||||
}
|
||||
if (csw->dCSWDataResidue) {
|
||||
no_issues = false;
|
||||
printf("Warning: csw indicates data residue of %"PRIu32" bytes!\n", csw->dCSWDataResidue);
|
||||
}
|
||||
if (csw->bCSWStatus) {
|
||||
no_issues = false;
|
||||
printf("Warning: csw indicates non-good status %d!\n", csw->bCSWStatus);
|
||||
}
|
||||
return no_issues;
|
||||
}
|
||||
|
||||
void mock_msc_scsi_init_reference_descriptors(void)
|
||||
{
|
||||
// Configuration descriptor
|
||||
uint8_t *dest_ptr = mock_msc_scsi_config_desc;
|
||||
memcpy(dest_ptr, (void*)&mock_msc_config_desc, sizeof(mock_msc_config_desc));
|
||||
dest_ptr += USB_CONFIG_DESC_SIZE;
|
||||
memcpy(dest_ptr, (void*)&mock_msc_intf_desc, sizeof(mock_msc_intf_desc));
|
||||
dest_ptr += USB_INTF_DESC_SIZE;
|
||||
memcpy(dest_ptr, (void*)&mock_msc_scsi_bulk_in_ep_desc, sizeof(mock_msc_scsi_bulk_in_ep_desc));
|
||||
dest_ptr += USB_EP_DESC_SIZE;
|
||||
memcpy(dest_ptr, (void*)&mock_msc_scsi_bulk_out_ep_desc, sizeof(mock_msc_scsi_bulk_out_ep_desc));
|
||||
|
||||
// String descriptors
|
||||
const char *str = MOCK_MSC_SCSI_STRING_1;
|
||||
uint8_t chr_count = strlen(str);
|
||||
mock_msc_scsi_str_desc_manu[0] = (USB_B_DESCRIPTOR_TYPE_STRING << 8 ) | (2 * chr_count + 2); // first byte is length (including header), second byte is string type
|
||||
for (uint8_t i = 0; i < chr_count; i++) {
|
||||
mock_msc_scsi_str_desc_manu[1 + i] = str[i];
|
||||
}
|
||||
|
||||
str = MOCK_MSC_SCSI_STRING_2;
|
||||
chr_count = strlen(str);
|
||||
mock_msc_scsi_str_desc_prod[0] = (USB_B_DESCRIPTOR_TYPE_STRING << 8 ) | (2 * chr_count + 2); // first byte is length (including header), second byte is string type
|
||||
for (uint8_t i = 0; i < chr_count; i++) {
|
||||
mock_msc_scsi_str_desc_prod[1 + i] = str[i];
|
||||
}
|
||||
|
||||
str = MOCK_MSC_SCSI_STRING_3;
|
||||
chr_count = strlen(str);
|
||||
mock_msc_scsi_str_desc_ser_num[0] = (USB_B_DESCRIPTOR_TYPE_STRING << 8 ) | (2 * chr_count + 2); // first byte is length (including header), second byte is string type
|
||||
for (uint8_t i = 0; i < chr_count; i++) {
|
||||
mock_msc_scsi_str_desc_ser_num[1 + i] = str[i];
|
||||
}
|
||||
}
|
196
components/usb/test_apps/common/test_usb_mock_msc.h
Normal file
196
components/usb/test_apps/common/test_usb_mock_msc.h
Normal file
@ -0,0 +1,196 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
This header contains bare-bone mock implementations of some device classes in order to test various layers of the USB
|
||||
Host stack.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_assert.h"
|
||||
#include "usb/usb_types_ch9.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------- MSC SCSI -------------------------------------------------------
|
||||
|
||||
extern const char *MSC_CLIENT_TAG;
|
||||
|
||||
/*
|
||||
Note: The mock MSC SCSI tests requires that USB flash drive be connected. The flash drive should...
|
||||
|
||||
- Be implement the Mass Storage class supporting BULK only transfers using SCSI commands
|
||||
- It's configuration 1 should have the following endpoints
|
||||
|
||||
------------------ Configuration Descriptor -------------------
|
||||
bLength : 0x09 (9 bytes)
|
||||
bDescriptorType : 0x02 (Configuration Descriptor)
|
||||
wTotalLength : 0x0020 (32 bytes)
|
||||
bNumInterfaces : 0x01 (1 Interface)
|
||||
bConfigurationValue : 0x01 (Configuration 1)
|
||||
iConfiguration : 0x00 (No String Descriptor)
|
||||
bmAttributes : 0x80
|
||||
D7: Reserved, set 1 : 0x01
|
||||
D6: Self Powered : 0x00 (no)
|
||||
D5: Remote Wakeup : 0x00 (no)
|
||||
D4..0: Reserved, set 0 : 0x00
|
||||
MaxPower : 0x70 (224 mA)
|
||||
Data (HexDump) : 09 02 20 00 01 01 00 80 70 09 04 00 00 02 08 06
|
||||
50 00 07 05 81 02 00 02 00 07 05 02 02 00 02 00
|
||||
|
||||
---------------- Interface Descriptor -----------------
|
||||
bLength : 0x09 (9 bytes)
|
||||
bDescriptorType : 0x04 (Interface Descriptor)
|
||||
bInterfaceNumber : 0x00
|
||||
bAlternateSetting : 0x00
|
||||
bNumEndpoints : 0x02 (2 Endpoints)
|
||||
bInterfaceClass : 0x08 (Mass Storage)
|
||||
bInterfaceSubClass : 0x06 (SCSI transparent command set)
|
||||
bInterfaceProtocol : 0x50 (Bulk-Only Transport)
|
||||
iInterface : 0x00 (No String Descriptor)
|
||||
Data (HexDump) : 09 04 00 00 02 08 06 50 00
|
||||
|
||||
----------------- Endpoint Descriptor -----------------
|
||||
bLength : 0x07 (7 bytes)
|
||||
bDescriptorType : 0x05 (Endpoint Descriptor)
|
||||
bEndpointAddress : 0x81 (Direction=IN EndpointID=1)
|
||||
bmAttributes : 0x02 (TransferType=Bulk)
|
||||
wMaxPacketSize : 0x0040 (max 64 bytes)
|
||||
bInterval : 0x00 (never NAKs)
|
||||
Data (HexDump) : 07 05 81 02 40 00 00
|
||||
|
||||
----------------- Endpoint Descriptor -----------------
|
||||
bLength : 0x07 (7 bytes)
|
||||
bDescriptorType : 0x05 (Endpoint Descriptor)
|
||||
bEndpointAddress : 0x02 (Direction=OUT EndpointID=2)
|
||||
bmAttributes : 0x02 (TransferType=Bulk)
|
||||
wMaxPacketSize : 0x0040 (max 64 bytes)
|
||||
bInterval : 0x00 (never NAKs)
|
||||
Data (HexDump) : 07 05 02 02 40 00 00
|
||||
|
||||
If you're using a flash driver with different endpoints, modify the endpoint descriptors below.
|
||||
*/
|
||||
|
||||
//Constant descriptors
|
||||
extern const usb_device_desc_t mock_msc_scsi_dev_desc;
|
||||
extern uint8_t mock_msc_scsi_config_desc[255];
|
||||
extern uint16_t mock_msc_scsi_str_desc_manu[128];
|
||||
extern uint16_t mock_msc_scsi_str_desc_prod[128];
|
||||
extern uint16_t mock_msc_scsi_str_desc_ser_num[128];
|
||||
extern const usb_ep_desc_t mock_msc_scsi_bulk_out_ep_desc;
|
||||
extern const usb_ep_desc_t mock_msc_scsi_bulk_in_ep_desc;
|
||||
|
||||
#define MOCK_MSC_SCSI_DEV_ID_VENDOR 0x0781 // Western Digital, Sandisk
|
||||
#define MOCK_MSC_SCSI_DEV_ID_PRODUCT 0x5595
|
||||
#define MOCK_MSC_SCSI_DEV_VERSION 0x0100 //1.00
|
||||
#define MOCK_MSC_SCSI_USB_VERSION 0x0210 //2.10
|
||||
#define MOCK_MSC_SCSI_DEV_DFLT_EP_MPS 64
|
||||
#define MOCK_MSC_SCSI_SECTOR_SIZE 512
|
||||
#define MOCK_MSC_SCSI_LUN 0
|
||||
#define MOCK_MSC_SCSI_INTF_NUMBER 0
|
||||
#define MOCK_MSC_SCSI_INTF_ALT_SETTING 0
|
||||
#define MOCK_MSC_SCSI_BULK_OUT_EP_ADDR 0x02
|
||||
#define MOCK_MSC_SCSI_BULK_IN_EP_ADDR 0x81
|
||||
#define MOCK_MSC_SCSI_BULK_EP_MPS 64
|
||||
#define MOCK_MSC_SCSI_STRING_1 (" USB")
|
||||
#define MOCK_MSC_SCSI_STRING_2 (" SanDisk 3.2Gen1")
|
||||
#define MOCK_MSC_SCSI_STRING_3 ("0101cdd1e856b427bbb796f870561a4b2b817af9da9872c8d75217cccdd5d5eccb3a0000000000000000000096abe1a3ff83610095558107aea948b4") // This string is NOT checked by the enum test
|
||||
|
||||
#define MOCK_MSC_SCSI_REQ_INIT_RESET(setup_pkt_ptr, intf_num) ({ \
|
||||
(setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT | USB_BM_REQUEST_TYPE_TYPE_CLASS | USB_BM_REQUEST_TYPE_RECIP_INTERFACE; \
|
||||
(setup_pkt_ptr)->bRequest = 0xFF; \
|
||||
(setup_pkt_ptr)->wValue = 0; \
|
||||
(setup_pkt_ptr)->wIndex = (intf_num); \
|
||||
(setup_pkt_ptr)->wLength = 0; \
|
||||
})
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t opcode; //0x28 = read(10), 0x2A=write(10)
|
||||
uint8_t flags;
|
||||
uint8_t lba_3;
|
||||
uint8_t lba_2;
|
||||
uint8_t lba_1;
|
||||
uint8_t lba_0;
|
||||
uint8_t group;
|
||||
uint8_t len_1;
|
||||
uint8_t len_0;
|
||||
uint8_t control;
|
||||
} mock_scsi_cmd10_t;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t dCBWSignature;
|
||||
uint32_t dCBWTag;
|
||||
uint32_t dCBWDataTransferLength;
|
||||
uint8_t bmCBWFlags;
|
||||
uint8_t bCBWLUN;
|
||||
uint8_t bCBWCBLength;
|
||||
mock_scsi_cmd10_t CBWCB;
|
||||
uint8_t padding[6];
|
||||
} mock_msc_bulk_cbw_t;
|
||||
|
||||
// USB Bulk Transfer Command Status Wrapper data
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t dCSWSignature;
|
||||
uint32_t dCSWTag;
|
||||
uint32_t dCSWDataResidue;
|
||||
uint8_t bCSWStatus;
|
||||
} mock_msc_bulk_csw_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize a MSC Command Block Wrapper (CBW) as an SCSI command
|
||||
*
|
||||
* @param cbw CBW structure
|
||||
* @param is_read Is a read command
|
||||
* @param offset Block offset
|
||||
* @param num_sectors Number of sectors to read
|
||||
* @param tag Tag (this is simply echoed back
|
||||
*/
|
||||
void mock_msc_scsi_init_cbw(mock_msc_bulk_cbw_t *cbw, bool is_read, int offset, int num_sectors, uint32_t tag);
|
||||
|
||||
/**
|
||||
* @brief Check that returned Command Status Wrapper (CSW) is valid
|
||||
*
|
||||
* @param csw CSW structure
|
||||
* @param tag_expect Expected tag
|
||||
* @return true CSW is valid
|
||||
* @return false CSW is not valid
|
||||
*/
|
||||
bool mock_msc_scsi_check_csw(mock_msc_bulk_csw_t *csw, uint32_t tag_expect);
|
||||
|
||||
/**
|
||||
* @brief Construct configuration and string descriptors
|
||||
*/
|
||||
void mock_msc_scsi_init_reference_descriptors(void);
|
||||
|
||||
// ---------------------------------------------------- Mock ISOC ------------------------------------------------------
|
||||
|
||||
/*
|
||||
Note: ISOC test rely on communicating with a non existent endpoint using ISOC OUT transfers. Since no ACK is given for
|
||||
ISOC, transferring to a non-existent endpoint should work. The non-existent endpoint descriptor is described below:
|
||||
*/
|
||||
|
||||
#define MOCK_ISOC_EP_NUM 2
|
||||
#define MOCK_ISOC_EP_MPS 512
|
||||
|
||||
|
||||
static const usb_ep_desc_t mock_isoc_out_ep_desc = {
|
||||
.bLength = sizeof(usb_ep_desc_t),
|
||||
.bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT,
|
||||
.bEndpointAddress = MOCK_ISOC_EP_NUM,
|
||||
.bmAttributes = USB_BM_ATTRIBUTES_XFER_ISOC,
|
||||
.wMaxPacketSize = MOCK_ISOC_EP_MPS, //MPS of 512 bytes
|
||||
.bInterval = 1, //Isoc interval is (2 ^ (bInterval - 1)) which means an interval of 1ms
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
6
components/usb/test_apps/hcd/CMakeLists.txt
Normal file
6
components/usb/test_apps/hcd/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
# This is the project CMakeLists.txt file for the test subproject
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
set(EXTRA_COMPONENT_DIRS "../common")
|
||||
project(test_app_usb_host)
|
10
components/usb/test_apps/hcd/README.md
Normal file
10
components/usb/test_apps/hcd/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
| Supported Targets | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | -------- | -------- |
|
||||
|
||||
# USB: Host test application
|
||||
|
||||
There are two sets of tests in this application:
|
||||
1. Low-speed: Expects low-speed USB mouse with interrupt endpoint to be connected
|
||||
2. Full-speed: Expects full-speed USB flash disk with 2 bulk endpoints to be connected
|
||||
|
||||
For running these tests locally, you will have to update device definitions (VID, PID, ...) in [test_usb_mock_classes.h](../common/test_usb_mock_classes.h).
|
6
components/usb/test_apps/hcd/main/CMakeLists.txt
Normal file
6
components/usb/test_apps/hcd/main/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
|
||||
# the component can be registered as WHOLE_ARCHIVE
|
||||
idf_component_register(SRC_DIRS "."
|
||||
PRIV_INCLUDE_DIRS "../../../private_include" "."
|
||||
REQUIRES usb unity common
|
||||
WHOLE_ARCHIVE)
|
48
components/usb/test_apps/hcd/main/test_app_main.c
Normal file
48
components/usb/test_apps/hcd/main/test_app_main.c
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#include "unity.h"
|
||||
#include "unity_test_runner.h"
|
||||
#include "unity_test_utils_memory.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "test_hcd_common.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
unity_utils_record_free_mem();
|
||||
port_hdl = test_hcd_setup();
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
//Short delay to allow task to be cleaned up
|
||||
vTaskDelay(10);
|
||||
test_hcd_teardown(port_hdl);
|
||||
port_hdl = NULL;
|
||||
unity_utils_evaluate_leaks();
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// ____ ___ ___________________ __ __
|
||||
// | | \/ _____/\______ \ _/ |_ ____ _______/ |_
|
||||
// | | /\_____ \ | | _/ \ __\/ __ \ / ___/\ __\.
|
||||
// | | / / \ | | \ | | \ ___/ \___ \ | |
|
||||
// |______/ /_______ / |______ / |__| \___ >____ > |__|
|
||||
// \/ \/ \/ \/
|
||||
printf(" ____ ___ ___________________ __ __ \r\n");
|
||||
printf("| | \\/ _____/\\______ \\ _/ |_ ____ _______/ |_ \r\n");
|
||||
printf("| | /\\_____ \\ | | _/ \\ __\\/ __ \\ / ___/\\ __\\\r\n");
|
||||
printf("| | / / \\ | | \\ | | \\ ___/ \\___ \\ | | \r\n");
|
||||
printf("|______/ /_______ / |______ / |__| \\___ >____ > |__| \r\n");
|
||||
printf(" \\/ \\/ \\/ \\/ \r\n");
|
||||
|
||||
unity_utils_setup_heap_record(80);
|
||||
unity_utils_set_leak_level(128);
|
||||
unity_run_menu();
|
||||
}
|
@ -9,8 +9,7 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "unity.h"
|
||||
#include "test_utils.h"
|
||||
#include "test_usb_mock_classes.h"
|
||||
#include "test_usb_mock_msc.h"
|
||||
#include "test_hcd_common.h"
|
||||
|
||||
// --------------------------------------------------- Test Cases ------------------------------------------------------
|
||||
@ -25,8 +24,8 @@ static void mock_msc_reset_req(hcd_pipe_handle_t default_pipe)
|
||||
//Enqueue, wait, dequeue, and check URB
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb));
|
||||
test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE);
|
||||
TEST_ASSERT_EQUAL(urb, hcd_urb_dequeue(default_pipe));
|
||||
TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status);
|
||||
TEST_ASSERT_EQUAL_PTR(urb, hcd_urb_dequeue(default_pipe));
|
||||
TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status, "Transfer NOT completed");
|
||||
//Free URB
|
||||
test_hcd_free_urb(urb);
|
||||
}
|
||||
@ -53,9 +52,8 @@ Procedure:
|
||||
#define TEST_NUM_SECTORS_TOTAL 10
|
||||
#define TEST_NUM_SECTORS_PER_XFER 2
|
||||
|
||||
TEST_CASE("Test HCD bulk pipe URBs", "[hcd][ignore]")
|
||||
TEST_CASE("Test HCD bulk pipe URBs", "[bulk][full_speed]")
|
||||
{
|
||||
hcd_port_handle_t port_hdl = test_hcd_setup(); //Setup the HCD and port
|
||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
|
||||
|
||||
@ -80,20 +78,20 @@ TEST_CASE("Test HCD bulk pipe URBs", "[hcd][ignore]")
|
||||
mock_msc_scsi_init_cbw((mock_msc_bulk_cbw_t *)urb_cbw->transfer.data_buffer, true, block_num, TEST_NUM_SECTORS_PER_XFER, 0xAAAAAAAA);
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(bulk_out_pipe, urb_cbw));
|
||||
test_hcd_expect_pipe_event(bulk_out_pipe, HCD_PIPE_EVENT_URB_DONE);
|
||||
TEST_ASSERT_EQUAL(urb_cbw, hcd_urb_dequeue(bulk_out_pipe));
|
||||
TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb_cbw->transfer.status);
|
||||
TEST_ASSERT_EQUAL_PTR(urb_cbw, hcd_urb_dequeue(bulk_out_pipe));
|
||||
TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb_cbw->transfer.status, "Transfer NOT completed");
|
||||
//Read data through BULK IN pipe
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(bulk_in_pipe, urb_data));
|
||||
test_hcd_expect_pipe_event(bulk_in_pipe, HCD_PIPE_EVENT_URB_DONE);
|
||||
TEST_ASSERT_EQUAL(urb_data, hcd_urb_dequeue(bulk_in_pipe));
|
||||
TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb_data->transfer.status);
|
||||
TEST_ASSERT_EQUAL_PTR(urb_data, hcd_urb_dequeue(bulk_in_pipe));
|
||||
TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb_data->transfer.status, "Transfer NOT completed");
|
||||
//Read the CSW through BULK IN pipe
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(bulk_in_pipe, urb_csw));
|
||||
test_hcd_expect_pipe_event(bulk_in_pipe, HCD_PIPE_EVENT_URB_DONE);
|
||||
TEST_ASSERT_EQUAL(urb_csw, hcd_urb_dequeue(bulk_in_pipe));
|
||||
TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb_data->transfer.status);
|
||||
TEST_ASSERT_EQUAL_PTR(urb_csw, hcd_urb_dequeue(bulk_in_pipe));
|
||||
TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb_data->transfer.status, "Transfer NOT completed");
|
||||
TEST_ASSERT_EQUAL(sizeof(mock_msc_bulk_csw_t), urb_csw->transfer.actual_num_bytes);
|
||||
TEST_ASSERT_EQUAL(true, mock_msc_scsi_check_csw((mock_msc_bulk_csw_t *)urb_csw->transfer.data_buffer, 0xAAAAAAAA));
|
||||
TEST_ASSERT_TRUE(mock_msc_scsi_check_csw((mock_msc_bulk_csw_t *)urb_csw->transfer.data_buffer, 0xAAAAAAAA));
|
||||
//Print the read data
|
||||
printf("Block %d to %d:\n", block_num, block_num + TEST_NUM_SECTORS_PER_XFER);
|
||||
for (int i = 0; i < urb_data->transfer.actual_num_bytes; i++) {
|
||||
@ -110,5 +108,4 @@ TEST_CASE("Test HCD bulk pipe URBs", "[hcd][ignore]")
|
||||
test_hcd_pipe_free(default_pipe);
|
||||
//Cleanup
|
||||
test_hcd_wait_for_disconn(port_hdl, false);
|
||||
test_hcd_teardown(port_hdl);
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "test_utils.h"
|
||||
#include "freertos/task.h"
|
||||
#include "soc/usb_wrap_struct.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_err.h"
|
||||
@ -19,6 +19,7 @@
|
||||
#include "usb/usb_types_ch9.h"
|
||||
#include "test_hcd_common.h"
|
||||
#include "test_usb_common.h"
|
||||
#include "unity.h"
|
||||
|
||||
#define PORT_NUM 1
|
||||
#define EVENT_QUEUE_LEN 5
|
||||
@ -35,6 +36,8 @@ typedef struct {
|
||||
hcd_pipe_event_t pipe_event;
|
||||
} pipe_event_msg_t;
|
||||
|
||||
hcd_port_handle_t port_hdl = NULL;
|
||||
|
||||
// ---------------------------------------------------- Private --------------------------------------------------------
|
||||
|
||||
/**
|
||||
@ -52,7 +55,7 @@ static bool port_callback(hcd_port_handle_t port_hdl, hcd_port_event_t port_even
|
||||
//We store the port's queue handle in the port's context variable
|
||||
void *port_ctx = hcd_port_get_context(port_hdl);
|
||||
QueueHandle_t port_evt_queue = (QueueHandle_t)port_ctx;
|
||||
TEST_ASSERT(in_isr); //Current HCD implementation should never call a port callback in a task context
|
||||
TEST_ASSERT_TRUE(in_isr); //Current HCD implementation should never call a port callback in a task context
|
||||
port_event_msg_t msg = {
|
||||
.port_hdl = port_hdl,
|
||||
.port_event = port_event,
|
||||
@ -95,13 +98,14 @@ void test_hcd_expect_port_event(hcd_port_handle_t port_hdl, hcd_port_event_t exp
|
||||
{
|
||||
//Get the port event queue from the port's context variable
|
||||
QueueHandle_t port_evt_queue = (QueueHandle_t)hcd_port_get_context(port_hdl);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, port_evt_queue);
|
||||
TEST_ASSERT_NOT_NULL(port_evt_queue);
|
||||
//Wait for port callback to send an event message
|
||||
port_event_msg_t msg;
|
||||
xQueueReceive(port_evt_queue, &msg, portMAX_DELAY);
|
||||
BaseType_t ret = xQueueReceive(port_evt_queue, &msg, pdMS_TO_TICKS(5000));
|
||||
TEST_ASSERT_EQUAL_MESSAGE(pdPASS, ret, "Port event not generated on time");
|
||||
//Check the contents of that event message
|
||||
TEST_ASSERT_EQUAL(port_hdl, msg.port_hdl);
|
||||
TEST_ASSERT_EQUAL(expected_event, msg.port_event);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(expected_event, msg.port_event, "Unexpected event");
|
||||
printf("\t-> Port event\n");
|
||||
}
|
||||
|
||||
@ -109,20 +113,21 @@ void test_hcd_expect_pipe_event(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t exp
|
||||
{
|
||||
//Get the pipe's event queue from the pipe's context variable
|
||||
QueueHandle_t pipe_evt_queue = (QueueHandle_t)hcd_pipe_get_context(pipe_hdl);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, pipe_evt_queue);
|
||||
TEST_ASSERT_NOT_NULL(pipe_evt_queue);
|
||||
//Wait for pipe callback to send an event message
|
||||
pipe_event_msg_t msg;
|
||||
xQueueReceive(pipe_evt_queue, &msg, portMAX_DELAY);
|
||||
BaseType_t ret = xQueueReceive(pipe_evt_queue, &msg, pdMS_TO_TICKS(5000));
|
||||
TEST_ASSERT_EQUAL_MESSAGE(pdPASS, ret, "Pipe event not generated on time");
|
||||
//Check the contents of that event message
|
||||
TEST_ASSERT_EQUAL(pipe_hdl, msg.pipe_hdl);
|
||||
TEST_ASSERT_EQUAL(expected_event, msg.pipe_event);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(expected_event, msg.pipe_event, "Unexpected event");
|
||||
}
|
||||
|
||||
int test_hcd_get_num_port_events(hcd_port_handle_t port_hdl)
|
||||
{
|
||||
//Get the port event queue from the port's context variable
|
||||
QueueHandle_t port_evt_queue = (QueueHandle_t)hcd_port_get_context(port_hdl);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, port_evt_queue);
|
||||
TEST_ASSERT_NOT_NULL(port_evt_queue);
|
||||
return EVENT_QUEUE_LEN - uxQueueSpacesAvailable(port_evt_queue);
|
||||
}
|
||||
|
||||
@ -130,7 +135,7 @@ int test_hcd_get_num_pipe_events(hcd_pipe_handle_t pipe_hdl)
|
||||
{
|
||||
//Get the pipe's event queue from the pipe's context variable
|
||||
QueueHandle_t pipe_evt_queue = (QueueHandle_t)hcd_pipe_get_context(pipe_hdl);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, pipe_evt_queue);
|
||||
TEST_ASSERT_NOT_NULL(pipe_evt_queue);
|
||||
return EVENT_QUEUE_LEN - uxQueueSpacesAvailable(pipe_evt_queue);
|
||||
}
|
||||
|
||||
@ -141,7 +146,7 @@ hcd_port_handle_t test_hcd_setup(void)
|
||||
test_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing
|
||||
//Create a queue for port callback to queue up port events
|
||||
QueueHandle_t port_evt_queue = xQueueCreate(EVENT_QUEUE_LEN, sizeof(port_event_msg_t));
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, port_evt_queue);
|
||||
TEST_ASSERT_NOT_NULL(port_evt_queue);
|
||||
//Install HCD
|
||||
hcd_config_t hcd_config = {
|
||||
.intr_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
@ -156,7 +161,7 @@ hcd_port_handle_t test_hcd_setup(void)
|
||||
};
|
||||
hcd_port_handle_t port_hdl;
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_port_init(PORT_NUM, &port_config, &port_hdl));
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, port_hdl);
|
||||
TEST_ASSERT_NOT_NULL(port_hdl);
|
||||
TEST_ASSERT_EQUAL(HCD_PORT_STATE_NOT_POWERED, hcd_port_get_state(port_hdl));
|
||||
test_usb_set_phy_state(false, 0); //Force disconnected state on PHY
|
||||
return port_hdl;
|
||||
@ -164,9 +169,12 @@ hcd_port_handle_t test_hcd_setup(void)
|
||||
|
||||
void test_hcd_teardown(hcd_port_handle_t port_hdl)
|
||||
{
|
||||
if (!port_hdl) {
|
||||
return; // In case of setup stage failure, don't run tear-down stage
|
||||
}
|
||||
//Get the queue handle from the port's context variable
|
||||
QueueHandle_t port_evt_queue = (QueueHandle_t)hcd_port_get_context(port_hdl);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, port_evt_queue);
|
||||
TEST_ASSERT_NOT_NULL(port_evt_queue);
|
||||
//Deinitialize a port
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_port_deinit(port_hdl));
|
||||
//Uninstall the HCD
|
||||
@ -226,7 +234,7 @@ hcd_pipe_handle_t test_hcd_pipe_alloc(hcd_port_handle_t port_hdl, const usb_ep_d
|
||||
{
|
||||
//Create a queue for pipe callback to queue up pipe events
|
||||
QueueHandle_t pipe_evt_queue = xQueueCreate(EVENT_QUEUE_LEN, sizeof(pipe_event_msg_t));
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, pipe_evt_queue);
|
||||
TEST_ASSERT_NOT_NULL(pipe_evt_queue);
|
||||
printf("Creating pipe\n");
|
||||
hcd_pipe_config_t pipe_config = {
|
||||
.callback = pipe_callback,
|
||||
@ -238,7 +246,7 @@ hcd_pipe_handle_t test_hcd_pipe_alloc(hcd_port_handle_t port_hdl, const usb_ep_d
|
||||
};
|
||||
hcd_pipe_handle_t pipe_hdl;
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_alloc(port_hdl, &pipe_config, &pipe_hdl));
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, pipe_hdl);
|
||||
TEST_ASSERT_NOT_NULL(pipe_hdl);
|
||||
return pipe_hdl;
|
||||
}
|
||||
|
||||
@ -246,7 +254,7 @@ void test_hcd_pipe_free(hcd_pipe_handle_t pipe_hdl)
|
||||
{
|
||||
//Get the pipe's event queue from its context variable
|
||||
QueueHandle_t pipe_evt_queue = (QueueHandle_t)hcd_pipe_get_context(pipe_hdl);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, pipe_evt_queue);
|
||||
TEST_ASSERT_NOT_NULL(pipe_evt_queue);
|
||||
//Free the pipe and queue
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_free(pipe_hdl));
|
||||
vQueueDelete(pipe_evt_queue);
|
||||
@ -257,8 +265,8 @@ urb_t *test_hcd_alloc_urb(int num_isoc_packets, size_t data_buffer_size)
|
||||
//Allocate a URB and data buffer
|
||||
urb_t *urb = heap_caps_calloc(1, sizeof(urb_t) + (num_isoc_packets * sizeof(usb_isoc_packet_desc_t)), MALLOC_CAP_DEFAULT);
|
||||
uint8_t *data_buffer = heap_caps_malloc(data_buffer_size, MALLOC_CAP_DMA);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, urb);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, data_buffer);
|
||||
TEST_ASSERT_NOT_NULL(urb);
|
||||
TEST_ASSERT_NOT_NULL(data_buffer);
|
||||
//Initialize URB and underlying transfer structure. Need to cast to dummy due to const fields
|
||||
usb_transfer_dummy_t *transfer_dummy = (usb_transfer_dummy_t *)&urb->transfer;
|
||||
transfer_dummy->data_buffer = data_buffer;
|
||||
@ -286,7 +294,7 @@ uint8_t test_hcd_enum_device(hcd_pipe_handle_t default_pipe)
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb));
|
||||
test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE);
|
||||
TEST_ASSERT_EQUAL(urb, hcd_urb_dequeue(default_pipe));
|
||||
TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status, "Transfer NOT completed");
|
||||
|
||||
//Update the MPS of the default pipe
|
||||
usb_device_desc_t *device_desc = (usb_device_desc_t *)(urb->transfer.data_buffer + sizeof(usb_setup_packet_t));
|
||||
@ -298,7 +306,7 @@ uint8_t test_hcd_enum_device(hcd_pipe_handle_t default_pipe)
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb));
|
||||
test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE);
|
||||
TEST_ASSERT_EQUAL(urb, hcd_urb_dequeue(default_pipe));
|
||||
TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status, "Transfer NOT completed");
|
||||
|
||||
//Update address of default pipe
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_update_dev_addr(default_pipe, ENUM_ADDR));
|
||||
@ -309,7 +317,7 @@ uint8_t test_hcd_enum_device(hcd_pipe_handle_t default_pipe)
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb));
|
||||
test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE);
|
||||
TEST_ASSERT_EQUAL(urb, hcd_urb_dequeue(default_pipe));
|
||||
TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status, "Transfer NOT completed");
|
||||
|
||||
//Free URB
|
||||
test_hcd_free_urb(urb);
|
@ -10,6 +10,8 @@
|
||||
#include "usb_private.h"
|
||||
#include "usb/usb_types_ch9.h"
|
||||
|
||||
extern hcd_port_handle_t port_hdl;
|
||||
|
||||
#define URB_CONTEXT_VAL ((void *)0xDEADBEEF)
|
||||
|
||||
// ------------------------------------------------- HCD Event Test ----------------------------------------------------
|
@ -1,22 +1,13 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// 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.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "unity.h"
|
||||
#include "test_utils.h"
|
||||
#include "test_hcd_common.h"
|
||||
|
||||
#define TEST_DEV_ADDR 0
|
||||
@ -42,9 +33,8 @@ Procedure:
|
||||
- Expect URB to be USB_TRANSFER_STATUS_CANCELED or USB_TRANSFER_STATUS_COMPLETED
|
||||
- Teardown
|
||||
*/
|
||||
TEST_CASE("Test HCD control pipe URBs", "[hcd][ignore]")
|
||||
TEST_CASE("Test HCD control pipe URBs", "[ctrl][low_speed][full_speed]")
|
||||
{
|
||||
hcd_port_handle_t port_hdl = test_hcd_setup(); //Setup the HCD and port
|
||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
|
||||
|
||||
@ -72,7 +62,7 @@ TEST_CASE("Test HCD control pipe URBs", "[hcd][ignore]")
|
||||
for (int i = 0; i < NUM_URBS; i++) {
|
||||
urb_t *urb = hcd_urb_dequeue(default_pipe);
|
||||
TEST_ASSERT_EQUAL(urb_list[i], urb);
|
||||
TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status, "Transfer NOT completed");
|
||||
TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context);
|
||||
//We must have transmitted at least the setup packet, but device may return less than bytes requested
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes);
|
||||
@ -115,12 +105,13 @@ TEST_CASE("Test HCD control pipe URBs", "[hcd][ignore]")
|
||||
test_hcd_pipe_free(default_pipe);
|
||||
//Cleanup
|
||||
test_hcd_wait_for_disconn(port_hdl, false);
|
||||
test_hcd_teardown(port_hdl);
|
||||
}
|
||||
|
||||
/*
|
||||
Test HCD control pipe STALL condition, abort, and clear
|
||||
|
||||
@todo this test is not passing with low-speed: test with bus analyzer
|
||||
|
||||
Purpose:
|
||||
- Test that a control pipe can react to a STALL (i.e., a HCD_PIPE_EVENT_ERROR_STALL event)
|
||||
- The HCD_PIPE_CMD_FLUSH can retire all URBs
|
||||
@ -137,9 +128,8 @@ Procedure:
|
||||
- Dequeue URBs
|
||||
- Teardown
|
||||
*/
|
||||
TEST_CASE("Test HCD control pipe STALL", "[hcd][ignore]")
|
||||
TEST_CASE("Test HCD control pipe STALL", "[ctrl][full_speed]")
|
||||
{
|
||||
hcd_port_handle_t port_hdl = test_hcd_setup(); //Setup the HCD and port
|
||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
|
||||
|
||||
@ -205,7 +195,7 @@ TEST_CASE("Test HCD control pipe STALL", "[hcd][ignore]")
|
||||
//expect_pipe_event(pipe_evt_queue, default_pipe, HCD_PIPE_EVENT_URB_DONE);
|
||||
urb_t *urb = hcd_urb_dequeue(default_pipe);
|
||||
TEST_ASSERT_EQUAL(urb_list[i], urb);
|
||||
TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status, "Transfer NOT completed");
|
||||
TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context);
|
||||
//We must have transmitted at least the setup packet, but device may return less than bytes requested
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes);
|
||||
@ -222,7 +212,6 @@ TEST_CASE("Test HCD control pipe STALL", "[hcd][ignore]")
|
||||
test_hcd_pipe_free(default_pipe);
|
||||
//Cleanup
|
||||
test_hcd_wait_for_disconn(port_hdl, false);
|
||||
test_hcd_teardown(port_hdl);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -243,9 +232,8 @@ Procedure:
|
||||
- Check that all URBs have completed successfully
|
||||
- Dequeue URBs and teardown
|
||||
*/
|
||||
TEST_CASE("Test HCD control pipe runtime halt and clear", "[hcd][ignore]")
|
||||
TEST_CASE("Test HCD control pipe runtime halt and clear", "[ctrl][low_speed][full_speed]")
|
||||
{
|
||||
hcd_port_handle_t port_hdl = test_hcd_setup(); //Setup the HCD and port
|
||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
|
||||
|
||||
@ -279,7 +267,7 @@ TEST_CASE("Test HCD control pipe runtime halt and clear", "[hcd][ignore]")
|
||||
//Wait for each URB to be done, dequeue, and check results
|
||||
for (int i = 0; i < NUM_URBS; i++) {
|
||||
urb_t *urb = hcd_urb_dequeue(default_pipe);
|
||||
TEST_ASSERT_EQUAL(urb_list[i], urb);
|
||||
TEST_ASSERT_EQUAL_PTR(urb_list[i], urb);
|
||||
TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED);
|
||||
if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) {
|
||||
//We must have transmitted at least the setup packet, but device may return less than bytes requested
|
||||
@ -302,5 +290,4 @@ TEST_CASE("Test HCD control pipe runtime halt and clear", "[hcd][ignore]")
|
||||
test_hcd_pipe_free(default_pipe);
|
||||
//Cleanup
|
||||
test_hcd_wait_for_disconn(port_hdl, false);
|
||||
test_hcd_teardown(port_hdl);
|
||||
}
|
@ -8,8 +8,8 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "unity.h"
|
||||
#include "test_utils.h"
|
||||
#include "test_usb_mock_classes.h"
|
||||
#include "test_usb_mock_msc.h"
|
||||
#include "test_usb_mock_hid.h"
|
||||
#include "test_hcd_common.h"
|
||||
|
||||
// --------------------------------------------------- Test Cases ------------------------------------------------------
|
||||
@ -36,14 +36,13 @@ Note: Some mice will NAK until it is moved, so try moving the mouse around if th
|
||||
|
||||
#define TEST_HID_DEV_SPEED USB_SPEED_LOW
|
||||
#define NUM_URBS 3
|
||||
#define URB_DATA_BUFF_SIZE 4 //MPS is 4
|
||||
#define URB_DATA_BUFF_SIZE MOCK_HID_MOUSE_INTR_IN_MPS
|
||||
#define NUM_URB_ITERS (NUM_URBS * 100)
|
||||
|
||||
TEST_CASE("Test HCD interrupt pipe URBs", "[hcd][ignore]")
|
||||
TEST_CASE("Test HCD interrupt pipe URBs", "[intr][low_speed]")
|
||||
{
|
||||
hcd_port_handle_t port_hdl = test_hcd_setup(); //Setup the HCD and port
|
||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
|
||||
TEST_ASSERT_EQUAL(TEST_HID_DEV_SPEED, TEST_HID_DEV_SPEED);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(TEST_HID_DEV_SPEED, port_speed, "Connected device is not Low Speed!");
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
|
||||
|
||||
hcd_pipe_handle_t default_pipe = test_hcd_pipe_alloc(port_hdl, NULL, 0, port_speed); //Create a default pipe (using a NULL EP descriptor)
|
||||
@ -68,7 +67,7 @@ TEST_CASE("Test HCD interrupt pipe URBs", "[hcd][ignore]")
|
||||
test_hcd_expect_pipe_event(intr_pipe, HCD_PIPE_EVENT_URB_DONE);
|
||||
//Dequeue the URB and check results
|
||||
urb_t *urb = hcd_urb_dequeue(intr_pipe);
|
||||
TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status, "Transfer NOT completed");
|
||||
TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context);
|
||||
mock_hid_process_report((mock_hid_mouse_report_t *)urb->transfer.data_buffer, iter_count);
|
||||
//Requeue URB
|
||||
@ -85,5 +84,4 @@ TEST_CASE("Test HCD interrupt pipe URBs", "[hcd][ignore]")
|
||||
test_hcd_pipe_free(default_pipe);
|
||||
//Clearnup
|
||||
test_hcd_wait_for_disconn(port_hdl, false);
|
||||
test_hcd_teardown(port_hdl);
|
||||
}
|
@ -9,8 +9,7 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "unity.h"
|
||||
#include "test_utils.h"
|
||||
#include "test_usb_mock_classes.h"
|
||||
#include "test_usb_mock_msc.h"
|
||||
#include "test_usb_common.h"
|
||||
#include "test_hcd_common.h"
|
||||
|
||||
@ -40,9 +39,8 @@ Procedure:
|
||||
- Teardown
|
||||
*/
|
||||
|
||||
TEST_CASE("Test HCD isochronous pipe URBs", "[hcd][ignore]")
|
||||
TEST_CASE("Test HCD isochronous pipe URBs", "[isoc][full_speed]")
|
||||
{
|
||||
hcd_port_handle_t port_hdl = test_hcd_setup(); //Setup the HCD and port
|
||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
|
||||
//The MPS of the ISOC OUT pipe is quite large, so we need to bias the FIFO sizing
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_port_set_fifo_bias(port_hdl, HCD_PORT_FIFO_BIAS_PTX));
|
||||
@ -82,9 +80,9 @@ TEST_CASE("Test HCD isochronous pipe URBs", "[hcd][ignore]")
|
||||
TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context);
|
||||
//Overall URB status and overall number of bytes
|
||||
TEST_ASSERT_EQUAL(URB_DATA_BUFF_SIZE, urb->transfer.actual_num_bytes);
|
||||
TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status, "Transfer NOT completed");
|
||||
for (int pkt_idx = 0; pkt_idx < NUM_PACKETS_PER_URB; pkt_idx++) {
|
||||
TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.isoc_packet_desc[pkt_idx].status);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.isoc_packet_desc[pkt_idx].status, "Transfer NOT completed");
|
||||
}
|
||||
}
|
||||
//Free URB list and pipe
|
||||
@ -95,7 +93,6 @@ TEST_CASE("Test HCD isochronous pipe URBs", "[hcd][ignore]")
|
||||
test_hcd_pipe_free(default_pipe);
|
||||
//Cleanup
|
||||
test_hcd_wait_for_disconn(port_hdl, false);
|
||||
test_hcd_teardown(port_hdl);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -122,9 +119,8 @@ Procedure:
|
||||
- Free both pipes
|
||||
- Teardown
|
||||
*/
|
||||
TEST_CASE("Test HCD isochronous pipe sudden disconnect", "[hcd][ignore]")
|
||||
TEST_CASE("Test HCD isochronous pipe sudden disconnect", "[isoc][full_speed]")
|
||||
{
|
||||
hcd_port_handle_t port_hdl = test_hcd_setup(); //Setup the HCD and port
|
||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
|
||||
//The MPS of the ISOC OUT pipe is quite large, so we need to bias the FIFO sizing
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_port_set_fifo_bias(port_hdl, HCD_PORT_FIFO_BIAS_PTX));
|
||||
@ -189,6 +185,4 @@ TEST_CASE("Test HCD isochronous pipe sudden disconnect", "[hcd][ignore]")
|
||||
}
|
||||
test_hcd_pipe_free(isoc_out_pipe);
|
||||
test_hcd_pipe_free(default_pipe);
|
||||
//Cleanup
|
||||
test_hcd_teardown(port_hdl);
|
||||
}
|
@ -9,7 +9,6 @@
|
||||
#include "freertos/semphr.h"
|
||||
#include "unity.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "test_utils.h"
|
||||
#include "test_usb_common.h"
|
||||
#include "test_hcd_common.h"
|
||||
|
||||
@ -42,9 +41,8 @@ Procedure:
|
||||
- Teardown port and HCD
|
||||
*/
|
||||
|
||||
TEST_CASE("Test HCD port sudden disconnect", "[hcd][ignore]")
|
||||
TEST_CASE("Test HCD port sudden disconnect", "[port][low_speed][full_speed]")
|
||||
{
|
||||
hcd_port_handle_t port_hdl = test_hcd_setup(); //Setup the HCD and port
|
||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
|
||||
|
||||
@ -110,7 +108,6 @@ TEST_CASE("Test HCD port sudden disconnect", "[hcd][ignore]")
|
||||
//Recovered port should be able to connect and disconnect again
|
||||
test_hcd_wait_for_conn(port_hdl);
|
||||
test_hcd_wait_for_disconn(port_hdl, false);
|
||||
test_hcd_teardown(port_hdl);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -133,9 +130,8 @@ Procedure:
|
||||
- Cleanup default pipe
|
||||
- Trigger disconnection and teardown
|
||||
*/
|
||||
TEST_CASE("Test HCD port suspend and resume", "[hcd][ignore]")
|
||||
TEST_CASE("Test HCD port suspend and resume", "[port][low_speed][full_speed]")
|
||||
{
|
||||
hcd_port_handle_t port_hdl = test_hcd_setup(); //Setup the HCD and port
|
||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
|
||||
|
||||
@ -169,7 +165,6 @@ TEST_CASE("Test HCD port suspend and resume", "[hcd][ignore]")
|
||||
test_hcd_pipe_free(default_pipe);
|
||||
//Cleanup
|
||||
test_hcd_wait_for_disconn(port_hdl, false);
|
||||
test_hcd_teardown(port_hdl);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -189,9 +184,8 @@ Procedure:
|
||||
- Check that a disconnection still works after disable
|
||||
- Teardown
|
||||
*/
|
||||
TEST_CASE("Test HCD port disable", "[hcd][ignore]")
|
||||
TEST_CASE("Test HCD port disable", "[port][low_speed][full_speed]")
|
||||
{
|
||||
hcd_port_handle_t port_hdl = test_hcd_setup(); //Setup the HCD and port
|
||||
usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
|
||||
|
||||
@ -210,15 +204,15 @@ TEST_CASE("Test HCD port disable", "[hcd][ignore]")
|
||||
printf("Enqueuing URBs\n");
|
||||
for (int i = 0; i < NUM_URBS; i++) {
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i]));
|
||||
//Add a short delay to let the transfers run for a bit
|
||||
esp_rom_delay_us(POST_ENQUEUE_DELAY_US);
|
||||
}
|
||||
//Add a short delay to let the transfers run for a bit
|
||||
esp_rom_delay_us(POST_ENQUEUE_DELAY_US);
|
||||
|
||||
//Halt the default pipe before suspending
|
||||
TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe));
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_HALT));
|
||||
TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe));
|
||||
|
||||
|
||||
//Check that port can be disabled
|
||||
TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_DISABLE));
|
||||
TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISABLED, hcd_port_get_state(port_hdl));
|
||||
@ -252,7 +246,6 @@ TEST_CASE("Test HCD port disable", "[hcd][ignore]")
|
||||
|
||||
//Trigger a disconnection and cleanup
|
||||
test_hcd_wait_for_disconn(port_hdl, true);
|
||||
test_hcd_teardown(port_hdl);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -279,17 +272,16 @@ static void concurrent_task(void *arg)
|
||||
vTaskDelay(portMAX_DELAY); //Block forever and wait to be deleted
|
||||
}
|
||||
|
||||
TEST_CASE("Test HCD port command bailout", "[hcd][ignore]")
|
||||
TEST_CASE("Test HCD port command bailout", "[port][low_speed][full_speed]")
|
||||
{
|
||||
hcd_port_handle_t port_hdl = test_hcd_setup(); //Setup the HCD and port
|
||||
test_hcd_wait_for_conn(port_hdl); //Trigger a connection
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
|
||||
|
||||
//Create task to run port commands concurrently
|
||||
SemaphoreHandle_t sync_sem = xSemaphoreCreateBinary();
|
||||
TaskHandle_t task_handle;
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, sync_sem);
|
||||
TEST_ASSERT_EQUAL(pdTRUE, xTaskCreatePinnedToCore(concurrent_task, "tsk", 4096, (void *) sync_sem, UNITY_FREERTOS_PRIORITY + 1, &task_handle, 0));
|
||||
TEST_ASSERT_NOT_NULL(sync_sem);
|
||||
TEST_ASSERT_EQUAL(pdTRUE, xTaskCreatePinnedToCore(concurrent_task, "tsk", 4096, (void *) sync_sem, uxTaskPriorityGet(NULL) + 1, &task_handle, 0));
|
||||
|
||||
//Suspend the device
|
||||
printf("Suspending\n");
|
||||
@ -310,6 +302,4 @@ TEST_CASE("Test HCD port command bailout", "[hcd][ignore]")
|
||||
vTaskDelay(pdMS_TO_TICKS(10)); //Short delay for concurrent task finish running
|
||||
vTaskDelete(task_handle);
|
||||
vSemaphoreDelete(sync_sem);
|
||||
|
||||
test_hcd_teardown(port_hdl);
|
||||
}
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include "unity.h"
|
||||
#include "test_utils.h"
|
||||
#include "usb/usb_host.h"
|
||||
|
||||
/*
|
||||
@ -347,11 +346,11 @@ static void test_walk_desc(const usb_config_desc_t *config_desc)
|
||||
const usb_standard_desc_t *cur_desc = (usb_standard_desc_t *)config_desc;
|
||||
for (int i = 0; i < TEST_NUM_INTF_DESC; i++) {
|
||||
cur_desc = usb_parse_next_descriptor_of_type(cur_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, cur_desc);
|
||||
TEST_ASSERT_NOT_NULL(cur_desc);
|
||||
}
|
||||
//Attempting to look for another interface descriptor should result in NULL
|
||||
cur_desc = usb_parse_next_descriptor_of_type(cur_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset);
|
||||
TEST_ASSERT_EQUAL(NULL, cur_desc);
|
||||
TEST_ASSERT_NULL(cur_desc);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -373,37 +372,37 @@ static void test_parse_intf_and_ep(const usb_config_desc_t *config_desc)
|
||||
|
||||
//Get bInterfaceNumber 0 (index 0)
|
||||
const usb_intf_desc_t *intf_desc = usb_parse_interface_descriptor(config_desc, 0, 0, &offset_intf);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, intf_desc);
|
||||
TEST_ASSERT_NOT_NULL(intf_desc);
|
||||
//Should only have one endpoint
|
||||
int offset_ep = offset_intf;
|
||||
const usb_ep_desc_t *ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, 0, config_desc->wTotalLength, &offset_ep);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, ep_desc);
|
||||
TEST_ASSERT_NOT_NULL(ep_desc);
|
||||
TEST_ASSERT_EQUAL(0x83, ep_desc->bEndpointAddress);
|
||||
offset_ep = offset_intf;
|
||||
ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, 1, config_desc->wTotalLength, &offset_ep);
|
||||
TEST_ASSERT_EQUAL(NULL, ep_desc);
|
||||
TEST_ASSERT_NULL(ep_desc);
|
||||
|
||||
//Get bInterfaceNumber 1 alternate setting 0
|
||||
offset_intf = 0;
|
||||
intf_desc = usb_parse_interface_descriptor(config_desc, 1, 0, &offset_intf);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, intf_desc);
|
||||
TEST_ASSERT_NOT_NULL(intf_desc);
|
||||
//Should have no endpoints
|
||||
offset_ep = offset_intf;
|
||||
ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, 0, config_desc->wTotalLength, &offset_ep);
|
||||
TEST_ASSERT_EQUAL(NULL, ep_desc);
|
||||
TEST_ASSERT_NULL(ep_desc);
|
||||
|
||||
//Get bInterfaceNumber 1 alternate setting 1
|
||||
offset_intf = 0;
|
||||
intf_desc = usb_parse_interface_descriptor(config_desc, 1, 1, &offset_intf);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, intf_desc);
|
||||
TEST_ASSERT_NOT_NULL(intf_desc);
|
||||
//Should only have one endpoint
|
||||
offset_ep = offset_intf;
|
||||
ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, 0, config_desc->wTotalLength, &offset_ep);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, ep_desc);
|
||||
TEST_ASSERT_NOT_NULL(ep_desc);
|
||||
TEST_ASSERT_EQUAL(0x81, ep_desc->bEndpointAddress);
|
||||
offset_ep = offset_intf;
|
||||
ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, 1, config_desc->wTotalLength, &offset_ep);
|
||||
TEST_ASSERT_EQUAL(NULL, ep_desc);
|
||||
TEST_ASSERT_NULL(ep_desc);
|
||||
}
|
||||
|
||||
static void test_parse_ep_by_address(const usb_config_desc_t *config_desc)
|
||||
@ -411,25 +410,25 @@ static void test_parse_ep_by_address(const usb_config_desc_t *config_desc)
|
||||
int offset_ep = 0;
|
||||
//Get bInterface 0 bAlternateSetting 0 EP 0x83
|
||||
const usb_ep_desc_t *ep_desc = usb_parse_endpoint_descriptor_by_address(config_desc, 0, 0, 0x83, &offset_ep);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, ep_desc);
|
||||
TEST_ASSERT_NOT_NULL(ep_desc);
|
||||
TEST_ASSERT_EQUAL(0x83, ep_desc->bEndpointAddress);
|
||||
//Getting same EP address under different interface should return NULL
|
||||
offset_ep = 0;
|
||||
ep_desc = usb_parse_endpoint_descriptor_by_address(config_desc, 1, 0, 0x83, &offset_ep);
|
||||
TEST_ASSERT_EQUAL(NULL, ep_desc);
|
||||
TEST_ASSERT_NULL(ep_desc);
|
||||
|
||||
//Get bInterface 1 bAlternateSetting 1 EP 0x81
|
||||
offset_ep = 0;
|
||||
ep_desc = usb_parse_endpoint_descriptor_by_address(config_desc, 1, 1, 0x81, &offset_ep);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, ep_desc);
|
||||
TEST_ASSERT_NOT_NULL(ep_desc);
|
||||
TEST_ASSERT_EQUAL(0x81, ep_desc->bEndpointAddress);
|
||||
//Getting same EP address under different interface should return NULL
|
||||
offset_ep = 0;
|
||||
ep_desc = usb_parse_endpoint_descriptor_by_address(config_desc, 1, 0, 0x81, &offset_ep);
|
||||
TEST_ASSERT_EQUAL(NULL, ep_desc);
|
||||
TEST_ASSERT_NULL(ep_desc);
|
||||
}
|
||||
|
||||
TEST_CASE("Test USB Helpers descriptor parsing", "[usb_host][ignore]")
|
||||
TEST_CASE("Test USB Helpers descriptor parsing", "[helpers][full_speed]")
|
||||
{
|
||||
const usb_config_desc_t *config_desc = (const usb_config_desc_t *)config_desc_bytes;
|
||||
test_walk_desc(config_desc);
|
14
components/usb/test_apps/hcd/pytest_usb_hcd.py
Normal file
14
components/usb/test_apps/hcd/pytest_usb_hcd.py
Normal file
@ -0,0 +1,14 @@
|
||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32s2
|
||||
@pytest.mark.esp32s3
|
||||
@pytest.mark.usb_host_flash_disk
|
||||
def test_usb_hcd(dut: Dut) -> None:
|
||||
dut.expect_exact('Press ENTER to see the list of tests')
|
||||
dut.write('[full_speed]')
|
||||
dut.expect_unity_test_output()
|
8
components/usb/test_apps/hcd/sdkconfig.defaults
Normal file
8
components/usb/test_apps/hcd/sdkconfig.defaults
Normal file
@ -0,0 +1,8 @@
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
|
||||
#
|
||||
# CONFIG_ESP_TASK_WDT_INIT is not set
|
||||
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
|
||||
# CONFIG_UNITY_ENABLE_FLOAT is not set
|
||||
# CONFIG_UNITY_ENABLE_DOUBLE is not set
|
||||
CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL=y
|
6
components/usb/test_apps/usb_host/CMakeLists.txt
Normal file
6
components/usb/test_apps/usb_host/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
# This is the project CMakeLists.txt file for the test subproject
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
set(EXTRA_COMPONENT_DIRS "../common")
|
||||
project(test_app_usb_host)
|
11
components/usb/test_apps/usb_host/README.md
Normal file
11
components/usb/test_apps/usb_host/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
| Supported Targets | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | -------- | -------- |
|
||||
|
||||
# USB: Host test application
|
||||
|
||||
There are two sets of tests in this application:
|
||||
1. Low-speed: Expects low-speed USB mouse with interrupt endpoint to be connected
|
||||
2. Full-speed: Expects full-speed USB flash disk with 2 bulk endpoints to be connected
|
||||
|
||||
For running these tests locally, you will have to update device definitions (VID, PID, ...) in [test_usb_mock_msc.h](../common/test_usb_mock_msc.h) and [test_usb_mock_hid.h](../common/test_usb_mock_hid.h).
|
||||
|
6
components/usb/test_apps/usb_host/main/CMakeLists.txt
Normal file
6
components/usb/test_apps/usb_host/main/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
|
||||
# the component can be registered as WHOLE_ARCHIVE
|
||||
idf_component_register(SRC_DIRS "."
|
||||
PRIV_INCLUDE_DIRS "."
|
||||
REQUIRES usb unity common
|
||||
WHOLE_ARCHIVE)
|
@ -14,7 +14,6 @@
|
||||
#include "ctrl_client.h"
|
||||
#include "usb/usb_host.h"
|
||||
#include "unity.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
/*
|
||||
Implementation of a control transfer client used for USB Host Tests.
|
||||
@ -63,7 +62,7 @@ static void ctrl_transfer_cb(usb_transfer_t *transfer)
|
||||
{
|
||||
ctrl_client_obj_t *ctrl_obj = (ctrl_client_obj_t *)transfer->context;
|
||||
//Check the completed control transfer
|
||||
TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, transfer->status);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, transfer->status, "Transfer NOT completed");
|
||||
TEST_ASSERT_EQUAL(ctrl_obj->config_desc_cached->wTotalLength, transfer->actual_num_bytes - sizeof(usb_setup_packet_t));
|
||||
ctrl_obj->num_xfer_done++;
|
||||
if (ctrl_obj->num_xfer_sent < ctrl_obj->test_param.num_ctrl_xfer_to_send) {
|
||||
@ -134,7 +133,7 @@ void ctrl_client_async_seq_task(void *arg)
|
||||
case TEST_STAGE_DEV_OPEN: {
|
||||
ESP_LOGD(CTRL_CLIENT_TAG, "Open");
|
||||
//Open the device
|
||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_open(ctrl_obj.client_hdl, ctrl_obj.dev_addr_to_open, &ctrl_obj.dev_hdl));
|
||||
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_host_device_open(ctrl_obj.client_hdl, ctrl_obj.dev_addr_to_open, &ctrl_obj.dev_hdl), "Failed to open the device");
|
||||
//Target our transfers to the device
|
||||
for (int i = 0; i < NUM_TRANSFER_OBJ; i++) {
|
||||
ctrl_xfer[i]->device_handle = ctrl_obj.dev_hdl;
|
||||
@ -169,6 +168,7 @@ void ctrl_client_async_seq_task(void *arg)
|
||||
}
|
||||
case TEST_STAGE_DEV_CLOSE: {
|
||||
ESP_LOGD(CTRL_CLIENT_TAG, "Close");
|
||||
vTaskDelay(10); // Give USB Host Lib some time to process all trnsfers
|
||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_close(ctrl_obj.client_hdl, ctrl_obj.dev_hdl));
|
||||
exit_loop = true;
|
||||
break;
|
@ -12,12 +12,11 @@
|
||||
#include "freertos/task.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "test_usb_mock_classes.h"
|
||||
#include "test_usb_mock_msc.h"
|
||||
#include "test_usb_common.h"
|
||||
#include "msc_client.h"
|
||||
#include "usb/usb_host.h"
|
||||
#include "unity.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
/*
|
||||
Implementation of an asynchronous MSC client used for USB Host disconnection test.
|
||||
@ -29,7 +28,7 @@ Implementation of an asynchronous MSC client used for USB Host disconnection tes
|
||||
- Trigger a single MSC SCSI transfer
|
||||
- Split the data stage into multiple transfers (so that the endpoint multiple queued up transfers)
|
||||
- Cause a disconnection mid-way through the data stage
|
||||
- All of the transfers should be automatically deqeueud
|
||||
- All of the transfers should be automatically dequeued
|
||||
- Then a USB_HOST_CLIENT_EVENT_DEV_GONE event should occur afterwards
|
||||
- Free transfer objects
|
||||
- Close device
|
||||
@ -62,7 +61,7 @@ static void msc_reset_cbw_transfer_cb(usb_transfer_t *transfer)
|
||||
{
|
||||
msc_client_obj_t *msc_obj = (msc_client_obj_t *)transfer->context;
|
||||
//We expect the reset and CBW transfers to complete with no issues
|
||||
TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, transfer->status);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, transfer->status, "Transfer NOT completed");
|
||||
TEST_ASSERT_EQUAL(transfer->num_bytes, transfer->actual_num_bytes);
|
||||
switch (msc_obj->cur_stage) {
|
||||
case TEST_STAGE_MSC_RESET:
|
@ -12,12 +12,11 @@
|
||||
#include "freertos/task.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "test_usb_mock_classes.h"
|
||||
#include "test_usb_mock_msc.h"
|
||||
#include "test_usb_common.h"
|
||||
#include "msc_client.h"
|
||||
#include "usb/usb_host.h"
|
||||
#include "unity.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
/*
|
||||
Implementation of an asynchronous MSC client used for USB Host enumeration test.
|
||||
@ -120,10 +119,10 @@ void msc_client_async_enum_task(void *arg)
|
||||
case TEST_STAGE_CHECK_DEV_DESC: {
|
||||
//Check the device descriptor
|
||||
const usb_device_desc_t *device_desc;
|
||||
const usb_device_desc_t *device_desc_ref = (const usb_device_desc_t *)mock_msc_scsi_dev_desc;
|
||||
const usb_device_desc_t *device_desc_ref = &mock_msc_scsi_dev_desc;
|
||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_get_device_descriptor(msc_obj.dev_hdl, &device_desc));
|
||||
TEST_ASSERT_EQUAL(device_desc_ref->bLength, device_desc->bLength);
|
||||
TEST_ASSERT_EQUAL(0, memcmp(device_desc_ref, device_desc, device_desc_ref->bLength));
|
||||
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(device_desc_ref, device_desc, device_desc_ref->bLength, "Device descriptors do not match.");
|
||||
msc_obj.next_stage = TEST_STAGE_CHECK_CONFIG_DESC;
|
||||
skip_event_handling = true; //Need to execute TEST_STAGE_CHECK_CONFIG_DESC
|
||||
break;
|
||||
@ -134,8 +133,8 @@ void msc_client_async_enum_task(void *arg)
|
||||
const usb_config_desc_t *config_desc;
|
||||
const usb_config_desc_t *config_desc_ref = (const usb_config_desc_t *)mock_msc_scsi_config_desc;
|
||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_get_active_config_descriptor(msc_obj.dev_hdl, &config_desc));
|
||||
TEST_ASSERT_EQUAL(config_desc_ref->wTotalLength, config_desc->wTotalLength);
|
||||
TEST_ASSERT_EQUAL(0, memcmp(config_desc_ref, config_desc, config_desc_ref->wTotalLength));
|
||||
TEST_ASSERT_EQUAL_MESSAGE(config_desc_ref->wTotalLength, config_desc->wTotalLength, "Incorrent length of CFG descriptor");
|
||||
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(config_desc_ref, config_desc, config_desc_ref->wTotalLength, "Configuration descriptors do not match");
|
||||
msc_obj.next_stage = TEST_STAGE_CHECK_STR_DESC;
|
||||
skip_event_handling = true; //Need to execute TEST_STAGE_CHECK_STR_DESC
|
||||
break;
|
||||
@ -150,9 +149,9 @@ void msc_client_async_enum_task(void *arg)
|
||||
TEST_ASSERT_EQUAL(manu_str_desc_ref->bLength, dev_info.str_desc_manufacturer->bLength);
|
||||
TEST_ASSERT_EQUAL(product_str_desc_ref->bLength, dev_info.str_desc_product->bLength);
|
||||
TEST_ASSERT_EQUAL(ser_num_str_desc_ref->bLength, dev_info.str_desc_serial_num->bLength);
|
||||
TEST_ASSERT_EQUAL(0, memcmp(manu_str_desc_ref, dev_info.str_desc_manufacturer , manu_str_desc_ref->bLength));
|
||||
TEST_ASSERT_EQUAL(0, memcmp(product_str_desc_ref, dev_info.str_desc_product , manu_str_desc_ref->bLength));
|
||||
TEST_ASSERT_EQUAL(0, memcmp(ser_num_str_desc_ref, dev_info.str_desc_serial_num , manu_str_desc_ref->bLength));
|
||||
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(manu_str_desc_ref, dev_info.str_desc_manufacturer , manu_str_desc_ref->bLength, "Manufacturer string descriptors do not match.");
|
||||
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(product_str_desc_ref, dev_info.str_desc_product , manu_str_desc_ref->bLength, "Product string descriptors do not match.");
|
||||
//TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ser_num_str_desc_ref, dev_info.str_desc_serial_num , manu_str_desc_ref->bLength, "Serial number string descriptors do not match.");
|
||||
//Get dev info and compare
|
||||
msc_obj.next_stage = TEST_STAGE_DEV_CLOSE;
|
||||
skip_event_handling = true; //Need to execute TEST_STAGE_DEV_CLOSE
|
@ -13,11 +13,10 @@
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "test_usb_common.h"
|
||||
#include "test_usb_mock_classes.h"
|
||||
#include "test_usb_mock_msc.h"
|
||||
#include "msc_client.h"
|
||||
#include "usb/usb_host.h"
|
||||
#include "unity.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
/*
|
||||
Implementation of an MSC client used for USB Host Tests
|
||||
@ -62,29 +61,29 @@ static void msc_transfer_cb(usb_transfer_t *transfer)
|
||||
switch (msc_obj->cur_stage) {
|
||||
case TEST_STAGE_MSC_RESET: {
|
||||
//Check MSC SCSI interface reset
|
||||
TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, transfer->status);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, transfer->status, "Transfer NOT completed");
|
||||
TEST_ASSERT_EQUAL(transfer->num_bytes, transfer->actual_num_bytes);
|
||||
msc_obj->next_stage = TEST_STAGE_MSC_CBW;
|
||||
break;
|
||||
}
|
||||
case TEST_STAGE_MSC_CBW: {
|
||||
//Check MSC SCSI CBW transfer
|
||||
TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, transfer->status);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, transfer->status, "Transfer NOT completed");
|
||||
TEST_ASSERT_EQUAL(sizeof(mock_msc_bulk_cbw_t), transfer->actual_num_bytes);
|
||||
msc_obj->next_stage = TEST_STAGE_MSC_DATA;
|
||||
break;
|
||||
}
|
||||
case TEST_STAGE_MSC_DATA: {
|
||||
//Check MSC SCSI data IN transfer
|
||||
TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, transfer->status);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, transfer->status, "Transfer NOT completed");
|
||||
TEST_ASSERT_EQUAL(MOCK_MSC_SCSI_SECTOR_SIZE * msc_obj->test_param.num_sectors_per_xfer, transfer->actual_num_bytes);
|
||||
msc_obj->next_stage = TEST_STAGE_MSC_CSW;
|
||||
break;
|
||||
}
|
||||
case TEST_STAGE_MSC_CSW: {
|
||||
//Check MSC SCSI CSW transfer
|
||||
TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, transfer->status);
|
||||
TEST_ASSERT_EQUAL(true, mock_msc_scsi_check_csw((mock_msc_bulk_csw_t *)transfer->data_buffer, msc_obj->test_param.msc_scsi_xfer_tag));
|
||||
TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, transfer->status, "Transfer NOT completed");
|
||||
TEST_ASSERT_TRUE(mock_msc_scsi_check_csw((mock_msc_bulk_csw_t *)transfer->data_buffer, msc_obj->test_param.msc_scsi_xfer_tag));
|
||||
msc_obj->num_sectors_read += msc_obj->test_param.num_sectors_per_xfer;
|
||||
if (msc_obj->num_sectors_read < msc_obj->test_param.num_sectors_to_read) {
|
||||
msc_obj->next_stage = TEST_STAGE_MSC_CBW;
|
59
components/usb/test_apps/usb_host/main/test_app_main.c
Normal file
59
components/usb/test_apps/usb_host/main/test_app_main.c
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#include "unity.h"
|
||||
#include "unity_test_runner.h"
|
||||
#include "unity_test_utils_memory.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "test_usb_common.h"
|
||||
#include "test_usb_mock_msc.h"
|
||||
#include "usb/usb_host.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
mock_msc_scsi_init_reference_descriptors();
|
||||
unity_utils_record_free_mem();
|
||||
test_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing
|
||||
//Install USB Host
|
||||
usb_host_config_t host_config = {
|
||||
.skip_phy_setup = true, //test_usb_init_phy() will already have setup the internal USB PHY for us
|
||||
.intr_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
};
|
||||
ESP_ERROR_CHECK(usb_host_install(&host_config));
|
||||
printf("USB Host installed\n");
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
//Short delay to allow task to be cleaned up
|
||||
vTaskDelay(10);
|
||||
//Clean up USB Host
|
||||
ESP_ERROR_CHECK(usb_host_uninstall());
|
||||
test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing
|
||||
unity_utils_evaluate_leaks();
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// ____ ___ ___________________ __ __
|
||||
// | | \/ _____/\______ \ _/ |_ ____ _______/ |_
|
||||
// | | /\_____ \ | | _/ \ __\/ __ \ / ___/\ __\.
|
||||
// | | / / \ | | \ | | \ ___/ \___ \ | |
|
||||
// |______/ /_______ / |______ / |__| \___ >____ > |__|
|
||||
// \/ \/ \/ \/
|
||||
printf(" ____ ___ ___________________ __ __ \r\n");
|
||||
printf("| | \\/ _____/\\______ \\ _/ |_ ____ _______/ |_ \r\n");
|
||||
printf("| | /\\_____ \\ | | _/ \\ __\\/ __ \\ / ___/\\ __\\\r\n");
|
||||
printf("| | / / \\ | | \\ | | \\ ___/ \\___ \\ | | \r\n");
|
||||
printf("|______/ /_______ / |______ / |__| \\___ >____ > |__| \r\n");
|
||||
printf(" \\/ \\/ \\/ \\/ \r\n");
|
||||
|
||||
unity_utils_setup_heap_record(80);
|
||||
unity_utils_set_leak_level(128);
|
||||
unity_run_menu();
|
||||
}
|
@ -11,12 +11,11 @@
|
||||
#include "esp_err.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "test_usb_common.h"
|
||||
#include "test_usb_mock_classes.h"
|
||||
#include "test_usb_mock_msc.h"
|
||||
#include "msc_client.h"
|
||||
#include "ctrl_client.h"
|
||||
#include "usb/usb_host.h"
|
||||
#include "unity.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
#define TEST_MSC_NUM_SECTORS_TOTAL 10
|
||||
#define TEST_MSC_NUM_SECTORS_PER_XFER 2
|
||||
@ -45,17 +44,8 @@ Procedure:
|
||||
- Uninstall USB Host Library
|
||||
*/
|
||||
|
||||
TEST_CASE("Test USB Host async client (single client)", "[usb_host][ignore]")
|
||||
TEST_CASE("Test USB Host async client (single client)", "[usb_host][full_speed]")
|
||||
{
|
||||
test_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing
|
||||
//Install USB Host
|
||||
usb_host_config_t host_config = {
|
||||
.skip_phy_setup = true, //test_usb_init_phy() will already have setup the internal USB PHY for us
|
||||
.intr_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
};
|
||||
ESP_ERROR_CHECK(usb_host_install(&host_config));
|
||||
printf("Installed\n");
|
||||
|
||||
//Create task to run client that communicates with MSC SCSI interface
|
||||
msc_client_test_param_t params = {
|
||||
.num_sectors_to_read = TEST_MSC_NUM_SECTORS_TOTAL,
|
||||
@ -66,6 +56,7 @@ TEST_CASE("Test USB Host async client (single client)", "[usb_host][ignore]")
|
||||
};
|
||||
TaskHandle_t task_hdl;
|
||||
xTaskCreatePinnedToCore(msc_client_async_seq_task, "async", 4096, (void *)¶ms, 2, &task_hdl, 0);
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(task_hdl, "Failed to create async task");
|
||||
//Start the task
|
||||
xTaskNotifyGive(task_hdl);
|
||||
|
||||
@ -81,12 +72,6 @@ TEST_CASE("Test USB Host async client (single client)", "[usb_host][ignore]")
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Short delay to allow task to be cleaned up
|
||||
vTaskDelay(10);
|
||||
//Clean up USB Host
|
||||
ESP_ERROR_CHECK(usb_host_uninstall());
|
||||
test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing
|
||||
}
|
||||
|
||||
/*
|
||||
@ -109,17 +94,8 @@ Procedure:
|
||||
- Free all devices
|
||||
- Uninstall USB Host Library
|
||||
*/
|
||||
TEST_CASE("Test USB Host async client (multi client)", "[usb_host][ignore]")
|
||||
TEST_CASE("Test USB Host async client (multi client)", "[usb_host][full_speed]")
|
||||
{
|
||||
test_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing
|
||||
//Install USB Host
|
||||
usb_host_config_t host_config = {
|
||||
.skip_phy_setup = true, //test_usb_init_phy() will already have setup the internal USB PHY for us
|
||||
.intr_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
};
|
||||
ESP_ERROR_CHECK(usb_host_install(&host_config));
|
||||
printf("Installed\n");
|
||||
|
||||
//Create task to run the MSC client
|
||||
msc_client_test_param_t msc_params = {
|
||||
.num_sectors_to_read = TEST_MSC_NUM_SECTORS_TOTAL,
|
||||
@ -130,6 +106,7 @@ TEST_CASE("Test USB Host async client (multi client)", "[usb_host][ignore]")
|
||||
};
|
||||
TaskHandle_t msc_task_hdl;
|
||||
xTaskCreatePinnedToCore(msc_client_async_seq_task, "msc", 4096, (void *)&msc_params, 2, &msc_task_hdl, 0);
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(msc_task_hdl, "Failed to create MSC task");
|
||||
|
||||
//Create task a control transfer client
|
||||
ctrl_client_test_param_t ctrl_params = {
|
||||
@ -139,6 +116,7 @@ TEST_CASE("Test USB Host async client (multi client)", "[usb_host][ignore]")
|
||||
};
|
||||
TaskHandle_t ctrl_task_hdl;
|
||||
xTaskCreatePinnedToCore(ctrl_client_async_seq_task, "ctrl", 4096, (void *)&ctrl_params, 2, &ctrl_task_hdl, 0);
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(ctrl_task_hdl, "Failed to create CTRL task");
|
||||
|
||||
//Start both tasks
|
||||
xTaskNotifyGive(msc_task_hdl);
|
||||
@ -156,12 +134,6 @@ TEST_CASE("Test USB Host async client (multi client)", "[usb_host][ignore]")
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Short delay to allow task to be cleaned up
|
||||
vTaskDelay(10);
|
||||
//Clean up USB Host
|
||||
ESP_ERROR_CHECK(usb_host_uninstall());
|
||||
test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing
|
||||
}
|
||||
|
||||
/*
|
||||
@ -214,18 +186,8 @@ static void test_async_client_cb(const usb_host_client_event_msg_t *event_msg, v
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test USB Host async API", "[usb_host][ignore]")
|
||||
TEST_CASE("Test USB Host async API", "[usb_host][full_speed][low_speed]")
|
||||
{
|
||||
test_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing
|
||||
|
||||
//Install USB Host
|
||||
usb_host_config_t host_config = {
|
||||
.skip_phy_setup = true, //test_usb_init_phy() will already have setup the internal USB PHY for us
|
||||
.intr_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
};
|
||||
ESP_ERROR_CHECK(usb_host_install(&host_config));
|
||||
printf("Installed\n");
|
||||
|
||||
//Register two clients
|
||||
client_test_stage_t client0_stage = CLIENT_TEST_STAGE_NONE;
|
||||
client_test_stage_t client1_stage = CLIENT_TEST_STAGE_NONE;
|
||||
@ -249,16 +211,17 @@ TEST_CASE("Test USB Host async API", "[usb_host][ignore]")
|
||||
usb_host_lib_handle_events(0, NULL);
|
||||
usb_host_client_handle_events(client0_hdl, 0);
|
||||
usb_host_client_handle_events(client1_hdl, 0);
|
||||
vTaskDelay(10);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
|
||||
//Check that both clients can open the device
|
||||
TEST_ASSERT_NOT_EQUAL(0, dev_addr);
|
||||
usb_device_handle_t client0_dev_hdl;
|
||||
usb_device_handle_t client1_dev_hdl;
|
||||
printf("Opening device\n");
|
||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_open(client0_hdl, dev_addr, &client0_dev_hdl));
|
||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_open(client1_hdl, dev_addr, &client1_dev_hdl));
|
||||
TEST_ASSERT_EQUAL(client0_dev_hdl, client1_dev_hdl); //Check that its the same device
|
||||
TEST_ASSERT_EQUAL_PTR(client0_dev_hdl, client1_dev_hdl); //Check that its the same device
|
||||
//Check that a client cannot open a non-existent device
|
||||
TEST_ASSERT_NOT_EQUAL(ESP_OK, usb_host_device_open(client0_hdl, 0, &client0_dev_hdl));
|
||||
|
||||
@ -266,12 +229,14 @@ TEST_CASE("Test USB Host async API", "[usb_host][ignore]")
|
||||
usb_device_handle_t dummy_dev_hdl;
|
||||
TEST_ASSERT_NOT_EQUAL(ESP_OK, usb_host_device_open(client0_hdl, dev_addr, &dummy_dev_hdl));
|
||||
TEST_ASSERT_NOT_EQUAL(ESP_OK, usb_host_device_open(client1_hdl, dev_addr, &dummy_dev_hdl));
|
||||
printf("Claiming interface\n");
|
||||
//Check that both clients cannot claim the same interface
|
||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_interface_claim(client0_hdl, client0_dev_hdl, MOCK_MSC_SCSI_INTF_NUMBER, MOCK_MSC_SCSI_INTF_ALT_SETTING));
|
||||
TEST_ASSERT_NOT_EQUAL(ESP_OK, usb_host_interface_claim(client1_hdl, client1_dev_hdl, MOCK_MSC_SCSI_INTF_NUMBER, MOCK_MSC_SCSI_INTF_ALT_SETTING));
|
||||
//Check that client0 cannot claim the same interface multiple times
|
||||
TEST_ASSERT_NOT_EQUAL(ESP_OK, usb_host_interface_claim(client0_hdl, client0_dev_hdl, MOCK_MSC_SCSI_INTF_NUMBER, MOCK_MSC_SCSI_INTF_ALT_SETTING));
|
||||
|
||||
printf("Releasing interface\n");
|
||||
//Check that client0 can release the interface
|
||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_interface_release(client0_hdl, client0_dev_hdl, MOCK_MSC_SCSI_INTF_NUMBER));
|
||||
//Check that client0 cannot release interface it has not claimed
|
||||
@ -285,6 +250,7 @@ TEST_CASE("Test USB Host async API", "[usb_host][ignore]")
|
||||
usb_host_client_handle_events(client1_hdl, 0);
|
||||
vTaskDelay(10);
|
||||
}
|
||||
printf("Closing device\n");
|
||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_close(client0_hdl, client0_dev_hdl));
|
||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_close(client1_hdl, client1_dev_hdl));
|
||||
|
||||
@ -300,8 +266,4 @@ TEST_CASE("Test USB Host async API", "[usb_host][ignore]")
|
||||
}
|
||||
vTaskDelay(10);
|
||||
}
|
||||
|
||||
//Cleanup
|
||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_uninstall());
|
||||
test_usb_deinit_phy();
|
||||
}
|
@ -10,12 +10,11 @@
|
||||
#include "esp_err.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "test_usb_common.h"
|
||||
#include "test_usb_mock_classes.h"
|
||||
#include "test_usb_mock_msc.h"
|
||||
#include "msc_client.h"
|
||||
#include "ctrl_client.h"
|
||||
#include "usb/usb_host.h"
|
||||
#include "unity.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
// --------------------------------------------------- Test Cases ------------------------------------------------------
|
||||
|
||||
@ -34,17 +33,8 @@ Procedure:
|
||||
|
||||
#define TEST_DCONN_NO_CLIENT_ITERATIONS 3
|
||||
|
||||
TEST_CASE("Test USB Host sudden disconnection (no client)", "[usb_host][ignore]")
|
||||
TEST_CASE("Test USB Host sudden disconnection (no client)", "[usb_host][full_speed][low_speed]")
|
||||
{
|
||||
test_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing
|
||||
//Install USB Host Library
|
||||
usb_host_config_t host_config = {
|
||||
.skip_phy_setup = true, //test_usb_init_phy() will already have setup the internal USB PHY for us
|
||||
.intr_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
};
|
||||
ESP_ERROR_CHECK(usb_host_install(&host_config));
|
||||
printf("Installed\n");
|
||||
|
||||
bool connected = false;
|
||||
int dconn_iter = 0;
|
||||
while (1) {
|
||||
@ -73,10 +63,6 @@ TEST_CASE("Test USB Host sudden disconnection (no client)", "[usb_host][ignore]"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Clean up USB Host
|
||||
ESP_ERROR_CHECK(usb_host_uninstall());
|
||||
test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing
|
||||
}
|
||||
|
||||
/*
|
||||
@ -95,17 +81,8 @@ Procedure:
|
||||
#define TEST_FORCE_DCONN_NUM_TRANSFERS 3
|
||||
#define TEST_MSC_SCSI_TAG 0xDEADBEEF
|
||||
|
||||
TEST_CASE("Test USB Host sudden disconnection (single client)", "[usb_host][ignore]")
|
||||
TEST_CASE("Test USB Host sudden disconnection (single client)", "[usb_host][full_speed]")
|
||||
{
|
||||
test_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing
|
||||
//Install USB Host
|
||||
usb_host_config_t host_config = {
|
||||
.skip_phy_setup = true, //test_usb_init_phy() will already have setup the internal USB PHY for us
|
||||
.intr_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
};
|
||||
ESP_ERROR_CHECK(usb_host_install(&host_config));
|
||||
printf("Installed\n");
|
||||
|
||||
//Create task to run client that communicates with MSC SCSI interface
|
||||
msc_client_test_param_t params = {
|
||||
.num_sectors_to_read = 1, //Unused by disconnect MSC client
|
||||
@ -134,12 +111,6 @@ TEST_CASE("Test USB Host sudden disconnection (single client)", "[usb_host][igno
|
||||
all_dev_free = true;
|
||||
}
|
||||
}
|
||||
|
||||
//Short delay to allow task to be cleaned up
|
||||
vTaskDelay(10);
|
||||
//Clean up USB Host
|
||||
ESP_ERROR_CHECK(usb_host_uninstall());
|
||||
test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing
|
||||
}
|
||||
|
||||
/*
|
||||
@ -160,17 +131,8 @@ Procedure:
|
||||
|
||||
#define TEST_ENUM_ITERATIONS 3
|
||||
|
||||
TEST_CASE("Test USB Host enumeration", "[usb_host][ignore]")
|
||||
TEST_CASE("Test USB Host enumeration", "[usb_host][full_speed]")
|
||||
{
|
||||
test_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing
|
||||
//Install USB Host
|
||||
usb_host_config_t host_config = {
|
||||
.skip_phy_setup = true, //test_usb_init_phy() will already have setup the internal USB PHY for us
|
||||
.intr_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
};
|
||||
ESP_ERROR_CHECK(usb_host_install(&host_config));
|
||||
printf("Installed\n");
|
||||
|
||||
//Create task to run client that checks the enumeration of the device
|
||||
TaskHandle_t task_hdl;
|
||||
xTaskCreatePinnedToCore(msc_client_async_enum_task, "async", 6144, NULL, 2, &task_hdl, 0);
|
||||
@ -192,10 +154,4 @@ TEST_CASE("Test USB Host enumeration", "[usb_host][ignore]")
|
||||
all_dev_free = true;
|
||||
}
|
||||
}
|
||||
|
||||
//Short delay to allow task to be cleaned up
|
||||
vTaskDelay(10);
|
||||
//Clean up USB Host
|
||||
ESP_ERROR_CHECK(usb_host_uninstall());
|
||||
test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing
|
||||
}
|
14
components/usb/test_apps/usb_host/pytest_usb_host.py
Normal file
14
components/usb/test_apps/usb_host/pytest_usb_host.py
Normal file
@ -0,0 +1,14 @@
|
||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32s2
|
||||
@pytest.mark.esp32s3
|
||||
@pytest.mark.usb_host_flash_disk
|
||||
def test_usb_host(dut: Dut) -> None:
|
||||
dut.expect_exact('Press ENTER to see the list of tests')
|
||||
dut.write('[full_speed]')
|
||||
dut.expect_unity_test_output()
|
8
components/usb/test_apps/usb_host/sdkconfig.defaults
Normal file
8
components/usb/test_apps/usb_host/sdkconfig.defaults
Normal file
@ -0,0 +1,8 @@
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
|
||||
#
|
||||
# CONFIG_ESP_TASK_WDT_INIT is not set
|
||||
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
|
||||
# CONFIG_UNITY_ENABLE_FLOAT is not set
|
||||
# CONFIG_UNITY_ENABLE_DOUBLE is not set
|
||||
CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL=y
|
@ -41,6 +41,7 @@ markers =
|
||||
quad_psram: runners with quad psram
|
||||
octal_psram: runners with octal psram
|
||||
usb_host: usb host runners
|
||||
usb_host_flash_disk: usb host runners with USB flash disk attached
|
||||
usb_device: usb device runners
|
||||
ethernet_ota: ethernet OTA runners
|
||||
flash_encryption: Flash Encryption runners
|
||||
|
Loading…
Reference in New Issue
Block a user