| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000 |
- using Ryujinx.Common.Memory;
- using Ryujinx.Cpu;
- using Ryujinx.HLE.Exceptions;
- using Ryujinx.HLE.HOS.Ipc;
- using Ryujinx.HLE.HOS.Kernel.Common;
- using Ryujinx.HLE.HOS.Kernel.Threading;
- using Ryujinx.HLE.HOS.Services.Hid;
- using Ryujinx.HLE.HOS.Services.Hid.HidServer;
- using Ryujinx.HLE.HOS.Services.Nfc.Nfp.NfpManager;
- using System;
- using System.Buffers.Binary;
- using System.Globalization;
- using System.Runtime.InteropServices;
- using System.Threading;
- using System.Threading.Tasks;
- namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
- {
- class INfp : IpcService
- {
- private ulong _appletResourceUserId;
- private ulong _mcuVersionData;
- private byte[] _mcuData;
- private State _state = State.NonInitialized;
- private KEvent _availabilityChangeEvent;
- private CancellationTokenSource _cancelTokenSource;
- private NfpPermissionLevel _permissionLevel;
- public INfp(NfpPermissionLevel permissionLevel)
- {
- _permissionLevel = permissionLevel;
- }
- [CommandHipc(0)]
- // Initialize(u64, u64, pid, buffer<unknown, 5>)
- public ResultCode Initialize(ServiceCtx context)
- {
- _appletResourceUserId = context.RequestData.ReadUInt64();
- _mcuVersionData = context.RequestData.ReadUInt64();
- ulong inputPosition = context.Request.SendBuff[0].Position;
- ulong inputSize = context.Request.SendBuff[0].Size;
- _mcuData = new byte[inputSize];
- context.Memory.Read(inputPosition, _mcuData);
- // TODO: The mcuData buffer seems to contains entries with a size of 0x40 bytes each. Usage of the data needs to be determined.
- // TODO: Handle this in a controller class directly.
- // Every functions which use the Handle call nn::hid::system::GetXcdHandleForNpadWithNfc().
- NfpDevice devicePlayer1 = new NfpDevice
- {
- NpadIdType = NpadIdType.Player1,
- Handle = HidUtils.GetIndexFromNpadIdType(NpadIdType.Player1),
- State = NfpDeviceState.Initialized
- };
- context.Device.System.NfpDevices.Add(devicePlayer1);
- // TODO: It mounts 0x8000000000000020 save data and stores a random generate value inside. Usage of the data needs to be determined.
- _state = State.Initialized;
- return ResultCode.Success;
- }
- [CommandHipc(1)]
- // Finalize()
- public ResultCode Finalize(ServiceCtx context)
- {
- if (_state == State.Initialized)
- {
- if (_cancelTokenSource != null)
- {
- _cancelTokenSource.Cancel();
- }
- // NOTE: All events are destroyed here.
- context.Device.System.NfpDevices.Clear();
- _state = State.NonInitialized;
- }
- return ResultCode.Success;
- }
- [CommandHipc(2)]
- // ListDevices() -> (u32, buffer<unknown, 0xa>)
- public ResultCode ListDevices(ServiceCtx context)
- {
- if (context.Request.RecvListBuff.Count == 0)
- {
- return ResultCode.WrongArgument;
- }
- ulong outputPosition = context.Request.RecvListBuff[0].Position;
- ulong outputSize = context.Request.RecvListBuff[0].Size;
- if (context.Device.System.NfpDevices.Count == 0)
- {
- return ResultCode.DeviceNotFound;
- }
- MemoryHelper.FillWithZeros(context.Memory, outputPosition, (int)outputSize);
- if (CheckNfcIsEnabled() == ResultCode.Success)
- {
- for (int i = 0; i < context.Device.System.NfpDevices.Count; i++)
- {
- context.Memory.Write(outputPosition + ((uint)i * sizeof(long)), (uint)context.Device.System.NfpDevices[i].Handle);
- }
- context.ResponseData.Write(context.Device.System.NfpDevices.Count);
- }
- else
- {
- context.ResponseData.Write(0);
- }
- return ResultCode.Success;
- }
- [CommandHipc(3)]
- // StartDetection(bytes<8, 4>)
- public ResultCode StartDetection(ServiceCtx context)
- {
- ResultCode resultCode = CheckNfcIsEnabled();
- if (resultCode != ResultCode.Success)
- {
- return resultCode;
- }
- uint deviceHandle = (uint)context.RequestData.ReadUInt64();
- for (int i = 0; i < context.Device.System.NfpDevices.Count; i++)
- {
- if (context.Device.System.NfpDevices[i].Handle == (PlayerIndex)deviceHandle)
- {
- context.Device.System.NfpDevices[i].State = NfpDeviceState.SearchingForTag;
- break;
- }
- }
- _cancelTokenSource = new CancellationTokenSource();
- Task.Run(() =>
- {
- while (true)
- {
- if (_cancelTokenSource.Token.IsCancellationRequested)
- {
- break;
- }
- for (int i = 0; i < context.Device.System.NfpDevices.Count; i++)
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagFound)
- {
- context.Device.System.NfpDevices[i].SignalActivate();
- Thread.Sleep(125); // NOTE: Simulate amiibo scanning delay.
- context.Device.System.NfpDevices[i].SignalDeactivate();
- break;
- }
- }
- }
- }, _cancelTokenSource.Token);
- return ResultCode.Success;
- }
- [CommandHipc(4)]
- // StopDetection(bytes<8, 4>)
- public ResultCode StopDetection(ServiceCtx context)
- {
- ResultCode resultCode = CheckNfcIsEnabled();
- if (resultCode != ResultCode.Success)
- {
- return resultCode;
- }
- if (_cancelTokenSource != null)
- {
- _cancelTokenSource.Cancel();
- }
- uint deviceHandle = (uint)context.RequestData.ReadUInt64();
- for (int i = 0; i < context.Device.System.NfpDevices.Count; i++)
- {
- if (context.Device.System.NfpDevices[i].Handle == (PlayerIndex)deviceHandle)
- {
- context.Device.System.NfpDevices[i].State = NfpDeviceState.Initialized;
- break;
- }
- }
- return ResultCode.Success;
- }
- [CommandHipc(5)]
- // Mount(bytes<8, 4>, u32, u32)
- public ResultCode Mount(ServiceCtx context)
- {
- ResultCode resultCode = CheckNfcIsEnabled();
- if (resultCode != ResultCode.Success)
- {
- return resultCode;
- }
- uint deviceHandle = (uint)context.RequestData.ReadUInt64();
- DeviceType deviceType = (DeviceType)context.RequestData.ReadUInt32();
- MountTarget mountTarget = (MountTarget)context.RequestData.ReadUInt32();
- if (deviceType != 0)
- {
- return ResultCode.WrongArgument;
- }
- if (((uint)mountTarget & 3) == 0)
- {
- return ResultCode.WrongArgument;
- }
- // TODO: Found how the MountTarget is handled.
- for (int i = 0; i < context.Device.System.NfpDevices.Count; i++)
- {
- if (context.Device.System.NfpDevices[i].Handle == (PlayerIndex)deviceHandle)
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagRemoved)
- {
- resultCode = ResultCode.TagNotFound;
- }
- else
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagFound)
- {
- // NOTE: This mount the amiibo data, which isn't needed in our case.
- context.Device.System.NfpDevices[i].State = NfpDeviceState.TagMounted;
- resultCode = ResultCode.Success;
- }
- else
- {
- resultCode = ResultCode.WrongDeviceState;
- }
- }
- break;
- }
- }
- return resultCode;
- }
- [CommandHipc(6)]
- // Unmount(bytes<8, 4>)
- public ResultCode Unmount(ServiceCtx context)
- {
- ResultCode resultCode = CheckNfcIsEnabled();
- if (resultCode != ResultCode.Success)
- {
- return resultCode;
- }
- uint deviceHandle = (uint)context.RequestData.ReadUInt64();
- if (context.Device.System.NfpDevices.Count == 0)
- {
- return ResultCode.DeviceNotFound;
- }
- for (int i = 0; i < context.Device.System.NfpDevices.Count; i++)
- {
- if (context.Device.System.NfpDevices[i].Handle == (PlayerIndex)deviceHandle)
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagRemoved)
- {
- resultCode = ResultCode.TagNotFound;
- }
- else
- {
- // NOTE: This mount the amiibo data, which isn't needed in our case.
- context.Device.System.NfpDevices[i].State = NfpDeviceState.TagFound;
- resultCode = ResultCode.Success;
- }
- break;
- }
- }
- return resultCode;
- }
- [CommandHipc(7)]
- // OpenApplicationArea(bytes<8, 4>, u32)
- public ResultCode OpenApplicationArea(ServiceCtx context)
- {
- ResultCode resultCode = CheckNfcIsEnabled();
- if (resultCode != ResultCode.Success)
- {
- return resultCode;
- }
- uint deviceHandle = (uint)context.RequestData.ReadUInt64();
- if (context.Device.System.NfpDevices.Count == 0)
- {
- return ResultCode.DeviceNotFound;
- }
- uint applicationAreaId = context.RequestData.ReadUInt32();
- bool isOpened = false;
- for (int i = 0; i < context.Device.System.NfpDevices.Count; i++)
- {
- if (context.Device.System.NfpDevices[i].Handle == (PlayerIndex)deviceHandle)
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagRemoved)
- {
- resultCode = ResultCode.TagNotFound;
- }
- else
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagMounted)
- {
- isOpened = VirtualAmiibo.OpenApplicationArea(context.Device.System.NfpDevices[i].AmiiboId, applicationAreaId);
- resultCode = ResultCode.Success;
- }
- else
- {
- resultCode = ResultCode.WrongDeviceState;
- }
- }
- break;
- }
- }
- if (!isOpened)
- {
- resultCode = ResultCode.ApplicationAreaIsNull;
- }
- return resultCode;
- }
- [CommandHipc(8)]
- // GetApplicationArea(bytes<8, 4>) -> (u32, buffer<unknown, 6>)
- public ResultCode GetApplicationArea(ServiceCtx context)
- {
- ResultCode resultCode = CheckNfcIsEnabled();
- if (resultCode != ResultCode.Success)
- {
- return resultCode;
- }
- uint deviceHandle = (uint)context.RequestData.ReadUInt64();
- if (context.Device.System.NfpDevices.Count == 0)
- {
- return ResultCode.DeviceNotFound;
- }
- ulong outputPosition = context.Request.ReceiveBuff[0].Position;
- ulong outputSize = context.Request.ReceiveBuff[0].Size;
- MemoryHelper.FillWithZeros(context.Memory, outputPosition, (int)outputSize);
- uint size = 0;
- for (int i = 0; i < context.Device.System.NfpDevices.Count; i++)
- {
- if (context.Device.System.NfpDevices[i].Handle == (PlayerIndex)deviceHandle)
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagRemoved)
- {
- resultCode = ResultCode.TagNotFound;
- }
- else
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagMounted)
- {
- byte[] applicationArea = VirtualAmiibo.GetApplicationArea(context.Device.System.NfpDevices[i].AmiiboId);
- context.Memory.Write(outputPosition, applicationArea);
- size = (uint)applicationArea.Length;
- resultCode = ResultCode.Success;
- }
- else
- {
- resultCode = ResultCode.WrongDeviceState;
- }
- }
- }
- }
- if (resultCode != ResultCode.Success)
- {
- return resultCode;
- }
- if (size == 0)
- {
- return ResultCode.ApplicationAreaIsNull;
- }
- context.ResponseData.Write(size);
- return ResultCode.Success;
- }
- [CommandHipc(9)]
- // SetApplicationArea(bytes<8, 4>, buffer<unknown, 5>)
- public ResultCode SetApplicationArea(ServiceCtx context)
- {
- ResultCode resultCode = CheckNfcIsEnabled();
- if (resultCode != ResultCode.Success)
- {
- return resultCode;
- }
- uint deviceHandle = (uint)context.RequestData.ReadUInt64();
- if (context.Device.System.NfpDevices.Count == 0)
- {
- return ResultCode.DeviceNotFound;
- }
- ulong inputPosition = context.Request.SendBuff[0].Position;
- ulong inputSize = context.Request.SendBuff[0].Size;
- byte[] applicationArea = new byte[inputSize];
- context.Memory.Read(inputPosition, applicationArea);
- for (int i = 0; i < context.Device.System.NfpDevices.Count; i++)
- {
- if (context.Device.System.NfpDevices[i].Handle == (PlayerIndex)deviceHandle)
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagRemoved)
- {
- resultCode = ResultCode.TagNotFound;
- }
- else
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagMounted)
- {
- VirtualAmiibo.SetApplicationArea(context.Device.System.NfpDevices[i].AmiiboId, applicationArea);
- resultCode = ResultCode.Success;
- }
- else
- {
- resultCode = ResultCode.WrongDeviceState;
- }
- }
- break;
- }
- }
- return resultCode;
- }
- [CommandHipc(10)]
- // Flush(bytes<8, 4>)
- public ResultCode Flush(ServiceCtx context)
- {
- uint deviceHandle = (uint)context.RequestData.ReadUInt64();
- if (context.Device.System.NfpDevices.Count == 0)
- {
- return ResultCode.DeviceNotFound;
- }
- // NOTE: Since we handle amiibo through VirtualAmiibo, we don't have to flush anything in our case.
- return ResultCode.Success;
- }
- [CommandHipc(11)]
- // Restore(bytes<8, 4>)
- public ResultCode Restore(ServiceCtx context)
- {
- throw new ServiceNotImplementedException(this, context);
- }
- [CommandHipc(12)]
- // CreateApplicationArea(bytes<8, 4>, u32, buffer<unknown, 5>)
- public ResultCode CreateApplicationArea(ServiceCtx context)
- {
- ResultCode resultCode = CheckNfcIsEnabled();
- if (resultCode != ResultCode.Success)
- {
- return resultCode;
- }
- uint deviceHandle = (uint)context.RequestData.ReadUInt64();
- if (context.Device.System.NfpDevices.Count == 0)
- {
- return ResultCode.DeviceNotFound;
- }
- uint applicationAreaId = context.RequestData.ReadUInt32();
- ulong inputPosition = context.Request.SendBuff[0].Position;
- ulong inputSize = context.Request.SendBuff[0].Size;
- byte[] applicationArea = new byte[inputSize];
- context.Memory.Read(inputPosition, applicationArea);
- bool isCreated = false;
- for (int i = 0; i < context.Device.System.NfpDevices.Count; i++)
- {
- if (context.Device.System.NfpDevices[i].Handle == (PlayerIndex)deviceHandle)
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagRemoved)
- {
- resultCode = ResultCode.TagNotFound;
- }
- else
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagMounted)
- {
- isCreated = VirtualAmiibo.CreateApplicationArea(context.Device.System.NfpDevices[i].AmiiboId, applicationAreaId, applicationArea);
- resultCode = ResultCode.Success;
- }
- else
- {
- resultCode = ResultCode.WrongDeviceState;
- }
- }
- break;
- }
- }
- if (!isCreated)
- {
- resultCode = ResultCode.ApplicationAreaIsNull;
- }
- return resultCode;
- }
- [CommandHipc(13)]
- // GetTagInfo(bytes<8, 4>) -> buffer<unknown<0x58>, 0x1a>
- public ResultCode GetTagInfo(ServiceCtx context)
- {
- ResultCode resultCode = CheckNfcIsEnabled();
- if (resultCode != ResultCode.Success)
- {
- return resultCode;
- }
- if (context.Request.RecvListBuff.Count == 0)
- {
- return ResultCode.WrongArgument;
- }
- ulong outputPosition = context.Request.RecvListBuff[0].Position;
- context.Response.PtrBuff[0] = context.Response.PtrBuff[0].WithSize((uint)Marshal.SizeOf(typeof(TagInfo)));
- MemoryHelper.FillWithZeros(context.Memory, outputPosition, Marshal.SizeOf(typeof(TagInfo)));
- uint deviceHandle = (uint)context.RequestData.ReadUInt64();
- if (context.Device.System.NfpDevices.Count == 0)
- {
- return ResultCode.DeviceNotFound;
- }
- for (int i = 0; i < context.Device.System.NfpDevices.Count; i++)
- {
- if (context.Device.System.NfpDevices[i].Handle == (PlayerIndex)deviceHandle)
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagRemoved)
- {
- resultCode = ResultCode.TagNotFound;
- }
- else
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagMounted || context.Device.System.NfpDevices[i].State == NfpDeviceState.TagFound)
- {
- byte[] Uuid = VirtualAmiibo.GenerateUuid(context.Device.System.NfpDevices[i].AmiiboId, context.Device.System.NfpDevices[i].UseRandomUuid);
- if (Uuid.Length > AmiiboConstants.UuidMaxLength)
- {
- throw new ArgumentOutOfRangeException();
- }
- TagInfo tagInfo = new TagInfo
- {
- UuidLength = (byte)Uuid.Length,
- Reserved1 = new Array21<byte>(),
- Protocol = uint.MaxValue, // All Protocol
- TagType = uint.MaxValue, // All Type
- Reserved2 = new Array6<byte>()
- };
- Uuid.CopyTo(tagInfo.Uuid.AsSpan());
- context.Memory.Write(outputPosition, tagInfo);
- resultCode = ResultCode.Success;
- }
- else
- {
- resultCode = ResultCode.WrongDeviceState;
- }
- }
- break;
- }
- }
- return resultCode;
- }
- [CommandHipc(14)]
- // GetRegisterInfo(bytes<8, 4>) -> buffer<unknown<0x100>, 0x1a>
- public ResultCode GetRegisterInfo(ServiceCtx context)
- {
- ResultCode resultCode = CheckNfcIsEnabled();
- if (resultCode != ResultCode.Success)
- {
- return resultCode;
- }
- if (context.Request.RecvListBuff.Count == 0)
- {
- return ResultCode.WrongArgument;
- }
- ulong outputPosition = context.Request.RecvListBuff[0].Position;
- context.Response.PtrBuff[0] = context.Response.PtrBuff[0].WithSize((uint)Marshal.SizeOf(typeof(RegisterInfo)));
- MemoryHelper.FillWithZeros(context.Memory, outputPosition, Marshal.SizeOf(typeof(RegisterInfo)));
- uint deviceHandle = (uint)context.RequestData.ReadUInt64();
- if (context.Device.System.NfpDevices.Count == 0)
- {
- return ResultCode.DeviceNotFound;
- }
- for (int i = 0; i < context.Device.System.NfpDevices.Count; i++)
- {
- if (context.Device.System.NfpDevices[i].Handle == (PlayerIndex)deviceHandle)
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagRemoved)
- {
- resultCode = ResultCode.TagNotFound;
- }
- else
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagMounted)
- {
- RegisterInfo registerInfo = VirtualAmiibo.GetRegisterInfo(
- context.Device.System.TickSource,
- context.Device.System.NfpDevices[i].AmiiboId,
- context.Device.System.AccountManager.LastOpenedUser.Name);
- context.Memory.Write(outputPosition, registerInfo);
- resultCode = ResultCode.Success;
- }
- else
- {
- resultCode = ResultCode.WrongDeviceState;
- }
- }
- break;
- }
- }
- return resultCode;
- }
- [CommandHipc(15)]
- // GetCommonInfo(bytes<8, 4>) -> buffer<unknown<0x40>, 0x1a>
- public ResultCode GetCommonInfo(ServiceCtx context)
- {
- ResultCode resultCode = CheckNfcIsEnabled();
- if (resultCode != ResultCode.Success)
- {
- return resultCode;
- }
- if (context.Request.RecvListBuff.Count == 0)
- {
- return ResultCode.WrongArgument;
- }
- ulong outputPosition = context.Request.RecvListBuff[0].Position;
- context.Response.PtrBuff[0] = context.Response.PtrBuff[0].WithSize((uint)Marshal.SizeOf(typeof(CommonInfo)));
- MemoryHelper.FillWithZeros(context.Memory, outputPosition, Marshal.SizeOf(typeof(CommonInfo)));
- uint deviceHandle = (uint)context.RequestData.ReadUInt64();
- if (context.Device.System.NfpDevices.Count == 0)
- {
- return ResultCode.DeviceNotFound;
- }
- for (int i = 0; i < context.Device.System.NfpDevices.Count; i++)
- {
- if (context.Device.System.NfpDevices[i].Handle == (PlayerIndex)deviceHandle)
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagRemoved)
- {
- resultCode = ResultCode.TagNotFound;
- }
- else
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagMounted)
- {
- CommonInfo commonInfo = VirtualAmiibo.GetCommonInfo(context.Device.System.NfpDevices[i].AmiiboId);
- context.Memory.Write(outputPosition, commonInfo);
- resultCode = ResultCode.Success;
- }
- else
- {
- resultCode = ResultCode.WrongDeviceState;
- }
- }
- break;
- }
- }
- return resultCode;
- }
- [CommandHipc(16)]
- // GetModelInfo(bytes<8, 4>) -> buffer<unknown<0x40>, 0x1a>
- public ResultCode GetModelInfo(ServiceCtx context)
- {
- ResultCode resultCode = CheckNfcIsEnabled();
- if (resultCode != ResultCode.Success)
- {
- return resultCode;
- }
- if (context.Request.RecvListBuff.Count == 0)
- {
- return ResultCode.WrongArgument;
- }
- ulong outputPosition = context.Request.RecvListBuff[0].Position;
- context.Response.PtrBuff[0] = context.Response.PtrBuff[0].WithSize((uint)Marshal.SizeOf(typeof(ModelInfo)));
- MemoryHelper.FillWithZeros(context.Memory, outputPosition, Marshal.SizeOf(typeof(ModelInfo)));
- uint deviceHandle = (uint)context.RequestData.ReadUInt64();
- if (context.Device.System.NfpDevices.Count == 0)
- {
- return ResultCode.DeviceNotFound;
- }
- for (int i = 0; i < context.Device.System.NfpDevices.Count; i++)
- {
- if (context.Device.System.NfpDevices[i].Handle == (PlayerIndex)deviceHandle)
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagRemoved)
- {
- resultCode = ResultCode.TagNotFound;
- }
- else
- {
- if (context.Device.System.NfpDevices[i].State == NfpDeviceState.TagMounted)
- {
- ModelInfo modelInfo = new ModelInfo
- {
- Reserved = new Array57<byte>()
- };
- modelInfo.CharacterId = BinaryPrimitives.ReverseEndianness(ushort.Parse(context.Device.System.NfpDevices[i].AmiiboId.Substring(0, 4), NumberStyles.HexNumber));
- modelInfo.CharacterVariant = byte.Parse(context.Device.System.NfpDevices[i].AmiiboId.Substring(4, 2), NumberStyles.HexNumber);
- modelInfo.Series = byte.Parse(context.Device.System.NfpDevices[i].AmiiboId.Substring(12, 2), NumberStyles.HexNumber);
- modelInfo.ModelNumber = ushort.Parse(context.Device.System.NfpDevices[i].AmiiboId.Substring(8, 4), NumberStyles.HexNumber);
- modelInfo.Type = byte.Parse(context.Device.System.NfpDevices[i].AmiiboId.Substring(6, 2), NumberStyles.HexNumber);
- context.Memory.Write(outputPosition, modelInfo);
- resultCode = ResultCode.Success;
- }
- else
- {
- resultCode = ResultCode.WrongDeviceState;
- }
- }
- break;
- }
- }
- return resultCode;
- }
- [CommandHipc(17)]
- // AttachActivateEvent(bytes<8, 4>) -> handle<copy>
- public ResultCode AttachActivateEvent(ServiceCtx context)
- {
- uint deviceHandle = context.RequestData.ReadUInt32();
- for (int i = 0; i < context.Device.System.NfpDevices.Count; i++)
- {
- if ((uint)context.Device.System.NfpDevices[i].Handle == deviceHandle)
- {
- context.Device.System.NfpDevices[i].ActivateEvent = new KEvent(context.Device.System.KernelContext);
- if (context.Process.HandleTable.GenerateHandle(context.Device.System.NfpDevices[i].ActivateEvent.ReadableEvent, out int activateEventHandle) != KernelResult.Success)
- {
- throw new InvalidOperationException("Out of handles!");
- }
- context.Response.HandleDesc = IpcHandleDesc.MakeCopy(activateEventHandle);
- return ResultCode.Success;
- }
- }
- return ResultCode.DeviceNotFound;
- }
- [CommandHipc(18)]
- // AttachDeactivateEvent(bytes<8, 4>) -> handle<copy>
- public ResultCode AttachDeactivateEvent(ServiceCtx context)
- {
- uint deviceHandle = context.RequestData.ReadUInt32();
- for (int i = 0; i < context.Device.System.NfpDevices.Count; i++)
- {
- if ((uint)context.Device.System.NfpDevices[i].Handle == deviceHandle)
- {
- context.Device.System.NfpDevices[i].DeactivateEvent = new KEvent(context.Device.System.KernelContext);
- if (context.Process.HandleTable.GenerateHandle(context.Device.System.NfpDevices[i].DeactivateEvent.ReadableEvent, out int deactivateEventHandle) != KernelResult.Success)
- {
- throw new InvalidOperationException("Out of handles!");
- }
- context.Response.HandleDesc = IpcHandleDesc.MakeCopy(deactivateEventHandle);
- return ResultCode.Success;
- }
- }
- return ResultCode.DeviceNotFound;
- }
- [CommandHipc(19)]
- // GetState() -> u32
- public ResultCode GetState(ServiceCtx context)
- {
- context.ResponseData.Write((int)_state);
- return ResultCode.Success;
- }
- [CommandHipc(20)]
- // GetDeviceState(bytes<8, 4>) -> u32
- public ResultCode GetDeviceState(ServiceCtx context)
- {
- uint deviceHandle = context.RequestData.ReadUInt32();
- for (int i = 0; i < context.Device.System.NfpDevices.Count; i++)
- {
- if ((uint)context.Device.System.NfpDevices[i].Handle == deviceHandle)
- {
- if (context.Device.System.NfpDevices[i].State > NfpDeviceState.Finalized)
- {
- throw new ArgumentOutOfRangeException();
- }
- context.ResponseData.Write((uint)context.Device.System.NfpDevices[i].State);
- return ResultCode.Success;
- }
- }
- context.ResponseData.Write((uint)NfpDeviceState.Unavailable);
- return ResultCode.DeviceNotFound;
- }
- [CommandHipc(21)]
- // GetNpadId(bytes<8, 4>) -> u32
- public ResultCode GetNpadId(ServiceCtx context)
- {
- uint deviceHandle = context.RequestData.ReadUInt32();
- for (int i = 0; i < context.Device.System.NfpDevices.Count; i++)
- {
- if ((uint)context.Device.System.NfpDevices[i].Handle == deviceHandle)
- {
- context.ResponseData.Write((uint)HidUtils.GetNpadIdTypeFromIndex(context.Device.System.NfpDevices[i].Handle));
- return ResultCode.Success;
- }
- }
- return ResultCode.DeviceNotFound;
- }
- [CommandHipc(22)]
- // GetApplicationAreaSize() -> u32
- public ResultCode GetApplicationAreaSize(ServiceCtx context)
- {
- context.ResponseData.Write(AmiiboConstants.ApplicationAreaSize);
- return ResultCode.Success;
- }
- [CommandHipc(23)] // 3.0.0+
- // AttachAvailabilityChangeEvent() -> handle<copy>
- public ResultCode AttachAvailabilityChangeEvent(ServiceCtx context)
- {
- _availabilityChangeEvent = new KEvent(context.Device.System.KernelContext);
- if (context.Process.HandleTable.GenerateHandle(_availabilityChangeEvent.ReadableEvent, out int availabilityChangeEventHandle) != KernelResult.Success)
- {
- throw new InvalidOperationException("Out of handles!");
- }
- context.Response.HandleDesc = IpcHandleDesc.MakeCopy(availabilityChangeEventHandle);
- return ResultCode.Success;
- }
- [CommandHipc(24)] // 3.0.0+
- // RecreateApplicationArea(bytes<8, 4>, u32, buffer<unknown, 5>)
- public ResultCode RecreateApplicationArea(ServiceCtx context)
- {
- throw new ServiceNotImplementedException(this, context);
- }
- [CommandHipc(102)]
- // GetRegisterInfo2(bytes<8, 4>) -> buffer<unknown<0x100>, 0x1a>
- public ResultCode GetRegisterInfo2(ServiceCtx context)
- {
- // TODO: Find the differencies between IUser and ISystem/IDebug.
- if (_permissionLevel == NfpPermissionLevel.Debug || _permissionLevel == NfpPermissionLevel.System)
- {
- return GetRegisterInfo(context);
- }
- return ResultCode.DeviceNotFound;
- }
- private ResultCode CheckNfcIsEnabled()
- {
- // TODO: Call nn::settings::detail::GetNfcEnableFlag when it will be implemented.
- return true ? ResultCode.Success : ResultCode.NfcDisabled;
- }
- }
- }
|