mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 21:37:52 -07:00
Merge b95af2e6f0
into 375a990e41
This commit is contained in:
commit
39ae4b2c0e
@ -190,6 +190,8 @@ const Info<bool> MAIN_WIIMOTE_CONTINUOUS_SCANNING{
|
||||
const Info<bool> MAIN_WIIMOTE_ENABLE_SPEAKER{{System::Main, "Core", "WiimoteEnableSpeaker"}, false};
|
||||
const Info<bool> MAIN_CONNECT_WIIMOTES_FOR_CONTROLLER_INTERFACE{
|
||||
{System::Main, "Core", "WiimoteControllerInterface"}, false};
|
||||
const Info<bool> MAIN_USE_GC_ADAPTER_FOR_CONTROLLER_INTERFACE{
|
||||
{System::Main, "Core", "GCAdapterControllerInterface"}, false};
|
||||
const Info<bool> MAIN_MMU{{System::Main, "Core", "MMU"}, false};
|
||||
const Info<bool> MAIN_PAUSE_ON_PANIC{{System::Main, "Core", "PauseOnPanic"}, false};
|
||||
const Info<int> MAIN_BB_DUMP_PORT{{System::Main, "Core", "BBDumpPort"}, -1};
|
||||
|
@ -108,6 +108,7 @@ extern const Info<bool> MAIN_WII_KEYBOARD;
|
||||
extern const Info<bool> MAIN_WIIMOTE_CONTINUOUS_SCANNING;
|
||||
extern const Info<bool> MAIN_WIIMOTE_ENABLE_SPEAKER;
|
||||
extern const Info<bool> MAIN_CONNECT_WIIMOTES_FOR_CONTROLLER_INTERFACE;
|
||||
extern const Info<bool> MAIN_USE_GC_ADAPTER_FOR_CONTROLLER_INTERFACE;
|
||||
extern const Info<bool> MAIN_MMU;
|
||||
extern const Info<bool> MAIN_PAUSE_ON_PANIC;
|
||||
extern const Info<int> MAIN_BB_DUMP_PORT;
|
||||
|
@ -532,6 +532,7 @@
|
||||
<ClInclude Include="InputCommon\ControllerInterface\MappingCommon.h" />
|
||||
<ClInclude Include="InputCommon\ControllerInterface\WGInput\WGInput.h" />
|
||||
<ClInclude Include="InputCommon\ControllerInterface\Wiimote\WiimoteController.h" />
|
||||
<ClInclude Include="InputCommon\ControllerInterface\GCAdapter\GCAdapter.h" />
|
||||
<ClInclude Include="InputCommon\ControllerInterface\Win32\Win32.h" />
|
||||
<ClInclude Include="InputCommon\ControllerInterface\XInput\XInput.h" />
|
||||
<ClInclude Include="InputCommon\ControllerInterface\SDL\SDL.h" />
|
||||
@ -1193,6 +1194,7 @@
|
||||
<ClCompile Include="InputCommon\ControllerInterface\MappingCommon.cpp" />
|
||||
<ClCompile Include="InputCommon\ControllerInterface\WGInput\WGInput.cpp" />
|
||||
<ClCompile Include="InputCommon\ControllerInterface\Wiimote\WiimoteController.cpp" />
|
||||
<ClCompile Include="InputCommon\ControllerInterface\GCAdapter\GCAdapter.cpp" />
|
||||
<ClCompile Include="InputCommon\ControllerInterface\Win32\Win32.cpp" />
|
||||
<ClCompile Include="InputCommon\ControllerInterface\XInput\XInput.cpp" />
|
||||
<ClCompile Include="InputCommon\ControllerInterface\SDL\SDL.cpp" />
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "DolphinQt/Config/GamecubeControllersWidget.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
@ -95,6 +96,10 @@ void GamecubeControllersWidget::CreateLayout()
|
||||
m_gc_layout->addWidget(gc_box, controller_row, 1);
|
||||
m_gc_layout->addWidget(gc_button, controller_row, 2);
|
||||
}
|
||||
|
||||
m_gcpad_ciface = new QCheckBox(tr("Use Wii-U Adapter for Emulated Controllers"));
|
||||
m_gc_layout->addWidget(m_gcpad_ciface, m_gc_layout->rowCount(), 0, 1, -1);
|
||||
|
||||
m_gc_box->setLayout(m_gc_layout);
|
||||
|
||||
auto* layout = new QVBoxLayout;
|
||||
@ -114,6 +119,8 @@ void GamecubeControllersWidget::ConnectWidgets()
|
||||
});
|
||||
connect(m_gc_buttons[i], &QPushButton::clicked, this, [this, i] { OnGCPadConfigure(i); });
|
||||
}
|
||||
|
||||
connect(m_gcpad_ciface, &QCheckBox::toggled, this, &GamecubeControllersWidget::SaveSettings);
|
||||
}
|
||||
|
||||
void GamecubeControllersWidget::OnGCTypeChanged(size_t index)
|
||||
@ -184,6 +191,9 @@ void GamecubeControllersWidget::LoadSettings(Core::State state)
|
||||
OnGCTypeChanged(i);
|
||||
}
|
||||
}
|
||||
|
||||
SignalBlocking(m_gcpad_ciface)
|
||||
->setChecked(Config::Get(Config::MAIN_USE_GC_ADAPTER_FOR_CONTROLLER_INTERFACE));
|
||||
}
|
||||
|
||||
void GamecubeControllersWidget::SaveSettings()
|
||||
@ -203,11 +213,15 @@ void GamecubeControllersWidget::SaveSettings()
|
||||
system.GetSerialInterface().ChangeDevice(si_device, static_cast<s32>(i));
|
||||
}
|
||||
}
|
||||
|
||||
Config::SetBaseOrCurrent(Config::MAIN_USE_GC_ADAPTER_FOR_CONTROLLER_INTERFACE,
|
||||
m_gcpad_ciface->isChecked());
|
||||
}
|
||||
|
||||
SConfig::GetInstance().SaveSettings();
|
||||
|
||||
if (GCAdapter::UseAdapter())
|
||||
GCAdapter::StartScanThread();
|
||||
else
|
||||
GCAdapter::StopScanThread();
|
||||
|
||||
SConfig::GetInstance().SaveSettings();
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <array>
|
||||
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
class QHBoxLayout;
|
||||
class QGridLayout;
|
||||
@ -40,4 +41,5 @@ private:
|
||||
std::array<QComboBox*, 4> m_gc_controller_boxes;
|
||||
std::array<QPushButton*, 4> m_gc_buttons;
|
||||
std::array<QHBoxLayout*, 4> m_gc_groups;
|
||||
QCheckBox* m_gcpad_ciface;
|
||||
};
|
||||
|
@ -64,6 +64,8 @@ add_library(inputcommon
|
||||
ControllerInterface/MappingCommon.h
|
||||
ControllerInterface/Wiimote/WiimoteController.cpp
|
||||
ControllerInterface/Wiimote/WiimoteController.h
|
||||
ControllerInterface/GCAdapter/GCAdapter.cpp
|
||||
ControllerInterface/GCAdapter/GCAdapter.h
|
||||
ControlReference/ControlReference.cpp
|
||||
ControlReference/ControlReference.h
|
||||
ControlReference/ExpressionParser.cpp
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "Common/Assert.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
||||
#include "InputCommon/ControllerInterface/GCAdapter/GCAdapter.h"
|
||||
|
||||
#ifdef CIFACE_USE_WIN32
|
||||
#include "InputCommon/ControllerInterface/Win32/Win32.h"
|
||||
@ -86,6 +87,9 @@ void ControllerInterface::Initialize(const WindowSystemInfo& wsi)
|
||||
m_input_backends.emplace_back(ciface::SteamDeck::CreateInputBackend(this));
|
||||
#endif
|
||||
|
||||
// TODO: obey Config::Get(Config::MAIN_USE_GC_ADAPTER_FOR_CONTROLLER_INTERFACE)
|
||||
m_input_backends.emplace_back(ciface::GCAdapter::CreateInputBackend(this));
|
||||
|
||||
// Don't allow backends to add devices before the first RefreshDevices() as they will be cleaned
|
||||
// there. Or they'd end up waiting on the devices mutex if populated from another thread.
|
||||
m_is_init = true;
|
||||
|
@ -0,0 +1,258 @@
|
||||
// Copyright 2022 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "InputCommon/ControllerInterface/GCAdapter/GCAdapter.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "Core/HW/SI/SI.h"
|
||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||
#include "InputCommon/GCAdapter.h"
|
||||
#include "InputCommon/GCPadStatus.h"
|
||||
|
||||
// TODO: namespace name matching the one in InputCommon/GCAdapter.h is annoying
|
||||
namespace ciface::GCAdapter
|
||||
{
|
||||
constexpr auto SOURCE_NAME = "GCAdapter";
|
||||
|
||||
class GCController;
|
||||
|
||||
class InputBackend final : public ciface::InputBackend
|
||||
{
|
||||
public:
|
||||
InputBackend(ControllerInterface* controller_interface);
|
||||
void PopulateDevices() override;
|
||||
void UpdateInput(std::vector<std::weak_ptr<ciface::Core::Device>>& devices_to_remove) override;
|
||||
|
||||
private:
|
||||
std::array<std::weak_ptr<GCController>, SerialInterface::MAX_SI_CHANNELS> m_devices;
|
||||
};
|
||||
|
||||
std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface)
|
||||
{
|
||||
return std::make_unique<InputBackend>(controller_interface);
|
||||
}
|
||||
|
||||
struct DigitalInputProps
|
||||
{
|
||||
u16 value;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
constexpr DigitalInputProps digital_inputs[] = {
|
||||
{PAD_BUTTON_UP, "Up"},
|
||||
{PAD_BUTTON_DOWN, "Down"},
|
||||
{PAD_BUTTON_LEFT, "Left"},
|
||||
{PAD_BUTTON_RIGHT, "Right"},
|
||||
{PAD_BUTTON_A, "A"},
|
||||
{PAD_BUTTON_B, "B"},
|
||||
{PAD_BUTTON_X, "X"},
|
||||
{PAD_BUTTON_Y, "Y"},
|
||||
{PAD_TRIGGER_Z, "Z"},
|
||||
{PAD_TRIGGER_L, "L"},
|
||||
{PAD_TRIGGER_R, "R"},
|
||||
// TODO: "START" or "Start"?
|
||||
{PAD_BUTTON_START, "Start"},
|
||||
};
|
||||
|
||||
struct AnalogInputProps
|
||||
{
|
||||
u8 GCPadStatus::*ptr;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
constexpr AnalogInputProps stick_inputs[] = {
|
||||
{&GCPadStatus::stickX, "Main X"},
|
||||
{&GCPadStatus::stickY, "Main Y"},
|
||||
{&GCPadStatus::substickX, "C X"},
|
||||
{&GCPadStatus::substickY, "C Y"},
|
||||
};
|
||||
|
||||
constexpr AnalogInputProps trigger_inputs[] = {
|
||||
{&GCPadStatus::triggerLeft, "L-Analog"},
|
||||
{&GCPadStatus::triggerRight, "R-Analog"},
|
||||
};
|
||||
|
||||
class DigitalInput : public Core::Device::Input
|
||||
{
|
||||
public:
|
||||
DigitalInput(const u16* button_state, u32 index) : m_button_state{*button_state}, m_index{index}
|
||||
{
|
||||
}
|
||||
|
||||
std::string GetName() const override { return digital_inputs[m_index].name; }
|
||||
|
||||
ControlState GetState() const override
|
||||
{
|
||||
return (digital_inputs[m_index].value & m_button_state) != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
const u16& m_button_state;
|
||||
const u32 m_index;
|
||||
};
|
||||
|
||||
class AnalogInput : public Core::Device::Input
|
||||
{
|
||||
public:
|
||||
AnalogInput(const GCPadStatus* pad_status, const AnalogInputProps& props, u8 neutral_value,
|
||||
s32 range)
|
||||
: m_base_name{props.name}, m_neutral_value{neutral_value}, m_range{range},
|
||||
m_state{pad_status->*props.ptr}
|
||||
{
|
||||
}
|
||||
|
||||
ControlState GetState() const override
|
||||
{
|
||||
return ControlState(m_state - m_neutral_value) / m_range;
|
||||
}
|
||||
|
||||
protected:
|
||||
const char* const m_base_name;
|
||||
const u8 m_neutral_value;
|
||||
const s32 m_range;
|
||||
|
||||
private:
|
||||
const u8& m_state;
|
||||
};
|
||||
|
||||
class StickInput : public AnalogInput
|
||||
{
|
||||
public:
|
||||
using AnalogInput::AnalogInput;
|
||||
|
||||
std::string GetName() const override
|
||||
{
|
||||
return std::string(m_base_name) + (m_range > 0 ? '+' : '-');
|
||||
}
|
||||
};
|
||||
|
||||
class TriggerInput : public AnalogInput
|
||||
{
|
||||
public:
|
||||
using AnalogInput::AnalogInput;
|
||||
|
||||
std::string GetName() const override { return m_base_name; }
|
||||
};
|
||||
|
||||
class Motor : public Core::Device::Output
|
||||
{
|
||||
public:
|
||||
Motor(u32 index) : m_index{index} {}
|
||||
|
||||
void SetState(ControlState value) override
|
||||
{
|
||||
const bool new_state = std::lround(value);
|
||||
|
||||
if (new_state == m_last_state)
|
||||
return;
|
||||
|
||||
m_last_state = new_state;
|
||||
|
||||
::GCAdapter::Output(m_index, new_state);
|
||||
}
|
||||
|
||||
std::string GetName() const override { return "Motor"; }
|
||||
|
||||
private:
|
||||
u32 m_index;
|
||||
bool m_last_state = false;
|
||||
};
|
||||
|
||||
class GCController : public Core::Device
|
||||
{
|
||||
public:
|
||||
GCController(u32 index) : m_index{index}
|
||||
{
|
||||
// Add buttons.
|
||||
for (u32 i = 0; i != std::size(digital_inputs); ++i)
|
||||
AddInput(new DigitalInput{&m_pad_status.button, i});
|
||||
|
||||
// TODO: use origin values.
|
||||
const auto origin = ::GCAdapter::GetOrigin(index);
|
||||
|
||||
// Add sticks.
|
||||
for (auto& props : stick_inputs)
|
||||
{
|
||||
// Add separate -/+ inputs.
|
||||
AddInput(new StickInput{&m_pad_status, props, GCPadStatus::MAIN_STICK_CENTER_X,
|
||||
-GCPadStatus::MAIN_STICK_RADIUS});
|
||||
AddInput(new StickInput{&m_pad_status, props, GCPadStatus::MAIN_STICK_CENTER_X,
|
||||
GCPadStatus::MAIN_STICK_RADIUS});
|
||||
}
|
||||
|
||||
// Add triggers.
|
||||
for (auto& props : trigger_inputs)
|
||||
AddInput(new TriggerInput{&m_pad_status, props, 0, std::numeric_limits<u8>::max()});
|
||||
|
||||
// Rumble.
|
||||
AddOutput(new Motor{index});
|
||||
}
|
||||
|
||||
std::optional<int> GetPreferredId() const override { return m_index; }
|
||||
|
||||
std::string GetName() const override
|
||||
{
|
||||
// TODO: name?
|
||||
return "GCPad";
|
||||
}
|
||||
|
||||
std::string GetSource() const override { return SOURCE_NAME; }
|
||||
|
||||
int GetSortPriority() const override { return -3; }
|
||||
|
||||
Core::DeviceRemoval UpdateInput() override
|
||||
{
|
||||
m_pad_status = ::GCAdapter::PeekInput(m_index);
|
||||
return Core::DeviceRemoval::Keep;
|
||||
}
|
||||
|
||||
private:
|
||||
GCPadStatus m_pad_status;
|
||||
const u32 m_index;
|
||||
};
|
||||
|
||||
InputBackend::InputBackend(ControllerInterface* controller_interface)
|
||||
: ciface::InputBackend(controller_interface)
|
||||
{
|
||||
::GCAdapter::Init();
|
||||
}
|
||||
|
||||
void InputBackend::PopulateDevices()
|
||||
{
|
||||
for (int i = 0; i != SerialInterface::MAX_SI_CHANNELS; ++i)
|
||||
{
|
||||
if (::GCAdapter::DeviceConnected(i))
|
||||
{
|
||||
auto new_device = std::make_shared<GCController>(i);
|
||||
m_devices[i] = new_device;
|
||||
GetControllerInterface().AddDevice(std::move(new_device));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputBackend::UpdateInput(std::vector<std::weak_ptr<ciface::Core::Device>>& devices_to_remove)
|
||||
{
|
||||
// "Hotplug" is handled here.
|
||||
for (int i = 0; i != SerialInterface::MAX_SI_CHANNELS; ++i)
|
||||
{
|
||||
const bool is_device_connected = ::GCAdapter::DeviceConnected(i);
|
||||
const auto device = m_devices[i].lock();
|
||||
|
||||
if (is_device_connected == (device != nullptr))
|
||||
continue;
|
||||
|
||||
if (is_device_connected)
|
||||
{
|
||||
auto new_device = std::make_shared<GCController>(i);
|
||||
m_devices[i] = new_device;
|
||||
GetControllerInterface().AddDevice(std::move(new_device));
|
||||
}
|
||||
else
|
||||
{
|
||||
devices_to_remove.emplace_back(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ciface::GCAdapter
|
@ -0,0 +1,14 @@
|
||||
// Copyright 2022 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "InputCommon/ControllerInterface/InputBackend.h"
|
||||
|
||||
namespace ciface::GCAdapter
|
||||
{
|
||||
std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface);
|
||||
|
||||
} // namespace ciface::GCAdapter
|
@ -142,15 +142,6 @@ static Common::Event s_hotplug_event;
|
||||
|
||||
static std::function<void(void)> s_detect_callback;
|
||||
|
||||
#if defined(__FreeBSD__) && __FreeBSD__ >= 11
|
||||
static bool s_libusb_hotplug_enabled = true;
|
||||
#else
|
||||
static bool s_libusb_hotplug_enabled = false;
|
||||
#endif
|
||||
#if LIBUSB_API_HAS_HOTPLUG
|
||||
static libusb_hotplug_callback_handle s_hotplug_handle;
|
||||
#endif
|
||||
|
||||
static std::unique_ptr<LibusbUtils::Context> s_libusb_context;
|
||||
|
||||
static u8 s_endpoint_in = 0;
|
||||
@ -346,24 +337,32 @@ static void ScanThreadFunc()
|
||||
|
||||
#if GCADAPTER_USE_LIBUSB_IMPLEMENTATION
|
||||
#if LIBUSB_API_HAS_HOTPLUG
|
||||
#ifndef __FreeBSD__
|
||||
s_libusb_hotplug_enabled = libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG) != 0;
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#if __FreeBSD__ >= 11
|
||||
bool hotplug_enabled = true;
|
||||
#else
|
||||
bool hotplug_enabled = false;
|
||||
#endif
|
||||
if (s_libusb_hotplug_enabled)
|
||||
#else
|
||||
bool hotplug_enabled = libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG) != 0;
|
||||
#endif
|
||||
libusb_hotplug_callback_handle hotplug_handle = {};
|
||||
if (hotplug_enabled)
|
||||
{
|
||||
const int error = libusb_hotplug_register_callback(
|
||||
*s_libusb_context,
|
||||
(libusb_hotplug_event)(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
|
||||
LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
|
||||
LIBUSB_HOTPLUG_ENUMERATE, 0x057e, 0x0337, LIBUSB_HOTPLUG_MATCH_ANY, HotplugCallback,
|
||||
nullptr, &s_hotplug_handle);
|
||||
nullptr, &hotplug_handle);
|
||||
if (error == LIBUSB_SUCCESS)
|
||||
{
|
||||
NOTICE_LOG_FMT(CONTROLLERINTERFACE, "Using libUSB hotplug detection");
|
||||
}
|
||||
else
|
||||
{
|
||||
s_libusb_hotplug_enabled = false;
|
||||
hotplug_enabled = false;
|
||||
ERROR_LOG_FMT(CONTROLLERINTERFACE, "Failed to add libUSB hotplug detection callback: {}",
|
||||
LibusbUtils::ErrorWrap(error));
|
||||
}
|
||||
@ -378,11 +377,17 @@ static void ScanThreadFunc()
|
||||
Setup();
|
||||
}
|
||||
|
||||
if (s_libusb_hotplug_enabled)
|
||||
if (hotplug_enabled)
|
||||
s_hotplug_event.Wait();
|
||||
else
|
||||
Common::SleepCurrentThread(500);
|
||||
}
|
||||
|
||||
#if LIBUSB_API_HAS_HOTPLUG
|
||||
if (hotplug_enabled)
|
||||
libusb_hotplug_deregister_callback(*s_libusb_context, hotplug_handle);
|
||||
#endif
|
||||
|
||||
#elif GCADAPTER_USE_ANDROID_IMPLEMENTATION
|
||||
JNIEnv* const env = IDCache::GetEnvForThread();
|
||||
|
||||
@ -410,12 +415,14 @@ void SetAdapterCallback(std::function<void(void)> func)
|
||||
|
||||
static void RefreshConfig()
|
||||
{
|
||||
s_is_adapter_wanted = false;
|
||||
s_is_adapter_wanted = Config::Get(Config::MAIN_USE_GC_ADAPTER_FOR_CONTROLLER_INTERFACE);
|
||||
|
||||
for (int i = 0; i < SerialInterface::MAX_SI_CHANNELS; ++i)
|
||||
{
|
||||
s_is_adapter_wanted |= Config::Get(Config::GetInfoForSIDevice(i)) ==
|
||||
SerialInterface::SIDevices::SIDEVICE_WIIU_ADAPTER;
|
||||
|
||||
// TODO: ControllerInterface shouldn't obey this setting.
|
||||
s_config_rumble_enabled[i] = Config::Get(Config::GetInfoForAdapterRumble(i));
|
||||
}
|
||||
}
|
||||
@ -676,12 +683,6 @@ static void AddGCAdapter(libusb_device* device)
|
||||
void Shutdown()
|
||||
{
|
||||
StopScanThread();
|
||||
#if GCADAPTER_USE_LIBUSB_IMPLEMENTATION
|
||||
#if LIBUSB_API_HAS_HOTPLUG
|
||||
if (s_libusb_context->IsValid() && s_libusb_hotplug_enabled)
|
||||
libusb_hotplug_deregister_callback(*s_libusb_context, s_hotplug_handle);
|
||||
#endif
|
||||
#endif
|
||||
Reset();
|
||||
|
||||
#if GCADAPTER_USE_LIBUSB_IMPLEMENTATION
|
||||
@ -766,6 +767,18 @@ GCPadStatus Input(int chan)
|
||||
return pad_state.status;
|
||||
}
|
||||
|
||||
GCPadStatus PeekInput(int chan)
|
||||
{
|
||||
std::lock_guard lk(s_read_mutex);
|
||||
return s_port_states[chan].status;
|
||||
}
|
||||
|
||||
GCPadStatus GetOrigin(int chan)
|
||||
{
|
||||
std::lock_guard lk(s_read_mutex);
|
||||
return s_port_states[chan].origin;
|
||||
}
|
||||
|
||||
// Get ControllerType from first byte in input payload.
|
||||
static ControllerType IdentifyControllerType(u8 data)
|
||||
{
|
||||
|
@ -22,6 +22,11 @@ void StopScanThread();
|
||||
// Netplay and CSIDevice_GCAdapter make use of this.
|
||||
GCPadStatus Input(int chan);
|
||||
|
||||
// Retreive the latest input without changing the new connection flag.
|
||||
GCPadStatus PeekInput(int chan);
|
||||
|
||||
GCPadStatus GetOrigin(int chan);
|
||||
|
||||
void Output(int chan, u8 rumble_command);
|
||||
bool IsDetected(const char** error_message);
|
||||
bool DeviceConnected(int chan);
|
||||
|
Loading…
Reference in New Issue
Block a user