diff --git a/.codespellrc b/.codespellrc index 4f3b1e3bee..389e346d2a 100644 --- a/.codespellrc +++ b/.codespellrc @@ -1,4 +1,4 @@ [codespell] skip = build,*.yuv,components/fatfs/src/*,alice.txt,*.rgb,components/wpa_supplicant/*,components/esp_wifi/* -ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart +ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart,wheight write-changes = true diff --git a/components/usb/test_apps/common/CMakeLists.txt b/components/usb/test_apps/common/CMakeLists.txt index f03c668f9e..047989446d 100644 --- a/components/usb/test_apps/common/CMakeLists.txt +++ b/components/usb/test_apps/common/CMakeLists.txt @@ -1,3 +1,7 @@ -idf_component_register(SRCS "test_usb_common.c" "test_usb_mock_msc.c" "test_usb_mock_hid.c" +idf_component_register(SRCS "dev_hid.c" + "dev_isoc.c" + "dev_msc.c" + "mock_msc.c" + "test_usb_common.c" INCLUDE_DIRS "." REQUIRES usb unity) diff --git a/components/usb/test_apps/common/dev_hid.c b/components/usb/test_apps/common/dev_hid.c new file mode 100644 index 0000000000..91d52a67b7 --- /dev/null +++ b/components/usb/test_apps/common/dev_hid.c @@ -0,0 +1,232 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "usb/usb_types_ch9.h" +#include "usb/usb_types_stack.h" +#include "dev_hid.h" + +/* +Some tests where the ESP (acting as host) will require that a particular test +device acting as an HID mouse be connected. That test device's information and descriptors are defined in this file. + +If you are connecting a different HID mouse, please update the descriptor and +getter functions accordingly. + +------------------------------ Device Descriptor ------------------------------- +bLength : 0x12 (18 bytes) +bDescriptorType : 0x01 (Device Descriptor) +bcdUSB : 0x0210 (2.00) +bDeviceClass : 0x00 +bDeviceSubClass : 0x00 +bDeviceProtocol : 0x00 +bMaxPacketSize0 : 0x08 (8 bytes) +idVendor : 0x413C (Dell Computer Corp) +idProduct : 0x301A (Dell MS116 Optical Mouse) +bcdDevice : 0x0100 (1.00) +iManufacturer : 1 +iProduct : 2 +iSerial : 0 +bNumConfigurations : 1 + +--------------------------- Configuration Descriptor --------------------------- +bLength : 0x09 (9 bytes) +bDescriptorType : 0x02 (Configuration Descriptor) +wTotalLength : 0x0022 (34 bytes) +bNumInterfaces : 0x01 (1 Interface) +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) + +-------------------------------- HID Descriptor -------------------------------- +bLength : 0x09 (9 bytes) +bDescriptorType : 0x21 (HID Descriptor) +bcdHID : 0x0200 (HID Version 2.00) +bCountryCode : 0x00 (00 = not localized) +bNumDescriptors : 0x01 +Descriptor 1: +bDescriptorType : 0x22 (Class=Report) +wDescriptorLength : 0x004D (77 bytes) + +------------------------------ 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) + +---------------------------- String Descriptor Manu ---------------------------- +bLength : 0x0E (14 bytes) +bDescriptorType : 0x03 (String Descriptor) +wData : "PixArt" + +---------------------------- String Descriptor Prod ---------------------------- +bLength : 0x3A (58 bytes) +bDescriptorType : 0x03 (String Descriptor) +wData : "Dell MS116 USB Optical Mouse" +*/ + +// ------------------------------- Descriptors --------------------------------- + +static const usb_device_desc_t dev_desc = { + .bLength = USB_DEVICE_DESC_SIZE, + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_DEVICE, + .bcdUSB = 0x0210, // 2.10 + .bDeviceClass = USB_CLASS_PER_INTERFACE, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = 64, + .idVendor = 0x413C, // Dell Computer Corp + .idProduct = 0x301A, // Dell MS116 Optical Mouse + .bcdDevice = 0x0100, // 1.00 + .iManufacturer = 1, + .iProduct = 2, + .iSerialNumber = 0, + .bNumConfigurations = 1, +}; + +static const usb_config_desc_t config_desc = { + .bLength = USB_CONFIG_DESC_SIZE, + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_CONFIGURATION, + .wTotalLength = 0x0022, // 34 bytes + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = 0xA0, + .bMaxPower = 0x32, // 100 mA +}; + +static const usb_intf_desc_t intf_desc = { + .bLength = USB_INTF_DESC_SIZE, + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_HID, + .bInterfaceSubClass = 0x01, // Boot Interface + .bInterfaceProtocol = 0x02, // Mouse + .iInterface = 0, // (No String Descriptor) +}; + +const usb_ep_desc_t in_ep_desc = { + .bLength = USB_EP_DESC_SIZE, + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = 0x81, // EP 1 IN + .bmAttributes = USB_BM_ATTRIBUTES_XFER_INT, + .wMaxPacketSize = 0x0008, + .bInterval = 0x0A, // 10 ms +}; + +/* +String descriptors are dynamically initialized due to issues with static +initialization of variable length array members. See IDF-9886. +*/ + +static const usb_str_desc_t str_desc_manu_base = { + .bLength = sizeof(usb_str_desc_t) + (6 * sizeof(uint16_t)), + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_STRING, +}; +static const uint16_t str_desc_manu_data[] = { + 0x0050, // 'P' + 0x0069, // 'i' + 0x0078, // 'x' + 0x0041, // 'A' + 0x0072, // 'r' + 0x0074, // 't' +}; +static uint8_t *str_desc_manu[sizeof(str_desc_manu_base) + sizeof(str_desc_manu_data)]; + +static const usb_str_desc_t str_desc_prod_base = { + .bLength = sizeof(usb_str_desc_t) + (28 * sizeof(uint16_t)), + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_STRING, +}; +static const uint16_t str_desc_prod_data[] = { + /* + The following string encoded in UTF-16LE + + "Dell MS116 USB Optical Mouse" + */ + 0x0044, 0x0065, 0x006c, 0x006c, 0x0020, 0x004d, 0x0053, 0x0031, 0x0031, + 0x0036, 0x0020, 0x0055, 0x0053, 0x0042, 0x0020, 0x004f, 0x0070, 0x0074, + 0x0069, 0x0063, 0x0061, 0x006c, 0x0020, 0x004d, 0x006f, 0x0075, 0x0073, + 0x0065, +}; +static uint8_t *str_desc_prod[sizeof(str_desc_prod_base) + sizeof(str_desc_prod_data)]; + +// -------------------------------- Functions ---------------------------------- + +void dev_hid_init(void) +{ + // Dynamically initialize string descriptors due to compiler limitations (see IDF-9886) + uint8_t *ptr; + + // Initialize manufacturer string descriptor + ptr = (uint8_t *)str_desc_manu; + memcpy(ptr, &str_desc_manu_base, sizeof(str_desc_manu_base)); + ptr += sizeof(str_desc_manu_base); + memcpy(ptr, &str_desc_manu_data, sizeof(str_desc_manu_data)); + + // Initialize product string descriptor + ptr = (uint8_t *)str_desc_prod; + memcpy(ptr, &str_desc_prod_base, sizeof(str_desc_prod_base)); + ptr += sizeof(str_desc_prod_base); + memcpy(ptr, &str_desc_prod_data, sizeof(str_desc_prod_data)); + + // No serial string descriptor +} + +const usb_device_desc_t *dev_hid_get_dev_desc(usb_speed_t speed) +{ + return &dev_desc; +} + +const usb_config_desc_t *dev_hid_get_config_desc(usb_speed_t speed) +{ + return &config_desc; +} + +const usb_intf_desc_t *dev_hid_get_intf_desc(usb_speed_t speed) +{ + return &intf_desc; +} + +const usb_ep_desc_t *dev_hid_get_in_ep_desc(usb_speed_t speed) +{ + return &in_ep_desc; +} + +const usb_str_desc_t *dev_hid_get_str_desc_manu(void) +{ + return (const usb_str_desc_t *)str_desc_manu; +} + +const usb_str_desc_t *dev_hid_get_str_desc_prod(void) +{ + return (const usb_str_desc_t *)str_desc_prod; +} diff --git a/components/usb/test_apps/common/dev_hid.h b/components/usb/test_apps/common/dev_hid.h new file mode 100644 index 0000000000..a0eb581e3d --- /dev/null +++ b/components/usb/test_apps/common/dev_hid.h @@ -0,0 +1,80 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "usb/usb_types_ch9.h" +#include "usb/usb_types_stack.h" + +/* +Some tests where the ESP (acting as host) will require that a particular test +device acting as an HID mouse be connected. That test device's information and descriptors are defined in this file. + +If you are connecting a different device, please update the descriptors in +dev_hid.c accordingly. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize the test device + * + * @note Call this before running tests. This is necessary due to IDF-9886 + */ +void dev_hid_init(void); + +/** + * @brief Get the test device's descriptor + * + * @param[in] speed Test device's current speed + * @return Device descriptor + */ +const usb_device_desc_t *dev_hid_get_dev_desc(usb_speed_t speed); + +/** + * @brief Get the test device's configuration descriptor + * + * @param[in] speed Test device's current speed + * @return Configuration descriptor + */ +const usb_config_desc_t *dev_hid_get_config_desc(usb_speed_t speed); + +/** + * @brief Get the test device's HID interface descriptor + * + * @param[in] speed Test device's current speed + * @return HID interface descriptor + */ +const usb_intf_desc_t *dev_hid_get_intf_desc(usb_speed_t speed); + +/** + * @brief Get the test device's HID interrupt IN endpoint descriptor + * + * @param[in] speed Test device's current speed + * @return Interrupt IN endpoint descriptor + */ +const usb_ep_desc_t *dev_hid_get_in_ep_desc(usb_speed_t speed); + +/** + * @brief Get the test device's manufacturer string descriptor + * + * @return Manufacturer string descriptor + */ +const usb_str_desc_t *dev_hid_get_str_desc_manu(void); + +/** + * @brief Get the test device's product string descriptor + * + * @return Product string descriptor + */ +const usb_str_desc_t *dev_hid_get_str_desc_prod(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/usb/test_apps/common/dev_isoc.c b/components/usb/test_apps/common/dev_isoc.c new file mode 100644 index 0000000000..6cf1eb52f6 --- /dev/null +++ b/components/usb/test_apps/common/dev_isoc.c @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "usb/usb_types_ch9.h" +#include "usb/usb_types_stack.h" +#include "dev_isoc.h" + +// ------------------------------- Descriptors --------------------------------- + +static const usb_ep_desc_t isoc_out_ep_desc = { + .bLength = sizeof(usb_ep_desc_t), + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = 0x02, // EP 2 OUT + .bmAttributes = USB_BM_ATTRIBUTES_XFER_ISOC, + .wMaxPacketSize = 512, + .bInterval = 1, // Isoc interval is (2 ^ (bInterval - 1)) which means an interval of 1ms +}; + +// -------------------------------- Functions ---------------------------------- + +const usb_ep_desc_t *dev_isoc_get_out_ep_desc(usb_speed_t speed) +{ + return &isoc_out_ep_desc; +} diff --git a/components/usb/test_apps/common/dev_isoc.h b/components/usb/test_apps/common/dev_isoc.h new file mode 100644 index 0000000000..9096179ac3 --- /dev/null +++ b/components/usb/test_apps/common/dev_isoc.h @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "usb/usb_types_ch9.h" +#include "usb/usb_types_stack.h" + +/* +Some tests where the ESP (acting as host) will require that a particular test +device containing an ISOC endpoint be connected. This header contains +functions to get information and descriptors about that test device. + +If you are connecting a different device, please update the descriptors in +dev_isoc.c accordingly. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Get the test device's ISOC OUT endpoint descriptor + * + * @param[in] speed Test device's current speed + * @return ISOC OUT endpoint descriptor + */ +const usb_ep_desc_t *dev_isoc_get_out_ep_desc(usb_speed_t speed); + +#ifdef __cplusplus +} +#endif diff --git a/components/usb/test_apps/common/dev_msc.c b/components/usb/test_apps/common/dev_msc.c new file mode 100644 index 0000000000..6d5d93d224 --- /dev/null +++ b/components/usb/test_apps/common/dev_msc.c @@ -0,0 +1,354 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "usb/usb_types_ch9.h" +#include "dev_msc.h" + +/* +Some tests where the ESP (acting as host) will require that a particular test +device acting as a MSC SCSI flash drive be connected. That test device's +information and descriptors are defined in this file. + +If you are connecting a different MSC SCSI flash drive, please update +the descriptor and getter functions accordingly. + +------------------------------ Device Descriptor ------------------------------- +bLength : 0x12 (18 bytes) +bDescriptorType : 0x01 (Device Descriptor) +bcdUSB : 0x0210 (2.10) +bDeviceClass : 0x00 +bDeviceSubClass : 0x00 +bDeviceProtocol : 0x00 +bMaxPacketSize0 : 0x40 (64 bytes) +idVendor : 0x0781 (SanDisk Corp) +idProduct : 0x5595 +bcdDevice : 0x0100 (1.00) +iManufacturer : 1 +iProduct : 2 +iSerial : 3 +bNumConfigurations : 1 + +--------------------------- 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) + +------------------------------ 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 for FS, 512 bytes for HS) +bInterval : 0x00 (never NAKs) + +------------------------------ 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 for FS, 512 bytes for HS) +bInterval : 0x00 (never NAKs) + +---------------------------- String Descriptor Manu ---------------------------- +bLength : 0x0A (10 bytes) +bDescriptorType : 0x03 (String Descriptor) +wData : " USB" + +---------------------------- String Descriptor Prod ---------------------------- +bLength : 0x22 (34 bytes) +bDescriptorType : 0x03 (String Descriptor) +wData : " SanDisk 3.2Gen1" + +----------------------------- String Descriptor Ser ---------------------------- +bLength : 0xF2 (242 bytes) +bDescriptorType : 0x03 (String Descriptor) +wData : "0101cdd1e856b427bbb796f870561a4b2b817af9da9872c8d75217cccdd5d5eccb3a0000000000000000000096abe1a3ff83610095558107aea948b4" +*/ + +// --------------------------- Device Information ------------------------------ + +static const dev_msc_info_t dev_info = { + .bInterfaceNumber = 0x00, + .bAlternateSetting = 0x00, + .in_ep_addr = 0x81, + .out_up_addr = 0x02, + .scsi_sector_size = 512, +}; + +// ------------------------------- Descriptors --------------------------------- + +static const usb_device_desc_t dev_desc = { + .bLength = USB_DEVICE_DESC_SIZE, + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_DEVICE, + .bcdUSB = 0x0210, // 2.10 + .bDeviceClass = USB_CLASS_PER_INTERFACE, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = 64, + .idVendor = 0x0781, // SanDisk Corp + .idProduct = 0x5595, + .bcdDevice = 0x0100, // 1.00 + .iManufacturer = 1, + .iProduct = 2, + .iSerialNumber = 3, + .bNumConfigurations = 1, +}; + +static const usb_config_desc_t config_desc = { + .bLength = USB_CONFIG_DESC_SIZE, + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_CONFIGURATION, + .wTotalLength = 0x0020, // 32 bytes + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = 0x80, + .bMaxPower = 0x70, // 224 mA +}; + +static const usb_intf_desc_t intf_desc = { + .bLength = USB_INTF_DESC_SIZE, + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_MASS_STORAGE, + .bInterfaceSubClass = 0x06, //SCSI + .bInterfaceProtocol = 0x50, //Bulk only + .iInterface = 0, +}; + +static const usb_ep_desc_t in_ep_desc_fs = { + .bLength = USB_EP_DESC_SIZE, + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = 0x81, // EP 1 IN + .bmAttributes = USB_BM_ATTRIBUTES_XFER_BULK, + .wMaxPacketSize = 64, + .bInterval = 0, +}; + +static const usb_ep_desc_t in_ep_desc_hs = { + .bLength = USB_EP_DESC_SIZE, + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = 0x81, // EP 1 IN + .bmAttributes = USB_BM_ATTRIBUTES_XFER_BULK, + .wMaxPacketSize = 512, + .bInterval = 0, +}; + +static const usb_ep_desc_t out_ep_desc_fs = { + .bLength = USB_EP_DESC_SIZE, + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = 0x02, // EP 2 OUT + .bmAttributes = USB_BM_ATTRIBUTES_XFER_BULK, + .wMaxPacketSize = 64, + .bInterval = 0, +}; + +static const usb_ep_desc_t out_ep_desc_hs = { + .bLength = USB_EP_DESC_SIZE, + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT, + .bEndpointAddress = 0x02, // EP 2 OUT + .bmAttributes = USB_BM_ATTRIBUTES_XFER_BULK, + .wMaxPacketSize = 512, + .bInterval = 0, +}; + +/* +String descriptors are dynamically initialized due to issues with static +initialization of variable length array members. See IDF-9886. +*/ + +static const usb_str_desc_t str_desc_manu_base = { + .bLength = sizeof(usb_str_desc_t) + (4 * sizeof(uint16_t)), + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_STRING, +}; +static const uint16_t str_desc_manu_data[] = { + 0x0020, // ' ' + 0x0055, // 'U' + 0x0053, // 'S' + 0x0042, // 'B' +}; +static uint8_t *str_desc_manu[sizeof(str_desc_manu_base) + sizeof(str_desc_manu_data)]; + +static const usb_str_desc_t str_desc_prod_base = { + .bLength = sizeof(usb_str_desc_t) + (16 * sizeof(uint16_t)), + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_STRING, +}; +static const uint16_t str_desc_prod_data[] = { + 0x0020, // ' ' + 0x0053, // 'S' + 0x0061, // 'a' + 0x006e, // 'n' + 0x0044, // 'D' + 0x0069, // 'i' + 0x0073, // 's' + 0x006b, // 'k' + 0x0020, // ' ' + 0x0033, // '3' + 0x002e, // '.' + 0x0032, // '2' + 0x0047, // 'G' + 0x0065, // 'e' + 0x006e, // 'n' + 0x0031, // '1' +}; +static uint8_t *str_desc_prod[sizeof(str_desc_prod_base) + sizeof(str_desc_prod_data)]; + +static const usb_str_desc_t str_desc_ser_base = { + .bLength = sizeof(usb_str_desc_t) + (120 * sizeof(uint16_t)), + .bDescriptorType = USB_B_DESCRIPTOR_TYPE_STRING, +}; +static const uint16_t str_desc_ser_data[] = { + /* + The following string encoded in UTF-16LE + + "0101cdd1e856b427bbb796f870561a4b2b817af9da9872c8d75217cccdd5d5eccb3a0000000 + 000000000000096abe1a3ff83610095558107aea948b4" + */ + 0x0030, 0x0031, 0x0030, 0x0031, 0x0063, 0x0064, 0x0064, 0x0031, 0x0065, + 0x0038, 0x0035, 0x0036, 0x0062, 0x0034, 0x0032, 0x0037, 0x0062, 0x0062, + 0x0062, 0x0037, 0x0039, 0x0036, 0x0066, 0x0038, 0x0037, 0x0030, 0x0035, + 0x0036, 0x0031, 0x0061, 0x0034, 0x0062, 0x0032, 0x0062, 0x0038, 0x0031, + 0x0037, 0x0061, 0x0066, 0x0039, 0x0064, 0x0061, 0x0039, 0x0038, 0x0037, + 0x0032, 0x0063, 0x0038, 0x0064, 0x0037, 0x0035, 0x0032, 0x0031, 0x0037, + 0x0063, 0x0063, 0x0063, 0x0064, 0x0064, 0x0035, 0x0064, 0x0035, 0x0065, + 0x0063, 0x0063, 0x0062, 0x0033, 0x0061, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, + 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0039, 0x0036, + 0x0061, 0x0062, 0x0065, 0x0031, 0x0061, 0x0033, 0x0066, 0x0066, 0x0038, + 0x0033, 0x0036, 0x0031, 0x0030, 0x0030, 0x0039, 0x0035, 0x0035, 0x0035, + 0x0038, 0x0031, 0x0030, 0x0037, 0x0061, 0x0065, 0x0061, 0x0039, 0x0034, + 0x0038, 0x0062, 0x0034, +}; +static uint8_t *str_desc_ser[sizeof(str_desc_ser_base) + sizeof(str_desc_ser_data)]; + +// -------------------------------- Functions ---------------------------------- + +void dev_msc_init(void) +{ + // Dynamically initialize string descriptors due to compiler limitations (see IDF-9886) + uint8_t *ptr; + + // Initialize manufacturer string descriptor + ptr = (uint8_t *)str_desc_manu; + memcpy(ptr, &str_desc_manu_base, sizeof(str_desc_manu_base)); + ptr += sizeof(str_desc_manu_base); + memcpy(ptr, &str_desc_manu_data, sizeof(str_desc_manu_data)); + + // Initialize product string descriptor + ptr = (uint8_t *)str_desc_prod; + memcpy(ptr, &str_desc_prod_base, sizeof(str_desc_prod_base)); + ptr += sizeof(str_desc_prod_base); + memcpy(ptr, &str_desc_prod_data, sizeof(str_desc_prod_data)); + + // Initialize serial string descriptor + ptr = (uint8_t *)str_desc_ser; + memcpy(ptr, &str_desc_ser_base, sizeof(str_desc_ser_base)); + ptr += sizeof(str_desc_ser_base); + memcpy(ptr, &str_desc_ser_data, sizeof(str_desc_ser_data)); +} + +const dev_msc_info_t *dev_msc_get_info(void) +{ + return &dev_info; +} + +const usb_device_desc_t *dev_msc_get_dev_desc(usb_speed_t speed) +{ + return &dev_desc; +} + +const usb_config_desc_t *dev_msc_get_config_desc(usb_speed_t speed) +{ + return &config_desc; +} + +const usb_intf_desc_t *dev_msc_get_intf_desc(usb_speed_t speed) +{ + return &intf_desc; +} + +const usb_ep_desc_t *dev_msc_get_in_ep_desc(usb_speed_t speed) +{ + const usb_ep_desc_t *ret; + + // EP descriptor differs by speed due to MPS + switch (speed) { + case USB_SPEED_FULL: + ret = &in_ep_desc_fs; + break; + case USB_SPEED_HIGH: + ret = &in_ep_desc_hs; + break; + default: + ret = NULL; + abort(); // Should never occur + break; + } + + return ret; +} + +const usb_ep_desc_t *dev_msc_get_out_ep_desc(usb_speed_t speed) +{ + const usb_ep_desc_t *ret; + + // EP descriptor differs by speed due to MPS + switch (speed) { + case USB_SPEED_FULL: + ret = &out_ep_desc_fs; + break; + case USB_SPEED_HIGH: + ret = &out_ep_desc_hs; + break; + default: + ret = NULL; + abort(); // Should never occur + break; + } + + return ret; +} + +const usb_str_desc_t *dev_msc_get_str_desc_manu(void) +{ + return (const usb_str_desc_t *)str_desc_manu; +} + +const usb_str_desc_t *dev_msc_get_str_desc_prod(void) +{ + return (const usb_str_desc_t *)str_desc_prod; +} + +const usb_str_desc_t *dev_msc_get_str_desc_ser(void) +{ + return (const usb_str_desc_t *)str_desc_ser; +} diff --git a/components/usb/test_apps/common/dev_msc.h b/components/usb/test_apps/common/dev_msc.h new file mode 100644 index 0000000000..ac21ca952e --- /dev/null +++ b/components/usb/test_apps/common/dev_msc.h @@ -0,0 +1,118 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "usb/usb_types_ch9.h" +#include "usb/usb_types_stack.h" + +/* +Some tests where the ESP (acting as host) will require that a particular test +device acting as a MSC SCSI flash drive be connected. This header contains +functions to get information and descriptors about that test device. + +If you are connecting a different MSC SCSI flash drive, please update +the descriptors in dev_msc.c accordingly. +*/ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @brief MSC SCSI test device information + * + * Structure containing basic information about the the MSC SCSI interface on + * the test device. + */ +typedef struct { + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t in_ep_addr; + uint8_t out_up_addr; + unsigned int scsi_sector_size; +} dev_msc_info_t; + +/** + * @brief Initialize the test device + * + * @note Call this before running tests. This is necessary due to IDF-9886 + */ +void dev_msc_init(void); + +/** + * @brief Get information about the test device's MSC SCSI interface + * + * @return Information object + */ +const dev_msc_info_t *dev_msc_get_info(void); + +/** + * @brief Get the test device's descriptor + * + * @param[in] speed Test device's current speed + * @return Device descriptor + */ +const usb_device_desc_t *dev_msc_get_dev_desc(usb_speed_t speed); + +/** + * @brief Get the test device's configuration descriptor + * + * @param[in] speed Test device's current speed + * @return Configuration descriptor + */ +const usb_config_desc_t *dev_msc_get_config_desc(usb_speed_t speed); + +/** + * @brief Get the test device's MSC interface descriptor + * + * @param[in] speed Test device's current speed + * @return MSC interface descriptor + */ +const usb_intf_desc_t *dev_msc_get_intf_desc(usb_speed_t speed); + +/** + * @brief Get the test device's MSC IN endpoint descriptor + * + * @param[in] speed Test device's current speed + * @return MSC IN endpoint descriptor + */ +const usb_ep_desc_t *dev_msc_get_in_ep_desc(usb_speed_t speed); + +/** + * @brief Get the test device's MSC OUT endpoint descriptor + * + * @param[in] speed Test device's current speed + * @return MSC OUT endpoint descriptor + */ +const usb_ep_desc_t *dev_msc_get_out_ep_desc(usb_speed_t speed); + +/** + * @brief Get the test device's manufacturer string descriptor + * + * @return Manufacturer string descriptor + */ +const usb_str_desc_t *dev_msc_get_str_desc_manu(void); + +/** + * @brief Get the test device's product string descriptor + * + * @return Product string descriptor + */ +const usb_str_desc_t *dev_msc_get_str_desc_prod(void); + +/** + * @brief Get the test device's serial number string descriptor + * + * @return Serial number string descriptor + */ +const usb_str_desc_t *dev_msc_get_str_desc_ser(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/usb/test_apps/common/mock_msc.c b/components/usb/test_apps/common/mock_msc.c new file mode 100644 index 0000000000..30538f0f7f --- /dev/null +++ b/components/usb/test_apps/common/mock_msc.c @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "usb/usb_types_ch9.h" +#include "mock_msc.h" + +// ---------------------------------------------------- MSC SCSI ------------------------------------------------------- + +const char *MSC_CLIENT_TAG = "MSC Client"; + +void mock_msc_scsi_init_cbw(mock_msc_bulk_cbw_t *cbw, + bool is_read, + unsigned int offset, + unsigned int num_sectors, + unsigned int sector_size, + uint32_t tag) +{ + cbw->dCBWSignature = 0x43425355; // Fixed value + cbw->dCBWTag = tag; // Random value that is echoed back + cbw->dCBWDataTransferLength = num_sectors * sector_size; + cbw->bmCBWFlags = (is_read) ? (1 << 7) : 0; // If this is a read, set the direction flag + cbw->bCBWLUN = 0; + 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; +} diff --git a/components/usb/test_apps/common/mock_msc.h b/components/usb/test_apps/common/mock_msc.h new file mode 100644 index 0000000000..17e347d49a --- /dev/null +++ b/components/usb/test_apps/common/mock_msc.h @@ -0,0 +1,100 @@ +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "esp_assert.h" +#include "usb/usb_types_ch9.h" + +/* +This header contains bare-bone mock implementations of the MSC SCSI class +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +extern const char *MSC_CLIENT_TAG; + +#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[in] cbw CBW structure + * @param[in] is_read Is a read command + * @param[in] offset Block offset + * @param[in] num_sectors Number of sectors to read + * @param[in] sector_size Size of each sector in bytes + * @param[in] tag Tag (this is simply echoed back + */ +void mock_msc_scsi_init_cbw(mock_msc_bulk_cbw_t *cbw, + bool is_read, + unsigned int offset, + unsigned int num_sectors, + unsigned int sector_size, + uint32_t tag); + +/** + * @brief Check that returned Command Status Wrapper (CSW) is valid + * + * @param[in] csw CSW structure + * @param[in] tag_expect Expected tag + * @return True if CSW is valid, false otherwise + */ +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); + +#ifdef __cplusplus +} +#endif diff --git a/components/usb/test_apps/common/test_usb_common.c b/components/usb/test_apps/common/test_usb_common.c index 2fa98b3dab..0934501762 100644 --- a/components/usb/test_apps/common/test_usb_common.c +++ b/components/usb/test_apps/common/test_usb_common.c @@ -17,12 +17,12 @@ static usb_phy_handle_t phy_hdl = NULL; void test_usb_init_phy(void) { - //Initialize the internal USB PHY to connect to the USB OTG peripheral + // Initialize the internal USB PHY to connect to the USB OTG peripheral usb_phy_config_t phy_config = { .controller = USB_PHY_CTRL_OTG, .target = USB_PHY_TARGET_INT, .otg_mode = USB_OTG_MODE_HOST, - .otg_speed = USB_PHY_SPEED_UNDEFINED, //In Host mode, the speed is determined by the connected device + .otg_speed = USB_PHY_SPEED_UNDEFINED, // In Host mode, the speed is determined by the connected device .ext_io_conf = NULL, .otg_io_conf = NULL, }; @@ -31,7 +31,7 @@ void test_usb_init_phy(void) void test_usb_deinit_phy(void) { - //Deinitialize the internal USB PHY + // Deinitialize the internal USB PHY TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_del_phy(phy_hdl), "Failed to delete PHY"); phy_hdl = NULL; } @@ -39,7 +39,7 @@ void test_usb_deinit_phy(void) void test_usb_set_phy_state(bool connected, TickType_t delay_ticks) { if (delay_ticks > 0) { - //Delay of 0 ticks causes a yield. So skip if delay_ticks is 0. + // Delay of 0 ticks causes a yield. So skip if delay_ticks is 0. vTaskDelay(delay_ticks); } ESP_ERROR_CHECK(usb_phy_action(phy_hdl, (connected) ? USB_PHY_ACTION_HOST_ALLOW_CONN : USB_PHY_ACTION_HOST_FORCE_DISCONN)); diff --git a/components/usb/test_apps/common/test_usb_mock_hid.c b/components/usb/test_apps/common/test_usb_mock_hid.c deleted file mode 100644 index ea7dc32af9..0000000000 --- a/components/usb/test_apps/common/test_usb_mock_hid.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#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); -} diff --git a/components/usb/test_apps/common/test_usb_mock_hid.h b/components/usb/test_apps/common/test_usb_mock_hid.h deleted file mode 100644 index a9a145fbdf..0000000000 --- a/components/usb/test_apps/common/test_usb_mock_hid.h +++ /dev/null @@ -1,112 +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 -#include -#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 diff --git a/components/usb/test_apps/common/test_usb_mock_msc.c b/components/usb/test_apps/common/test_usb_mock_msc.c deleted file mode 100644 index 6f75260236..0000000000 --- a/components/usb/test_apps/common/test_usb_mock_msc.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#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]; -usb_ep_desc_t mock_msc_scsi_bulk_out_ep_desc; -usb_ep_desc_t mock_msc_scsi_bulk_in_ep_desc; - -const usb_ep_desc_t mock_msc_scsi_bulk_out_ep_desc_fs = { - .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_FS, //MPS of 64 bytes - .bInterval = 0, -}; - -const usb_ep_desc_t mock_msc_scsi_bulk_out_ep_desc_hs = { - .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_HS, //MPS of 512 bytes - .bInterval = 0, -}; - -const usb_ep_desc_t mock_msc_scsi_bulk_in_ep_desc_fs = { - .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_FS, //MPS of 64 bytes - .bInterval = 0, -}; - -const usb_ep_desc_t mock_msc_scsi_bulk_in_ep_desc_hs = { - .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_HS, //MPS of 512 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; - // Set endpoint descriptors with zeroes, FS or HS device has not been connected - memset(dest_ptr, 0, sizeof(usb_ep_desc_t)); - dest_ptr += USB_EP_DESC_SIZE; - memset(dest_ptr, 0, sizeof(usb_ep_desc_t)); - - // 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]; - } -} diff --git a/components/usb/test_apps/common/test_usb_mock_msc.h b/components/usb/test_apps/common/test_usb_mock_msc.h deleted file mode 100644 index 466decf2be..0000000000 --- a/components/usb/test_apps/common/test_usb_mock_msc.h +++ /dev/null @@ -1,202 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2024 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 -#include -#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 for FS, 512 bytes for HS) -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 for FS, 512 bytest for HS) -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 usb_ep_desc_t mock_msc_scsi_bulk_out_ep_desc; -extern usb_ep_desc_t mock_msc_scsi_bulk_in_ep_desc; -extern const usb_ep_desc_t mock_msc_scsi_bulk_out_ep_desc_fs; -extern const usb_ep_desc_t mock_msc_scsi_bulk_in_ep_desc_fs; -extern const usb_ep_desc_t mock_msc_scsi_bulk_out_ep_desc_hs; -extern const usb_ep_desc_t mock_msc_scsi_bulk_in_ep_desc_hs; - -#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_FS 64 // FS wMaxPacketSize -#define MOCK_MSC_SCSI_BULK_EP_MPS_HS 512 // HS wMaxPacketSize -#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 diff --git a/components/usb/test_apps/hcd/main/test_app_main.c b/components/usb/test_apps/hcd/main/test_app_main.c index 224b068ada..9137bfe469 100644 --- a/components/usb/test_apps/hcd/main/test_app_main.c +++ b/components/usb/test_apps/hcd/main/test_app_main.c @@ -7,20 +7,23 @@ #include "unity.h" #include "unity_test_runner.h" #include "unity_test_utils_memory.h" - #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "dev_msc.h" +#include "dev_hid.h" #include "test_hcd_common.h" void setUp(void) { unity_utils_record_free_mem(); + dev_msc_init(); + dev_hid_init(); port_hdl = test_hcd_setup(); } void tearDown(void) { - //Short delay to allow task to be cleaned up + // Short delay to allow task to be cleaned up vTaskDelay(10); test_hcd_teardown(port_hdl); port_hdl = NULL; diff --git a/components/usb/test_apps/hcd/main/test_hcd_bulk.c b/components/usb/test_apps/hcd/main/test_hcd_bulk.c index 5ad852f590..8d72020012 100644 --- a/components/usb/test_apps/hcd/main/test_hcd_bulk.c +++ b/components/usb/test_apps/hcd/main/test_hcd_bulk.c @@ -9,24 +9,25 @@ #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "unity.h" -#include "test_usb_mock_msc.h" +#include "mock_msc.h" +#include "dev_msc.h" #include "test_hcd_common.h" // --------------------------------------------------- Test Cases ------------------------------------------------------ -static void mock_msc_reset_req(hcd_pipe_handle_t default_pipe) +static void mock_msc_reset_req(hcd_pipe_handle_t default_pipe, uint8_t bInterfaceNumber) { - //Create URB + // Create URB urb_t *urb = test_hcd_alloc_urb(0, sizeof(usb_setup_packet_t)); usb_setup_packet_t *setup_pkt = (usb_setup_packet_t *)urb->transfer.data_buffer; - MOCK_MSC_SCSI_REQ_INIT_RESET(setup_pkt, MOCK_MSC_SCSI_INTF_NUMBER); + MOCK_MSC_SCSI_REQ_INIT_RESET(setup_pkt, bInterfaceNumber); urb->transfer.num_bytes = sizeof(usb_setup_packet_t); - //Enqueue, wait, dequeue, and check URB + // 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_PTR(urb, hcd_urb_dequeue(default_pipe)); TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status, "Transfer NOT completed"); - //Free URB + // Free URB test_hcd_free_urb(urb); } @@ -54,47 +55,54 @@ Procedure: TEST_CASE("Test HCD bulk pipe URBs", "[bulk][full_speed]") { - 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) + 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) - //Enumerate and reset MSC SCSI device - 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) + // Enumerate and reset MSC SCSI device + 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) uint8_t dev_addr = test_hcd_enum_device(default_pipe); - mock_msc_reset_req(default_pipe); - test_hcd_set_mock_msc_ep_descriptor(port_speed); + const dev_msc_info_t *dev_info = dev_msc_get_info(); + mock_msc_reset_req(default_pipe, dev_info->bInterfaceNumber); - //Create BULK IN and BULK OUT pipes for SCSI - hcd_pipe_handle_t bulk_out_pipe = test_hcd_pipe_alloc(port_hdl, &mock_msc_scsi_bulk_out_ep_desc, dev_addr, port_speed); - hcd_pipe_handle_t bulk_in_pipe = test_hcd_pipe_alloc(port_hdl, &mock_msc_scsi_bulk_in_ep_desc, dev_addr, port_speed); - //Create URBs for CBW, Data, and CSW transport. IN Buffer sizes are rounded up to nearest MPS + // Create BULK IN and BULK OUT pipes for SCSI + const usb_ep_desc_t *out_ep_desc = dev_msc_get_out_ep_desc(port_speed); + const usb_ep_desc_t *in_ep_desc = dev_msc_get_in_ep_desc(port_speed); + const uint16_t mps = USB_EP_DESC_GET_MPS(in_ep_desc) ; + hcd_pipe_handle_t bulk_out_pipe = test_hcd_pipe_alloc(port_hdl, out_ep_desc, dev_addr, port_speed); + hcd_pipe_handle_t bulk_in_pipe = test_hcd_pipe_alloc(port_hdl, in_ep_desc, dev_addr, port_speed); + // Create URBs for CBW, Data, and CSW transport. IN Buffer sizes are rounded up to nearest MPS urb_t *urb_cbw = test_hcd_alloc_urb(0, sizeof(mock_msc_bulk_cbw_t)); - urb_t *urb_data = test_hcd_alloc_urb(0, TEST_NUM_SECTORS_PER_XFER * MOCK_MSC_SCSI_SECTOR_SIZE); - const uint16_t mps = USB_EP_DESC_GET_MPS(&mock_msc_scsi_bulk_in_ep_desc) ; + urb_t *urb_data = test_hcd_alloc_urb(0, TEST_NUM_SECTORS_PER_XFER * dev_info->scsi_sector_size); urb_t *urb_csw = test_hcd_alloc_urb(0, sizeof(mock_msc_bulk_csw_t) + (mps - (sizeof(mock_msc_bulk_csw_t) % mps))); urb_cbw->transfer.num_bytes = sizeof(mock_msc_bulk_cbw_t); - urb_data->transfer.num_bytes = TEST_NUM_SECTORS_PER_XFER * MOCK_MSC_SCSI_SECTOR_SIZE; + urb_data->transfer.num_bytes = TEST_NUM_SECTORS_PER_XFER * dev_info->scsi_sector_size; urb_csw->transfer.num_bytes = sizeof(mock_msc_bulk_csw_t) + (mps - (sizeof(mock_msc_bulk_csw_t) % mps)); for (int block_num = 0; block_num < TEST_NUM_SECTORS_TOTAL; block_num += TEST_NUM_SECTORS_PER_XFER) { - //Initialize CBW URB, then send it on the BULK OUT pipe - mock_msc_scsi_init_cbw((mock_msc_bulk_cbw_t *)urb_cbw->transfer.data_buffer, true, block_num, TEST_NUM_SECTORS_PER_XFER, 0xAAAAAAAA); + // Initialize CBW URB, then send it on the BULK OUT pipe + mock_msc_scsi_init_cbw((mock_msc_bulk_cbw_t *)urb_cbw->transfer.data_buffer, + true, + block_num, + TEST_NUM_SECTORS_PER_XFER, + dev_info->scsi_sector_size, + 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_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 + // 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_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 + // 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_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_TRUE(mock_msc_scsi_check_csw((mock_msc_bulk_csw_t *)urb_csw->transfer.data_buffer, 0xAAAAAAAA)); - //Print the read data + // 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++) { printf("0x%02x,", ((char *)urb_data->transfer.data_buffer)[i]); @@ -108,6 +116,6 @@ TEST_CASE("Test HCD bulk pipe URBs", "[bulk][full_speed]") test_hcd_pipe_free(bulk_out_pipe); test_hcd_pipe_free(bulk_in_pipe); test_hcd_pipe_free(default_pipe); - //Cleanup + // Cleanup test_hcd_wait_for_disconn(port_hdl, false); } diff --git a/components/usb/test_apps/hcd/main/test_hcd_common.c b/components/usb/test_apps/hcd/main/test_hcd_common.c index b2147b5ad1..293f6ca21f 100644 --- a/components/usb/test_apps/hcd/main/test_hcd_common.c +++ b/components/usb/test_apps/hcd/main/test_hcd_common.c @@ -19,14 +19,14 @@ #include "usb/usb_types_ch9.h" #include "test_hcd_common.h" #include "test_usb_common.h" -#include "test_usb_mock_msc.h" +#include "mock_msc.h" #include "unity.h" #include "esp_dma_utils.h" #define PORT_NUM 1 #define EVENT_QUEUE_LEN 5 -#define ENUM_ADDR 1 //Device address to use for tests that enumerate the device -#define ENUM_CONFIG 1 //Device configuration number to use for tests that enumerate the device +#define ENUM_ADDR 1 // Device address to use for tests that enumerate the device +#define ENUM_CONFIG 1 // Device configuration number to use for tests that enumerate the device typedef struct { hcd_port_handle_t port_hdl; @@ -54,10 +54,10 @@ hcd_port_handle_t port_hdl = NULL; */ static bool port_callback(hcd_port_handle_t port_hdl, hcd_port_event_t port_event, void *user_arg, bool in_isr) { - //We store the port's queue handle in the port's context variable + // 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_TRUE(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, @@ -98,14 +98,14 @@ static bool pipe_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t pipe_even void test_hcd_expect_port_event(hcd_port_handle_t port_hdl, hcd_port_event_t expected_event) { - //Get the port event queue from the port's context variable + // 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_NULL(port_evt_queue); - //Wait for port callback to send an event message + // Wait for port callback to send an event message port_event_msg_t msg; 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 + // Check the contents of that event message TEST_ASSERT_EQUAL(port_hdl, msg.port_hdl); TEST_ASSERT_EQUAL_MESSAGE(expected_event, msg.port_event, "Unexpected event"); printf("\t-> Port event\n"); @@ -113,21 +113,21 @@ void test_hcd_expect_port_event(hcd_port_handle_t port_hdl, hcd_port_event_t exp void test_hcd_expect_pipe_event(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t expected_event) { - //Get the pipe's event queue from the pipe's context variable + // 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_NULL(pipe_evt_queue); - //Wait for pipe callback to send an event message + // Wait for pipe callback to send an event message pipe_event_msg_t msg; 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 + // Check the contents of that event message TEST_ASSERT_EQUAL(pipe_hdl, msg.pipe_hdl); 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 + // 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_NULL(port_evt_queue); return EVENT_QUEUE_LEN - uxQueueSpacesAvailable(port_evt_queue); @@ -135,7 +135,7 @@ int test_hcd_get_num_port_events(hcd_port_handle_t port_hdl) 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 + // 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_NULL(pipe_evt_queue); return EVENT_QUEUE_LEN - uxQueueSpacesAvailable(pipe_evt_queue); @@ -145,16 +145,16 @@ int test_hcd_get_num_pipe_events(hcd_pipe_handle_t pipe_hdl) 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 + 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_NULL(port_evt_queue); - //Install HCD + // Install HCD hcd_config_t hcd_config = { .intr_flags = ESP_INTR_FLAG_LEVEL1, }; TEST_ASSERT_EQUAL(ESP_OK, hcd_install(&hcd_config)); - //Initialize a port + // Initialize a port hcd_port_config_t port_config = { .fifo_bias = HCD_PORT_FIFO_BIAS_BALANCED, .callback = port_callback, @@ -165,7 +165,7 @@ hcd_port_handle_t test_hcd_setup(void) TEST_ASSERT_EQUAL(ESP_OK, hcd_port_init(PORT_NUM, &port_config, &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 + test_usb_set_phy_state(false, 0); // Force disconnected state on PHY return port_hdl; } @@ -174,33 +174,33 @@ 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 + // 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_NULL(port_evt_queue); - //Deinitialize a port + // Deinitialize a port TEST_ASSERT_EQUAL(ESP_OK, hcd_port_deinit(port_hdl)); - //Uninstall the HCD + // Uninstall the HCD TEST_ASSERT_EQUAL(ESP_OK, hcd_uninstall()); vQueueDelete(port_evt_queue); - test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing + test_usb_deinit_phy(); // Deinitialize the internal USB PHY after testing } usb_speed_t test_hcd_wait_for_conn(hcd_port_handle_t port_hdl) { - //Power ON the port + // Power ON the port TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_POWER_ON)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISCONNECTED, hcd_port_get_state(port_hdl)); - //Wait for connection event + // Wait for connection event printf("Waiting for connection\n"); - test_usb_set_phy_state(true, pdMS_TO_TICKS(100)); //Allow for connected state on PHY + test_usb_set_phy_state(true, pdMS_TO_TICKS(100)); // Allow for connected state on PHY test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_CONNECTION); TEST_ASSERT_EQUAL(HCD_PORT_EVENT_CONNECTION, hcd_port_handle_event(port_hdl)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISABLED, hcd_port_get_state(port_hdl)); - //Reset newly connected device + // Reset newly connected device printf("Resetting\n"); TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_RESET)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_ENABLED, hcd_port_get_state(port_hdl)); - //Get speed of connected + // Get speed of connected usb_speed_t port_speed; TEST_ASSERT_EQUAL(ESP_OK, hcd_port_get_speed(port_hdl, &port_speed)); TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(USB_SPEED_HIGH, port_speed, "Invalid port speed"); @@ -213,18 +213,18 @@ usb_speed_t test_hcd_wait_for_conn(hcd_port_handle_t port_hdl) void test_hcd_wait_for_disconn(hcd_port_handle_t port_hdl, bool already_disabled) { if (!already_disabled) { - //Disable the device + // Disable the device printf("Disabling\n"); 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)); } - //Wait for a safe disconnect + // Wait for a safe disconnect printf("Waiting for disconnection\n"); - test_usb_set_phy_state(false, pdMS_TO_TICKS(100)); //Force disconnected state on PHY + test_usb_set_phy_state(false, pdMS_TO_TICKS(100)); // Force disconnected state on PHY test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION); TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_RECOVERY, hcd_port_get_state(port_hdl)); - //Power down the port + // Power down the port TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_POWER_OFF)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_NOT_POWERED, hcd_port_get_state(port_hdl)); } @@ -233,7 +233,7 @@ void test_hcd_wait_for_disconn(hcd_port_handle_t port_hdl, bool already_disabled hcd_pipe_handle_t test_hcd_pipe_alloc(hcd_port_handle_t port_hdl, const usb_ep_desc_t *ep_desc, uint8_t dev_addr, usb_speed_t dev_speed) { - //Create a queue for pipe callback to queue up pipe events + // 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_NULL(pipe_evt_queue); hcd_pipe_config_t pipe_config = { @@ -252,17 +252,17 @@ hcd_pipe_handle_t test_hcd_pipe_alloc(hcd_port_handle_t port_hdl, const usb_ep_d void test_hcd_pipe_free(hcd_pipe_handle_t pipe_hdl) { - //Get the pipe's event queue from its context variable + // 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_NULL(pipe_evt_queue); - //Free the pipe and queue + // Free the pipe and queue TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_free(pipe_hdl)); vQueueDelete(pipe_evt_queue); } urb_t *test_hcd_alloc_urb(int num_isoc_packets, size_t data_buffer_size) { - //Allocate a URB and data buffer + // Allocate a URB and data buffer urb_t *urb = heap_caps_calloc(1, sizeof(urb_t) + (sizeof(usb_isoc_packet_desc_t) * num_isoc_packets), MALLOC_CAP_DEFAULT); void *data_buffer; size_t real_size; @@ -273,7 +273,7 @@ urb_t *test_hcd_alloc_urb(int num_isoc_packets, size_t data_buffer_size) TEST_ASSERT_NOT_NULL_MESSAGE(urb, "Failed to allocate URB"); TEST_ASSERT_NOT_NULL_MESSAGE(data_buffer, "Failed to allocate transfer buffer"); - //Initialize URB and underlying transfer structure. Need to cast to dummy due to const fields + // 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; transfer_dummy->data_buffer_size = real_size; @@ -283,19 +283,19 @@ urb_t *test_hcd_alloc_urb(int num_isoc_packets, size_t data_buffer_size) void test_hcd_free_urb(urb_t *urb) { - //Free data buffer of the transfer + // Free data buffer of the transfer heap_caps_free(urb->transfer.data_buffer); - //Free the URB + // Free the URB heap_caps_free(urb); } uint8_t test_hcd_enum_device(hcd_pipe_handle_t default_pipe) { - //We need to create a URB for the enumeration control transfers + // We need to create a URB for the enumeration control transfers urb_t *urb = test_hcd_alloc_urb(0, sizeof(usb_setup_packet_t) + 256); usb_setup_packet_t *setup_pkt = (usb_setup_packet_t *)urb->transfer.data_buffer; - //Get the device descriptor (note that device might only return 8 bytes) + // Get the device descriptor (note that device might only return 8 bytes) USB_SETUP_PACKET_INIT_GET_DEVICE_DESC(setup_pkt); urb->transfer.num_bytes = sizeof(usb_setup_packet_t) + sizeof(usb_device_desc_t); TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb)); @@ -303,22 +303,22 @@ uint8_t test_hcd_enum_device(hcd_pipe_handle_t default_pipe) TEST_ASSERT_EQUAL(urb, hcd_urb_dequeue(default_pipe)); TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status, "Transfer NOT completed"); - //Update the MPS of the default pipe + // 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)); TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_update_mps(default_pipe, device_desc->bMaxPacketSize0)); - //Send a set address request - USB_SETUP_PACKET_INIT_SET_ADDR(setup_pkt, ENUM_ADDR); //We only support one device for now so use address 1 + // Send a set address request + USB_SETUP_PACKET_INIT_SET_ADDR(setup_pkt, ENUM_ADDR); // We only support one device for now so use address 1 urb->transfer.num_bytes = sizeof(usb_setup_packet_t); 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_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status, "Transfer NOT completed"); - //Update address of default pipe + // Update address of default pipe TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_update_dev_addr(default_pipe, ENUM_ADDR)); - //Send a set configuration request + // Send a set configuration request USB_SETUP_PACKET_INIT_SET_CONFIG(setup_pkt, ENUM_CONFIG); urb->transfer.num_bytes = sizeof(usb_setup_packet_t); TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb)); @@ -326,18 +326,7 @@ uint8_t test_hcd_enum_device(hcd_pipe_handle_t default_pipe) TEST_ASSERT_EQUAL(urb, hcd_urb_dequeue(default_pipe)); TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status, "Transfer NOT completed"); - //Free URB + // Free URB test_hcd_free_urb(urb); return ENUM_ADDR; } - -void test_hcd_set_mock_msc_ep_descriptor(usb_speed_t port_speed) -{ - if (port_speed == USB_SPEED_HIGH) { - mock_msc_scsi_bulk_out_ep_desc = mock_msc_scsi_bulk_out_ep_desc_hs; // HS wMaxPacketSize = 512 - mock_msc_scsi_bulk_in_ep_desc = mock_msc_scsi_bulk_in_ep_desc_hs; - } else { - mock_msc_scsi_bulk_out_ep_desc = mock_msc_scsi_bulk_out_ep_desc_fs; // FS wMaxPacketSize = 64 - mock_msc_scsi_bulk_in_ep_desc = mock_msc_scsi_bulk_in_ep_desc_fs; - } -} diff --git a/components/usb/test_apps/hcd/main/test_hcd_ctrl.c b/components/usb/test_apps/hcd/main/test_hcd_ctrl.c index 789d8b3c66..75190e41c8 100644 --- a/components/usb/test_apps/hcd/main/test_hcd_ctrl.c +++ b/components/usb/test_apps/hcd/main/test_hcd_ctrl.c @@ -13,7 +13,7 @@ #define TEST_DEV_ADDR 0 #define NUM_URBS 3 #define TRANSFER_MAX_BYTES 256 -#define URB_DATA_BUFF_SIZE (sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES) //256 is worst case size for configuration descriptors +#define URB_DATA_BUFF_SIZE (sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES) // 256 is worst case size for configuration descriptors /* Test HCD control pipe URBs (normal completion and early abort) @@ -35,36 +35,36 @@ Procedure: */ TEST_CASE("Test HCD control pipe URBs", "[ctrl][low_speed][full_speed]") { - 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) + 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) - //Allocate some URBs and initialize their data buffers with control transfers - hcd_pipe_handle_t default_pipe = test_hcd_pipe_alloc(port_hdl, NULL, TEST_DEV_ADDR, port_speed); //Create a default pipe (using a NULL EP descriptor) + // Allocate some URBs and initialize their data buffers with control transfers + hcd_pipe_handle_t default_pipe = test_hcd_pipe_alloc(port_hdl, NULL, TEST_DEV_ADDR, port_speed); // Create a default pipe (using a NULL EP descriptor) urb_t *urb_list[NUM_URBS]; for (int i = 0; i < NUM_URBS; i++) { urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE); - //Initialize with a "Get Config Descriptor request" + // Initialize with a "Get Config Descriptor request" urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES; USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); urb_list[i]->transfer.context = URB_CONTEXT_VAL; } - //Enqueue URBs but immediately suspend the port + // Enqueue URBs but immediately suspend the port 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])); } - //Wait for each done event of each URB + // Wait for each done event of each URB for (int i = 0; i < NUM_URBS; i++) { test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); } - //Dequeue URBs, check, and print + // Dequeue URBs, check, and print 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_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 + // 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); TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); usb_config_desc_t *config_desc = (usb_config_desc_t *)(urb->transfer.data_buffer + sizeof(usb_setup_packet_t)); @@ -72,38 +72,38 @@ TEST_CASE("Test HCD control pipe URBs", "[ctrl][low_speed][full_speed]") printf("Config Desc wTotalLength %d\n", config_desc->wTotalLength); } - //Enqueue URBs again but abort them short after + // Enqueue URBs again but abort them short after for (int i = 0; i < NUM_URBS; i++) { TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i])); } for (int i = 0; i < NUM_URBS; i++) { TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_abort(urb_list[i])); } - vTaskDelay(pdMS_TO_TICKS(100)); //Give some time for any inflight transfers to complete + vTaskDelay(pdMS_TO_TICKS(100)); // Give some time for any inflight transfers to complete - //Wait for the URBs to complete and dequeue them, then check results - //Dequeue URBs + // Wait for the URBs to complete and dequeue them, then check results + // Dequeue URBs for (int i = 0; i < NUM_URBS; i++) { urb_t *urb = hcd_urb_dequeue(default_pipe); - //No need to check for URB pointer address as they may be out of order + // No need to check for URB pointer address as they may be out of order 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 + // 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); TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); } else { - //A failed transfer should 0 actual number of bytes transmitted + // A failed transfer should 0 actual number of bytes transmitted TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes); } TEST_ASSERT_EQUAL(urb->transfer.context, URB_CONTEXT_VAL); } - //Free URB list and pipe + // Free URB list and pipe for (int i = 0; i < NUM_URBS; i++) { test_hcd_free_urb(urb_list[i]); } test_hcd_pipe_free(default_pipe); - //Cleanup + // Cleanup test_hcd_wait_for_disconn(port_hdl, false); } @@ -130,27 +130,27 @@ Procedure: */ TEST_CASE("Test HCD control pipe STALL", "[ctrl][full_speed]") { - 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) + 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) - //Allocate some URBs and initialize their data buffers with control transfers - hcd_pipe_handle_t default_pipe = test_hcd_pipe_alloc(port_hdl, NULL, TEST_DEV_ADDR, port_speed); //Create a default pipe (using a NULL EP descriptor) + // Allocate some URBs and initialize their data buffers with control transfers + hcd_pipe_handle_t default_pipe = test_hcd_pipe_alloc(port_hdl, NULL, TEST_DEV_ADDR, port_speed); // Create a default pipe (using a NULL EP descriptor) urb_t *urb_list[NUM_URBS]; for (int i = 0; i < NUM_URBS; i++) { urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE); - //Initialize with a "Get Config Descriptor request" + // Initialize with a "Get Config Descriptor request" urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES; USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); urb_list[i]->transfer.context = URB_CONTEXT_VAL; } - //Corrupt the first URB so that it triggers a STALL + // Corrupt the first URB so that it triggers a STALL ((usb_setup_packet_t *)urb_list[0]->transfer.data_buffer)->bRequest = 0xAA; - //Enqueue URBs. A STALL should occur + // Enqueue URBs. A STALL should occur int num_enqueued = 0; for (int i = 0; i < NUM_URBS; i++) { if (hcd_urb_enqueue(default_pipe, urb_list[i]) != ESP_OK) { - //STALL may occur before we are done enqueing + // STALL may occur before we are done enqueuing break; } num_enqueued++; @@ -160,7 +160,7 @@ TEST_CASE("Test HCD control pipe STALL", "[ctrl][full_speed]") test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_ERROR_STALL); TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe)); - //Call the pipe abort command to retire all URBs then dequeue them all + // Call the pipe abort command to retire all URBs then dequeue them all TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_FLUSH)); test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); for (int i = 0; i < num_enqueued; i++) { @@ -168,36 +168,36 @@ TEST_CASE("Test HCD control pipe STALL", "[ctrl][full_speed]") TEST_ASSERT_EQUAL(urb_list[i], urb); TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_STALL || 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 + // 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); TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); } else { - //A failed transfer should 0 actual number of bytes transmitted + // A failed transfer should 0 actual number of bytes transmitted TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes); } TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context); } - //Call the clear command to un-stall the pipe + // Call the clear command to un-stall the pipe TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_CLEAR)); TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe)); printf("Retrying\n"); - //Correct first URB then requeue + // Correct first URB then requeue USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[0]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); for (int i = 0; i < NUM_URBS; i++) { TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i])); } - //Wait for each URB to be done, deequeue, and check results + // Wait for each URB to be done, deequeue, and check results for (int i = 0; i < NUM_URBS; i++) { test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); - //expect_pipe_event(pipe_evt_queue, default_pipe, HCD_PIPE_EVENT_URB_DONE); + // 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_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 + // 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); TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); usb_config_desc_t *config_desc = (usb_config_desc_t *)(urb->transfer.data_buffer + sizeof(usb_setup_packet_t)); @@ -205,12 +205,12 @@ TEST_CASE("Test HCD control pipe STALL", "[ctrl][full_speed]") printf("Config Desc wTotalLength %d\n", config_desc->wTotalLength); } - //Free URB list and pipe + // Free URB list and pipe for (int i = 0; i < NUM_URBS; i++) { test_hcd_free_urb(urb_list[i]); } test_hcd_pipe_free(default_pipe); - //Cleanup + // Cleanup test_hcd_wait_for_disconn(port_hdl, false); } @@ -234,21 +234,21 @@ Procedure: */ TEST_CASE("Test HCD control pipe runtime halt and clear", "[ctrl][low_speed][full_speed]") { - 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) + 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) - //Allocate some URBs and initialize their data buffers with control transfers - hcd_pipe_handle_t default_pipe = test_hcd_pipe_alloc(port_hdl, NULL, TEST_DEV_ADDR, port_speed); //Create a default pipe (using a NULL EP descriptor) + // Allocate some URBs and initialize their data buffers with control transfers + hcd_pipe_handle_t default_pipe = test_hcd_pipe_alloc(port_hdl, NULL, TEST_DEV_ADDR, port_speed); // Create a default pipe (using a NULL EP descriptor) urb_t *urb_list[NUM_URBS]; for (int i = 0; i < NUM_URBS; i++) { urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE); - //Initialize with a "Get Config Descriptor request" + // Initialize with a "Get Config Descriptor request" urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES; USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); urb_list[i]->transfer.context = URB_CONTEXT_VAL; } - //Enqueue URBs but immediately halt the pipe + // Enqueue URBs but immediately halt the pipe 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])); @@ -258,36 +258,36 @@ TEST_CASE("Test HCD control pipe runtime halt and clear", "[ctrl][low_speed][ful TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe)); printf("Pipe halted\n"); - //Un-halt the pipe + // Un-halt the pipe TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_CLEAR)); TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe)); printf("Pipe cleared\n"); - vTaskDelay(pdMS_TO_TICKS(100)); //Give some time pending for transfers to restart and complete + vTaskDelay(pdMS_TO_TICKS(100)); // Give some time pending for transfers to restart and complete - //Wait for each URB to be done, dequeue, and check results + // 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_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 + // 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); TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); usb_config_desc_t *config_desc = (usb_config_desc_t *)(urb->transfer.data_buffer + sizeof(usb_setup_packet_t)); TEST_ASSERT_EQUAL(USB_B_DESCRIPTOR_TYPE_CONFIGURATION, config_desc->bDescriptorType); printf("Config Desc wTotalLength %d\n", config_desc->wTotalLength); } else { - //A failed transfer should 0 actual number of bytes transmitted + // A failed transfer should 0 actual number of bytes transmitted TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes); } TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context); } - //Free URB list and pipe + // Free URB list and pipe for (int i = 0; i < NUM_URBS; i++) { test_hcd_free_urb(urb_list[i]); } test_hcd_pipe_free(default_pipe); - //Cleanup + // Cleanup test_hcd_wait_for_disconn(port_hdl, false); } diff --git a/components/usb/test_apps/hcd/main/test_hcd_intr.c b/components/usb/test_apps/hcd/main/test_hcd_intr.c index cf300d2693..4416967c1b 100644 --- a/components/usb/test_apps/hcd/main/test_hcd_intr.c +++ b/components/usb/test_apps/hcd/main/test_hcd_intr.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,8 +8,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "unity.h" -#include "test_usb_mock_msc.h" -#include "test_usb_mock_hid.h" +#include "dev_hid.h" #include "test_hcd_common.h" // --------------------------------------------------- Test Cases ------------------------------------------------------ @@ -36,52 +35,54 @@ 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 MOCK_HID_MOUSE_INTR_IN_MPS #define NUM_URB_ITERS (NUM_URBS * 100) TEST_CASE("Test HCD interrupt pipe URBs", "[intr][low_speed]") { - usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection + usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); // Trigger a connection 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) + 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) + 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) uint8_t dev_addr = test_hcd_enum_device(default_pipe); - //Allocate interrupt pipe and URBS - hcd_pipe_handle_t intr_pipe = test_hcd_pipe_alloc(port_hdl, &mock_hid_mouse_in_ep_desc, dev_addr, port_speed); + // Allocate interrupt pipe and URBS + const usb_ep_desc_t *in_ep_desc = dev_hid_get_in_ep_desc(port_speed); + const int data_buff_size = USB_EP_DESC_GET_MPS(in_ep_desc); + hcd_pipe_handle_t intr_pipe = test_hcd_pipe_alloc(port_hdl, in_ep_desc, dev_addr, port_speed); urb_t *urb_list[NUM_URBS]; for (int i = 0; i < NUM_URBS; i++) { - urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE); - urb_list[i]->transfer.num_bytes = URB_DATA_BUFF_SIZE; + urb_list[i] = test_hcd_alloc_urb(0, data_buff_size); + urb_list[i]->transfer.num_bytes = data_buff_size; urb_list[i]->transfer.context = URB_CONTEXT_VAL; } - //Enqueue URBs + // Enqueue URBs for (int i = 0; i < NUM_URBS; i++) { TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(intr_pipe, urb_list[i])); } int iter_count = NUM_URB_ITERS; for (iter_count = NUM_URB_ITERS; iter_count > 0; iter_count--) { - //Wait for an URB to be done + // Wait for an URB to be done test_hcd_expect_pipe_event(intr_pipe, HCD_PIPE_EVENT_URB_DONE); - //Dequeue the URB and check results + // Dequeue the URB and check results urb_t *urb = hcd_urb_dequeue(intr_pipe); 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 + // Byte 1 and 2 contains x and y movement respectively + printf("X mov %d, Y mov %d\n", urb->transfer.data_buffer[1], urb->transfer.data_buffer[2]); + // Requeue URB if (iter_count > NUM_URBS) { TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(intr_pipe, urb)); } } - //Free URB list and pipe + // Free URB list and pipe for (int i = 0; i < NUM_URBS; i++) { test_hcd_free_urb(urb_list[i]); } test_hcd_pipe_free(intr_pipe); test_hcd_pipe_free(default_pipe); - //Clearnup + // Clearnup test_hcd_wait_for_disconn(port_hdl, false); } diff --git a/components/usb/test_apps/hcd/main/test_hcd_isoc.c b/components/usb/test_apps/hcd/main/test_hcd_isoc.c index aff0440b49..20c4c63ab5 100644 --- a/components/usb/test_apps/hcd/main/test_hcd_isoc.c +++ b/components/usb/test_apps/hcd/main/test_hcd_isoc.c @@ -10,14 +10,13 @@ #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "unity.h" -#include "test_usb_mock_msc.h" +#include "dev_isoc.h" +#include "usb/usb_types_ch9.h" #include "test_usb_common.h" #include "test_hcd_common.h" #define NUM_URBS 3 #define NUM_PACKETS_PER_URB 3 -#define ISOC_PACKET_SIZE MOCK_ISOC_EP_MPS -#define URB_DATA_BUFF_SIZE (NUM_PACKETS_PER_URB * ISOC_PACKET_SIZE) #define POST_ENQUEUE_DELAY_US 20 #define ENQUEUE_DELAY (OTG_HSPHY_INTERFACE ? 100 : 500) // With this delay we want to enqueue the URBs at different times @@ -43,57 +42,59 @@ Procedure: TEST_CASE("Test HCD isochronous pipe URBs", "[isoc][full_speed]") { - 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 + 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)); - vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS) + vTaskDelay(pdMS_TO_TICKS(100)); // Short delay send of SOF (for FS) or EOPs (for LS) - //Enumerate and reset device - 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) + // Enumerate and reset device + 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) uint8_t dev_addr = test_hcd_enum_device(default_pipe); - //Create ISOC OUT pipe to non-existent device - hcd_pipe_handle_t isoc_out_pipe = test_hcd_pipe_alloc(port_hdl, &mock_isoc_out_ep_desc, dev_addr + 1, port_speed); - //Create URBs + // Create ISOC OUT pipe to non-existent device + const usb_ep_desc_t *out_ep_desc = dev_isoc_get_out_ep_desc(port_speed); + const int isoc_packet_size = USB_EP_DESC_GET_MPS(out_ep_desc); + hcd_pipe_handle_t isoc_out_pipe = test_hcd_pipe_alloc(port_hdl, out_ep_desc, dev_addr + 1, port_speed); + // Create URBs urb_t *urb_list[NUM_URBS]; - //Initialize URBs + // Initialize URBs for (int urb_idx = 0; urb_idx < NUM_URBS; urb_idx++) { - urb_list[urb_idx] = test_hcd_alloc_urb(NUM_PACKETS_PER_URB, URB_DATA_BUFF_SIZE); - urb_list[urb_idx]->transfer.num_bytes = URB_DATA_BUFF_SIZE; + urb_list[urb_idx] = test_hcd_alloc_urb(NUM_PACKETS_PER_URB, NUM_PACKETS_PER_URB * isoc_packet_size); + urb_list[urb_idx]->transfer.num_bytes = NUM_PACKETS_PER_URB * isoc_packet_size; urb_list[urb_idx]->transfer.context = URB_CONTEXT_VAL; for (int pkt_idx = 0; pkt_idx < NUM_PACKETS_PER_URB; pkt_idx++) { - urb_list[urb_idx]->transfer.isoc_packet_desc[pkt_idx].num_bytes = ISOC_PACKET_SIZE; - //Each packet will consist of the same byte, but each subsequent packet's byte will increment (i.e., packet 0 transmits all 0x0, packet 1 transmits all 0x1) - memset(&urb_list[urb_idx]->transfer.data_buffer[pkt_idx * ISOC_PACKET_SIZE], (urb_idx * NUM_URBS) + pkt_idx, ISOC_PACKET_SIZE); + urb_list[urb_idx]->transfer.isoc_packet_desc[pkt_idx].num_bytes = isoc_packet_size; + // Each packet will consist of the same byte, but each subsequent packet's byte will increment (i.e., packet 0 transmits all 0x0, packet 1 transmits all 0x1) + memset(&urb_list[urb_idx]->transfer.data_buffer[pkt_idx * isoc_packet_size], (urb_idx * NUM_URBS) + pkt_idx, isoc_packet_size); } } - //Enqueue URBs + // Enqueue URBs for (int i = 0; i < NUM_URBS; i++) { TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(isoc_out_pipe, urb_list[i])); } - //Wait for each done event from each URB + // Wait for each done event from each URB for (int i = 0; i < NUM_URBS; i++) { test_hcd_expect_pipe_event(isoc_out_pipe, HCD_PIPE_EVENT_URB_DONE); } - //Dequeue URBs + // Dequeue URBs for (int urb_idx = 0; urb_idx < NUM_URBS; urb_idx++) { urb_t *urb = hcd_urb_dequeue(isoc_out_pipe); TEST_ASSERT_EQUAL(urb_list[urb_idx], urb); 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); + // Overall URB status and overall number of bytes + TEST_ASSERT_EQUAL(NUM_PACKETS_PER_URB * isoc_packet_size, urb->transfer.actual_num_bytes); 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_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.isoc_packet_desc[pkt_idx].status, "Transfer NOT completed"); } } - //Free URB list and pipe + // Free URB list and pipe for (int i = 0; i < NUM_URBS; i++) { test_hcd_free_urb(urb_list[i]); } test_hcd_pipe_free(isoc_out_pipe); test_hcd_pipe_free(default_pipe); - //Cleanup + // Cleanup test_hcd_wait_for_disconn(port_hdl, false); } @@ -116,23 +117,25 @@ Procedure: */ TEST_CASE("Test HCD isochronous pipe URBs all", "[isoc][full_speed]") { - 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 + 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)); - vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS) + vTaskDelay(pdMS_TO_TICKS(100)); // Short delay send of SOF (for FS) or EOPs (for LS) - //Enumerate and reset device - 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) + // Enumerate and reset device + 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) uint8_t dev_addr = test_hcd_enum_device(default_pipe); urb_t *urb_list[NUM_URBS]; hcd_pipe_handle_t unused_pipes[OTG_NUM_HOST_CHAN]; + const usb_ep_desc_t *out_ep_desc = dev_isoc_get_out_ep_desc(port_speed); + const int isoc_packet_size = USB_EP_DESC_GET_MPS(out_ep_desc); // For all channels for (int channel = 0; channel < OTG_NUM_HOST_CHAN - 1; channel++) { // Allocate unused pipes, so the active isoc_out_pipe uses different channel index for (int ch = 0; ch < channel; ch++) { - unused_pipes[ch] = test_hcd_pipe_alloc(port_hdl, &mock_isoc_out_ep_desc, dev_addr + 1, port_speed); + unused_pipes[ch] = test_hcd_pipe_alloc(port_hdl, out_ep_desc, dev_addr + 1, port_speed); } // For all intervals @@ -141,48 +144,49 @@ TEST_CASE("Test HCD isochronous pipe URBs all", "[isoc][full_speed]") vTaskDelay(5); unsigned num_packets_per_urb = 32; // This is maximum number of packets if interval = 1. This is limited by FRAME_LIST_LEN num_packets_per_urb >>= (interval - 1); - //Create ISOC OUT pipe - usb_ep_desc_t isoc_out_ep = mock_isoc_out_ep_desc; // Implicit copy + // Create ISOC OUT pipe + usb_ep_desc_t isoc_out_ep; + memcpy(&isoc_out_ep, out_ep_desc, sizeof(usb_ep_desc_t)); isoc_out_ep.bInterval = interval; isoc_out_ep.bEndpointAddress = interval; // So you can see the bInterval value in trace hcd_pipe_handle_t isoc_out_pipe = test_hcd_pipe_alloc(port_hdl, &isoc_out_ep, channel + 1, port_speed); // Channel number represented in dev_num, so you can see it in trace - //Initialize URBs + // Initialize URBs for (int urb_idx = 0; urb_idx < NUM_URBS; urb_idx++) { - urb_list[urb_idx] = test_hcd_alloc_urb(num_packets_per_urb, num_packets_per_urb * ISOC_PACKET_SIZE); - urb_list[urb_idx]->transfer.num_bytes = num_packets_per_urb * ISOC_PACKET_SIZE; + urb_list[urb_idx] = test_hcd_alloc_urb(num_packets_per_urb, num_packets_per_urb * isoc_packet_size); + urb_list[urb_idx]->transfer.num_bytes = num_packets_per_urb * isoc_packet_size; urb_list[urb_idx]->transfer.context = URB_CONTEXT_VAL; for (int pkt_idx = 0; pkt_idx < num_packets_per_urb; pkt_idx++) { - urb_list[urb_idx]->transfer.isoc_packet_desc[pkt_idx].num_bytes = ISOC_PACKET_SIZE; - //Each packet will consist of the same byte, but each subsequent packet's byte will increment (i.e., packet 0 transmits all 0x0, packet 1 transmits all 0x1) - memset(&urb_list[urb_idx]->transfer.data_buffer[pkt_idx * ISOC_PACKET_SIZE], (urb_idx * num_packets_per_urb) + pkt_idx, ISOC_PACKET_SIZE); + urb_list[urb_idx]->transfer.isoc_packet_desc[pkt_idx].num_bytes = isoc_packet_size; + // Each packet will consist of the same byte, but each subsequent packet's byte will increment (i.e., packet 0 transmits all 0x0, packet 1 transmits all 0x1) + memset(&urb_list[urb_idx]->transfer.data_buffer[pkt_idx * isoc_packet_size], (urb_idx * num_packets_per_urb) + pkt_idx, isoc_packet_size); } } // Add a delay so we start scheduling the transactions at different time in USB frame esp_rom_delay_us(ENQUEUE_DELAY * interval + ENQUEUE_DELAY * channel); - //Enqueue URBs + // Enqueue URBs for (int i = 0; i < NUM_URBS; i++) { TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(isoc_out_pipe, urb_list[i])); } - //Wait for each done event from each URB + // Wait for each done event from each URB for (int i = 0; i < NUM_URBS; i++) { test_hcd_expect_pipe_event(isoc_out_pipe, HCD_PIPE_EVENT_URB_DONE); } - //Dequeue URBs + // Dequeue URBs for (int urb_idx = 0; urb_idx < NUM_URBS; urb_idx++) { urb_t *urb = hcd_urb_dequeue(isoc_out_pipe); TEST_ASSERT_EQUAL(urb_list[urb_idx], urb); TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context); - //Overall URB status and overall number of bytes - TEST_ASSERT_EQUAL(num_packets_per_urb * ISOC_PACKET_SIZE, urb->transfer.actual_num_bytes); + // Overall URB status and overall number of bytes + TEST_ASSERT_EQUAL(num_packets_per_urb * isoc_packet_size, urb->transfer.actual_num_bytes); 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_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.isoc_packet_desc[pkt_idx].status, "Transfer NOT completed"); } } - //Free URB list and pipe + // Free URB list and pipe for (int i = 0; i < NUM_URBS; i++) { test_hcd_free_urb(urb_list[i]); } @@ -195,7 +199,7 @@ TEST_CASE("Test HCD isochronous pipe URBs all", "[isoc][full_speed]") } } test_hcd_pipe_free(default_pipe); - //Cleanup + // Cleanup test_hcd_wait_for_disconn(port_hdl, false); } @@ -225,65 +229,67 @@ Procedure: */ TEST_CASE("Test HCD isochronous pipe sudden disconnect", "[isoc][full_speed]") { - 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 + 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)); - vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS) + vTaskDelay(pdMS_TO_TICKS(100)); // Short delay send of SOF (for FS) or EOPs (for LS) - //Enumerate and reset device - 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) + // Enumerate and reset device + 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) uint8_t dev_addr = test_hcd_enum_device(default_pipe); - //Create ISOC OUT pipe to non-existent device - hcd_pipe_handle_t isoc_out_pipe = test_hcd_pipe_alloc(port_hdl, &mock_isoc_out_ep_desc, dev_addr + 1, port_speed); - //Create URBs + // Create ISOC OUT pipe to non-existent device + const usb_ep_desc_t *out_ep_desc = dev_isoc_get_out_ep_desc(port_speed); + const int isoc_packet_size = USB_EP_DESC_GET_MPS(out_ep_desc); + hcd_pipe_handle_t isoc_out_pipe = test_hcd_pipe_alloc(port_hdl, out_ep_desc, dev_addr + 1, port_speed); + // Create URBs urb_t *urb_list[NUM_URBS]; - //Initialize URBs + // Initialize URBs for (int urb_idx = 0; urb_idx < NUM_URBS; urb_idx++) { - urb_list[urb_idx] = test_hcd_alloc_urb(NUM_PACKETS_PER_URB, URB_DATA_BUFF_SIZE); - urb_list[urb_idx]->transfer.num_bytes = URB_DATA_BUFF_SIZE; + urb_list[urb_idx] = test_hcd_alloc_urb(NUM_PACKETS_PER_URB, NUM_PACKETS_PER_URB * isoc_packet_size); + urb_list[urb_idx]->transfer.num_bytes = NUM_PACKETS_PER_URB * isoc_packet_size; urb_list[urb_idx]->transfer.context = URB_CONTEXT_VAL; for (int pkt_idx = 0; pkt_idx < NUM_PACKETS_PER_URB; pkt_idx++) { - urb_list[urb_idx]->transfer.isoc_packet_desc[pkt_idx].num_bytes = ISOC_PACKET_SIZE; - //Each packet will consist of the same byte, but each subsequent packet's byte will increment (i.e., packet 0 transmits all 0x0, packet 1 transmits all 0x1) - memset(&urb_list[urb_idx]->transfer.data_buffer[pkt_idx * ISOC_PACKET_SIZE], (urb_idx * NUM_URBS) + pkt_idx, ISOC_PACKET_SIZE); + urb_list[urb_idx]->transfer.isoc_packet_desc[pkt_idx].num_bytes = isoc_packet_size; + // Each packet will consist of the same byte, but each subsequent packet's byte will increment (i.e., packet 0 transmits all 0x0, packet 1 transmits all 0x1) + memset(&urb_list[urb_idx]->transfer.data_buffer[pkt_idx * isoc_packet_size], (urb_idx * NUM_URBS) + pkt_idx, isoc_packet_size); } } - //Enqueue URBs + // Enqueue URBs for (int i = 0; i < NUM_URBS; i++) { TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(isoc_out_pipe, urb_list[i])); } - //Add a short delay to let the transfers run for a bit + // Add a short delay to let the transfers run for a bit esp_rom_delay_us(POST_ENQUEUE_DELAY_US); test_usb_set_phy_state(false, 0); - //Disconnect event should have occurred. Handle the port event + // Disconnect event should have occurred. Handle the port event test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION); TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_RECOVERY, hcd_port_get_state(port_hdl)); printf("Sudden disconnect\n"); - //Both pipes should still be active + // Both pipes should still be active TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe)); TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(isoc_out_pipe)); - //Halt both pipes + // Halt both pipes TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_HALT)); TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(isoc_out_pipe, HCD_PIPE_CMD_HALT)); TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe)); TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(isoc_out_pipe)); - //Flush both pipes. ISOC pipe should return completed URBs + // Flush both pipes. ISOC pipe should return completed URBs TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_FLUSH)); TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(isoc_out_pipe, HCD_PIPE_CMD_FLUSH)); - //Dequeue ISOC URBs + // Dequeue ISOC URBs for (int urb_idx = 0; urb_idx < NUM_URBS; urb_idx++) { urb_t *urb = hcd_urb_dequeue(isoc_out_pipe); TEST_ASSERT_EQUAL(urb_list[urb_idx], urb); TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context); - //The URB has either completed entirely or is marked as no_device + // The URB has either completed entirely or is marked as no_device TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_NO_DEVICE); } - //Free URB list and pipe + // Free URB list and pipe for (int i = 0; i < NUM_URBS; i++) { test_hcd_free_urb(urb_list[i]); } diff --git a/components/usb/test_apps/hcd/main/test_hcd_port.c b/components/usb/test_apps/hcd/main/test_hcd_port.c index 3b44623cba..67f502335b 100644 --- a/components/usb/test_apps/hcd/main/test_hcd_port.c +++ b/components/usb/test_apps/hcd/main/test_hcd_port.c @@ -15,7 +15,7 @@ #define TEST_DEV_ADDR 0 #define NUM_URBS 3 #define TRANSFER_MAX_BYTES 256 -#define URB_DATA_BUFF_SIZE (sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES) //256 is worst case size for configuration descriptors +#define URB_DATA_BUFF_SIZE (sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES) // 256 is worst case size for configuration descriptors #define POST_ENQUEUE_DELAY_US 10 /* @@ -43,35 +43,35 @@ Procedure: TEST_CASE("Test HCD port sudden disconnect", "[port][low_speed][full_speed]") { - 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) + 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) - //Allocate some URBs and initialize their data buffers with control transfers - hcd_pipe_handle_t default_pipe = test_hcd_pipe_alloc(port_hdl, NULL, TEST_DEV_ADDR, port_speed); //Create a default pipe (using a NULL EP descriptor) + // Allocate some URBs and initialize their data buffers with control transfers + hcd_pipe_handle_t default_pipe = test_hcd_pipe_alloc(port_hdl, NULL, TEST_DEV_ADDR, port_speed); // Create a default pipe (using a NULL EP descriptor) urb_t *urb_list[NUM_URBS]; for (int i = 0; i < NUM_URBS; i++) { urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE); - //Initialize with a "Get Config Descriptor request" + // Initialize with a "Get Config Descriptor request" urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES; USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); urb_list[i]->transfer.context = (void *)0xDEADBEEF; } - //Enqueue URBs but immediately trigger a disconnect + // Enqueue URBs but immediately trigger a disconnect 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 + // Add a short delay to let the transfers run for a bit esp_rom_delay_us(POST_ENQUEUE_DELAY_US); test_usb_set_phy_state(false, 0); - //Disconnect event should have occurred. Handle the port event + // Disconnect event should have occurred. Handle the port event test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION); TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_RECOVERY, hcd_port_get_state(port_hdl)); printf("Sudden disconnect\n"); - //We should be able to halt then flush the pipe + // We should be able to halt then flush the pipe 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)); printf("Pipe halted\n"); @@ -80,32 +80,32 @@ TEST_CASE("Test HCD port sudden disconnect", "[port][low_speed][full_speed]") test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); printf("Pipe flushed\n"); - //Dequeue URBs + // Dequeue URBs 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(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_NO_DEVICE); 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 + // 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); TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); } else { - //A failed transfer should 0 actual number of bytes transmitted + // A failed transfer should 0 actual number of bytes transmitted TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes); } TEST_ASSERT_EQUAL(0xDEADBEEF, urb->transfer.context); } - //Free URB list and pipe + // Free URB list and pipe for (int i = 0; i < NUM_URBS; i++) { test_hcd_free_urb(urb_list[i]); } test_hcd_pipe_free(default_pipe); - //Recover the port should return to the to NOT POWERED state + // Recover the port should return to the to NOT POWERED state TEST_ASSERT_EQUAL(ESP_OK, hcd_port_recover(port_hdl)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_NOT_POWERED, hcd_port_get_state(port_hdl)); - //Recovered port should be able to connect and disconnect again + // 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); } @@ -132,38 +132,38 @@ Procedure: */ TEST_CASE("Test HCD port suspend and resume", "[port][low_speed][full_speed]") { - 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) + 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) - //Allocate some URBs and initialize their data buffers with control transfers - hcd_pipe_handle_t default_pipe = test_hcd_pipe_alloc(port_hdl, NULL, TEST_DEV_ADDR, port_speed); //Create a default pipe (using a NULL EP descriptor) + // Allocate some URBs and initialize their data buffers with control transfers + hcd_pipe_handle_t default_pipe = test_hcd_pipe_alloc(port_hdl, NULL, TEST_DEV_ADDR, port_speed); // Create a default pipe (using a NULL EP descriptor) - //Test that suspending the port now fails as there is an active pipe + // Test that suspending the port now fails as there is an active pipe TEST_ASSERT_NOT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_SUSPEND)); - //Halt the default pipe before suspending + // 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)); - //Suspend the port + // Suspend the port TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_SUSPEND)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_SUSPENDED, hcd_port_get_state(port_hdl)); printf("Suspended\n"); - vTaskDelay(pdMS_TO_TICKS(100)); //Give some time for bus to remain suspended + vTaskDelay(pdMS_TO_TICKS(100)); // Give some time for bus to remain suspended - //Resume the port + // Resume the port TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_RESUME)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_ENABLED, hcd_port_get_state(port_hdl)); printf("Resumed\n"); - //Clear the default pipe's halt + // Clear the default pipe's halt TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_CLEAR)); TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe)); - vTaskDelay(pdMS_TO_TICKS(100)); //Give some time for resumed URBs to complete + vTaskDelay(pdMS_TO_TICKS(100)); // Give some time for resumed URBs to complete test_hcd_pipe_free(default_pipe); - //Cleanup + // Cleanup test_hcd_wait_for_disconn(port_hdl, false); } @@ -186,65 +186,65 @@ Procedure: */ TEST_CASE("Test HCD port disable", "[port][low_speed][full_speed]") { - 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) + 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) - //Allocate some URBs and initialize their data buffers with control transfers - hcd_pipe_handle_t default_pipe = test_hcd_pipe_alloc(port_hdl, NULL, TEST_DEV_ADDR, port_speed); //Create a default pipe (using a NULL EP descriptor) + // Allocate some URBs and initialize their data buffers with control transfers + hcd_pipe_handle_t default_pipe = test_hcd_pipe_alloc(port_hdl, NULL, TEST_DEV_ADDR, port_speed); // Create a default pipe (using a NULL EP descriptor) urb_t *urb_list[NUM_URBS]; for (int i = 0; i < NUM_URBS; i++) { urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE); - //Initialize with a "Get Config Descriptor request" + // Initialize with a "Get Config Descriptor request" urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES; USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); urb_list[i]->transfer.context = (void *)0xDEADBEEF; } - //Enqueue URBs but immediately disable the port + // Enqueue URBs but immediately disable the port 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 + // 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 + // 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 + // 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)); printf("Disabled\n"); - //Flush pipe + // Flush pipe TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_FLUSH)); - //Dequeue URBs + // Dequeue URBs 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(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || //The transfer completed before the pipe halted - urb->transfer.status == USB_TRANSFER_STATUS_CANCELED || //The transfer was stopped mid-way by the halt - urb->transfer.status == USB_TRANSFER_STATUS_NO_DEVICE); //The transfer was never started + TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || // The transfer completed before the pipe halted + urb->transfer.status == USB_TRANSFER_STATUS_CANCELED || // The transfer was stopped mid-way by the halt + urb->transfer.status == USB_TRANSFER_STATUS_NO_DEVICE); // The transfer was never started 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 + // 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); TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); } else { - //A failed transfer should 0 actual number of bytes transmitted + // A failed transfer should 0 actual number of bytes transmitted TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes); } TEST_ASSERT_EQUAL(0xDEADBEEF, urb->transfer.context); } - //Free URB list and pipe + // Free URB list and pipe for (int i = 0; i < NUM_URBS; i++) { test_hcd_free_urb(urb_list[i]); } test_hcd_pipe_free(default_pipe); - //Trigger a disconnection and cleanup + // Trigger a disconnection and cleanup test_hcd_wait_for_disconn(port_hdl, true); } @@ -266,40 +266,40 @@ static void concurrent_task(void *arg) { SemaphoreHandle_t sync_sem = (SemaphoreHandle_t) arg; xSemaphoreTake(sync_sem, portMAX_DELAY); - vTaskDelay(pdMS_TO_TICKS(10)); //Give a short delay let reset command start in main thread - //Force a disconnection + vTaskDelay(pdMS_TO_TICKS(10)); // Give a short delay let reset command start in main thread + // Force a disconnection test_usb_set_phy_state(false, 0); - vTaskDelay(portMAX_DELAY); //Block forever and wait to be deleted + vTaskDelay(portMAX_DELAY); // Block forever and wait to be deleted } TEST_CASE("Test HCD port command bailout", "[port][low_speed][full_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) + 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 + // Create task to run port commands concurrently SemaphoreHandle_t sync_sem = xSemaphoreCreateBinary(); TaskHandle_t task_handle; 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 + // Suspend the device printf("Suspending\n"); TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_SUSPEND)); - vTaskDelay(pdMS_TO_TICKS(20)); //Short delay for device to enter suspend state + vTaskDelay(pdMS_TO_TICKS(20)); // Short delay for device to enter suspend state - //Attempt to resume the port. But the concurrent task should override this with a disconnection event + // Attempt to resume the port. But the concurrent task should override this with a disconnection event printf("Attempting to resume\n"); - xSemaphoreGive(sync_sem); //Trigger concurrent task + xSemaphoreGive(sync_sem); // Trigger concurrent task TEST_ASSERT_EQUAL(ESP_ERR_INVALID_RESPONSE, hcd_port_command(port_hdl, HCD_PORT_CMD_RESUME)); - //Check that concurrent task triggered a sudden disconnection + // Check that concurrent task triggered a sudden disconnection test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION); TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_RECOVERY, hcd_port_get_state(port_hdl)); - //Cleanup task and semaphore - vTaskDelay(pdMS_TO_TICKS(10)); //Short delay for concurrent task finish running + // Cleanup task and semaphore + vTaskDelay(pdMS_TO_TICKS(10)); // Short delay for concurrent task finish running vTaskDelete(task_handle); vSemaphoreDelete(sync_sem); } diff --git a/components/usb/test_apps/hcd/main/test_usb_helpers.c b/components/usb/test_apps/hcd/main/test_usb_helpers.c index fafe81c032..742ae56125 100644 --- a/components/usb/test_apps/hcd/main/test_usb_helpers.c +++ b/components/usb/test_apps/hcd/main/test_usb_helpers.c @@ -333,7 +333,7 @@ static uint8_t config_desc_bytes [] = { }; _Static_assert(sizeof(config_desc_bytes) == 0x0185, "Configuration Descriptor size does not match"); -#define TEST_NUM_INTF_DESC 3 //Total number of interface descriptors (including alternate) +#define TEST_NUM_INTF_DESC 3 // Total number of interface descriptors (including alternate) // --------------------- Sub-Test 1 ------------------------ @@ -348,7 +348,7 @@ static void test_walk_desc(const usb_config_desc_t *config_desc) cur_desc = usb_parse_next_descriptor_of_type(cur_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset); TEST_ASSERT_NOT_NULL(cur_desc); } - //Attempting to look for another interface descriptor should result in NULL + // 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_NULL(cur_desc); } @@ -358,11 +358,11 @@ Test if the count of number of alternate descriptors is correct */ static void test_alt_intf_desc_count(const usb_config_desc_t *config_desc) { - //bInterface 0 has no alternate interfaces + // bInterface 0 has no alternate interfaces TEST_ASSERT_EQUAL(0, usb_parse_interface_number_of_alternate(config_desc, 0)); - //bInterface 1 has 1 alternate interface + // bInterface 1 has 1 alternate interface TEST_ASSERT_EQUAL(1, usb_parse_interface_number_of_alternate(config_desc, 1)); - //Non existent bInterface 2 should return -1 + // Non existent bInterface 2 should return -1 TEST_ASSERT_EQUAL(-1, usb_parse_interface_number_of_alternate(config_desc, 2)); } @@ -370,10 +370,10 @@ static void test_parse_intf_and_ep(const usb_config_desc_t *config_desc) { int offset_intf = 0; - //Get bInterfaceNumber 0 (index 0) + // 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_NULL(intf_desc); - //Should only have one endpoint + // 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_NULL(ep_desc); @@ -382,20 +382,20 @@ static void test_parse_intf_and_ep(const usb_config_desc_t *config_desc) ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, 1, config_desc->wTotalLength, &offset_ep); TEST_ASSERT_NULL(ep_desc); - //Get bInterfaceNumber 1 alternate setting 0 + // Get bInterfaceNumber 1 alternate setting 0 offset_intf = 0; intf_desc = usb_parse_interface_descriptor(config_desc, 1, 0, &offset_intf); TEST_ASSERT_NOT_NULL(intf_desc); - //Should have no endpoints + // 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_NULL(ep_desc); - //Get bInterfaceNumber 1 alternate setting 1 + // Get bInterfaceNumber 1 alternate setting 1 offset_intf = 0; intf_desc = usb_parse_interface_descriptor(config_desc, 1, 1, &offset_intf); TEST_ASSERT_NOT_NULL(intf_desc); - //Should only have one endpoint + // 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_NULL(ep_desc); @@ -408,21 +408,21 @@ static void test_parse_intf_and_ep(const usb_config_desc_t *config_desc) 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 + // 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_NULL(ep_desc); TEST_ASSERT_EQUAL(0x83, ep_desc->bEndpointAddress); - //Getting same EP address under different interface should return NULL + // 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_NULL(ep_desc); - //Get bInterface 1 bAlternateSetting 1 EP 0x81 + // 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_NULL(ep_desc); TEST_ASSERT_EQUAL(0x81, ep_desc->bEndpointAddress); - //Getting same EP address under different interface should return NULL + // 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_NULL(ep_desc); diff --git a/components/usb/test_apps/usb_host/README.md b/components/usb/test_apps/usb_host/README.md index afe40d8da3..c76482cea3 100644 --- a/components/usb/test_apps/usb_host/README.md +++ b/components/usb/test_apps/usb_host/README.md @@ -7,5 +7,5 @@ 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). +For running these tests locally, you will have to update device definitions (VID, PID, ...) in [mock_msc.h](../common/mock_msc.h) and [mock_hid.h](../common/mock_hid.h). diff --git a/components/usb/test_apps/usb_host/main/ctrl_client.h b/components/usb/test_apps/usb_host/main/ctrl_client.h index 4cfeccc53d..b780571f6b 100644 --- a/components/usb/test_apps/usb_host/main/ctrl_client.h +++ b/components/usb/test_apps/usb_host/main/ctrl_client.h @@ -8,8 +8,6 @@ typedef struct { int num_ctrl_xfer_to_send; - uint16_t idVendor; - uint16_t idProduct; } ctrl_client_test_param_t; void ctrl_client_async_seq_task(void *arg); diff --git a/components/usb/test_apps/usb_host/main/ctrl_client_async_seq.c b/components/usb/test_apps/usb_host/main/ctrl_client_async_seq.c index b163dc20fb..657cf87595 100644 --- a/components/usb/test_apps/usb_host/main/ctrl_client_async_seq.c +++ b/components/usb/test_apps/usb_host/main/ctrl_client_async_seq.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +11,7 @@ #include "esp_err.h" #include "esp_log.h" #include "test_usb_common.h" +#include "dev_msc.h" #include "ctrl_client.h" #include "usb/usb_host.h" #include "unity.h" @@ -47,21 +48,26 @@ typedef enum { } test_stage_t; typedef struct { + // Test parameters ctrl_client_test_param_t test_param; + // MSC device info + uint8_t dev_addr; + usb_speed_t dev_speed; + // Client variables + usb_host_client_handle_t client_hdl; + usb_device_handle_t dev_hdl; + // Test state test_stage_t cur_stage; test_stage_t next_stage; uint8_t num_xfer_done; uint8_t num_xfer_sent; - uint8_t dev_addr_to_open; - usb_host_client_handle_t client_hdl; - usb_device_handle_t dev_hdl; const usb_config_desc_t *config_desc_cached; } ctrl_client_obj_t; 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 + // Check the completed control transfer 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++; @@ -79,10 +85,10 @@ static void ctrl_client_event_cb(const usb_host_client_event_msg_t *event_msg, v case USB_HOST_CLIENT_EVENT_NEW_DEV: TEST_ASSERT_EQUAL(TEST_STAGE_WAIT_CONN, ctrl_obj->cur_stage); ctrl_obj->next_stage = TEST_STAGE_DEV_OPEN; - ctrl_obj->dev_addr_to_open = event_msg->new_dev.address; + ctrl_obj->dev_addr = event_msg->new_dev.address; break; default: - abort(); //Should never occur in this test + abort(); // Should never occur in this test break; } } @@ -94,7 +100,7 @@ void ctrl_client_async_seq_task(void *arg) ctrl_obj.cur_stage = TEST_STAGE_WAIT_CONN; ctrl_obj.next_stage = TEST_STAGE_WAIT_CONN; - //Register client + // Register client usb_host_client_config_t client_config = { .is_synchronous = false, .max_num_event_msg = CTRL_CLIENT_MAX_EVENT_MSGS, @@ -105,7 +111,7 @@ void ctrl_client_async_seq_task(void *arg) }; TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_register(&client_config, &ctrl_obj.client_hdl)); - //Allocate transfers + // Allocate transfers usb_transfer_t *ctrl_xfer[NUM_TRANSFER_OBJ] = {NULL}; for (int i = 0; i < NUM_TRANSFER_OBJ; i++) { TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_alloc(sizeof(usb_setup_packet_t) + MAX_TRANSFER_BYTES, 0, &ctrl_xfer[i])); @@ -113,7 +119,7 @@ void ctrl_client_async_seq_task(void *arg) ctrl_xfer[i]->context = (void *)&ctrl_obj; } - //Wait to be started by main thread + // Wait to be started by main thread ulTaskNotifyTake(pdTRUE, portMAX_DELAY); ESP_LOGD(CTRL_CLIENT_TAG, "Starting"); @@ -132,18 +138,23 @@ void ctrl_client_async_seq_task(void *arg) switch (ctrl_obj.next_stage) { case TEST_STAGE_DEV_OPEN: { ESP_LOGD(CTRL_CLIENT_TAG, "Open"); - //Open the device - 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 + // Open the device + TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_host_device_open(ctrl_obj.client_hdl, ctrl_obj.dev_addr, &ctrl_obj.dev_hdl), "Failed to open the device"); + // Get device info to get device speed + usb_device_info_t dev_info; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_info(ctrl_obj.dev_hdl, &dev_info)); + ctrl_obj.dev_speed = dev_info.speed; + // Target our transfers to the device for (int i = 0; i < NUM_TRANSFER_OBJ; i++) { ctrl_xfer[i]->device_handle = ctrl_obj.dev_hdl; } - //Check the VID/PID of the opened device + // Check that the device descriptor matches our expected MSC device const usb_device_desc_t *device_desc; + const usb_device_desc_t *device_desc_ref = dev_msc_get_dev_desc(ctrl_obj.dev_speed); TEST_ASSERT_EQUAL(ESP_OK, usb_host_get_device_descriptor(ctrl_obj.dev_hdl, &device_desc)); - TEST_ASSERT_EQUAL(ctrl_obj.test_param.idVendor, device_desc->idVendor); - TEST_ASSERT_EQUAL(ctrl_obj.test_param.idProduct, device_desc->idProduct); - //Cache the active configuration descriptor for later comparison + TEST_ASSERT_EQUAL(device_desc_ref->bLength, device_desc->bLength); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(device_desc_ref, device_desc, sizeof(usb_device_desc_t), "Device descriptors do not match."); + // Cache the active configuration descriptor for later comparison TEST_ASSERT_EQUAL(ESP_OK, usb_host_get_active_config_descriptor(ctrl_obj.dev_hdl, &ctrl_obj.config_desc_cached)); ctrl_obj.next_stage = TEST_STAGE_CTRL_XFER; skip_event_handling = true; @@ -151,7 +162,7 @@ void ctrl_client_async_seq_task(void *arg) } case TEST_STAGE_CTRL_XFER: { ESP_LOGD(CTRL_CLIENT_TAG, "Transfer"); - //Send a control transfer to get the device's configuration descriptor + // Send a control transfer to get the device's configuration descriptor usb_transfer_t *transfer = ctrl_xfer[ctrl_obj.num_xfer_sent % NUM_TRANSFER_OBJ]; USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)transfer->data_buffer, 0, MAX_TRANSFER_BYTES); transfer->num_bytes = sizeof(usb_setup_packet_t) + MAX_TRANSFER_BYTES; @@ -163,12 +174,12 @@ void ctrl_client_async_seq_task(void *arg) break; } case TEST_STAGE_CTRL_XFER_WAIT: { - //Nothing to do but wait + // Nothing to do but wait break; } case TEST_STAGE_DEV_CLOSE: { ESP_LOGD(CTRL_CLIENT_TAG, "Close"); - vTaskDelay(10); // Give USB Host Lib some time to process all trnsfers + vTaskDelay(10); // Give USB Host Lib some time to process all transfers TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_close(ctrl_obj.client_hdl, ctrl_obj.dev_hdl)); exit_loop = true; break; @@ -178,7 +189,7 @@ void ctrl_client_async_seq_task(void *arg) break; } } - //Free transfers and deregister client + // Free transfers and deregister client for (int i = 0; i < NUM_TRANSFER_OBJ; i++) { TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_free(ctrl_xfer[i])); } diff --git a/components/usb/test_apps/usb_host/main/msc_client.h b/components/usb/test_apps/usb_host/main/msc_client.h index c3bf2063f2..6a816547bd 100644 --- a/components/usb/test_apps/usb_host/main/msc_client.h +++ b/components/usb/test_apps/usb_host/main/msc_client.h @@ -12,8 +12,6 @@ typedef struct { int num_sectors_to_read; int num_sectors_per_xfer; uint32_t msc_scsi_xfer_tag; - uint16_t idVendor; - uint16_t idProduct; } msc_client_test_param_t; void msc_client_async_seq_task(void *arg); diff --git a/components/usb/test_apps/usb_host/main/msc_client_async_dconn.c b/components/usb/test_apps/usb_host/main/msc_client_async_dconn.c index af6bc5435b..5f1df1cf15 100644 --- a/components/usb/test_apps/usb_host/main/msc_client_async_dconn.c +++ b/components/usb/test_apps/usb_host/main/msc_client_async_dconn.c @@ -12,9 +12,11 @@ #include "freertos/task.h" #include "esp_err.h" #include "esp_log.h" -#include "test_usb_mock_msc.h" +#include "mock_msc.h" +#include "dev_msc.h" #include "test_usb_common.h" #include "msc_client.h" +#include "usb/usb_types_ch9.h" #include "usb/usb_host.h" #include "unity.h" @@ -47,21 +49,26 @@ typedef enum { } test_stage_t; typedef struct { + // Test parameters msc_client_test_param_t test_param; - test_stage_t cur_stage; - test_stage_t next_stage; - uint8_t dev_addr_to_open; + // MSC device info + const dev_msc_info_t *dev_info; + usb_speed_t dev_speed; + uint8_t dev_addr; + // Client variables usb_host_client_handle_t client_hdl; usb_device_handle_t dev_hdl; + // Test state + test_stage_t cur_stage; + test_stage_t next_stage; int num_data_transfers; int event_count; - usb_speed_t dev_speed; } msc_client_obj_t; 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 + // We expect the reset and CBW transfers to complete with no issues 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) { @@ -79,7 +86,7 @@ static void msc_reset_cbw_transfer_cb(usb_transfer_t *transfer) static void msc_data_transfer_cb(usb_transfer_t *transfer) { - //The data stage should have either completed, or failed due to the disconnection. + // The data stage should have either completed, or failed due to the disconnection. TEST_ASSERT(transfer->status == USB_TRANSFER_STATUS_COMPLETED || transfer->status == USB_TRANSFER_STATUS_NO_DEVICE); if (transfer->status == USB_TRANSFER_STATUS_COMPLETED) { TEST_ASSERT_EQUAL(transfer->num_bytes, transfer->actual_num_bytes); @@ -88,7 +95,7 @@ static void msc_data_transfer_cb(usb_transfer_t *transfer) } msc_client_obj_t *msc_obj = (msc_client_obj_t *)transfer->context; msc_obj->event_count++; - //If all transfers dequeued and device gone event occurred. Go to next stage + // If all transfers dequeued and device gone event occurred. Go to next stage if (msc_obj->event_count >= msc_obj->num_data_transfers + 1) { msc_obj->next_stage = TEST_STAGE_DEV_CLOSE; } @@ -101,17 +108,17 @@ static void msc_client_event_cb(const usb_host_client_event_msg_t *event_msg, vo case USB_HOST_CLIENT_EVENT_NEW_DEV: TEST_ASSERT_EQUAL(TEST_STAGE_WAIT_CONN, msc_obj->cur_stage); msc_obj->next_stage = TEST_STAGE_DEV_OPEN; - msc_obj->dev_addr_to_open = event_msg->new_dev.address; + msc_obj->dev_addr = event_msg->new_dev.address; break; case USB_HOST_CLIENT_EVENT_DEV_GONE: msc_obj->event_count++; - //If all transfers dequeued and device gone event occurred. Go to next stage + // If all transfers dequeued and device gone event occurred. Go to next stage if (msc_obj->event_count >= msc_obj->num_data_transfers + 1) { msc_obj->next_stage = TEST_STAGE_DEV_CLOSE; } break; default: - abort(); //Should never occur in this test + abort(); // Should never occur in this test break; } } @@ -119,16 +126,20 @@ static void msc_client_event_cb(const usb_host_client_event_msg_t *event_msg, vo void msc_client_async_dconn_task(void *arg) { msc_client_obj_t msc_obj; + // Initialize test params memcpy(&msc_obj.test_param, arg, sizeof(msc_client_test_param_t)); - msc_obj.cur_stage = TEST_STAGE_WAIT_CONN; - msc_obj.next_stage = TEST_STAGE_WAIT_CONN; - msc_obj.dev_addr_to_open = 0; + // Initialize MSC device info + msc_obj.dev_info = dev_msc_get_info(); + // Initialize client variables msc_obj.client_hdl = NULL; msc_obj.dev_hdl = NULL; - msc_obj.num_data_transfers = msc_obj.test_param.num_sectors_per_xfer / MOCK_MSC_SCSI_SECTOR_SIZE; + // Initialize test state + msc_obj.cur_stage = TEST_STAGE_WAIT_CONN; + msc_obj.next_stage = TEST_STAGE_WAIT_CONN; + msc_obj.num_data_transfers = msc_obj.test_param.num_sectors_per_xfer / msc_obj.dev_info->scsi_sector_size; msc_obj.event_count = 0; - //Register client + // Register client usb_host_client_config_t client_config = { .is_synchronous = false, .max_num_event_msg = MSC_ASYNC_CLIENT_MAX_EVENT_MSGS, @@ -139,11 +150,11 @@ void msc_client_async_dconn_task(void *arg) }; TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_register(&client_config, &msc_obj.client_hdl)); - //Allocate transfers - usb_transfer_t *xfer_out; //Must be large enough to contain CBW and MSC reset control transfer - usb_transfer_t *xfer_in[msc_obj.num_data_transfers]; //We manually split the data stage into multiple transfers + // Allocate transfers + usb_transfer_t *xfer_out; // Must be large enough to contain CBW and MSC reset control transfer + usb_transfer_t *xfer_in[msc_obj.num_data_transfers]; // We manually split the data stage into multiple transfers size_t xfer_out_size = MAX(sizeof(mock_msc_bulk_cbw_t), sizeof(usb_setup_packet_t)); - size_t xfer_in_size = MOCK_MSC_SCSI_SECTOR_SIZE; + size_t xfer_in_size = msc_obj.dev_info->scsi_sector_size; TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_alloc(xfer_out_size, 0, &xfer_out)); xfer_out->context = (void *)&msc_obj; for (int i = 0; i < msc_obj.num_data_transfers; i++) { @@ -151,7 +162,7 @@ void msc_client_async_dconn_task(void *arg) xfer_in[i]->context = (void *)&msc_obj; } - //Wait to be started by main thread + // Wait to be started by main thread ulTaskNotifyTake(pdTRUE, portMAX_DELAY); ESP_LOGD(MSC_CLIENT_TAG, "Starting"); @@ -170,82 +181,90 @@ void msc_client_async_dconn_task(void *arg) switch (msc_obj.cur_stage) { case TEST_STAGE_WAIT_CONN: { - //Nothing to do while waiting for connection + // Nothing to do while waiting for connection break; } case TEST_STAGE_DEV_OPEN: { ESP_LOGD(MSC_CLIENT_TAG, "Open"); - //Open the device - TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_open(msc_obj.client_hdl, msc_obj.dev_addr_to_open, &msc_obj.dev_hdl)); - //Target our transfers to the device + // Open the device + TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_open(msc_obj.client_hdl, msc_obj.dev_addr, &msc_obj.dev_hdl)); + // Target our transfers to the device xfer_out->device_handle = msc_obj.dev_hdl; xfer_out->callback = msc_reset_cbw_transfer_cb; for (int i = 0; i < msc_obj.num_data_transfers; i++) { xfer_in[i]->device_handle = msc_obj.dev_hdl; xfer_in[i]->callback = msc_data_transfer_cb; } - //Check the VID/PID of the opened device - const usb_device_desc_t *device_desc; - TEST_ASSERT_EQUAL(ESP_OK, usb_host_get_device_descriptor(msc_obj.dev_hdl, &device_desc)); - TEST_ASSERT_EQUAL(msc_obj.test_param.idVendor, device_desc->idVendor); - TEST_ASSERT_EQUAL(msc_obj.test_param.idProduct, device_desc->idProduct); - //Get device info to get device speed + // Get device info to get device speed usb_device_info_t dev_info; TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_info(msc_obj.dev_hdl, &dev_info)); msc_obj.dev_speed = dev_info.speed; - //Claim the MSC interface - TEST_ASSERT_EQUAL(ESP_OK, usb_host_interface_claim(msc_obj.client_hdl, msc_obj.dev_hdl, MOCK_MSC_SCSI_INTF_NUMBER, MOCK_MSC_SCSI_INTF_ALT_SETTING)); + // Check the device descriptor of the opened device + const usb_device_desc_t *device_desc; + const usb_device_desc_t *device_desc_ref = dev_msc_get_dev_desc(msc_obj.dev_speed); + 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_MEMORY_MESSAGE(device_desc_ref, device_desc, device_desc_ref->bLength, "Device descriptors do not match."); + // Claim the MSC interface + TEST_ASSERT_EQUAL(ESP_OK, usb_host_interface_claim(msc_obj.client_hdl, + msc_obj.dev_hdl, + msc_obj.dev_info->bInterfaceNumber, + msc_obj.dev_info->bAlternateSetting)); msc_obj.next_stage = TEST_STAGE_MSC_RESET; - skip_event_handling = true; //Need to execute TEST_STAGE_MSC_RESET + skip_event_handling = true; // Need to execute TEST_STAGE_MSC_RESET break; } case TEST_STAGE_MSC_RESET: { ESP_LOGD(MSC_CLIENT_TAG, "MSC Reset"); - //Send an MSC SCSI interface reset - MOCK_MSC_SCSI_REQ_INIT_RESET((usb_setup_packet_t *)xfer_out->data_buffer, MOCK_MSC_SCSI_INTF_NUMBER); + // Send an MSC SCSI interface reset + MOCK_MSC_SCSI_REQ_INIT_RESET((usb_setup_packet_t *)xfer_out->data_buffer, msc_obj.dev_info->bInterfaceNumber); xfer_out->num_bytes = sizeof(usb_setup_packet_t); xfer_out->bEndpointAddress = 0; TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit_control(msc_obj.client_hdl, xfer_out)); - //Next stage set from transfer callback + // Next stage set from transfer callback break; } case TEST_STAGE_MSC_CBW: { ESP_LOGD(MSC_CLIENT_TAG, "CBW"); - mock_msc_scsi_init_cbw((mock_msc_bulk_cbw_t *)xfer_out->data_buffer, true, 0, msc_obj.test_param.num_sectors_per_xfer, msc_obj.test_param.msc_scsi_xfer_tag); + mock_msc_scsi_init_cbw((mock_msc_bulk_cbw_t *)xfer_out->data_buffer, + true, + 0, + msc_obj.test_param.num_sectors_per_xfer, + msc_obj.dev_info->scsi_sector_size, + msc_obj.test_param.msc_scsi_xfer_tag); xfer_out->num_bytes = sizeof(mock_msc_bulk_cbw_t); - xfer_out->bEndpointAddress = MOCK_MSC_SCSI_BULK_OUT_EP_ADDR; + xfer_out->bEndpointAddress = msc_obj.dev_info->out_up_addr; TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_out)); - //Next stage set from transfer callback + // Next stage set from transfer callback break; } case TEST_STAGE_MSC_DATA_DCONN: { ESP_LOGD(MSC_CLIENT_TAG, "Data and disconnect"); - //Setup the Data IN transfers - const int bulk_ep_mps = (msc_obj.dev_speed == USB_SPEED_HIGH) - ? MOCK_MSC_SCSI_BULK_EP_MPS_HS - : MOCK_MSC_SCSI_BULK_EP_MPS_FS; + // Setup the Data IN transfers + const usb_ep_desc_t *in_ep_desc = dev_msc_get_in_ep_desc(msc_obj.dev_speed); + const int bulk_ep_mps = USB_EP_DESC_GET_MPS(in_ep_desc); for (int i = 0; i < msc_obj.num_data_transfers; i++) { - xfer_in[i]->num_bytes = usb_round_up_to_mps(MOCK_MSC_SCSI_SECTOR_SIZE, bulk_ep_mps); - xfer_in[i]->bEndpointAddress = MOCK_MSC_SCSI_BULK_IN_EP_ADDR; + xfer_in[i]->num_bytes = usb_round_up_to_mps(msc_obj.dev_info->scsi_sector_size, bulk_ep_mps); + xfer_in[i]->bEndpointAddress = msc_obj.dev_info->in_ep_addr; } - //Submit those transfers + // Submit those transfers for (int i = 0; i < msc_obj.num_data_transfers; i++) { TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_in[i])); } - //Trigger a disconnect + // Trigger a disconnect test_usb_set_phy_state(false, 0); - //Next stage set from transfer callback + // Next stage set from transfer callback break; } case TEST_STAGE_DEV_CLOSE: { ESP_LOGD(MSC_CLIENT_TAG, "Close"); - TEST_ASSERT_EQUAL(ESP_OK, usb_host_interface_release(msc_obj.client_hdl, msc_obj.dev_hdl, MOCK_MSC_SCSI_INTF_NUMBER)); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_interface_release(msc_obj.client_hdl, msc_obj.dev_hdl, msc_obj.dev_info->bInterfaceNumber)); TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_close(msc_obj.client_hdl, msc_obj.dev_hdl)); dconn_iter++; if (dconn_iter < TEST_DCONN_ITERATIONS) { - //Start the next test iteration by going back to TEST_STAGE_WAIT_CONN and reenabling connections + // Start the next test iteration by going back to TEST_STAGE_WAIT_CONN and reenabling connections msc_obj.next_stage = TEST_STAGE_WAIT_CONN; - skip_event_handling = true; //Need to execute TEST_STAGE_WAIT_CONN + skip_event_handling = true; // Need to execute TEST_STAGE_WAIT_CONN test_usb_set_phy_state(true, 0); } else { exit_loop = true; @@ -257,12 +276,12 @@ void msc_client_async_dconn_task(void *arg) break; } } - //Free transfers + // Free transfers TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_free(xfer_out)); for (int i = 0; i < msc_obj.num_data_transfers; i++) { TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_free(xfer_in[i])); } - //Deregister the client + // Deregister the client TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_deregister(msc_obj.client_hdl)); ESP_LOGD(MSC_CLIENT_TAG, "Done"); vTaskDelete(NULL); diff --git a/components/usb/test_apps/usb_host/main/msc_client_async_enum.c b/components/usb/test_apps/usb_host/main/msc_client_async_enum.c index 38da2aee23..e33ad0ad36 100644 --- a/components/usb/test_apps/usb_host/main/msc_client_async_enum.c +++ b/components/usb/test_apps/usb_host/main/msc_client_async_enum.c @@ -12,7 +12,8 @@ #include "freertos/task.h" #include "esp_err.h" #include "esp_log.h" -#include "test_usb_mock_msc.h" +#include "dev_msc.h" +#include "mock_msc.h" #include "test_usb_common.h" #include "msc_client.h" #include "usb/usb_host.h" @@ -61,30 +62,12 @@ static void msc_client_event_cb(const usb_host_client_event_msg_t *event_msg, vo msc_obj->dev_addr_to_open = event_msg->new_dev.address; break; default: - abort(); //Should never occur in this test + abort(); // Should never occur in this test break; } } -static void mock_msc_scsi_init_reference_ep_descriptors(const msc_client_obj_t *msc_obj) -{ - uint8_t *dest_ptr = mock_msc_scsi_config_desc; - dest_ptr += USB_CONFIG_DESC_SIZE; - dest_ptr += USB_INTF_DESC_SIZE; - - const usb_ep_desc_t en_desc_in = (msc_obj->dev_speed == USB_SPEED_HIGH) - ? mock_msc_scsi_bulk_in_ep_desc_hs - : mock_msc_scsi_bulk_in_ep_desc_fs; - const usb_ep_desc_t en_desc_out = (msc_obj->dev_speed == USB_SPEED_HIGH) - ? mock_msc_scsi_bulk_out_ep_desc_hs - : mock_msc_scsi_bulk_out_ep_desc_fs; - - memcpy(dest_ptr, (void*)&en_desc_in, sizeof(en_desc_in)); - dest_ptr += USB_EP_DESC_SIZE; - memcpy(dest_ptr, (void*)&en_desc_out, sizeof(en_desc_out)); -} - void msc_client_async_enum_task(void *arg) { msc_client_obj_t msc_obj; @@ -94,7 +77,7 @@ void msc_client_async_enum_task(void *arg) msc_obj.dev_addr_to_open = 0; msc_obj.dev_hdl = NULL; - //Register client + // Register client usb_host_client_config_t client_config = { .is_synchronous = false, .max_num_event_msg = MSC_ASYNC_CLIENT_MAX_EVENT_MSGS, @@ -105,7 +88,7 @@ void msc_client_async_enum_task(void *arg) }; TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_register(&client_config, &msc_obj.client_hdl)); - //Wait to be started by main thread + // Wait to be started by main thread ulTaskNotifyTake(pdTRUE, portMAX_DELAY); ESP_LOGD(MSC_CLIENT_TAG, "Starting"); @@ -124,61 +107,60 @@ void msc_client_async_enum_task(void *arg) switch (msc_obj.cur_stage) { case TEST_STAGE_WAIT_CONN: { - //Wait for connection, nothing to do + // Wait for connection, nothing to do break; } case TEST_STAGE_DEV_OPEN: { ESP_LOGD(MSC_CLIENT_TAG, "Open"); - //Open the device + // Open the device TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_open(msc_obj.client_hdl, msc_obj.dev_addr_to_open, &msc_obj.dev_hdl)); msc_obj.next_stage = TEST_STAGE_CHECK_DEV_DESC; - //Get device info to get device speed + // Get device info to get device speed usb_device_info_t dev_info; TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_info(msc_obj.dev_hdl, &dev_info)); msc_obj.dev_speed = dev_info.speed; - mock_msc_scsi_init_reference_ep_descriptors(&msc_obj); - skip_event_handling = true; //Need to execute TEST_STAGE_CHECK_DEV_DESC + skip_event_handling = true; // Need to execute TEST_STAGE_CHECK_DEV_DESC break; } case TEST_STAGE_CHECK_DEV_DESC: { - //Check the device descriptor + // Check the device descriptor const usb_device_desc_t *device_desc; - const usb_device_desc_t *device_desc_ref = &mock_msc_scsi_dev_desc; + const usb_device_desc_t *device_desc_ref = dev_msc_get_dev_desc(msc_obj.dev_speed); 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_MEMORY_MESSAGE(device_desc_ref, device_desc, device_desc_ref->bLength, "Device descriptors do not match."); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(device_desc_ref, device_desc, sizeof(usb_device_desc_t), "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 + skip_event_handling = true; // Need to execute TEST_STAGE_CHECK_CONFIG_DESC break; } case TEST_STAGE_CHECK_CONFIG_DESC: { - //Check the configuration descriptor + // Check the configuration descriptor 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; + const usb_config_desc_t *config_desc_ref = dev_msc_get_config_desc(msc_obj.dev_speed); TEST_ASSERT_EQUAL(ESP_OK, usb_host_get_active_config_descriptor(msc_obj.dev_hdl, &config_desc)); - 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"); + TEST_ASSERT_EQUAL_MESSAGE(config_desc_ref->wTotalLength, config_desc->wTotalLength, "Incorrect length of CFG descriptor"); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(config_desc_ref, config_desc, sizeof(usb_config_desc_t), "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 + skip_event_handling = true; // Need to execute TEST_STAGE_CHECK_STR_DESC break; } case TEST_STAGE_CHECK_STR_DESC: { usb_device_info_t dev_info; TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_info(msc_obj.dev_hdl, &dev_info)); - //Check manufacturer string descriptors - const usb_str_desc_t *manu_str_desc_ref = (const usb_str_desc_t *)mock_msc_scsi_str_desc_manu; - const usb_str_desc_t *product_str_desc_ref = (const usb_str_desc_t *)mock_msc_scsi_str_desc_prod; - const usb_str_desc_t *ser_num_str_desc_ref = (const usb_str_desc_t *)mock_msc_scsi_str_desc_ser_num; + // Check manufacturer string descriptors + const usb_str_desc_t *manu_str_desc_ref = dev_msc_get_str_desc_manu(); + const usb_str_desc_t *product_str_desc_ref = dev_msc_get_str_desc_prod(); + const usb_str_desc_t *ser_num_str_desc_ref = dev_msc_get_str_desc_ser(); 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_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 + 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 + skip_event_handling = true; // Need to execute TEST_STAGE_DEV_CLOSE break; } @@ -187,11 +169,11 @@ void msc_client_async_enum_task(void *arg) TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_close(msc_obj.client_hdl, msc_obj.dev_hdl)); enum_iter++; if (enum_iter < TEST_ENUM_ITERATIONS) { - //Start the next test iteration by disconnecting the device, then going back to TEST_STAGE_WAIT_CONN stage + // Start the next test iteration by disconnecting the device, then going back to TEST_STAGE_WAIT_CONN stage test_usb_set_phy_state(false, 0); test_usb_set_phy_state(true, 0); msc_obj.next_stage = TEST_STAGE_WAIT_CONN; - skip_event_handling = true; //Need to execute TEST_STAGE_WAIT_CONN + skip_event_handling = true; // Need to execute TEST_STAGE_WAIT_CONN } else { exit_loop = true; } @@ -202,7 +184,7 @@ void msc_client_async_enum_task(void *arg) break; } } - //Free transfers and deregister the client + // Free transfers and deregister the client TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_deregister(msc_obj.client_hdl)); ESP_LOGD(MSC_CLIENT_TAG, "Done"); vTaskDelete(NULL); diff --git a/components/usb/test_apps/usb_host/main/msc_client_async_seq.c b/components/usb/test_apps/usb_host/main/msc_client_async_seq.c index 69187ea583..192012fb34 100644 --- a/components/usb/test_apps/usb_host/main/msc_client_async_seq.c +++ b/components/usb/test_apps/usb_host/main/msc_client_async_seq.c @@ -13,7 +13,8 @@ #include "esp_err.h" #include "esp_log.h" #include "test_usb_common.h" -#include "test_usb_mock_msc.h" +#include "mock_msc.h" +#include "dev_msc.h" #include "msc_client.h" #include "usb/usb_host.h" #include "unity.h" @@ -46,14 +47,19 @@ typedef enum { } test_stage_t; typedef struct { + // Test parameters msc_client_test_param_t test_param; - test_stage_t cur_stage; - test_stage_t next_stage; - uint8_t dev_addr_to_open; + // MSC device info + const dev_msc_info_t *dev_info; + usb_speed_t dev_speed; + uint8_t dev_addr; + // Client variables usb_host_client_handle_t client_hdl; usb_device_handle_t dev_hdl; + // Test state + test_stage_t cur_stage; + test_stage_t next_stage; int num_sectors_read; - usb_speed_t dev_speed; } msc_client_obj_t; static void msc_transfer_cb(usb_transfer_t *transfer) @@ -61,28 +67,28 @@ static void msc_transfer_cb(usb_transfer_t *transfer) msc_client_obj_t *msc_obj = (msc_client_obj_t *)transfer->context; switch (msc_obj->cur_stage) { case TEST_STAGE_MSC_RESET: { - //Check MSC SCSI interface reset + // Check MSC SCSI interface reset 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 + // Check MSC SCSI CBW transfer 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 + // Check MSC SCSI data IN transfer 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); + TEST_ASSERT_EQUAL(msc_obj->dev_info->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 + // Check MSC SCSI CSW transfer 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; @@ -107,10 +113,10 @@ static void msc_client_event_cb(const usb_host_client_event_msg_t *event_msg, vo case USB_HOST_CLIENT_EVENT_NEW_DEV: TEST_ASSERT_EQUAL(TEST_STAGE_WAIT_CONN, msc_obj->cur_stage); msc_obj->next_stage = TEST_STAGE_DEV_OPEN; - msc_obj->dev_addr_to_open = event_msg->new_dev.address; + msc_obj->dev_addr = event_msg->new_dev.address; break; default: - abort(); //Should never occur in this test + abort(); // Should never occur in this test break; } @@ -119,15 +125,20 @@ static void msc_client_event_cb(const usb_host_client_event_msg_t *event_msg, vo void msc_client_async_seq_task(void *arg) { msc_client_obj_t msc_obj; + // Initialize test params memcpy(&msc_obj.test_param, arg, sizeof(msc_client_test_param_t)); + // Initialize MSC device info + msc_obj.dev_info = dev_msc_get_info(); + // Initialize client variables + msc_obj.client_hdl = NULL; + msc_obj.dev_hdl = NULL; + // Initialize test state msc_obj.cur_stage = TEST_STAGE_WAIT_CONN; msc_obj.next_stage = TEST_STAGE_WAIT_CONN; - msc_obj.client_hdl = NULL; - msc_obj.dev_addr_to_open = 0; - msc_obj.dev_hdl = NULL; + msc_obj.dev_addr = 0; msc_obj.num_sectors_read = 0; - //Register client + // Register client usb_host_client_config_t client_config = { .is_synchronous = false, .max_num_event_msg = MSC_ASYNC_CLIENT_MAX_EVENT_MSGS, @@ -138,19 +149,12 @@ void msc_client_async_seq_task(void *arg) }; TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_register(&client_config, &msc_obj.client_hdl)); - //Allocate transfers - usb_transfer_t *xfer_out = NULL; //Must be large enough to contain CBW and MSC reset control transfer - usb_transfer_t *xfer_in = NULL; //Must be large enough to contain CSW and Data - size_t out_worst_case_size = MAX(sizeof(mock_msc_bulk_cbw_t), sizeof(usb_setup_packet_t)); - size_t in_worst_case_size = usb_round_up_to_mps(MAX(MOCK_MSC_SCSI_SECTOR_SIZE * msc_obj.test_param.num_sectors_per_xfer, sizeof(mock_msc_bulk_csw_t)), MOCK_MSC_SCSI_BULK_EP_MPS_HS); - TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_alloc(out_worst_case_size, 0, &xfer_out)); - TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_alloc(in_worst_case_size, 0, &xfer_in)); - xfer_out->callback = msc_transfer_cb; - xfer_in->callback = msc_transfer_cb; - xfer_out->context = (void *)&msc_obj; - xfer_in->context = (void *)&msc_obj; + // IN MPS and transfers to be set/allocated later (after device connects and MPS is determined) + int in_ep_mps = 0; + usb_transfer_t *xfer_in = NULL; + usb_transfer_t *xfer_out = NULL; - //Wait to be started by main thread + // Wait to be started by main thread ulTaskNotifyTake(pdTRUE, portMAX_DELAY); ESP_LOGD(MSC_CLIENT_TAG, "Starting"); @@ -169,78 +173,100 @@ void msc_client_async_seq_task(void *arg) switch (msc_obj.cur_stage) { case TEST_STAGE_DEV_OPEN: { ESP_LOGD(MSC_CLIENT_TAG, "Open"); - //Open the device - TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_open(msc_obj.client_hdl, msc_obj.dev_addr_to_open, &msc_obj.dev_hdl)); - //Target our transfers to the device - xfer_out->device_handle = msc_obj.dev_hdl; - xfer_in->device_handle = msc_obj.dev_hdl; - //Check the VID/PID of the opened device - const usb_device_desc_t *device_desc; - TEST_ASSERT_EQUAL(ESP_OK, usb_host_get_device_descriptor(msc_obj.dev_hdl, &device_desc)); - TEST_ASSERT_EQUAL(msc_obj.test_param.idVendor, device_desc->idVendor); - TEST_ASSERT_EQUAL(msc_obj.test_param.idProduct, device_desc->idProduct); - //Get device info to get device speed + // Open the device + TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_open(msc_obj.client_hdl, msc_obj.dev_addr, &msc_obj.dev_hdl)); + // Get device info to get device speed usb_device_info_t dev_info; TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_info(msc_obj.dev_hdl, &dev_info)); msc_obj.dev_speed = dev_info.speed; - //Claim the MSC interface - TEST_ASSERT_EQUAL(ESP_OK, usb_host_interface_claim(msc_obj.client_hdl, msc_obj.dev_hdl, MOCK_MSC_SCSI_INTF_NUMBER, MOCK_MSC_SCSI_INTF_ALT_SETTING)); + // Check that the device descriptor matches our expected MSC device + const usb_device_desc_t *device_desc; + const usb_device_desc_t *device_desc_ref = dev_msc_get_dev_desc(msc_obj.dev_speed); + 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_MEMORY_MESSAGE(device_desc_ref, device_desc, sizeof(usb_device_desc_t), "Device descriptors do not match."); + // Claim the MSC interface + TEST_ASSERT_EQUAL(ESP_OK, usb_host_interface_claim(msc_obj.client_hdl, + msc_obj.dev_hdl, + msc_obj.dev_info->bInterfaceNumber, + msc_obj.dev_info->bAlternateSetting)); + /* + Allocate transfers + + IN transfer must be large enough to contain CSW and Data + OUT transfer must be large enough to contain CBW and MSC reset control transfer + */ + const usb_ep_desc_t *in_ep_desc = dev_msc_get_in_ep_desc(msc_obj.dev_speed); + in_ep_mps = USB_EP_DESC_GET_MPS(in_ep_desc); + const size_t in_worst_case_size = usb_round_up_to_mps(MAX(msc_obj.dev_info->scsi_sector_size * msc_obj.test_param.num_sectors_per_xfer, + sizeof(mock_msc_bulk_csw_t)), + in_ep_mps); + const size_t out_worst_case_size = MAX(sizeof(mock_msc_bulk_cbw_t), sizeof(usb_setup_packet_t)); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_alloc(out_worst_case_size, 0, &xfer_out)); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_alloc(in_worst_case_size, 0, &xfer_in)); + xfer_out->callback = msc_transfer_cb; + xfer_in->callback = msc_transfer_cb; + xfer_out->context = (void *)&msc_obj; + xfer_in->context = (void *)&msc_obj; + // Target our transfers to the device + xfer_out->device_handle = msc_obj.dev_hdl; + xfer_in->device_handle = msc_obj.dev_hdl; + // Set next stage msc_obj.next_stage = TEST_STAGE_MSC_RESET; - skip_event_handling = true; //Need to execute TEST_STAGE_MSC_RESET + skip_event_handling = true; // Need to execute TEST_STAGE_MSC_RESET break; } case TEST_STAGE_MSC_RESET: { ESP_LOGD(MSC_CLIENT_TAG, "MSC Reset"); - //Send an MSC SCSI interface reset - MOCK_MSC_SCSI_REQ_INIT_RESET((usb_setup_packet_t *)xfer_out->data_buffer, MOCK_MSC_SCSI_INTF_NUMBER); + // Send an MSC SCSI interface reset + MOCK_MSC_SCSI_REQ_INIT_RESET((usb_setup_packet_t *)xfer_out->data_buffer, msc_obj.dev_info->bInterfaceNumber); xfer_out->num_bytes = sizeof(usb_setup_packet_t); xfer_out->bEndpointAddress = 0; TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit_control(msc_obj.client_hdl, xfer_out)); - //Test that an inflight control transfer cannot be resubmitted + // Test that an inflight control transfer cannot be resubmitted TEST_ASSERT_EQUAL(ESP_ERR_NOT_FINISHED, usb_host_transfer_submit_control(msc_obj.client_hdl, xfer_out)); - //Next stage set from transfer callback + // Next stage set from transfer callback break; } case TEST_STAGE_MSC_CBW: { ESP_LOGD(MSC_CLIENT_TAG, "CBW"); - mock_msc_scsi_init_cbw((mock_msc_bulk_cbw_t *)xfer_out->data_buffer, true, msc_obj.next_stage, msc_obj.test_param.num_sectors_per_xfer, msc_obj.test_param.msc_scsi_xfer_tag); + mock_msc_scsi_init_cbw((mock_msc_bulk_cbw_t *)xfer_out->data_buffer, + true, + msc_obj.next_stage, + msc_obj.test_param.num_sectors_per_xfer, + msc_obj.dev_info->scsi_sector_size, + msc_obj.test_param.msc_scsi_xfer_tag); xfer_out->num_bytes = sizeof(mock_msc_bulk_cbw_t); - xfer_out->bEndpointAddress = MOCK_MSC_SCSI_BULK_OUT_EP_ADDR; + xfer_out->bEndpointAddress = msc_obj.dev_info->out_up_addr; TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_out)); - //Test that an inflight transfer cannot be resubmitted + // Test that an inflight transfer cannot be resubmitted TEST_ASSERT_EQUAL(ESP_ERR_NOT_FINISHED, usb_host_transfer_submit(xfer_out)); - //Next stage set from transfer callback + // Next stage set from transfer callback break; } case TEST_STAGE_MSC_DATA: { ESP_LOGD(MSC_CLIENT_TAG, "Data"); - const int bulk_ep_mps = (msc_obj.dev_speed == USB_SPEED_HIGH) - ? MOCK_MSC_SCSI_BULK_EP_MPS_HS - : MOCK_MSC_SCSI_BULK_EP_MPS_FS; - xfer_in->num_bytes = usb_round_up_to_mps(MOCK_MSC_SCSI_SECTOR_SIZE * msc_obj.test_param.num_sectors_per_xfer, bulk_ep_mps); - xfer_in->bEndpointAddress = MOCK_MSC_SCSI_BULK_IN_EP_ADDR; + xfer_in->num_bytes = usb_round_up_to_mps(msc_obj.dev_info->scsi_sector_size * msc_obj.test_param.num_sectors_per_xfer, in_ep_mps); + xfer_in->bEndpointAddress = msc_obj.dev_info->in_ep_addr; TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_in)); - //Test that an inflight transfer cannot be resubmitted + // Test that an inflight transfer cannot be resubmitted TEST_ASSERT_EQUAL(ESP_ERR_NOT_FINISHED, usb_host_transfer_submit(xfer_in)); - //Next stage set from transfer callback + // Next stage set from transfer callback break; } case TEST_STAGE_MSC_CSW: { ESP_LOGD(MSC_CLIENT_TAG, "CSW"); - const int bulk_ep_mps = (msc_obj.dev_speed == USB_SPEED_HIGH) - ? MOCK_MSC_SCSI_BULK_EP_MPS_HS - : MOCK_MSC_SCSI_BULK_EP_MPS_FS; - xfer_in->num_bytes = usb_round_up_to_mps(sizeof(mock_msc_bulk_csw_t), bulk_ep_mps); - xfer_in->bEndpointAddress = MOCK_MSC_SCSI_BULK_IN_EP_ADDR; + xfer_in->num_bytes = usb_round_up_to_mps(sizeof(mock_msc_bulk_csw_t), in_ep_mps); + xfer_in->bEndpointAddress = msc_obj.dev_info->in_ep_addr; TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_in)); - //Test that an inflight transfer cannot be resubmitted + // Test that an inflight transfer cannot be resubmitted TEST_ASSERT_EQUAL(ESP_ERR_NOT_FINISHED, usb_host_transfer_submit(xfer_in)); - //Next stage set from transfer callback + // Next stage set from transfer callback break; } case TEST_STAGE_DEV_CLOSE: { ESP_LOGD(MSC_CLIENT_TAG, "Close"); - TEST_ASSERT_EQUAL(ESP_OK, usb_host_interface_release(msc_obj.client_hdl, msc_obj.dev_hdl, MOCK_MSC_SCSI_INTF_NUMBER)); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_interface_release(msc_obj.client_hdl, msc_obj.dev_hdl, msc_obj.dev_info->bInterfaceNumber)); TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_close(msc_obj.client_hdl, msc_obj.dev_hdl)); exit_loop = true; break; @@ -250,7 +276,7 @@ void msc_client_async_seq_task(void *arg) break; } } - //Free transfers and deregister the client + // Free transfers and deregister the client TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_free(xfer_out)); TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_free(xfer_in)); TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_deregister(msc_obj.client_hdl)); diff --git a/components/usb/test_apps/usb_host/main/test_app_main.c b/components/usb/test_apps/usb_host/main/test_app_main.c index 6a23633595..93e2510374 100644 --- a/components/usb/test_apps/usb_host/main/test_app_main.c +++ b/components/usb/test_apps/usb_host/main/test_app_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -7,21 +7,20 @@ #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 "dev_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 + dev_msc_init(); + 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 + .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)); @@ -30,11 +29,11 @@ void setUp(void) void tearDown(void) { - //Short delay to allow task to be cleaned up + // Short delay to allow task to be cleaned up vTaskDelay(10); - //Clean up USB Host + // Clean up USB Host ESP_ERROR_CHECK(usb_host_uninstall()); - test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing + test_usb_deinit_phy(); // Deinitialize the internal USB PHY after testing unity_utils_evaluate_leaks(); } diff --git a/components/usb/test_apps/usb_host/main/test_usb_host_async.c b/components/usb/test_apps/usb_host/main/test_usb_host_async.c index 98b978acf9..c7329d91fa 100644 --- a/components/usb/test_apps/usb_host/main/test_usb_host_async.c +++ b/components/usb/test_apps/usb_host/main/test_usb_host_async.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,7 +11,7 @@ #include "esp_err.h" #include "esp_intr_alloc.h" #include "test_usb_common.h" -#include "test_usb_mock_msc.h" +#include "dev_msc.h" #include "msc_client.h" #include "ctrl_client.h" #include "usb/usb_host.h" @@ -46,22 +46,20 @@ Procedure: TEST_CASE("Test USB Host async client (single client)", "[usb_host][full_speed][high_speed]") { - //Create task to run client that communicates with MSC SCSI interface + // 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, .num_sectors_per_xfer = TEST_MSC_NUM_SECTORS_PER_XFER, .msc_scsi_xfer_tag = TEST_MSC_SCSI_TAG, - .idVendor = MOCK_MSC_SCSI_DEV_ID_VENDOR, - .idProduct = MOCK_MSC_SCSI_DEV_ID_PRODUCT, }; 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 + // Start the task xTaskNotifyGive(task_hdl); while (1) { - //Start handling system events + // Start handling system events uint32_t event_flags; usb_host_lib_handle_events(portMAX_DELAY, &event_flags); if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) { @@ -96,34 +94,30 @@ Procedure: */ TEST_CASE("Test USB Host async client (multi client)", "[usb_host][full_speed][high_speed]") { - //Create task to run the MSC client + // Create task to run the MSC client msc_client_test_param_t msc_params = { .num_sectors_to_read = TEST_MSC_NUM_SECTORS_TOTAL, .num_sectors_per_xfer = TEST_MSC_NUM_SECTORS_PER_XFER, .msc_scsi_xfer_tag = TEST_MSC_SCSI_TAG, - .idVendor = MOCK_MSC_SCSI_DEV_ID_VENDOR, - .idProduct = MOCK_MSC_SCSI_DEV_ID_PRODUCT, }; 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 + // Create task a control transfer client ctrl_client_test_param_t ctrl_params = { .num_ctrl_xfer_to_send = TEST_CTRL_NUM_TRANSFERS, - .idVendor = MOCK_MSC_SCSI_DEV_ID_VENDOR, - .idProduct = MOCK_MSC_SCSI_DEV_ID_PRODUCT, }; 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 + // Start both tasks xTaskNotifyGive(msc_task_hdl); xTaskNotifyGive(ctrl_task_hdl); while (1) { - //Start handling system events + // Start handling system events uint32_t event_flags; usb_host_lib_handle_events(portMAX_DELAY, &event_flags); if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) { @@ -188,7 +182,7 @@ 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][full_speed][low_speed]") { - //Register two clients + // Register two clients client_test_stage_t client0_stage = CLIENT_TEST_STAGE_NONE; client_test_stage_t client1_stage = CLIENT_TEST_STAGE_NONE; @@ -206,7 +200,7 @@ TEST_CASE("Test USB Host async API", "[usb_host][full_speed][low_speed]") client_config.async.callback_arg = (void *)&client1_stage; TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_register(&client_config, &client1_hdl)); - //Wait until the device connects and the clients receive the event + // Wait until the device connects and the clients receive the event while (!(client0_stage == CLIENT_TEST_STAGE_CONN && client1_stage == CLIENT_TEST_STAGE_CONN)) { usb_host_lib_handle_events(0, NULL); usb_host_client_handle_events(client0_hdl, 0); @@ -214,35 +208,49 @@ TEST_CASE("Test USB Host async API", "[usb_host][full_speed][low_speed]") vTaskDelay(pdMS_TO_TICKS(10)); } - //Check that both clients can open the device + // 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_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_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)); - //Check that the device cannot be opened again by the same client + // Check that the device cannot be opened again by the same client + const dev_msc_info_t *dev_info = dev_msc_get_info(); 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)); + // Check that both clients cannot claim the same interface + TEST_ASSERT_EQUAL(ESP_OK, usb_host_interface_claim(client0_hdl, + client0_dev_hdl, + dev_info->bInterfaceNumber, + dev_info->bAlternateSetting)); + TEST_ASSERT_NOT_EQUAL(ESP_OK, usb_host_interface_claim(client1_hdl, + client1_dev_hdl, + dev_info->bInterfaceNumber, + dev_info->bAlternateSetting)); + // 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, + dev_info->bInterfaceNumber, + dev_info->bAlternateSetting)); 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 - TEST_ASSERT_NOT_EQUAL(ESP_OK, usb_host_interface_release(client0_hdl, client0_dev_hdl, MOCK_MSC_SCSI_INTF_NUMBER)); + // Check that client0 can release the interface + TEST_ASSERT_EQUAL(ESP_OK, usb_host_interface_release(client0_hdl, + client0_dev_hdl, + dev_info->bInterfaceNumber)); + // Check that client0 cannot release interface it has not claimed + TEST_ASSERT_NOT_EQUAL(ESP_OK, usb_host_interface_release(client0_hdl, + client0_dev_hdl, + dev_info->bInterfaceNumber)); - //Wait until the device disconnects and the clients receive the event + // Wait until the device disconnects and the clients receive the event test_usb_set_phy_state(false, 0); while (!(client0_stage == CLIENT_TEST_STAGE_DCONN && client1_stage == CLIENT_TEST_STAGE_DCONN)) { usb_host_lib_handle_events(0, NULL); @@ -254,7 +262,7 @@ TEST_CASE("Test USB Host async API", "[usb_host][full_speed][low_speed]") 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)); - //Deregister the clients + // Deregister the clients TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_deregister(client0_hdl)); TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_deregister(client1_hdl)); diff --git a/components/usb/test_apps/usb_host/main/test_usb_host_plugging.c b/components/usb/test_apps/usb_host/main/test_usb_host_plugging.c index 5851988f42..263898c0de 100644 --- a/components/usb/test_apps/usb_host/main/test_usb_host_plugging.c +++ b/components/usb/test_apps/usb_host/main/test_usb_host_plugging.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,7 +10,8 @@ #include "esp_err.h" #include "esp_intr_alloc.h" #include "test_usb_common.h" -#include "test_usb_mock_msc.h" +#include "mock_msc.h" +#include "dev_msc.h" #include "msc_client.h" #include "ctrl_client.h" #include "usb/usb_host.h" @@ -38,24 +39,24 @@ TEST_CASE("Test USB Host sudden disconnection (no client)", "[usb_host][full_spe bool connected = false; int dconn_iter = 0; while (1) { - //Start handling system events + // Start handling system events uint32_t event_flags; usb_host_lib_handle_events(portMAX_DELAY, &event_flags); if (!connected) { usb_host_lib_info_t lib_info; TEST_ASSERT_EQUAL(ESP_OK, usb_host_lib_info(&lib_info)); if (lib_info.num_devices == 1) { - //We've just connected. Trigger a disconnect + // We've just connected. Trigger a disconnect connected = true; printf("Forcing Sudden Disconnect\n"); test_usb_set_phy_state(false, 0); } } if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) { - //The device has disconnected and it's disconnection has been handled + // The device has disconnected and it's disconnection has been handled printf("Dconn iter %d done\n", dconn_iter); if (++dconn_iter < TEST_DCONN_NO_CLIENT_ITERATIONS) { - //Start next iteration + // Start next iteration connected = false; test_usb_set_phy_state(true, 0); } else { @@ -83,23 +84,22 @@ Procedure: TEST_CASE("Test USB Host sudden disconnection (single client)", "[usb_host][full_speed]") { - //Create task to run client that communicates with MSC SCSI interface + // Create task to run client that communicates with MSC SCSI interface + const dev_msc_info_t *dev_info = dev_msc_get_info(); msc_client_test_param_t params = { - .num_sectors_to_read = 1, //Unused by disconnect MSC client - .num_sectors_per_xfer = TEST_FORCE_DCONN_NUM_TRANSFERS * MOCK_MSC_SCSI_SECTOR_SIZE, + .num_sectors_to_read = 1, // Unused by disconnect MSC client + .num_sectors_per_xfer = TEST_FORCE_DCONN_NUM_TRANSFERS * dev_info->scsi_sector_size, .msc_scsi_xfer_tag = TEST_MSC_SCSI_TAG, - .idVendor = MOCK_MSC_SCSI_DEV_ID_VENDOR, - .idProduct = MOCK_MSC_SCSI_DEV_ID_PRODUCT, }; TaskHandle_t task_hdl; xTaskCreatePinnedToCore(msc_client_async_dconn_task, "async", 4096, (void *)¶ms, 2, &task_hdl, 0); - //Start the task + // Start the task xTaskNotifyGive(task_hdl); bool all_clients_gone = false; bool all_dev_free = false; while (!all_clients_gone || !all_dev_free) { - //Start handling system events + // Start handling system events uint32_t event_flags; usb_host_lib_handle_events(portMAX_DELAY, &event_flags); if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) { @@ -133,16 +133,16 @@ Procedure: TEST_CASE("Test USB Host enumeration", "[usb_host][full_speed]") { - //Create task to run client that checks the enumeration of the device + // 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); - //Start the task + // Start the task xTaskNotifyGive(task_hdl); bool all_clients_gone = false; bool all_dev_free = false; while (!all_clients_gone || !all_dev_free) { - //Start handling system events + // Start handling system events uint32_t event_flags; usb_host_lib_handle_events(portMAX_DELAY, &event_flags); if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {