From 7533206d89ceb028221a9e094c6eb9a0cc019cab Mon Sep 17 00:00:00 2001 From: Joshua de Reeper Date: Mon, 31 Mar 2025 17:55:21 +0200 Subject: [PATCH] usbd: Implement libusb passthrough (#2271) * usbd: Implement libusb passthrough * clang-format * only do kernel activities on non-windows * use variable to represent "fake" windows kernel driver --------- Co-authored-by: georgemoralis --- .gitmodules | 3 + CMakeLists.txt | 3 +- externals/CMakeLists.txt | 5 + externals/libusb | 1 + src/core/libraries/usbd/usbd.cpp | 512 ++++++++++++++++++++----------- src/core/libraries/usbd/usbd.h | 198 ++++++++---- 6 files changed, 475 insertions(+), 247 deletions(-) create mode 160000 externals/libusb diff --git a/.gitmodules b/.gitmodules index 98fba2098..065a4570f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -107,3 +107,6 @@ path = externals/MoltenVK/cereal url = https://github.com/USCiLab/cereal shallow = true +[submodule "externals/libusb"] + path = externals/libusb + url = https://github.com/libusb/libusb-cmake.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 021167d58..74d555adc 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,6 +224,7 @@ find_package(xxHash 0.8.2 MODULE) find_package(ZLIB 1.3 MODULE) find_package(Zydis 5.0.0 CONFIG) find_package(pugixml 1.14 CONFIG) +find_package(usb-1.0 1.0.27 CONFIG) if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR NOT MSVC) find_package(cryptopp 8.9.0 MODULE) @@ -1061,7 +1062,7 @@ endif() create_target_directory_groups(shadps4) target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half ZLIB::ZLIB PNG::PNG) -target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator LibAtrac9 sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::glslang SDL3::SDL3 pugixml::pugixml stb::headers) +target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator LibAtrac9 sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::glslang SDL3::SDL3 pugixml::pugixml stb::headers usb-1.0) target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h") target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h") diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index d6bdda023..ef75e8f3e 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -201,6 +201,11 @@ if (NOT TARGET pugixml::pugixml) add_subdirectory(pugixml) endif() +# libusb +if (NOT TARGET usb-1.0) + add_subdirectory(libusb) +endif() + # Discord RPC if (ENABLE_DISCORD_RPC) add_subdirectory(discord-rpc) diff --git a/externals/libusb b/externals/libusb new file mode 160000 index 000000000..8f0b4a38f --- /dev/null +++ b/externals/libusb @@ -0,0 +1 @@ +Subproject commit 8f0b4a38fc3eefa2b26a99dff89e1c12bf37afd4 diff --git a/src/core/libraries/usbd/usbd.cpp b/src/core/libraries/usbd/usbd.cpp index fdfa50b23..e5f6151eb 100644 --- a/src/core/libraries/usbd/usbd.cpp +++ b/src/core/libraries/usbd/usbd.cpp @@ -7,311 +7,455 @@ #include "core/libraries/libs.h" #include "usbd.h" +#include +#include + namespace Libraries::Usbd { -int PS4_SYSV_ABI sceUsbdAllocTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 libusb_to_orbis_error(int retVal) { + if (retVal == LIBUSB_ERROR_OTHER) + return 0x802400FF; + if (retVal < 0) { + LOG_ERROR(Lib_Usbd, "libusb returned: {}", libusb_error_name(retVal)); + return 0x80240000 - retVal; + } + + return retVal; } -int PS4_SYSV_ABI sceUsbdAttachKernelDriver() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +libusb_context* g_libusb_context; + +#if defined(_WIN32) +bool s_has_removed_driver = false; +#endif + +s32 PS4_SYSV_ABI sceUsbdInit() { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_init(&g_libusb_context)); } -int PS4_SYSV_ABI sceUsbdBulkTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +void PS4_SYSV_ABI sceUsbdExit() { + LOG_DEBUG(Lib_Usbd, "called"); + + libusb_exit(g_libusb_context); } -int PS4_SYSV_ABI sceUsbdCancelTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s64 PS4_SYSV_ABI sceUsbdGetDeviceList(SceUsbdDevice*** list) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_get_device_list(g_libusb_context, list)); } -int PS4_SYSV_ABI sceUsbdCheckConnected() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +void PS4_SYSV_ABI sceUsbdFreeDeviceList(SceUsbdDevice** list, s32 unref_devices) { + LOG_DEBUG(Lib_Usbd, "called"); + + libusb_free_device_list(list, unref_devices); } -int PS4_SYSV_ABI sceUsbdClaimInterface() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +SceUsbdDevice* PS4_SYSV_ABI sceUsbdRefDevice(SceUsbdDevice* device) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_ref_device(device); } -int PS4_SYSV_ABI sceUsbdClearHalt() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +void PS4_SYSV_ABI sceUsbdUnrefDevice(SceUsbdDevice* device) { + LOG_DEBUG(Lib_Usbd, "called"); + + libusb_unref_device(device); } -int PS4_SYSV_ABI sceUsbdClose() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdGetConfiguration(SceUsbdDeviceHandle* dev_handle, s32* config) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_get_configuration(dev_handle, config)); } -int PS4_SYSV_ABI sceUsbdControlTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdGetDeviceDescriptor(SceUsbdDevice* device, SceUsbdDeviceDescriptor* desc) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_get_device_descriptor(device, desc)); } -int PS4_SYSV_ABI sceUsbdControlTransferGetData() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdGetActiveConfigDescriptor(SceUsbdDevice* device, + SceUsbdConfigDescriptor** config) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_get_active_config_descriptor(device, config)); } -int PS4_SYSV_ABI sceUsbdControlTransferGetSetup() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdGetConfigDescriptor(SceUsbdDevice* device, u8 config_index, + SceUsbdConfigDescriptor** config) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_get_config_descriptor(device, config_index, config)); } -int PS4_SYSV_ABI sceUsbdDetachKernelDriver() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdGetConfigDescriptorByValue(SceUsbdDevice* device, u8 bConfigurationValue, + SceUsbdConfigDescriptor** config) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error( + libusb_get_config_descriptor_by_value(device, bConfigurationValue, config)); } -int PS4_SYSV_ABI sceUsbdEventHandlerActive() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +void PS4_SYSV_ABI sceUsbdFreeConfigDescriptor(SceUsbdConfigDescriptor* config) { + LOG_DEBUG(Lib_Usbd, "called"); + + libusb_free_config_descriptor(config); } -int PS4_SYSV_ABI sceUsbdEventHandlingOk() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +u8 PS4_SYSV_ABI sceUsbdGetBusNumber(SceUsbdDevice* device) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_get_bus_number(device); } -int PS4_SYSV_ABI sceUsbdExit() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +u8 PS4_SYSV_ABI sceUsbdGetDeviceAddress(SceUsbdDevice* device) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_get_device_address(device); } -int PS4_SYSV_ABI sceUsbdFillBulkTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +SceUsbdSpeed PS4_SYSV_ABI sceUsbdGetDeviceSpeed(SceUsbdDevice* device) { + LOG_DEBUG(Lib_Usbd, "called"); + + return static_cast(libusb_get_device_speed(device)); } -int PS4_SYSV_ABI sceUsbdFillControlSetup() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdGetMaxPacketSize(SceUsbdDevice* device, u8 endpoint) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_get_max_packet_size(device, endpoint)); } -int PS4_SYSV_ABI sceUsbdFillControlTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize(SceUsbdDevice* device, u8 endpoint) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_get_max_iso_packet_size(device, endpoint)); } -int PS4_SYSV_ABI sceUsbdFillInterruptTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdOpen(SceUsbdDevice* device, SceUsbdDeviceHandle** dev_handle) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_open(device, dev_handle)); } -int PS4_SYSV_ABI sceUsbdFillIsoTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +void PS4_SYSV_ABI sceUsbdClose(SceUsbdDeviceHandle* dev_handle) { + LOG_DEBUG(Lib_Usbd, "called"); + + libusb_close(dev_handle); } -int PS4_SYSV_ABI sceUsbdFreeConfigDescriptor() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +SceUsbdDevice* PS4_SYSV_ABI sceUsbdGetDevice(SceUsbdDeviceHandle* dev_handle) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_get_device(dev_handle); } -int PS4_SYSV_ABI sceUsbdFreeDeviceList() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdSetConfiguration(SceUsbdDeviceHandle* dev_handle, s32 config) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_set_configuration(dev_handle, config)); } -int PS4_SYSV_ABI sceUsbdFreeTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdClaimInterface(SceUsbdDeviceHandle* dev_handle, s32 interface_number) { + LOG_DEBUG(Lib_Usbd, "called"); + + if (sceUsbdKernelDriverActive(dev_handle, interface_number)) { + sceUsbdDetachKernelDriver(dev_handle, interface_number); + } + + return libusb_to_orbis_error(libusb_claim_interface(dev_handle, interface_number)); } -int PS4_SYSV_ABI sceUsbdGetActiveConfigDescriptor() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdReleaseInterface(SceUsbdDeviceHandle* dev_handle, s32 interface_number) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_release_interface(dev_handle, interface_number)); } -int PS4_SYSV_ABI sceUsbdGetBusNumber() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +SceUsbdDeviceHandle* PS4_SYSV_ABI sceUsbdOpenDeviceWithVidPid(u16 vendor_id, u16 product_id) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_open_device_with_vid_pid(g_libusb_context, vendor_id, product_id); } -int PS4_SYSV_ABI sceUsbdGetConfigDescriptor() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdSetInterfaceAltSetting(SceUsbdDeviceHandle* dev_handle, + int interface_number, int alternate_setting) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error( + libusb_set_interface_alt_setting(dev_handle, interface_number, alternate_setting)); } -int PS4_SYSV_ABI sceUsbdGetConfigDescriptorByValue() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdClearHalt(SceUsbdDeviceHandle* dev_handle, uint8_t endpoint) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_clear_halt(dev_handle, endpoint)); } -int PS4_SYSV_ABI sceUsbdGetConfiguration() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdResetDevice(SceUsbdDeviceHandle* dev_handle) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_reset_device(dev_handle)); } -int PS4_SYSV_ABI sceUsbdGetDescriptor() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdKernelDriverActive(SceUsbdDeviceHandle* dev_handle, int interface_number) { + LOG_DEBUG(Lib_Usbd, "called"); + +#if defined(_WIN32) + if (!s_has_removed_driver) + return 1; + else + return 0; +#endif + + return libusb_to_orbis_error(libusb_kernel_driver_active(dev_handle, interface_number)); } -int PS4_SYSV_ABI sceUsbdGetDevice() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdDetachKernelDriver(SceUsbdDeviceHandle* dev_handle, int interface_number) { + LOG_DEBUG(Lib_Usbd, "called"); + +#if defined(_WIN32) + s_has_removed_driver = true; + return 0; +#endif + + return libusb_to_orbis_error(libusb_detach_kernel_driver(dev_handle, interface_number)); } -int PS4_SYSV_ABI sceUsbdGetDeviceAddress() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdAttachKernelDriver(SceUsbdDeviceHandle* dev_handle, int interface_number) { + LOG_DEBUG(Lib_Usbd, "called"); + +#if defined(_WIN32) + s_has_removed_driver = false; + return 0; +#endif + + return libusb_to_orbis_error(libusb_attach_kernel_driver(dev_handle, interface_number)); } -int PS4_SYSV_ABI sceUsbdGetDeviceDescriptor() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +u8* PS4_SYSV_ABI sceUsbdControlTransferGetData(SceUsbdTransfer* transfer) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_control_transfer_get_data(transfer); } -int PS4_SYSV_ABI sceUsbdGetDeviceList() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +SceUsbdControlSetup* PS4_SYSV_ABI sceUsbdControlTransferGetSetup(SceUsbdTransfer* transfer) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_control_transfer_get_setup(transfer); } -int PS4_SYSV_ABI sceUsbdGetDeviceSpeed() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +void PS4_SYSV_ABI sceUsbdFillControlSetup(u8* buf, u8 bmRequestType, u8 bRequest, u16 wValue, + u16 wIndex, u16 wLength) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_fill_control_setup(buf, bmRequestType, bRequest, wValue, wIndex, wLength); } -int PS4_SYSV_ABI sceUsbdGetIsoPacketBuffer() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +SceUsbdTransfer* PS4_SYSV_ABI sceUsbdAllocTransfer(int iso_packets) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_alloc_transfer(iso_packets); } -int PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdSubmitTransfer(SceUsbdTransfer* transfer) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_submit_transfer(transfer)); } -int PS4_SYSV_ABI sceUsbdGetMaxPacketSize() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdCancelTransfer(SceUsbdTransfer* transfer) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_cancel_transfer(transfer)); } -int PS4_SYSV_ABI sceUsbdGetStringDescriptor() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +void PS4_SYSV_ABI sceUsbdFreeTransfer(SceUsbdTransfer* transfer) { + LOG_DEBUG(Lib_Usbd, "called"); + + libusb_free_transfer(transfer); } -int PS4_SYSV_ABI sceUsbdGetStringDescriptorAscii() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +void PS4_SYSV_ABI sceUsbdFillControlTransfer(SceUsbdTransfer* transfer, + SceUsbdDeviceHandle* dev_handle, u8* buffer, + SceUsbdTransferCallback callback, void* user_data, + u32 timeout) { + LOG_DEBUG(Lib_Usbd, "called"); + + libusb_fill_control_transfer(transfer, dev_handle, buffer, callback, user_data, timeout); } -int PS4_SYSV_ABI sceUsbdHandleEvents() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +void PS4_SYSV_ABI sceUsbdFillBulkTransfer(SceUsbdTransfer* transfer, + SceUsbdDeviceHandle* dev_handle, uint8_t endpoint, + u8* buffer, s32 length, SceUsbdTransferCallback callback, + void* user_data, u32 timeout) { + LOG_DEBUG(Lib_Usbd, "called"); + + libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length, callback, user_data, + timeout); } -int PS4_SYSV_ABI sceUsbdHandleEventsLocked() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +void PS4_SYSV_ABI sceUsbdFillInterruptTransfer(SceUsbdTransfer* transfer, + SceUsbdDeviceHandle* dev_handle, uint8_t endpoint, + u8* buffer, s32 length, + SceUsbdTransferCallback callback, void* user_data, + u32 timeout) { + LOG_DEBUG(Lib_Usbd, "called"); + + libusb_fill_interrupt_transfer(transfer, dev_handle, endpoint, buffer, length, callback, + user_data, timeout); } -int PS4_SYSV_ABI sceUsbdHandleEventsTimeout() { - LOG_DEBUG(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +void PS4_SYSV_ABI sceUsbdFillIsoTransfer(SceUsbdTransfer* transfer, SceUsbdDeviceHandle* dev_handle, + uint8_t endpoint, u8* buffer, s32 length, + s32 num_iso_packets, SceUsbdTransferCallback callback, + void* user_data, u32 timeout) { + LOG_DEBUG(Lib_Usbd, "called"); + + libusb_fill_iso_transfer(transfer, dev_handle, endpoint, buffer, length, num_iso_packets, + callback, user_data, timeout); } -int PS4_SYSV_ABI sceUsbdInit() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return 0x80240005; // Skip +void PS4_SYSV_ABI sceUsbdSetIsoPacketLengths(SceUsbdTransfer* transfer, u32 length) { + LOG_DEBUG(Lib_Usbd, "called"); + + libusb_set_iso_packet_lengths(transfer, length); } -int PS4_SYSV_ABI sceUsbdInterruptTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +u8* PS4_SYSV_ABI sceUsbdGetIsoPacketBuffer(SceUsbdTransfer* transfer, u32 packet) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_get_iso_packet_buffer(transfer, packet); } -int PS4_SYSV_ABI sceUsbdKernelDriverActive() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdControlTransfer(SceUsbdDeviceHandle* dev_handle, u8 request_type, + u8 bRequest, u16 wValue, u16 wIndex, u8* data, s32 wLength, + u32 timeout) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_control_transfer(dev_handle, request_type, bRequest, wValue, + wIndex, data, wLength, timeout)); } -int PS4_SYSV_ABI sceUsbdLockEvents() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdBulkTransfer(SceUsbdDeviceHandle* dev_handle, u8 endpoint, u8* data, + s32 length, s32* actual_length, u32 timeout) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error( + libusb_bulk_transfer(dev_handle, endpoint, data, length, actual_length, timeout)); } -int PS4_SYSV_ABI sceUsbdLockEventWaiters() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdInterruptTransfer(SceUsbdDeviceHandle* dev_handle, u8 endpoint, u8* data, + s32 length, s32* actual_length, u32 timeout) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error( + libusb_interrupt_transfer(dev_handle, endpoint, data, length, actual_length, timeout)); } -int PS4_SYSV_ABI sceUsbdOpen() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdGetDescriptor(SceUsbdDeviceHandle* dev_handle, u8 descType, u8 descIndex, + u8* data, s32 length) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error( + libusb_get_descriptor(dev_handle, descType, descIndex, data, length)); } -int PS4_SYSV_ABI sceUsbdOpenDeviceWithVidPid() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdGetStringDescriptor(SceUsbdDeviceHandle* dev_handle, u8 desc_index, + u16 langid, u8* data, s32 length) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error( + libusb_get_string_descriptor(dev_handle, desc_index, langid, data, length)); } -int PS4_SYSV_ABI sceUsbdRefDevice() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdGetStringDescriptorAscii(SceUsbdDeviceHandle* dev_handle, u8 desc_index, + u8* data, s32 length) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error( + libusb_get_string_descriptor_ascii(dev_handle, desc_index, data, length)); } -int PS4_SYSV_ABI sceUsbdReleaseInterface() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdTryLockEvents() { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_try_lock_events(g_libusb_context); } -int PS4_SYSV_ABI sceUsbdResetDevice() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +void PS4_SYSV_ABI sceUsbdLockEvents() { + LOG_DEBUG(Lib_Usbd, "called"); + + libusb_lock_events(g_libusb_context); } -int PS4_SYSV_ABI sceUsbdSetConfiguration() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +void PS4_SYSV_ABI sceUsbdUnlockEvents() { + LOG_DEBUG(Lib_Usbd, "called"); + + libusb_unlock_events(g_libusb_context); } -int PS4_SYSV_ABI sceUsbdSetInterfaceAltSetting() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdEventHandlingOk() { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_event_handling_ok(g_libusb_context); } -int PS4_SYSV_ABI sceUsbdSetIsoPacketLengths() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdEventHandlerActive() { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_event_handler_active(g_libusb_context); } -int PS4_SYSV_ABI sceUsbdSubmitTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +void PS4_SYSV_ABI sceUsbdLockEventWaiters() { + LOG_DEBUG(Lib_Usbd, "called"); + + libusb_lock_event_waiters(g_libusb_context); } -int PS4_SYSV_ABI sceUsbdTryLockEvents() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +void PS4_SYSV_ABI sceUsbdUnlockEventWaiters() { + LOG_DEBUG(Lib_Usbd, "called"); + + libusb_unlock_event_waiters(g_libusb_context); } -int PS4_SYSV_ABI sceUsbdUnlockEvents() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdWaitForEvent(timeval* tv) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_wait_for_event(g_libusb_context, tv)); } -int PS4_SYSV_ABI sceUsbdUnlockEventWaiters() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdHandleEventsTimeout(timeval* tv) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_handle_events_timeout(g_libusb_context, tv)); } -int PS4_SYSV_ABI sceUsbdUnrefDevice() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdHandleEvents() { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_handle_events(g_libusb_context)); } -int PS4_SYSV_ABI sceUsbdWaitForEvent() { - LOG_ERROR(Lib_Usbd, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceUsbdHandleEventsLocked(timeval* tv) { + LOG_DEBUG(Lib_Usbd, "called"); + + return libusb_to_orbis_error(libusb_handle_events_locked(g_libusb_context, tv)); +} + +s32 PS4_SYSV_ABI sceUsbdCheckConnected(SceUsbdDeviceHandle* dev_handle) { + LOG_DEBUG(Lib_Usbd, "called"); + + // There's no libusb version of this function. + // Simulate by querying data. + + int config; + int r = libusb_get_configuration(dev_handle, &config); + + return libusb_to_orbis_error(r); } int PS4_SYSV_ABI Func_65F6EF33E38FFF50() { @@ -406,4 +550,4 @@ void RegisterlibSceUsbd(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("1WtDBgcgseA", "libSceUsbd", 1, "libSceUsbd", 1, 1, Func_D56B43060720B1E0); }; -} // namespace Libraries::Usbd +} // namespace Libraries::Usbd \ No newline at end of file diff --git a/src/core/libraries/usbd/usbd.h b/src/core/libraries/usbd/usbd.h index 4ed153587..3bd8134a7 100644 --- a/src/core/libraries/usbd/usbd.h +++ b/src/core/libraries/usbd/usbd.h @@ -1,76 +1,150 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX - FileCopyrightText : Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include "common/types.h" +extern "C" { +struct libusb_device; +struct libusb_device_handle; +struct libusb_device_descriptor; +struct libusb_config_descriptor; +struct libusb_transfer; +struct libusb_control_setup; +struct timeval; +} + namespace Core::Loader { class SymbolsResolver; } + namespace Libraries::Usbd { -int PS4_SYSV_ABI sceUsbdAllocTransfer(); -int PS4_SYSV_ABI sceUsbdAttachKernelDriver(); -int PS4_SYSV_ABI sceUsbdBulkTransfer(); -int PS4_SYSV_ABI sceUsbdCancelTransfer(); -int PS4_SYSV_ABI sceUsbdCheckConnected(); -int PS4_SYSV_ABI sceUsbdClaimInterface(); -int PS4_SYSV_ABI sceUsbdClearHalt(); -int PS4_SYSV_ABI sceUsbdClose(); -int PS4_SYSV_ABI sceUsbdControlTransfer(); -int PS4_SYSV_ABI sceUsbdControlTransferGetData(); -int PS4_SYSV_ABI sceUsbdControlTransferGetSetup(); -int PS4_SYSV_ABI sceUsbdDetachKernelDriver(); -int PS4_SYSV_ABI sceUsbdEventHandlerActive(); -int PS4_SYSV_ABI sceUsbdEventHandlingOk(); -int PS4_SYSV_ABI sceUsbdExit(); -int PS4_SYSV_ABI sceUsbdFillBulkTransfer(); -int PS4_SYSV_ABI sceUsbdFillControlSetup(); -int PS4_SYSV_ABI sceUsbdFillControlTransfer(); -int PS4_SYSV_ABI sceUsbdFillInterruptTransfer(); -int PS4_SYSV_ABI sceUsbdFillIsoTransfer(); -int PS4_SYSV_ABI sceUsbdFreeConfigDescriptor(); -int PS4_SYSV_ABI sceUsbdFreeDeviceList(); -int PS4_SYSV_ABI sceUsbdFreeTransfer(); -int PS4_SYSV_ABI sceUsbdGetActiveConfigDescriptor(); -int PS4_SYSV_ABI sceUsbdGetBusNumber(); -int PS4_SYSV_ABI sceUsbdGetConfigDescriptor(); -int PS4_SYSV_ABI sceUsbdGetConfigDescriptorByValue(); -int PS4_SYSV_ABI sceUsbdGetConfiguration(); -int PS4_SYSV_ABI sceUsbdGetDescriptor(); -int PS4_SYSV_ABI sceUsbdGetDevice(); -int PS4_SYSV_ABI sceUsbdGetDeviceAddress(); -int PS4_SYSV_ABI sceUsbdGetDeviceDescriptor(); -int PS4_SYSV_ABI sceUsbdGetDeviceList(); -int PS4_SYSV_ABI sceUsbdGetDeviceSpeed(); -int PS4_SYSV_ABI sceUsbdGetIsoPacketBuffer(); -int PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize(); -int PS4_SYSV_ABI sceUsbdGetMaxPacketSize(); -int PS4_SYSV_ABI sceUsbdGetStringDescriptor(); -int PS4_SYSV_ABI sceUsbdGetStringDescriptorAscii(); -int PS4_SYSV_ABI sceUsbdHandleEvents(); -int PS4_SYSV_ABI sceUsbdHandleEventsLocked(); -int PS4_SYSV_ABI sceUsbdHandleEventsTimeout(); -int PS4_SYSV_ABI sceUsbdInit(); -int PS4_SYSV_ABI sceUsbdInterruptTransfer(); -int PS4_SYSV_ABI sceUsbdKernelDriverActive(); -int PS4_SYSV_ABI sceUsbdLockEvents(); -int PS4_SYSV_ABI sceUsbdLockEventWaiters(); -int PS4_SYSV_ABI sceUsbdOpen(); -int PS4_SYSV_ABI sceUsbdOpenDeviceWithVidPid(); -int PS4_SYSV_ABI sceUsbdRefDevice(); -int PS4_SYSV_ABI sceUsbdReleaseInterface(); -int PS4_SYSV_ABI sceUsbdResetDevice(); -int PS4_SYSV_ABI sceUsbdSetConfiguration(); -int PS4_SYSV_ABI sceUsbdSetInterfaceAltSetting(); -int PS4_SYSV_ABI sceUsbdSetIsoPacketLengths(); -int PS4_SYSV_ABI sceUsbdSubmitTransfer(); -int PS4_SYSV_ABI sceUsbdTryLockEvents(); -int PS4_SYSV_ABI sceUsbdUnlockEvents(); -int PS4_SYSV_ABI sceUsbdUnlockEventWaiters(); -int PS4_SYSV_ABI sceUsbdUnrefDevice(); -int PS4_SYSV_ABI sceUsbdWaitForEvent(); +using SceUsbdDevice = libusb_device; +using SceUsbdDeviceHandle = libusb_device_handle; +using SceUsbdDeviceDescriptor = libusb_device_descriptor; +using SceUsbdConfigDescriptor = libusb_config_descriptor; +using SceUsbdTransfer = libusb_transfer; +using SceUsbdControlSetup = libusb_control_setup; +using SceUsbdTransferCallback = void (*)(SceUsbdTransfer* transfer); + +enum class SceUsbdSpeed : u32 { + UNKNOWN = 0, + LOW = 1, + FULL = 2, + HIGH = 3, + SUPER = 4, + SUPER_PLUS = 5 +}; + +s32 PS4_SYSV_ABI sceUsbdInit(); +void PS4_SYSV_ABI sceUsbdExit(); + +s64 PS4_SYSV_ABI sceUsbdGetDeviceList(SceUsbdDevice*** list); +void PS4_SYSV_ABI sceUsbdFreeDeviceList(SceUsbdDevice** list, s32 unref_devices); + +SceUsbdDevice* PS4_SYSV_ABI sceUsbdRefDevice(SceUsbdDevice* device); +void PS4_SYSV_ABI sceUsbdUnrefDevice(SceUsbdDevice* device); + +s32 PS4_SYSV_ABI sceUsbdGetConfiguration(SceUsbdDeviceHandle* dev_handle, s32* config); +s32 PS4_SYSV_ABI sceUsbdGetDeviceDescriptor(SceUsbdDevice* device, SceUsbdDeviceDescriptor* desc); +s32 PS4_SYSV_ABI sceUsbdGetActiveConfigDescriptor(SceUsbdDevice* device, + SceUsbdConfigDescriptor** config); +s32 PS4_SYSV_ABI sceUsbdGetConfigDescriptor(SceUsbdDevice* device, u8 config_index, + SceUsbdConfigDescriptor** config); +s32 PS4_SYSV_ABI sceUsbdGetConfigDescriptorByValue(SceUsbdDevice* device, u8 bConfigurationValue, + SceUsbdConfigDescriptor** config); +void PS4_SYSV_ABI sceUsbdFreeConfigDescriptor(SceUsbdConfigDescriptor* config); + +u8 PS4_SYSV_ABI sceUsbdGetBusNumber(SceUsbdDevice* device); +u8 PS4_SYSV_ABI sceUsbdGetDeviceAddress(SceUsbdDevice* device); + +SceUsbdSpeed PS4_SYSV_ABI sceUsbdGetDeviceSpeed(SceUsbdDevice* device); +s32 PS4_SYSV_ABI sceUsbdGetMaxPacketSize(SceUsbdDevice* device, u8 endpoint); +s32 PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize(SceUsbdDevice* device, u8 endpoint); + +s32 PS4_SYSV_ABI sceUsbdOpen(SceUsbdDevice* device, SceUsbdDeviceHandle** dev_handle); +void PS4_SYSV_ABI sceUsbdClose(SceUsbdDeviceHandle* dev_handle); +SceUsbdDevice* PS4_SYSV_ABI sceUsbdGetDevice(SceUsbdDeviceHandle* dev_handle); + +s32 PS4_SYSV_ABI sceUsbdSetConfiguration(SceUsbdDeviceHandle* dev_handle, s32 config); +s32 PS4_SYSV_ABI sceUsbdClaimInterface(SceUsbdDeviceHandle* dev_handle, s32 interface_number); +s32 PS4_SYSV_ABI sceUsbdReleaseInterface(SceUsbdDeviceHandle* dev_handle, s32 interface_number); + +SceUsbdDeviceHandle* PS4_SYSV_ABI sceUsbdOpenDeviceWithVidPid(u16 vendor_id, u16 product_id); + +s32 PS4_SYSV_ABI sceUsbdSetInterfaceAltSetting(SceUsbdDeviceHandle* dev_handle, + int interface_number, int alternate_setting); +s32 PS4_SYSV_ABI sceUsbdClearHalt(SceUsbdDeviceHandle* dev_handle, u8 endpoint); +s32 PS4_SYSV_ABI sceUsbdResetDevice(SceUsbdDeviceHandle* dev_handle); + +s32 PS4_SYSV_ABI sceUsbdKernelDriverActive(SceUsbdDeviceHandle* dev_handle, int interface_number); +s32 PS4_SYSV_ABI sceUsbdDetachKernelDriver(SceUsbdDeviceHandle* dev_handle, int interface_number); +s32 PS4_SYSV_ABI sceUsbdAttachKernelDriver(SceUsbdDeviceHandle* dev_handle, int interface_number); + +u8* PS4_SYSV_ABI sceUsbdControlTransferGetData(SceUsbdTransfer* transfer); +SceUsbdControlSetup* PS4_SYSV_ABI sceUsbdControlTransferGetSetup(SceUsbdTransfer* transfer); + +void PS4_SYSV_ABI sceUsbdFillControlSetup(u8* buf, u8 bmRequestType, u8 bRequest, u16 wValue, + u16 wIndex, u16 wLength); + +SceUsbdTransfer* PS4_SYSV_ABI sceUsbdAllocTransfer(int iso_packets); +s32 PS4_SYSV_ABI sceUsbdSubmitTransfer(SceUsbdTransfer* transfer); +s32 PS4_SYSV_ABI sceUsbdCancelTransfer(SceUsbdTransfer* transfer); +void PS4_SYSV_ABI sceUsbdFreeTransfer(SceUsbdTransfer* transfer); + +void PS4_SYSV_ABI sceUsbdFillControlTransfer(SceUsbdTransfer* transfer, + SceUsbdDeviceHandle* dev_handle, u8* buffer, + SceUsbdTransferCallback callback, void* user_data, + u32 timeout); +void PS4_SYSV_ABI sceUsbdFillBulkTransfer(SceUsbdTransfer* transfer, + SceUsbdDeviceHandle* dev_handle, u8 endpoint, u8* buffer, + s32 length, SceUsbdTransferCallback callback, + void* user_data, u32 timeout); +void PS4_SYSV_ABI sceUsbdFillInterruptTransfer(SceUsbdTransfer* transfer, + SceUsbdDeviceHandle* dev_handle, u8 endpoint, + u8* buffer, s32 length, + SceUsbdTransferCallback callback, void* user_data, + u32 timeout); +void PS4_SYSV_ABI sceUsbdFillIsoTransfer(SceUsbdTransfer* transfer, SceUsbdDeviceHandle* dev_handle, + u8 endpoint, u8* buffer, s32 length, s32 num_iso_packets, + SceUsbdTransferCallback callback, void* userData, + u32 timeout); + +void PS4_SYSV_ABI sceUsbdSetIsoPacketLengths(SceUsbdTransfer* transfer, u32 length); +u8* PS4_SYSV_ABI sceUsbdGetIsoPacketBuffer(SceUsbdTransfer* transfer, u32 packet); + +s32 PS4_SYSV_ABI sceUsbdControlTransfer(SceUsbdDeviceHandle* dev_handle, u8 request_type, + u8 bRequest, u16 wValue, u16 wIndex, u8* data, s32 wLength, + u32 timeout); +s32 PS4_SYSV_ABI sceUsbdBulkTransfer(SceUsbdDeviceHandle* dev_handle, u8 endpoint, u8* data, + s32 length, s32* actual_length, u32 timeout); +s32 PS4_SYSV_ABI sceUsbdInterruptTransfer(SceUsbdDeviceHandle* dev_handle, u8 endpoint, u8* data, + s32 length, s32* actual_length, u32 timeout); + +s32 PS4_SYSV_ABI sceUsbdGetDescriptor(SceUsbdDeviceHandle* dev_handle, u8 descType, u8 descIndex, + u8* data, s32 length); +s32 PS4_SYSV_ABI sceUsbdGetStringDescriptor(SceUsbdDeviceHandle* dev_handle, u8 desc_index, + u16 langid, u8* data, s32 length); +s32 PS4_SYSV_ABI sceUsbdGetStringDescriptorAscii(SceUsbdDeviceHandle* dev_handle, u8 desc_index, + u8* data, s32 length); + +s32 PS4_SYSV_ABI sceUsbdTryLockEvents(); +void PS4_SYSV_ABI sceUsbdLockEvents(); +void PS4_SYSV_ABI sceUsbdUnlockEvents(); +s32 PS4_SYSV_ABI sceUsbdEventHandlingOk(); +s32 PS4_SYSV_ABI sceUsbdEventHandlerActive(); +void PS4_SYSV_ABI sceUsbdLockEventWaiters(); +void PS4_SYSV_ABI sceUsbdUnlockEventWaiters(); +s32 PS4_SYSV_ABI sceUsbdWaitForEvent(timeval* tv); + +s32 PS4_SYSV_ABI sceUsbdHandleEventsTimeout(timeval* tv); +s32 PS4_SYSV_ABI sceUsbdHandleEvents(); +s32 PS4_SYSV_ABI sceUsbdHandleEventsLocked(timeval* tv); + +s32 PS4_SYSV_ABI sceUsbdCheckConnected(SceUsbdDeviceHandle* dev_handle); + int PS4_SYSV_ABI Func_65F6EF33E38FFF50(); int PS4_SYSV_ABI Func_97F056BAD90AADE7(); int PS4_SYSV_ABI Func_C55104A33B35B264();