| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <fuchsia/sysinfo/c/fidl.h> |
| #include <lib/async-loop/cpp/loop.h> |
| #include <lib/async-loop/default.h> |
| #include <lib/fdio/directory.h> |
| #include <lib/fdio/fd.h> |
| #include <lib/fdio/fdio.h> |
| #include <lib/stdcompat/span.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <zircon/status.h> |
| |
| #include <iterator> |
| |
| #include <fbl/algorithm.h> |
| #include <fbl/string.h> |
| #include <fbl/unique_fd.h> |
| #include <sdk/lib/device-watcher/cpp/device-watcher.h> |
| #include <zxtest/base/log-sink.h> |
| #include <zxtest/zxtest.h> |
| |
| #include "src/lib/fsl/io/device_watcher.h" |
| #include "zircon/system/utest/device-enumeration/aemu.h" |
| |
| namespace { |
| |
| using device_watcher::RecursiveWaitForFile; |
| |
| // Asyncronously wait for a path to appear, and call `callback` when the path exists. |
| // The `watchers` array is needed because each directory in the path needs to allocate a |
| // DeviceWatcher, and they need to be stored somewhere that can be freed later. |
| void RecursiveWaitFor(std::string full_path, size_t slash_index, fit::function<void()>* callback, |
| std::vector<std::unique_ptr<fsl::DeviceWatcher>>* watchers) { |
| if (slash_index == full_path.size()) { |
| fprintf(stderr, "Found %s \n", full_path.c_str()); |
| (*callback)(); |
| return; |
| } |
| |
| std::string dir_path = full_path.substr(0, slash_index); |
| size_t next_slash = full_path.find_first_of("/", slash_index + 1); |
| if (next_slash == std::string::npos) { |
| next_slash = full_path.size(); |
| } |
| std::string file_name = full_path.substr(slash_index + 1, next_slash - (slash_index + 1)); |
| |
| watchers->push_back(fsl::DeviceWatcher::Create( |
| dir_path, |
| [file_name, full_path, next_slash, callback, watchers](int dir_fd, const std::string& name) { |
| if (name.compare(file_name) == 0) { |
| RecursiveWaitFor(full_path, next_slash, callback, watchers); |
| } |
| })); |
| } |
| |
| void WaitForOne(cpp20::span<const char*> device_paths) { |
| async::Loop loop = async::Loop(&kAsyncLoopConfigAttachToCurrentThread); |
| |
| std::vector<std::unique_ptr<fsl::DeviceWatcher>> watchers; |
| auto callback = fit::function<void()>([&loop]() { loop.Shutdown(); }); |
| |
| for (const char* path : device_paths) { |
| RecursiveWaitFor(std::string("/dev/") + path, 4, &callback, &watchers); |
| } |
| |
| loop.Run(); |
| } |
| |
| fbl::String GetTestFilter() { |
| constexpr char kSysInfoPath[] = "/svc/fuchsia.sysinfo.SysInfo"; |
| fbl::unique_fd sysinfo(open(kSysInfoPath, O_RDONLY)); |
| if (!sysinfo) { |
| return "Unknown"; |
| } |
| |
| zx::channel channel; |
| if (fdio_get_service_handle(sysinfo.release(), channel.reset_and_get_address()) != ZX_OK) { |
| return "Unknown"; |
| } |
| |
| char board_name[fuchsia_sysinfo_BOARD_NAME_LEN + 1]; |
| zx_status_t status; |
| size_t actual_size; |
| zx_status_t fidl_status = fuchsia_sysinfo_SysInfoGetBoardName(channel.get(), &status, board_name, |
| sizeof(board_name), &actual_size); |
| if (fidl_status != ZX_OK || status != ZX_OK) { |
| return "Unknown"; |
| } |
| board_name[actual_size] = '\0'; |
| |
| printf("Found board %s\n", board_name); |
| |
| if (!strcmp(board_name, "qemu")) { |
| return "*QemuArm64*"; |
| } else if (!strcmp(board_name, "vim3")) { |
| return "*Vim3*"; |
| } else if (!strcmp(board_name, "astro")) { |
| return "*Astro*"; |
| } else if (!strcmp(board_name, "sherlock")) { |
| return "*Sherlock*"; |
| } else if (!strcmp(board_name, "msm8x53-som")) { |
| return "*Msm8x53Som*"; |
| } else if (!strcmp(board_name, "Nocturne")) { |
| return "*Nocturne*"; |
| } else if (!strcmp(board_name, "nelson")) { |
| return "*Nelson*"; |
| } else if (!strcmp(board_name, "luis")) { |
| return "*Luis*"; |
| } else if (!strcmp(board_name, "Eve")) { |
| return "*Eve*"; |
| } else if (!strcmp(board_name, "NUC7i5DNB")) { |
| return "*Nuc*"; |
| } else if (!strcmp(board_name, "Atlas")) { |
| return "*Atlas*"; |
| } else if (!strcmp(board_name, "Standard PC (Q35 + ICH9, 2009)")) { |
| // QEMU and AEMU with emulated Q35 boards have this board name. |
| return "*QemuX64Q35*"; |
| } else if (!strcmp(board_name, "av400")) { |
| return "*Av400*"; |
| } else if (!strcmp(board_name, "arm64") || !strcmp(board_name, "x64")) { |
| return "*GenericShouldFail*"; |
| } |
| |
| return "Unknown"; |
| } |
| |
| class DeviceEnumerationTest : public zxtest::Test { |
| protected: |
| void TestRunner(const char** device_paths, size_t paths_num) { |
| fbl::unique_fd devfs_root(open("/dev", O_RDONLY)); |
| ASSERT_TRUE(devfs_root); |
| |
| fbl::unique_fd fd; |
| for (size_t i = 0; i < paths_num; ++i) { |
| // stderr helps diagnosibility, since stdout doesn't show up in test logs |
| fprintf(stderr, "Checking %s\n", device_paths[i]); |
| EXPECT_OK(RecursiveWaitForFile(devfs_root, device_paths[i], &fd), "%s", device_paths[i]); |
| } |
| } |
| }; |
| |
| TEST_F(DeviceEnumerationTest, Av400Test) { |
| static const char* kDevicePaths[] = { |
| "sys/platform/platform-passthrough/av400", |
| "sys/platform/05:07:1/aml-axg-gpio", |
| "sys/platform/05:07:1d", // pwm |
| "sys/platform/05:07:2c/clocks", |
| "sys/platform/05:00:2/aml-i2c", |
| "sys/platform/00:00:29", // registers device |
| "aml_emmc/aml-sd-emmc/sdmmc/sdmmc-mmc", |
| "aml_sdio/aml-sd-emmc/sdmmc/sdmmc-sdio", |
| "spi-1/aml-spi-1/spi/spi-1-0", |
| "pwm-init", |
| }; |
| |
| ASSERT_NO_FATAL_FAILURE(TestRunner(kDevicePaths, std::size(kDevicePaths))); |
| } |
| |
| TEST_F(DeviceEnumerationTest, QemuArm64Test) { |
| static const char* kDevicePaths[] = { |
| "sys/platform/platform-passthrough/qemu-bus", |
| "sys/platform/00:00:6/rtc", |
| "sys/platform/pci/00:00.0", |
| }; |
| |
| ASSERT_NO_FATAL_FAILURE(TestRunner(kDevicePaths, std::size(kDevicePaths))); |
| } |
| |
| TEST_F(DeviceEnumerationTest, Vim3Test) { |
| static const char* kDevicePaths[] = { |
| "sys/platform/platform-passthrough/vim3", |
| "sys/platform/00:00:1b/sysmem", |
| "sys/platform/05:06:1/aml-axg-gpio", |
| "sys/platform/05:06:14/clocks", |
| "sys/platform/05:00:2/aml-i2c", |
| "sys/platform/05:00:2/aml-i2c/i2c/i2c-0-81/rtc", |
| "dwmac/dwmac/eth_phy/phy_null_device", |
| "dwmac/dwmac/Designware-MAC/ethernet", |
| "ethernet_mac/aml-ethernet", |
| "aml_sd/aml-sd-emmc", |
| "aml_sdio/aml-sd-emmc/sdmmc/sdmmc-sdio/sdmmc-sdio-1", |
| "aml_sdio/aml-sd-emmc/sdmmc/sdmmc-sdio/sdmmc-sdio-2", |
| "aml-nna", |
| "sys/platform/00:00:29", // registers device |
| "mali/aml-gpu", |
| "sys/platform/05:00:10/aml-canvas", |
| "display/amlogic-display/display-controller", |
| "sys/platform/05:06:2b/aml-hdmi", |
| "sys/platform/05:06:1d", // pwm |
| "vreg/pwm-0-regulator", |
| "vreg/pwm-9-regulator", |
| "aml-power-impl-composite", |
| "pd-big-core", |
| "pd-little-core", |
| "sys/platform/05:06:26", // power |
| |
| // CPU devices. |
| "sys/platform/05:06:1e", |
| "aml-cpu/a311d-arm-a73", |
| "aml-cpu/a311d-arm-a53", |
| |
| "fusb302", |
| |
| // USB |
| "vim3-usb-phy", |
| "dwc2/dwc2/usb-peripheral/function-000/cdc-eth-function", |
| "xhci/xhci", |
| "xhci/xhci/usb-bus/000/usb-hub", // USB 2.0 Hub |
| |
| // Thermal |
| "sys/platform/05:06:28", |
| "sys/platform/05:06:a", |
| "class/thermal/000", |
| |
| // GPIO |
| "gpio-expander/ti-tca6408a/gpio-107", |
| |
| "sys/platform/05:00:2/aml-i2c/i2c/i2c-0-24-fidl/vim3-mcu", |
| }; |
| |
| ASSERT_NO_FATAL_FAILURE(TestRunner(kDevicePaths, std::size(kDevicePaths))); |
| } |
| |
| TEST_F(DeviceEnumerationTest, AstroTest) { |
| static const char* kDevicePaths[] = { |
| "sys/platform/platform-passthrough/astro", |
| "sys/platform/05:03:1/aml-axg-gpio", |
| "astro-buttons/hid-buttons", |
| "sys/platform/05:00:2/aml-i2c", |
| "mali/aml-gpu", |
| "aml-usb-phy-v2", |
| "class/bt-transport/000", |
| "class/bt-hci/000", |
| |
| // XHCI driver will not be loaded if we are in USB peripheral mode. |
| // "xhci/xhci/usb-bus", |
| |
| "backlight/ti-lp8556", |
| "display/amlogic-display/display-controller", |
| "sys/platform/00:00:1e/dw-dsi", |
| "class/dsi-base/000", |
| "sys/platform/05:00:10/aml-canvas", |
| "tee/optee", |
| "aml-video", |
| "sys/platform/05:00:f/aml-raw_nand/nand/bl2/skip-block", |
| "sys/platform/05:00:f/aml-raw_nand/nand/tpl/skip-block", |
| "sys/platform/05:00:f/aml-raw_nand/nand/fts/skip-block", |
| "sys/platform/05:00:f/aml-raw_nand/nand/factory/skip-block", |
| "sys/platform/05:00:f/aml-raw_nand/nand/zircon-b/skip-block", |
| "sys/platform/05:00:f/aml-raw_nand/nand/zircon-a/skip-block", |
| "sys/platform/05:00:f/aml-raw_nand/nand/zircon-r/skip-block", |
| "sys/platform/05:00:f/aml-raw_nand/nand/sys-config/skip-block", |
| "sys/platform/05:00:f/aml-raw_nand/nand/migration/skip-block", |
| "aml-sdio/aml-sd-emmc/sdmmc", |
| "aml-sdio/aml-sd-emmc/sdmmc/sdmmc-sdio", |
| "aml-sdio/aml-sd-emmc/sdmmc/sdmmc-sdio/sdmmc-sdio-1", |
| "aml-sdio/aml-sd-emmc/sdmmc/sdmmc-sdio/sdmmc-sdio-2", |
| "wifi/brcmfmac-wlanphy", |
| "wifi/brcmfmac-wlanphy/wlanphy", |
| "tcs3400-light/tcs-3400", |
| "sys/platform/05:03:11/clocks", |
| "astro-i2s-audio-out", |
| "sys/platform/05:03:13/astro-audio-pdm-in", |
| "aml-secure-mem/aml-securemem", |
| //"sys/platform/05:05:3/aml-uart/serial/bt-transport-uart/bcm-hci", |
| "pwm-init", |
| |
| // CPU Device. |
| "sys/platform/03:03:6", |
| "class/cpu-ctrl/000", |
| "aml-cpu/s905d2-arm-a53", |
| // LED. |
| "class/light/000", |
| // RAM (DDR) control. |
| "sys/platform/05:03:24/ram", |
| |
| // Power Device. |
| "aml-power-impl-composite", |
| "composite-pd-armcore", |
| "composite-pd-armcore/power-0", |
| |
| // Thermal |
| "sys/platform/05:03:a/thermal", |
| "sys/platform/05:03:28/thermal", |
| "class/thermal/000", |
| "class/thermal/001", |
| |
| // Thermistor/ADC |
| "class/adc/000", |
| "class/adc/001", |
| "class/adc/002", |
| "class/adc/003", |
| "class/temperature/000", |
| "class/temperature/001", |
| "class/temperature/002", |
| "class/temperature/003", |
| |
| // Registers Device. |
| "sys/platform/00:00:29", |
| }; |
| |
| ASSERT_NO_FATAL_FAILURE(TestRunner(kDevicePaths, std::size(kDevicePaths))); |
| |
| static const char* kTouchscreenDevicePaths[] = { |
| "gt92xx-touch/gt92xx HidDevice/hid-device/InputReport", |
| "ft3x27-touch/focaltouch HidDevice/hid-device/InputReport", |
| }; |
| ASSERT_NO_FATAL_FAILURE( |
| WaitForOne(cpp20::span(kTouchscreenDevicePaths, std::size(kTouchscreenDevicePaths)))); |
| } |
| |
| TEST_F(DeviceEnumerationTest, NelsonTest) { |
| static const char* kDevicePaths[] = { |
| "sys/platform/platform-passthrough/nelson", |
| "sys/platform/05:05:1/aml-axg-gpio", |
| "sys/platform/05:05:1:1/aml-axg-gpio", |
| "nelson-buttons/hid-buttons", |
| "class/bt-transport/000", |
| "class/bt-hci/000", |
| "sys/platform/05:00:2/aml-i2c", |
| "mali/aml-gpu", |
| "sys/platform/05:0a:21/nelson-usb-phy", |
| "nelson-audio-i2s-out", |
| "sys/platform/05:05:13/nelson-audio-pdm-in", |
| "sys/platform/00:00:29", // registers device |
| |
| // XHCI driver will not be loaded if we are in USB peripheral mode. |
| // "xhci/xhci/usb-bus", |
| |
| "backlight/ti-lp8556", |
| "sys/platform/05:00:10/aml-canvas", |
| "tee/optee", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/boot1/block", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/boot2/block", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/rpmb", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-000/block", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-001/block", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-002/block", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-003/block", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-004/block", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-005/block", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-006/block", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-007/block", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-008/block", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-009/block", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-010/block", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-011/block", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-012/block", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-013/block", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-014/block", |
| "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-015/block", |
| "tcs3400-light/tcs-3400", |
| "aml-nna", |
| "sys/platform/05:05:22/clocks", |
| "aml-thermal-pll/thermal", |
| "class/thermal/000", |
| // "sys/platform/05:03:1e/cpu", |
| "aml-secure-mem/aml-securemem", |
| "class/pwm/000", |
| "class/pwm/001", |
| "class/pwm/002", |
| "class/pwm/003", |
| "class/pwm/004", |
| "class/pwm/005", |
| "class/pwm/006", |
| "class/pwm/007", |
| "class/pwm/008", |
| "class/pwm/009", |
| "aml-sdio/aml-sd-emmc/sdmmc", |
| "aml-sdio/aml-sd-emmc/sdmmc/sdmmc-sdio", |
| "aml-sdio/aml-sd-emmc/sdmmc/sdmmc-sdio/sdmmc-sdio-1", |
| "aml-sdio/aml-sd-emmc/sdmmc/sdmmc-sdio/sdmmc-sdio-2", |
| "wifi/brcmfmac-wlanphy", |
| "wifi/brcmfmac-wlanphy/wlanphy", |
| "sys/platform/00:00:1e/dw-dsi", |
| "display/amlogic-display/display-controller", |
| "class/dsi-base/000", |
| "ti-ina231-mlb/ti-ina231", |
| "ti-ina231-speakers/ti-ina231", |
| "sys/platform/05:00:2/aml-i2c/i2c/i2c-0-112/shtv3", |
| "gt6853-touch/gt6853", |
| |
| // Amber LED. |
| "gpio-light", |
| "class/light/000", |
| |
| // This should exist, but open() will fail because it is already being used by radar. |
| // "spi-1/aml-spi-1/spi/spi-1-0", |
| "selina/selina", |
| "class/radar/000", |
| |
| "sys/platform/05:05:24/ram", |
| |
| "sys/platform/03:0a:27/thermistor-device/therm-thread", |
| "sys/platform/03:0a:27/thermistor-device/therm-audio", |
| |
| "brownout-protection/nelson-brownout-protection", |
| |
| "spi-0/aml-spi-0/spi/spi-0-0", |
| "nrf52811-radio", |
| }; |
| |
| ASSERT_NO_FATAL_FAILURE(TestRunner(kDevicePaths, std::size(kDevicePaths))); |
| |
| static const char* kTouchscreenDevicePaths[] = { |
| // One of these touch devices could be on P0/P1 boards. |
| "gtx8x-touch/gt92xx HidDevice/hid-device/InputReport", |
| "ft3x27-touch/focaltouch HidDevice/hid-device/InputReport", |
| // This is the only possible touch device for P2 and beyond. |
| "gt6853-touch/gt6853", |
| }; |
| ASSERT_NO_FATAL_FAILURE( |
| WaitForOne(cpp20::span(kTouchscreenDevicePaths, std::size(kTouchscreenDevicePaths)))); |
| } |
| |
| TEST_F(DeviceEnumerationTest, SherlockTest) { |
| static const char* kDevicePaths[] = { |
| "sys/platform/platform-passthrough/sherlock", |
| "sys/platform/05:04:1/aml-axg-gpio", |
| "sys/platform/05:00:14/clocks", |
| "sys/platform/05:00:2/aml-i2c", |
| "sys/platform/05:00:10/aml-canvas", |
| "aml-thermal-pll/thermal", |
| "sys/platform/00:00:1e/dw-dsi", |
| "display/amlogic-display/display-controller", |
| "class/dsi-base/000", |
| "aml-usb-phy-v2", |
| |
| // XHCI driver will not be loaded if we are in USB peripheral mode. |
| // "xhci/xhci/usb-bus", |
| |
| "sherlock-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/boot1/block", |
| "sherlock-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/boot2/block", |
| "sherlock-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/rpmb", |
| "sherlock-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-000/block", |
| "sherlock-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-002/block", |
| "sherlock-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-000/block", |
| "sherlock-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-002/block", |
| "sherlock-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-003/block", |
| "sherlock-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-004/block", |
| "sherlock-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-005/block", |
| "sherlock-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-006/block", |
| "sherlock-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-007/block", |
| "sherlock-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-008/block", |
| "sherlock-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-009/block", |
| "sherlock-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-010/block", |
| "sherlock-sd-emmc/aml-sd-emmc/sdmmc/sdmmc-sdio/sdmmc-sdio-1", |
| "sherlock-sd-emmc/aml-sd-emmc/sdmmc/sdmmc-sdio/sdmmc-sdio-2", |
| "wifi/brcmfmac-wlanphy", |
| "wifi/brcmfmac-wlanphy/wlanphy", |
| "sys/platform/05:04:15/aml-mipi", |
| "aml-nna", |
| "sys/platform/05:04:1d", // pwm |
| "gdc", |
| "ge2d", |
| "gpio-light", |
| "imx227-sensor", |
| "isp", |
| "camera-controller", |
| "aml-video", |
| "aml-video-enc", |
| "aml-hevc-enc", |
| "mali/aml-gpu", |
| "sys/platform/05:04:13/sherlock-audio-pdm-in", |
| "sherlock-i2s-audio-out", |
| "ft5726-touch", |
| "tee/optee", |
| "spi-0/aml-spi-0/spi/spi-0-0", |
| "sherlock-buttons/hid-buttons", |
| "nrf52840-radio", |
| "backlight/ti-lp8556", |
| "SherlockLightSensor/tcs-3400", |
| "aml-secure-mem/aml-securemem", |
| "pwm-init", |
| "sys/platform/05:04:24/ram", |
| "sys/platform/00:00:29", // registers device |
| |
| // CPU Devices. |
| "sys/platform/03:05:6", |
| "class/cpu-ctrl/000", |
| "class/cpu-ctrl/001", |
| "aml-cpu/big-cluster", |
| "aml-cpu/little-cluster", |
| |
| // Thermal devices. |
| "sys/platform/05:04:a", |
| "sys/platform/05:04:28", |
| "class/thermal/000", |
| "class/thermal/001", |
| |
| "class/adc/000", |
| "class/adc/001", |
| "class/adc/002", |
| "class/adc/003", |
| "class/temperature/000", |
| "class/temperature/001", |
| "class/temperature/002", |
| |
| // LCD Bias |
| "sys/platform/05:00:2/aml-i2c/i2c/i2c-2-62", |
| }; |
| |
| ASSERT_NO_FATAL_FAILURE(TestRunner(kDevicePaths, std::size(kDevicePaths))); |
| } |
| |
| TEST_F(DeviceEnumerationTest, LuisTest) { |
| static const char* kDevicePaths[] = { |
| "sys/platform/05:04:13/luis-audio-pdm-in", |
| "luis-i2s-audio-out", |
| "sherlock-buttons/hid-buttons", |
| |
| // Thermal devices |
| "sys/platform/05:04:28/thermal", |
| |
| // Thermistor and ADC devices |
| "sys/platform/03:0c:27/thermistor-device/therm-mic", |
| "sys/platform/03:0c:27/thermistor-device/therm-amp", |
| "sys/platform/03:0c:27/thermistor-device/therm-ambient", |
| "class/adc/000", |
| "class/adc/001", |
| "class/adc/002", |
| "class/adc/003", |
| "class/temperature/000", |
| "class/temperature/001", |
| "class/temperature/002", |
| |
| // Power Device Bucks. |
| "0p8_ee_buck", |
| "cpu_a_buck", |
| |
| // Power Implementation Device / Children. |
| "aml-power-impl-composite", |
| "composite-pd-big-core", |
| "composite-pd-big-core/power-0", |
| "composite-pd-little-core", |
| "composite-pd-little-core/power-1", |
| |
| // CPU Device. |
| // TODO(fxbug.dev/60492): Temporarily removed. |
| // "sys/platform/03:0c:6", |
| // "class/cpu-ctrl/000", |
| // "class/cpu-ctrl/001", |
| |
| // USB ethernet; Can be RNDIS or CDC based on build config. Update this after fxbug.dev/58584 |
| // is fixed. |
| "dwc2/dwc2/usb-peripheral/function-000", |
| }; |
| |
| ASSERT_NO_FATAL_FAILURE(TestRunner(kDevicePaths, std::size(kDevicePaths))); |
| } |
| |
| TEST_F(DeviceEnumerationTest, EveTest) { |
| static const char* kDevicePaths[] = { |
| "sys/platform/pci/00:1f.3/intel-hda-000/output-stream-001", // Controller |
| // headphones/speakers. |
| "sys/platform/pci/00:1f.3/intel-hda-000/output-stream-003", // Controller |
| // headphones/speakers. |
| "sys/platform/pci/00:1f.3/intel-hda-000/input-stream-002", // Controller mics. |
| "sys/platform/pci/00:19.2/i2c-bus-9d64/i2c/i2c-0-57/max98927", // Codec left speaker. |
| "sys/platform/pci/00:19.2/i2c-bus-9d64/i2c/i2c-0-58/max98927", // Codec right speaker. |
| "sys/platform/pci/00:19.2/i2c-bus-9d64/i2c/i2c-0-19/alc5663", // Codec headphones. |
| "sys/platform/pci/00:19.2/i2c-bus-9d64/i2c/i2c-0-87/alc5514", // Codec mics. |
| }; |
| |
| ASSERT_NO_FATAL_FAILURE(TestRunner(kDevicePaths, std::size(kDevicePaths))); |
| } |
| |
| TEST_F(DeviceEnumerationTest, NucTest) { |
| static const char* kDevicePaths[] = { |
| "pci-00:02.0/intel_i915/intel-gpu-core", |
| "pci-00:02.0/intel_i915/intel-display-controller/display-controller", |
| "pci-00:14.0/xhci/usb-bus", |
| "pci-00:15.0/i2c-bus-9d60", |
| "pci-00:15.1/i2c-bus-9d61", |
| "pci-00:17.0/ahci", |
| // TODO(fxbug.dev/84037): Temporarily removed. |
| // "pci-00:1f.3/intel-hda-000", |
| // "pci-00:1f.3/intel-hda-controller", |
| "pci-00:1f.6/e1000", |
| }; |
| |
| ASSERT_NO_FATAL_FAILURE(TestRunner(kDevicePaths, std::size(kDevicePaths))); |
| } |
| |
| TEST_F(DeviceEnumerationTest, AtlasTest) { |
| static const char* kDevicePaths[] = { |
| "pci-01:00.0/iwlwifi-wlanphyimpl", "pci-01:00.0/iwlwifi-wlanphyimpl/wlanphy", |
| "pci-00:19.2/i2c-bus-9d64/i2c/i2c-3-26", // Codec headphones. |
| }; |
| |
| ASSERT_NO_FATAL_FAILURE(TestRunner(kDevicePaths, std::size(kDevicePaths))); |
| } |
| |
| TEST_F(DeviceEnumerationTest, NocturneTest) { |
| static const char* kDevicePaths[] = { |
| "sys/platform/pci/00:1f.3/intel-hda-000/input-stream-002", |
| "sys/platform/pci/00:1f.3/intel-hda-000/output-stream-001", |
| "sys/platform/pci/00:02.0/intel_i915/intel-gpu-core/msd-intel-gen", |
| "sys/platform/pci/00:02.0/intel_i915/display-controller", |
| "sys/platform/platform-passthrough/acpi/TSR0", |
| "sys/platform/platform-passthrough/acpi/TSR1", |
| "sys/platform/platform-passthrough/acpi/TSR2", |
| "sys/platform/platform-passthrough/acpi/TSR3", |
| "sys/platform/platform-passthrough/acpi/acpi-lid/hid-device/InputReport", |
| "sys/platform/platform-passthrough/acpi/acpi-pwrbtn/hid-device/InputReport", |
| "sys/platform/pci/00:15.0/i2c-bus-9d60/000a/i2c-hid/hid-device/InputReport", |
| }; |
| |
| ASSERT_NO_FATAL_FAILURE(TestRunner(kDevicePaths, std::size(kDevicePaths))); |
| } |
| |
| TEST_F(DeviceEnumerationTest, QemuX64Q35Test) { |
| static const char* kDevicePaths[] = { |
| "class/sysmem/000", |
| |
| "pci-00:00.0", |
| "pci-00:1f.2/ahci", |
| |
| "sys/platform/platform-passthrough/acpi", |
| "sys/platform/platform-passthrough/acpi/acpi-pwrbtn", |
| "acpi-KBD_-composite/i8042/i8042-keyboard", |
| "acpi-KBD_-composite/i8042/i8042-mouse", |
| }; |
| |
| ASSERT_NO_FATAL_FAILURE(TestRunner(kDevicePaths, std::size(kDevicePaths))); |
| |
| if (!device_enumeration::IsAemuBoard()) { |
| return; |
| } |
| printf("INFO: AEMU board detected. Test enumerating AEMU-specific devices.\n"); |
| |
| static const char* kAemuDevicePaths[] = { |
| "pci-00:01.0/virtio-input", |
| "pci-00:02.0/virtio-input", |
| "pci-00:0b.0/goldfish-address-space", |
| |
| "acpi-GFPP-composite", |
| // Verify goldfish pipe root device created. |
| "acpi-GFPP-composite/goldfish-pipe", |
| // Verify goldfish pipe child devices created. |
| "acpi-GFPP-composite/goldfish-pipe/goldfish-pipe-control", |
| "acpi-GFPP-composite/goldfish-pipe/goldfish-pipe-sensor", |
| "acpi-GFSK-composite", |
| "acpi-GFSK-composite/goldfish-sync", |
| |
| "goldfish-control-2", |
| "goldfish-control-2/goldfish-control", |
| "goldfish-control-2/goldfish-control/goldfish-display", |
| }; |
| |
| ASSERT_NO_FATAL_FAILURE(TestRunner(kAemuDevicePaths, std::size(kAemuDevicePaths))); |
| } |
| |
| // If this test fails, it indicates that the board driver set the board name incorrectly. |
| TEST_F(DeviceEnumerationTest, GenericShouldFailTest) { |
| ASSERT_TRUE(false, |
| "Board name was a generic board name, likely indicating that the board driver failed " |
| "to find a real board name."); |
| } |
| |
| } // namespace |
| |
| int main(int argc, char** argv) { |
| fbl::Vector<fbl::String> errors; |
| auto options = zxtest::Runner::Options::FromArgs(argc, argv, &errors); |
| zxtest::LogSink* log_sink = zxtest::Runner::GetInstance()->mutable_reporter()->mutable_log_sink(); |
| |
| if (!errors.is_empty()) { |
| for (const auto& error : errors) { |
| log_sink->Write("%s\n", error.c_str()); |
| } |
| options.help = true; |
| } |
| |
| options.filter = fbl::StringPrintf("%s:%s", GetTestFilter().c_str(), options.filter.c_str()); |
| |
| // Errors will always set help to true. |
| if (options.help) { |
| zxtest::Runner::Options::Usage(argv[0], log_sink); |
| return errors.is_empty(); |
| } |
| |
| if (options.list) { |
| zxtest::Runner::GetInstance()->List(options); |
| return 0; |
| } |
| |
| return zxtest::Runner::GetInstance()->Run(options); |
| } |