Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds IPC mechanism #380

Merged
merged 140 commits into from
Oct 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
140 commits
Select commit Hold shift + click to select a range
eff4fc5
Adding memory mapped file IPC mechanism
nefarius Aug 11, 2024
e1baa67
IPC test success
nefarius Aug 11, 2024
570992c
Added driver context for IPC
nefarius Aug 11, 2024
6579fe2
Added IPC clean-up
nefarius Aug 11, 2024
44261de
Update Driver.c
nefarius Aug 11, 2024
9d7fcb7
Code clean-up
nefarius Aug 11, 2024
e2ea4c5
Update IPC.c
nefarius Aug 11, 2024
3ce9f0e
Update dshidmini.sln.DotSettings
nefarius Aug 11, 2024
bbdecb2
Added sync mutext object
nefarius Aug 12, 2024
ef8b644
Update IPC.h
nefarius Aug 12, 2024
862a836
Added worker thread and sync
nefarius Aug 12, 2024
79a8420
Update IPC.c
nefarius Aug 12, 2024
cb4e390
Update IPC.c
nefarius Aug 12, 2024
90ac719
Update IPC.c
nefarius Aug 12, 2024
9cf5236
Update IPC.c
nefarius Aug 12, 2024
208f9bf
Added IPC types
nefarius Aug 12, 2024
e60ac77
Update IPC.c
nefarius Aug 12, 2024
21aa73f
More comments
nefarius Aug 13, 2024
3ef01ab
Added dispatcher function
nefarius Aug 13, 2024
843aaec
Update IPC.c
nefarius Aug 13, 2024
434d766
Added ipctest app
nefarius Aug 13, 2024
82527c7
Namespace fixes
nefarius Aug 13, 2024
4677c48
More IPC fun
nefarius Aug 13, 2024
8f7a3c2
More IPC implementation
nefarius Aug 13, 2024
353fa9e
Fixes
nefarius Aug 13, 2024
801f3ac
Ping implementation works
nefarius Aug 13, 2024
049ba60
Update DsHidMiniInterop.cs
nefarius Aug 13, 2024
189a81f
Project structure clean-up
nefarius Aug 13, 2024
5bdd1bb
Refined boundary checks
nefarius Aug 13, 2024
dde100b
Bugfixes
nefarius Aug 13, 2024
af8fdc3
Update DsHidMiniInterop.cs
nefarius Aug 13, 2024
f2e6f25
Added API docs
nefarius Aug 13, 2024
9eb6388
Shortened timeout
nefarius Aug 13, 2024
dd72d7e
Update DsHidMiniInterop.cs
nefarius Aug 13, 2024
246e3e8
Added multi-threading protection
nefarius Aug 13, 2024
d8de67e
Update DsHidMiniInterop.cs
nefarius Aug 13, 2024
8417146
Added device slots to context
nefarius Aug 14, 2024
a9dfdbb
Added slots assignment
nefarius Aug 14, 2024
3213181
Implemented per device message dispatcher
nefarius Aug 14, 2024
274d937
Update DsHidMiniInterop.cs
nefarius Aug 14, 2024
c3ba7be
Finished pairing command skeleton
nefarius Aug 14, 2024
427bb53
Logging improvements
nefarius Aug 14, 2024
f4be330
Source clean-up
nefarius Aug 14, 2024
2c994b9
Update IPC.Device.c
nefarius Aug 14, 2024
e5a3b08
Added API docs
nefarius Aug 14, 2024
0a68f5f
Implemented DSHM_IPC_MSG_CMD_DEVICE_PAIR_TO via IPC
nefarius Aug 14, 2024
9b722b1
New IPC based pairing works
nefarius Aug 14, 2024
404b408
Added docs
nefarius Aug 14, 2024
194e0b6
Minor fixes
nefarius Aug 14, 2024
88be487
Added DsHidMiniInteropInvalidDeviceIndexException
nefarius Aug 14, 2024
919ea04
Update Program.cs
nefarius Aug 14, 2024
ff21dd2
Update DsHidMiniInterop.cs
nefarius Aug 14, 2024
dad620a
Update IPC.c
nefarius Aug 14, 2024
1f6ab5d
Update IPC.c
nefarius Aug 14, 2024
add9623
Update IPC.c
nefarius Aug 14, 2024
61975de
Update IPC.c
nefarius Aug 14, 2024
3866665
Code simplification
nefarius Aug 14, 2024
f7c9056
Added DSHM_IPC_MSG_CMD_DEVICE_SET_PLAYER_INDEX
nefarius Aug 14, 2024
a85bae7
Added SET_PLAYER_INDEX types
nefarius Aug 14, 2024
82476b4
Update appveyor.yml
nefarius Aug 14, 2024
67c4914
Fixed ARM64 build warnings
nefarius Aug 14, 2024
226c9ee
Update appveyor.yml
nefarius Aug 14, 2024
c5d891a
Update appveyor.yml
nefarius Aug 14, 2024
8a6049e
Update appveyor.yml
nefarius Aug 14, 2024
2f77788
Update appveyor.yml
nefarius Aug 14, 2024
cdb6f6e
Moved models to class library
nefarius Aug 15, 2024
7207f9d
Removed obsolete build logic
nefarius Aug 15, 2024
965857c
Update Directory.Build.props
nefarius Aug 15, 2024
f1b3ea8
Adding support for multiple shared regions
nefarius Aug 15, 2024
ce9dc0b
Synced driver and SDK code
nefarius Aug 15, 2024
5ac93c9
Improved locking logic
nefarius Aug 15, 2024
34e588a
Fixed issue with None address in SetHostAddress
nefarius Aug 15, 2024
9e89c42
Update DsHidMiniInterop.cs
nefarius Aug 15, 2024
c1944a7
Renamed mutex
nefarius Aug 15, 2024
d40b3e2
Bugfix
nefarius Aug 15, 2024
61c02b5
Added copying raw input report to shared memory region
nefarius Aug 15, 2024
237cce7
Added GetRawInputReport
nefarius Aug 15, 2024
23aff90
Fixed offsets
nefarius Aug 15, 2024
8eaccb8
Update DsHidMiniInterop.cs
nefarius Aug 15, 2024
ab49469
Adding input report event
nefarius Aug 15, 2024
e3ddb7f
Input report reading performance fixes
nefarius Aug 16, 2024
432239c
Create README.md
nefarius Aug 16, 2024
a737624
Implemented HID IPC clean-up
nefarius Aug 16, 2024
e87c3ca
Added auto-generated docs
nefarius Aug 16, 2024
388b898
Updated summary
nefarius Aug 16, 2024
a55ec84
Split class
nefarius Aug 16, 2024
a52584b
Update nefarius.dshidmini.ipc.dshidminiinterop.md
nefarius Aug 16, 2024
0f5b6f9
Update DsHidMiniInterop.Commands.cs
nefarius Aug 16, 2024
7ee2953
Update DsHidMiniInterop.cs
nefarius Aug 16, 2024
4429909
Updated docs
nefarius Aug 16, 2024
c7b64a4
Update DsHidMiniInterop.cs
nefarius Aug 16, 2024
145d10f
Added more missing API docs
nefarius Aug 16, 2024
e7044af
Update RawInputReport.cs
nefarius Aug 16, 2024
36bfe81
Update README.md
nefarius Aug 16, 2024
e9cdcb1
Updated report API
nefarius Aug 16, 2024
33e7e73
Update Program.cs
nefarius Aug 16, 2024
6ae515f
Updated API docs
nefarius Aug 16, 2024
75d2b43
Update DsHidMiniInterop.Commands.cs
nefarius Aug 16, 2024
f2b40be
Update Directory.Build.props
nefarius Aug 16, 2024
3b13905
Update Directory.Build.props
nefarius Aug 16, 2024
4974651
Update Directory.Build.props
nefarius Aug 16, 2024
ef61e10
Update Directory.Build.props
nefarius Aug 16, 2024
48bf19c
Update Directory.Build.props
nefarius Aug 16, 2024
b706ed2
Removed unused exception
nefarius Aug 16, 2024
80e6431
Update Exceptions.cs
nefarius Aug 16, 2024
e09a1c7
Copied some shared types
nefarius Aug 17, 2024
95b59a0
Update DsHidMiniDriver.cs
nefarius Aug 17, 2024
e8b12b0
Update DsHidMiniDriver.cs
nefarius Aug 17, 2024
7ddb74c
Updated API docs
nefarius Aug 17, 2024
4ed0d46
Reworking connection state machine
nefarius Aug 17, 2024
4701c2b
Update DsHidMiniInterop.cs
nefarius Aug 17, 2024
27a251a
Minor version bump
nefarius Aug 17, 2024
407818e
IPC bugfixes
nefarius Aug 17, 2024
19e087d
Improving pointer shenanigans
nefarius Aug 17, 2024
f4f7de2
Removed structure packing
nefarius Aug 17, 2024
29136b8
Update README.md
nefarius Aug 17, 2024
b1415b3
Update dshidmini_tvp.twx
nefarius Aug 17, 2024
b4e34b2
Introduced native WinAPIs
nefarius Aug 17, 2024
bad5f31
Alligned section sizes with page size
nefarius Aug 17, 2024
0a1dce4
Synced C# with C side
nefarius Aug 17, 2024
2155b21
Fixed shared memory alignment BS for good
nefarius Aug 17, 2024
35ca5e3
Cleaned up use of pointers
nefarius Aug 17, 2024
b2d3be8
Update DsHidMiniInterop.Commands.cs
nefarius Aug 17, 2024
aea9711
Overhauled exception handling
nefarius Aug 17, 2024
e639e89
More exceptions cleanup
nefarius Aug 17, 2024
e9e9a8d
Update Program.cs
nefarius Aug 17, 2024
0f2a6cc
Name consolidation
nefarius Aug 17, 2024
af1210a
Added WDF_USB_CONTROL_SETUP_PACKET
nefarius Aug 17, 2024
4e9d001
Merge branch 'master' into nefarius/experimental/ipc
nefarius Aug 23, 2024
6746624
Merge branch 'master' into nefarius/experimental/ipc
nefarius Aug 23, 2024
4baab5f
Bumped minor version
nefarius Aug 23, 2024
8fb104f
Merge branch 'master' into nefarius/experimental/ipc
nefarius Aug 25, 2024
f57b97f
Added more API docs
nefarius Aug 25, 2024
15ab34e
Merge branch 'master' into nefarius/experimental/ipc
nefarius Sep 23, 2024
8858fad
Merge branch 'master' into nefarius/experimental/ipc
nefarius Sep 23, 2024
aac6129
Fixed background image problem
nefarius Sep 23, 2024
a51dd59
Merge branch 'master' into nefarius/experimental/ipc
nefarius Sep 23, 2024
baba2ef
Merge branch 'master' into nefarius/experimental/ipc
nefarius Sep 24, 2024
e8c97bf
Merge branch 'master' into nefarius/experimental/ipc
nefarius Oct 19, 2024
9582445
Updated dependencies for build project
nefarius Oct 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions ControlApp/ControlApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@
<RootNamespace>Nefarius.DsHidMini.ControlApp</RootNamespace>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>3.0.0</Version>
<Authors>Kanuan, Nefarius</Authors>
<Copyright>Copyright (c) 2024 Nefarius Software Solutions e.U.</Copyright>
<Configurations>Debug;Release</Configurations>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
Expand Down
22 changes: 22 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project>

