2019-10-31 18:00:42 +00:00
|
|
|
#include "SwitchHDLHandler.h"
|
2019-11-08 18:06:02 +00:00
|
|
|
#include "ControllerHelpers.h"
|
2019-10-31 18:00:42 +00:00
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
SwitchHDLHandler::SwitchHDLHandler(std::unique_ptr<IController> &&controller)
|
|
|
|
: SwitchVirtualGamepadHandler(std::move(controller))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
SwitchHDLHandler::~SwitchHDLHandler()
|
|
|
|
{
|
|
|
|
Exit();
|
|
|
|
}
|
|
|
|
|
|
|
|
Result SwitchHDLHandler::Initialize()
|
|
|
|
{
|
|
|
|
Result rc = m_controllerHandler.Initialize();
|
|
|
|
if (R_FAILED(rc))
|
|
|
|
return rc;
|
|
|
|
|
2019-11-09 20:22:41 +00:00
|
|
|
if (DoesControllerSupport(GetController()->GetType(), SUPPORTS_NOTHING))
|
|
|
|
return rc;
|
|
|
|
|
2019-10-31 18:00:42 +00:00
|
|
|
rc = InitHdlState();
|
|
|
|
if (R_FAILED(rc))
|
|
|
|
return rc;
|
|
|
|
|
2019-11-08 23:31:49 +00:00
|
|
|
if (DoesControllerSupport(GetController()->GetType(), SUPPORTS_PAIRING))
|
2019-11-08 18:06:02 +00:00
|
|
|
{
|
|
|
|
rc = InitOutputThread();
|
|
|
|
if (R_FAILED(rc))
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2019-11-06 12:28:56 +00:00
|
|
|
rc = InitInputThread();
|
|
|
|
if (R_FAILED(rc))
|
|
|
|
return rc;
|
2019-11-02 17:42:24 +00:00
|
|
|
|
2019-10-31 18:00:42 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SwitchHDLHandler::Exit()
|
|
|
|
{
|
|
|
|
m_controllerHandler.Exit();
|
2019-11-09 20:22:41 +00:00
|
|
|
|
|
|
|
if (DoesControllerSupport(GetController()->GetType(), SUPPORTS_NOTHING))
|
|
|
|
return;
|
|
|
|
|
2019-10-31 18:00:42 +00:00
|
|
|
ExitInputThread();
|
|
|
|
ExitOutputThread();
|
|
|
|
ExitHdlState();
|
|
|
|
}
|
|
|
|
|
|
|
|
Result SwitchHDLHandler::InitHdlState()
|
|
|
|
{
|
|
|
|
m_hdlHandle = 0;
|
|
|
|
m_deviceInfo = {0};
|
|
|
|
m_hdlState = {0};
|
|
|
|
|
|
|
|
// Set the controller type to Pro-Controller, and set the npadInterfaceType.
|
2019-11-02 17:42:24 +00:00
|
|
|
m_deviceInfo.deviceType = HidDeviceType_FullKey15;
|
2019-10-31 18:00:42 +00:00
|
|
|
m_deviceInfo.npadInterfaceType = NpadInterfaceType_USB;
|
|
|
|
// Set the controller colors. The grip colors are for Pro-Controller on [9.0.0+].
|
2019-11-13 20:49:15 +00:00
|
|
|
ControllerConfig *config = GetController()->GetConfig();
|
|
|
|
m_deviceInfo.singleColorBody = config->bodyColor.rgbaValue;
|
|
|
|
m_deviceInfo.singleColorButtons = config->buttonsColor.rgbaValue;
|
|
|
|
m_deviceInfo.colorLeftGrip = config->leftGripColor.rgbaValue;
|
|
|
|
m_deviceInfo.colorRightGrip = config->rightGripColor.rgbaValue;
|
2019-10-31 18:00:42 +00:00
|
|
|
|
|
|
|
m_hdlState.batteryCharge = 4; // Set battery charge to full.
|
|
|
|
m_hdlState.joysticks[JOYSTICK_LEFT].dx = 0x1234;
|
|
|
|
m_hdlState.joysticks[JOYSTICK_LEFT].dy = -0x1234;
|
|
|
|
m_hdlState.joysticks[JOYSTICK_RIGHT].dx = 0x5678;
|
|
|
|
m_hdlState.joysticks[JOYSTICK_RIGHT].dy = -0x5678;
|
|
|
|
|
2019-11-08 23:31:49 +00:00
|
|
|
if (GetController()->IsControllerActive())
|
|
|
|
return hiddbgAttachHdlsVirtualDevice(&m_hdlHandle, &m_deviceInfo);
|
|
|
|
|
|
|
|
return 0;
|
2019-10-31 18:00:42 +00:00
|
|
|
}
|
|
|
|
Result SwitchHDLHandler::ExitHdlState()
|
|
|
|
{
|
|
|
|
return hiddbgDetachHdlsVirtualDevice(m_hdlHandle);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Sets the state of the class's HDL controller to the state stored in class's hdl.state
|
|
|
|
Result SwitchHDLHandler::UpdateHdlState()
|
|
|
|
{
|
|
|
|
//Checks if the virtual device was erased, in which case re-attach the device
|
2019-11-07 17:46:47 +00:00
|
|
|
bool isAttached;
|
2019-11-06 12:28:56 +00:00
|
|
|
|
2019-11-07 17:46:47 +00:00
|
|
|
if (R_SUCCEEDED(hiddbgIsHdlsVirtualDeviceAttached(m_hdlHandle, &isAttached)))
|
2019-10-31 18:00:42 +00:00
|
|
|
{
|
2019-11-07 17:46:47 +00:00
|
|
|
if (!isAttached)
|
2019-11-06 12:28:56 +00:00
|
|
|
hiddbgAttachHdlsVirtualDevice(&m_hdlHandle, &m_deviceInfo);
|
2019-10-31 18:00:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return hiddbgSetHdlsState(m_hdlHandle, &m_hdlState);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SwitchHDLHandler::FillHdlState(const NormalizedButtonData &data)
|
|
|
|
{
|
|
|
|
m_hdlState.buttons = 0;
|
|
|
|
|
2019-11-07 17:46:47 +00:00
|
|
|
m_hdlState.buttons |= (data.buttons[0] ? KEY_X : 0);
|
|
|
|
m_hdlState.buttons |= (data.buttons[1] ? KEY_A : 0);
|
|
|
|
m_hdlState.buttons |= (data.buttons[2] ? KEY_B : 0);
|
|
|
|
m_hdlState.buttons |= (data.buttons[3] ? KEY_Y : 0);
|
2019-10-31 18:00:42 +00:00
|
|
|
|
2019-11-07 17:46:47 +00:00
|
|
|
m_hdlState.buttons |= (data.buttons[4] ? KEY_LSTICK : 0);
|
|
|
|
m_hdlState.buttons |= (data.buttons[5] ? KEY_RSTICK : 0);
|
2019-10-31 18:00:42 +00:00
|
|
|
|
2019-11-07 17:46:47 +00:00
|
|
|
m_hdlState.buttons |= (data.buttons[6] ? KEY_L : 0);
|
|
|
|
m_hdlState.buttons |= (data.buttons[7] ? KEY_R : 0);
|
2019-10-31 18:00:42 +00:00
|
|
|
|
2019-11-07 17:46:47 +00:00
|
|
|
m_hdlState.buttons |= (data.buttons[8] ? KEY_ZL : 0);
|
|
|
|
m_hdlState.buttons |= (data.buttons[9] ? KEY_ZR : 0);
|
2019-10-31 18:00:42 +00:00
|
|
|
|
2019-11-07 17:46:47 +00:00
|
|
|
m_hdlState.buttons |= (data.buttons[10] ? KEY_MINUS : 0);
|
|
|
|
m_hdlState.buttons |= (data.buttons[11] ? KEY_PLUS : 0);
|
2019-10-31 18:00:42 +00:00
|
|
|
|
2019-11-09 20:36:52 +00:00
|
|
|
ControllerConfig *config = GetController()->GetConfig();
|
2019-10-31 18:00:42 +00:00
|
|
|
|
2019-11-09 20:36:52 +00:00
|
|
|
if (config && config->swapDPADandLSTICK)
|
|
|
|
{
|
|
|
|
m_hdlState.buttons |= ((data.sticks[0].axis_y > 0.5f) ? KEY_DUP : 0);
|
|
|
|
m_hdlState.buttons |= ((data.sticks[0].axis_x > 0.5f) ? KEY_DRIGHT : 0);
|
|
|
|
m_hdlState.buttons |= ((data.sticks[0].axis_y < -0.5f) ? KEY_DDOWN : 0);
|
|
|
|
m_hdlState.buttons |= ((data.sticks[0].axis_x < -0.5f) ? KEY_DLEFT : 0);
|
|
|
|
|
|
|
|
float daxis_x{}, daxis_y{};
|
|
|
|
|
|
|
|
daxis_y += data.buttons[12] ? 1.0f : 0.0f; //DUP
|
|
|
|
daxis_x += data.buttons[13] ? 1.0f : 0.0f; //DRIGHT
|
|
|
|
daxis_y += data.buttons[14] ? -1.0f : 0.0f; //DDOWN
|
|
|
|
daxis_x += data.buttons[15] ? -1.0f : 0.0f; //DLEFT
|
|
|
|
|
|
|
|
m_controllerHandler.ConvertAxisToSwitchAxis(daxis_x, daxis_y, 0, &m_hdlState.joysticks[JOYSTICK_LEFT].dx, &m_hdlState.joysticks[JOYSTICK_LEFT].dy);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_hdlState.buttons |= (data.buttons[12] ? KEY_DUP : 0);
|
|
|
|
m_hdlState.buttons |= (data.buttons[13] ? KEY_DRIGHT : 0);
|
|
|
|
m_hdlState.buttons |= (data.buttons[14] ? KEY_DDOWN : 0);
|
|
|
|
m_hdlState.buttons |= (data.buttons[15] ? KEY_DLEFT : 0);
|
|
|
|
|
|
|
|
m_controllerHandler.ConvertAxisToSwitchAxis(data.sticks[0].axis_x, data.sticks[0].axis_y, 0, &m_hdlState.joysticks[JOYSTICK_LEFT].dx, &m_hdlState.joysticks[JOYSTICK_LEFT].dy);
|
|
|
|
}
|
2019-10-31 18:00:42 +00:00
|
|
|
|
2019-11-07 17:46:47 +00:00
|
|
|
m_controllerHandler.ConvertAxisToSwitchAxis(data.sticks[1].axis_x, data.sticks[1].axis_y, 0, &m_hdlState.joysticks[JOYSTICK_RIGHT].dx, &m_hdlState.joysticks[JOYSTICK_RIGHT].dy);
|
2019-11-09 20:36:52 +00:00
|
|
|
|
|
|
|
m_hdlState.buttons |= (data.buttons[16] ? KEY_CAPTURE : 0);
|
|
|
|
m_hdlState.buttons |= (data.buttons[17] ? KEY_HOME : 0);
|
2019-11-15 11:03:06 +00:00
|
|
|
m_hdlState.buttons |= (data.buttons[18] ? KEY_TOUCH : 0);
|
2019-10-31 18:00:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SwitchHDLHandler::UpdateInput()
|
|
|
|
{
|
|
|
|
Result rc;
|
|
|
|
rc = GetController()->GetInput();
|
|
|
|
if (R_FAILED(rc))
|
|
|
|
return;
|
|
|
|
|
2019-11-08 23:31:49 +00:00
|
|
|
if (!GetController()->IsControllerActive())
|
|
|
|
{
|
|
|
|
hiddbgDetachHdlsVirtualDevice(m_hdlHandle);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FillHdlState(GetController()->GetNormalizedButtonData());
|
|
|
|
rc = UpdateHdlState();
|
|
|
|
if (R_FAILED(rc))
|
|
|
|
return;
|
|
|
|
}
|
2019-10-31 18:00:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SwitchHDLHandler::UpdateOutput()
|
|
|
|
{
|
2019-11-08 23:31:49 +00:00
|
|
|
if (R_SUCCEEDED(GetController()->OutputBuffer()))
|
2019-10-31 18:00:42 +00:00
|
|
|
return;
|
|
|
|
|
2019-11-08 23:31:49 +00:00
|
|
|
if (DoesControllerSupport(GetController()->GetType(), SUPPORTS_RUMBLE))
|
2019-11-08 18:06:02 +00:00
|
|
|
{
|
|
|
|
Result rc;
|
|
|
|
HidVibrationValue value;
|
|
|
|
rc = hidGetActualVibrationValue(&m_vibrationDeviceHandle, &value);
|
|
|
|
if (R_SUCCEEDED(rc))
|
|
|
|
GetController()->SetRumble(static_cast<uint8_t>(value.amp_high * 255.0f), static_cast<uint8_t>(value.amp_low * 255.0f));
|
|
|
|
}
|
2019-10-31 18:00:42 +00:00
|
|
|
|
|
|
|
svcSleepThread(1e+7L);
|
|
|
|
}
|