Merge 01a7732d50
into 1ae0b23265
This commit is contained in:
commit
1bc1397b50
|
@ -542,6 +542,8 @@ const Info<std::string> MAIN_BLUETOOTH_PASSTHROUGH_LINK_KEYS{
|
|||
|
||||
// Main.USBPassthrough
|
||||
|
||||
const Info<bool> MAIN_USB_PASSTHROUGH_DISGUISE_PLAYSTATION_AS_WII{
|
||||
{System::Main, "USBPassthrough", "DisguisePlayStationAsWii"}, true};
|
||||
const Info<std::string> MAIN_USB_PASSTHROUGH_DEVICES{{System::Main, "USBPassthrough", "Devices"},
|
||||
""};
|
||||
|
||||
|
|
|
@ -352,6 +352,7 @@ extern const Info<std::string> MAIN_BLUETOOTH_PASSTHROUGH_LINK_KEYS;
|
|||
|
||||
// Main.USBPassthrough
|
||||
|
||||
extern const Info<bool> MAIN_USB_PASSTHROUGH_DISGUISE_PLAYSTATION_AS_WII;
|
||||
extern const Info<std::string> MAIN_USB_PASSTHROUGH_DEVICES;
|
||||
std::set<std::pair<u16, u16>> GetUSBDeviceWhitelist();
|
||||
void SetUSBDeviceWhitelist(const std::set<std::pair<u16, u16>>& devices);
|
||||
|
|
|
@ -10,14 +10,17 @@
|
|||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <ranges>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <libusb.h>
|
||||
|
||||
#include "Common/Assert.h"
|
||||
#include "Common/Config/Config.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Core/Config/MainSettings.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/IOS/Device.h"
|
||||
#include "Core/IOS/IOS.h"
|
||||
|
@ -30,8 +33,8 @@ LibusbDevice::LibusbDevice(EmulationKernel& ios, libusb_device* device,
|
|||
: m_ios(ios), m_device(device)
|
||||
{
|
||||
libusb_ref_device(m_device);
|
||||
m_vid = descriptor.idVendor;
|
||||
m_pid = descriptor.idProduct;
|
||||
m_vid = m_spoofed_vid = descriptor.idVendor;
|
||||
m_pid = m_spoofed_pid = descriptor.idProduct;
|
||||
m_id = (static_cast<u64>(m_vid) << 32 | static_cast<u64>(m_pid) << 16 |
|
||||
static_cast<u64>(libusb_get_bus_number(device)) << 8 |
|
||||
static_cast<u64>(libusb_get_device_address(device)));
|
||||
|
@ -46,6 +49,9 @@ LibusbDevice::LibusbDevice(EmulationKernel& ios, libusb_device* device,
|
|||
}
|
||||
m_config_descriptors.emplace_back(std::move(config_descriptor));
|
||||
}
|
||||
|
||||
if (Config::Get(Config::MAIN_USB_PASSTHROUGH_DISGUISE_PLAYSTATION_AS_WII))
|
||||
DisguisePlayStationDevice();
|
||||
}
|
||||
|
||||
LibusbDevice::~LibusbDevice()
|
||||
|
@ -65,6 +71,8 @@ DeviceDescriptor LibusbDevice::GetDeviceDescriptor() const
|
|||
DeviceDescriptor descriptor;
|
||||
// The libusb_device_descriptor struct is the same as the IOS one, and it's not going to change.
|
||||
std::memcpy(&descriptor, &device_descriptor, sizeof(descriptor));
|
||||
descriptor.idVendor = m_spoofed_vid;
|
||||
descriptor.idProduct = m_spoofed_pid;
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
|
@ -196,6 +204,99 @@ int LibusbDevice::SetAltSetting(const u8 alt_setting)
|
|||
return libusb_set_interface_alt_setting(m_handle, m_active_interface, alt_setting);
|
||||
}
|
||||
|
||||
void LibusbDevice::DisguisePlayStationDevice()
|
||||
{
|
||||
// PS3 and Wii Rock Band controllers are very similar to each other, but the VIDs and PIDs differ.
|
||||
// By reporting PS3 Rock Band controllers as having Wii VIDs and PIDs, we can get PS3 controllers
|
||||
// working with Wii games.
|
||||
//
|
||||
// Microphones are already cross-platform and therefore work without us doing anything here.
|
||||
//
|
||||
// The PS3 versions of the controllers that are new for Rock Band 3 - keyboards and pro guitars -
|
||||
// have a feature that isn't present on Wii equivalents. By default, the controller won't send any
|
||||
// data for the keys or frets & strings respectively, presumably to avoid them triggering
|
||||
// unintended actions in the XMB (PS3 system menu). The PS3 version of Rock Band 3 sends a control
|
||||
// transfer to enable these inputs. Because Wii controllers always have these inputs enabled, the
|
||||
// Wii version of Rock Band 3 doesn't send the necessary control transfer, so we have to send it
|
||||
// ourselves. Whether we should do this is controlled by
|
||||
// m_needs_playstation_rock_band_3_instrument_control_transfer.
|
||||
|
||||
if (m_vid != 0x12ba) // Sony Computer Entertainment America
|
||||
return;
|
||||
|
||||
switch (m_pid)
|
||||
{
|
||||
case 0x0200: // Rock Band guitar
|
||||
// Unlike the Wii, the PS3 uses the same PID (0x0200) for Rock Band 1 and Rock Band 2 guitars.
|
||||
// The Wii VID here is set to the Rock Band 2 device (0x3010) rather than the Rock Band 1 device
|
||||
// (0x0004) because the Rock Band 2 device has more functionality (automatic latency
|
||||
// calibration).
|
||||
m_spoofed_pid = 0x3010;
|
||||
break;
|
||||
case 0x0210: // Rock Band drums
|
||||
// Unlike the Wii, the PS3 uses the same PID (0x0210) for Rock Band 1 and Rock Band 2 drums.
|
||||
// The Wii VID here is set to the Rock Band 2 device (0x3110) rather than the Rock Band 1 device
|
||||
// (0x0005) because the Rock Band 2 device has more functionality (cymbals).
|
||||
m_spoofed_pid = 0x3110;
|
||||
break;
|
||||
case 0x0218: // Rock Band 3 MIDI Pro Adapter with drums
|
||||
m_spoofed_pid = 0x3138;
|
||||
break;
|
||||
case 0x2330: // Rock Band 3 keyboard
|
||||
m_spoofed_pid = 0x3330;
|
||||
m_needs_playstation_rock_band_3_instrument_control_transfer = true;
|
||||
break;
|
||||
case 0x2338: // Rock Band 3 MIDI Pro Adapter with keyboard
|
||||
m_spoofed_pid = 0x3338;
|
||||
m_needs_playstation_rock_band_3_instrument_control_transfer = true;
|
||||
break;
|
||||
case 0x2430: // Rock Band 3 Mustang pro guitar
|
||||
m_spoofed_pid = 0x3430;
|
||||
m_needs_playstation_rock_band_3_instrument_control_transfer = true;
|
||||
break;
|
||||
case 0x2438: // Rock Band 3 MIDI Pro Adapter with Mustang pro guitar
|
||||
m_spoofed_pid = 0x3438;
|
||||
m_needs_playstation_rock_band_3_instrument_control_transfer = true;
|
||||
break;
|
||||
case 0x2530: // Rock Band 3 Squier pro guitar (doesn't exist in reality, but game supports it)
|
||||
m_spoofed_pid = 0x3530;
|
||||
m_needs_playstation_rock_band_3_instrument_control_transfer = true;
|
||||
break;
|
||||
case 0x2538: // Rock Band 3 MIDI Pro Adapter with Squier pro guitar
|
||||
m_spoofed_pid = 0x3538;
|
||||
m_needs_playstation_rock_band_3_instrument_control_transfer = true;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
m_spoofed_vid = 0x1bad;
|
||||
}
|
||||
|
||||
int LibusbDevice::SubmitPlayStationRockBand3InstrumentControlTransfer()
|
||||
{
|
||||
constexpr size_t length = 40;
|
||||
constexpr std::array<u8, length> enable_instrument_inputs = {
|
||||
0xe9, 0x00, 0x89, 0x1b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xe9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const size_t size = length + LIBUSB_CONTROL_SETUP_SIZE;
|
||||
auto buffer = std::make_unique<u8[]>(size);
|
||||
std::ranges::copy(enable_instrument_inputs, buffer.get() + LIBUSB_CONTROL_SETUP_SIZE);
|
||||
|
||||
libusb_fill_control_setup(buffer.get(), 0x21, 0x09, 0x0300, 0x00, length);
|
||||
|
||||
libusb_transfer* transfer = libusb_alloc_transfer(0);
|
||||
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
|
||||
libusb_fill_control_transfer(transfer, m_handle, buffer.release(), nullptr, this, 0);
|
||||
return libusb_submit_transfer(transfer);
|
||||
}
|
||||
|
||||
static bool IsRockBand3LEDControlTransfer(const CtrlMessage& cmd)
|
||||
{
|
||||
return cmd.request_type == 0x21 && cmd.request == 0x9 && cmd.length == 8;
|
||||
}
|
||||
|
||||
int LibusbDevice::SubmitTransfer(std::unique_ptr<CtrlMessage> cmd)
|
||||
{
|
||||
if (!m_device_attached)
|
||||
|
@ -253,11 +354,22 @@ int LibusbDevice::SubmitTransfer(std::unique_ptr<CtrlMessage> cmd)
|
|||
auto& memory = system.GetMemory();
|
||||
memory.CopyFromEmu(buffer.get() + LIBUSB_CONTROL_SETUP_SIZE, cmd->data_address, cmd->length);
|
||||
|
||||
// If the game is telling a Rock Band 3 device what player LEDs to turn on, take the opportunity
|
||||
// to also tell the device to enable instrument inputs if necessary
|
||||
const bool submit_rock_band_3_instrument_control_transfer =
|
||||
m_needs_playstation_rock_band_3_instrument_control_transfer &&
|
||||
IsRockBand3LEDControlTransfer(*cmd);
|
||||
|
||||
libusb_transfer* transfer = libusb_alloc_transfer(0);
|
||||
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
|
||||
libusb_fill_control_transfer(transfer, m_handle, buffer.release(), CtrlTransferCallback, this, 0);
|
||||
m_transfer_endpoints[0].AddTransfer(std::move(cmd), transfer);
|
||||
return libusb_submit_transfer(transfer);
|
||||
int ret = libusb_submit_transfer(transfer);
|
||||
|
||||
if (submit_rock_band_3_instrument_control_transfer)
|
||||
SubmitPlayStationRockBand3InstrumentControlTransfer();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int LibusbDevice::SubmitTransfer(std::unique_ptr<BulkMessage> cmd)
|
||||
|
|
|
@ -51,8 +51,11 @@ private:
|
|||
std::vector<LibusbUtils::ConfigDescriptor> m_config_descriptors;
|
||||
u16 m_vid = 0;
|
||||
u16 m_pid = 0;
|
||||
u16 m_spoofed_vid = 0;
|
||||
u16 m_spoofed_pid = 0;
|
||||
u8 m_active_interface = 0;
|
||||
bool m_device_attached = false;
|
||||
bool m_needs_playstation_rock_band_3_instrument_control_transfer = false;
|
||||
|
||||
libusb_device* m_device = nullptr;
|
||||
libusb_device_handle* m_handle = nullptr;
|
||||
|
@ -72,6 +75,9 @@ private:
|
|||
static void CtrlTransferCallback(libusb_transfer* transfer);
|
||||
static void TransferCallback(libusb_transfer* transfer);
|
||||
|
||||
void DisguisePlayStationDevice();
|
||||
int SubmitPlayStationRockBand3InstrumentControlTransfer();
|
||||
|
||||
int ClaimAllInterfaces(u8 config_num) const;
|
||||
int ReleaseAllInterfaces(u8 config_num) const;
|
||||
int ReleaseAllInterfacesForCurrentConfig() const;
|
||||
|
|
|
@ -17,20 +17,33 @@
|
|||
// Because opening and getting the device name from devices is slow, especially on Windows
|
||||
// with usbdk, we cannot do that for every single device. We should however still show
|
||||
// device names for known Wii peripherals.
|
||||
static const std::map<std::pair<u16, u16>, std::string_view> s_wii_peripherals{{
|
||||
static const std::map<std::pair<u16, u16>, std::string_view> s_known_peripherals{{
|
||||
{{0x046d, 0x0a03}, "Logitech Microphone"},
|
||||
{{0x057e, 0x0308}, "Wii Speak"},
|
||||
{{0x057e, 0x0309}, "Nintendo USB Microphone"},
|
||||
{{0x057e, 0x030a}, "Ubisoft Motion Tracking Camera"},
|
||||
{{0x0e6f, 0x0129}, "Disney Infinity Reader (Portal Device)"},
|
||||
{{0x12ba, 0x0200}, "Harmonix Guitar for PlayStation 3"},
|
||||
{{0x12ba, 0x0210}, "Harmonix Drum Kit for PlayStation 3"},
|
||||
{{0x12ba, 0x0218}, "Harmonix Drum Kit for PlayStation 3"},
|
||||
{{0x12ba, 0x2330}, "Harmonix RB3 Keyboard for PlayStation 3"},
|
||||
{{0x12ba, 0x2338}, "Harmonix RB3 MIDI Keyboard Interface for PlayStation 3"},
|
||||
{{0x12ba, 0x2430}, "Harmonix RB3 Mustang Guitar for PlayStation 3"},
|
||||
{{0x12ba, 0x2438}, "Harmonix RB3 MIDI Guitar Interface for PlayStation 3"},
|
||||
{{0x12ba, 0x2530}, "Harmonix RB3 Squier Guitar for PlayStation 3"},
|
||||
{{0x12ba, 0x2538}, "Harmonix RB3 MIDI Guitar Interface for PlayStation 3"},
|
||||
{{0x1430, 0x0100}, "Tony Hawk Ride Skateboard"},
|
||||
{{0x1430, 0x0150}, "Skylanders Portal"},
|
||||
{{0x1bad, 0x0004}, "Harmonix Guitar Controller"},
|
||||
{{0x1bad, 0x3110}, "Rock Band Drum Set"},
|
||||
{{0x1bad, 0x0004}, "Harmonix Guitar Controller for Nintendo Wii"},
|
||||
{{0x1bad, 0x0005}, "Harmonix Drum Controller for Nintendo Wii"},
|
||||
{{0x1bad, 0x3010}, "Harmonix Guitar Controller for Nintendo Wii"},
|
||||
{{0x1bad, 0x3110}, "Harmonix Drum Controller for Nintendo Wii"},
|
||||
{{0x1bad, 0x3138}, "Harmonix Drum Controller for Nintendo Wii"},
|
||||
{{0x1bad, 0x3330}, "Harmonix RB3 Keyboard for Nintendo Wii"},
|
||||
{{0x1bad, 0x3338}, "Harmonix RB3 MIDI Keyboard Interface for Nintendo Wii"},
|
||||
{{0x1bad, 0x3430}, "Harmonix RB3 Mustang Guitar for Nintendo Wii"},
|
||||
{{0x1bad, 0x3438}, "Harmonix RB3 MIDI Guitar Interface for Nintendo Wii"},
|
||||
{{0x1bad, 0x3530}, "Harmonix RB3 Squier Guitar for Nintendo Wii"},
|
||||
{{0x1bad, 0x3538}, "Harmonix RB3 MIDI Guitar Interface for Nintendo Wii"},
|
||||
{{0x21a4, 0xac40}, "EA Active NFL"},
|
||||
}};
|
||||
|
@ -62,8 +75,9 @@ std::map<std::pair<u16, u16>, std::string> GetInsertedDevices()
|
|||
|
||||
std::string GetDeviceName(const std::pair<u16, u16> vid_pid)
|
||||
{
|
||||
const auto iter = s_wii_peripherals.find(vid_pid);
|
||||
const std::string_view device_name = iter == s_wii_peripherals.cend() ? "Unknown" : iter->second;
|
||||
const auto iter = s_known_peripherals.find(vid_pid);
|
||||
const std::string_view device_name =
|
||||
iter == s_known_peripherals.cend() ? "Unknown" : iter->second;
|
||||
return fmt::format("{:04x}:{:04x} - {}", vid_pid.first, vid_pid.second, device_name);
|
||||
}
|
||||
} // namespace USBUtils
|
||||
|
|
Loading…
Reference in New Issue