mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-22 00:59:18 +01:00
Linux/MacOS: Add wiimote support via HIDAPI (#934)
This commit is contained in:
parent
892ae13680
commit
85aa4f095b
@ -89,6 +89,9 @@ if (WIN32)
|
|||||||
option(ENABLE_XINPUT "Enables the usage of XInput" ON)
|
option(ENABLE_XINPUT "Enables the usage of XInput" ON)
|
||||||
option(ENABLE_DIRECTINPUT "Enables the usage of DirectInput" ON)
|
option(ENABLE_DIRECTINPUT "Enables the usage of DirectInput" ON)
|
||||||
add_compile_definitions(HAS_DIRECTINPUT)
|
add_compile_definitions(HAS_DIRECTINPUT)
|
||||||
|
set(ENABLE_WIIMOTE ON)
|
||||||
|
elseif (UNIX)
|
||||||
|
option(ENABLE_HIDAPI "Build with HIDAPI" ON)
|
||||||
endif()
|
endif()
|
||||||
option(ENABLE_SDL "Enables the SDLController backend" ON)
|
option(ENABLE_SDL "Enables the SDLController backend" ON)
|
||||||
|
|
||||||
@ -155,6 +158,12 @@ if (ENABLE_DISCORD_RPC)
|
|||||||
target_include_directories(discord-rpc INTERFACE ./dependencies/discord-rpc/include)
|
target_include_directories(discord-rpc INTERFACE ./dependencies/discord-rpc/include)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (ENABLE_HIDAPI)
|
||||||
|
find_package(hidapi REQUIRED)
|
||||||
|
set(ENABLE_WIIMOTE ON)
|
||||||
|
add_compile_definitions(HAS_HIDAPI)
|
||||||
|
endif ()
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
if(ENABLE_FERAL_GAMEMODE)
|
if(ENABLE_FERAL_GAMEMODE)
|
||||||
add_compile_definitions(ENABLE_FERAL_GAMEMODE)
|
add_compile_definitions(ENABLE_FERAL_GAMEMODE)
|
||||||
|
@ -44,18 +44,6 @@ add_library(CemuInput
|
|||||||
set_property(TARGET CemuInput PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
set_property(TARGET CemuInput PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
# Native wiimote (Win32 only for now)
|
|
||||||
target_sources(CemuInput PRIVATE
|
|
||||||
api/Wiimote/WiimoteControllerProvider.h
|
|
||||||
api/Wiimote/windows/WinWiimoteDevice.cpp
|
|
||||||
api/Wiimote/windows/WinWiimoteDevice.h
|
|
||||||
api/Wiimote/WiimoteControllerProvider.cpp
|
|
||||||
api/Wiimote/WiimoteMessages.h
|
|
||||||
api/Wiimote/NativeWiimoteController.h
|
|
||||||
api/Wiimote/NativeWiimoteController.cpp
|
|
||||||
api/Wiimote/WiimoteDevice.h
|
|
||||||
)
|
|
||||||
|
|
||||||
# XInput
|
# XInput
|
||||||
target_sources(CemuInput PRIVATE
|
target_sources(CemuInput PRIVATE
|
||||||
api/XInput/XInputControllerProvider.cpp
|
api/XInput/XInputControllerProvider.cpp
|
||||||
@ -73,6 +61,29 @@ if(WIN32)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (ENABLE_WIIMOTE)
|
||||||
|
target_sources(CemuInput PRIVATE
|
||||||
|
api/Wiimote/WiimoteControllerProvider.h
|
||||||
|
api/Wiimote/WiimoteControllerProvider.cpp
|
||||||
|
api/Wiimote/WiimoteMessages.h
|
||||||
|
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 ()
|
||||||
|
|
||||||
|
|
||||||
target_include_directories(CemuInput PUBLIC "../")
|
target_include_directories(CemuInput PUBLIC "../")
|
||||||
|
|
||||||
target_link_libraries(CemuInput PRIVATE
|
target_link_libraries(CemuInput PRIVATE
|
||||||
@ -87,6 +98,9 @@ target_link_libraries(CemuInput PRIVATE
|
|||||||
pugixml::pugixml
|
pugixml::pugixml
|
||||||
SDL2::SDL2
|
SDL2::SDL2
|
||||||
)
|
)
|
||||||
|
if (ENABLE_HIDAPI)
|
||||||
|
target_link_libraries(CemuInput PRIVATE hidapi::hidapi)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (ENABLE_WXWIDGETS)
|
if (ENABLE_WXWIDGETS)
|
||||||
target_link_libraries(CemuInput PRIVATE wx::base wx::core)
|
target_link_libraries(CemuInput PRIVATE wx::base wx::core)
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
#if BOOST_OS_WINDOWS
|
#if BOOST_OS_WINDOWS
|
||||||
#include "input/api/DirectInput/DirectInputControllerProvider.h"
|
#include "input/api/DirectInput/DirectInputControllerProvider.h"
|
||||||
#include "input/api/XInput/XInputControllerProvider.h"
|
#include "input/api/XInput/XInputControllerProvider.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAS_HIDAPI) || BOOST_OS_WINDOWS
|
||||||
#include "input/api/Wiimote/WiimoteControllerProvider.h"
|
#include "input/api/Wiimote/WiimoteControllerProvider.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
#include "input/api/Wiimote/NativeWiimoteController.h"
|
#include "input/api/Wiimote/NativeWiimoteController.h"
|
||||||
#include "input/api/Wiimote/WiimoteMessages.h"
|
#include "input/api/Wiimote/WiimoteMessages.h"
|
||||||
|
|
||||||
#if BOOST_OS_WINDOWS
|
#ifdef HAS_HIDAPI
|
||||||
|
#include "input/api/Wiimote/hidapi/HidapiWiimote.h"
|
||||||
|
#elif BOOST_OS_WINDOWS
|
||||||
#include "input/api/Wiimote/windows/WinWiimoteDevice.h"
|
#include "input/api/Wiimote/windows/WinWiimoteDevice.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -36,7 +38,7 @@ std::vector<std::shared_ptr<ControllerBase>> WiimoteControllerProvider::get_cont
|
|||||||
{
|
{
|
||||||
// only add unknown, connected devices to our list
|
// only add unknown, connected devices to our list
|
||||||
const bool is_new_device = std::none_of(m_wiimotes.cbegin(), m_wiimotes.cend(),
|
const bool is_new_device = std::none_of(m_wiimotes.cbegin(), m_wiimotes.cend(),
|
||||||
[&device](const auto& it) { return *it.device == *device; });
|
[device](const auto& it) { return *it.device == *device; });
|
||||||
if (is_new_device)
|
if (is_new_device)
|
||||||
{
|
{
|
||||||
m_wiimotes.push_back(std::make_unique<Wiimote>(device));
|
m_wiimotes.push_back(std::make_unique<Wiimote>(device));
|
||||||
@ -163,9 +165,7 @@ void WiimoteControllerProvider::reader_thread()
|
|||||||
{
|
{
|
||||||
case kStatus:
|
case kStatus:
|
||||||
{
|
{
|
||||||
#ifdef WIIMOTE_DEBUG
|
cemuLog_logDebug(LogType::Force,"WiimoteControllerProvider::read_thread: kStatus");
|
||||||
printf("WiimoteControllerProvider::read_thread: kStatus\n");
|
|
||||||
#endif
|
|
||||||
new_state.buttons = (*(uint16*)data) & (~0x60E0);
|
new_state.buttons = (*(uint16*)data) & (~0x60E0);
|
||||||
data += 2;
|
data += 2;
|
||||||
new_state.flags = *data;
|
new_state.flags = *data;
|
||||||
@ -183,9 +183,7 @@ void WiimoteControllerProvider::reader_thread()
|
|||||||
|
|
||||||
if (HAS_FLAG(new_state.flags, kExtensionConnected))
|
if (HAS_FLAG(new_state.flags, kExtensionConnected))
|
||||||
{
|
{
|
||||||
#ifdef WIIMOTE_DEBUG
|
cemuLog_logDebug(LogType::Force,"Extension flag is set");
|
||||||
printf("\tExtension flag is set\n");
|
|
||||||
#endif
|
|
||||||
if(new_state.m_extension.index() == 0)
|
if(new_state.m_extension.index() == 0)
|
||||||
request_extension(index);
|
request_extension(index);
|
||||||
}
|
}
|
||||||
@ -199,9 +197,7 @@ void WiimoteControllerProvider::reader_thread()
|
|||||||
break;
|
break;
|
||||||
case kRead:
|
case kRead:
|
||||||
{
|
{
|
||||||
#ifdef WIIMOTE_DEBUG
|
cemuLog_logDebug(LogType::Force,"WiimoteControllerProvider::read_thread: kRead");
|
||||||
printf("WiimoteControllerProvider::read_thread: kRead\n");
|
|
||||||
#endif
|
|
||||||
new_state.buttons = (*(uint16*)data) & (~0x60E0);
|
new_state.buttons = (*(uint16*)data) & (~0x60E0);
|
||||||
data += 2;
|
data += 2;
|
||||||
const uint8 error_flag = *data & 0xF, size = (*data >> 4) + 1;
|
const uint8 error_flag = *data & 0xF, size = (*data >> 4) + 1;
|
||||||
@ -209,10 +205,9 @@ void WiimoteControllerProvider::reader_thread()
|
|||||||
|
|
||||||
if (error_flag)
|
if (error_flag)
|
||||||
{
|
{
|
||||||
|
|
||||||
// 7 means that wiimote is already enabled or not available
|
// 7 means that wiimote is already enabled or not available
|
||||||
#ifdef WIIMOTE_DEBUG
|
cemuLog_logDebug(LogType::Force,"Received error on data read {:#x}", error_flag);
|
||||||
printf("Received error on data read 0x%x\n", error_flag);
|
|
||||||
#endif
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,9 +215,7 @@ void WiimoteControllerProvider::reader_thread()
|
|||||||
data += 2;
|
data += 2;
|
||||||
if (address == (kRegisterCalibration & 0xFFFF))
|
if (address == (kRegisterCalibration & 0xFFFF))
|
||||||
{
|
{
|
||||||
#ifdef WIIMOTE_DEBUG
|
cemuLog_logDebug(LogType::Force,"Calibration received");
|
||||||
printf("Calibration received\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cemu_assert(size == 8);
|
cemu_assert(size == 8);
|
||||||
|
|
||||||
@ -255,17 +248,10 @@ void WiimoteControllerProvider::reader_thread()
|
|||||||
{
|
{
|
||||||
if (size == 0xf)
|
if (size == 0xf)
|
||||||
{
|
{
|
||||||
#ifdef WIIMOTE_DEBUG
|
cemuLog_logDebug(LogType::Force,"Extension type received but no extension connected");
|
||||||
printf("Extension type received but no extension connected\n");
|
|
||||||
#endif
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef WIIMOTE_DEBUG
|
|
||||||
printf("Extension type received\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cemu_assert(size == 6);
|
cemu_assert(size == 6);
|
||||||
auto be_type = *(betype<uint64>*)data;
|
auto be_type = *(betype<uint64>*)data;
|
||||||
data += 6; // 48
|
data += 6; // 48
|
||||||
@ -274,42 +260,38 @@ void WiimoteControllerProvider::reader_thread()
|
|||||||
switch (be_type.value())
|
switch (be_type.value())
|
||||||
{
|
{
|
||||||
case kExtensionNunchuck:
|
case kExtensionNunchuck:
|
||||||
#ifdef WIIMOTE_DEBUG
|
cemuLog_logDebug(LogType::Force,"Extension Type Received: Nunchuck");
|
||||||
printf("\tNunchuck\n");
|
|
||||||
#endif
|
|
||||||
new_state.m_extension = NunchuckData{};
|
new_state.m_extension = NunchuckData{};
|
||||||
break;
|
break;
|
||||||
case kExtensionClassic:
|
case kExtensionClassic:
|
||||||
#ifdef WIIMOTE_DEBUG
|
cemuLog_logDebug(LogType::Force,"Extension Type Received: Classic");
|
||||||
printf("\tClassic\n");
|
|
||||||
#endif
|
|
||||||
new_state.m_extension = ClassicData{};
|
new_state.m_extension = ClassicData{};
|
||||||
break;
|
break;
|
||||||
case kExtensionClassicPro:
|
case kExtensionClassicPro:
|
||||||
break;
|
cemuLog_logDebug(LogType::Force,"Extension Type Received: Classic Pro");
|
||||||
|
break;
|
||||||
case kExtensionGuitar:
|
case kExtensionGuitar:
|
||||||
break;
|
cemuLog_logDebug(LogType::Force,"Extension Type Received: Guitar");
|
||||||
|
break;
|
||||||
case kExtensionDrums:
|
case kExtensionDrums:
|
||||||
break;
|
cemuLog_logDebug(LogType::Force,"Extension Type Received: Drums");
|
||||||
|
break;
|
||||||
case kExtensionBalanceBoard:
|
case kExtensionBalanceBoard:
|
||||||
break;
|
cemuLog_logDebug(LogType::Force,"Extension Type Received: Balance Board");
|
||||||
|
break;
|
||||||
case kExtensionMotionPlus:
|
case kExtensionMotionPlus:
|
||||||
//m_motion_plus = true;
|
cemuLog_logDebug(LogType::Force,"Extension Type Received: MotionPlus");
|
||||||
#ifdef WIIMOTE_DEBUG
|
|
||||||
printf("\tMotion plus detected\n");
|
|
||||||
#endif
|
|
||||||
set_motion_plus(index, true);
|
set_motion_plus(index, true);
|
||||||
new_state.m_motion_plus = MotionPlusData{};
|
new_state.m_motion_plus = MotionPlusData{};
|
||||||
break;
|
break;
|
||||||
case kExtensionPartialyInserted:
|
case kExtensionPartialyInserted:
|
||||||
#ifdef WIIMOTE_DEBUG
|
cemuLog_logDebug(LogType::Force,"Extension only partially inserted");
|
||||||
printf("\tExtension only partially inserted!\n");
|
|
||||||
#endif
|
|
||||||
new_state.m_extension = {};
|
new_state.m_extension = {};
|
||||||
request_status(index);
|
request_status(index);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
new_state.m_extension = {};
|
cemuLog_logDebug(LogType::Force,"Unknown extension: {:#x}", be_type.value());
|
||||||
|
new_state.m_extension = {};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,9 +301,7 @@ void WiimoteControllerProvider::reader_thread()
|
|||||||
else if (address == (kRegisterExtensionCalibration & 0xFFFF))
|
else if (address == (kRegisterExtensionCalibration & 0xFFFF))
|
||||||
{
|
{
|
||||||
cemu_assert(size == 0x10);
|
cemu_assert(size == 0x10);
|
||||||
#ifdef WIIMOTE_DEBUG
|
cemuLog_logDebug(LogType::Force,"Extension calibration received");
|
||||||
printf("Extension calibration received\n");
|
|
||||||
#endif
|
|
||||||
std::visit(
|
std::visit(
|
||||||
overloaded
|
overloaded
|
||||||
{
|
{
|
||||||
@ -337,9 +317,7 @@ void WiimoteControllerProvider::reader_thread()
|
|||||||
std::array<uint8, 14> zero{};
|
std::array<uint8, 14> zero{};
|
||||||
if (memcmp(zero.data(), data, zero.size()) == 0)
|
if (memcmp(zero.data(), data, zero.size()) == 0)
|
||||||
{
|
{
|
||||||
#ifdef WIIMOTE_DEBUG
|
cemuLog_logDebug(LogType::Force,"Extension calibration data is zero");
|
||||||
printf("\tExtension calibration data is zero!\n");
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,15 +350,23 @@ void WiimoteControllerProvider::reader_thread()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef WIIMOTE_DEBUG
|
cemuLog_logDebug(LogType::Force,"Unhandled read data received");
|
||||||
printf("Unhandled read data received\n");
|
continue;
|
||||||
#endif
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update_report = true;
|
update_report = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case kAcknowledge:
|
||||||
|
{
|
||||||
|
new_state.buttons = *(uint16*)data & (~0x60E0);
|
||||||
|
data += 2;
|
||||||
|
const auto report_id = *data++;
|
||||||
|
const auto error = *data++;
|
||||||
|
if (error)
|
||||||
|
cemuLog_logDebug(LogType::Force, "Error {:#x} from output report {:#x}", error, report_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case kDataCore:
|
case kDataCore:
|
||||||
{
|
{
|
||||||
// 30 BB BB
|
// 30 BB BB
|
||||||
@ -476,10 +462,7 @@ void WiimoteControllerProvider::reader_thread()
|
|||||||
orientation /= tmp;*/
|
orientation /= tmp;*/
|
||||||
|
|
||||||
mp.orientation = orientation;
|
mp.orientation = orientation;
|
||||||
#ifdef WIIMOTE_DEBUG
|
cemuLog_logDebug(LogType::Force,"MotionPlus: {:.2f}, {:.2f} {:.2f}", mp.orientation.x, mp.orientation.y, mp.orientation.z);
|
||||||
printf("\tmp: %.2lf %.2lf %.2lf\n", mp.orientation.x, mp.orientation.y,
|
|
||||||
mp.orientation.z);
|
|
||||||
#endif
|
|
||||||
},
|
},
|
||||||
[data](NunchuckData& nunchuck) mutable
|
[data](NunchuckData& nunchuck) mutable
|
||||||
{
|
{
|
||||||
@ -553,12 +536,11 @@ void WiimoteControllerProvider::reader_thread()
|
|||||||
zero3,
|
zero3,
|
||||||
zero4
|
zero4
|
||||||
);
|
);
|
||||||
#ifdef WIIMOTE_DEBUG
|
cemuLog_logDebug(LogType::Force,"Nunchuck: Z={}, C={} | {}, {} | {:.2f}, {:.2f}, {:.2f}",
|
||||||
printf("\tn: %d,%d | %lf - %lf | %.2lf %.2lf %.2lf\n", nunchuck.z, nunchuck.c,
|
nunchuck.z, nunchuck.c,
|
||||||
nunchuck.axis.x, nunchuck.axis.y,
|
nunchuck.axis.x, nunchuck.axis.y,
|
||||||
RadToDeg(nunchuck.acceleration.x), RadToDeg(nunchuck.acceleration.y),
|
RadToDeg(nunchuck.acceleration.x), RadToDeg(nunchuck.acceleration.y),
|
||||||
RadToDeg(nunchuck.acceleration.z));
|
RadToDeg(nunchuck.acceleration.z));
|
||||||
#endif
|
|
||||||
},
|
},
|
||||||
[data](ClassicData& classic) mutable
|
[data](ClassicData& classic) mutable
|
||||||
{
|
{
|
||||||
@ -592,11 +574,11 @@ void WiimoteControllerProvider::reader_thread()
|
|||||||
|
|
||||||
classic.trigger = classic.raw_trigger;
|
classic.trigger = classic.raw_trigger;
|
||||||
classic.trigger /= 31.0f;
|
classic.trigger /= 31.0f;
|
||||||
#ifdef WIIMOTE_DEBUG
|
cemuLog_logDebug(LogType::Force,"Classic Controller: Buttons={:b} | {}, {} | {}, {} | {}, {}",
|
||||||
printf("\tc: %d | %lf - %lf | %lf - %lf | %lf - %lf\n", classic.buttons,
|
classic.buttons, classic.left_axis.x, classic.left_axis.y,
|
||||||
classic.left_axis.x, classic.left_axis.y, classic.right_axis.x,
|
classic.right_axis.x, classic.right_axis.y, classic.trigger.x,
|
||||||
classic.right_axis.y, classic.trigger.x, classic.trigger.y);
|
classic.trigger.y);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}, new_state.m_extension);
|
}, new_state.m_extension);
|
||||||
|
|
||||||
@ -609,9 +591,7 @@ void WiimoteControllerProvider::reader_thread()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
#ifdef WIIMOTE_DEBUG
|
cemuLog_logDebug(LogType::Force,"unhandled input packet id {} for wiimote {}", id, index);
|
||||||
printf("unhandled input packet id %d for wiimote\n", data[0]);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update motion data
|
// update motion data
|
||||||
@ -694,7 +674,6 @@ void WiimoteControllerProvider::parse_acceleration(WiimoteState& wiimote_state,
|
|||||||
tmp -= calib.zero;
|
tmp -= calib.zero;
|
||||||
acceleration = (wiimote_state.m_acceleration / tmp);
|
acceleration = (wiimote_state.m_acceleration / tmp);
|
||||||
|
|
||||||
//printf("%d, %d, %d\n", (int)m_acceleration.x, (int)m_acceleration.y, (int)m_acceleration.z);
|
|
||||||
const float pi_2 = (float)std::numbers::pi / 2.0f;
|
const float pi_2 = (float)std::numbers::pi / 2.0f;
|
||||||
wiimote_state.m_roll = std::atan2(acceleration.z, acceleration.x) - pi_2;
|
wiimote_state.m_roll = std::atan2(acceleration.z, acceleration.x) - pi_2;
|
||||||
}
|
}
|
||||||
@ -713,7 +692,6 @@ void WiimoteControllerProvider::rotate_ir(WiimoteState& wiimote_state)
|
|||||||
i++;
|
i++;
|
||||||
if (!dot.visible)
|
if (!dot.visible)
|
||||||
continue;
|
continue;
|
||||||
//printf("%d:\t%.02lf | %.02lf\n", i, dot.pos.x, dot.pos.y);
|
|
||||||
// move to center, rotate and move back
|
// move to center, rotate and move back
|
||||||
dot.pos -= 0.5f;
|
dot.pos -= 0.5f;
|
||||||
dot.pos.x = (dot.pos.x * cos) + (dot.pos.y * (-sin));
|
dot.pos.x = (dot.pos.x * cos) + (dot.pos.y * (-sin));
|
||||||
@ -973,9 +951,7 @@ void WiimoteControllerProvider::update_report_type(size_t index)
|
|||||||
else
|
else
|
||||||
report_type = kDataCore;
|
report_type = kDataCore;
|
||||||
|
|
||||||
#ifdef WIIMOTE_DEBUG
|
cemuLog_logDebug(LogType::Force,"Setting report type to {}", report_type);
|
||||||
printf("Setting report type to %d\n", report_type);
|
|
||||||
#endif
|
|
||||||
send_packet(index, {kType, 0x04, report_type});
|
send_packet(index, {kType, 0x04, report_type});
|
||||||
|
|
||||||
state.ir_camera.mode = set_ir_camera(index, true);
|
state.ir_camera.mode = set_ir_camera(index, true);
|
||||||
|
@ -8,7 +8,7 @@ enum InputReportId : uint8
|
|||||||
|
|
||||||
kStatus = 0x20,
|
kStatus = 0x20,
|
||||||
kRead = 0x21,
|
kRead = 0x21,
|
||||||
kWrite = 0x22,
|
kAcknowledge = 0x22,
|
||||||
|
|
||||||
kDataCore = 0x30,
|
kDataCore = 0x30,
|
||||||
kDataCoreAcc = 0x31,
|
kDataCoreAcc = 0x31,
|
||||||
|
55
src/input/api/Wiimote/hidapi/HidapiWiimote.cpp
Normal file
55
src/input/api/Wiimote/hidapi/HidapiWiimote.cpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#include "HidapiWiimote.h"
|
||||||
|
|
||||||
|
static constexpr uint16 WIIMOTE_VENDOR_ID = 0x057e;
|
||||||
|
static constexpr uint16 WIIMOTE_PRODUCT_ID = 0x0306;
|
||||||
|
static constexpr uint16 WIIMOTE_MP_PRODUCT_ID = 0x0330;
|
||||||
|
static constexpr uint16 WIIMOTE_MAX_INPUT_REPORT_LENGTH = 22;
|
||||||
|
|
||||||
|
HidapiWiimote::HidapiWiimote(hid_device* dev, uint64_t identifier)
|
||||||
|
: m_handle(dev), m_identifier(identifier) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HidapiWiimote::write_data(const std::vector<uint8> &data) {
|
||||||
|
return hid_write(m_handle, data.data(), data.size()) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::vector<uint8>> HidapiWiimote::read_data() {
|
||||||
|
std::array<uint8, WIIMOTE_MAX_INPUT_REPORT_LENGTH> read_data{};
|
||||||
|
const auto result = hid_read(m_handle, read_data.data(), WIIMOTE_MAX_INPUT_REPORT_LENGTH);
|
||||||
|
if (result < 0)
|
||||||
|
return {};
|
||||||
|
return {{read_data.cbegin(), read_data.cbegin() + result}};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<WiimoteDevicePtr> HidapiWiimote::get_devices() {
|
||||||
|
std::vector<WiimoteDevicePtr> wiimote_devices;
|
||||||
|
hid_init();
|
||||||
|
const auto device_enumeration = hid_enumerate(WIIMOTE_VENDOR_ID, 0x0);
|
||||||
|
|
||||||
|
for (auto it = device_enumeration; it != nullptr; it = it->next){
|
||||||
|
if (it->product_id != WIIMOTE_PRODUCT_ID && it->product_id != WIIMOTE_MP_PRODUCT_ID)
|
||||||
|
continue;
|
||||||
|
auto dev = hid_open_path(it->path);
|
||||||
|
if (!dev){
|
||||||
|
cemuLog_logDebug(LogType::Force, "Unable to open Wiimote device at {}: {}", it->path, boost::nowide::narrow(hid_error(nullptr)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Enough to have a unique id for each device within a session
|
||||||
|
uint64_t id = (static_cast<uint64>(it->interface_number) << 32) |
|
||||||
|
(static_cast<uint64>(it->usage_page) << 16) |
|
||||||
|
(it->usage);
|
||||||
|
wiimote_devices.push_back(std::make_shared<HidapiWiimote>(dev, id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hid_free_enumeration(device_enumeration);
|
||||||
|
return wiimote_devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HidapiWiimote::operator==(WiimoteDevice& o) const {
|
||||||
|
return m_identifier == static_cast<HidapiWiimote&>(o).m_identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
HidapiWiimote::~HidapiWiimote() {
|
||||||
|
hid_close(m_handle);
|
||||||
|
}
|
23
src/input/api/Wiimote/hidapi/HidapiWiimote.h
Normal file
23
src/input/api/Wiimote/hidapi/HidapiWiimote.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <api/Wiimote/WiimoteDevice.h>
|
||||||
|
#include <hidapi.h>
|
||||||
|
|
||||||
|
class HidapiWiimote : public WiimoteDevice {
|
||||||
|
public:
|
||||||
|
HidapiWiimote(hid_device* dev, uint64_t identifier);
|
||||||
|
~HidapiWiimote() override;
|
||||||
|
|
||||||
|
bool write_data(const std::vector<uint8> &data) override;
|
||||||
|
std::optional<std::vector<uint8>> read_data() override;
|
||||||
|
bool operator==(WiimoteDevice& o) const override;
|
||||||
|
|
||||||
|
static std::vector<WiimoteDevicePtr> get_devices();
|
||||||
|
|
||||||
|
private:
|
||||||
|
hid_device* m_handle;
|
||||||
|
uint64_t m_identifier;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
using WiimoteDevice_t = HidapiWiimote;
|
@ -26,6 +26,10 @@
|
|||||||
"boost-static-string",
|
"boost-static-string",
|
||||||
"boost-random",
|
"boost-random",
|
||||||
"fmt",
|
"fmt",
|
||||||
|
{
|
||||||
|
"name": "hidapi",
|
||||||
|
"platform": "!windows"
|
||||||
|
},
|
||||||
"libpng",
|
"libpng",
|
||||||
"glm",
|
"glm",
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user