yuzu-fork/src/input_common/gcadapter/gc_adapter.h

168 lines
4.3 KiB
C++
Raw Normal View History

2020-06-21 20:31:57 +01:00
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
2020-06-21 17:36:28 +01:00
#pragma once
#include <algorithm>
#include <functional>
2020-06-21 20:31:57 +01:00
#include <mutex>
2020-06-22 01:32:43 +01:00
#include <thread>
#include <unordered_map>
2020-06-21 17:36:28 +01:00
#include "common/common_types.h"
#include "common/threadsafe_queue.h"
2020-09-02 00:17:59 +01:00
#include "input_common/main.h"
struct libusb_context;
struct libusb_device;
struct libusb_device_handle;
namespace GCAdapter {
2020-06-21 17:36:28 +01:00
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,
2020-06-21 17:36:28 +01:00
// Below is for compatibility with "AxisButton" type
Stick = 0x2000,
2020-06-21 17:36:28 +01:00
};
enum class PadAxes : u8 {
StickX,
StickY,
SubstickX,
SubstickY,
TriggerLeft,
TriggerRight,
Undefined,
};
2020-06-21 17:36:28 +01:00
enum class ControllerTypes {
None,
Wired,
Wireless,
};
2020-06-21 17:36:28 +01:00
struct GCPadStatus {
std::size_t port{};
2020-07-16 18:00:04 +01:00
PadButton button{PadButton::Undefined}; // Or-ed PAD_BUTTON_* and PAD_TRIGGER_* bits
PadAxes axis{PadAxes::Undefined};
s16 axis_value{};
u8 axis_threshold{50};
2020-06-21 17:36:28 +01:00
};
struct GCController {
ControllerTypes type{};
bool enable_vibration{};
u8 rumble_amplitude{};
u16 buttons{};
PadButton last_button{};
std::array<s16, 6> axis_values{};
std::array<u8, 6> axis_origin{};
2020-06-21 17:36:28 +01:00
};
class Adapter {
public:
Adapter();
~Adapter();
/// Request a vibration for a controller
bool RumblePlay(std::size_t port, u8 amplitude);
/// Used for polling
void BeginConfiguration();
void EndConfiguration();
Common::SPSCQueue<GCPadStatus>& GetPadQueue();
const Common::SPSCQueue<GCPadStatus>& GetPadQueue() const;
GCController& GetPadState(std::size_t port);
const GCController& GetPadState(std::size_t port) const;
/// Returns true if there is a device connected to port
bool DeviceConnected(std::size_t port) const;
/// Used for automapping features
2020-09-02 00:17:59 +01:00
std::vector<Common::ParamPackage> GetInputDevices() const;
InputCommon::ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) const;
InputCommon::AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) const;
private:
using AdapterPayload = std::array<u8, 37>;
void UpdatePadType(std::size_t port, ControllerTypes pad_type);
void UpdateControllers(const AdapterPayload& adapter_payload);
void UpdateYuzuSettings(std::size_t port);
void UpdateStateButtons(std::size_t port, u8 b1, u8 b2);
void UpdateStateAxes(std::size_t port, const AdapterPayload& adapter_payload);
void UpdateVibrations();
void AdapterInputThread();
void AdapterScanThread();
bool IsPayloadCorrect(const AdapterPayload& adapter_payload, s32 payload_size);
// Updates vibration state of all controllers
void SendVibrations();
/// For use in initialization, querying devices to find the adapter
void Setup();
2020-06-21 17:36:28 +01:00
/// Resets status of all GC controller devices to a disconected state
void ResetDevices();
2020-06-21 17:36:28 +01:00
/// Resets status of device connected to a disconected state
void ResetDevice(std::size_t port);
2020-06-21 17:36:28 +01:00
/// Returns true if we successfully gain access to GC Adapter
bool CheckDeviceAccess();
2020-06-21 17:36:28 +01:00
/// Captures GC Adapter endpoint address
/// Returns true if the endpoind was set correctly
bool GetGCEndpoint(libusb_device* device);
2020-06-21 17:36:28 +01:00
/// For shutting down, clear all data, join all threads, release usb
void Reset();
2020-06-21 17:36:28 +01:00
// Join all threads
void JoinThreads();
// Release usb handles
void ClearLibusbHandle();
2020-06-21 17:36:28 +01:00
libusb_device_handle* usb_adapter_handle = nullptr;
std::array<GCController, 4> pads;
Common::SPSCQueue<GCPadStatus> pad_queue;
std::thread adapter_input_thread;
std::thread adapter_scan_thread;
bool adapter_input_thread_running;
bool adapter_scan_thread_running;
bool restart_scan_thread;
libusb_context* 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 configuring{false};
bool rumble_enabled{true};
bool vibration_changed{true};
};
} // namespace GCAdapter