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 <giorgosmrls@gmail.com>
This commit is contained in:
Joshua de Reeper 2025-03-31 17:55:21 +02:00 committed by GitHub
parent b0a12c02e1
commit 7533206d89
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 475 additions and 247 deletions

3
.gitmodules vendored
View file

@ -107,3 +107,6 @@
path = externals/MoltenVK/cereal path = externals/MoltenVK/cereal
url = https://github.com/USCiLab/cereal url = https://github.com/USCiLab/cereal
shallow = true shallow = true
[submodule "externals/libusb"]
path = externals/libusb
url = https://github.com/libusb/libusb-cmake.git

View file

@ -224,6 +224,7 @@ find_package(xxHash 0.8.2 MODULE)
find_package(ZLIB 1.3 MODULE) find_package(ZLIB 1.3 MODULE)
find_package(Zydis 5.0.0 CONFIG) find_package(Zydis 5.0.0 CONFIG)
find_package(pugixml 1.14 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) if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR NOT MSVC)
find_package(cryptopp 8.9.0 MODULE) find_package(cryptopp 8.9.0 MODULE)
@ -1061,7 +1062,7 @@ endif()
create_target_directory_groups(shadps4) 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 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(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") target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h")

View file

@ -201,6 +201,11 @@ if (NOT TARGET pugixml::pugixml)
add_subdirectory(pugixml) add_subdirectory(pugixml)
endif() endif()
# libusb
if (NOT TARGET usb-1.0)
add_subdirectory(libusb)
endif()
# Discord RPC # Discord RPC
if (ENABLE_DISCORD_RPC) if (ENABLE_DISCORD_RPC)
add_subdirectory(discord-rpc) add_subdirectory(discord-rpc)

1
externals/libusb vendored Submodule

@ -0,0 +1 @@
Subproject commit 8f0b4a38fc3eefa2b26a99dff89e1c12bf37afd4

View file

