gc_adapter.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  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. #ifdef _MSC_VER
  7. #pragma warning(push)
  8. #pragma warning(disable : 4200) // nonstandard extension used : zero-sized array in struct/union
  9. #endif
  10. #include <libusb.h>
  11. #ifdef _MSC_VER
  12. #pragma warning(pop)
  13. #endif
  14. #include "common/logging/log.h"
  15. #include "common/param_package.h"
  16. #include "input_common/gcadapter/gc_adapter.h"
  17. #include "input_common/settings.h"
  18. namespace GCAdapter {
  19. /// Used to loop through and assign button in poller
  20. constexpr std::array<PadButton, 12> PadButtonArray{
  21. PadButton::PAD_BUTTON_LEFT, PadButton::PAD_BUTTON_RIGHT, PadButton::PAD_BUTTON_DOWN,
  22. PadButton::PAD_BUTTON_UP, PadButton::PAD_TRIGGER_Z, PadButton::PAD_TRIGGER_R,
  23. PadButton::PAD_TRIGGER_L, PadButton::PAD_BUTTON_A, PadButton::PAD_BUTTON_B,
  24. PadButton::PAD_BUTTON_X, PadButton::PAD_BUTTON_Y, PadButton::PAD_BUTTON_START,
  25. };
  26. Adapter::Adapter() {
  27. if (usb_adapter_handle != nullptr) {
  28. return;
  29. }
  30. LOG_INFO(Input, "GC Adapter Initialization started");
  31. const int init_res = libusb_init(&libusb_ctx);
  32. if (init_res == LIBUSB_SUCCESS) {
  33. Setup();
  34. } else {
  35. LOG_ERROR(Input, "libusb could not be initialized. failed with error = {}", init_res);
  36. }
  37. }
  38. GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload) {
  39. GCPadStatus pad = {};
  40. const std::size_t offset = 1 + (9 * port);
  41. adapter_controllers_status[port] = static_cast<ControllerTypes>(adapter_payload[offset] >> 4);
  42. static constexpr std::array<PadButton, 8> b1_buttons{
  43. PadButton::PAD_BUTTON_A, PadButton::PAD_BUTTON_B, PadButton::PAD_BUTTON_X,
  44. PadButton::PAD_BUTTON_Y, PadButton::PAD_BUTTON_LEFT, PadButton::PAD_BUTTON_RIGHT,
  45. PadButton::PAD_BUTTON_DOWN, PadButton::PAD_BUTTON_UP,
  46. };
  47. static constexpr std::array<PadButton, 4> b2_buttons{
  48. PadButton::PAD_BUTTON_START,
  49. PadButton::PAD_TRIGGER_Z,
  50. PadButton::PAD_TRIGGER_R,
  51. PadButton::PAD_TRIGGER_L,
  52. };
  53. static constexpr std::array<PadAxes, 6> axes{
  54. PadAxes::StickX, PadAxes::StickY, PadAxes::SubstickX,
  55. PadAxes::SubstickY, PadAxes::TriggerLeft, PadAxes::TriggerRight,
  56. };
  57. if (adapter_controllers_status[port] == ControllerTypes::None && !get_origin[port]) {
  58. // Controller may have been disconnected, recalibrate if reconnected.
  59. get_origin[port] = true;
  60. }
  61. if (adapter_controllers_status[port] != ControllerTypes::None) {
  62. const u8 b1 = adapter_payload[offset + 1];
  63. const u8 b2 = adapter_payload[offset + 2];
  64. for (std::size_t i = 0; i < b1_buttons.size(); ++i) {
  65. if ((b1 & (1U << i)) != 0) {
  66. pad.button |= static_cast<u16>(b1_buttons[i]);
  67. }
  68. }
  69. for (std::size_t j = 0; j < b2_buttons.size(); ++j) {
  70. if ((b2 & (1U << j)) != 0) {
  71. pad.button |= static_cast<u16>(b2_buttons[j]);
  72. }
  73. }
  74. for (PadAxes axis : axes) {
  75. const std::size_t index = static_cast<std::size_t>(axis);
  76. pad.axis_values[index] = adapter_payload[offset + 3 + index];
  77. }
  78. if (get_origin[port]) {
  79. origin_status[port].axis_values = pad.axis_values;
  80. get_origin[port] = false;
  81. }
  82. }
  83. return pad;
  84. }
  85. void Adapter::PadToState(const GCPadStatus& pad, GCState& state) {
  86. for (const auto& button : PadButtonArray) {
  87. const u16 button_value = static_cast<u16>(button);
  88. state.buttons.insert_or_assign(button_value, pad.button & button_value);
  89. }
  90. for (size_t i = 0; i < pad.axis_values.size(); ++i) {
  91. state.axes.insert_or_assign(static_cast<u8>(i), pad.axis_values[i]);
  92. }
  93. }
  94. void Adapter::Read() {
  95. LOG_DEBUG(Input, "GC Adapter Read() thread started");
  96. int payload_size;
  97. std::array<u8, 37> adapter_payload;
  98. std::array<GCPadStatus, 4> pads;
  99. while (adapter_thread_running) {
  100. libusb_interrupt_transfer(usb_adapter_handle, input_endpoint, adapter_payload.data(),
  101. sizeof(adapter_payload), &payload_size, 16);
  102. if (payload_size != sizeof(adapter_payload) || adapter_payload[0] != LIBUSB_DT_HID) {
  103. LOG_ERROR(Input,
  104. "Error reading payload (size: {}, type: {:02x}) Is the adapter connected?",
  105. payload_size, adapter_payload[0]);
  106. adapter_thread_running = false; // error reading from adapter, stop reading.
  107. break;
  108. }
  109. for (std::size_t port = 0; port < pads.size(); ++port) {
  110. pads[port] = GetPadStatus(port, adapter_payload);
  111. if (DeviceConnected(port) && configuring) {
  112. if (pads[port].button != 0) {
  113. pad_queue[port].Push(pads[port]);
  114. }
  115. // Accounting for a threshold here to ensure an intentional press
  116. for (size_t i = 0; i < pads[port].axis_values.size(); ++i) {
  117. const u8 value = pads[port].axis_values[i];
  118. const u8 origin = origin_status[port].axis_values[i];
  119. if (value > origin + pads[port].THRESHOLD ||
  120. value < origin - pads[port].THRESHOLD) {
  121. pads[port].axis = static_cast<PadAxes>(i);
  122. pads[port].axis_value = pads[port].axis_values[i];
  123. pad_queue[port].Push(pads[port]);
  124. }
  125. }
  126. }
  127. PadToState(pads[port], state[port]);
  128. }
  129. std::this_thread::yield();
  130. }
  131. }
  132. void Adapter::Setup() {
  133. // Initialize all controllers as unplugged
  134. adapter_controllers_status.fill(ControllerTypes::None);
  135. // Initialize all ports to store axis origin values
  136. get_origin.fill(true);
  137. // pointer to list of connected usb devices
  138. libusb_device** devices{};
  139. // populate the list of devices, get the count
  140. const ssize_t device_count = libusb_get_device_list(libusb_ctx, &devices);
  141. if (device_count < 0) {
  142. LOG_ERROR(Input, "libusb_get_device_list failed with error: {}", device_count);
  143. return;
  144. }
  145. if (devices != nullptr) {
  146. for (std::size_t index = 0; index < static_cast<std::size_t>(device_count); ++index) {
  147. if (CheckDeviceAccess(devices[index])) {
  148. // GC Adapter found and accessible, registering it
  149. GetGCEndpoint(devices[index]);
  150. break;
  151. }
  152. }
  153. libusb_free_device_list(devices, 1);
  154. }
  155. }
  156. bool Adapter::CheckDeviceAccess(libusb_device* device) {
  157. libusb_device_descriptor desc;
  158. const int get_descriptor_error = libusb_get_device_descriptor(device, &desc);
  159. if (get_descriptor_error) {
  160. // could not acquire the descriptor, no point in trying to use it.
  161. LOG_ERROR(Input, "libusb_get_device_descriptor failed with error: {}",
  162. get_descriptor_error);
  163. return false;
  164. }
  165. if (desc.idVendor != 0x057e || desc.idProduct != 0x0337) {
  166. // This isn't the device we are looking for.
  167. return false;
  168. }
  169. const int open_error = libusb_open(device, &usb_adapter_handle);
  170. if (open_error == LIBUSB_ERROR_ACCESS) {
  171. LOG_ERROR(Input, "Yuzu can not gain access to this device: ID {:04X}:{:04X}.",
  172. desc.idVendor, desc.idProduct);
  173. return false;
  174. }
  175. if (open_error) {
  176. LOG_ERROR(Input, "libusb_open failed to open device with error = {}", open_error);
  177. return false;
  178. }
  179. int kernel_driver_error = libusb_kernel_driver_active(usb_adapter_handle, 0);
  180. if (kernel_driver_error == 1) {
  181. kernel_driver_error = libusb_detach_kernel_driver(usb_adapter_handle, 0);
  182. if (kernel_driver_error != 0 && kernel_driver_error != LIBUSB_ERROR_NOT_SUPPORTED) {
  183. LOG_ERROR(Input, "libusb_detach_kernel_driver failed with error = {}",
  184. kernel_driver_error);
  185. }
  186. }
  187. if (kernel_driver_error && kernel_driver_error != LIBUSB_ERROR_NOT_SUPPORTED) {
  188. libusb_close(usb_adapter_handle);
  189. usb_adapter_handle = nullptr;
  190. return false;
  191. }
  192. const int interface_claim_error = libusb_claim_interface(usb_adapter_handle, 0);
  193. if (interface_claim_error) {
  194. LOG_ERROR(Input, "libusb_claim_interface failed with error = {}", interface_claim_error);
  195. libusb_close(usb_adapter_handle);
  196. usb_adapter_handle = nullptr;
  197. return false;
  198. }
  199. return true;
  200. }
  201. void Adapter::GetGCEndpoint(libusb_device* device) {
  202. libusb_config_descriptor* config = nullptr;
  203. const int config_descriptor_return = libusb_get_config_descriptor(device, 0, &config);
  204. if (config_descriptor_return != LIBUSB_SUCCESS) {
  205. LOG_ERROR(Input, "libusb_get_config_descriptor failed with error = {}",
  206. config_descriptor_return);
  207. return;
  208. }
  209. for (u8 ic = 0; ic < config->bNumInterfaces; ic++) {
  210. const libusb_interface* interfaceContainer = &config->interface[ic];
  211. for (int i = 0; i < interfaceContainer->num_altsetting; i++) {
  212. const libusb_interface_descriptor* interface = &interfaceContainer->altsetting[i];
  213. for (u8 e = 0; e < interface->bNumEndpoints; e++) {
  214. const libusb_endpoint_descriptor* endpoint = &interface->endpoint[e];
  215. if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) {
  216. input_endpoint = endpoint->bEndpointAddress;
  217. } else {
  218. output_endpoint = endpoint->bEndpointAddress;
  219. }
  220. }
  221. }
  222. }
  223. // This transfer seems to be responsible for clearing the state of the adapter
  224. // Used to clear the "busy" state of when the device is unexpectedly unplugged
  225. unsigned char clear_payload = 0x13;
  226. libusb_interrupt_transfer(usb_adapter_handle, output_endpoint, &clear_payload,
  227. sizeof(clear_payload), nullptr, 16);
  228. adapter_thread_running = true;
  229. adapter_input_thread = std::thread(&Adapter::Read, this);
  230. }
  231. Adapter::~Adapter() {
  232. Reset();
  233. }
  234. void Adapter::Reset() {
  235. if (adapter_thread_running) {
  236. adapter_thread_running = false;
  237. }
  238. if (adapter_input_thread.joinable()) {
  239. adapter_input_thread.join();
  240. }
  241. adapter_controllers_status.fill(ControllerTypes::None);
  242. get_origin.fill(true);
  243. if (usb_adapter_handle) {
  244. libusb_release_interface(usb_adapter_handle, 1);
  245. libusb_close(usb_adapter_handle);
  246. usb_adapter_handle = nullptr;
  247. }
  248. if (libusb_ctx) {
  249. libusb_exit(libusb_ctx);
  250. }
  251. }
  252. std::vector<Common::ParamPackage> Adapter::GetInputDevices() const {
  253. std::vector<Common::ParamPackage> devices;
  254. for (std::size_t port = 0; port < state.size(); ++port) {
  255. if (!DeviceConnected(port)) {
  256. continue;
  257. }
  258. std::string name = fmt::format("Gamecube Controller {}", port);
  259. devices.emplace_back(Common::ParamPackage{
  260. {"class", "gcpad"},
  261. {"display", std::move(name)},
  262. {"port", std::to_string(port)},
  263. });
  264. }
  265. return devices;
  266. }
  267. InputCommon::ButtonMapping Adapter::GetButtonMappingForDevice(
  268. const Common::ParamPackage& params) const {
  269. // This list is missing ZL/ZR since those are not considered buttons.
  270. // We will add those afterwards
  271. // This list also excludes any button that can't be really mapped
  272. static constexpr std::array<std::pair<Settings::NativeButton::Values, PadButton>, 12>
  273. switch_to_gcadapter_button = {
  274. std::pair{Settings::NativeButton::A, PadButton::PAD_BUTTON_A},
  275. {Settings::NativeButton::B, PadButton::PAD_BUTTON_B},
  276. {Settings::NativeButton::X, PadButton::PAD_BUTTON_X},
  277. {Settings::NativeButton::Y, PadButton::PAD_BUTTON_Y},
  278. {Settings::NativeButton::Plus, PadButton::PAD_BUTTON_START},
  279. {Settings::NativeButton::DLeft, PadButton::PAD_BUTTON_LEFT},
  280. {Settings::NativeButton::DUp, PadButton::PAD_BUTTON_UP},
  281. {Settings::NativeButton::DRight, PadButton::PAD_BUTTON_RIGHT},
  282. {Settings::NativeButton::DDown, PadButton::PAD_BUTTON_DOWN},
  283. {Settings::NativeButton::SL, PadButton::PAD_TRIGGER_L},
  284. {Settings::NativeButton::SR, PadButton::PAD_TRIGGER_R},
  285. {Settings::NativeButton::R, PadButton::PAD_TRIGGER_Z},
  286. };
  287. if (!params.Has("port")) {
  288. return {};
  289. }
  290. InputCommon::ButtonMapping mapping{};
  291. for (const auto& [switch_button, gcadapter_button] : switch_to_gcadapter_button) {
  292. Common::ParamPackage button_params({{"engine", "gcpad"}});
  293. button_params.Set("port", params.Get("port", 0));
  294. button_params.Set("button", static_cast<int>(gcadapter_button));
  295. mapping.insert_or_assign(switch_button, std::move(button_params));
  296. }
  297. // Add the missing bindings for ZL/ZR
  298. static constexpr std::array<std::pair<Settings::NativeButton::Values, PadAxes>, 2>
  299. switch_to_gcadapter_axis = {
  300. std::pair{Settings::NativeButton::ZL, PadAxes::TriggerLeft},
  301. {Settings::NativeButton::ZR, PadAxes::TriggerRight},
  302. };
  303. for (const auto& [switch_button, gcadapter_axis] : switch_to_gcadapter_axis) {
  304. Common::ParamPackage button_params({{"engine", "gcpad"}});
  305. button_params.Set("port", params.Get("port", 0));
  306. button_params.Set("button", static_cast<int>(PadButton::PAD_STICK));
  307. button_params.Set("axis", static_cast<int>(gcadapter_axis));
  308. mapping.insert_or_assign(switch_button, std::move(button_params));
  309. }
  310. return mapping;
  311. }
  312. InputCommon::AnalogMapping Adapter::GetAnalogMappingForDevice(
  313. const Common::ParamPackage& params) const {
  314. if (!params.Has("port")) {
  315. return {};
  316. }
  317. InputCommon::AnalogMapping mapping = {};
  318. Common::ParamPackage left_analog_params;
  319. left_analog_params.Set("engine", "gcpad");
  320. left_analog_params.Set("port", params.Get("port", 0));
  321. left_analog_params.Set("axis_x", static_cast<int>(PadAxes::StickX));
  322. left_analog_params.Set("axis_y", static_cast<int>(PadAxes::StickY));
  323. mapping.insert_or_assign(Settings::NativeAnalog::LStick, std::move(left_analog_params));
  324. Common::ParamPackage right_analog_params;
  325. right_analog_params.Set("engine", "gcpad");
  326. right_analog_params.Set("port", params.Get("port", 0));
  327. right_analog_params.Set("axis_x", static_cast<int>(PadAxes::SubstickX));
  328. right_analog_params.Set("axis_y", static_cast<int>(PadAxes::SubstickY));
  329. mapping.insert_or_assign(Settings::NativeAnalog::RStick, std::move(right_analog_params));
  330. return mapping;
  331. }
  332. bool Adapter::DeviceConnected(std::size_t port) const {
  333. return adapter_controllers_status[port] != ControllerTypes::None;
  334. }
  335. void Adapter::ResetDeviceType(std::size_t port) {
  336. adapter_controllers_status[port] = ControllerTypes::None;
  337. }
  338. void Adapter::BeginConfiguration() {
  339. get_origin.fill(true);
  340. for (auto& pq : pad_queue) {
  341. pq.Clear();
  342. }
  343. configuring = true;
  344. }
  345. void Adapter::EndConfiguration() {
  346. for (auto& pq : pad_queue) {
  347. pq.Clear();
  348. }
  349. configuring = false;
  350. }
  351. std::array<Common::SPSCQueue<GCPadStatus>, 4>& Adapter::GetPadQueue() {
  352. return pad_queue;
  353. }
  354. const std::array<Common::SPSCQueue<GCPadStatus>, 4>& Adapter::GetPadQueue() const {
  355. return pad_queue;
  356. }
  357. std::array<GCState, 4>& Adapter::GetPadState() {
  358. return state;
  359. }
  360. const std::array<GCState, 4>& Adapter::GetPadState() const {
  361. return state;
  362. }
  363. int Adapter::GetOriginValue(int port, int axis) const {
  364. return origin_status[port].axis_values[axis];
  365. }
  366. } // namespace GCAdapter