diff --git a/src/core/libraries/usbd/usbd.cpp b/src/core/libraries/usbd/usbd.cpp index e5f6151eb..bd9a02ef3 100644 --- a/src/core/libraries/usbd/usbd.cpp +++ b/src/core/libraries/usbd/usbd.cpp @@ -10,6 +10,33 @@ #include #include +#include +#include + +namespace { + std::unordered_map g_transfer_callbacks; + std::mutex g_callback_mutex; + + void transfer_abi_callback(libusb_transfer* transfer) { + using SysVCallback = void (PS4_SYSV_ABI *)(Libraries::Usbd::SceUsbdTransfer*); + SysVCallback callback = nullptr; + + { + std::lock_guard lock(g_callback_mutex); + auto it = g_transfer_callbacks.find(transfer); + if (it != g_transfer_callbacks.end()) { + callback = (SysVCallback)it->second; + } + } + + if (callback) { + callback(transfer); + } else { + LOG_WARNING(Lib_Usbd, "No registered callback for USB transfer {:p}"); + } + } +} + namespace Libraries::Usbd { s32 libusb_to_orbis_error(int retVal) { @@ -276,6 +303,11 @@ s32 PS4_SYSV_ABI sceUsbdCancelTransfer(SceUsbdTransfer* transfer) { void PS4_SYSV_ABI sceUsbdFreeTransfer(SceUsbdTransfer* transfer) { LOG_DEBUG(Lib_Usbd, "called"); + { + std::lock_guard lock(g_callback_mutex); + g_transfer_callbacks.erase(transfer); + } + libusb_free_transfer(transfer); } @@ -305,7 +337,12 @@ void PS4_SYSV_ABI sceUsbdFillInterruptTransfer(SceUsbdTransfer* transfer, u32 timeout) { LOG_DEBUG(Lib_Usbd, "called"); - libusb_fill_interrupt_transfer(transfer, dev_handle, endpoint, buffer, length, callback, + { + std::lock_guard lock(g_callback_mutex); + g_transfer_callbacks[transfer] = callback; + } + + libusb_fill_interrupt_transfer(transfer, dev_handle, endpoint, buffer, length, transfer_abi_callback, user_data, timeout); }