@ -7,311 +7,455 @@
#include "core/libraries/libs.h" #include "core/libraries/libs.h"
#include "usbd.h" #include "usbd.h"
#include <fmt/format.h>
#include <libusb.h>
namespace Libraries::Usbd { namespace Libraries::Usbd {
int PS4_SYSV_ABI sceUsbdAllocTransfer() { s32 libusb_to_orbis_error(int retVal) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); if (retVal == LIBUSB_ERROR_OTHER)
return ORBIS_OK; 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() { libusb_context* g_libusb_context;
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
return ORBIS_OK; #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() { void PS4_SYSV_ABI sceUsbdExit() {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
libusb_exit(g_libusb_context);
} }
int PS4_SYSV_ABI sceUsbdCancelTransfer() { s64 PS4_SYSV_ABI sceUsbdGetDeviceList(SceUsbdDevice*** list) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_to_orbis_error(libusb_get_device_list(g_libusb_context, list));
} }
int PS4_SYSV_ABI sceUsbdCheckConnected() { void PS4_SYSV_ABI sceUsbdFreeDeviceList(SceUsbdDevice** list, s32 unref_devices) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
libusb_free_device_list(list, unref_devices);
} }
int PS4_SYSV_ABI sceUsbdClaimInterface() { SceUsbdDevice* PS4_SYSV_ABI sceUsbdRefDevice(SceUsbdDevice* device) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_ref_device(device);
} }
int PS4_SYSV_ABI sceUsbdClearHalt() { void PS4_SYSV_ABI sceUsbdUnrefDevice(SceUsbdDevice* device) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
libusb_unref_device(device);
} }
int PS4_SYSV_ABI sceUsbdClose() { s32 PS4_SYSV_ABI sceUsbdGetConfiguration(SceUsbdDeviceHandle* dev_handle, s32* config) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_to_orbis_error(libusb_get_configuration(dev_handle, config));
} }
int PS4_SYSV_ABI sceUsbdControlTransfer() { s32 PS4_SYSV_ABI sceUsbdGetDeviceDescriptor(SceUsbdDevice* device, SceUsbdDeviceDescriptor* desc) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_to_orbis_error(libusb_get_device_descriptor(device, desc));
} }
int PS4_SYSV_ABI sceUsbdControlTransferGetData() { s32 PS4_SYSV_ABI sceUsbdGetActiveConfigDescriptor(SceUsbdDevice* device,
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); SceUsbdConfigDescriptor** config) {
return ORBIS_OK; LOG_DEBUG(Lib_Usbd, "called");
return libusb_to_orbis_error(libusb_get_active_config_descriptor(device, config));
} }
int PS4_SYSV_ABI sceUsbdControlTransferGetSetup() { s32 PS4_SYSV_ABI sceUsbdGetConfigDescriptor(SceUsbdDevice* device, u8 config_index,
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); SceUsbdConfigDescriptor** config) {
return ORBIS_OK; LOG_DEBUG(Lib_Usbd, "called");
return libusb_to_orbis_error(libusb_get_config_descriptor(device, config_index, config));
} }
int PS4_SYSV_ABI sceUsbdDetachKernelDriver() { s32 PS4_SYSV_ABI sceUsbdGetConfigDescriptorByValue(SceUsbdDevice* device, u8 bConfigurationValue,
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); SceUsbdConfigDescriptor** config) {
return ORBIS_OK; LOG_DEBUG(Lib_Usbd, "called");
return libusb_to_orbis_error(
libusb_get_config_descriptor_by_value(device, bConfigurationValue, config));
} }
int PS4_SYSV_ABI sceUsbdEventHandlerActive() { void PS4_SYSV_ABI sceUsbdFreeConfigDescriptor(SceUsbdConfigDescriptor* config) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
libusb_free_config_descriptor(config);
} }
int PS4_SYSV_ABI sceUsbdEventHandlingOk() { u8 PS4_SYSV_ABI sceUsbdGetBusNumber(SceUsbdDevice* device) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_get_bus_number(device);
} }
int PS4_SYSV_ABI sceUsbdExit() { u8 PS4_SYSV_ABI sceUsbdGetDeviceAddress(SceUsbdDevice* device) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_get_device_address(device);
} }
int PS4_SYSV_ABI sceUsbdFillBulkTransfer() { SceUsbdSpeed PS4_SYSV_ABI sceUsbdGetDeviceSpeed(SceUsbdDevice* device) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return static_cast<SceUsbdSpeed>(libusb_get_device_speed(device));
} }
int PS4_SYSV_ABI sceUsbdFillControlSetup() { s32 PS4_SYSV_ABI sceUsbdGetMaxPacketSize(SceUsbdDevice* device, u8 endpoint) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_to_orbis_error(libusb_get_max_packet_size(device, endpoint));
} }
int PS4_SYSV_ABI sceUsbdFillControlTransfer() { s32 PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize(SceUsbdDevice* device, u8 endpoint) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_to_orbis_error(libusb_get_max_iso_packet_size(device, endpoint));
} }
int PS4_SYSV_ABI sceUsbdFillInterruptTransfer() { s32 PS4_SYSV_ABI sceUsbdOpen(SceUsbdDevice* device, SceUsbdDeviceHandle** dev_handle) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_to_orbis_error(libusb_open(device, dev_handle));
} }
int PS4_SYSV_ABI sceUsbdFillIsoTransfer() { void PS4_SYSV_ABI sceUsbdClose(SceUsbdDeviceHandle* dev_handle) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
libusb_close(dev_handle);
} }
int PS4_SYSV_ABI sceUsbdFreeConfigDescriptor() { SceUsbdDevice* PS4_SYSV_ABI sceUsbdGetDevice(SceUsbdDeviceHandle* dev_handle) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_get_device(dev_handle);
} }
int PS4_SYSV_ABI sceUsbdFreeDeviceList() { s32 PS4_SYSV_ABI sceUsbdSetConfiguration(SceUsbdDeviceHandle* dev_handle, s32 config) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_to_orbis_error(libusb_set_configuration(dev_handle, config));
} }
int PS4_SYSV_ABI sceUsbdFreeTransfer() { s32 PS4_SYSV_ABI sceUsbdClaimInterface(SceUsbdDeviceHandle* dev_handle, s32 interface_number) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
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() { s32 PS4_SYSV_ABI sceUsbdReleaseInterface(SceUsbdDeviceHandle* dev_handle, s32 interface_number) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_to_orbis_error(libusb_release_interface(dev_handle, interface_number));
} }
int PS4_SYSV_ABI sceUsbdGetBusNumber() { SceUsbdDeviceHandle* PS4_SYSV_ABI sceUsbdOpenDeviceWithVidPid(u16 vendor_id, u16 product_id) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_open_device_with_vid_pid(g_libusb_context, vendor_id, product_id);
} }
int PS4_SYSV_ABI sceUsbdGetConfigDescriptor() { s32 PS4_SYSV_ABI sceUsbdSetInterfaceAltSetting(SceUsbdDeviceHandle* dev_handle,
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); int interface_number, int alternate_setting) {
return ORBIS_OK; 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() { s32 PS4_SYSV_ABI sceUsbdClearHalt(SceUsbdDeviceHandle* dev_handle, uint8_t endpoint) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_to_orbis_error(libusb_clear_halt(dev_handle, endpoint));
} }
int PS4_SYSV_ABI sceUsbdGetConfiguration() { s32 PS4_SYSV_ABI sceUsbdResetDevice(SceUsbdDeviceHandle* dev_handle) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_to_orbis_error(libusb_reset_device(dev_handle));
} }
int PS4_SYSV_ABI sceUsbdGetDescriptor() { s32 PS4_SYSV_ABI sceUsbdKernelDriverActive(SceUsbdDeviceHandle* dev_handle, int interface_number) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
#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() { s32 PS4_SYSV_ABI sceUsbdDetachKernelDriver(SceUsbdDeviceHandle* dev_handle, int interface_number) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
#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() { s32 PS4_SYSV_ABI sceUsbdAttachKernelDriver(SceUsbdDeviceHandle* dev_handle, int interface_number) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
#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() { u8* PS4_SYSV_ABI sceUsbdControlTransferGetData(SceUsbdTransfer* transfer) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_control_transfer_get_data(transfer);
} }
int PS4_SYSV_ABI sceUsbdGetDeviceList() { SceUsbdControlSetup* PS4_SYSV_ABI sceUsbdControlTransferGetSetup(SceUsbdTransfer* transfer) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_control_transfer_get_setup(transfer);
} }
int PS4_SYSV_ABI sceUsbdGetDeviceSpeed() { void PS4_SYSV_ABI sceUsbdFillControlSetup(u8* buf, u8 bmRequestType, u8 bRequest, u16 wValue,
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); u16 wIndex, u16 wLength) {
return ORBIS_OK; LOG_DEBUG(Lib_Usbd, "called");
return libusb_fill_control_setup(buf, bmRequestType, bRequest, wValue, wIndex, wLength);
} }
int PS4_SYSV_ABI sceUsbdGetIsoPacketBuffer() { SceUsbdTransfer* PS4_SYSV_ABI sceUsbdAllocTransfer(int iso_packets) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_alloc_transfer(iso_packets);
} }
int PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize() { s32 PS4_SYSV_ABI sceUsbdSubmitTransfer(SceUsbdTransfer* transfer) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_to_orbis_error(libusb_submit_transfer(transfer));
} }
int PS4_SYSV_ABI sceUsbdGetMaxPacketSize() { s32 PS4_SYSV_ABI sceUsbdCancelTransfer(SceUsbdTransfer* transfer) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_to_orbis_error(libusb_cancel_transfer(transfer));
} }
int PS4_SYSV_ABI sceUsbdGetStringDescriptor() { void PS4_SYSV_ABI sceUsbdFreeTransfer(SceUsbdTransfer* transfer) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
libusb_free_transfer(transfer);
} }
int PS4_SYSV_ABI sceUsbdGetStringDescriptorAscii() { void PS4_SYSV_ABI sceUsbdFillControlTransfer(SceUsbdTransfer* transfer,
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); SceUsbdDeviceHandle* dev_handle, u8* buffer,
return ORBIS_OK; 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() { void PS4_SYSV_ABI sceUsbdFillBulkTransfer(SceUsbdTransfer* transfer,
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); SceUsbdDeviceHandle* dev_handle, uint8_t endpoint,
return ORBIS_OK; 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() { void PS4_SYSV_ABI sceUsbdFillInterruptTransfer(SceUsbdTransfer* transfer,
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); SceUsbdDeviceHandle* dev_handle, uint8_t endpoint,
return ORBIS_OK; 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() { void PS4_SYSV_ABI sceUsbdFillIsoTransfer(SceUsbdTransfer* transfer, SceUsbdDeviceHandle* dev_handle,
LOG_DEBUG(Lib_Usbd, "(STUBBED) called"); uint8_t endpoint, u8* buffer, s32 length,
return ORBIS_OK; 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() { void PS4_SYSV_ABI sceUsbdSetIsoPacketLengths(SceUsbdTransfer* transfer, u32 length) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return 0x80240005; // Skip
libusb_set_iso_packet_lengths(transfer, length);
} }
int PS4_SYSV_ABI sceUsbdInterruptTransfer() { u8* PS4_SYSV_ABI sceUsbdGetIsoPacketBuffer(SceUsbdTransfer* transfer, u32 packet) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_get_iso_packet_buffer(transfer, packet);
} }
int PS4_SYSV_ABI sceUsbdKernelDriverActive() { s32 PS4_SYSV_ABI sceUsbdControlTransfer(SceUsbdDeviceHandle* dev_handle, u8 request_type,
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); u8 bRequest, u16 wValue, u16 wIndex, u8* data, s32 wLength,
return ORBIS_OK; 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() { s32 PS4_SYSV_ABI sceUsbdBulkTransfer(SceUsbdDeviceHandle* dev_handle, u8 endpoint, u8* data,
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); s32 length, s32* actual_length, u32 timeout) {
return ORBIS_OK; 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() { s32 PS4_SYSV_ABI sceUsbdInterruptTransfer(SceUsbdDeviceHandle* dev_handle, u8 endpoint, u8* data,
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); s32 length, s32* actual_length, u32 timeout) {
return ORBIS_OK; 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() { s32 PS4_SYSV_ABI sceUsbdGetDescriptor(SceUsbdDeviceHandle* dev_handle, u8 descType, u8 descIndex,
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); u8* data, s32 length) {
return ORBIS_OK; LOG_DEBUG(Lib_Usbd, "called");
return libusb_to_orbis_error(
libusb_get_descriptor(dev_handle, descType, descIndex, data, length));
} }
int PS4_SYSV_ABI sceUsbdOpenDeviceWithVidPid() { s32 PS4_SYSV_ABI sceUsbdGetStringDescriptor(SceUsbdDeviceHandle* dev_handle, u8 desc_index,
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); u16 langid, u8* data, s32 length) {
return ORBIS_OK; 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() { s32 PS4_SYSV_ABI sceUsbdGetStringDescriptorAscii(SceUsbdDeviceHandle* dev_handle, u8 desc_index,
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); u8* data, s32 length) {
return ORBIS_OK; 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() { s32 PS4_SYSV_ABI sceUsbdTryLockEvents() {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_try_lock_events(g_libusb_context);
} }
int PS4_SYSV_ABI sceUsbdResetDevice() { void PS4_SYSV_ABI sceUsbdLockEvents() {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
libusb_lock_events(g_libusb_context);
} }
int PS4_SYSV_ABI sceUsbdSetConfiguration() { void PS4_SYSV_ABI sceUsbdUnlockEvents() {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
libusb_unlock_events(g_libusb_context);
} }
int PS4_SYSV_ABI sceUsbdSetInterfaceAltSetting() { s32 PS4_SYSV_ABI sceUsbdEventHandlingOk() {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_event_handling_ok(g_libusb_context);
} }
int PS4_SYSV_ABI sceUsbdSetIsoPacketLengths() { s32 PS4_SYSV_ABI sceUsbdEventHandlerActive() {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_event_handler_active(g_libusb_context);
} }
int PS4_SYSV_ABI sceUsbdSubmitTransfer() { void PS4_SYSV_ABI sceUsbdLockEventWaiters() {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
libusb_lock_event_waiters(g_libusb_context);
} }
int PS4_SYSV_ABI sceUsbdTryLockEvents() { void PS4_SYSV_ABI sceUsbdUnlockEventWaiters() {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
libusb_unlock_event_waiters(g_libusb_context);
} }
int PS4_SYSV_ABI sceUsbdUnlockEvents() { s32 PS4_SYSV_ABI sceUsbdWaitForEvent(timeval* tv) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_to_orbis_error(libusb_wait_for_event(g_libusb_context, tv));
} }
int PS4_SYSV_ABI sceUsbdUnlockEventWaiters() { s32 PS4_SYSV_ABI sceUsbdHandleEventsTimeout(timeval* tv) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_to_orbis_error(libusb_handle_events_timeout(g_libusb_context, tv));
} }
int PS4_SYSV_ABI sceUsbdUnrefDevice() { s32 PS4_SYSV_ABI sceUsbdHandleEvents() {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
return libusb_to_orbis_error(libusb_handle_events(g_libusb_context));
} }
int PS4_SYSV_ABI sceUsbdWaitForEvent() { s32 PS4_SYSV_ABI sceUsbdHandleEventsLocked(timeval* tv) {
LOG_ERROR(Lib_Usbd, "(STUBBED) called"); LOG_DEBUG(Lib_Usbd, "called");
return ORBIS_OK;
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() { 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); LIB_FUNCTION("1WtDBgcgseA", "libSceUsbd", 1, "libSceUsbd", 1, 1, Func_D56B43060720B1E0);
}; };
} // namespace Libraries::Usbd } // namespace Libraries::Usbd

View file

@ -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 // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
#include "common/types.h" #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 { namespace Core::Loader {
class SymbolsResolver; class SymbolsResolver;
} }
namespace Libraries::Usbd { namespace Libraries::Usbd {
int PS4_SYSV_ABI sceUsbdAllocTransfer(); using SceUsbdDevice = libusb_device;
int PS4_SYSV_ABI sceUsbdAttachKernelDriver(); using SceUsbdDeviceHandle = libusb_device_handle;
int PS4_SYSV_ABI sceUsbdBulkTransfer(); using SceUsbdDeviceDescriptor = libusb_device_descriptor;
int PS4_SYSV_ABI sceUsbdCancelTransfer(); using SceUsbdConfigDescriptor = libusb_config_descriptor;
int PS4_SYSV_ABI sceUsbdCheckConnected(); using SceUsbdTransfer = libusb_transfer;
int PS4_SYSV_ABI sceUsbdClaimInterface(); using SceUsbdControlSetup = libusb_control_setup;
int PS4_SYSV_ABI sceUsbdClearHalt(); using SceUsbdTransferCallback = void (*)(SceUsbdTransfer* transfer);
int PS4_SYSV_ABI sceUsbdClose();
int PS4_SYSV_ABI sceUsbdControlTransfer(); enum class SceUsbdSpeed : u32 {
int PS4_SYSV_ABI sceUsbdControlTransferGetData(); UNKNOWN = 0,
int PS4_SYSV_ABI sceUsbdControlTransferGetSetup(); LOW = 1,
int PS4_SYSV_ABI sceUsbdDetachKernelDriver(); FULL = 2,
int PS4_SYSV_ABI sceUsbdEventHandlerActive(); HIGH = 3,
int PS4_SYSV_ABI sceUsbdEventHandlingOk(); SUPER = 4,
int PS4_SYSV_ABI sceUsbdExit(); SUPER_PLUS = 5
int PS4_SYSV_ABI sceUsbdFillBulkTransfer(); };
int PS4_SYSV_ABI sceUsbdFillControlSetup();
int PS4_SYSV_ABI sceUsbdFillControlTransfer(); s32 PS4_SYSV_ABI sceUsbdInit();
int PS4_SYSV_ABI sceUsbdFillInterruptTransfer(); void PS4_SYSV_ABI sceUsbdExit();
int PS4_SYSV_ABI sceUsbdFillIsoTransfer();
int PS4_SYSV_ABI sceUsbdFreeConfigDescriptor(); s64 PS4_SYSV_ABI sceUsbdGetDeviceList(SceUsbdDevice*** list);
int PS4_SYSV_ABI sceUsbdFreeDeviceList(); void PS4_SYSV_ABI sceUsbdFreeDeviceList(SceUsbdDevice** list, s32 unref_devices);
int PS4_SYSV_ABI sceUsbdFreeTransfer();
int PS4_SYSV_ABI sceUsbdGetActiveConfigDescriptor(); SceUsbdDevice* PS4_SYSV_ABI sceUsbdRefDevice(SceUsbdDevice* device);
int PS4_SYSV_ABI sceUsbdGetBusNumber(); void PS4_SYSV_ABI sceUsbdUnrefDevice(SceUsbdDevice* device);
int PS4_SYSV_ABI sceUsbdGetConfigDescriptor();
int PS4_SYSV_ABI sceUsbdGetConfigDescriptorByValue(); s32 PS4_SYSV_ABI sceUsbdGetConfiguration(SceUsbdDeviceHandle* dev_handle, s32* config);
int PS4_SYSV_ABI sceUsbdGetConfiguration(); s32 PS4_SYSV_ABI sceUsbdGetDeviceDescriptor(SceUsbdDevice* device, SceUsbdDeviceDescriptor* desc);
int PS4_SYSV_ABI sceUsbdGetDescriptor(); s32 PS4_SYSV_ABI sceUsbdGetActiveConfigDescriptor(SceUsbdDevice* device,
int PS4_SYSV_ABI sceUsbdGetDevice(); SceUsbdConfigDescriptor** config);
int PS4_SYSV_ABI sceUsbdGetDeviceAddress(); s32 PS4_SYSV_ABI sceUsbdGetConfigDescriptor(SceUsbdDevice* device, u8 config_index,
int PS4_SYSV_ABI sceUsbdGetDeviceDescriptor(); SceUsbdConfigDescriptor** config);
int PS4_SYSV_ABI sceUsbdGetDeviceList(); s32 PS4_SYSV_ABI sceUsbdGetConfigDescriptorByValue(SceUsbdDevice* device, u8 bConfigurationValue,
int PS4_SYSV_ABI sceUsbdGetDeviceSpeed(); SceUsbdConfigDescriptor** config);
int PS4_SYSV_ABI sceUsbdGetIsoPacketBuffer(); void PS4_SYSV_ABI sceUsbdFreeConfigDescriptor(SceUsbdConfigDescriptor* config);
int PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize();
int PS4_SYSV_ABI sceUsbdGetMaxPacketSize(); u8 PS4_SYSV_ABI sceUsbdGetBusNumber(SceUsbdDevice* device);
int PS4_SYSV_ABI sceUsbdGetStringDescriptor(); u8 PS4_SYSV_ABI sceUsbdGetDeviceAddress(SceUsbdDevice* device);
int PS4_SYSV_ABI sceUsbdGetStringDescriptorAscii();
int PS4_SYSV_ABI sceUsbdHandleEvents(); SceUsbdSpeed PS4_SYSV_ABI sceUsbdGetDeviceSpeed(SceUsbdDevice* device);
int PS4_SYSV_ABI sceUsbdHandleEventsLocked(); s32 PS4_SYSV_ABI sceUsbdGetMaxPacketSize(SceUsbdDevice* device, u8 endpoint);
int PS4_SYSV_ABI sceUsbdHandleEventsTimeout(); s32 PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize(SceUsbdDevice* device, u8 endpoint);
int PS4_SYSV_ABI sceUsbdInit();
int PS4_SYSV_ABI sceUsbdInterruptTransfer(); s32 PS4_SYSV_ABI sceUsbdOpen(SceUsbdDevice* device, SceUsbdDeviceHandle** dev_handle);
int PS4_SYSV_ABI sceUsbdKernelDriverActive(); void PS4_SYSV_ABI sceUsbdClose(SceUsbdDeviceHandle* dev_handle);
int PS4_SYSV_ABI sceUsbdLockEvents(); SceUsbdDevice* PS4_SYSV_ABI sceUsbdGetDevice(SceUsbdDeviceHandle* dev_handle);
int PS4_SYSV_ABI sceUsbdLockEventWaiters();
int PS4_SYSV_ABI sceUsbdOpen(); s32 PS4_SYSV_ABI sceUsbdSetConfiguration(SceUsbdDeviceHandle* dev_handle, s32 config);
int PS4_SYSV_ABI sceUsbdOpenDeviceWithVidPid(); s32 PS4_SYSV_ABI sceUsbdClaimInterface(SceUsbdDeviceHandle* dev_handle, s32 interface_number);
int PS4_SYSV_ABI sceUsbdRefDevice(); s32 PS4_SYSV_ABI sceUsbdReleaseInterface(SceUsbdDeviceHandle* dev_handle, s32 interface_number);
int PS4_SYSV_ABI sceUsbdReleaseInterface();
int PS4_SYSV_ABI sceUsbdResetDevice(); SceUsbdDeviceHandle* PS4_SYSV_ABI sceUsbdOpenDeviceWithVidPid(u16 vendor_id, u16 product_id);
int PS4_SYSV_ABI sceUsbdSetConfiguration();
int PS4_SYSV_ABI sceUsbdSetInterfaceAltSetting(); s32 PS4_SYSV_ABI sceUsbdSetInterfaceAltSetting(SceUsbdDeviceHandle* dev_handle,
int PS4_SYSV_ABI sceUsbdSetIsoPacketLengths(); int interface_number, int alternate_setting);
int PS4_SYSV_ABI sceUsbdSubmitTransfer(); s32 PS4_SYSV_ABI sceUsbdClearHalt(SceUsbdDeviceHandle* dev_handle, u8 endpoint);
int PS4_SYSV_ABI sceUsbdTryLockEvents(); s32 PS4_SYSV_ABI sceUsbdResetDevice(SceUsbdDeviceHandle* dev_handle);
int PS4_SYSV_ABI sceUsbdUnlockEvents();
int PS4_SYSV_ABI sceUsbdUnlockEventWaiters(); s32 PS4_SYSV_ABI sceUsbdKernelDriverActive(SceUsbdDeviceHandle* dev_handle, int interface_number);
int PS4_SYSV_ABI sceUsbdUnrefDevice(); s32 PS4_SYSV_ABI sceUsbdDetachKernelDriver(SceUsbdDeviceHandle* dev_handle, int interface_number);
int PS4_SYSV_ABI sceUsbdWaitForEvent(); 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_65F6EF33E38FFF50();
int PS4_SYSV_ABI Func_97F056BAD90AADE7(); int PS4_SYSV_ABI Func_97F056BAD90AADE7();
int PS4_SYSV_ABI Func_C55104A33B35B264(); int PS4_SYSV_ABI Func_C55104A33B35B264();