| | |
| | |
| | |
| |
|
| | #pragma once |
| |
|
| | #include <algorithm> |
| | #include <array> |
| | #include <functional> |
| | #include <mutex> |
| | #include <thread> |
| | #include <vector> |
| | #include "common/common_types.h" |
| | #include "common/threadsafe_queue.h" |
| |
|
| | struct libusb_context; |
| | struct libusb_device; |
| | struct libusb_device_handle; |
| |
|
| | namespace Common { |
| | class ParamPackage; |
| | } |
| |
|
| | namespace GCAdapter { |
| |
|
| | 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, |
| | |
| | Stick = 0x2000, |
| | }; |
| |
|
| | enum class PadAxes : u8 { |
| | StickX, |
| | StickY, |
| | SubstickX, |
| | SubstickY, |
| | TriggerLeft, |
| | TriggerRight, |
| | Undefined, |
| | }; |
| |
|
| | enum class ControllerTypes { |
| | None, |
| | Wired, |
| | Wireless, |
| | }; |
| |
|
| | struct GCPadStatus { |
| | std::size_t port{}; |
| |
|
| | PadButton button{PadButton::Undefined}; |
| |
|
| | PadAxes axis{PadAxes::Undefined}; |
| | s16 axis_value{}; |
| | u8 axis_threshold{50}; |
| | }; |
| |
|
| | struct GCController { |
| | ControllerTypes type{}; |
| | u16 buttons{}; |
| | PadButton last_button{}; |
| | std::array<s16, 6> axis_values{}; |
| | std::array<u8, 6> axis_origin{}; |
| | }; |
| |
|
| | class Adapter { |
| | public: |
| | Adapter(); |
| | ~Adapter(); |
| |
|
| | |
| | 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; |
| |
|
| | |
| | bool DeviceConnected(std::size_t port) const; |
| |
|
| | std::vector<Common::ParamPackage> GetInputDevices() const; |
| |
|
| | private: |
| | using AdapterPayload = std::array<u8, 37>; |
| |
|
| | void UpdatePadType(std::size_t port, ControllerTypes pad_type); |
| | void UpdateControllers(const AdapterPayload& adapter_payload); |
| | void UpdateSettings(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 AdapterInputThread(); |
| |
|
| | void AdapterScanThread(); |
| |
|
| | bool IsPayloadCorrect(const AdapterPayload& adapter_payload, s32 payload_size); |
| |
|
| | |
| | void Setup(); |
| |
|
| | |
| | void ResetDevices(); |
| |
|
| | |
| | void ResetDevice(std::size_t port); |
| |
|
| | |
| | bool CheckDeviceAccess(); |
| |
|
| | |
| | |
| | bool GetGCEndpoint(libusb_device* device); |
| |
|
| | |
| | void JoinThreads(); |
| |
|
| | |
| | void ClearLibusbHandle(); |
| |
|
| | 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}; |
| |
|
| | bool configuring{false}; |
| | }; |
| | } |
| |
|