| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- // Copyright 2014 Dolphin Emulator Project
- // Licensed under GPLv2+
- // Refer to the license.txt file included.
- #pragma once
- #include <algorithm>
- #include <functional>
- #include <mutex>
- #include <thread>
- #include <libusb.h>
- #include "common/common_types.h"
- #include "common/threadsafe_queue.h"
- namespace GCAdapter {
- enum {
- PAD_USE_ORIGIN = 0x0080,
- PAD_GET_ORIGIN = 0x2000,
- PAD_ERR_STATUS = 0x8000,
- };
- enum class PadButton {
- PAD_BUTTON_LEFT = 0x0001,
- PAD_BUTTON_RIGHT = 0x0002,
- PAD_BUTTON_DOWN = 0x0004,
- PAD_BUTTON_UP = 0x0008,
- PAD_TRIGGER_Z = 0x0010,
- PAD_TRIGGER_R = 0x0020,
- PAD_TRIGGER_L = 0x0040,
- PAD_BUTTON_A = 0x0100,
- PAD_BUTTON_B = 0x0200,
- PAD_BUTTON_X = 0x0400,
- PAD_BUTTON_Y = 0x0800,
- PAD_BUTTON_START = 0x1000,
- // Below is for compatibility with "AxisButton" type
- PAD_STICK = 0x2000,
- };
- /// Used to loop through the and assign button in poller
- static constexpr std::array<PadButton, 12> PadButtonArray{
- PadButton::PAD_BUTTON_LEFT, PadButton::PAD_BUTTON_RIGHT, PadButton::PAD_BUTTON_DOWN,
- PadButton::PAD_BUTTON_UP, PadButton::PAD_TRIGGER_Z, PadButton::PAD_TRIGGER_R,
- PadButton::PAD_TRIGGER_L, PadButton::PAD_BUTTON_A, PadButton::PAD_BUTTON_B,
- PadButton::PAD_BUTTON_X, PadButton::PAD_BUTTON_Y, PadButton::PAD_BUTTON_START};
- enum class PadAxes : u8 {
- StickX,
- StickY,
- SubstickX,
- SubstickY,
- TriggerLeft,
- TriggerRight,
- Undefined,
- };
- struct GCPadStatus {
- u16 button{}; // Or-ed PAD_BUTTON_* and PAD_TRIGGER_* bits
- u8 stick_x{}; // 0 <= stick_x <= 255
- u8 stick_y{}; // 0 <= stick_y <= 255
- u8 substick_x{}; // 0 <= substick_x <= 255
- u8 substick_y{}; // 0 <= substick_y <= 255
- u8 trigger_left{}; // 0 <= trigger_left <= 255
- u8 trigger_right{}; // 0 <= trigger_right <= 255
- static constexpr u8 MAIN_STICK_CENTER_X = 0x80;
- static constexpr u8 MAIN_STICK_CENTER_Y = 0x80;
- static constexpr u8 MAIN_STICK_RADIUS = 0x7f;
- static constexpr u8 C_STICK_CENTER_X = 0x80;
- static constexpr u8 C_STICK_CENTER_Y = 0x80;
- static constexpr u8 C_STICK_RADIUS = 0x7f;
- static constexpr u8 TRIGGER_CENTER = 20;
- static constexpr u8 THRESHOLD = 10;
- u8 port{};
- PadAxes axis{PadAxes::Undefined};
- u8 axis_value{255};
- };
- struct GCState {
- std::unordered_map<int, bool> buttons;
- std::unordered_map<int, u16> axes;
- };
- enum class ControllerTypes { None, Wired, Wireless };
- enum {
- NO_ADAPTER_DETECTED = 0,
- ADAPTER_DETECTED = 1,
- };
- class Adapter {
- public:
- /// Initialize the GC Adapter capture and read sequence
- Adapter();
- /// Close the adapter read thread and release the adapter
- ~Adapter();
- /// Used for polling
- void BeginConfiguration();
- void EndConfiguration();
- std::array<Common::SPSCQueue<GCPadStatus>, 4>& GetPadQueue();
- const std::array<Common::SPSCQueue<GCPadStatus>, 4>& GetPadQueue() const;
- std::array<GCState, 4>& GetPadState();
- const std::array<GCState, 4>& GetPadState() const;
- private:
- GCPadStatus GetPadStatus(int port, const std::array<u8, 37>& adapter_payload);
- void PadToState(const GCPadStatus& pad, GCState& state);
- void Read();
- void ScanThreadFunc();
- /// Begin scanning for the GC Adapter.
- void StartScanThread();
- /// Stop scanning for the adapter
- void StopScanThread();
- /// Returns true if there is a device connected to port
- bool DeviceConnected(int port);
- /// Resets status of device connected to port
- void ResetDeviceType(int port);
- /// Returns true if we successfully gain access to GC Adapter
- bool CheckDeviceAccess(libusb_device* device);
- /// Captures GC Adapter endpoint address,
- void GetGCEndpoint(libusb_device* device);
- /// For shutting down, clear all data, join all threads, release usb
- void Reset();
- /// For use in initialization, querying devices to find the adapter
- void Setup();
- int current_status = NO_ADAPTER_DETECTED;
- libusb_device_handle* usb_adapter_handle = nullptr;
- std::array<ControllerTypes, 4> adapter_controllers_status{};
- std::mutex s_mutex;
- std::thread adapter_input_thread;
- bool adapter_thread_running;
- std::mutex initialization_mutex;
- std::thread detect_thread;
- bool detect_thread_running = false;
- libusb_context* libusb_ctx;
- u8 input_endpoint = 0;
- bool configuring = false;
- std::array<Common::SPSCQueue<GCPadStatus>, 4> pad_queue;
- std::array<GCState, 4> state;
- };
- } // namespace GCAdapter
|