gc_adapter.h 4.5 KB

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