<PropertyGroup>
<!-- Copyright information -->
<Authors>Kanuan, Benjamin Höglinger-Stelzer</Authors>
<Copyright>Copyright © Nefarius Software Solutions e.U. 2022-2024</Copyright>

<!-- Common solution settings -->
<!--<OutputPath>$(SolutionDir)bin\</OutputPath>-->
<LangVersion>latest</LangVersion>

<!-- Suppress warnings if CI environment variable is set to true -->
<NoWarn Condition="'$(CI)' == 'True'">$(NoWarn),0219,1587,1591,8600,8601,8602,8603,8604,8618,8619,8622,8629,8765,8767</NoWarn>

<!-- Docs and symbols generation -->
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
</PropertyGroup>
</Project>
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ The following awesome resources have made this project possible.
- [linux/drivers/hid/hid-sony.c](https://github.com/torvalds/linux/blob/master/drivers/hid/hid-sony.c)
- [The HID Page](http://janaxelson.com/hidpage.htm)
- [CircumSpector/Research/Sony DualShock 3](https://github.com/CircumSpector/Research/tree/master/Sony%20DualShock%203)
- [Memory-Mapped Files and Overlaid Structs](https://blog.stephencleary.com/2023/09/memory-mapped-files-overlaid-structs.html)

### DevOps

Expand Down
305 changes: 305 additions & 0 deletions SDK/Nefarius.DsHidMini.IPC/DsHidMiniInterop.Commands.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,305 @@
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Net.NetworkInformation;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

using Nefarius.DsHidMini.IPC.Exceptions;
using Nefarius.DsHidMini.IPC.Models;
using Nefarius.DsHidMini.IPC.Models.Public;

namespace Nefarius.DsHidMini.IPC;

public partial class DsHidMiniInterop
{
/// <summary>
/// Attempts to read the <see cref="DS3_RAW_INPUT_REPORT" /> from a given device instance.
/// </summary>
/// <remarks>
/// If <paramref name="timeout" /> is null, this method returns the last known input report copy immediately. If
/// you use this call in a busy loop, you should set a timeout so this call becomes event-based, meaning the call will
/// only return when the driver signaled that new data is available, otherwise you will just burn through CPU for no
/// good reason. A new input report is typically available each average 5 milliseconds, depending on the connection
/// (wired or wireless) so a timeout of 20 milliseconds should be a good recommendation.
/// </remarks>
/// <param name="deviceIndex">The one-based device index.</param>
/// <param name="report">The <see cref="DS3_RAW_INPUT_REPORT" /> to populate.</param>
/// <param name="timeout">Optional timeout to wait for a report update to arrive. Default invocation returns immediately.</param>
/// <exception cref="DsHidMiniInteropAccessDeniedException">
/// Driver process interaction failed due to missing permissions;
/// this operation requires elevated privileges.
/// </exception>
/// <exception cref="DsHidMiniInteropUnexpectedReplyException">The driver returned unexpected or malformed data.</exception>
/// <exception cref="Win32Exception">Handle duplication failed.</exception>
/// <exception cref="DsHidMiniInteropReplyTimeoutException">The driver didn't respond within an expected period.</exception>
/// <exception cref="DsHidMiniInteropConcurrencyException">A different thread is currently performing a data exchange.</exception>
/// <exception cref="DsHidMiniInteropUnavailableException">
/// No driver instance is available. Make sure that at least one
/// device is connected and that the driver is installed and working properly. Call <see cref="IsAvailable" /> prior to
/// avoid this exception.
/// </exception>
/// <returns>
/// TRUE if <paramref name="report" /> got filled in or FALSE if the given <paramref name="deviceIndex" /> is not
/// occupied.
/// </returns>
[SuppressMessage("ReSharper", "UnusedMember.Global")]
public unsafe bool GetRawInputReport(int deviceIndex, ref DS3_RAW_INPUT_REPORT report, TimeSpan? timeout = null)
{
if (_hidView is null)
{
throw new DsHidMiniInteropUnavailableException();
}

ValidateDeviceIndex(deviceIndex);

ref IPC_HID_INPUT_REPORT_MESSAGE message = ref Unsafe.AsRef<IPC_HID_INPUT_REPORT_MESSAGE>(_hidView);

if (timeout.HasValue)
{
_inputReportEvent ??= GetHidReportWaitHandle(deviceIndex);

_inputReportEvent.WaitOne(timeout.Value);
}

//
// Device is/got disconnected
//
if (message.SlotIndex == 0)
{
return false;
}

//
// Index mismatch is not supposed to happen
//
if (message.SlotIndex != deviceIndex)
{
throw new DsHidMiniInteropUnexpectedReplyException();
}

report = message.InputReport;

return true;
}

/// <summary>
/// Send a PING to the driver and awaits the reply.
/// </summary>
/// <exception cref="DsHidMiniInteropUnavailableException">
/// Driver IPC unavailable, make sure that at least one compatible
/// controller is connected and operational.
/// </exception>
/// <exception cref="DsHidMiniInteropReplyTimeoutException">The driver didn't respond within an expected period.</exception>
/// <exception cref="DsHidMiniInteropUnexpectedReplyException">The driver returned unexpected or malformed data.</exception>
[SuppressMessage("ReSharper", "UnusedMember.Global")]
public unsafe void SendPing()
{
if (_commandMutex is null || _cmdView is null)
{
throw new DsHidMiniInteropUnavailableException();
}

AcquireCommandLock();

try
{
ref DSHM_IPC_MSG_HEADER message = ref Unsafe.AsRef<DSHM_IPC_MSG_HEADER>(_cmdView);

message.Type = DSHM_IPC_MSG_TYPE.DSHM_IPC_MSG_TYPE_REQUEST_RESPONSE;
message.Target = DSHM_IPC_MSG_TARGET.DSHM_IPC_MSG_TARGET_DRIVER;
message.Command.Driver = DSHM_IPC_MSG_CMD_DRIVER.DSHM_IPC_MSG_CMD_DRIVER_PING;
message.TargetIndex = 0;
message.Size = (uint)Marshal.SizeOf<DSHM_IPC_MSG_HEADER>();

if (!SendAndWait())
{
throw new DsHidMiniInteropReplyTimeoutException();
}

ref DSHM_IPC_MSG_HEADER reply = ref Unsafe.AsRef<DSHM_IPC_MSG_HEADER>(_cmdView);

//
// Plausibility check
//
if (reply is
{
Type: DSHM_IPC_MSG_TYPE.DSHM_IPC_MSG_TYPE_REQUEST_REPLY,
Target: DSHM_IPC_MSG_TARGET.DSHM_IPC_MSG_TARGET_CLIENT,
Command.Driver: DSHM_IPC_MSG_CMD_DRIVER.DSHM_IPC_MSG_CMD_DRIVER_PING, TargetIndex: 0
}
&& reply.Size == Marshal.SizeOf<DSHM_IPC_MSG_HEADER>())
{
return;
}

throw new DsHidMiniInteropUnexpectedReplyException(ref reply);
}
finally
{
_commandMutex.ReleaseMutex();
}
}

/// <summary>
/// Writes a new host address to the given device.
/// </summary>
/// <exception cref="DsHidMiniInteropUnavailableException">
/// Driver IPC unavailable, make sure that at least one compatible
/// controller is connected and operational.
/// </exception>
/// <returns>A <see cref="SetHostResult" /> containing success (or error) details.</returns>
/// <remarks>This is synonymous with "pairing" to a new Bluetooth host.</remarks>
/// <param name="deviceIndex">The one-based device index.</param>
/// <param name="hostAddress">The new host address.</param>
/// <exception cref="DsHidMiniInteropInvalidDeviceIndexException">
/// The <paramref name="deviceIndex" /> was outside a valid
/// range.
/// </exception>
/// <exception cref="DsHidMiniInteropConcurrencyException">A different thread is currently performing a data exchange.</exception>
/// <exception cref="DsHidMiniInteropReplyTimeoutException">The driver didn't respond within an expected period.</exception>
/// <exception cref="DsHidMiniInteropUnexpectedReplyException">The driver returned unexpected or malformed data.</exception>
[SuppressMessage("ReSharper", "UnusedMember.Global")]
public unsafe SetHostResult SetHostAddress(int deviceIndex, PhysicalAddress hostAddress)
{
if (_commandMutex is null || _cmdView is null)
{
throw new DsHidMiniInteropUnavailableException();
}

ValidateDeviceIndex(deviceIndex);

AcquireCommandLock();

try
{
ref DSHM_IPC_MSG_PAIR_TO_REQUEST request = ref Unsafe.AsRef<DSHM_IPC_MSG_PAIR_TO_REQUEST>(_cmdView);

request.Header.Type = DSHM_IPC_MSG_TYPE.DSHM_IPC_MSG_TYPE_REQUEST_RESPONSE;
request.Header.Target = DSHM_IPC_MSG_TARGET.DSHM_IPC_MSG_TARGET_DEVICE;
request.Header.Command.Device = DSHM_IPC_MSG_CMD_DEVICE.DSHM_IPC_MSG_CMD_DEVICE_PAIR_TO;
request.Header.TargetIndex = (uint)deviceIndex;
request.Header.Size = (uint)Marshal.SizeOf<DSHM_IPC_MSG_PAIR_TO_REQUEST>();

fixed (byte* source = hostAddress.GetAddressBytes())
fixed (byte* address = request.Address)
{
if (source is not null)
{
Buffer.MemoryCopy(source, address, 6, 6);
}
else
{
// there might be previous values there we need to zero out
Unsafe.InitBlockUnaligned(address, 0, 6);
}
}

if (!SendAndWait())
{
throw new DsHidMiniInteropReplyTimeoutException();
}

ref DSHM_IPC_MSG_PAIR_TO_REPLY reply = ref Unsafe.AsRef<DSHM_IPC_MSG_PAIR_TO_REPLY>(_cmdView);

//
// Plausibility check
//
if (reply.Header.Type == DSHM_IPC_MSG_TYPE.DSHM_IPC_MSG_TYPE_REQUEST_REPLY
&& reply.Header is
{
Target: DSHM_IPC_MSG_TARGET.DSHM_IPC_MSG_TARGET_CLIENT,
Command.Device: DSHM_IPC_MSG_CMD_DEVICE.DSHM_IPC_MSG_CMD_DEVICE_PAIR_TO
}
&& reply.Header.TargetIndex == deviceIndex
&& reply.Header.Size == Marshal.SizeOf<DSHM_IPC_MSG_PAIR_TO_REPLY>())
{
return new SetHostResult { WriteStatus = reply.WriteStatus, ReadStatus = reply.ReadStatus };
}

throw new DsHidMiniInteropUnexpectedReplyException(ref reply.Header);
}
finally
{
_commandMutex.ReleaseMutex();
}
}

/// <summary>
/// Overwrites the player slot indicator (player LEDs) of the given device.
/// </summary>
/// <param name="deviceIndex">The one-based device index.</param>
/// <param name="playerIndex">The player index to set to. Valid values include 1 to 7.</param>
/// <exception cref="DsHidMiniInteropUnavailableException">
/// Driver IPC unavailable, make sure that at least one compatible
/// controller is connected and operational.
/// </exception>
/// <returns></returns>
/// <exception cref="ArgumentOutOfRangeException">
/// The <paramref name="deviceIndex" /> or <paramref name="playerIndex" />
/// were out of range.
/// </exception>
/// <exception cref="DsHidMiniInteropConcurrencyException">A different thread is currently performing a data exchange.</exception>
/// <exception cref="DsHidMiniInteropReplyTimeoutException">The driver didn't respond within an expected period.</exception>
/// <exception cref="DsHidMiniInteropUnexpectedReplyException">The driver returned unexpected or malformed data.</exception>
[SuppressMessage("ReSharper", "UnusedMember.Global")]
public unsafe UInt32 SetPlayerIndex(int deviceIndex, byte playerIndex)
{
if (_commandMutex is null || _cmdView is null)
{
throw new DsHidMiniInteropUnavailableException();
}

ValidateDeviceIndex(deviceIndex);

if (playerIndex is < 1 or > 7)
{
throw new ArgumentOutOfRangeException(nameof(playerIndex),
"Player index must be between (including) 1 and 7.");
}

AcquireCommandLock();

try
{
ref DSHM_IPC_MSG_SET_PLAYER_INDEX_REQUEST request =
ref Unsafe.AsRef<DSHM_IPC_MSG_SET_PLAYER_INDEX_REQUEST>(_cmdView);

request.Header.Type = DSHM_IPC_MSG_TYPE.DSHM_IPC_MSG_TYPE_REQUEST_RESPONSE;
request.Header.Target = DSHM_IPC_MSG_TARGET.DSHM_IPC_MSG_TARGET_DEVICE;
request.Header.Command.Device = DSHM_IPC_MSG_CMD_DEVICE.DSHM_IPC_MSG_CMD_DEVICE_SET_PLAYER_INDEX;
request.Header.TargetIndex = (uint)deviceIndex;
request.Header.Size = (uint)Marshal.SizeOf<DSHM_IPC_MSG_SET_PLAYER_INDEX_REQUEST>();

request.PlayerIndex = playerIndex;

if (!SendAndWait())
{
throw new DsHidMiniInteropReplyTimeoutException();
}

ref DSHM_IPC_MSG_SET_PLAYER_INDEX_REPLY reply =
ref Unsafe.AsRef<DSHM_IPC_MSG_SET_PLAYER_INDEX_REPLY>(_cmdView);

//
// Plausibility check
//
if (reply.Header is
{
Type: DSHM_IPC_MSG_TYPE.DSHM_IPC_MSG_TYPE_REQUEST_REPLY,
Target: DSHM_IPC_MSG_TARGET.DSHM_IPC_MSG_TARGET_CLIENT,
Command.Device: DSHM_IPC_MSG_CMD_DEVICE.DSHM_IPC_MSG_CMD_DEVICE_SET_PLAYER_INDEX
}
&& reply.Header.TargetIndex == deviceIndex
&& reply.Header.Size == Marshal.SizeOf<DSHM_IPC_MSG_SET_PLAYER_INDEX_REPLY>())
{
return reply.NtStatus;
}

throw new DsHidMiniInteropUnexpectedReplyException(ref reply.Header);
}
finally
{
_commandMutex.ReleaseMutex();
}
}
}
Loading