#include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include #include namespace { struct UsbdTimeval { std::int64_t seconds; std::int64_t microseconds; }; } extern "C" { std::int32_t APS5_VABI sceUsbdInit(); void APS5_VABI sceUsbdExit(); std::int64_t APS5_VABI sceUsbdGetDeviceList(void*** list); void APS5_VABI sceUsbdFreeDeviceList(void** list, std::int32_t unrefDevices); std::int32_t APS5_VABI sceUsbdHandleEventsTimeout(const UsbdTimeval* timeout); int APS5_VABI sceUsbdOpen(); } namespace { constexpr std::int32_t invalidArgument = static_cast(0x80240002); void Require(bool condition, const char* message) { if (!condition) { std::fprintf(stderr, "USBD: %s\n", message); std::abort(); } } } int main() { Require(sceUsbdInit() == 0, "initialization failed"); void** list = nullptr; Require(sceUsbdGetDeviceList(&list) == 0, "a device was listed"); Require(list != nullptr && list[0] == nullptr, "device list is not an empty null-terminated array"); sceUsbdFreeDeviceList(list, 1); Require(sceUsbdGetDeviceList(nullptr) == invalidArgument, "null list accepted"); Require(sceUsbdHandleEventsTimeout(nullptr) == invalidArgument, "null timeout accepted"); const UsbdTimeval invalid{0, 1000000}; Require(sceUsbdHandleEventsTimeout(&invalid) == invalidArgument, "out-of-range microseconds accepted"); const UsbdTimeval timeout{0, 50000}; const auto start = std::chrono::steady_clock::now(); Require(sceUsbdHandleEventsTimeout(&timeout) == 0, "event handling failed"); Require(std::chrono::steady_clock::now() - start >= std::chrono::milliseconds(45), "event handling returned before the timeout"); bool threw = false; try { sceUsbdOpen(); } catch (const std::runtime_error&) { threw = true; } Require(threw, "opening a device did not throw"); sceUsbdExit(); std::puts("USBD tests passed"); return 0; }