From 843b030eda4d42672e8aea2b5607f4ba3048bd36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 24 Jul 2016 17:20:40 +0200 Subject: [PATCH] WiimoteReal: Add a hidapi IO implementation Based on ca0c2efe7ab19c85449d52dd1bf4beec8603bbfe. Credits go to flacs. However, unlike the original commit, hidapi does not completely replace the current implementations, so we can still connect Wiimotes with 1+2 (without pairing). Also, it is only used on Linux and OS X for now. This removes the advantage of having only one implementation but there is no other choice: using hidapi on Windows is currently impossible because hid_write() is implemented in a way that won't work with Wiimotes. Additionally: * We now check for the device name in addition to the PID/VID so we can support the Balance Board and maybe third-party Wiimotes too. This doesn't achieve anything with the DolphinBar but it does with hidraw. * Added a check to not connect to the same device more than once. --- CMakeLists.txt | 27 +++ CMakeTests/FindHIDAPI.cmake | 9 + Data/51-usb-device.rules | 5 +- Externals/hidapi/libusb/CMakeLists.txt | 1 + Externals/hidapi/linux/CMakeLists.txt | 1 + Externals/hidapi/mac/CMakeLists.txt | 1 + Source/Core/Core/CMakeLists.txt | 3 + Source/Core/Core/HW/WiimoteReal/IOLinux.cpp | 2 +- Source/Core/Core/HW/WiimoteReal/IOWin.cpp | 2 +- Source/Core/Core/HW/WiimoteReal/IOdarwin.h | 11 -- Source/Core/Core/HW/WiimoteReal/IOdarwin.mm | 162 +----------------- .../Core/HW/WiimoteReal/IOdarwin_private.h | 34 +--- Source/Core/Core/HW/WiimoteReal/IOhidapi.cpp | 152 ++++++++++++++++ Source/Core/Core/HW/WiimoteReal/IOhidapi.h | 50 ++++++ .../Core/Core/HW/WiimoteReal/WiimoteReal.cpp | 5 +- Source/Core/Core/HW/WiimoteReal/WiimoteReal.h | 2 +- 16 files changed, 257 insertions(+), 210 deletions(-) create mode 100644 CMakeTests/FindHIDAPI.cmake create mode 100644 Externals/hidapi/libusb/CMakeLists.txt create mode 100644 Externals/hidapi/linux/CMakeLists.txt create mode 100644 Externals/hidapi/mac/CMakeLists.txt create mode 100644 Source/Core/Core/HW/WiimoteReal/IOhidapi.cpp create mode 100644 Source/Core/Core/HW/WiimoteReal/IOhidapi.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a7e53e624..93dc457fed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -835,6 +835,33 @@ else() endif() list(APPEND LIBS ${ICONV_LIBRARIES}) +if(NOT ANDROID) + include(FindHIDAPI OPTIONAL) + find_package(HIDAPI) + if(HIDAPI_FOUND) + message("Using shared ${HIDAPI_LIBRARIES} ${HIDAPI_VERSION}") + include_directories(${HIDAPI_INCLUDE_DIRS}) + list(APPEND LIBS ${HIDAPI_LIBRARIES}) + else() + include_directories(Externals/hidapi/hidapi) + if(APPLE) + message("Using static hidapi from Externals") + add_subdirectory(Externals/hidapi/mac) + list(APPEND LIBS hidapi) + elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + message("Using static hidapi-hidraw from Externals") + add_subdirectory(Externals/hidapi/linux) + list(APPEND LIBS hidapi-hidraw udev) + else() + message("Using static hidapi-libusb from Externals") + add_subdirectory(Externals/hidapi/libusb) + list(APPEND LIBS hidapi-libusb) + endif() + endif() + set(HIDAPI_FOUND 1) + add_definitions(-DHAVE_HIDAPI=1) +endif() + find_library(OPENSLES_LIBRARIES NAMES OpenSLES) find_path(OPENSLES_INCLUDE_DIR NAMES SLES/OpenSLES.h) diff --git a/CMakeTests/FindHIDAPI.cmake b/CMakeTests/FindHIDAPI.cmake new file mode 100644 index 0000000000..b75110ab12 --- /dev/null +++ b/CMakeTests/FindHIDAPI.cmake @@ -0,0 +1,9 @@ +find_path(HIDAPI_INCLUDE_DIR NAMES hidapi.h PATH_SUFFIXES hidapi) +find_library(HIDAPI_LIBRARY NAMES hidapi hidapi-hidraw hidapi-libusb) +set(HIDAPI_LIBRARIES ${HIDAPI_LIBRARY}) +set(HIDAPI_INCLUDE_DIRS ${HIDAPI_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(HIDAPI DEFAULT_MSG HIDAPI_LIBRARY HIDAPI_INCLUDE_DIR) + +mark_as_advanced(HIDAPI_INCLUDE_DIR HIDAPI_LIBRARY) diff --git a/Data/51-usb-device.rules b/Data/51-usb-device.rules index 96d8e6bf1d..09a32f9944 100644 --- a/Data/51-usb-device.rules +++ b/Data/51-usb-device.rules @@ -1,5 +1,6 @@ #GameCube Controller Adapter SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="0337", TAG+="uaccess" -#Mayflash DolphinBar -SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="0306", TAG+="uaccess" +#Wiimotes or DolphinBar +SUBSYSTEM=="hidraw*", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="0306", TAG+="uaccess" +SUBSYSTEM=="hidraw*", ATTRS{idVendor}=="057e", ATTRS{idProduct}=="0330", TAG+="uaccess" diff --git a/Externals/hidapi/libusb/CMakeLists.txt b/Externals/hidapi/libusb/CMakeLists.txt new file mode 100644 index 0000000000..5bb2c08688 --- /dev/null +++ b/Externals/hidapi/libusb/CMakeLists.txt @@ -0,0 +1 @@ +add_library(hidapi-libusb hid.c) diff --git a/Externals/hidapi/linux/CMakeLists.txt b/Externals/hidapi/linux/CMakeLists.txt new file mode 100644 index 0000000000..f7984bd755 --- /dev/null +++ b/Externals/hidapi/linux/CMakeLists.txt @@ -0,0 +1 @@ +add_library(hidapi-hidraw hid.c) diff --git a/Externals/hidapi/mac/CMakeLists.txt b/Externals/hidapi/mac/CMakeLists.txt new file mode 100644 index 0000000000..ccd2898ed4 --- /dev/null +++ b/Externals/hidapi/mac/CMakeLists.txt @@ -0,0 +1 @@ +add_library(hidapi hid.c) diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index ef5c3e9d1e..5250837e6f 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -263,6 +263,9 @@ elseif(UNIX) set(SRCS ${SRCS} HW/WiimoteReal/IOAndroid.cpp) endif() endif() +if(HIDAPI_FOUND) + set(SRCS ${SRCS} HW/WiimoteReal/IOhidapi.cpp) +endif(HIDAPI_FOUND) if(PORTAUDIO_FOUND) set(LIBS ${LIBS} portaudio) diff --git a/Source/Core/Core/HW/WiimoteReal/IOLinux.cpp b/Source/Core/Core/HW/WiimoteReal/IOLinux.cpp index 8a8c2eea2d..f27c5428fd 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOLinux.cpp +++ b/Source/Core/Core/HW/WiimoteReal/IOLinux.cpp @@ -90,7 +90,7 @@ void WiimoteScannerLinux::FindWiimotes(std::vector& found_wiimotes, Wi } NOTICE_LOG(WIIMOTE, "device name %s", name); - if (!IsValidBluetoothName(name)) + if (!IsValidDeviceName(name)) continue; char bdaddr_str[18] = {}; diff --git a/Source/Core/Core/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/HW/WiimoteReal/IOWin.cpp index b0e6e4d4ef..74fd866d63 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/HW/WiimoteReal/IOWin.cpp @@ -983,7 +983,7 @@ void ProcessWiimotes(bool new_scan, T& callback) DEBUG_LOG(WIIMOTE, "Authenticated %i connected %i remembered %i ", btdi.fAuthenticated, btdi.fConnected, btdi.fRemembered); - if (IsValidBluetoothName(UTF16ToUTF8(btdi.szName))) + if (IsValidDeviceName(UTF16ToUTF8(btdi.szName))) { callback(hRadio, radioInfo, btdi); } diff --git a/Source/Core/Core/HW/WiimoteReal/IOdarwin.h b/Source/Core/Core/HW/WiimoteReal/IOdarwin.h index bf88d5ea24..a0149d5212 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOdarwin.h +++ b/Source/Core/Core/HW/WiimoteReal/IOdarwin.h @@ -18,16 +18,6 @@ public: void FindWiimotes(std::vector&, Wiimote*&) override; void Update() override{}; // not needed }; - -class WiimoteScannerDarwinHID final : public WiimoteScannerBackend -{ -public: - WiimoteScannerDarwinHID() = default; - ~WiimoteScannerDarwinHID() override = default; - bool IsReady() const override; - void FindWiimotes(std::vector&, Wiimote*&) override; - void Update() override{}; // not needed -}; } #else @@ -35,6 +25,5 @@ public: namespace WiimoteReal { using WiimoteScannerDarwin = WiimoteScannerDummy; -using WiimoteScannerDarwinHID = WiimoteScannerDummy; } #endif diff --git a/Source/Core/Core/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/HW/WiimoteReal/IOdarwin.mm index 6b810227a0..fa607f88d9 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/HW/WiimoteReal/IOdarwin.mm @@ -66,7 +66,7 @@ void WiimoteScannerDarwin::FindWiimotes(std::vector& found_wiimotes, for (int i = 0; i < found_devices; i++) { IOBluetoothDevice* dev = [en nextObject]; - if (!IsValidBluetoothName([[dev name] UTF8String])) + if (!IsValidDeviceName([[dev name] UTF8String])) continue; Wiimote* wm = new WiimoteDarwin([dev retain]); @@ -92,55 +92,6 @@ bool WiimoteScannerDarwin::IsReady() const return true; } -void WiimoteScannerDarwinHID::FindWiimotes(std::vector& found_wiimotes, - Wiimote*& found_board) -{ - found_board = nullptr; - - IOHIDManagerRef hid = IOHIDManagerCreate(NULL, kIOHIDOptionsTypeNone); - bool hidFailed = CFGetTypeID(hid) != IOHIDManagerGetTypeID(); - if (hidFailed) - { - CFRelease(hid); - WARN_LOG(WIIMOTE, "No HID manager"); - return; - } - - NSArray* criteria = @[ - @{ @kIOHIDVendorIDKey : @0x057e, - @kIOHIDProductIDKey : @0x0306 }, - @{ @kIOHIDVendorIDKey : @0x057e, - @kIOHIDProductIDKey : @0x0330 }, - ]; - IOHIDManagerSetDeviceMatchingMultiple(hid, (CFArrayRef)criteria); - if (IOHIDManagerOpen(hid, kIOHIDOptionsTypeNone) != kIOReturnSuccess) - WARN_LOG(WIIMOTE, "Failed to open HID Manager"); - CFSetRef devices = IOHIDManagerCopyDevices(hid); - if (devices) - { - int found_devices = CFSetGetCount(devices); - if (found_devices) - { - NOTICE_LOG(WIIMOTE, "Found %i HID devices", found_devices); - - IOHIDDeviceRef values[found_devices]; - CFSetGetValues(devices, reinterpret_cast(&values)); - for (int i = 0; i < found_devices; i++) - { - Wiimote* wm = new WiimoteDarwinHid(values[i]); - found_wiimotes.push_back(wm); - } - } - } - CFRelease(hid); -} - -bool WiimoteScannerDarwinHID::IsReady() const -{ - // TODO: only return true when !hidFailed - return true; -} - WiimoteDarwin::WiimoteDarwin(IOBluetoothDevice* device) : m_btd(device) { m_inputlen = 0; @@ -296,117 +247,6 @@ void WiimoteDarwin::DisablePowerAssertionInternal() ERROR_LOG(WIIMOTE, "Could not release power management assertion: %08x", ret); } } - -WiimoteDarwinHid::WiimoteDarwinHid(IOHIDDeviceRef device) : m_device(device) -{ - CFRetain(m_device); - m_connected = false; - m_report_buffer = Report(MAX_PAYLOAD); -} - -WiimoteDarwinHid::~WiimoteDarwinHid() -{ - Shutdown(); - CFRelease(m_device); -} - -bool WiimoteDarwinHid::ConnectInternal() -{ - IOReturn ret = IOHIDDeviceOpen(m_device, kIOHIDOptionsTypeNone); - m_connected = ret == kIOReturnSuccess; - if (m_connected) - { - IOHIDDeviceScheduleWithRunLoop(m_device, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); - IOHIDDeviceRegisterInputReportCallback(m_device, m_report_buffer.data() + 1, MAX_PAYLOAD - 1, - &WiimoteDarwinHid::ReportCallback, this); - IOHIDDeviceRegisterRemovalCallback(m_device, &WiimoteDarwinHid::RemoveCallback, this); - NOTICE_LOG(WIIMOTE, "Connected to Wiimote %i", m_index + 1); - } - else - { - ERROR_LOG(WIIMOTE, "Could not open IOHID Wiimote: %08x", ret); - } - - return m_connected; -} - -void WiimoteDarwinHid::DisconnectInternal() -{ - IOHIDDeviceUnscheduleFromRunLoop(m_device, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); - IOWakeup(); - IOReturn ret = IOHIDDeviceClose(m_device, kIOHIDOptionsTypeNone); - if (ret != kIOReturnSuccess) - ERROR_LOG(WIIMOTE, "Error closing IOHID Wiimote: %08x", ret); - - if (!IsConnected()) - return; - - NOTICE_LOG(WIIMOTE, "Disconnecting Wiimote %i", m_index + 1); - - m_buffered_reports.Clear(); - - m_connected = false; -} - -bool WiimoteDarwinHid::IsConnected() const -{ - return m_connected; -} - -void WiimoteDarwinHid::IOWakeup() -{ - m_interrupted.store(true); - CFRunLoopStop(CFRunLoopGetCurrent()); -} - -int WiimoteDarwinHid::IORead(u8* buf) -{ - Report rpt; - m_interrupted.store(false); - while (m_buffered_reports.Empty() && !m_interrupted.load()) - CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); - - if (m_buffered_reports.Pop(rpt)) - { - memcpy(buf, rpt.data(), rpt.size()); - return rpt.size(); - } - return -1; -} - -int WiimoteDarwinHid::IOWrite(u8 const* buf, size_t len) -{ - IOReturn ret = IOHIDDeviceSetReport(m_device, kIOHIDReportTypeOutput, buf[1], buf + 1, len - 1); - if (ret != kIOReturnSuccess) - { - ERROR_LOG(WIIMOTE, "Error writing to Wiimote: %08x", ret); - return 0; - } - return len; -} - -void WiimoteDarwinHid::QueueBufferReport(int length) -{ - Report rpt(m_report_buffer); - rpt[0] = 0xa1; - rpt.resize(length + 1); - m_buffered_reports.Push(std::move(rpt)); -} - -void WiimoteDarwinHid::ReportCallback(void* context, IOReturn result, void*, IOHIDReportType type, - u32 report_id, u8* report, CFIndex report_length) -{ - WiimoteDarwinHid* wm = static_cast(context); - report[0] = report_id; - wm->QueueBufferReport(report_length); -} - -void WiimoteDarwinHid::RemoveCallback(void* context, IOReturn result, void*) -{ - WiimoteDarwinHid* wm = static_cast(context); - wm->DisconnectInternal(); -} - } // namespace @implementation SearchBT diff --git a/Source/Core/Core/HW/WiimoteReal/IOdarwin_private.h b/Source/Core/Core/HW/WiimoteReal/IOdarwin_private.h index 5ced0d708d..a49eb2befb 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOdarwin_private.h +++ b/Source/Core/Core/HW/WiimoteReal/IOdarwin_private.h @@ -4,8 +4,6 @@ #pragma once -#include "Core/HW/WiimoteReal/WiimoteReal.h" - // Work around an Apple bug: for some reason, IOBluetooth.h errors on // inclusion in Mavericks, but only in Objective-C++ C++11 mode. I filed // this as ; in the meantime... @@ -13,10 +11,11 @@ #undef NS_ENUM_AVAILABLE #define NS_ENUM_AVAILABLE(...) // end hack -#include -#include +#import #include +#include "Core/HW/WiimoteReal/WiimoteReal.h" + namespace WiimoteReal { class WiimoteDarwin final : public Wiimote @@ -47,31 +46,4 @@ private: CFRunLoopRef m_wiimote_thread_run_loop; IOPMAssertionID m_pm_assertion; }; - -class WiimoteDarwinHid final : public Wiimote -{ -public: - WiimoteDarwinHid(IOHIDDeviceRef device); - ~WiimoteDarwinHid() override; - -protected: - bool ConnectInternal() override; - void DisconnectInternal() override; - bool IsConnected() const override; - void IOWakeup() override; - int IORead(u8* buf) override; - int IOWrite(u8 const* buf, size_t len) override; - -private: - static void ReportCallback(void* context, IOReturn result, void* sender, IOHIDReportType type, - u32 reportID, u8* report, CFIndex reportLength); - static void RemoveCallback(void* context, IOReturn result, void* sender); - void QueueBufferReport(int length); - IOHIDDeviceRef m_device; - bool m_connected; - std::atomic m_interrupted; - Report m_report_buffer; - Common::FifoQueue m_buffered_reports; -}; - } // namespace WiimoteReal diff --git a/Source/Core/Core/HW/WiimoteReal/IOhidapi.cpp b/Source/Core/Core/HW/WiimoteReal/IOhidapi.cpp new file mode 100644 index 0000000000..6305f26088 --- /dev/null +++ b/Source/Core/Core/HW/WiimoteReal/IOhidapi.cpp @@ -0,0 +1,152 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include + +#include "Common/Assert.h" +#include "Common/Logging/Log.h" +#include "Common/StringUtil.h" +#include "Core/HW/WiimoteEmu/WiimoteHid.h" +#include "Core/HW/WiimoteReal/IOhidapi.h" + +// This is used to store connected Wiimotes' paths, so we don't connect +// more than once to the same device. +static std::unordered_set s_known_paths; + +static bool IsDeviceUsable(const std::string& device_path) +{ + hid_device* handle = hid_open_path(device_path.c_str()); + if (handle == nullptr) + { + ERROR_LOG(WIIMOTE, "Could not connect to Wiimote at \"%s\". " + "Do you have permission to access the device?", + device_path.c_str()); + return false; + } + // Some third-party adapters (DolphinBar) always expose all four Wiimotes as HIDs + // even when they are not connected, which causes an endless error loop when we try to use them. + // Try to write a report to the device to see if this Wiimote is really usable. + static const u8 report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REQUEST_STATUS, 0}; + const int result = hid_write(handle, report, sizeof(report)); + // The DolphinBar uses EPIPE to signal the absence of a Wiimote connected to this HID. + if (result == -1 && errno != EPIPE) + ERROR_LOG(WIIMOTE, "Couldn't write to Wiimote at \"%s\".", device_path.c_str()); + + hid_close(handle); + return result != -1; +} + +namespace WiimoteReal +{ +WiimoteScannerHidapi::WiimoteScannerHidapi() +{ + s_known_paths.clear(); + int ret = hid_init(); + _assert_msg_(WIIMOTE, ret == 0, "Couldn't initialise hidapi."); +} + +WiimoteScannerHidapi::~WiimoteScannerHidapi() +{ + if (hid_exit() == -1) + ERROR_LOG(WIIMOTE, "Failed to clean up hidapi."); +} + +bool WiimoteScannerHidapi::IsReady() const +{ + return true; +} + +void WiimoteScannerHidapi::FindWiimotes(std::vector& wiimotes, Wiimote*& board) +{ + hid_device_info* list = hid_enumerate(0x0, 0x0); + for (hid_device_info* device = list; device; device = device->next) + { + const std::string name = device->product_string ? UTF16ToUTF8(device->product_string) : ""; + const bool is_wiimote = + IsValidDeviceName(name) || (device->vendor_id == 0x057e && + (device->product_id == 0x0306 || device->product_id == 0x0330)); + if (!is_wiimote || s_known_paths.count(device->path) != 0 || !IsDeviceUsable(device->path)) + continue; + + const bool is_balance_board = IsBalanceBoardName(name); + NOTICE_LOG(WIIMOTE, "Found %s at %s: %ls %ls (%04hx:%04hx)", + is_balance_board ? "balance board" : "Wiimote", device->path, + device->manufacturer_string, device->product_string, device->vendor_id, + device->product_id); + + Wiimote* wiimote = new WiimoteHidapi(device->path); + if (is_balance_board) + board = wiimote; + else + wiimotes.push_back(wiimote); + } + hid_free_enumeration(list); +} + +WiimoteHidapi::WiimoteHidapi(const std::string& device_path) : m_device_path(device_path) +{ + s_known_paths.insert(m_device_path); +} + +WiimoteHidapi::~WiimoteHidapi() +{ + Shutdown(); + s_known_paths.erase(m_device_path); +} + +bool WiimoteHidapi::ConnectInternal() +{ + m_handle = hid_open_path(m_device_path.c_str()); + if (m_handle == nullptr) + { + ERROR_LOG(WIIMOTE, "Could not connect to Wiimote at \"%s\". " + "Do you have permission to access the device?", + m_device_path.c_str()); + s_known_paths.erase(m_device_path); + } + return m_handle != nullptr; +} + +void WiimoteHidapi::DisconnectInternal() +{ + hid_close(m_handle); + m_handle = nullptr; +} + +bool WiimoteHidapi::IsConnected() const +{ + return m_handle != nullptr; +} + +int WiimoteHidapi::IORead(u8* buf) +{ + int timeout = 200; // ms + int result = hid_read_timeout(m_handle, buf + 1, MAX_PAYLOAD - 1, timeout); + // TODO: If and once we use hidapi across plaforms, change our internal API to clean up this mess. + if (result == -1) + { + ERROR_LOG(WIIMOTE, "Failed to read from %s.", m_device_path.c_str()); + return 0; // error + } + if (result == 0) + { + return -1; // didn't read packet + } + buf[0] = WM_SET_REPORT | WM_BT_INPUT; + return result + 1; // number of bytes read +} + +int WiimoteHidapi::IOWrite(const u8* buf, size_t len) +{ + _dbg_assert_(WIIMOTE, buf[0] == (WM_SET_REPORT | WM_BT_OUTPUT)); + int result = hid_write(m_handle, buf + 1, len - 1); + if (result == -1) + { + ERROR_LOG(WIIMOTE, "Failed to write to %s.", m_device_path.c_str()); + return 0; + } + return (result == 0) ? 1 : result; +} +}; // WiimoteReal diff --git a/Source/Core/Core/HW/WiimoteReal/IOhidapi.h b/Source/Core/Core/HW/WiimoteReal/IOhidapi.h new file mode 100644 index 0000000000..5cacf06ccf --- /dev/null +++ b/Source/Core/Core/HW/WiimoteReal/IOhidapi.h @@ -0,0 +1,50 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#ifdef HAVE_HIDAPI +#include + +#include "Core/HW/WiimoteReal/WiimoteReal.h" + +namespace WiimoteReal +{ +class WiimoteHidapi final : public Wiimote +{ +public: + explicit WiimoteHidapi(const std::string& device_path); + ~WiimoteHidapi() override; + +protected: + bool ConnectInternal() override; + void DisconnectInternal() override; + bool IsConnected() const override; + void IOWakeup() override {} + int IORead(u8* buf) override; + int IOWrite(const u8* buf, size_t len) override; + +private: + std::string m_device_path; + hid_device* m_handle = nullptr; +}; + +class WiimoteScannerHidapi final : public WiimoteScannerBackend +{ +public: + WiimoteScannerHidapi(); + ~WiimoteScannerHidapi(); + bool IsReady() const override; + void FindWiimotes(std::vector&, Wiimote*&) override; + void Update() override{}; // not needed for hidapi +}; +} + +#else +#include "Core/HW/WiimoteReal/IODummy.h" +namespace WiimoteReal +{ +using WiimoteScannerHidapi = WiimoteScannerDummy; +} +#endif diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp index 7205156625..a1fe2bb9c5 100644 --- a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp @@ -21,6 +21,7 @@ #include "Core/HW/WiimoteReal/IOLinux.h" #include "Core/HW/WiimoteReal/IOWin.h" #include "Core/HW/WiimoteReal/IOdarwin.h" +#include "Core/HW/WiimoteReal/IOhidapi.h" #include "Core/Host.h" #include "InputCommon/InputConfig.h" @@ -616,7 +617,7 @@ void Initialize(::Wiimote::InitializeMode init_mode) g_wiimote_scanner.AddScannerBackend(std::make_unique()); g_wiimote_scanner.AddScannerBackend(std::make_unique()); g_wiimote_scanner.AddScannerBackend(std::make_unique()); - g_wiimote_scanner.AddScannerBackend(std::make_unique()); + g_wiimote_scanner.AddScannerBackend(std::make_unique()); g_wiimote_scanner.StartThread(); } @@ -810,7 +811,7 @@ void StateChange(EMUSTATE_CHANGE newState) // TODO: disable/enable auto reporting, maybe } -bool IsValidBluetoothName(const std::string& name) +bool IsValidDeviceName(const std::string& name) { return "Nintendo RVL-CNT-01" == name || "Nintendo RVL-CNT-01-TR" == name || IsBalanceBoardName(name); diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h index c9618731e7..54039ab2b2 100644 --- a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h @@ -160,7 +160,7 @@ void ConnectOnInput(int _WiimoteNumber); void StateChange(EMUSTATE_CHANGE newState); void ChangeWiimoteSource(unsigned int index, int source); -bool IsValidBluetoothName(const std::string& name); +bool IsValidDeviceName(const std::string& name); bool IsBalanceBoardName(const std::string& name); #ifdef ANDROID