mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-29 18:27:20 +02:00
usb: Refactor USB Host tests
* Error messages improved
* Configurable for different mock devices
Note: Backport 645592e157
to v4.4 without
migrating to pytest.
This commit is contained in:
committed by
Darian Leung
parent
7295933f5f
commit
5842aca69c
@ -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;
|
||||
|
||||
@ -24,13 +25,13 @@ void test_usb_init_phy(void)
|
||||
.otg_speed = USB_PHY_SPEED_UNDEFINED, //In Host mode, the speed is determined by the connected device
|
||||
.gpio_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);
|
||||
|
||||
|
@ -1,132 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.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%X)\n", csw->dCSWSignature);
|
||||
}
|
||||
if (csw->dCSWTag != tag_expect) {
|
||||
no_issues = false;
|
||||
printf("Warning: csw tag unexpected! Expected %d got %d\n", tag_expect, csw->dCSWTag);
|
||||
}
|
||||
if (csw->dCSWDataResidue) {
|
||||
no_issues = false;
|
||||
printf("Warning: csw indicates data residue of %d 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 -------------------------------------------------------
|
||||
|
||||
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
|
42
components/usb/test/common/test_usb_mock_hid.c
Normal file
42
components/usb/test/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/common/test_usb_mock_hid.h
Normal file
113
components/usb/test/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/common/test_usb_mock_msc.c
Normal file
158
components/usb/test/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/common/test_usb_mock_msc.h
Normal file
196
components/usb/test/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
|
@ -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);
|
||||
}
|
||||
@ -80,20 +79,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++) {
|
||||
|
@ -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
|
||||
@ -52,7 +53,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 +96,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 +111,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 +133,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 +144,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 +159,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 +167,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 +232,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 +244,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 +252,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 +263,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 +292,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 +304,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 +315,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);
|
||||
|
@ -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
|
||||
@ -72,7 +63,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);
|
||||
@ -121,6 +112,8 @@ TEST_CASE("Test HCD control pipe URBs", "[hcd][ignore]")
|
||||
/*
|
||||
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
|
||||
@ -205,7 +198,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);
|
||||
@ -279,7 +272,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
|
||||
|
@ -8,8 +8,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_hid.h"
|
||||
#include "test_hcd_common.h"
|
||||
|
||||
// --------------------------------------------------- Test Cases ------------------------------------------------------
|
||||
@ -36,14 +35,14 @@ 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]")
|
||||
{
|
||||
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
|
||||
|
@ -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"
|
||||
|
||||
@ -82,9 +81,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
|
||||
|
@ -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"
|
||||
|
||||
@ -210,15 +209,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));
|
||||
@ -288,8 +287,8 @@ TEST_CASE("Test HCD port command bailout", "[hcd][ignore]")
|
||||
//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");
|
||||
|
@ -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;
|
||||
|
@ -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,22 +410,22 @@ 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]")
|
||||
|
@ -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
|
||||
@ -66,6 +65,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);
|
||||
|
||||
@ -130,6 +130,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 +140,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);
|
||||
@ -249,16 +251,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 +269,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 +290,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));
|
||||
|
||||
|
@ -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 ------------------------------------------------------
|
||||
|
||||
@ -162,6 +161,7 @@ Procedure:
|
||||
|
||||
TEST_CASE("Test USB Host enumeration", "[usb_host][ignore]")
|
||||
{
|
||||
mock_msc_scsi_init_reference_descriptors();
|
||||
test_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing
|
||||
//Install USB Host
|
||||
usb_host_config_t host_config = {
|
||||
|
Reference in New Issue
Block a user