Initial project setup

This commit is contained in:
2025-12-13 11:59:11 +02:00
commit 3218e6039f
2176 changed files with 355321 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
set(COMPONENTS main)
project(test_app_vendor_specific)

View File

@@ -0,0 +1,4 @@
idf_component_register(SRC_DIRS .
INCLUDE_DIRS .
REQUIRES unity
WHOLE_ARCHIVE)

View File

@@ -0,0 +1,5 @@
## IDF Component Manager Manifest File
dependencies:
espressif/esp_tinyusb:
version: "*"
override_path: "../../../"

View File

@@ -0,0 +1,48 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#include "unity.h"
#include "unity_test_runner.h"
void app_main(void)
{
/*
_ _ _
| | (_) | |
___ ___ _ __ | |_ _ _ __ _ _ _ _ ___| |__
/ _ \/ __| '_ \| __| | '_ \| | | | | | / __| '_ \
| __/\__ \ |_) | |_| | | | | |_| | |_| \__ \ |_) |
\___||___/ .__/ \__|_|_| |_|\__, |\__,_|___/_.__/
| |______ __/ |
|_|______| |___/
_____ _____ _____ _____
|_ _| ___/ ___|_ _|
| | | |__ \ `--. | |
| | | __| `--. \ | |
| | | |___/\__/ / | |
\_/ \____/\____/ \_/
*/
printf(" _ _ _ \n");
printf(" | | (_) | | \n");
printf(" ___ ___ _ __ | |_ _ _ __ _ _ _ _ ___| |__ \n");
printf(" / _ \\/ __| '_ \\| __| | '_ \\| | | | | | / __| '_ \\ \n");
printf("| __/\\__ \\ |_) | |_| | | | | |_| | |_| \\__ \\ |_) |\n");
printf(" \\___||___/ .__/ \\__|_|_| |_|\\__, |\\__,_|___/_.__/ \n");
printf(" | |______ __/ | \n");
printf(" |_|______| |___/ \n");
printf(" _____ _____ _____ _____ \n");
printf("|_ _| ___/ ___|_ _| \n");
printf(" | | | |__ \\ `--. | | \n");
printf(" | | | __| `--. \\ | | \n");
printf(" | | | |___/\\__/ / | | \n");
printf(" \\_/ \\____/\\____/ \\_/ \n");
// We don't check memory leaks here because we cannot uninstall TinyUSB yet
unity_run_menu();
}

View File

@@ -0,0 +1,71 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/soc_caps.h"
#if SOC_USB_OTG_SUPPORTED
#include <stdio.h>
#include <string.h>
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_err.h"
#include "unity.h"
#include "tinyusb.h"
static const char *TAG = "vendor_test";
char buffer_in[64];
#if (TUSB_VERSION_MINOR >= 17)
void tud_vendor_rx_cb(uint8_t itf, uint8_t const *buffer, uint16_t bufsize)
#else
void tud_vendor_rx_cb(uint8_t itf)
#endif // TUSB_VERSION_MINOR
{
ESP_LOGI(TAG, "tud_vendor_rx_cb(itf=%d)", itf);
int available = tud_vendor_n_available(itf);
int read = tud_vendor_n_read(itf, buffer_in, available);
ESP_LOGI(TAG, "actual read: %d. buffer message: %s", read, buffer_in);
}
// Invoked when a control transfer occurred on an interface of this class
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
// return false to stall control endpoint (e.g unsupported request)
bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request)
{
// nothing to with DATA & ACK stage
if (stage != CONTROL_STAGE_SETUP) {
return true;
}
// stall unknown request
return false;
}
/**
* @brief TinyUSB Vendor specific testcase
*/
TEST_CASE("tinyusb_vendor", "[esp_tinyusb][vendor]")
{
// Install TinyUSB driver
const tinyusb_config_t tusb_cfg = {
.external_phy = false,
.device_descriptor = NULL,
#if (TUD_OPT_HIGH_SPEED)
.fs_configuration_descriptor = NULL,
.hs_configuration_descriptor = NULL,
.qualifier_descriptor = NULL,
#else
.configuration_descriptor = NULL,
#endif // TUD_OPT_HIGH_SPEED
};
TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg));
}
#endif

View File

@@ -0,0 +1,96 @@
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import pytest
from pytest_embedded_idf.dut import IdfDut
import usb.core
import usb.util
from time import sleep
def find_interface_by_index(device, interface_index):
'''
Function to find the interface by index
'''
for cfg in device:
for intf in cfg:
if intf.bInterfaceNumber == interface_index:
return intf
return None
def send_data_to_intf(VID, PID, interface_index):
'''
Find a device, its interface and dual BULK endpoints
Send some data to it
'''
# Find the USB device by VID and PID
dev = usb.core.find(idVendor=VID, idProduct=PID)
if dev is None:
raise ValueError("Device not found")
# Find the interface by index
intf = find_interface_by_index(dev, interface_index)
if intf is None:
raise ValueError(f"Interface with index {interface_index} not found")
if intf:
def ep_read(len):
try:
return ep_in.read(len, 100)
except:
return None
def ep_write(buf):
try:
ep_out.write(buf, 100)
except:
pass
maximum_packet_size = 64
ep_in = usb.util.find_descriptor(intf, custom_match = \
lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN)
ep_out = usb.util.find_descriptor(intf, custom_match = \
lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT)
#print(ep_in)
#print(ep_out)
buf = "IF{}\n".format(interface_index).encode('utf-8')
ep_write(bytes(buf))
ep_read(maximum_packet_size)
else:
print("NOT found")
@pytest.mark.esp32s2
@pytest.mark.esp32s3
@pytest.mark.esp32p4
#@pytest.mark.usb_device Disable in CI, for now, not possible to run this test in Docker container
def test_usb_device_vendor(dut: IdfDut) -> None:
'''
Running the test locally:
1. Build the test app for your DUT
2. Connect you DUT to your test runner (local machine) with USB port and flashing port
3. Run `pytest --target esp32s3`
Important note: On Windows you must manually assign a driver the device, otherwise it will never be configured.
On Linux this is automatic
Test procedure:
1. Run the test on the DUT
2. Expect 2 Vendor specific interfaces in the system
3. Send some data to it, check log output
'''
dut.run_all_single_board_cases(group='vendor')
sleep(2) # Wait until the device is enumerated
VID = 0x303A # Replace with your device's Vendor ID
PID = 0x4040 # Replace with your device's Product ID
send_data_to_intf(VID, PID, 0)
dut.expect_exact('vendor_test: actual read: 4. buffer message: IF0')
send_data_to_intf(VID, PID, 1)
dut.expect_exact('vendor_test: actual read: 4. buffer message: IF1')

View File

@@ -0,0 +1,15 @@
# Configure TinyUSB, it will be used to mock USB devices
CONFIG_TINYUSB_VENDOR_COUNT=2
# Disable watchdogs, they'd get triggered during unity interactive menu
CONFIG_ESP_INT_WDT=n
CONFIG_ESP_TASK_WDT=n
# Run-time checks of Heap and Stack
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
CONFIG_COMPILER_STACK_CHECK_MODE_STRONG=y
CONFIG_COMPILER_STACK_CHECK=y
CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL=y
CONFIG_COMPILER_CXX_EXCEPTIONS=y