gc_adapter.h 4.3 KB

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