mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-09 21:31:04 +00:00
usbd: Implement usb backend system (#3737)
* initial impl * reviews * upstreamed deReaperJosh changes * fixed config.cpp --------- Co-authored-by: georgemoralis <giorgosmrls@gmail.com>
This commit is contained in:
@@ -532,6 +532,7 @@ set(RANDOM_LIB src/core/libraries/random/random.cpp
|
|||||||
|
|
||||||
set(USBD_LIB src/core/libraries/usbd/usbd.cpp
|
set(USBD_LIB src/core/libraries/usbd/usbd.cpp
|
||||||
src/core/libraries/usbd/usbd.h
|
src/core/libraries/usbd/usbd.h
|
||||||
|
src/core/libraries/usbd/usb_backend.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(FIBER_LIB src/core/libraries/fiber/fiber_context.s
|
set(FIBER_LIB src/core/libraries/fiber/fiber_context.s
|
||||||
|
|||||||
@@ -208,6 +208,9 @@ std::filesystem::path save_data_path = {};
|
|||||||
// Settings
|
// Settings
|
||||||
ConfigEntry<u32> m_language(1); // english
|
ConfigEntry<u32> m_language(1); // english
|
||||||
|
|
||||||
|
// USB Device
|
||||||
|
static ConfigEntry<int> usbDeviceBackend(UsbBackendType::Real);
|
||||||
|
|
||||||
// Keys
|
// Keys
|
||||||
static string trophyKey = "";
|
static string trophyKey = "";
|
||||||
|
|
||||||
@@ -817,6 +820,14 @@ void setRcasAttenuation(int value, bool is_game_specific) {
|
|||||||
rcasAttenuation.set(value, is_game_specific);
|
rcasAttenuation.set(value, is_game_specific);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getUsbDeviceBackend() {
|
||||||
|
return usbDeviceBackend.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUsbDeviceBackend(int value, bool is_game_specific) {
|
||||||
|
usbDeviceBackend.set(value, is_game_specific);
|
||||||
|
}
|
||||||
|
|
||||||
bool getLoadAutoPatches() {
|
bool getLoadAutoPatches() {
|
||||||
return load_auto_patches;
|
return load_auto_patches;
|
||||||
}
|
}
|
||||||
@@ -881,6 +892,7 @@ void load(const std::filesystem::path& path, bool is_game_specific) {
|
|||||||
isMotionControlsEnabled.setFromToml(input, "isMotionControlsEnabled", is_game_specific);
|
isMotionControlsEnabled.setFromToml(input, "isMotionControlsEnabled", is_game_specific);
|
||||||
useUnifiedInputConfig.setFromToml(input, "useUnifiedInputConfig", is_game_specific);
|
useUnifiedInputConfig.setFromToml(input, "useUnifiedInputConfig", is_game_specific);
|
||||||
backgroundControllerInput.setFromToml(input, "backgroundControllerInput", is_game_specific);
|
backgroundControllerInput.setFromToml(input, "backgroundControllerInput", is_game_specific);
|
||||||
|
usbDeviceBackend.setFromToml(input, "usbDeviceBackend", is_game_specific);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.contains("Audio")) {
|
if (data.contains("Audio")) {
|
||||||
@@ -1063,6 +1075,7 @@ void save(const std::filesystem::path& path, bool is_game_specific) {
|
|||||||
is_game_specific);
|
is_game_specific);
|
||||||
backgroundControllerInput.setTomlValue(data, "Input", "backgroundControllerInput",
|
backgroundControllerInput.setTomlValue(data, "Input", "backgroundControllerInput",
|
||||||
is_game_specific);
|
is_game_specific);
|
||||||
|
usbDeviceBackend.setTomlValue(data, "Input", "usbDeviceBackend", is_game_specific);
|
||||||
|
|
||||||
micDevice.setTomlValue(data, "Audio", "micDevice", is_game_specific);
|
micDevice.setTomlValue(data, "Audio", "micDevice", is_game_specific);
|
||||||
mainOutputDevice.setTomlValue(data, "Audio", "mainOutputDevice", is_game_specific);
|
mainOutputDevice.setTomlValue(data, "Audio", "mainOutputDevice", is_game_specific);
|
||||||
@@ -1194,6 +1207,7 @@ void setDefaultValues(bool is_game_specific) {
|
|||||||
cursorHideTimeout.set(5, is_game_specific);
|
cursorHideTimeout.set(5, is_game_specific);
|
||||||
isMotionControlsEnabled.set(true, is_game_specific);
|
isMotionControlsEnabled.set(true, is_game_specific);
|
||||||
backgroundControllerInput.set(false, is_game_specific);
|
backgroundControllerInput.set(false, is_game_specific);
|
||||||
|
usbDeviceBackend.set(UsbBackendType::Real, is_game_specific);
|
||||||
|
|
||||||
// GS - Audio
|
// GS - Audio
|
||||||
micDevice.set("Default Device", is_game_specific);
|
micDevice.set("Default Device", is_game_specific);
|
||||||
|
|||||||
@@ -151,6 +151,10 @@ void setSysModulesPath(const std::filesystem::path& path);
|
|||||||
bool getLoadAutoPatches();
|
bool getLoadAutoPatches();
|
||||||
void setLoadAutoPatches(bool enable);
|
void setLoadAutoPatches(bool enable);
|
||||||
|
|
||||||
|
enum UsbBackendType : int { Real, SkylandersPortal, InfinityBase, DimensionsToypad };
|
||||||
|
int getUsbDeviceBackend();
|
||||||
|
void setUsbDeviceBackend(int value, bool is_game_specific = false);
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
std::filesystem::path GetSaveDataPath();
|
std::filesystem::path GetSaveDataPath();
|
||||||
std::string getUserName();
|
std::string getUserName();
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "core/libraries/audio/audioout.h"
|
#include "core/libraries/audio/audioout.h"
|
||||||
#include "input/input_handler.h"
|
#include "input/input_handler.h"
|
||||||
#include "sdl_window.h"
|
#include "sdl_window.h"
|
||||||
|
#include "src/core/libraries/usbd/usbd.h"
|
||||||
#include "video_core/renderer_vulkan/vk_presenter.h"
|
#include "video_core/renderer_vulkan/vk_presenter.h"
|
||||||
|
|
||||||
extern std::unique_ptr<Vulkan::Presenter> presenter;
|
extern std::unique_ptr<Vulkan::Presenter> presenter;
|
||||||
@@ -169,6 +170,43 @@ void IPC::InputLoop() {
|
|||||||
presenter->GetFsrSettingsRef().rcas_attenuation =
|
presenter->GetFsrSettingsRef().rcas_attenuation =
|
||||||
static_cast<float>(value / 1000.0f);
|
static_cast<float>(value / 1000.0f);
|
||||||
}
|
}
|
||||||
|
} else if (cmd == "USB_LOAD_FIGURE") {
|
||||||
|
const auto ref = Libraries::Usbd::usb_backend->GetImplRef();
|
||||||
|
if (ref) {
|
||||||
|
const std::string& file_name = next_str();
|
||||||
|
const u8 pad = next_u64();
|
||||||
|
const u8 slot = next_u64();
|
||||||
|
ref->LoadFigure(file_name, pad, slot);
|
||||||
|
}
|
||||||
|
} else if (cmd == "USB_REMOVE_FIGURE") {
|
||||||
|
const auto ref = Libraries::Usbd::usb_backend->GetImplRef();
|
||||||
|
if (ref) {
|
||||||
|
const u8 pad = next_u64();
|
||||||
|
const u8 slot = next_u64();
|
||||||
|
const bool full_remove = next_u64() != 0;
|
||||||
|
ref->RemoveFigure(pad, slot, full_remove);
|
||||||
|
}
|
||||||
|
} else if (cmd == "USB_MOVE_FIGURE") {
|
||||||
|
const auto ref = Libraries::Usbd::usb_backend->GetImplRef();
|
||||||
|
if (ref) {
|
||||||
|
const u8 new_pad = next_u64();
|
||||||
|
const u8 new_index = next_u64();
|
||||||
|
const u8 old_pad = next_u64();
|
||||||
|
const u8 old_index = next_u64();
|
||||||
|
ref->MoveFigure(new_pad, new_index, old_pad, old_index);
|
||||||
|
}
|
||||||
|
} else if (cmd == "USB_TEMP_REMOVE_FIGURE") {
|
||||||
|
const auto ref = Libraries::Usbd::usb_backend->GetImplRef();
|
||||||
|
if (ref) {
|
||||||
|
const u8 index = next_u64();
|
||||||
|
ref->TempRemoveFigure(index);
|
||||||
|
}
|
||||||
|
} else if (cmd == "USB_CANCEL_REMOVE_FIGURE") {
|
||||||
|
const auto ref = Libraries::Usbd::usb_backend->GetImplRef();
|
||||||
|
if (ref) {
|
||||||
|
const u8 index = next_u64();
|
||||||
|
ref->CancelRemoveFigure(index);
|
||||||
|
}
|
||||||
} else if (cmd == "RELOAD_INPUTS") {
|
} else if (cmd == "RELOAD_INPUTS") {
|
||||||
std::string config = next_str();
|
std::string config = next_str();
|
||||||
Input::ParseInputConfig(config);
|
Input::ParseInputConfig(config);
|
||||||
|
|||||||
477
src/core/libraries/usbd/usb_backend.h
Normal file
477
src/core/libraries/usbd/usb_backend.h
Normal file
@@ -0,0 +1,477 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include <libusb.h>
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/types.h"
|
||||||
|
|
||||||
|
namespace Libraries::Usbd {
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
typedef CRITICAL_SECTION usbi_mutex_t;
|
||||||
|
#else
|
||||||
|
typedef pthread_mutex_t usbi_mutex_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct list_head {
|
||||||
|
struct list_head *prev, *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Forward declared libusb structs
|
||||||
|
struct UsbDeviceHandle {
|
||||||
|
usbi_mutex_t lock;
|
||||||
|
unsigned long claimed_interfaces;
|
||||||
|
struct list_head list;
|
||||||
|
struct libusb_device* dev;
|
||||||
|
int auto_detach_kernel_driver;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UsbDevice {
|
||||||
|
volatile long refcnt;
|
||||||
|
|
||||||
|
struct libusb_context* ctx;
|
||||||
|
struct libusb_device* parent_dev;
|
||||||
|
|
||||||
|
u8 bus_number;
|
||||||
|
u8 port_number;
|
||||||
|
u8 device_address;
|
||||||
|
enum libusb_speed speed;
|
||||||
|
|
||||||
|
struct list_head list;
|
||||||
|
unsigned long session_data;
|
||||||
|
|
||||||
|
struct libusb_device_descriptor device_descriptor;
|
||||||
|
volatile long attached;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UsbEmulatedImpl {
|
||||||
|
public:
|
||||||
|
UsbEmulatedImpl() = default;
|
||||||
|
|
||||||
|
virtual void LoadFigure(std::string file_name, u8 pad, u8 slot) = 0;
|
||||||
|
virtual void RemoveFigure(u8 pad, u8 slot, bool full_remove) = 0;
|
||||||
|
virtual void MoveFigure(u8 new_pad, u8 new_index, u8 old_pad, u8 old_index) = 0;
|
||||||
|
virtual void TempRemoveFigure(u8 index) = 0;
|
||||||
|
virtual void CancelRemoveFigure(u8 index) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~UsbEmulatedImpl() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UsbBackend {
|
||||||
|
public:
|
||||||
|
UsbBackend() = default;
|
||||||
|
|
||||||
|
virtual s32 Init() = 0;
|
||||||
|
virtual void Exit() = 0;
|
||||||
|
|
||||||
|
virtual s64 GetDeviceList(libusb_device*** list) = 0;
|
||||||
|
virtual void FreeDeviceList(libusb_device** list, s32 unref_devices) = 0;
|
||||||
|
|
||||||
|
virtual s32 GetConfiguration(libusb_device_handle* dev, s32* config) = 0;
|
||||||
|
virtual s32 GetDeviceDescriptor(libusb_device* dev, libusb_device_descriptor* desc) = 0;
|
||||||
|
virtual s32 GetActiveConfigDescriptor(libusb_device* dev,
|
||||||
|
libusb_config_descriptor** config) = 0;
|
||||||
|
virtual s32 GetConfigDescriptor(libusb_device* dev, u8 config_index,
|
||||||
|
libusb_config_descriptor** config) = 0;
|
||||||
|
virtual void FreeConfigDescriptor(libusb_config_descriptor* config) = 0;
|
||||||
|
|
||||||
|
virtual u8 GetBusNumber(libusb_device* dev) = 0;
|
||||||
|
virtual u8 GetDeviceAddress(libusb_device* dev) = 0;
|
||||||
|
virtual s32 GetMaxPacketSize(libusb_device* dev, u8 endpoint) = 0;
|
||||||
|
|
||||||
|
virtual s32 OpenDevice(libusb_device* dev, libusb_device_handle** dev_handle) = 0;
|
||||||
|
virtual void CloseDevice(libusb_device_handle* dev_handle) = 0;
|
||||||
|
virtual libusb_device* GetDevice(libusb_device_handle* dev_handle) = 0;
|
||||||
|
|
||||||
|
virtual s32 SetConfiguration(libusb_device_handle* dev_handle, s32 configuration) = 0;
|
||||||
|
virtual s32 ClaimInterface(libusb_device_handle* dev_handle, s32 interface_number) = 0;
|
||||||
|
virtual libusb_device_handle* OpenDeviceWithVidPid(u16 vendor_id, u16 product_id) = 0;
|
||||||
|
virtual s32 ResetDevice(libusb_device_handle* dev_handle) = 0;
|
||||||
|
|
||||||
|
virtual s32 KernelDriverActive(libusb_device_handle* dev_handle, s32 interface_number) = 0;
|
||||||
|
virtual s32 DetachKernelDriver(libusb_device_handle* dev_handle, s32 interface_number) = 0;
|
||||||
|
virtual s32 AttachKernelDriver(libusb_device_handle* dev_handle, s32 interface_number) = 0;
|
||||||
|
|
||||||
|
virtual s32 ControlTransfer(libusb_device_handle* dev_handle, u8 bmRequestType, u8 bRequest,
|
||||||
|
u16 wValue, u16 wIndex, u8* data, u16 wLength, u32 timeout) = 0;
|
||||||
|
virtual s32 SubmitTransfer(libusb_transfer* transfer) = 0;
|
||||||
|
|
||||||
|
virtual s32 TryLockEvents() = 0;
|
||||||
|
virtual void LockEvents() = 0;
|
||||||
|
virtual void UnlockEvents() = 0;
|
||||||
|
virtual s32 EventHandlingOk() = 0;
|
||||||
|
virtual s32 EventHandlerActive() = 0;
|
||||||
|
virtual void LockEventWaiters() = 0;
|
||||||
|
virtual void UnlockEventWaiters() = 0;
|
||||||
|
virtual s32 WaitForEvent(timeval* tv) = 0;
|
||||||
|
|
||||||
|
virtual s32 HandleEventsTimeout(timeval* tv) = 0;
|
||||||
|
virtual s32 HandleEvents() = 0;
|
||||||
|
virtual s32 HandleEventsLocked(timeval* tv) = 0;
|
||||||
|
|
||||||
|
virtual s32 CheckConnected(libusb_device_handle* dev) = 0;
|
||||||
|
virtual std::shared_ptr<UsbEmulatedImpl> GetImplRef() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~UsbBackend() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UsbRealBackend : public UsbBackend {
|
||||||
|
public:
|
||||||
|
s32 Init() override {
|
||||||
|
return libusb_init(&g_libusb_context);
|
||||||
|
}
|
||||||
|
void Exit() override {
|
||||||
|
libusb_exit(g_libusb_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 GetDeviceList(libusb_device*** list) override {
|
||||||
|
return libusb_get_device_list(g_libusb_context, list);
|
||||||
|
}
|
||||||
|
void FreeDeviceList(libusb_device** list, s32 unref_devices) override {
|
||||||
|
libusb_free_device_list(list, unref_devices);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 GetConfiguration(libusb_device_handle* dev, s32* config) override {
|
||||||
|
return libusb_get_configuration(dev, config);
|
||||||
|
}
|
||||||
|
s32 GetDeviceDescriptor(libusb_device* dev, libusb_device_descriptor* desc) override {
|
||||||
|
return libusb_get_device_descriptor(dev, desc);
|
||||||
|
}
|
||||||
|
s32 GetActiveConfigDescriptor(libusb_device* dev, libusb_config_descriptor** config) override {
|
||||||
|
return libusb_get_active_config_descriptor(dev, config);
|
||||||
|
}
|
||||||
|
s32 GetConfigDescriptor(libusb_device* dev, u8 config_index,
|
||||||
|
libusb_config_descriptor** config) override {
|
||||||
|
return libusb_get_config_descriptor(dev, config_index, config);
|
||||||
|
}
|
||||||
|
void FreeConfigDescriptor(libusb_config_descriptor* config) override {
|
||||||
|
libusb_free_config_descriptor(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 GetBusNumber(libusb_device* dev) override {
|
||||||
|
return libusb_get_bus_number(dev);
|
||||||
|
}
|
||||||
|
u8 GetDeviceAddress(libusb_device* dev) override {
|
||||||
|
return libusb_get_device_address(dev);
|
||||||
|
}
|
||||||
|
s32 GetMaxPacketSize(libusb_device* dev, u8 endpoint) override {
|
||||||
|
return libusb_get_max_packet_size(dev, endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 OpenDevice(libusb_device* dev, libusb_device_handle** dev_handle) override {
|
||||||
|
return libusb_open(dev, dev_handle);
|
||||||
|
}
|
||||||
|
void CloseDevice(libusb_device_handle* dev_handle) override {
|
||||||
|
libusb_close(dev_handle);
|
||||||
|
}
|
||||||
|
libusb_device* GetDevice(libusb_device_handle* dev_handle) override {
|
||||||
|
return libusb_get_device(dev_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 SetConfiguration(libusb_device_handle* dev_handle, s32 configuration) override {
|
||||||
|
return libusb_set_configuration(dev_handle, configuration);
|
||||||
|
}
|
||||||
|
s32 ClaimInterface(libusb_device_handle* dev_handle, s32 interface_number) override {
|
||||||
|
return libusb_claim_interface(dev_handle, interface_number);
|
||||||
|
}
|
||||||
|
libusb_device_handle* OpenDeviceWithVidPid(u16 vendor_id, u16 product_id) override {
|
||||||
|
return libusb_open_device_with_vid_pid(g_libusb_context, vendor_id, product_id);
|
||||||
|
}
|
||||||
|
s32 ResetDevice(libusb_device_handle* dev_handle) override {
|
||||||
|
return libusb_reset_device(dev_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 KernelDriverActive(libusb_device_handle* dev_handle, s32 interface_number) override {
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
|
return s_has_removed_driver ? 0 : 1;
|
||||||
|
#else
|
||||||
|
return libusb_kernel_driver_active(dev_handle, interface_number);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
s32 DetachKernelDriver(libusb_device_handle* dev_handle, s32 interface_number) override {
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
|
s_has_removed_driver = true;
|
||||||
|
return LIBUSB_SUCCESS;
|
||||||
|
#else
|
||||||
|
return libusb_detach_kernel_driver(dev_handle, interface_number);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
s32 AttachKernelDriver(libusb_device_handle* dev_handle, s32 interface_number) override {
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
|
s_has_removed_driver = false;
|
||||||
|
return LIBUSB_SUCCESS;
|
||||||
|
#else
|
||||||
|
return libusb_attach_kernel_driver(dev_handle, interface_number);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 ControlTransfer(libusb_device_handle* dev_handle, u8 bmRequestType, u8 bRequest, u16 wValue,
|
||||||
|
u16 wIndex, u8* data, u16 wLength, u32 timeout) override {
|
||||||
|
return libusb_control_transfer(dev_handle, bmRequestType, bRequest, wValue, wIndex, data,
|
||||||
|
wLength, timeout);
|
||||||
|
}
|
||||||
|
s32 SubmitTransfer(libusb_transfer* transfer) override {
|
||||||
|
return libusb_submit_transfer(transfer);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 TryLockEvents() override {
|
||||||
|
return libusb_try_lock_events(g_libusb_context);
|
||||||
|
}
|
||||||
|
void LockEvents() override {
|
||||||
|
return libusb_lock_events(g_libusb_context);
|
||||||
|
}
|
||||||
|
void UnlockEvents() override {
|
||||||
|
return libusb_unlock_events(g_libusb_context);
|
||||||
|
}
|
||||||
|
s32 EventHandlingOk() override {
|
||||||
|
return libusb_event_handling_ok(g_libusb_context);
|
||||||
|
}
|
||||||
|
s32 EventHandlerActive() override {
|
||||||
|
return libusb_event_handler_active(g_libusb_context);
|
||||||
|
}
|
||||||
|
void LockEventWaiters() override {
|
||||||
|
return libusb_lock_event_waiters(g_libusb_context);
|
||||||
|
}
|
||||||
|
void UnlockEventWaiters() override {
|
||||||
|
return libusb_unlock_event_waiters(g_libusb_context);
|
||||||
|
}
|
||||||
|
s32 WaitForEvent(timeval* tv) override {
|
||||||
|
return libusb_wait_for_event(g_libusb_context, tv);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 HandleEventsTimeout(timeval* tv) override {
|
||||||
|
return libusb_handle_events_timeout(g_libusb_context, tv);
|
||||||
|
}
|
||||||
|
s32 HandleEvents() override {
|
||||||
|
return libusb_handle_events(g_libusb_context);
|
||||||
|
}
|
||||||
|
s32 HandleEventsLocked(timeval* tv) override {
|
||||||
|
return libusb_handle_events_locked(g_libusb_context, tv);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 CheckConnected(libusb_device_handle* dev) override {
|
||||||
|
// There's no libusb version of this function.
|
||||||
|
// Simulate by querying data.
|
||||||
|
|
||||||
|
int config;
|
||||||
|
return libusb_get_configuration(dev, &config);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<UsbEmulatedImpl> GetImplRef() override {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
libusb_context* g_libusb_context = nullptr;
|
||||||
|
bool s_has_removed_driver = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UsbEmulatedBackend : public UsbRealBackend {
|
||||||
|
public:
|
||||||
|
s64 GetDeviceList(libusb_device*** list) override {
|
||||||
|
auto** fake = static_cast<libusb_device**>(calloc(2, sizeof(libusb_device*)));
|
||||||
|
fake[0] = GetDevice(nullptr);
|
||||||
|
fake[1] = nullptr;
|
||||||
|
*list = fake;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
void FreeDeviceList(libusb_device** list, s32 unref_devices) override {
|
||||||
|
if (!list) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unref_devices) {
|
||||||
|
int i = 0;
|
||||||
|
libusb_device* dev;
|
||||||
|
|
||||||
|
while ((dev = list[i++]) != nullptr) {
|
||||||
|
free(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 GetConfiguration(libusb_device_handle* dev, s32* config) override {
|
||||||
|
config = nullptr;
|
||||||
|
return LIBUSB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 GetDeviceDescriptor(libusb_device* dev, libusb_device_descriptor* desc) override {
|
||||||
|
std::memcpy(desc, FillDeviceDescriptor(), sizeof(libusb_device_descriptor));
|
||||||
|
return LIBUSB_SUCCESS;
|
||||||
|
}
|
||||||
|
s32 GetActiveConfigDescriptor(libusb_device* dev, libusb_config_descriptor** config) override {
|
||||||
|
const auto endpoint_descs = FillEndpointDescriptorPair();
|
||||||
|
const auto interface_desc = FillInterfaceDescriptor(endpoint_descs);
|
||||||
|
|
||||||
|
const auto interface = static_cast<libusb_interface*>(calloc(1, sizeof(libusb_interface*)));
|
||||||
|
interface->altsetting = interface_desc;
|
||||||
|
interface->num_altsetting = 1;
|
||||||
|
|
||||||
|
const auto new_config = FillConfigDescriptor(interface);
|
||||||
|
|
||||||
|
ASSERT(endpoint_descs && interface_desc && new_config);
|
||||||
|
*config = new_config;
|
||||||
|
return LIBUSB_SUCCESS;
|
||||||
|
}
|
||||||
|
s32 GetConfigDescriptor(libusb_device* dev, u8 config_index,
|
||||||
|
libusb_config_descriptor** config) override {
|
||||||
|
if (config_index >= 1) {
|
||||||
|
return LIBUSB_ERROR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
return GetActiveConfigDescriptor(dev, config);
|
||||||
|
}
|
||||||
|
void FreeConfigDescriptor(libusb_config_descriptor* config) override {
|
||||||
|
// Member variable reference, don't free
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 GetBusNumber(libusb_device* dev) override {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
u8 GetDeviceAddress(libusb_device* dev) override {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
s32 GetMaxPacketSize(libusb_device* dev, u8 endpoint) override {
|
||||||
|
libusb_device_descriptor* desc = nullptr;
|
||||||
|
|
||||||
|
int r = GetDeviceDescriptor(dev, desc);
|
||||||
|
if (r < LIBUSB_SUCCESS) {
|
||||||
|
return LIBUSB_ERROR_OTHER;
|
||||||
|
}
|
||||||
|
return desc->bMaxPacketSize0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 OpenDevice(libusb_device* dev, libusb_device_handle** dev_handle) override {
|
||||||
|
auto* _dev_handle = static_cast<UsbDeviceHandle*>(calloc(1, sizeof(libusb_device_handle*)));
|
||||||
|
if (!_dev_handle) {
|
||||||
|
return LIBUSB_ERROR_NO_MEM;
|
||||||
|
}
|
||||||
|
_dev_handle->dev = dev;
|
||||||
|
*dev_handle = reinterpret_cast<libusb_device_handle*>(_dev_handle);
|
||||||
|
return LIBUSB_SUCCESS;
|
||||||
|
}
|
||||||
|
void CloseDevice(libusb_device_handle* dev_handle) override {
|
||||||
|
LOG_WARNING(Lib_Usbd, "Guest decided to close device, might be an implementation issue");
|
||||||
|
free(dev_handle);
|
||||||
|
}
|
||||||
|
libusb_device* GetDevice(libusb_device_handle* dev_handle) override {
|
||||||
|
const auto desc = FillDeviceDescriptor();
|
||||||
|
ASSERT(desc);
|
||||||
|
|
||||||
|
const auto fake = static_cast<UsbDevice*>(calloc(1, sizeof(UsbDevice*)));
|
||||||
|
fake->bus_number = 0;
|
||||||
|
fake->port_number = 0;
|
||||||
|
fake->device_address = 0;
|
||||||
|
fake->device_descriptor = *desc;
|
||||||
|
fake->ctx = g_libusb_context;
|
||||||
|
return reinterpret_cast<libusb_device*>(fake);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 SetConfiguration(libusb_device_handle* dev_handle, s32 configuration) override {
|
||||||
|
return LIBUSB_SUCCESS;
|
||||||
|
}
|
||||||
|
s32 ClaimInterface(libusb_device_handle* dev_handle, s32 interface_number) override {
|
||||||
|
return LIBUSB_SUCCESS;
|
||||||
|
}
|
||||||
|
libusb_device_handle* OpenDeviceWithVidPid(u16 vendor_id, u16 product_id) override {
|
||||||
|
libusb_device_handle* dev_handle = nullptr;
|
||||||
|
OpenDevice(GetDevice(nullptr), &dev_handle);
|
||||||
|
return dev_handle;
|
||||||
|
}
|
||||||
|
s32 ResetDevice(libusb_device_handle* dev_handle) override {
|
||||||
|
LOG_WARNING(Lib_Usbd, "Guest decided to reset device, might be an implementation issue");
|
||||||
|
return LIBUSB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 KernelDriverActive(libusb_device_handle* dev_handle, s32 interface_number) override {
|
||||||
|
return s_has_removed_driver ? 0 : 1;
|
||||||
|
}
|
||||||
|
s32 DetachKernelDriver(libusb_device_handle* dev_handle, s32 interface_number) override {
|
||||||
|
s_has_removed_driver = true;
|
||||||
|
return LIBUSB_SUCCESS;
|
||||||
|
}
|
||||||
|
s32 AttachKernelDriver(libusb_device_handle* dev_handle, s32 interface_number) override {
|
||||||
|
s_has_removed_driver = false;
|
||||||
|
return LIBUSB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 ControlTransfer(libusb_device_handle* dev_handle, u8 bmRequestType, u8 bRequest, u16 wValue,
|
||||||
|
u16 wIndex, u8* data, u16 wLength, u32 timeout) override {
|
||||||
|
LOG_WARNING(Lib_Usbd, "Backend has not handled control transfers");
|
||||||
|
return LIBUSB_ERROR_PIPE;
|
||||||
|
}
|
||||||
|
s32 SubmitTransfer(libusb_transfer* transfer) override {
|
||||||
|
ASSERT(transfer->type == LIBUSB_TRANSFER_TYPE_INTERRUPT);
|
||||||
|
|
||||||
|
// if we have no other flying transfers, start the list with this one
|
||||||
|
if (flight_list.empty()) {
|
||||||
|
flight_list.push_front(transfer);
|
||||||
|
return LIBUSB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we have infinite timeout, append to end of list
|
||||||
|
if (transfer->timeout == 0) {
|
||||||
|
flight_list.push_back(transfer);
|
||||||
|
return LIBUSB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise, find appropriate place in list
|
||||||
|
for (auto it = flight_list.begin(); it != flight_list.end(); ++it) {
|
||||||
|
if ((*it)->timeout > transfer->timeout) {
|
||||||
|
flight_list.insert(it, transfer);
|
||||||
|
return LIBUSB_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise we need to be inserted at the end
|
||||||
|
flight_list.push_back(transfer);
|
||||||
|
return LIBUSB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 HandleEventsTimeout(timeval* tv) override {
|
||||||
|
return HandleEvents();
|
||||||
|
}
|
||||||
|
s32 HandleEvents() override {
|
||||||
|
if (!flight_list.empty()) {
|
||||||
|
const auto transfer = flight_list.front();
|
||||||
|
|
||||||
|
const u8 flags = transfer->flags;
|
||||||
|
transfer->status = HandleAsyncTransfer(transfer);
|
||||||
|
transfer->actual_length = transfer->length;
|
||||||
|
if (transfer->callback) {
|
||||||
|
transfer->callback(transfer);
|
||||||
|
}
|
||||||
|
if (flags & LIBUSB_TRANSFER_FREE_TRANSFER) {
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
|
}
|
||||||
|
flight_list.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
return LIBUSB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 CheckConnected(libusb_device_handle* dev) override {
|
||||||
|
return LIBUSB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual libusb_endpoint_descriptor* FillEndpointDescriptorPair() = 0;
|
||||||
|
virtual libusb_interface_descriptor* FillInterfaceDescriptor(
|
||||||
|
libusb_endpoint_descriptor* descs) = 0;
|
||||||
|
virtual libusb_config_descriptor* FillConfigDescriptor(libusb_interface* inter) = 0;
|
||||||
|
virtual libusb_device_descriptor* FillDeviceDescriptor() = 0;
|
||||||
|
|
||||||
|
virtual libusb_transfer_status HandleAsyncTransfer(libusb_transfer* transfer) = 0;
|
||||||
|
|
||||||
|
std::list<libusb_transfer*> flight_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Libraries::Usbd
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/singleton.h"
|
|
||||||
#include "core/libraries/error_codes.h"
|
#include "core/libraries/error_codes.h"
|
||||||
#include "core/libraries/libs.h"
|
#include "core/libraries/libs.h"
|
||||||
#include "usbd.h"
|
#include "usbd.h"
|
||||||
@@ -10,6 +9,8 @@
|
|||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <libusb.h>
|
#include <libusb.h>
|
||||||
|
|
||||||
|
#include "common/config.h"
|
||||||
|
|
||||||
namespace Libraries::Usbd {
|
namespace Libraries::Usbd {
|
||||||
|
|
||||||
s32 libusb_to_orbis_error(int retVal) {
|
s32 libusb_to_orbis_error(int retVal) {
|
||||||
@@ -23,7 +24,7 @@ s32 libusb_to_orbis_error(int retVal) {
|
|||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
libusb_context* g_libusb_context;
|
std::shared_ptr<UsbBackend> usb_backend;
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
bool s_has_removed_driver = false;
|
bool s_has_removed_driver = false;
|
||||||
@@ -32,25 +33,25 @@ bool s_has_removed_driver = false;
|
|||||||
s32 PS4_SYSV_ABI sceUsbdInit() {
|
s32 PS4_SYSV_ABI sceUsbdInit() {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_init(&g_libusb_context));
|
return libusb_to_orbis_error(usb_backend->Init());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PS4_SYSV_ABI sceUsbdExit() {
|
void PS4_SYSV_ABI sceUsbdExit() {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
libusb_exit(g_libusb_context);
|
usb_backend->Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 PS4_SYSV_ABI sceUsbdGetDeviceList(SceUsbdDevice*** list) {
|
s64 PS4_SYSV_ABI sceUsbdGetDeviceList(SceUsbdDevice*** list) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_get_device_list(g_libusb_context, list));
|
return libusb_to_orbis_error(usb_backend->GetDeviceList(list));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PS4_SYSV_ABI sceUsbdFreeDeviceList(SceUsbdDevice** list, s32 unref_devices) {
|
void PS4_SYSV_ABI sceUsbdFreeDeviceList(SceUsbdDevice** list, s32 unref_devices) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
libusb_free_device_list(list, unref_devices);
|
usb_backend->FreeDeviceList(list, unref_devices);
|
||||||
}
|
}
|
||||||
|
|
||||||
SceUsbdDevice* PS4_SYSV_ABI sceUsbdRefDevice(SceUsbdDevice* device) {
|
SceUsbdDevice* PS4_SYSV_ABI sceUsbdRefDevice(SceUsbdDevice* device) {
|
||||||
@@ -68,27 +69,27 @@ void PS4_SYSV_ABI sceUsbdUnrefDevice(SceUsbdDevice* device) {
|
|||||||
s32 PS4_SYSV_ABI sceUsbdGetConfiguration(SceUsbdDeviceHandle* dev_handle, s32* config) {
|
s32 PS4_SYSV_ABI sceUsbdGetConfiguration(SceUsbdDeviceHandle* dev_handle, s32* config) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_get_configuration(dev_handle, config));
|
return libusb_to_orbis_error(usb_backend->GetConfiguration(dev_handle, config));
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdGetDeviceDescriptor(SceUsbdDevice* device, SceUsbdDeviceDescriptor* desc) {
|
s32 PS4_SYSV_ABI sceUsbdGetDeviceDescriptor(SceUsbdDevice* device, SceUsbdDeviceDescriptor* desc) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_get_device_descriptor(device, desc));
|
return libusb_to_orbis_error(usb_backend->GetDeviceDescriptor(device, desc));
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdGetActiveConfigDescriptor(SceUsbdDevice* device,
|
s32 PS4_SYSV_ABI sceUsbdGetActiveConfigDescriptor(SceUsbdDevice* device,
|
||||||
SceUsbdConfigDescriptor** config) {
|
SceUsbdConfigDescriptor** config) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_get_active_config_descriptor(device, config));
|
return libusb_to_orbis_error(usb_backend->GetActiveConfigDescriptor(device, config));
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdGetConfigDescriptor(SceUsbdDevice* device, u8 config_index,
|
s32 PS4_SYSV_ABI sceUsbdGetConfigDescriptor(SceUsbdDevice* device, u8 config_index,
|
||||||
SceUsbdConfigDescriptor** config) {
|
SceUsbdConfigDescriptor** config) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_get_config_descriptor(device, config_index, config));
|
return libusb_to_orbis_error(usb_backend->GetConfigDescriptor(device, config_index, config));
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdGetConfigDescriptorByValue(SceUsbdDevice* device, u8 bConfigurationValue,
|
s32 PS4_SYSV_ABI sceUsbdGetConfigDescriptorByValue(SceUsbdDevice* device, u8 bConfigurationValue,
|
||||||
@@ -102,19 +103,19 @@ s32 PS4_SYSV_ABI sceUsbdGetConfigDescriptorByValue(SceUsbdDevice* device, u8 bCo
|
|||||||
void PS4_SYSV_ABI sceUsbdFreeConfigDescriptor(SceUsbdConfigDescriptor* config) {
|
void PS4_SYSV_ABI sceUsbdFreeConfigDescriptor(SceUsbdConfigDescriptor* config) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
libusb_free_config_descriptor(config);
|
usb_backend->FreeConfigDescriptor(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 PS4_SYSV_ABI sceUsbdGetBusNumber(SceUsbdDevice* device) {
|
u8 PS4_SYSV_ABI sceUsbdGetBusNumber(SceUsbdDevice* device) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_get_bus_number(device);
|
return usb_backend->GetBusNumber(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 PS4_SYSV_ABI sceUsbdGetDeviceAddress(SceUsbdDevice* device) {
|
u8 PS4_SYSV_ABI sceUsbdGetDeviceAddress(SceUsbdDevice* device) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_get_device_address(device);
|
return usb_backend->GetDeviceAddress(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
SceUsbdSpeed PS4_SYSV_ABI sceUsbdGetDeviceSpeed(SceUsbdDevice* device) {
|
SceUsbdSpeed PS4_SYSV_ABI sceUsbdGetDeviceSpeed(SceUsbdDevice* device) {
|
||||||
@@ -126,7 +127,7 @@ SceUsbdSpeed PS4_SYSV_ABI sceUsbdGetDeviceSpeed(SceUsbdDevice* device) {
|
|||||||
s32 PS4_SYSV_ABI sceUsbdGetMaxPacketSize(SceUsbdDevice* device, u8 endpoint) {
|
s32 PS4_SYSV_ABI sceUsbdGetMaxPacketSize(SceUsbdDevice* device, u8 endpoint) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_get_max_packet_size(device, endpoint));
|
return libusb_to_orbis_error(usb_backend->GetMaxPacketSize(device, endpoint));
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize(SceUsbdDevice* device, u8 endpoint) {
|
s32 PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize(SceUsbdDevice* device, u8 endpoint) {
|
||||||
@@ -138,25 +139,25 @@ s32 PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize(SceUsbdDevice* device, u8 endpoint)
|
|||||||
s32 PS4_SYSV_ABI sceUsbdOpen(SceUsbdDevice* device, SceUsbdDeviceHandle** dev_handle) {
|
s32 PS4_SYSV_ABI sceUsbdOpen(SceUsbdDevice* device, SceUsbdDeviceHandle** dev_handle) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_open(device, dev_handle));
|
return libusb_to_orbis_error(usb_backend->OpenDevice(device, dev_handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PS4_SYSV_ABI sceUsbdClose(SceUsbdDeviceHandle* dev_handle) {
|
void PS4_SYSV_ABI sceUsbdClose(SceUsbdDeviceHandle* dev_handle) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
libusb_close(dev_handle);
|
usb_backend->CloseDevice(dev_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
SceUsbdDevice* PS4_SYSV_ABI sceUsbdGetDevice(SceUsbdDeviceHandle* dev_handle) {
|
SceUsbdDevice* PS4_SYSV_ABI sceUsbdGetDevice(SceUsbdDeviceHandle* dev_handle) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_get_device(dev_handle);
|
return usb_backend->GetDevice(dev_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdSetConfiguration(SceUsbdDeviceHandle* dev_handle, s32 config) {
|
s32 PS4_SYSV_ABI sceUsbdSetConfiguration(SceUsbdDeviceHandle* dev_handle, s32 config) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_set_configuration(dev_handle, config));
|
return libusb_to_orbis_error(usb_backend->SetConfiguration(dev_handle, config));
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdClaimInterface(SceUsbdDeviceHandle* dev_handle, s32 interface_number) {
|
s32 PS4_SYSV_ABI sceUsbdClaimInterface(SceUsbdDeviceHandle* dev_handle, s32 interface_number) {
|
||||||
@@ -166,7 +167,7 @@ s32 PS4_SYSV_ABI sceUsbdClaimInterface(SceUsbdDeviceHandle* dev_handle, s32 inte
|
|||||||
sceUsbdDetachKernelDriver(dev_handle, interface_number);
|
sceUsbdDetachKernelDriver(dev_handle, interface_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_claim_interface(dev_handle, interface_number));
|
return libusb_to_orbis_error(usb_backend->ClaimInterface(dev_handle, interface_number));
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdReleaseInterface(SceUsbdDeviceHandle* dev_handle, s32 interface_number) {
|
s32 PS4_SYSV_ABI sceUsbdReleaseInterface(SceUsbdDeviceHandle* dev_handle, s32 interface_number) {
|
||||||
@@ -178,7 +179,7 @@ s32 PS4_SYSV_ABI sceUsbdReleaseInterface(SceUsbdDeviceHandle* dev_handle, s32 in
|
|||||||
SceUsbdDeviceHandle* PS4_SYSV_ABI sceUsbdOpenDeviceWithVidPid(u16 vendor_id, u16 product_id) {
|
SceUsbdDeviceHandle* PS4_SYSV_ABI sceUsbdOpenDeviceWithVidPid(u16 vendor_id, u16 product_id) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_open_device_with_vid_pid(g_libusb_context, vendor_id, product_id);
|
return usb_backend->OpenDeviceWithVidPid(vendor_id, product_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdSetInterfaceAltSetting(SceUsbdDeviceHandle* dev_handle,
|
s32 PS4_SYSV_ABI sceUsbdSetInterfaceAltSetting(SceUsbdDeviceHandle* dev_handle,
|
||||||
@@ -198,42 +199,25 @@ s32 PS4_SYSV_ABI sceUsbdClearHalt(SceUsbdDeviceHandle* dev_handle, uint8_t endpo
|
|||||||
s32 PS4_SYSV_ABI sceUsbdResetDevice(SceUsbdDeviceHandle* dev_handle) {
|
s32 PS4_SYSV_ABI sceUsbdResetDevice(SceUsbdDeviceHandle* dev_handle) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_reset_device(dev_handle));
|
return libusb_to_orbis_error(usb_backend->ResetDevice(dev_handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdKernelDriverActive(SceUsbdDeviceHandle* dev_handle, int interface_number) {
|
s32 PS4_SYSV_ABI sceUsbdKernelDriverActive(SceUsbdDeviceHandle* dev_handle, int interface_number) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
#if defined(_WIN32)
|
return libusb_to_orbis_error(usb_backend->KernelDriverActive(dev_handle, interface_number));
|
||||||
if (!s_has_removed_driver)
|
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_kernel_driver_active(dev_handle, interface_number));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdDetachKernelDriver(SceUsbdDeviceHandle* dev_handle, int interface_number) {
|
s32 PS4_SYSV_ABI sceUsbdDetachKernelDriver(SceUsbdDeviceHandle* dev_handle, int interface_number) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
#if defined(_WIN32)
|
return libusb_to_orbis_error(usb_backend->DetachKernelDriver(dev_handle, interface_number));
|
||||||
s_has_removed_driver = true;
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_detach_kernel_driver(dev_handle, interface_number));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdAttachKernelDriver(SceUsbdDeviceHandle* dev_handle, int interface_number) {
|
s32 PS4_SYSV_ABI sceUsbdAttachKernelDriver(SceUsbdDeviceHandle* dev_handle, int interface_number) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
#if defined(_WIN32)
|
return libusb_to_orbis_error(usb_backend->AttachKernelDriver(dev_handle, interface_number));
|
||||||
s_has_removed_driver = false;
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_attach_kernel_driver(dev_handle, interface_number));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u8* PS4_SYSV_ABI sceUsbdControlTransferGetData(SceUsbdTransfer* transfer) {
|
u8* PS4_SYSV_ABI sceUsbdControlTransferGetData(SceUsbdTransfer* transfer) {
|
||||||
@@ -264,7 +248,7 @@ SceUsbdTransfer* PS4_SYSV_ABI sceUsbdAllocTransfer(int iso_packets) {
|
|||||||
s32 PS4_SYSV_ABI sceUsbdSubmitTransfer(SceUsbdTransfer* transfer) {
|
s32 PS4_SYSV_ABI sceUsbdSubmitTransfer(SceUsbdTransfer* transfer) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_submit_transfer(transfer));
|
return libusb_to_orbis_error(usb_backend->SubmitTransfer(transfer));
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdCancelTransfer(SceUsbdTransfer* transfer) {
|
s32 PS4_SYSV_ABI sceUsbdCancelTransfer(SceUsbdTransfer* transfer) {
|
||||||
@@ -336,8 +320,8 @@ s32 PS4_SYSV_ABI sceUsbdControlTransfer(SceUsbdDeviceHandle* dev_handle, u8 requ
|
|||||||
u32 timeout) {
|
u32 timeout) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_control_transfer(dev_handle, request_type, bRequest, wValue,
|
return libusb_to_orbis_error(usb_backend->ControlTransfer(
|
||||||
wIndex, data, wLength, timeout));
|
dev_handle, request_type, bRequest, wValue, wIndex, data, wLength, timeout));
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdBulkTransfer(SceUsbdDeviceHandle* dev_handle, u8 endpoint, u8* data,
|
s32 PS4_SYSV_ABI sceUsbdBulkTransfer(SceUsbdDeviceHandle* dev_handle, u8 endpoint, u8* data,
|
||||||
@@ -383,79 +367,73 @@ s32 PS4_SYSV_ABI sceUsbdGetStringDescriptorAscii(SceUsbdDeviceHandle* dev_handle
|
|||||||
s32 PS4_SYSV_ABI sceUsbdTryLockEvents() {
|
s32 PS4_SYSV_ABI sceUsbdTryLockEvents() {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_try_lock_events(g_libusb_context);
|
return usb_backend->TryLockEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PS4_SYSV_ABI sceUsbdLockEvents() {
|
void PS4_SYSV_ABI sceUsbdLockEvents() {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
libusb_lock_events(g_libusb_context);
|
usb_backend->LockEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PS4_SYSV_ABI sceUsbdUnlockEvents() {
|
void PS4_SYSV_ABI sceUsbdUnlockEvents() {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
libusb_unlock_events(g_libusb_context);
|
usb_backend->UnlockEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdEventHandlingOk() {
|
s32 PS4_SYSV_ABI sceUsbdEventHandlingOk() {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_event_handling_ok(g_libusb_context);
|
return usb_backend->EventHandlingOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdEventHandlerActive() {
|
s32 PS4_SYSV_ABI sceUsbdEventHandlerActive() {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_event_handler_active(g_libusb_context);
|
return usb_backend->EventHandlerActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PS4_SYSV_ABI sceUsbdLockEventWaiters() {
|
void PS4_SYSV_ABI sceUsbdLockEventWaiters() {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
libusb_lock_event_waiters(g_libusb_context);
|
usb_backend->LockEventWaiters();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PS4_SYSV_ABI sceUsbdUnlockEventWaiters() {
|
void PS4_SYSV_ABI sceUsbdUnlockEventWaiters() {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
libusb_unlock_event_waiters(g_libusb_context);
|
usb_backend->UnlockEventWaiters();
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdWaitForEvent(timeval* tv) {
|
s32 PS4_SYSV_ABI sceUsbdWaitForEvent(timeval* tv) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_wait_for_event(g_libusb_context, tv));
|
return libusb_to_orbis_error(usb_backend->WaitForEvent(tv));
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdHandleEventsTimeout(timeval* tv) {
|
s32 PS4_SYSV_ABI sceUsbdHandleEventsTimeout(timeval* tv) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_handle_events_timeout(g_libusb_context, tv));
|
return libusb_to_orbis_error(usb_backend->HandleEventsTimeout(tv));
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdHandleEvents() {
|
s32 PS4_SYSV_ABI sceUsbdHandleEvents() {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_handle_events(g_libusb_context));
|
return libusb_to_orbis_error(usb_backend->HandleEvents());
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdHandleEventsLocked(timeval* tv) {
|
s32 PS4_SYSV_ABI sceUsbdHandleEventsLocked(timeval* tv) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
return libusb_to_orbis_error(libusb_handle_events_locked(g_libusb_context, tv));
|
return libusb_to_orbis_error(usb_backend->HandleEventsTimeout(tv));
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUsbdCheckConnected(SceUsbdDeviceHandle* dev_handle) {
|
s32 PS4_SYSV_ABI sceUsbdCheckConnected(SceUsbdDeviceHandle* dev_handle) {
|
||||||
LOG_DEBUG(Lib_Usbd, "called");
|
LOG_DEBUG(Lib_Usbd, "called");
|
||||||
|
|
||||||
// There's no libusb version of this function.
|
return libusb_to_orbis_error(usb_backend->CheckConnected(dev_handle));
|
||||||
// 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() {
|
||||||
@@ -479,6 +457,21 @@ int PS4_SYSV_ABI Func_D56B43060720B1E0() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||||
|
switch (Config::getUsbDeviceBackend()) {
|
||||||
|
case Config::SkylandersPortal:
|
||||||
|
usb_backend = std::make_shared<SkylandersPortalBackend>();
|
||||||
|
break;
|
||||||
|
case Config::InfinityBase:
|
||||||
|
usb_backend = std::make_shared<InfinityBaseBackend>();
|
||||||
|
break;
|
||||||
|
case Config::DimensionsToypad:
|
||||||
|
usb_backend = std::make_shared<DimensionsToypadBackend>();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usb_backend = std::make_shared<UsbRealBackend>();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
LIB_FUNCTION("0ktE1PhzGFU", "libSceUsbd", 1, "libSceUsbd", sceUsbdAllocTransfer);
|
LIB_FUNCTION("0ktE1PhzGFU", "libSceUsbd", 1, "libSceUsbd", sceUsbdAllocTransfer);
|
||||||
LIB_FUNCTION("BKMEGvfCPyU", "libSceUsbd", 1, "libSceUsbd", sceUsbdAttachKernelDriver);
|
LIB_FUNCTION("BKMEGvfCPyU", "libSceUsbd", 1, "libSceUsbd", sceUsbdAttachKernelDriver);
|
||||||
LIB_FUNCTION("fotb7DzeHYw", "libSceUsbd", 1, "libSceUsbd", sceUsbdBulkTransfer);
|
LIB_FUNCTION("fotb7DzeHYw", "libSceUsbd", 1, "libSceUsbd", sceUsbdBulkTransfer);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
#include "usb_backend.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
struct libusb_device;
|
struct libusb_device;
|
||||||
@@ -21,6 +22,8 @@ class SymbolsResolver;
|
|||||||
|
|
||||||
namespace Libraries::Usbd {
|
namespace Libraries::Usbd {
|
||||||
|
|
||||||
|
extern std::shared_ptr<UsbBackend> usb_backend;
|
||||||
|
|
||||||
using SceUsbdDevice = libusb_device;
|
using SceUsbdDevice = libusb_device;
|
||||||
using SceUsbdDeviceHandle = libusb_device_handle;
|
using SceUsbdDeviceHandle = libusb_device_handle;
|
||||||
using SceUsbdDeviceDescriptor = libusb_device_descriptor;
|
using SceUsbdDeviceDescriptor = libusb_device_descriptor;
|
||||||
@@ -29,6 +32,11 @@ using SceUsbdTransfer = libusb_transfer;
|
|||||||
using SceUsbdControlSetup = libusb_control_setup;
|
using SceUsbdControlSetup = libusb_control_setup;
|
||||||
using SceUsbdTransferCallback = void PS4_SYSV_ABI (*)(SceUsbdTransfer* transfer);
|
using SceUsbdTransferCallback = void PS4_SYSV_ABI (*)(SceUsbdTransfer* transfer);
|
||||||
|
|
||||||
|
// TODO: implement emulated devices
|
||||||
|
using SkylandersPortalBackend = UsbRealBackend;
|
||||||
|
using InfinityBaseBackend = UsbRealBackend;
|
||||||
|
using DimensionsToypadBackend = UsbRealBackend;
|
||||||
|
|
||||||
enum class SceUsbdSpeed : u32 {
|
enum class SceUsbdSpeed : u32 {
|
||||||
UNKNOWN = 0,
|
UNKNOWN = 0,
|
||||||
LOW = 1,
|
LOW = 1,
|
||||||
|
|||||||
Reference in New Issue
Block a user