diff --git a/sw/device/tests/BUILD b/sw/device/tests/BUILD index a02331de85fb1b..a3d253af8c4be2 100644 --- a/sw/device/tests/BUILD +++ b/sw/device/tests/BUILD @@ -4403,7 +4403,13 @@ opentitan_test( EARLGREY_TEST_ENVS, EARLGREY_SILICON_OWNER_ROM_EXT_ENVS, ), - fpga = fpga_params(tags = ["manual"]), + fpga = fpga_params( + tags = ["manual"], + test_cmd = """ + --bootstrap="{firmware}" + """, + test_harness = "//sw/host/tests/chip/usb:usbdev_smoketest", + ), verilator = verilator_params(timeout = "long"), deps = [ "//hw/top_earlgrey/sw/autogen:top_earlgrey", diff --git a/sw/host/tests/chip/usb/BUILD b/sw/host/tests/chip/usb/BUILD index a5babf53e81fcb..bba76b2d34ea7c 100644 --- a/sw/host/tests/chip/usb/BUILD +++ b/sw/host/tests/chip/usb/BUILD @@ -51,3 +51,20 @@ rust_binary( "@crate_index//:log", ], ) + +rust_binary( + name = "usbdev_smoketest", + srcs = [ + "usbdev_smoketest.rs", + ], + deps = [ + ":usb", + "//sw/host/opentitanlib", + "@crate_index//:anyhow", + "@crate_index//:clap", + "@crate_index//:humantime", + "@crate_index//:log", + "@crate_index//:rusb", + "@crate_index//:serialport", + ], +) diff --git a/sw/host/tests/chip/usb/usbdev_smoketest.rs b/sw/host/tests/chip/usb/usbdev_smoketest.rs new file mode 100644 index 00000000000000..8a823dae3237d9 --- /dev/null +++ b/sw/host/tests/chip/usb/usbdev_smoketest.rs @@ -0,0 +1,70 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::{bail, Result}; +use clap::{Parser}; +use std::time::Duration; + +use opentitanlib::execute_test; +use opentitanlib::io::uart::Uart; +use opentitanlib::test_utils::init::InitializeTest; +use opentitanlib::uart::console::UartConsole; +use opentitanlib::transport::common::uart::SerialPortUart; + +use usb::UsbOpts; + +#[derive(Debug, Parser)] +struct Opts { + #[command(flatten)] + init: InitializeTest, + + /// Console/USB timeout. + #[arg(long, value_parser = humantime::parse_duration, default_value = "10s")] + timeout: Duration, + + /// USB options. + #[command(flatten)] + usb: UsbOpts, +} + +fn usbdev_echo(opts: &Opts, uart: &dyn Uart) -> Result<()> { + log::info!("waiting for device..."); + let devices = opts.usb.wait_for_device(opts.timeout)?; + if devices.is_empty() { + bail!("no USB device found"); + } + + let ports = serialport::available_ports()?; + let port = ports.iter().find(|&port| { + if let serialport::SerialPortType::UsbPort(info) = &port.port_type{ + info.vid == opts.usb.vid && info.pid == opts.usb.pid + } + else { + false + } + }).unwrap(); + + let usb_uart = SerialPortUart::open(&port.port_name, 115200)?; + + let mut buffer = [0u8; 256]; + let len = usb_uart.read(&mut buffer)?; + + usb_uart.write(&buffer[0..len])?; + + let _ = UartConsole::wait_for(uart, r"PASS!", opts.timeout)?; + Ok(()) +} + +fn main() -> Result<()> { + let opts = Opts::parse(); + opts.init.init_logging(); + let transport = opts.init.init_target()?; + + let uart = transport.uart("console")?; + let _ = UartConsole::wait_for(&*uart, r"Running [^\r\n]*", opts.timeout)?; + + execute_test!(usbdev_echo, &opts, &*uart); + + Ok(()) +}