Skip to content

Commit

Permalink
tests: usb: add test for new USB device support
Browse files Browse the repository at this point in the history
This is initial patch to add tests for new USB device support.
The test uses USB host support and virtual USB bus by default,
but should work on real hardware as well. For now, only the
Get Configuration and Set Interface requests are tested by default.
More tests will follow.

Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
  • Loading branch information
jfischer-no authored and jhedberg committed Oct 1, 2023
1 parent d18cb6c commit ed7d56f
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 0 deletions.
11 changes: 11 additions & 0 deletions tests/subsys/usb/device_next/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright (c) 2023 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(test_usb_device_next)

target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/usb/host)

target_sources(app PRIVATE src/main.c)
19 changes: 19 additions & 0 deletions tests/subsys/usb/device_next/boards/native_posix.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

/delete-node/ &zephyr_udc0;

/ {
zephyr_uhc0: uhc_vrt0 {
compatible = "zephyr,uhc-virtual";

zephyr_udc0: udc_vrt0 {
compatible = "zephyr,udc-virtual";
num-bidir-endpoints = <8>;
maximum-speed = "high-speed";
};
};
};
17 changes: 17 additions & 0 deletions tests/subsys/usb/device_next/boards/qemu_cortex_m3.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

/ {
zephyr_uhc0: uhc_vrt0 {
compatible = "zephyr,uhc-virtual";

zephyr_udc0: udc_vrt0 {
compatible = "zephyr,udc-virtual";
num-bidir-endpoints = <8>;
maximum-speed = "high-speed";
};
};
};
12 changes: 12 additions & 0 deletions tests/subsys/usb/device_next/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright (c) 2023 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

CONFIG_LOG=y
CONFIG_ZTEST=y
CONFIG_ZTEST_NEW_API=y

CONFIG_USB_DEVICE_STACK_NEXT=y
CONFIG_USBD_LOOPBACK_CLASS=y

CONFIG_UHC_DRIVER=y
CONFIG_USB_HOST_STACK=y
160 changes: 160 additions & 0 deletions tests/subsys/usb/device_next/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/ztest.h>
#include <zephyr/usb/usbd.h>
#include <zephyr/usb/usbh.h>

#include "usbh_ch9.h"
#include "usbh_device.h"

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(usb_test, LOG_LEVEL_INF);

#define TEST_DEFAULT_INTERFACE 0
#define TEST_DEFAULT_ALTERNATE 1

USBD_CONFIGURATION_DEFINE(test_config,
USB_SCD_SELF_POWERED | USB_SCD_REMOTE_WAKEUP,
200);

USBD_DESC_LANG_DEFINE(test_lang);
USBD_DESC_STRING_DEFINE(test_mfg, "ZEPHYR", 1);
USBD_DESC_STRING_DEFINE(test_product, "Zephyr USB Test", 2);
USBD_DESC_STRING_DEFINE(test_sn, "0123456789ABCDEF", 3);

USBD_DEVICE_DEFINE(test_usbd,
DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)),
0x2fe3, 0xffff);

USBH_CONTROLLER_DEFINE(uhs_ctx, DEVICE_DT_GET(DT_NODELABEL(zephyr_uhc0)));

/* Get Configuration request test */
ZTEST(device_next, test_get_configuration)
{
struct usb_device *udev;
uint8_t cfg = 0;
int err;

udev = usbh_device_get_any(&uhs_ctx);
err = usbh_req_get_cfg(udev, &cfg);

switch (udev->state) {
case USB_STATE_DEFAULT:
/* Not specified, expect protocol error */
zassert_equal(err, -EPIPE, "Transfer status is not a protocol error");
break;
case USB_STATE_ADDRESSED:
/* TODO: Expect zero value */
zassert_equal(err, 0, "Transfer status is an error");
zassert_equal(cfg, 0, "Device not in address state");
break;
case USB_STATE_CONFIGURED:
/* TODO: Expect non-zero valid configuration value */
zassert_equal(err, 0, "Transfer status is an error");
zassert_not_equal(cfg, 0, "Device not in configured state");
break;
default:
break;
}
}

/* Set Interface request test */
ZTEST(device_next, test_set_interface)
{
struct usb_device *udev;
int err;

udev = usbh_device_get_any(&uhs_ctx);
err = usbh_req_set_alt(udev, TEST_DEFAULT_INTERFACE,
TEST_DEFAULT_ALTERNATE);

switch (udev->state) {
case USB_STATE_DEFAULT:
/* Not specified, expect protocol error */
case USB_STATE_ADDRESSED:
/* Expect protocol error */
zassert_equal(err, -EPIPE, "Transfer status is not a protocol error");
break;
case USB_STATE_CONFIGURED:
/* TODO */
default:
break;
}
}

static void *usb_test_enable(void)
{
struct usb_device *udev;
int err;

err = usbh_init(&uhs_ctx);
zassert_equal(err, 0, "Failed to initialize USB host");

err = usbh_enable(&uhs_ctx);
zassert_equal(err, 0, "Failed to enable USB host");

err = uhc_bus_reset(uhs_ctx.dev);
zassert_equal(err, 0, "Failed to signal bus reset");

err = uhc_bus_resume(uhs_ctx.dev);
zassert_equal(err, 0, "Failed to signal bus resume");

err = uhc_sof_enable(uhs_ctx.dev);
zassert_equal(err, 0, "Failed to enable SoF generator");

LOG_INF("Host controller enabled");

err = usbd_add_descriptor(&test_usbd, &test_lang);
zassert_equal(err, 0, "Failed to initialize descriptor (%d)", err);

err = usbd_add_descriptor(&test_usbd, &test_mfg);
zassert_equal(err, 0, "Failed to initialize descriptor (%d)", err);

err = usbd_add_descriptor(&test_usbd, &test_product);
zassert_equal(err, 0, "Failed to initialize descriptor (%d)", err);

err = usbd_add_descriptor(&test_usbd, &test_sn);
zassert_equal(err, 0, "Failed to initialize descriptor (%d)", err);

err = usbd_add_configuration(&test_usbd, &test_config);
zassert_equal(err, 0, "Failed to add configuration (%d)");

err = usbd_register_class(&test_usbd, "loopback_0", 1);
zassert_equal(err, 0, "Failed to register loopback_0 class (%d)");

err = usbd_init(&test_usbd);
zassert_equal(err, 0, "Failed to initialize device support");

err = usbd_enable(&test_usbd);
zassert_equal(err, 0, "Failed to enable device support");

LOG_INF("Device support enabled");
udev = usbh_device_get_any(&uhs_ctx);
udev->state = USB_STATE_DEFAULT;

return NULL;
}

static void usb_test_shutdown(void *f)
{
int err;

err = usbd_disable(&test_usbd);
zassert_equal(err, 0, "Failed to enable device support");

err = usbd_shutdown(&test_usbd);
zassert_equal(err, 0, "Failed to shutdown device support");

LOG_INF("Device support disabled");

err = usbh_disable(&uhs_ctx);
zassert_equal(err, 0, "Failed to disable USB host");

LOG_INF("Host controller disabled");
}

ZTEST_SUITE(device_next, NULL, usb_test_enable, NULL, NULL, usb_test_shutdown);
9 changes: 9 additions & 0 deletions tests/subsys/usb/device_next/testcase.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
tests:
usb.device_next:
depends_on: usb_device
tags: usb
platform_allow:
- native_posix
- qemu_cortex_m3
integration_platforms:
- native_posix

0 comments on commit ed7d56f

Please sign in to comment.