aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs64
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/HidServer/HidUtils.cs14
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs76
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/IHidSystemServer.cs70
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/ResultCode.cs12
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/AppletFooterUiType.cs30
-rw-r--r--Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadInternalState.cs2
7 files changed, 205 insertions, 63 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs
index 3ff7e733..a063b41f 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/HidDevices/NpadDevices.cs
@@ -239,45 +239,51 @@ namespace Ryujinx.HLE.HOS.Services.Hid
switch (type)
{
case ControllerType.ProController:
- controller.StyleSet = NpadStyleTag.FullKey;
- controller.DeviceType = DeviceType.FullKey;
- controller.SystemProperties |= NpadSystemProperties.IsAbxyButtonOriented |
- NpadSystemProperties.IsPlusAvailable |
- NpadSystemProperties.IsMinusAvailable;
+ controller.StyleSet = NpadStyleTag.FullKey;
+ controller.DeviceType = DeviceType.FullKey;
+ controller.SystemProperties |= NpadSystemProperties.IsAbxyButtonOriented |
+ NpadSystemProperties.IsPlusAvailable |
+ NpadSystemProperties.IsMinusAvailable;
+ controller.AppletFooterUiType = AppletFooterUiType.SwitchProController;
break;
case ControllerType.Handheld:
- controller.StyleSet = NpadStyleTag.Handheld;
- controller.DeviceType = DeviceType.HandheldLeft |
- DeviceType.HandheldRight;
- controller.SystemProperties |= NpadSystemProperties.IsAbxyButtonOriented |
- NpadSystemProperties.IsPlusAvailable |
- NpadSystemProperties.IsMinusAvailable;
+ controller.StyleSet = NpadStyleTag.Handheld;
+ controller.DeviceType = DeviceType.HandheldLeft |
+ DeviceType.HandheldRight;
+ controller.SystemProperties |= NpadSystemProperties.IsAbxyButtonOriented |
+ NpadSystemProperties.IsPlusAvailable |
+ NpadSystemProperties.IsMinusAvailable;
+ controller.AppletFooterUiType = AppletFooterUiType.HandheldJoyConLeftJoyConRight;
break;
case ControllerType.JoyconPair:
- controller.StyleSet = NpadStyleTag.JoyDual;
- controller.DeviceType = DeviceType.JoyLeft |
- DeviceType.JoyRight;
- controller.SystemProperties |= NpadSystemProperties.IsAbxyButtonOriented |
- NpadSystemProperties.IsPlusAvailable |
- NpadSystemProperties.IsMinusAvailable;
+ controller.StyleSet = NpadStyleTag.JoyDual;
+ controller.DeviceType = DeviceType.JoyLeft |
+ DeviceType.JoyRight;
+ controller.SystemProperties |= NpadSystemProperties.IsAbxyButtonOriented |
+ NpadSystemProperties.IsPlusAvailable |
+ NpadSystemProperties.IsMinusAvailable;
+ controller.AppletFooterUiType = _device.System.State.DockedMode ? AppletFooterUiType.JoyDual : AppletFooterUiType.HandheldJoyConLeftJoyConRight;
break;
case ControllerType.JoyconLeft:
- controller.StyleSet = NpadStyleTag.JoyLeft;
- controller.JoyAssignmentMode = NpadJoyAssignmentMode.Single;
- controller.DeviceType = DeviceType.JoyLeft;
- controller.SystemProperties |= NpadSystemProperties.IsSlSrButtonOriented |
- NpadSystemProperties.IsMinusAvailable;
+ controller.StyleSet = NpadStyleTag.JoyLeft;
+ controller.JoyAssignmentMode = NpadJoyAssignmentMode.Single;
+ controller.DeviceType = DeviceType.JoyLeft;
+ controller.SystemProperties |= NpadSystemProperties.IsSlSrButtonOriented |
+ NpadSystemProperties.IsMinusAvailable;
+ controller.AppletFooterUiType = _device.System.State.DockedMode ? AppletFooterUiType.JoyDualLeftOnly : AppletFooterUiType.HandheldJoyConLeftOnly;
break;
case ControllerType.JoyconRight:
- controller.StyleSet = NpadStyleTag.JoyRight;
- controller.JoyAssignmentMode = NpadJoyAssignmentMode.Single;
- controller.DeviceType = DeviceType.JoyRight;
- controller.SystemProperties |= NpadSystemProperties.IsSlSrButtonOriented |
- NpadSystemProperties.IsPlusAvailable;
+ controller.StyleSet = NpadStyleTag.JoyRight;
+ controller.JoyAssignmentMode = NpadJoyAssignmentMode.Single;
+ controller.DeviceType = DeviceType.JoyRight;
+ controller.SystemProperties |= NpadSystemProperties.IsSlSrButtonOriented |
+ NpadSystemProperties.IsPlusAvailable;
+ controller.AppletFooterUiType = _device.System.State.DockedMode ? AppletFooterUiType.JoyDualRightOnly : AppletFooterUiType.HandheldJoyConRightOnly;
break;
case ControllerType.Pokeball:
- controller.StyleSet = NpadStyleTag.Palma;
- controller.DeviceType = DeviceType.Palma;
+ controller.StyleSet = NpadStyleTag.Palma;
+ controller.DeviceType = DeviceType.Palma;
+ controller.AppletFooterUiType = AppletFooterUiType.None;
break;
}
diff --git a/Ryujinx.HLE/HOS/Services/Hid/HidServer/HidUtils.cs b/Ryujinx.HLE/HOS/Services/Hid/HidServer/HidUtils.cs
index 9db5b518..c2cd8432 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/HidServer/HidUtils.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/HidServer/HidUtils.cs
@@ -35,19 +35,5 @@ namespace Ryujinx.HLE.HOS.Services.Hid.HidServer
PlayerIndex.Unknown => NpadIdType.Unknown,
_ => 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
- };
}
} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs b/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs
index 0155fb1e..3f2aae35 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs
@@ -746,22 +746,33 @@ namespace Ryujinx.HLE.HOS.Services.Hid
}
[CommandHipc(108)]
- // GetPlayerLedPattern(uint NpadId) -> ulong LedPattern
+ // GetPlayerLedPattern(u32 npad_id) -> u64 led_pattern
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);
- Logger.Stub?.PrintStub(LogClass.ServiceHid, new { npadId, ledPattern });
-
return ResultCode.Success;
}
[CommandHipc(109)] // 5.0.0+
- // ActivateNpadWithRevision(nn::applet::AppletResourceUserId, int Unknown)
+ // ActivateNpadWithRevision(nn::applet::AppletResourceUserId, int revision)
public ResultCode ActivateNpadWithRevision(ServiceCtx context)
{
int revision = context.RequestData.ReadInt32();
@@ -798,32 +809,46 @@ namespace Ryujinx.HLE.HOS.Services.Hid
}
[CommandHipc(120)]
- // SetNpadJoyHoldType(nn::applet::AppletResourceUserId, long NpadJoyHoldType)
+ // SetNpadJoyHoldType(nn::applet::AppletResourceUserId, ulong NpadJoyHoldType)
public ResultCode SetNpadJoyHoldType(ServiceCtx context)
{
long appletResourceUserId = context.RequestData.ReadInt64();
- context.Device.Hid.Npads.JoyHold = (NpadJoyHoldType)context.RequestData.ReadInt64();
- Logger.Stub?.PrintStub(LogClass.ServiceHid, new {
- appletResourceUserId,
- context.Device.Hid.Npads.JoyHold
- });
+ NpadJoyHoldType npadJoyHoldType = (NpadJoyHoldType)context.RequestData.ReadUInt64();
+
+ 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;
}
[CommandHipc(121)]
- // GetNpadJoyHoldType(nn::applet::AppletResourceUserId) -> long NpadJoyHoldType
+ // GetNpadJoyHoldType(nn::applet::AppletResourceUserId) -> ulong NpadJoyHoldType
public ResultCode GetNpadJoyHoldType(ServiceCtx context)
{
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 {
- appletResourceUserId,
- context.Device.Hid.Npads.JoyHold
- });
+ context.ResponseData.Write((ulong)context.Device.Hid.Npads.JoyHold);
return ResultCode.Success;
}
@@ -1171,6 +1196,21 @@ namespace Ryujinx.HLE.HOS.Services.Hid
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)]
// ActivateConsoleSixAxisSensor(nn::applet::AppletResourceUserId)
public ResultCode ActivateConsoleSixAxisSensor(ServiceCtx context)
diff --git a/Ryujinx.HLE/HOS/Services/Hid/IHidSystemServer.cs b/Ryujinx.HLE/HOS/Services/Hid/IHidSystemServer.cs
index 019e9954..ec8295e2 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/IHidSystemServer.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/IHidSystemServer.cs
@@ -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")]
class IHidSystemServer : IpcService
{
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;
+ }
}
} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/ResultCode.cs b/Ryujinx.HLE/HOS/Services/Hid/ResultCode.cs
new file mode 100644
index 00000000..9b829cc5
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/ResultCode.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.HLE.HOS.Services.Hid
+{
+ enum ResultCode
+ {
+ ModuleId = 202,
+ ErrorCodeShift = 9,
+
+ Success = 0,
+
+ InvalidNpadIdType = (710 << ErrorCodeShift) | ModuleId
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/AppletFooterUiType.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/AppletFooterUiType.cs
new file mode 100644
index 00000000..c4ff8d7e
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/AppletFooterUiType.cs
@@ -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
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadInternalState.cs b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadInternalState.cs
index f225ff67..5ef5f48d 100644
--- a/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadInternalState.cs
+++ b/Ryujinx.HLE/HOS/Services/Hid/Types/SharedMemory/Npad/NpadInternalState.cs
@@ -29,7 +29,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Types.SharedMemory.Npad
public NpadBatteryLevel BatteryLevelJoyLeft;
public NpadBatteryLevel BatteryLevelJoyRight;
public uint AppletFooterUiAttributes;
- public byte AppletFooterUiType;
+ public AppletFooterUiType AppletFooterUiType;
private unsafe fixed byte _reserved2[0x7B];
public RingLifo<NpadGcTriggerState> GcTrigger;
public NpadLarkType LarkTypeLeftAndMain;