Use hidapi for Wiimotes on Windows (#1033)

This commit is contained in:
capitalistspz 2023-12-06 01:33:29 +00:00 committed by GitHub
parent 09409a5108
commit 1849083073
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 4 additions and 175 deletions

View File

@ -89,10 +89,9 @@ if (WIN32)
option(ENABLE_XINPUT "Enables the usage of XInput" ON)
option(ENABLE_DIRECTINPUT "Enables the usage of DirectInput" ON)
add_compile_definitions(HAS_DIRECTINPUT)
set(ENABLE_WIIMOTE ON)
elseif (UNIX)
option(ENABLE_HIDAPI "Build with HIDAPI" ON)
endif()
option(ENABLE_HIDAPI "Build with HIDAPI" ON)
option(ENABLE_SDL "Enables the SDLController backend" ON)
# audio backends

View File

@ -70,18 +70,9 @@ if (ENABLE_WIIMOTE)
api/Wiimote/NativeWiimoteController.h
api/Wiimote/NativeWiimoteController.cpp
api/Wiimote/WiimoteDevice.h
)
if (ENABLE_HIDAPI)
target_sources(CemuInput PRIVATE
api/Wiimote/hidapi/HidapiWiimote.cpp
api/Wiimote/hidapi/HidapiWiimote.h
)
elseif (WIN32)
target_sources(CemuInput PRIVATE
api/Wiimote/windows/WinWiimoteDevice.cpp
api/Wiimote/windows/WinWiimoteDevice.h
)
endif()
)
endif ()

View File

@ -2,11 +2,7 @@
#include "input/api/Wiimote/NativeWiimoteController.h"
#include "input/api/Wiimote/WiimoteMessages.h"
#ifdef HAS_HIDAPI
#include "input/api/Wiimote/hidapi/HidapiWiimote.h"
#elif BOOST_OS_WINDOWS
#include "input/api/Wiimote/windows/WinWiimoteDevice.h"
#endif
#include <numbers>
#include <queue>

View File

@ -1,130 +0,0 @@
#include "input/api/Wiimote/windows/WinWiimoteDevice.h"
#include <hidsdi.h>
#include <SetupAPI.h>
#pragma comment(lib, "Setupapi.lib")
#pragma comment(lib, "hid.lib")
WinWiimoteDevice::WinWiimoteDevice(HANDLE handle, std::vector<uint8_t> identifier)
: m_handle(handle), m_identifier(std::move(identifier))
{
m_overlapped.hEvent = CreateEvent(nullptr, TRUE, TRUE, nullptr);
}
WinWiimoteDevice::~WinWiimoteDevice()
{
CancelIo(m_handle);
ResetEvent(m_overlapped.hEvent);
CloseHandle(m_handle);
}
bool WinWiimoteDevice::write_data(const std::vector<uint8>& data)
{
return HidD_SetOutputReport(m_handle, (void*)data.data(), (ULONG)data.size());
}
std::optional<std::vector<uint8_t>> WinWiimoteDevice::read_data()
{
DWORD read = 0;
std::array<uint8_t, 32> buffer{};
if (!ReadFile(m_handle, buffer.data(), (DWORD)buffer.size(), &read, &m_overlapped))
{
const auto error = GetLastError();
if (error == ERROR_DEVICE_NOT_CONNECTED)
return {};
else if (error == ERROR_IO_PENDING)
{
const auto wait_result = WaitForSingleObject(m_overlapped.hEvent, 100);
if (wait_result == WAIT_TIMEOUT)
{
CancelIo(m_handle);
ResetEvent(m_overlapped.hEvent);
return {};
}
else if (wait_result == WAIT_FAILED)
return {};
if (GetOverlappedResult(m_handle, &m_overlapped, &read, FALSE) == FALSE)
return {};
}
else if (error == ERROR_INVALID_HANDLE)
{
ResetEvent(m_overlapped.hEvent);
return {};
}
else
{
cemu_assert_debug(false);
}
}
ResetEvent(m_overlapped.hEvent);
if (read == 0)
return {};
return {{buffer.cbegin(), buffer.cbegin() + read}};
}
std::vector<WiimoteDevicePtr> WinWiimoteDevice::get_devices()
{
std::vector<WiimoteDevicePtr> result;
GUID hid_guid;
HidD_GetHidGuid(&hid_guid);
const auto device_info = SetupDiGetClassDevs(&hid_guid, nullptr, nullptr, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
for (DWORD index = 0; ; ++index)
{
SP_DEVICE_INTERFACE_DATA device_data{};
device_data.cbSize = sizeof(device_data);
if (SetupDiEnumDeviceInterfaces(device_info, nullptr, &hid_guid, index, &device_data) == FALSE)
break;
DWORD device_data_len;
if (SetupDiGetDeviceInterfaceDetail(device_info, &device_data, nullptr, 0, &device_data_len, nullptr) == FALSE
&& GetLastError() != ERROR_INSUFFICIENT_BUFFER)
continue;
std::vector<uint8_t> detail_data_buffer;
detail_data_buffer.resize(device_data_len);
const auto detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)detail_data_buffer.data();
detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, device_data_len, nullptr, nullptr)
== FALSE)
continue;
HANDLE device_handle = CreateFile(detail_data->DevicePath, (GENERIC_READ | GENERIC_WRITE),
(FILE_SHARE_READ | FILE_SHARE_WRITE), nullptr, OPEN_EXISTING,
FILE_FLAG_OVERLAPPED, nullptr);
if (device_handle == INVALID_HANDLE_VALUE)
continue;
HIDD_ATTRIBUTES attributes{};
attributes.Size = sizeof(attributes);
if (HidD_GetAttributes(device_handle, &attributes) == FALSE)
{
CloseHandle(device_handle);
continue;
}
if (attributes.VendorID != 0x057e || (attributes.ProductID != 0x0306 && attributes.ProductID != 0x0330))
{
CloseHandle(device_handle);
continue;
}
result.emplace_back(std::make_shared<WinWiimoteDevice>(device_handle, detail_data_buffer));
}
return result;
}
bool WinWiimoteDevice::operator==(WiimoteDevice& o) const
{
return m_identifier == static_cast<WinWiimoteDevice&>(o).m_identifier;
}

View File

@ -1,24 +0,0 @@
#pragma once
#include "input/api/Wiimote/WiimoteDevice.h"
class WinWiimoteDevice : public WiimoteDevice
{
public:
WinWiimoteDevice(HANDLE handle, std::vector<uint8_t> identifier);
~WinWiimoteDevice();
bool write_data(const std::vector<uint8>& data) override;
std::optional<std::vector<uint8_t>> read_data() override;
static std::vector<WiimoteDevicePtr> get_devices();
bool operator==(WiimoteDevice& o) const override;
private:
HANDLE m_handle;
OVERLAPPED m_overlapped{};
std::vector<uint8_t> m_identifier;
};
using WiimoteDevice_t = WinWiimoteDevice;

View File

@ -26,10 +26,7 @@
"boost-static-string",
"boost-random",
"fmt",
{
"name": "hidapi",
"platform": "!windows"
},
"hidapi",
"libpng",
"glm",
{