diff options
Diffstat (limited to 'src/input_common/gcadapter/gc_adapter.h')
| -rw-r--r-- | src/input_common/gcadapter/gc_adapter.h | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/input_common/gcadapter/gc_adapter.h b/src/input_common/gcadapter/gc_adapter.h new file mode 100644 index 000000000..b1c2a1958 --- /dev/null +++ b/src/input_common/gcadapter/gc_adapter.h | |||
| @@ -0,0 +1,161 @@ | |||
| 1 | // Copyright 2014 Dolphin Emulator Project | ||
| 2 | // Licensed under GPLv2+ | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | #include <algorithm> | ||
| 7 | #include <functional> | ||
| 8 | #include <mutex> | ||
| 9 | #include <thread> | ||
| 10 | #include <unordered_map> | ||
| 11 | #include <libusb.h> | ||
| 12 | #include "common/common_types.h" | ||
| 13 | #include "common/threadsafe_queue.h" | ||
| 14 | |||
| 15 | namespace GCAdapter { | ||
| 16 | |||
| 17 | enum { | ||
| 18 | PAD_USE_ORIGIN = 0x0080, | ||
| 19 | PAD_GET_ORIGIN = 0x2000, | ||
| 20 | PAD_ERR_STATUS = 0x8000, | ||
| 21 | }; | ||
| 22 | |||
| 23 | enum class PadButton { | ||
| 24 | PAD_BUTTON_LEFT = 0x0001, | ||
| 25 | PAD_BUTTON_RIGHT = 0x0002, | ||
| 26 | PAD_BUTTON_DOWN = 0x0004, | ||
| 27 | PAD_BUTTON_UP = 0x0008, | ||
| 28 | PAD_TRIGGER_Z = 0x0010, | ||
| 29 | PAD_TRIGGER_R = 0x0020, | ||
| 30 | PAD_TRIGGER_L = 0x0040, | ||
| 31 | PAD_BUTTON_A = 0x0100, | ||
| 32 | PAD_BUTTON_B = 0x0200, | ||
| 33 | PAD_BUTTON_X = 0x0400, | ||
| 34 | PAD_BUTTON_Y = 0x0800, | ||
| 35 | PAD_BUTTON_START = 0x1000, | ||
| 36 | // Below is for compatibility with "AxisButton" type | ||
| 37 | PAD_STICK = 0x2000, | ||
| 38 | }; | ||
| 39 | |||
| 40 | extern const std::array<PadButton, 12> PadButtonArray; | ||
| 41 | |||
| 42 | enum class PadAxes : u8 { | ||
| 43 | StickX, | ||
| 44 | StickY, | ||
| 45 | SubstickX, | ||
| 46 | SubstickY, | ||
| 47 | TriggerLeft, | ||
| 48 | TriggerRight, | ||
| 49 | Undefined, | ||
| 50 | }; | ||
| 51 | |||
| 52 | struct GCPadStatus { | ||
| 53 | u16 button{}; // Or-ed PAD_BUTTON_* and PAD_TRIGGER_* bits | ||
| 54 | u8 stick_x{}; // 0 <= stick_x <= 255 | ||
| 55 | u8 stick_y{}; // 0 <= stick_y <= 255 | ||
| 56 | u8 substick_x{}; // 0 <= substick_x <= 255 | ||
| 57 | u8 substick_y{}; // 0 <= substick_y <= 255 | ||
| 58 | u8 trigger_left{}; // 0 <= trigger_left <= 255 | ||
| 59 | u8 trigger_right{}; // 0 <= trigger_right <= 255 | ||
| 60 | |||
| 61 | static constexpr u8 MAIN_STICK_CENTER_X = 0x80; | ||
| 62 | static constexpr u8 MAIN_STICK_CENTER_Y = 0x80; | ||
| 63 | static constexpr u8 MAIN_STICK_RADIUS = 0x7f; | ||
| 64 | static constexpr u8 C_STICK_CENTER_X = 0x80; | ||
| 65 | static constexpr u8 C_STICK_CENTER_Y = 0x80; | ||
| 66 | static constexpr u8 C_STICK_RADIUS = 0x7f; | ||
| 67 | static constexpr u8 THRESHOLD = 10; | ||
| 68 | |||
| 69 | // 256/4, at least a quarter press to count as a press. For polling mostly | ||
| 70 | static constexpr u8 TRIGGER_THRESHOLD = 64; | ||
| 71 | |||
| 72 | u8 port{}; | ||
| 73 | PadAxes axis{PadAxes::Undefined}; | ||
| 74 | u8 axis_value{255}; | ||
| 75 | }; | ||
| 76 | |||
| 77 | struct GCState { | ||
| 78 | std::unordered_map<int, bool> buttons; | ||
| 79 | std::unordered_map<int, u16> axes; | ||
| 80 | }; | ||
| 81 | |||
| 82 | enum class ControllerTypes { None, Wired, Wireless }; | ||
| 83 | |||
| 84 | enum { | ||
| 85 | NO_ADAPTER_DETECTED = 0, | ||
| 86 | ADAPTER_DETECTED = 1, | ||
| 87 | }; | ||
| 88 | |||
| 89 | class Adapter { | ||
| 90 | public: | ||
| 91 | /// Initialize the GC Adapter capture and read sequence | ||
| 92 | Adapter(); | ||
| 93 | |||
| 94 | /// Close the adapter read thread and release the adapter | ||
| 95 | ~Adapter(); | ||
| 96 | /// Used for polling | ||
| 97 | void BeginConfiguration(); | ||
| 98 | void EndConfiguration(); | ||
| 99 | |||
| 100 | std::array<Common::SPSCQueue<GCPadStatus>, 4>& GetPadQueue(); | ||
| 101 | const std::array<Common::SPSCQueue<GCPadStatus>, 4>& GetPadQueue() const; | ||
| 102 | |||
| 103 | std::array<GCState, 4>& GetPadState(); | ||
| 104 | const std::array<GCState, 4>& GetPadState() const; | ||
| 105 | |||
| 106 | private: | ||
| 107 | GCPadStatus GetPadStatus(int port, const std::array<u8, 37>& adapter_payload); | ||
| 108 | |||
| 109 | void PadToState(const GCPadStatus& pad, GCState& state); | ||
| 110 | |||
| 111 | void Read(); | ||
| 112 | void ScanThreadFunc(); | ||
| 113 | /// Begin scanning for the GC Adapter. | ||
| 114 | void StartScanThread(); | ||
| 115 | |||
| 116 | /// Stop scanning for the adapter | ||
| 117 | void StopScanThread(); | ||
| 118 | |||
| 119 | /// Returns true if there is a device connected to port | ||
| 120 | bool DeviceConnected(int port); | ||
| 121 | |||
| 122 | /// Resets status of device connected to port | ||
| 123 | void ResetDeviceType(int port); | ||
| 124 | |||
| 125 | /// Returns true if we successfully gain access to GC Adapter | ||
| 126 | bool CheckDeviceAccess(libusb_device* device); | ||
| 127 | |||
| 128 | /// Captures GC Adapter endpoint address, | ||
| 129 | void GetGCEndpoint(libusb_device* device); | ||
| 130 | |||
| 131 | /// For shutting down, clear all data, join all threads, release usb | ||
| 132 | void Reset(); | ||
| 133 | |||
| 134 | /// For use in initialization, querying devices to find the adapter | ||
| 135 | void Setup(); | ||
| 136 | |||
| 137 | int current_status = NO_ADAPTER_DETECTED; | ||
| 138 | libusb_device_handle* usb_adapter_handle = nullptr; | ||
| 139 | std::array<ControllerTypes, 4> adapter_controllers_status{}; | ||
| 140 | |||
| 141 | std::mutex s_mutex; | ||
| 142 | |||
| 143 | std::thread adapter_input_thread; | ||
| 144 | bool adapter_thread_running; | ||
| 145 | |||
| 146 | std::mutex initialization_mutex; | ||
| 147 | std::thread detect_thread; | ||
| 148 | bool detect_thread_running = false; | ||
| 149 | |||
| 150 | libusb_context* libusb_ctx; | ||
| 151 | |||
| 152 | u8 input_endpoint = 0; | ||
| 153 | u8 output_endpoint = 0; | ||
| 154 | |||
| 155 | bool configuring = false; | ||
| 156 | |||
| 157 | std::array<Common::SPSCQueue<GCPadStatus>, 4> pad_queue; | ||
| 158 | std::array<GCState, 4> state; | ||
| 159 | }; | ||
| 160 | |||
| 161 | } // namespace GCAdapter | ||