gc_adapter.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. // Copyright 2014 Dolphin Emulator Project
  2. // Licensed under GPLv2+
  3. // Refer to the license.txt file included.
  4. #include <chrono>
  5. #include <thread>
  6. #include "common/logging/log.h"
  7. #include "input_common/gcadapter/gc_adapter.h"
  8. namespace GCAdapter {
  9. Adapter::Adapter() {
  10. if (usb_adapter_handle != nullptr) {
  11. return;
  12. }
  13. LOG_INFO(Input, "GC Adapter Initialization started");
  14. current_status = NO_ADAPTER_DETECTED;
  15. libusb_init(&libusb_ctx);
  16. StartScanThread();
  17. }
  18. GCPadStatus Adapter::GetPadStatus(int port, const std::array<u8, 37>& adapter_payload) {
  19. GCPadStatus pad = {};
  20. bool get_origin = false;
  21. ControllerTypes type = ControllerTypes(adapter_payload[1 + (9 * port)] >> 4);
  22. if (type != ControllerTypes::None) {
  23. get_origin = true;
  24. }
  25. adapter_controllers_status[port] = type;
  26. constexpr std::array<PadButton, 8> b1_buttons{
  27. PadButton::PAD_BUTTON_A, PadButton::PAD_BUTTON_B, PadButton::PAD_BUTTON_X,
  28. PadButton::PAD_BUTTON_Y, PadButton::PAD_BUTTON_LEFT, PadButton::PAD_BUTTON_RIGHT,
  29. PadButton::PAD_BUTTON_DOWN, PadButton::PAD_BUTTON_UP};
  30. constexpr std::array<PadButton, 4> b2_buttons{
  31. PadButton::PAD_BUTTON_START, PadButton::PAD_TRIGGER_Z, PadButton::PAD_TRIGGER_R,
  32. PadButton::PAD_TRIGGER_L};
  33. if (adapter_controllers_status[port] != ControllerTypes::None) {
  34. const u8 b1 = adapter_payload[1 + (9 * port) + 1];
  35. const u8 b2 = adapter_payload[1 + (9 * port) + 2];
  36. for (std::size_t i = 0; i < b1_buttons.size(); ++i) {
  37. if (b1 & (1 << i)) {
  38. pad.button |= static_cast<u16>(b1_buttons[i]);
  39. }
  40. }
  41. for (std::size_t j = 0; j < b2_buttons.size(); ++j) {
  42. if (b2 & (1 << j)) {
  43. pad.button |= static_cast<u16>(b2_buttons[j]);
  44. }
  45. }
  46. if (get_origin) {
  47. pad.button |= PAD_GET_ORIGIN;
  48. }
  49. pad.stick_x = adapter_payload[1 + (9 * port) + 3];
  50. pad.stick_y = adapter_payload[1 + (9 * port) + 4];
  51. pad.substick_x = adapter_payload[1 + (9 * port) + 5];
  52. pad.substick_y = adapter_payload[1 + (9 * port) + 6];
  53. pad.trigger_left = adapter_payload[1 + (9 * port) + 7];
  54. pad.trigger_right = adapter_payload[1 + (9 * port) + 8];
  55. }
  56. return pad;
  57. }
  58. void Adapter::PadToState(const GCPadStatus& pad, GCState& state) {
  59. for (const auto& button : PadButtonArray) {
  60. const u16 button_value = static_cast<u16>(button);
  61. state.buttons.insert_or_assign(button_value, pad.button & button_value);
  62. }
  63. state.axes.insert_or_assign(static_cast<u8>(PadAxes::StickX), pad.stick_x);
  64. state.axes.insert_or_assign(static_cast<u8>(PadAxes::StickY), pad.stick_y);
  65. state.axes.insert_or_assign(static_cast<u8>(PadAxes::SubstickX), pad.substick_x);
  66. state.axes.insert_or_assign(static_cast<u8>(PadAxes::SubstickY), pad.substick_y);
  67. state.axes.insert_or_assign(static_cast<u8>(PadAxes::TriggerLeft), pad.trigger_left);
  68. state.axes.insert_or_assign(static_cast<u8>(PadAxes::TriggerRight), pad.trigger_right);
  69. }
  70. void Adapter::Read() {
  71. LOG_DEBUG(Input, "GC Adapter Read() thread started");
  72. int payload_size_in, payload_size_copy;
  73. std::array<u8, 37> adapter_payload;
  74. std::array<u8, 37> adapter_payload_copy;
  75. std::array<GCPadStatus, 4> pads;
  76. while (adapter_thread_running) {
  77. libusb_interrupt_transfer(usb_adapter_handle, input_endpoint, adapter_payload.data(),
  78. sizeof(adapter_payload), &payload_size_in, 16);
  79. payload_size_copy = 0;
  80. {
  81. std::lock_guard<std::mutex> lk(s_mutex);
  82. std::copy(std::begin(adapter_payload), std::end(adapter_payload),
  83. std::begin(adapter_payload_copy));
  84. payload_size_copy = payload_size_in;
  85. }
  86. if (payload_size_copy != sizeof(adapter_payload_copy) ||
  87. adapter_payload_copy[0] != LIBUSB_DT_HID) {
  88. LOG_ERROR(Input, "error reading payload (size: %d, type: %02x)", payload_size_copy,
  89. adapter_payload_copy[0]);
  90. adapter_thread_running = false; // error reading from adapter, stop reading.
  91. break;
  92. }
  93. for (std::size_t port = 0; port < pads.size(); ++port) {
  94. pads[port] = GetPadStatus(port, adapter_payload_copy);
  95. if (DeviceConnected(port) && configuring) {
  96. if (pads[port].button != PAD_GET_ORIGIN) {
  97. pad_queue[port].Push(pads[port]);
  98. }
  99. // Accounting for a threshold here because of some controller variance
  100. if (pads[port].stick_x > pads[port].MAIN_STICK_CENTER_X + pads[port].THRESHOLD ||
  101. pads[port].stick_x < pads[port].MAIN_STICK_CENTER_X - pads[port].THRESHOLD) {
  102. pads[port].axis = GCAdapter::PadAxes::StickX;
  103. pads[port].axis_value = pads[port].stick_x;
  104. pad_queue[port].Push(pads[port]);
  105. }
  106. if (pads[port].stick_y > pads[port].MAIN_STICK_CENTER_Y + pads[port].THRESHOLD ||
  107. pads[port].stick_y < pads[port].MAIN_STICK_CENTER_Y - pads[port].THRESHOLD) {
  108. pads[port].axis = GCAdapter::PadAxes::StickY;
  109. pads[port].axis_value = pads[port].stick_y;
  110. pad_queue[port].Push(pads[port]);
  111. }
  112. if (pads[port].substick_x > pads[port].C_STICK_CENTER_X + pads[port].THRESHOLD ||
  113. pads[port].substick_x < pads[port].C_STICK_CENTER_X - pads[port].THRESHOLD) {
  114. pads[port].axis = GCAdapter::PadAxes::SubstickX;
  115. pads[port].axis_value = pads[port].substick_x;
  116. pad_queue[port].Push(pads[port]);
  117. }
  118. if (pads[port].substick_y > pads[port].C_STICK_CENTER_Y + pads[port].THRESHOLD ||
  119. pads[port].substick_y < pads[port].C_STICK_CENTER_Y - pads[port].THRESHOLD) {
  120. pads[port].axis = GCAdapter::PadAxes::SubstickY;
  121. pads[port].axis_value = pads[port].substick_y;
  122. pad_queue[port].Push(pads[port]);
  123. }
  124. }
  125. PadToState(pads[port], state[port]);
  126. }
  127. std::this_thread::yield();
  128. }
  129. }
  130. void Adapter::ScanThreadFunc() {
  131. LOG_INFO(Input, "GC Adapter scanning thread started");
  132. while (detect_thread_running) {
  133. if (usb_adapter_handle == nullptr) {
  134. std::lock_guard<std::mutex> lk(initialization_mutex);
  135. Setup();
  136. }
  137. std::this_thread::sleep_for(std::chrono::milliseconds(500));
  138. }
  139. }
  140. void Adapter::StartScanThread() {
  141. if (detect_thread_running) {
  142. return;
  143. }
  144. if (!libusb_ctx) {
  145. return;
  146. }
  147. detect_thread_running = true;
  148. detect_thread = std::thread([=] { ScanThreadFunc(); });
  149. }
  150. void Adapter::StopScanThread() {
  151. detect_thread_running = false;
  152. detect_thread.join();
  153. }
  154. void Adapter::Setup() {
  155. // Reset the error status in case the adapter gets unplugged
  156. if (current_status < 0) {
  157. current_status = NO_ADAPTER_DETECTED;
  158. }
  159. adapter_controllers_status.fill(ControllerTypes::None);
  160. // pointer to list of connected usb devices
  161. libusb_device** devices;
  162. // populate the list of devices, get the count
  163. const std::size_t device_count = libusb_get_device_list(libusb_ctx, &devices);
  164. for (std::size_t index = 0; index < device_count; ++index) {
  165. if (CheckDeviceAccess(devices[index])) {
  166. // GC Adapter found and accessible, registering it
  167. GetGCEndpoint(devices[index]);
  168. break;
  169. }
  170. }
  171. }
  172. bool Adapter::CheckDeviceAccess(libusb_device* device) {
  173. libusb_device_descriptor desc;
  174. const int get_descriptor_error = libusb_get_device_descriptor(device, &desc);
  175. if (get_descriptor_error) {
  176. // could not acquire the descriptor, no point in trying to use it.
  177. LOG_ERROR(Input, "libusb_get_device_descriptor failed with error: %d",
  178. get_descriptor_error);
  179. return false;
  180. }
  181. if (desc.idVendor != 0x057e || desc.idProduct != 0x0337) {
  182. // This isn't the device we are looking for.
  183. return false;
  184. }
  185. const int open_error = libusb_open(device, &usb_adapter_handle);
  186. if (open_error == LIBUSB_ERROR_ACCESS) {
  187. LOG_ERROR(Input, "Yuzu can not gain access to this device: ID %04X:%04X.", desc.idVendor,
  188. desc.idProduct);
  189. return false;
  190. }
  191. if (open_error) {
  192. LOG_ERROR(Input, "libusb_open failed to open device with error = %d", open_error);
  193. return false;
  194. }
  195. int kernel_driver_error = libusb_kernel_driver_active(usb_adapter_handle, 0);
  196. if (kernel_driver_error == 1) {
  197. kernel_driver_error = libusb_detach_kernel_driver(usb_adapter_handle, 0);
  198. if (kernel_driver_error != 0 && kernel_driver_error != LIBUSB_ERROR_NOT_SUPPORTED) {
  199. LOG_ERROR(Input, "libusb_detach_kernel_driver failed with error = %d",
  200. kernel_driver_error);
  201. }
  202. }
  203. if (kernel_driver_error && kernel_driver_error != LIBUSB_ERROR_NOT_SUPPORTED) {
  204. libusb_close(usb_adapter_handle);
  205. usb_adapter_handle = nullptr;
  206. return false;
  207. }
  208. const int interface_claim_error = libusb_claim_interface(usb_adapter_handle, 0);
  209. if (interface_claim_error) {
  210. LOG_ERROR(Input, "libusb_claim_interface failed with error = %d", interface_claim_error);
  211. libusb_close(usb_adapter_handle);
  212. usb_adapter_handle = nullptr;
  213. return false;
  214. }
  215. return true;
  216. }
  217. void Adapter::GetGCEndpoint(libusb_device* device) {
  218. libusb_config_descriptor* config = nullptr;
  219. libusb_get_config_descriptor(device, 0, &config);
  220. for (u8 ic = 0; ic < config->bNumInterfaces; ic++) {
  221. const libusb_interface* interfaceContainer = &config->interface[ic];
  222. for (int i = 0; i < interfaceContainer->num_altsetting; i++) {
  223. const libusb_interface_descriptor* interface = &interfaceContainer->altsetting[i];
  224. for (u8 e = 0; e < interface->bNumEndpoints; e++) {
  225. const libusb_endpoint_descriptor* endpoint = &interface->endpoint[e];
  226. if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) {
  227. input_endpoint = endpoint->bEndpointAddress;
  228. }
  229. }
  230. }
  231. }
  232. adapter_thread_running = true;
  233. current_status = ADAPTER_DETECTED;
  234. adapter_input_thread = std::thread([=] { Read(); }); // Read input
  235. }
  236. Adapter::~Adapter() {
  237. StopScanThread();
  238. Reset();
  239. }
  240. void Adapter::Reset() {
  241. std::unique_lock<std::mutex> lock(initialization_mutex, std::defer_lock);
  242. if (!lock.try_lock()) {
  243. return;
  244. }
  245. if (current_status != ADAPTER_DETECTED) {
  246. return;
  247. }
  248. if (adapter_thread_running) {
  249. adapter_thread_running = false;
  250. }
  251. adapter_input_thread.join();
  252. adapter_controllers_status.fill(ControllerTypes::None);
  253. current_status = NO_ADAPTER_DETECTED;
  254. if (usb_adapter_handle) {
  255. libusb_release_interface(usb_adapter_handle, 1);
  256. libusb_close(usb_adapter_handle);
  257. usb_adapter_handle = nullptr;
  258. }
  259. if (libusb_ctx) {
  260. libusb_exit(libusb_ctx);
  261. }
  262. }
  263. bool Adapter::DeviceConnected(int port) {
  264. return adapter_controllers_status[port] != ControllerTypes::None;
  265. }
  266. void Adapter::ResetDeviceType(int port) {
  267. adapter_controllers_status[port] = ControllerTypes::None;
  268. }
  269. void Adapter::BeginConfiguration() {
  270. for (auto& pq : pad_queue) {
  271. pq.Clear();
  272. }
  273. configuring = true;
  274. }
  275. void Adapter::EndConfiguration() {
  276. for (auto& pq : pad_queue) {
  277. pq.Clear();
  278. }
  279. configuring = false;
  280. }
  281. std::array<Common::SPSCQueue<GCPadStatus>, 4>& Adapter::GetPadQueue() {
  282. return pad_queue;
  283. }
  284. const std::array<Common::SPSCQueue<GCPadStatus>, 4>& Adapter::GetPadQueue() const {
  285. return pad_queue;
  286. }
  287. std::array<GCState, 4>& Adapter::GetPadState() {
  288. return state;
  289. }
  290. const std::array<GCState, 4>& Adapter::GetPadState() const {
  291. return state;
  292. }
  293. } // namespace GCAdapter