gc_adapter.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. struct libusb_context;
  13. struct libusb_device;
  14. struct libusb_device_handle;
  15. namespace GCAdapter {
  16. enum class PadButton {
  17. PAD_BUTTON_LEFT = 0x0001,
  18. PAD_BUTTON_RIGHT = 0x0002,
  19. PAD_BUTTON_DOWN = 0x0004,
  20. PAD_BUTTON_UP = 0x0008,
  21. PAD_TRIGGER_Z = 0x0010,
  22. PAD_TRIGGER_R = 0x0020,
  23. PAD_TRIGGER_L = 0x0040,
  24. PAD_BUTTON_A = 0x0100,
  25. PAD_BUTTON_B = 0x0200,
  26. PAD_BUTTON_X = 0x0400,
  27. PAD_BUTTON_Y = 0x0800,
  28. PAD_BUTTON_START = 0x1000,
  29. // Below is for compatibility with "AxisButton" type
  30. PAD_STICK = 0x2000,
  31. };
  32. extern const std::array<PadButton, 12> PadButtonArray;
  33. enum class PadAxes : u8 {
  34. StickX,
  35. StickY,
  36. SubstickX,
  37. SubstickY,
  38. TriggerLeft,
  39. TriggerRight,
  40. Undefined,
  41. };
  42. struct GCPadStatus {
  43. u16 button{}; // Or-ed PAD_BUTTON_* and PAD_TRIGGER_* bits
  44. std::array<u8, 6> axis_values{}; // Triggers and sticks, following indices defined in PadAxes
  45. static constexpr u8 THRESHOLD = 50; // Threshold for axis press for polling
  46. u8 port{};
  47. PadAxes axis{PadAxes::Undefined};
  48. u8 axis_value{255};
  49. };
  50. struct GCState {
  51. std::unordered_map<int, bool> buttons;
  52. std::unordered_map<int, u16> axes;
  53. };
  54. enum class ControllerTypes { None, Wired, Wireless };
  55. class Adapter {
  56. public:
  57. /// Initialize the GC Adapter capture and read sequence
  58. Adapter();
  59. /// Close the adapter read thread and release the adapter
  60. ~Adapter();
  61. /// Used for polling
  62. void BeginConfiguration();
  63. void EndConfiguration();
  64. /// Returns true if there is a device connected to port
  65. bool DeviceConnected(std::size_t port) const;
  66. std::array<Common::SPSCQueue<GCPadStatus>, 4>& GetPadQueue();
  67. const std::array<Common::SPSCQueue<GCPadStatus>, 4>& GetPadQueue() const;
  68. std::array<GCState, 4>& GetPadState();
  69. const std::array<GCState, 4>& GetPadState() const;
  70. int GetOriginValue(int port, int axis) const;
  71. private:
  72. GCPadStatus GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload);
  73. void PadToState(const GCPadStatus& pad, GCState& state);
  74. void Read();
  75. /// Resets status of device connected to port
  76. void ResetDeviceType(std::size_t port);
  77. /// Returns true if we successfully gain access to GC Adapter
  78. bool CheckDeviceAccess(libusb_device* device);
  79. /// Captures GC Adapter endpoint address,
  80. void GetGCEndpoint(libusb_device* device);
  81. /// For shutting down, clear all data, join all threads, release usb
  82. void Reset();
  83. /// For use in initialization, querying devices to find the adapter
  84. void Setup();
  85. libusb_device_handle* usb_adapter_handle = nullptr;
  86. std::thread adapter_input_thread;
  87. bool adapter_thread_running;
  88. libusb_context* libusb_ctx;
  89. u8 input_endpoint = 0;
  90. u8 output_endpoint = 0;
  91. bool configuring = false;
  92. std::array<GCState, 4> state;
  93. std::array<bool, 4> get_origin;
  94. std::array<GCPadStatus, 4> origin_status;
  95. std::array<Common::SPSCQueue<GCPadStatus>, 4> pad_queue;
  96. std::array<ControllerTypes, 4> adapter_controllers_status{};
  97. };
  98. } // namespace GCAdapter