summaryrefslogtreecommitdiff
path: root/src/input_common/gcadapter/gc_adapter.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/gcadapter/gc_adapter.h')
-rw-r--r--src/input_common/gcadapter/gc_adapter.h167
1 files changed, 167 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..f1256c9da
--- /dev/null
+++ b/src/input_common/gcadapter/gc_adapter.h
@@ -0,0 +1,167 @@
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 "common/common_types.h"
12#include "common/threadsafe_queue.h"
13#include "input_common/main.h"
14
15struct libusb_context;
16struct libusb_device;
17struct libusb_device_handle;
18
19namespace GCAdapter {
20
21enum class PadButton {
22 Undefined = 0x0000,
23 ButtonLeft = 0x0001,
24 ButtonRight = 0x0002,
25 ButtonDown = 0x0004,
26 ButtonUp = 0x0008,
27 TriggerZ = 0x0010,
28 TriggerR = 0x0020,
29 TriggerL = 0x0040,
30 ButtonA = 0x0100,
31 ButtonB = 0x0200,
32 ButtonX = 0x0400,
33 ButtonY = 0x0800,
34 ButtonStart = 0x1000,
35 // Below is for compatibility with "AxisButton" type
36 Stick = 0x2000,
37};
38
39enum class PadAxes : u8 {
40 StickX,
41 StickY,
42 SubstickX,
43 SubstickY,
44 TriggerLeft,
45 TriggerRight,
46 Undefined,
47};
48
49enum class ControllerTypes {
50 None,
51 Wired,
52 Wireless,
53};
54
55struct GCPadStatus {
56 std::size_t port{};
57
58 PadButton button{PadButton::Undefined}; // Or-ed PAD_BUTTON_* and PAD_TRIGGER_* bits
59
60 PadAxes axis{PadAxes::Undefined};
61 s16 axis_value{};
62 u8 axis_threshold{50};
63};
64
65struct GCController {
66 ControllerTypes type{};
67 bool enable_vibration{};
68 u8 rumble_amplitude{};
69 u16 buttons{};
70 PadButton last_button{};
71 std::array<s16, 6> axis_values{};
72 std::array<u8, 6> axis_origin{};
73};
74
75class Adapter {
76public:
77 Adapter();
78 ~Adapter();
79
80 /// Request a vibration for a controller
81 bool RumblePlay(std::size_t port, u8 amplitude);
82
83 /// Used for polling
84 void BeginConfiguration();
85 void EndConfiguration();
86
87 Common::SPSCQueue<GCPadStatus>& GetPadQueue();
88 const Common::SPSCQueue<GCPadStatus>& GetPadQueue() const;
89
90 GCController& GetPadState(std::size_t port);
91 const GCController& GetPadState(std::size_t port) const;
92
93 /// Returns true if there is a device connected to port
94 bool DeviceConnected(std::size_t port) const;
95
96 /// Used for automapping features
97 std::vector<Common::ParamPackage> GetInputDevices() const;
98 InputCommon::ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) const;
99 InputCommon::AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) const;
100
101private:
102 using AdapterPayload = std::array<u8, 37>;
103
104 void UpdatePadType(std::size_t port, ControllerTypes pad_type);
105 void UpdateControllers(const AdapterPayload& adapter_payload);
106 void UpdateYuzuSettings(std::size_t port);
107 void UpdateStateButtons(std::size_t port, u8 b1, u8 b2);
108 void UpdateStateAxes(std::size_t port, const AdapterPayload& adapter_payload);
109 void UpdateVibrations();
110
111 void AdapterInputThread();
112
113 void AdapterScanThread();
114
115 bool IsPayloadCorrect(const AdapterPayload& adapter_payload, s32 payload_size);
116
117 // Updates vibration state of all controllers
118 void SendVibrations();
119
120 /// For use in initialization, querying devices to find the adapter
121 void Setup();
122
123 /// Resets status of all GC controller devices to a disconected state
124 void ResetDevices();
125
126 /// Resets status of device connected to a disconected state
127 void ResetDevice(std::size_t port);
128
129 /// Returns true if we successfully gain access to GC Adapter
130 bool CheckDeviceAccess();
131
132 /// Captures GC Adapter endpoint address
133 /// Returns true if the endpoind was set correctly
134 bool GetGCEndpoint(libusb_device* device);
135
136 /// For shutting down, clear all data, join all threads, release usb
137 void Reset();
138
139 // Join all threads
140 void JoinThreads();
141
142 // Release usb handles
143 void ClearLibusbHandle();
144
145 libusb_device_handle* usb_adapter_handle = nullptr;
146 std::array<GCController, 4> pads;
147 Common::SPSCQueue<GCPadStatus> pad_queue;
148
149 std::thread adapter_input_thread;
150 std::thread adapter_scan_thread;
151 bool adapter_input_thread_running;
152 bool adapter_scan_thread_running;
153 bool restart_scan_thread;
154
155 libusb_context* libusb_ctx;
156
157 u8 input_endpoint{0};
158 u8 output_endpoint{0};
159 u8 input_error_counter{0};
160 u8 output_error_counter{0};
161 int vibration_counter{0};
162
163 bool configuring{false};
164 bool rumble_enabled{true};
165 bool vibration_changed{true};
166};
167} // namespace GCAdapter