| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997 |
- 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.ToSpan());
- 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.NfpDevices[i].AmiiboId);
- 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;
- }
- }
- }
|