hid: Cleanup and implement some calls (#2380)
This commit is contained in:
parent
9efe124fc5
commit
eb23933331
7 changed files with 205 additions and 63 deletions
|
@ -244,6 +244,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
controller.SystemProperties |= NpadSystemProperties.IsAbxyButtonOriented |
|
controller.SystemProperties |= NpadSystemProperties.IsAbxyButtonOriented |
|
||||||
NpadSystemProperties.IsPlusAvailable |
|
NpadSystemProperties.IsPlusAvailable |
|
||||||
NpadSystemProperties.IsMinusAvailable;
|
NpadSystemProperties.IsMinusAvailable;
|
||||||
|
controller.AppletFooterUiType = AppletFooterUiType.SwitchProController;
|
||||||
break;
|
break;
|
||||||
case ControllerType.Handheld:
|
case ControllerType.Handheld:
|
||||||
controller.StyleSet = NpadStyleTag.Handheld;
|
controller.StyleSet = NpadStyleTag.Handheld;
|
||||||
|
@ -252,6 +253,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
controller.SystemProperties |= NpadSystemProperties.IsAbxyButtonOriented |
|
controller.SystemProperties |= NpadSystemProperties.IsAbxyButtonOriented |
|
||||||
NpadSystemProperties.IsPlusAvailable |
|
NpadSystemProperties.IsPlusAvailable |
|
||||||
NpadSystemProperties.IsMinusAvailable;
|
NpadSystemProperties.IsMinusAvailable;
|
||||||
|
controller.AppletFooterUiType = AppletFooterUiType.HandheldJoyConLeftJoyConRight;
|
||||||
break;
|
break;
|
||||||
case ControllerType.JoyconPair:
|
case ControllerType.JoyconPair:
|
||||||
controller.StyleSet = NpadStyleTag.JoyDual;
|
controller.StyleSet = NpadStyleTag.JoyDual;
|
||||||
|
@ -260,6 +262,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
controller.SystemProperties |= NpadSystemProperties.IsAbxyButtonOriented |
|
controller.SystemProperties |= NpadSystemProperties.IsAbxyButtonOriented |
|
||||||
NpadSystemProperties.IsPlusAvailable |
|
NpadSystemProperties.IsPlusAvailable |
|
||||||
NpadSystemProperties.IsMinusAvailable;
|
NpadSystemProperties.IsMinusAvailable;
|
||||||
|
controller.AppletFooterUiType = _device.System.State.DockedMode ? AppletFooterUiType.JoyDual : AppletFooterUiType.HandheldJoyConLeftJoyConRight;
|
||||||
break;
|
break;
|
||||||
case ControllerType.JoyconLeft:
|
case ControllerType.JoyconLeft:
|
||||||
controller.StyleSet = NpadStyleTag.JoyLeft;
|
controller.StyleSet = NpadStyleTag.JoyLeft;
|
||||||
|
@ -267,6 +270,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
controller.DeviceType = DeviceType.JoyLeft;
|
controller.DeviceType = DeviceType.JoyLeft;
|
||||||
controller.SystemProperties |= NpadSystemProperties.IsSlSrButtonOriented |
|
controller.SystemProperties |= NpadSystemProperties.IsSlSrButtonOriented |
|
||||||
NpadSystemProperties.IsMinusAvailable;
|
NpadSystemProperties.IsMinusAvailable;
|
||||||
|
controller.AppletFooterUiType = _device.System.State.DockedMode ? AppletFooterUiType.JoyDualLeftOnly : AppletFooterUiType.HandheldJoyConLeftOnly;
|
||||||
break;
|
break;
|
||||||
case ControllerType.JoyconRight:
|
case ControllerType.JoyconRight:
|
||||||
controller.StyleSet = NpadStyleTag.JoyRight;
|
controller.StyleSet = NpadStyleTag.JoyRight;
|
||||||
|
@ -274,10 +278,12 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
controller.DeviceType = DeviceType.JoyRight;
|
controller.DeviceType = DeviceType.JoyRight;
|
||||||
controller.SystemProperties |= NpadSystemProperties.IsSlSrButtonOriented |
|
controller.SystemProperties |= NpadSystemProperties.IsSlSrButtonOriented |
|
||||||
NpadSystemProperties.IsPlusAvailable;
|
NpadSystemProperties.IsPlusAvailable;
|
||||||
|
controller.AppletFooterUiType = _device.System.State.DockedMode ? AppletFooterUiType.JoyDualRightOnly : AppletFooterUiType.HandheldJoyConRightOnly;
|
||||||
break;
|
break;
|
||||||
case ControllerType.Pokeball:
|
case ControllerType.Pokeball:
|
||||||
controller.StyleSet = NpadStyleTag.Palma;
|
controller.StyleSet = NpadStyleTag.Palma;
|
||||||
controller.DeviceType = DeviceType.Palma;
|
controller.DeviceType = DeviceType.Palma;
|
||||||
|
controller.AppletFooterUiType = AppletFooterUiType.None;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,19 +35,5 @@ namespace Ryujinx.HLE.HOS.Services.Hid.HidServer
|
||||||
PlayerIndex.Unknown => NpadIdType.Unknown,
|
PlayerIndex.Unknown => NpadIdType.Unknown,
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(index))
|
_ => throw new ArgumentOutOfRangeException(nameof(index))
|
||||||
};
|
};
|
||||||
|
|
||||||
public static long GetLedPatternFromNpadId(NpadIdType npadIdType)
|
|
||||||
=> npadIdType switch
|
|
||||||
{
|
|
||||||
NpadIdType.Player1 => 0b0001,
|
|
||||||
NpadIdType.Player2 => 0b0011,
|
|
||||||
NpadIdType.Player3 => 0b0111,
|
|
||||||
NpadIdType.Player4 => 0b1111,
|
|
||||||
NpadIdType.Player5 => 0b1001,
|
|
||||||
NpadIdType.Player6 => 0b0101,
|
|
||||||
NpadIdType.Player7 => 0b1101,
|
|
||||||
NpadIdType.Player8 => 0b0110,
|
|
||||||
_ => 0b0000
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -746,22 +746,33 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
}
|
}
|
||||||
|
|
||||||
[CommandHipc(108)]
|
[CommandHipc(108)]
|
||||||
// GetPlayerLedPattern(uint NpadId) -> ulong LedPattern
|
// GetPlayerLedPattern(u32 npad_id) -> u64 led_pattern
|
||||||
public ResultCode GetPlayerLedPattern(ServiceCtx context)
|
public ResultCode GetPlayerLedPattern(ServiceCtx context)
|
||||||
{
|
{
|
||||||
NpadIdType npadId = (NpadIdType)context.RequestData.ReadInt32();
|
NpadIdType npadId = (NpadIdType)context.RequestData.ReadUInt32();
|
||||||
|
|
||||||
long ledPattern = HidUtils.GetLedPatternFromNpadId(npadId);
|
ulong ledPattern = npadId switch
|
||||||
|
{
|
||||||
|
NpadIdType.Player1 => 0b0001,
|
||||||
|
NpadIdType.Player2 => 0b0011,
|
||||||
|
NpadIdType.Player3 => 0b0111,
|
||||||
|
NpadIdType.Player4 => 0b1111,
|
||||||
|
NpadIdType.Player5 => 0b1001,
|
||||||
|
NpadIdType.Player6 => 0b0101,
|
||||||
|
NpadIdType.Player7 => 0b1101,
|
||||||
|
NpadIdType.Player8 => 0b0110,
|
||||||
|
NpadIdType.Unknown => 0b0000,
|
||||||
|
NpadIdType.Handheld => 0b0000,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(npadId))
|
||||||
|
};
|
||||||
|
|
||||||
context.ResponseData.Write(ledPattern);
|
context.ResponseData.Write(ledPattern);
|
||||||
|
|
||||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { npadId, ledPattern });
|
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
[CommandHipc(109)] // 5.0.0+
|
[CommandHipc(109)] // 5.0.0+
|
||||||
// ActivateNpadWithRevision(nn::applet::AppletResourceUserId, int Unknown)
|
// ActivateNpadWithRevision(nn::applet::AppletResourceUserId, int revision)
|
||||||
public ResultCode ActivateNpadWithRevision(ServiceCtx context)
|
public ResultCode ActivateNpadWithRevision(ServiceCtx context)
|
||||||
{
|
{
|
||||||
int revision = context.RequestData.ReadInt32();
|
int revision = context.RequestData.ReadInt32();
|
||||||
|
@ -798,32 +809,46 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
}
|
}
|
||||||
|
|
||||||
[CommandHipc(120)]
|
[CommandHipc(120)]
|
||||||
// SetNpadJoyHoldType(nn::applet::AppletResourceUserId, long NpadJoyHoldType)
|
// SetNpadJoyHoldType(nn::applet::AppletResourceUserId, ulong NpadJoyHoldType)
|
||||||
public ResultCode SetNpadJoyHoldType(ServiceCtx context)
|
public ResultCode SetNpadJoyHoldType(ServiceCtx context)
|
||||||
{
|
{
|
||||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||||
context.Device.Hid.Npads.JoyHold = (NpadJoyHoldType)context.RequestData.ReadInt64();
|
|
||||||
|
|
||||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, new {
|
NpadJoyHoldType npadJoyHoldType = (NpadJoyHoldType)context.RequestData.ReadUInt64();
|
||||||
appletResourceUserId,
|
|
||||||
context.Device.Hid.Npads.JoyHold
|
if (npadJoyHoldType > NpadJoyHoldType.Horizontal)
|
||||||
});
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(npadJoyHoldType));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (PlayerIndex playerIndex in context.Device.Hid.Npads.GetSupportedPlayers())
|
||||||
|
{
|
||||||
|
if (HidUtils.GetNpadIdTypeFromIndex(playerIndex) > NpadIdType.Handheld)
|
||||||
|
{
|
||||||
|
return ResultCode.InvalidNpadIdType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Device.Hid.Npads.JoyHold = npadJoyHoldType;
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
[CommandHipc(121)]
|
[CommandHipc(121)]
|
||||||
// GetNpadJoyHoldType(nn::applet::AppletResourceUserId) -> long NpadJoyHoldType
|
// GetNpadJoyHoldType(nn::applet::AppletResourceUserId) -> ulong NpadJoyHoldType
|
||||||
public ResultCode GetNpadJoyHoldType(ServiceCtx context)
|
public ResultCode GetNpadJoyHoldType(ServiceCtx context)
|
||||||
{
|
{
|
||||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||||
|
|
||||||
context.ResponseData.Write((long)context.Device.Hid.Npads.JoyHold);
|
foreach (PlayerIndex playerIndex in context.Device.Hid.Npads.GetSupportedPlayers())
|
||||||
|
{
|
||||||
|
if (HidUtils.GetNpadIdTypeFromIndex(playerIndex) > NpadIdType.Handheld)
|
||||||
|
{
|
||||||
|
return ResultCode.InvalidNpadIdType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, new {
|
context.ResponseData.Write((ulong)context.Device.Hid.Npads.JoyHold);
|
||||||
appletResourceUserId,
|
|
||||||
context.Device.Hid.Npads.JoyHold
|
|
||||||
});
|
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -1171,6 +1196,21 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CommandHipc(211)] // 7.0.0+
|
||||||
|
// IsVibrationDeviceMounted(nn::hid::VibrationDeviceHandle, nn::applet::AppletResourceUserId)
|
||||||
|
public ResultCode IsVibrationDeviceMounted(ServiceCtx context)
|
||||||
|
{
|
||||||
|
int vibrationDeviceHandle = context.RequestData.ReadInt32();
|
||||||
|
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||||
|
|
||||||
|
// NOTE: Service use vibrationDeviceHandle to get the PlayerIndex.
|
||||||
|
// And return false if (npadIdType >= (NpadIdType)8 && npadIdType != NpadIdType.Handheld && npadIdType != NpadIdType.Unknown)
|
||||||
|
|
||||||
|
context.ResponseData.Write(true);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
[CommandHipc(300)]
|
[CommandHipc(300)]
|
||||||
// ActivateConsoleSixAxisSensor(nn::applet::AppletResourceUserId)
|
// ActivateConsoleSixAxisSensor(nn::applet::AppletResourceUserId)
|
||||||
public ResultCode ActivateConsoleSixAxisSensor(ServiceCtx context)
|
public ResultCode ActivateConsoleSixAxisSensor(ServiceCtx context)
|
||||||
|
|
|
@ -1,8 +1,76 @@
|
||||||
namespace Ryujinx.HLE.HOS.Services.Hid
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Hid.HidServer;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Hid.Types;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
{
|
{
|
||||||
[Service("hid:sys")]
|
[Service("hid:sys")]
|
||||||
class IHidSystemServer : IpcService
|
class IHidSystemServer : IpcService
|
||||||
{
|
{
|
||||||
public IHidSystemServer(ServiceCtx context) { }
|
public IHidSystemServer(ServiceCtx context) { }
|
||||||
|
|
||||||
|
[CommandHipc(303)]
|
||||||
|
// ApplyNpadSystemCommonPolicy(u64)
|
||||||
|
public ResultCode ApplyNpadSystemCommonPolicy(ServiceCtx context)
|
||||||
|
{
|
||||||
|
ulong commonPolicy = context.RequestData.ReadUInt64();
|
||||||
|
|
||||||
|
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { commonPolicy });
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(306)]
|
||||||
|
// GetLastActiveNpad(u32) -> u8, u8
|
||||||
|
public ResultCode GetLastActiveNpad(ServiceCtx context)
|
||||||
|
{
|
||||||
|
// TODO: RequestData seems to have garbage data, reading an extra uint seems to fix the issue.
|
||||||
|
context.RequestData.ReadUInt32();
|
||||||
|
|
||||||
|
ResultCode resultCode = GetAppletFooterUiTypeImpl(context, out AppletFooterUiType appletFooterUiType);
|
||||||
|
|
||||||
|
context.ResponseData.Write((byte)appletFooterUiType);
|
||||||
|
context.ResponseData.Write((byte)0);
|
||||||
|
|
||||||
|
return resultCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(307)]
|
||||||
|
// GetNpadSystemExtStyle() -> u64
|
||||||
|
public ResultCode GetNpadSystemExtStyle(ServiceCtx context)
|
||||||
|
{
|
||||||
|
foreach (PlayerIndex playerIndex in context.Device.Hid.Npads.GetSupportedPlayers())
|
||||||
|
{
|
||||||
|
if (HidUtils.GetNpadIdTypeFromIndex(playerIndex) > NpadIdType.Handheld)
|
||||||
|
{
|
||||||
|
return ResultCode.InvalidNpadIdType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context.ResponseData.Write((ulong)context.Device.Hid.Npads.SupportedStyleSets);
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CommandHipc(314)] // 9.0.0+
|
||||||
|
// GetAppletFooterUiType(u32) -> u8
|
||||||
|
public ResultCode GetAppletFooterUiType(ServiceCtx context)
|
||||||
|
{
|
||||||
|
ResultCode resultCode = GetAppletFooterUiTypeImpl(context, out AppletFooterUiType appletFooterUiType);
|
||||||
|
|
||||||
|
context.ResponseData.Write((byte)appletFooterUiType);
|
||||||
|
|
||||||
|
return resultCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultCode GetAppletFooterUiTypeImpl(ServiceCtx context, out AppletFooterUiType appletFooterUiType)
|
||||||
|
{
|
||||||
|
NpadIdType npadIdType = (NpadIdType)context.RequestData.ReadUInt32();
|
||||||
|
PlayerIndex playerIndex = HidUtils.GetIndexFromNpadIdType(npadIdType);
|
||||||
|
|
||||||
|
appletFooterUiType = context.Device.Hid.SharedMemory.Npads[(int)playerIndex].InternalState.AppletFooterUiType;
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
12
Ryujinx.HLE/HOS/Services/Hid/ResultCode.cs
Normal file
12
Ryujinx.HLE/HOS/Services/Hid/ResultCode.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
|
{
|
||||||
|
enum ResultCode
|
||||||
|
{
|
||||||
|
ModuleId = 202,
|
||||||
|
ErrorCodeShift = 9,
|
||||||
|
|
||||||
|
Success = 0,
|
||||||
|
|
||||||
|
InvalidNpadIdType = (710 << ErrorCodeShift) | ModuleId
|
||||||
|
}
|
||||||
|
}
|
30
Ryujinx.HLE/HOS/Services/Hid/Types/AppletFooterUiType.cs
Normal file
30
Ryujinx.HLE/HOS/Services/Hid/Types/AppletFooterUiType.cs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Hid.Types
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
enum AppletFooterUiType : byte
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
HandheldNone,
|
||||||
|
HandheldJoyConLeftOnly,
|
||||||
|
HandheldJoyConRightOnly,
|
||||||
|
HandheldJoyConLeftJoyConRight,
|
||||||
|
JoyDual,
|
||||||
|
JoyDualLeftOnly,
|
||||||
|
JoyDualRightOnly,
|
||||||
|
JoyLeftHorizontal,
|
||||||
|
JoyLeftVertical,
|
||||||
|
JoyRightHorizontal,
|
||||||
|
JoyRightVertical,
|
||||||
|
SwitchProController,
|
||||||
|
CompatibleProController,
|
||||||
|
CompatibleJoyCon,
|
||||||
|
LarkHvc1,
|
||||||
|
LarkHvc2,
|
||||||
|
LarkNesLeft,
|
||||||
|
LarkNesRight,
|
||||||
|
Lucia,
|
||||||
|
Verification
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,7 +29,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
|
||||||
public NpadBatteryLevel BatteryLevelJoyLeft;
|
public NpadBatteryLevel BatteryLevelJoyLeft;
|
||||||
public NpadBatteryLevel BatteryLevelJoyRight;
|
public NpadBatteryLevel BatteryLevelJoyRight;
|
||||||
public uint AppletFooterUiAttributes;
|
public uint AppletFooterUiAttributes;
|
||||||
public byte AppletFooterUiType;
|
public AppletFooterUiType AppletFooterUiType;
|
||||||
private unsafe fixed byte _reserved2[0x7B];
|
private unsafe fixed byte _reserved2[0x7B];
|
||||||
public RingLifo<NpadGcTriggerState> GcTrigger;
|
public RingLifo<NpadGcTriggerState> GcTrigger;
|
||||||
public NpadLarkType LarkTypeLeftAndMain;
|
public NpadLarkType LarkTypeLeftAndMain;
|
||||||
|
|
Reference in a new issue