2022-04-28 18:24:11 +02:00
|
|
|
// SPDX-FileCopyrightText: 2014 Dolphin Emulator Project
|
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2021-09-21 00:22:07 +02:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2021-10-31 04:23:10 +01:00
|
|
|
#include <array>
|
|
|
|
#include <memory>
|
|
|
|
#include <string>
|
2021-09-21 00:22:07 +02:00
|
|
|
#include <thread>
|
|
|
|
|
2022-11-21 17:31:18 +01:00
|
|
|
#include "common/polyfill_thread.h"
|
2021-09-21 00:22:07 +02:00
|
|
|
#include "input_common/input_engine.h"
|
|
|
|
|
|
|
|
struct libusb_context;
|
|
|
|
struct libusb_device;
|
|
|
|
struct libusb_device_handle;
|
|
|
|
|
|
|
|
namespace InputCommon {
|
|
|
|
|
|
|
|
class LibUSBContext;
|
|
|
|
class LibUSBDeviceHandle;
|
|
|
|
|
2021-12-13 15:05:23 +01:00
|
|
|
class GCAdapter : public InputEngine {
|
2021-09-21 00:22:07 +02:00
|
|
|
public:
|
2021-12-13 15:05:23 +01:00
|
|
|
explicit GCAdapter(std::string input_engine_);
|
|
|
|
~GCAdapter() override;
|
2021-09-21 00:22:07 +02:00
|
|
|
|
2022-12-26 18:11:01 +01:00
|
|
|
Common::Input::DriverResult SetVibration(
|
2021-12-13 15:09:03 +01:00
|
|
|
const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override;
|
2021-09-21 00:22:07 +02:00
|
|
|
|
2022-10-21 07:23:12 +02:00
|
|
|
bool IsVibrationEnabled(const PadIdentifier& identifier) override;
|
|
|
|
|
2021-09-21 00:22:07 +02:00
|
|
|
/// Used for automapping features
|
|
|
|
std::vector<Common::ParamPackage> GetInputDevices() const override;
|
|
|
|
ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override;
|
|
|
|
AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override;
|
2021-11-21 21:12:01 +01:00
|
|
|
Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override;
|
2021-09-21 00:22:07 +02:00
|
|
|
|
2022-03-04 18:47:13 +01:00
|
|
|
bool IsStickInverted(const Common::ParamPackage& params) override;
|
|
|
|
|
2021-09-21 00:22:07 +02:00
|
|
|
private:
|
|
|
|
enum class PadButton {
|
|
|
|
Undefined = 0x0000,
|
|
|
|
ButtonLeft = 0x0001,
|
|
|
|
ButtonRight = 0x0002,
|
|
|
|
ButtonDown = 0x0004,
|
|
|
|
ButtonUp = 0x0008,
|
|
|
|
TriggerZ = 0x0010,
|
|
|
|
TriggerR = 0x0020,
|
|
|
|
TriggerL = 0x0040,
|
|
|
|
ButtonA = 0x0100,
|
|
|
|
ButtonB = 0x0200,
|
|
|
|
ButtonX = 0x0400,
|
|
|
|
ButtonY = 0x0800,
|
|
|
|
ButtonStart = 0x1000,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class PadAxes : u8 {
|
|
|
|
StickX,
|
|
|
|
StickY,
|
|
|
|
SubstickX,
|
|
|
|
SubstickY,
|
|
|
|
TriggerLeft,
|
|
|
|
TriggerRight,
|
|
|
|
Undefined,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class ControllerTypes {
|
|
|
|
None,
|
|
|
|
Wired,
|
|
|
|
Wireless,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct GCController {
|
|
|
|
ControllerTypes type = ControllerTypes::None;
|
|
|
|
PadIdentifier identifier{};
|
|
|
|
bool enable_vibration = false;
|
|
|
|
u8 rumble_amplitude{};
|
|
|
|
std::array<u8, 6> axis_origin{};
|
|
|
|
u8 reset_origin_counter{};
|
|
|
|
};
|
|
|
|
|
|
|
|
using AdapterPayload = std::array<u8, 37>;
|
|
|
|
|
|
|
|
void UpdatePadType(std::size_t port, ControllerTypes pad_type);
|
|
|
|
void UpdateControllers(const AdapterPayload& adapter_payload);
|
|
|
|
void UpdateStateButtons(std::size_t port, u8 b1, u8 b2);
|
|
|
|
void UpdateStateAxes(std::size_t port, const AdapterPayload& adapter_payload);
|
|
|
|
|
|
|
|
void AdapterInputThread(std::stop_token stop_token);
|
|
|
|
|
|
|
|
void AdapterScanThread(std::stop_token stop_token);
|
|
|
|
|
|
|
|
bool IsPayloadCorrect(const AdapterPayload& adapter_payload, s32 payload_size);
|
|
|
|
|
|
|
|
/// For use in initialization, querying devices to find the adapter
|
|
|
|
bool Setup();
|
|
|
|
|
|
|
|
/// Returns true if we successfully gain access to GC Adapter
|
|
|
|
bool CheckDeviceAccess();
|
|
|
|
|
|
|
|
/// Captures GC Adapter endpoint address
|
|
|
|
/// Returns true if the endpoint was set correctly
|
|
|
|
bool GetGCEndpoint(libusb_device* device);
|
|
|
|
|
|
|
|
/// Returns true if there is a device connected to port
|
|
|
|
bool DeviceConnected(std::size_t port) const;
|
|
|
|
|
|
|
|
/// For shutting down, clear all data, join all threads, release usb
|
|
|
|
void Reset();
|
|
|
|
|
|
|
|
void UpdateVibrations();
|
2021-10-19 07:12:24 +02:00
|
|
|
|
|
|
|
/// Updates vibration state of all controllers
|
2021-09-21 00:22:07 +02:00
|
|
|
void SendVibrations();
|
2021-10-19 07:12:24 +02:00
|
|
|
|
2021-11-21 21:12:01 +01:00
|
|
|
Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const;
|
2021-10-19 07:12:24 +02:00
|
|
|
|
2021-09-21 00:22:07 +02:00
|
|
|
std::unique_ptr<LibUSBDeviceHandle> usb_adapter_handle;
|
|
|
|
std::array<GCController, 4> pads;
|
|
|
|
|
|
|
|
std::jthread adapter_input_thread;
|
|
|
|
std::jthread adapter_scan_thread;
|
|
|
|
bool restart_scan_thread{};
|
|
|
|
|
|
|
|
std::unique_ptr<LibUSBContext> libusb_ctx;
|
|
|
|
|
|
|
|
u8 input_endpoint{0};
|
|
|
|
u8 output_endpoint{0};
|
|
|
|
u8 input_error_counter{0};
|
|
|
|
u8 output_error_counter{0};
|
|
|
|
int vibration_counter{0};
|
|
|
|
|
|
|
|
bool rumble_enabled{true};
|
|
|
|
bool vibration_changed{true};
|
|
|
|
};
|
|
|
|
} // namespace InputCommon
|