├── EmuController ├── EmuController.rc ├── EmuController.inf ├── resource.h ├── NamedPipeServer.h ├── Driver.h ├── MessageProcessor.h ├── Queue.h ├── ReadMe.txt ├── Ioctl.h ├── Trace.h ├── Device.h ├── EmuController.vcxproj.filters ├── Driver.c ├── MessageProcessor.c └── Queue.c ├── SetupAPI.NET ├── SetupAPI.NET.csproj └── DeviceConfig.Native.cs ├── EmuController.Client.NET ├── EmuControllerException.cs ├── Input │ ├── IInputState.cs │ ├── UsageId.cs │ ├── MessageHeader.cs │ ├── ControlCollection.cs │ ├── DPads.cs │ ├── Buttons.cs │ ├── Axes.cs │ └── EmuControllerInputState.cs ├── PID │ ├── PIDStateFlags.cs │ ├── PIDSetGainReport.cs │ ├── PIDEffectTypeEnum.cs │ ├── PIDBlockFreeReport.cs │ ├── PIDBloadLoadReport.cs │ ├── FFBPacket.cs │ ├── PIDNewEffectReport.cs │ ├── PIDSetConstantForce.cs │ ├── PIDDownloadSampleReport.cs │ ├── PIDReportIdEnum.cs │ ├── PIDSetCustomForceReport.cs │ ├── PIDDeviceControlReport.cs │ ├── PIDSetRampReport.cs │ ├── PIDEffectOperationReport.cs │ ├── PIDSetCustomForceDataReport.cs │ ├── PIDSetPeriodicReport.cs │ ├── PIDSetEnvelopeReport.cs │ ├── PIDSetConditionReport.cs │ ├── PIDSetEffectReport.cs │ └── FFBDataReceivedEventArgs.cs ├── EmuController.Client.NET.csproj ├── WMIPnpEntity.cs ├── Utils.cs ├── Resources.Designer.cs ├── EmuControllerInfo.cs ├── Resources.resx └── EmuControllerClient.cs ├── EmuController.Client.NET.Demo ├── Program.cs ├── EmuController.Client.NET.Demo.csproj └── FeederReceptor.cs ├── EmuController.DevManager ├── AppSettings.xml ├── Start.xaml ├── Views │ ├── MainWindow.xaml │ ├── MainWindow.xaml.cs │ ├── SingleLineInputDialog.xaml │ ├── DeviceList.xaml │ ├── SingleLineInputDialog.xaml.cs │ └── DeviceList.xaml.cs ├── AssemblyInfo.cs ├── EmuController.DevManager.csproj ├── Commands │ ├── DeviceMenuCommand.cs │ └── DeviceCommand.cs ├── Start.xaml.cs ├── Behaviors │ └── MaxCharactersBehavior.cs ├── XmlSerializer.cs ├── Utils.cs ├── AppSettings.cs ├── WMIPnpEntity.cs ├── SingleInstanceApplicationLock.cs ├── app.manifest └── ViewModels │ └── EmuControllerDevice.cs ├── EmuController.sln.licenseheader ├── EmuController.Client.NETTests ├── Input │ ├── ControlCollectionTests.cs │ ├── ButtonsTests.cs │ └── EmuInputStateTests.cs └── EmuController.Client.NETTests.csproj ├── .gitattributes ├── EmuController.sln └── .gitignore /EmuController/EmuController.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FirstPlatoLV/EmuController/HEAD/EmuController/EmuController.rc -------------------------------------------------------------------------------- /EmuController/EmuController.inf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FirstPlatoLV/EmuController/HEAD/EmuController/EmuController.inf -------------------------------------------------------------------------------- /SetupAPI.NET/SetupAPI.NET.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | x64 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /EmuController.Client.NET/EmuControllerException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EmuController.Client.NET 6 | { 7 | class EmuControllerException : Exception 8 | { 9 | public EmuControllerException(string message) : base(message) 10 | { 11 | 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /EmuController.Client.NET/Input/IInputState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EmuController.Client.NET.Input 6 | { 7 | public interface IInputState 8 | { 9 | void CreateDefaultState(); 10 | byte[] GetStateUpdateMessage(); 11 | byte[] GetInputReportMessage(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /EmuController.Client.NET.Demo/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmuController.Client.NET.Demo 4 | { 5 | class Program 6 | { 7 | static void Main() 8 | { 9 | FeederReceptor feedReceive = new FeederReceptor(); 10 | feedReceive.Connect(); 11 | feedReceive.Feed(); 12 | Console.ReadLine(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /EmuController.DevManager/AppSettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | drv\ 4 | 5 | emucontroller.cat 6 | emucontroller.dll 7 | emucontroller.inf 8 | 9 | -------------------------------------------------------------------------------- /EmuController.Client.NET.Demo/EmuController.Client.NET.Demo.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net5.0-windows7.0 6 | x64;x86 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /EmuController/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by EmuController.rc 4 | // 5 | 6 | // Next default values for new objects 7 | // 8 | #ifdef APSTUDIO_INVOKED 9 | #ifndef APSTUDIO_READONLY_SYMBOLS 10 | #define _APS_NEXT_RESOURCE_VALUE 101 11 | #define _APS_NEXT_COMMAND_VALUE 40001 12 | #define _APS_NEXT_CONTROL_VALUE 1001 13 | #define _APS_NEXT_SYMED_VALUE 101 14 | #endif 15 | #endif 16 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/PIDStateFlags.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EmuController.Client.NET.PID 6 | { 7 | [Flags] 8 | public enum PIDStateFlags : byte 9 | { 10 | DevicePaused = 0x01, 11 | ActuatorsEnabled = 0x02, 12 | ActuatorsPowered = 0x10, 13 | Paused = DevicePaused | ActuatorsEnabled | ActuatorsPowered, 14 | Default = ActuatorsEnabled | ActuatorsPowered, 15 | Disabled = 0 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /EmuController.sln.licenseheader: -------------------------------------------------------------------------------- 1 | extensions: designer.cs generated.cs 2 | extensions: .cs .cpp .h .c 3 | // Copyright 2020 Maris Melbardis 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | extensions: .aspx .ascx 17 | <%-- 18 | Copyright (c) 2011 rubicon IT GmbH 19 | --%> 20 | extensions: .vb 21 | 'Sample license text. 22 | extensions: .xml .config .xsd 23 | -------------------------------------------------------------------------------- /EmuController.Client.NETTests/Input/ControlCollectionTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using EmuController.Client.NET.Input; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace EmuController.Client.NET.Input.Tests 8 | { 9 | [TestClass()] 10 | public class ControlCollectionTests 11 | { 12 | [TestMethod()] 13 | public void GetUpdatedValuesTest() 14 | { 15 | EmuControllerInputState emu = new EmuControllerInputState(); 16 | 17 | emu.Buttons.SetValue(0, true); 18 | emu.Buttons.SetValue(0, false); 19 | 20 | emu.Buttons.SetValue(8, true); 21 | 22 | emu.Buttons.SetValue(16, true); 23 | emu.Buttons.SetValue(16, false); 24 | 25 | ReadOnlySpan updatedButtons = emu.Buttons.GetUpdatedValues(); 26 | 27 | Assert.IsTrue(updatedButtons.Length == 2); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /EmuController.Client.NET/Input/UsageId.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Linq; 17 | using System.Text; 18 | using System.Threading.Tasks; 19 | 20 | namespace EmuController.Client.NET.Input 21 | { 22 | public enum UsageId : byte 23 | { 24 | Axis = 0x10, 25 | Button = 0x11, 26 | DPad = 0x12, 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /EmuController.DevManager/Start.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /EmuController.Client.NETTests/Input/ButtonsTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using EmuController.Client.NET.Input; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using Xunit.Sdk; 7 | using System.Security.Cryptography; 8 | 9 | namespace EmuController.Client.NET.Input.Tests 10 | { 11 | [TestClass()] 12 | public class ButtonsTests 13 | { 14 | [TestMethod()] 15 | public void SetValueTest() 16 | { 17 | EmuControllerInputState emu = new EmuControllerInputState(); 18 | 19 | Random rndVal = new Random(); 20 | 21 | for (int i = 0; i < emu.Buttons.AllValues.Length * sizeof(ushort); i++) 22 | { 23 | int index = rndVal.Next(0, emu.Buttons.AllValues.Length * sizeof(ushort)); 24 | emu.Buttons.SetValue(index, true); 25 | 26 | Assert.IsTrue(Utils.IsBitSet(emu.Buttons.AllValues[index / 16], index % 16)); 27 | 28 | emu.Buttons.SetValue(index, false); 29 | Assert.IsFalse(Utils.IsBitSet(emu.Buttons.AllValues[index / 16], index % 16)); 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /EmuController.Client.NET/Input/MessageHeader.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Linq; 17 | using System.Text; 18 | using System.Threading.Tasks; 19 | 20 | namespace EmuController.Client.NET.Input 21 | { 22 | class MessageHeader 23 | { 24 | public MessageType Type { get; set; } = MessageType.Input; 25 | public byte Length { get; set; } 26 | 27 | public enum MessageType 28 | { 29 | Input = 0x01, 30 | InputFull = 0x02, 31 | PID = 0x03, 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /EmuController.DevManager/Views/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 16 | 17 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/PIDSetGainReport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Linq; 17 | using System.Text; 18 | using System.Threading.Tasks; 19 | 20 | namespace EmuController.Client.NET.PID 21 | { 22 | public class PIDSetGainReport : FFBPacket 23 | { 24 | public ushort Gain { get; private set; } 25 | public PIDSetGainReport(byte[] packet): base(packet) 26 | { 27 | 28 | } 29 | 30 | protected override void Deserialize() 31 | { 32 | Gain = BitConverter.ToUInt16(DataPacket, 1); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/PIDEffectTypeEnum.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Linq; 17 | using System.Text; 18 | using System.Threading.Tasks; 19 | 20 | namespace EmuController.Client.NET.PID 21 | { 22 | public enum PIDEffectTypeEnum 23 | { 24 | Constant = 1, 25 | Ramp = 2, 26 | Square = 3, 27 | Sine = 4, 28 | Triangle = 5, 29 | SawtoothUp = 6, 30 | SawtoothDown = 7, 31 | Spring = 8, 32 | Damper = 9, 33 | Inertia = 10, 34 | Friction = 11, 35 | CustomForce = 12 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /EmuController.DevManager/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System.Windows; 15 | 16 | [assembly: ThemeInfo( 17 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 18 | //(used if a resource is not found in the page, 19 | // or application resource dictionaries) 20 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 21 | //(used if a resource is not found in the page, 22 | // app, or any theme specific resource dictionaries) 23 | )] 24 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/PIDBlockFreeReport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Collections.ObjectModel; 17 | using System.Linq; 18 | using System.Text; 19 | using System.Threading.Tasks; 20 | 21 | namespace EmuController.Client.NET.PID 22 | { 23 | public class PIDBlockFreeReport : FFBPacket 24 | { 25 | public byte FreeReportEffectBlockIndex { get; private set; } 26 | public PIDBlockFreeReport(byte[] packet): base(packet) 27 | { 28 | 29 | } 30 | 31 | protected override void Deserialize() 32 | { 33 | FreeReportEffectBlockIndex = DataPacket[1]; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/PIDBloadLoadReport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Collections.ObjectModel; 17 | using System.Linq; 18 | using System.Runtime.Serialization; 19 | using System.Text; 20 | using System.Threading.Tasks; 21 | 22 | namespace EmuController.Client.NET.PID 23 | { 24 | public class PIDBloadLoadReport : FFBPacket 25 | { 26 | public byte EffectBlockIndex { get; private set; } 27 | 28 | public PIDBloadLoadReport(byte[] packet): base(packet) 29 | { 30 | 31 | } 32 | 33 | protected override void Deserialize() 34 | { 35 | EffectBlockIndex = DataPacket[1]; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/FFBPacket.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Collections.ObjectModel; 17 | using System.Linq; 18 | using System.Runtime.Serialization; 19 | using System.Text; 20 | using System.Threading.Tasks; 21 | 22 | namespace EmuController.Client.NET.PID 23 | { 24 | public abstract class FFBPacket 25 | { 26 | public PIDReportIdEnum ReportId { get => (PIDReportIdEnum)DataPacket[0]; } 27 | 28 | protected byte[] DataPacket; 29 | 30 | public FFBPacket(byte[] packet) 31 | { 32 | DataPacket = packet; 33 | Deserialize(); 34 | } 35 | 36 | protected abstract void Deserialize(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /EmuController/NamedPipeServer.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #pragma once 15 | EXTERN_C_START 16 | 17 | 18 | #define BUFFER_SIZE 128 19 | #define INPUT_INSTANCES 128 20 | #define PID_INSTANCES 128 21 | 22 | DWORD 23 | CreateNamedPipeServer( 24 | LPVOID Params 25 | ); 26 | 27 | DWORD WINAPI 28 | InputPipeServerThread( 29 | LPVOID Params); 30 | 31 | DWORD WINAPI 32 | PidPipeServerThread( 33 | LPVOID Params); 34 | 35 | VOID 36 | WriteResponseToPidClient( 37 | PQUEUE_CONTEXT queueContext); 38 | 39 | VOID 40 | CompleteReadRequest( 41 | PDEVICE_CONTEXT devContext, 42 | UCHAR ReportId); 43 | 44 | BOOL 45 | CreatePipeSecurity( 46 | PSECURITY_ATTRIBUTES* pSecurityAttributes); 47 | 48 | VOID 49 | FreePipeSecurity( 50 | PSECURITY_ATTRIBUTES psa); 51 | 52 | EXTERN_C_END -------------------------------------------------------------------------------- /EmuController.DevManager/EmuController.DevManager.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net5.0-windows 6 | true 7 | x64 8 | app.manifest 9 | EmuController.DevManager.Start 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | PreserveNewest 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/PIDNewEffectReport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Collections.ObjectModel; 17 | using System.Linq; 18 | using System.Text; 19 | using System.Threading.Tasks; 20 | 21 | namespace EmuController.Client.NET.PID 22 | { 23 | public class PIDNewEffectReport : FFBPacket 24 | { 25 | public PIDEffectTypeEnum EffectType { get; private set; } 26 | public byte ByteCount { get; private set; } 27 | public PIDNewEffectReport(byte[] packet): base(packet) 28 | { 29 | 30 | } 31 | 32 | protected override void Deserialize() 33 | { 34 | EffectType = (PIDEffectTypeEnum)DataPacket[1]; 35 | ByteCount = DataPacket[2]; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/PIDSetConstantForce.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Collections.ObjectModel; 17 | using System.Linq; 18 | using System.Text; 19 | using System.Threading.Tasks; 20 | 21 | namespace EmuController.Client.NET.PID 22 | { 23 | public class PIDSetConstantForce : FFBPacket 24 | { 25 | public byte EffectBlockIndex { get; private set; } 26 | public short Magnitude { get; private set; } 27 | 28 | public PIDSetConstantForce(byte[] packet): base(packet) 29 | { 30 | 31 | 32 | } 33 | 34 | protected override void Deserialize() 35 | { 36 | EffectBlockIndex = DataPacket[1]; 37 | Magnitude = BitConverter.ToInt16(DataPacket, 2); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/PIDDownloadSampleReport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Collections.ObjectModel; 17 | using System.Linq; 18 | using System.Text; 19 | using System.Threading.Tasks; 20 | 21 | namespace EmuController.Client.NET.PID 22 | { 23 | public class PIDDownloadSampleReport : FFBPacket 24 | { 25 | public sbyte DownloadForceSampleX { get; private set; } 26 | public sbyte DownloadForceSampleY { get; private set; } 27 | public PIDDownloadSampleReport(byte[] packet): base(packet) 28 | { 29 | 30 | } 31 | 32 | protected override void Deserialize() 33 | { 34 | DownloadForceSampleX = (sbyte)DataPacket[1]; 35 | DownloadForceSampleY = (sbyte)DataPacket[2]; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /EmuController/Driver.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /*++ 16 | 17 | Module Name: 18 | 19 | driver.h 20 | 21 | Abstract: 22 | 23 | This file contains the driver definitions. 24 | 25 | Environment: 26 | 27 | User-mode Driver Framework 2 28 | 29 | --*/ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include "device.h" 40 | #include "queue.h" 41 | #include "ioctl.h" 42 | #include "namedpipeserver.h" 43 | #include "messageprocessor.h" 44 | #include "trace.h" 45 | 46 | EXTERN_C_START 47 | 48 | // 49 | // WDFDRIVER Events 50 | // 51 | 52 | DRIVER_INITIALIZE DriverEntry; 53 | EVT_WDF_DRIVER_DEVICE_ADD EmuControllerEvtDeviceAdd; 54 | EVT_WDF_OBJECT_CONTEXT_CLEANUP EmuControllerEvtDriverContextCleanup; 55 | 56 | EXTERN_C_END 57 | -------------------------------------------------------------------------------- /EmuController.DevManager/Commands/DeviceMenuCommand.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Text; 17 | using System.Windows.Input; 18 | 19 | namespace EmuController.DevManager.Commands 20 | { 21 | public class DeviceMenuCommand 22 | { 23 | public DeviceCommmandEnum CommandType { get; set; } 24 | public string CommandName { get => CommandType.ToString(); } 25 | public DeviceCommand Command { get; set; } 26 | 27 | public DeviceMenuCommand(DeviceCommmandEnum commandType, DeviceCommand command) 28 | { 29 | CommandType = commandType; 30 | Command = command; 31 | } 32 | } 33 | 34 | public enum DeviceCommmandEnum 35 | { 36 | Install, 37 | Rename, 38 | Uninstall, 39 | SetActive, 40 | Toggle 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/PIDReportIdEnum.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Linq; 17 | using System.Text; 18 | using System.Threading.Tasks; 19 | 20 | namespace EmuController.Client.NET.PID 21 | { 22 | public enum PIDReportIdEnum 23 | { 24 | // Output report Ids. 25 | SetEffect = 0x10, 26 | SetEnvelope = 0x11, 27 | SetCondition = 0x12, 28 | SetPeriodic = 0x13, 29 | SetConstant = 0x14, 30 | SetRamp = 0x15, 31 | SetCustomForceData = 0x16, 32 | DownloadSample = 0x17, 33 | EffectOperation = 0x18, 34 | DeviceControl = 0x19, 35 | BlockFree = 0x1A, 36 | SetGain = 0x1B, 37 | SetCustomForce = 0x1C, 38 | 39 | // Feature report Ids. 40 | NewEffect = 0x20, 41 | BlockLoad = 0x21, 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /EmuController/MessageProcessor.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | EXTERN_C_START 15 | 16 | // Control type ids in input report message 17 | #define INPUT_AXIS 0x10 18 | #define INPUT_BUTTON 0x11 19 | #define INPUT_DPAD 0x12 20 | 21 | // Maximum number of value updates in message for each control type 22 | #define AXIS_COUNT 8 23 | #define BUTTON_SET_COUNT 8 24 | #define DPAD_COUNT 4 25 | 26 | // 27 | // Checks if specified bit in UCHAR value is set. 28 | // 29 | BOOL 30 | IsBitSet( 31 | UCHAR Value, 32 | INT Bit); 33 | 34 | 35 | // 36 | // Deserializes joystick input report message received from named pipe client. 37 | // 38 | VOID 39 | DeserializeJoyInput( 40 | _In_ UCHAR* JoystickInputMessage, 41 | _Out_ JOYSTICK_INPUT_REPORT* Report); 42 | 43 | 44 | // 45 | // Sets the joystick input report to default values. 46 | // 47 | VOID 48 | SetDefaultControllerState( 49 | _Out_ JOYSTICK_INPUT_REPORT* Report); 50 | 51 | EXTERN_C_END -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/PIDSetCustomForceReport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Collections.ObjectModel; 17 | using System.Linq; 18 | using System.Text; 19 | using System.Threading.Tasks; 20 | 21 | namespace EmuController.Client.NET.PID 22 | { 23 | public class PIDSetCustomForceReport : FFBPacket 24 | { 25 | public byte EffectBlockIndex { get; private set; } 26 | public byte SampleCount { get; private set; } 27 | public ushort SamplePeriod { get; private set; } 28 | public PIDSetCustomForceReport(byte[] packet): base(packet) 29 | { 30 | 31 | } 32 | 33 | protected override void Deserialize() 34 | { 35 | EffectBlockIndex = DataPacket[1]; 36 | SampleCount = DataPacket[2]; 37 | SamplePeriod = BitConverter.ToUInt16(DataPacket, 3); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /EmuController.Client.NET/EmuController.Client.NET.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0-windows7.0 5 | 1.0.0.0 6 | 1.0.0.0 7 | Library for communicating with EmuController device 8 | (C) Maris Melbardis 2020 9 | 1.0.0 10 | true 11 | false 12 | x64;x86 13 | 14 | 15 | 16 | x64 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | True 28 | True 29 | Resources.resx 30 | 31 | 32 | 33 | 34 | 35 | ResXFileCodeGenerator 36 | Resources.Designer.cs 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /EmuController.Client.NET/WMIPnpEntity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Management; 4 | using System.Runtime.Versioning; 5 | using System.Text; 6 | 7 | namespace EmuController.Client.NET 8 | { 9 | public sealed class WMIPnpEntity 10 | { 11 | private static readonly string Scope = "root\\CIMV2"; 12 | private const string ClassGuid = "{4DB9B76D-4379-437E-9457-4F00B3090C1F}"; 13 | private readonly ManagementObjectSearcher Mos; 14 | private static readonly Lazy 15 | lazy = 16 | new Lazy 17 | (() => new WMIPnpEntity()); 18 | 19 | public static WMIPnpEntity Instance { get { return lazy.Value; } } 20 | 21 | private WMIPnpEntity() 22 | { 23 | string queryString = $"SELECT * FROM Win32_PnPEntity WHERE ClassGuid = '{ClassGuid}'"; 24 | Mos = new ManagementObjectSearcher(Scope, queryString); 25 | } 26 | 27 | public IList GetEmuControllers() 28 | { 29 | List devices = new List(); 30 | 31 | // All active EmuController devices will be returned when quering PnPEntities 32 | // matching EmuController classGuid. 33 | foreach (ManagementObject queryObj in Mos.Get()) 34 | { 35 | EmuControllerInfo info = new EmuControllerInfo(queryObj); 36 | devices.Add(info); 37 | } 38 | 39 | return devices; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/PIDDeviceControlReport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Collections.ObjectModel; 17 | using System.Linq; 18 | using System.Text; 19 | using System.Threading.Tasks; 20 | 21 | namespace EmuController.Client.NET.PID 22 | { 23 | public class PIDDeviceControlReport : FFBPacket 24 | { 25 | public DeviceControlEnum ControlCommand { get; private set; } 26 | 27 | public PIDDeviceControlReport(byte[] packet): base(packet) 28 | { 29 | 30 | } 31 | public enum DeviceControlEnum 32 | { 33 | EnableActuactors = 1, 34 | DisableActuactors = 2, 35 | StopAllEffects = 3, 36 | Reset = 4, 37 | Pause = 5, 38 | Continue = 6 39 | } 40 | 41 | protected override void Deserialize() 42 | { 43 | ControlCommand = (DeviceControlEnum)DataPacket[1]; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/PIDSetRampReport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Collections.ObjectModel; 17 | using System.Linq; 18 | using System.Runtime.InteropServices; 19 | using System.Text; 20 | using System.Threading.Tasks; 21 | 22 | namespace EmuController.Client.NET.PID 23 | { 24 | public class PIDSetRampReport : FFBPacket 25 | { 26 | public byte EffectBlockIndex { get; private set; } 27 | public short RampStart { get; private set; } 28 | public short RampEnd { get; private set; } 29 | 30 | public PIDSetRampReport(byte[] packet): base(packet) 31 | { 32 | 33 | } 34 | 35 | protected override void Deserialize() 36 | { 37 | EffectBlockIndex = DataPacket[1]; 38 | ReadOnlySpan packetSpan = MemoryMarshal.Cast(DataPacket); 39 | RampStart = packetSpan[1]; 40 | RampEnd = packetSpan[2]; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /EmuController.DevManager/Start.xaml.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Text; 17 | using System.Windows; 18 | using System.Windows.Controls; 19 | using System.Windows.Data; 20 | using System.Windows.Documents; 21 | using System.Windows.Input; 22 | using System.Windows.Media; 23 | using System.Windows.Media.Imaging; 24 | using System.Windows.Navigation; 25 | using System.Windows.Shapes; 26 | 27 | namespace EmuController.DevManager 28 | { 29 | /// 30 | /// Interaction logic for Start.xaml 31 | /// 32 | public partial class Start : Application 33 | { 34 | [STAThread] 35 | public static void Main() 36 | { 37 | using var appLock = new SingleInstanceApplicationLock(); 38 | if (!appLock.TryAcquireExclusiveLock()) 39 | return; 40 | 41 | Start app = new Start(); 42 | app.InitializeComponent(); 43 | app.Run(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /EmuController.Client.NET/Input/ControlCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | 4 | namespace EmuController.Client.NET.Input 5 | { 6 | public abstract class ControlCollection where T : IComparable, IComparable, IConvertible, IEquatable, IFormattable 7 | { 8 | protected readonly BitArray arrayMap = new BitArray(8); 9 | 10 | internal byte ArrayMap 11 | { 12 | get 13 | { 14 | byte[] b = new byte[1]; 15 | arrayMap.CopyTo(b, 0); 16 | return b[0]; 17 | } 18 | } 19 | 20 | private int setControls = 0; 21 | 22 | protected T[] values; 23 | public ReadOnlySpan AllValues => values; 24 | 25 | public ReadOnlySpan GetUpdatedValues() 26 | { 27 | if (setControls == 0) 28 | { 29 | return null; 30 | } 31 | 32 | T[] results = new T[setControls]; 33 | int index = 0; 34 | for (int i = 0; i < arrayMap.Count; i++) 35 | { 36 | if (arrayMap[i]) 37 | { 38 | results[index] = values[i]; 39 | index++; 40 | } 41 | } 42 | return results; 43 | 44 | } 45 | 46 | protected void SetValue(int index, T value) 47 | { 48 | if (!arrayMap.Get(index)) 49 | { 50 | setControls++; 51 | } 52 | arrayMap.Set(index, true); 53 | values[index] = value; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /EmuController/Queue.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /*++ 16 | 17 | Module Name: 18 | 19 | queue.h 20 | 21 | Abstract: 22 | 23 | This file contains the queue definitions. 24 | 25 | Environment: 26 | 27 | User-mode Driver Framework 2 28 | 29 | --*/ 30 | 31 | EXTERN_C_START 32 | 33 | // 34 | // This is the context that can be placed per queue 35 | // and would contain per queue information. 36 | // 37 | typedef struct _QUEUE_CONTEXT { 38 | 39 | WDFQUEUE Queue; 40 | PDEVICE_CONTEXT DeviceContext; 41 | 42 | } QUEUE_CONTEXT, *PQUEUE_CONTEXT; 43 | 44 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(QUEUE_CONTEXT, QueueGetContext) 45 | 46 | NTSTATUS 47 | EmuControllerQueueInitialize( 48 | _In_ WDFDEVICE Device, 49 | _Out_ WDFQUEUE *Queue 50 | ); 51 | 52 | NTSTATUS 53 | EmuControllerManualQueueInitialize( 54 | _In_ WDFDEVICE Device, 55 | _Out_ WDFQUEUE* Queue 56 | ); 57 | 58 | // 59 | // Events from the IoQueue object 60 | // 61 | EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL EmuControllerEvtIoDeviceControl; 62 | 63 | EXTERN_C_END 64 | -------------------------------------------------------------------------------- /EmuController.Client.NETTests/EmuController.Client.NETTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0-windows7.0 5 | 6 | false 7 | 8 | x64;x86 9 | 10 | 11 | 12 | x64 13 | 14 | 15 | 16 | x64 17 | 18 | 19 | 20 | x64 21 | 22 | 23 | 24 | x64 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | all 33 | runtime; build; native; contentfiles; analyzers; buildtransitive 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/PIDEffectOperationReport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Collections.ObjectModel; 17 | using System.Linq; 18 | using System.Text; 19 | using System.Threading.Tasks; 20 | 21 | namespace EmuController.Client.NET.PID 22 | { 23 | public class PIDEffectOperationReport : FFBPacket 24 | { 25 | public byte EffectBlockIndex { get; private set; } 26 | public EffectOpEnum EffectOperation { get; private set; } 27 | public byte LoopCount { get; private set; } 28 | 29 | 30 | public PIDEffectOperationReport(byte[] packet): base(packet) 31 | { 32 | 33 | } 34 | 35 | protected override void Deserialize() 36 | { 37 | EffectBlockIndex = DataPacket[1]; 38 | EffectOperation = (EffectOpEnum)DataPacket[2]; 39 | LoopCount = DataPacket[3]; 40 | } 41 | } 42 | public enum EffectOpEnum 43 | { 44 | Start = 1, 45 | StartSolo = 2, 46 | Stop = 3 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /EmuController.DevManager/Behaviors/MaxCharactersBehavior.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using Microsoft.Xaml.Behaviors; 15 | using System; 16 | using System.Collections.Generic; 17 | using System.Text; 18 | using System.Windows; 19 | using System.Windows.Input; 20 | 21 | namespace EmuController.DevManager.Behaviors 22 | { 23 | public class MaxCharactersBehavior : Behavior 24 | { 25 | public int MaxCharacters { get; set; } 26 | 27 | protected override void OnAttached() 28 | { 29 | base.OnAttached(); 30 | AssociatedObject.PreviewTextInput += AssociatedObject_PreviewTextInput; 31 | } 32 | 33 | protected override void OnDetaching() 34 | { 35 | base.OnDetaching(); 36 | AssociatedObject.PreviewTextInput -= AssociatedObject_PreviewTextInput; 37 | } 38 | 39 | private void AssociatedObject_PreviewTextInput(object sender, TextCompositionEventArgs e) 40 | { 41 | e.Handled = ((System.Windows.Controls.TextBox)e.OriginalSource).Text.Length >= MaxCharacters; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/PIDSetCustomForceDataReport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Collections.ObjectModel; 17 | using System.Linq; 18 | using System.Text; 19 | using System.Threading.Tasks; 20 | 21 | namespace EmuController.Client.NET.PID 22 | { 23 | public class PIDSetCustomForceDataReport : FFBPacket 24 | { 25 | private const int DataLength = 12; 26 | public byte EffectBlockIndex { get; private set; } 27 | public ushort DataOffset { get; private set; } 28 | 29 | public ReadOnlyCollection Data => new ReadOnlyCollection(data); 30 | 31 | private byte[] data; 32 | public PIDSetCustomForceDataReport(byte[] packet): base(packet) 33 | { 34 | 35 | } 36 | 37 | protected override void Deserialize() 38 | { 39 | EffectBlockIndex = DataPacket[1]; 40 | DataOffset = BitConverter.ToUInt16(DataPacket, 2); 41 | 42 | ReadOnlySpan packetSpan = DataPacket; 43 | data = packetSpan[4..].ToArray(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /EmuController.Client.NET/Input/DPads.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System.Linq; 15 | 16 | namespace EmuController.Client.NET.Input 17 | { 18 | public class DPads : ControlCollection 19 | { 20 | internal DPads() 21 | { 22 | values = Enumerable.Repeat((byte)0xFF, 4).ToArray(); 23 | } 24 | 25 | /// 26 | /// Set value for DPad with the specified index. 27 | /// 28 | /// Index of the DPad 29 | /// Cardinal Direction 30 | public void SetValue(int index, DPadDirectionEnum direction) 31 | { 32 | SetValue(index, (byte)direction); 33 | } 34 | } 35 | 36 | /// 37 | /// DPad values expressed as Cardinal directions 38 | /// 39 | public enum DPadDirectionEnum 40 | { 41 | Null = -1, 42 | North = 0, 43 | NorthEast = 1, 44 | East = 2, 45 | SouthEast = 3, 46 | South = 4, 47 | SouthWest = 5, 48 | West = 6, 49 | NorthWest = 7 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /EmuController.DevManager/XmlSerializer.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.IO; 17 | using System.Text; 18 | using System.Xml.Serialization; 19 | 20 | namespace EmuController.DevManager 21 | { 22 | public class XmlSerializer 23 | { 24 | private readonly Type type; 25 | 26 | public XmlSerializer() 27 | { 28 | type = typeof(T); 29 | } 30 | 31 | public void Save(string path, object obj) 32 | { 33 | using TextWriter textWriter = new StreamWriter(path); 34 | XmlSerializer serializer = new XmlSerializer(type); 35 | serializer.Serialize(textWriter, obj); 36 | 37 | } 38 | 39 | public T Read(string path) 40 | { 41 | T result; 42 | using (TextReader textReader = new StreamReader(Path.GetFullPath(path))) 43 | { 44 | XmlSerializer deserializer = new XmlSerializer(type); 45 | result = (T)deserializer.Deserialize(textReader); 46 | } 47 | return result; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /EmuController.Client.NET/Input/Buttons.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections; 16 | using System.Collections.Generic; 17 | using System.Linq; 18 | using System.Text; 19 | using System.Threading.Tasks; 20 | 21 | namespace EmuController.Client.NET.Input 22 | { 23 | public class Buttons : ControlCollection 24 | { 25 | internal Buttons() 26 | { 27 | values = new ushort[8]; 28 | } 29 | 30 | 31 | /// 32 | /// Set state for button with the specified index. 33 | /// 34 | /// 35 | /// 36 | 37 | public void SetValue(int index, bool pressed) 38 | { 39 | int arrayIndex = index / 16; 40 | int bit = index % 16; 41 | int result = values[arrayIndex]; 42 | if (pressed) 43 | { 44 | result |= 1 << bit; 45 | } 46 | else 47 | { 48 | result &= ~(1 << bit); 49 | } 50 | 51 | SetValue(arrayIndex, (ushort)result); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/PIDSetPeriodicReport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Linq; 17 | using System.Runtime.InteropServices; 18 | using System.Text; 19 | using System.Threading.Tasks; 20 | 21 | namespace EmuController.Client.NET.PID 22 | { 23 | public class PIDSetPeriodicReport : FFBPacket 24 | { 25 | public byte EffectBlockIndex { get; private set; } 26 | public ushort Magnitude { get; private set; } 27 | public short Offset { get; private set; } 28 | public ushort Phase { get; private set; } 29 | public ushort Period { get; private set; } 30 | public PIDSetPeriodicReport(byte[] packet): base(packet) 31 | { 32 | 33 | } 34 | 35 | protected override void Deserialize() 36 | { 37 | EffectBlockIndex = DataPacket[1]; 38 | ReadOnlySpan packetSpan = MemoryMarshal.Cast(DataPacket); 39 | Magnitude = packetSpan[1]; 40 | Offset = BitConverter.ToInt16(DataPacket, 4); 41 | Phase = packetSpan[3]; 42 | Period = packetSpan[4]; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/PIDSetEnvelopeReport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Linq; 17 | using System.Runtime.InteropServices; 18 | using System.Text; 19 | using System.Threading.Tasks; 20 | 21 | namespace EmuController.Client.NET.PID 22 | { 23 | public class PIDSetEnvelopeReport : FFBPacket 24 | { 25 | public byte EffectBlockIndex { get; private set; } 26 | public ushort AttackLevel { get; private set; } 27 | public ushort FadeLevel { get; private set; } 28 | public ushort AttackTime { get; private set; } 29 | public ushort FadeTime { get; private set; } 30 | public PIDSetEnvelopeReport(byte[] packet): base(packet) 31 | { 32 | 33 | } 34 | 35 | protected override void Deserialize() 36 | { 37 | 38 | ReadOnlySpan packetSpan = MemoryMarshal.Cast(DataPacket); 39 | 40 | EffectBlockIndex = DataPacket[1]; 41 | AttackLevel = packetSpan[1]; 42 | FadeLevel = packetSpan[2]; 43 | AttackTime = packetSpan[3]; 44 | FadeTime = packetSpan[4]; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /EmuController.Client.NET/Utils.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using Microsoft.Win32; 15 | using System; 16 | using System.Globalization; 17 | 18 | namespace EmuController.Client.NET 19 | { 20 | public static class Utils 21 | { 22 | public static string GetStringFromRegistry(string regPath, string regKeyName) 23 | { 24 | RegistryKey key = null; 25 | string res = string.Empty; 26 | try 27 | { 28 | key = Registry.CurrentUser.OpenSubKey(regPath); 29 | if (key != null) 30 | { 31 | res = (string)key.GetValue(regKeyName); 32 | } 33 | } 34 | finally 35 | { 36 | if (key != null) 37 | { 38 | key.Dispose(); 39 | } 40 | } 41 | 42 | return res; 43 | } 44 | public static bool IsBitSet(T b, int pos) where T : 45 | IComparable, IComparable, 46 | IConvertible, IEquatable, 47 | IFormattable 48 | { 49 | long val = b.ToInt64(CultureInfo.CurrentCulture); 50 | return (val & (1 << pos)) != 0; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /EmuController/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | EmuController Project Overview 3 | ======================================================================== 4 | 5 | This file contains a summary of what you will find in each of the files that make up your project. 6 | 7 | EmuController.vcxproj 8 | This is the main project file for projects generated using an Application Wizard. 9 | It contains information about the version of the product that generated the file, and 10 | information about the platforms, configurations, and project features selected with the 11 | Application Wizard. 12 | 13 | EmuController.vcxproj.filters 14 | This is the filters file for VC++ projects generated using an Application Wizard. 15 | It contains information about the association between the files in your project 16 | and the filters. This association is used in the IDE to show grouping of files with 17 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 18 | "Source Files" filter). 19 | 20 | Public.h 21 | Header file to be shared with applications. 22 | 23 | Driver.c & Driver.h 24 | DriverEntry and WDFDRIVER related functionality and callbacks. 25 | 26 | Device.c & Device.h 27 | WDFDEVICE related functionality and callbacks. 28 | 29 | Queue.c & Queue.h 30 | WDFQUEUE related functionality and callbacks. 31 | 32 | Ioctl.c & Ioctl.h 33 | Functionality for handling various input/output control calls. 34 | 35 | NamedPipeServer.c & NamedPipeServer.h 36 | Functionality for setting up a side-communication with driver via two named pipe server instances. 37 | 38 | MessageProcessor.c & MessageProcessor.h 39 | Functionality for processing messages from input client that contains non-complete input report updates. 40 | 41 | Trace.h 42 | Definitions for WPP tracing. 43 | -------------------------------------------------------------------------------- /EmuController.DevManager/Commands/DeviceCommand.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Windows.Input; 16 | 17 | namespace EmuController.DevManager.Commands 18 | { 19 | public class DeviceCommand : ICommand 20 | { 21 | public DeviceCommand(Action execute) : this(execute, null) { } 22 | public DeviceCommand(Action execute, Predicate canExecute) 23 | { 24 | CanExecuteDelegate = canExecute; 25 | ExecuteDelegate = execute; 26 | } 27 | 28 | public Predicate CanExecuteDelegate { get; set; } 29 | 30 | public Action ExecuteDelegate { get; set; } 31 | 32 | public bool CanExecute(object parameter) 33 | { 34 | return CanExecuteDelegate == null || CanExecuteDelegate(parameter); 35 | } 36 | 37 | public void SetExecuteState(bool canExecute) 38 | { 39 | CanExecuteDelegate = x => canExecute; 40 | } 41 | 42 | public event EventHandler CanExecuteChanged 43 | { 44 | add => CommandManager.RequerySuggested += value; 45 | remove => CommandManager.RequerySuggested -= value; 46 | } 47 | 48 | public void Execute(object parameter) 49 | { 50 | ExecuteDelegate?.Invoke(parameter); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /EmuController.Client.NET/Input/Axes.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections; 16 | 17 | namespace EmuController.Client.NET.Input 18 | { 19 | public class Axes : ControlCollection 20 | { 21 | private const ushort DefaultSymmAxisValue = 32768; 22 | private const ushort DefaultAsymmAxisValue = 65535; 23 | 24 | internal Axes() 25 | { 26 | values = new ushort[8] { DefaultSymmAxisValue, DefaultSymmAxisValue, 27 | DefaultAsymmAxisValue, DefaultAsymmAxisValue, 28 | DefaultAsymmAxisValue, DefaultAsymmAxisValue, 29 | DefaultAsymmAxisValue, DefaultAsymmAxisValue}; 30 | 31 | } 32 | 33 | /// 34 | /// Set value for Axis with the specified index. 35 | /// 36 | /// Axis type 37 | /// Axis value 38 | public void SetValue(AxisEnum axisType, ushort value) 39 | { 40 | SetValue((int)axisType, value); 41 | } 42 | } 43 | 44 | /// 45 | /// Axis types for HID game controllers. 46 | /// Values correspond to indices of DirectInput controller 47 | /// 48 | public enum AxisEnum 49 | { 50 | AxisX, 51 | AxisY, 52 | AxisZ, 53 | AxisRx, 54 | AxisRy, 55 | AxisRz, 56 | AxisSlider, 57 | AxisDial 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /EmuController.DevManager/Utils.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using Microsoft.Win32; 15 | using System; 16 | using System.Collections.Generic; 17 | using System.Text; 18 | 19 | namespace EmuController.DevManager 20 | { 21 | public static class Utils 22 | { 23 | public static string GetStringFromRegistry(string regPath, string regValueName) 24 | { 25 | RegistryKey key = null; 26 | string res = string.Empty; 27 | try 28 | { 29 | key = Registry.CurrentUser.OpenSubKey(regPath); 30 | if (key != null) 31 | { 32 | res = (string)key.GetValue(regValueName); 33 | } 34 | } 35 | finally 36 | { 37 | if (key != null) 38 | { 39 | key.Dispose(); 40 | } 41 | } 42 | 43 | return res; 44 | } 45 | 46 | public static string SetStringFromRegistry(string regPath, string regKeyName, string textString) 47 | { 48 | RegistryKey key = null; 49 | string res = string.Empty; 50 | try 51 | { 52 | key = Registry.CurrentUser.CreateSubKey(regPath, true); 53 | if (key != null) 54 | { 55 | key.SetValue(regKeyName, textString, RegistryValueKind.String); 56 | } 57 | } 58 | finally 59 | { 60 | if (key != null) 61 | { 62 | key.Dispose(); 63 | } 64 | } 65 | 66 | return res; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/PIDSetConditionReport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Collections.ObjectModel; 17 | using System.Linq; 18 | using System.Runtime.InteropServices; 19 | using System.Text; 20 | using System.Threading.Tasks; 21 | 22 | namespace EmuController.Client.NET.PID 23 | { 24 | public class PIDSetConditionReport : FFBPacket 25 | { 26 | public byte EffectBlockIndex { get; private set; } 27 | public ConditionParamBlockEnum ParameterBlockOffset { get; private set; } 28 | public short CenterPointOffset { get; private set; } 29 | public short NegativeCoefficient { get; private set; } 30 | public short PositiveCoefficient { get; private set; } 31 | public ushort NegativeSaturation { get; private set; } 32 | public ushort PositiveSaturation { get; private set; } 33 | public ushort DeadBand { get; private set; } 34 | 35 | public PIDSetConditionReport(byte[] packet): base(packet) 36 | { 37 | 38 | } 39 | 40 | protected override void Deserialize() 41 | { 42 | EffectBlockIndex = DataPacket[1]; 43 | ParameterBlockOffset = (ConditionParamBlockEnum)(DataPacket[2] & 0x0F); 44 | 45 | ReadOnlySpan packetSpan = DataPacket; 46 | ReadOnlySpan shortSpan = MemoryMarshal.Cast(packetSpan[3..]); 47 | CenterPointOffset = shortSpan[0]; 48 | NegativeCoefficient = shortSpan[1]; 49 | PositiveCoefficient = shortSpan[2]; 50 | NegativeSaturation = (ushort)shortSpan[3]; 51 | PositiveSaturation = (ushort)shortSpan[4]; 52 | DeadBand = (ushort)shortSpan[5]; 53 | } 54 | } 55 | public enum ConditionParamBlockEnum 56 | { 57 | AxisX, 58 | AxisY 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/PIDSetEffectReport.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Runtime.InteropServices; 16 | 17 | namespace EmuController.Client.NET.PID 18 | { 19 | public class PIDSetEffectReport : FFBPacket 20 | { 21 | public byte EffectBlockIndex { get; private set; } 22 | 23 | public PIDEffectTypeEnum EffectType { get; private set; } 24 | public ushort Duration { get; private set; } 25 | public ushort TriggerRepeatInterval { get; private set; } 26 | public ushort SamplePeriod { get; private set; } 27 | public ushort Gain { get; private set; } 28 | public byte TriggerButton { get; private set; } 29 | 30 | public AxesDirFlags EnableAxesDirFlags { get; private set; } 31 | public ushort DirectionX { get; private set; } 32 | public ushort DirectionY { get; private set; } 33 | public ushort StartDelay { get; private set; } 34 | 35 | 36 | public PIDSetEffectReport(byte[] packet): base(packet) 37 | { 38 | 39 | } 40 | 41 | protected override void Deserialize() 42 | { 43 | EffectBlockIndex = DataPacket[1]; 44 | EffectType = (PIDEffectTypeEnum)DataPacket[2]; 45 | 46 | ReadOnlySpan packetSpan = DataPacket; 47 | ReadOnlySpan shortSpan = MemoryMarshal.Cast(packetSpan[3..]); 48 | 49 | 50 | Duration = shortSpan[0]; 51 | TriggerRepeatInterval = shortSpan[1]; 52 | SamplePeriod = shortSpan[2]; 53 | Gain = shortSpan[3]; 54 | TriggerButton = DataPacket[11]; 55 | EnableAxesDirFlags = (AxesDirFlags)DataPacket[12]; 56 | DirectionX = shortSpan[5]; 57 | DirectionY = shortSpan[6]; 58 | StartDelay = shortSpan[7]; 59 | } 60 | } 61 | 62 | [Flags] 63 | public enum AxesDirFlags 64 | { 65 | EnableAxisX = 0x01, 66 | EnableAxisY = 0x02, 67 | EnableDirection = 0x04 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /EmuController/Ioctl.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /*++ 16 | 17 | Module Name: 18 | 19 | ioctl.h 20 | 21 | Abstract: 22 | 23 | This file contains the ioctl definitions. 24 | 25 | Environment: 26 | 27 | User-mode Driver Framework 2 28 | 29 | --*/ 30 | 31 | EXTERN_C_START 32 | 33 | NTSTATUS 34 | ReadReport( 35 | _In_ PQUEUE_CONTEXT QueueContext, 36 | _In_ WDFREQUEST Request, 37 | _Always_(_Out_) 38 | BOOLEAN* CompleteRequest 39 | ); 40 | 41 | NTSTATUS 42 | WriteReport( 43 | _In_ PQUEUE_CONTEXT QueueContext, 44 | _In_ WDFREQUEST Request 45 | ); 46 | 47 | NTSTATUS 48 | GetFeature( 49 | _In_ PQUEUE_CONTEXT QueueContext, 50 | _In_ WDFREQUEST Request 51 | ); 52 | 53 | NTSTATUS 54 | SetFeature( 55 | _In_ PQUEUE_CONTEXT QueueContext, 56 | _In_ WDFREQUEST Request 57 | ); 58 | 59 | NTSTATUS 60 | GetInputReport( 61 | _In_ PQUEUE_CONTEXT QueueContext, 62 | _In_ WDFREQUEST Request 63 | ); 64 | 65 | NTSTATUS 66 | SetOutputReport( 67 | _In_ PQUEUE_CONTEXT QueueContext, 68 | _In_ WDFREQUEST Request 69 | ); 70 | 71 | NTSTATUS 72 | GetString( 73 | _In_ WDFREQUEST Request 74 | ); 75 | 76 | NTSTATUS 77 | GetIndexedString( 78 | _In_ WDFREQUEST Request 79 | ); 80 | 81 | NTSTATUS 82 | GetStringId( 83 | _In_ WDFREQUEST Request, 84 | _Out_ ULONG* StringId, 85 | _Out_ ULONG* LanguageId 86 | ); 87 | 88 | NTSTATUS 89 | RequestCopyFromBuffer( 90 | _In_ WDFREQUEST Request, 91 | _In_ PVOID SourceBuffer, 92 | _When_(NumBytesToCopyFrom == 0, __drv_reportError(NumBytesToCopyFrom cannot be zero)) 93 | _In_ size_t NumBytesToCopyFrom 94 | ); 95 | 96 | NTSTATUS 97 | RequestGetHidXferPacket_ToReadFromDevice( 98 | _In_ WDFREQUEST Request, 99 | _Out_ HID_XFER_PACKET* Packet 100 | ); 101 | 102 | NTSTATUS 103 | RequestGetHidXferPacket_ToWriteToDevice( 104 | _In_ WDFREQUEST Request, 105 | _Out_ HID_XFER_PACKET* Packet 106 | ); 107 | 108 | EXTERN_C_END 109 | -------------------------------------------------------------------------------- /EmuController.DevManager/Views/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using MahApps.Metro.Controls; 15 | using MahApps.Metro.Controls.Dialogs; 16 | using System; 17 | using System.Collections.ObjectModel; 18 | using System.IO; 19 | using System.Windows; 20 | using System.Threading.Tasks; 21 | using SetupAPI.NET; 22 | 23 | namespace EmuController.DevManager.Views 24 | { 25 | /// 26 | /// Interaction logic for MainWindow.xaml 27 | /// 28 | public partial class MainWindow : MetroWindow 29 | { 30 | public MainWindow() 31 | { 32 | InitializeComponent(); 33 | Loaded += MainWindowLoaded; 34 | } 35 | 36 | private async void MainWindowLoaded(object sender, RoutedEventArgs e) 37 | { 38 | if (!IsOSSupported()) 39 | { 40 | await ShowUnsupportedOsMessage(); 41 | Application.Current.Shutdown(); 42 | } 43 | 44 | if (!AppSettings.Instance.IsValid()) 45 | { 46 | await ShowDriverFilesNotFound(); 47 | Application.Current.Shutdown(); 48 | } 49 | DataContext = this; 50 | } 51 | 52 | private static bool IsOSSupported() 53 | { 54 | bool result = true; 55 | OperatingSystem env = Environment.OSVersion; 56 | if (env.Version.Major != 10 && env.Version.Build < 16299) 57 | { 58 | result = false; 59 | } 60 | 61 | return result; 62 | } 63 | 64 | private async Task ShowUnsupportedOsMessage() 65 | { 66 | await this.ShowMessageAsync("Unsupported OS detected", 67 | "This application is designed to run on Microsoft Windows 10. ", MessageDialogStyle.Affirmative); 68 | } 69 | 70 | private async Task ShowDriverFilesNotFound() 71 | { 72 | await this.ShowMessageAsync("Driver files not found", 73 | "Could not find driver files in the driver installation directory.", 74 | MessageDialogStyle.Affirmative); 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /EmuController.DevManager/AppSettings.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.IO; 17 | using System.Xml; 18 | using System.Xml.Serialization; 19 | 20 | namespace EmuController.DevManager 21 | { 22 | [XmlRoot] 23 | public class AppSettings 24 | { 25 | private static readonly Lazy lazy = new Lazy(() => GetSettings() 26 | ); 27 | 28 | public static AppSettings Instance { get { return lazy.Value; } } 29 | 30 | private AppSettings() 31 | { 32 | } 33 | 34 | [XmlElement(IsNullable = false)] 35 | public string FilePath { get; set; } 36 | 37 | [XmlArray(IsNullable = false)] 38 | public List ExpectedFiles { get; set; } 39 | 40 | public bool IsValid() 41 | { 42 | if (ExpectedFiles == null) 43 | { 44 | return false; 45 | } 46 | foreach (string fileName in ExpectedFiles) 47 | { 48 | string fullPath = Path.Combine(Path.GetFullPath(FilePath, Directory.GetCurrentDirectory())); 49 | if (!File.Exists(Path.Combine(fullPath, fileName))) 50 | { 51 | return false; 52 | } 53 | } 54 | return true; 55 | } 56 | 57 | private void GetDefaultSettings() 58 | { 59 | FilePath = @"drv\"; 60 | ExpectedFiles = new List 61 | { 62 | "emucontroller.inf", 63 | "emucontroller.cat", 64 | "emucontroller.dll" 65 | }; 66 | } 67 | 68 | private static AppSettings GetSettings() 69 | { 70 | XmlSerializer appset = new XmlSerializer(); 71 | AppSettings settings = new AppSettings(); 72 | try 73 | { 74 | settings = appset.Read("AppSettings.xml"); 75 | } 76 | catch 77 | { 78 | settings.GetDefaultSettings(); 79 | } 80 | return settings; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /EmuController.DevManager/WMIPnpEntity.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using EmuController.DevManager.ViewModels; 15 | using System; 16 | using System.Collections.Generic; 17 | using System.Management; 18 | using System.Text; 19 | 20 | namespace EmuController.DevManager 21 | { 22 | public sealed class WMIPnpEntity 23 | { 24 | private static readonly string Scope = "root\\CIMV2"; 25 | private const string ClassGuid = "{4DB9B76D-4379-437E-9457-4F00B3090C1F}"; 26 | private readonly ManagementObjectSearcher Mos; 27 | private static readonly Lazy 28 | lazy = 29 | new Lazy 30 | (() => new WMIPnpEntity()); 31 | 32 | public static WMIPnpEntity Instance { get { return lazy.Value; } } 33 | 34 | private WMIPnpEntity() 35 | { 36 | string queryString = $"SELECT * FROM Win32_PnPEntity WHERE ClassGuid = '{ClassGuid}'"; 37 | Mos = new ManagementObjectSearcher(Scope, queryString); 38 | } 39 | 40 | public static void SetDeviceStatus(EmuControllerDevice device) 41 | { 42 | device.IsInstalled = false; 43 | device.IsEnabled = false; 44 | 45 | foreach (ManagementObject queryObj in Instance.Mos.Get()) 46 | { 47 | string hardwareId = ((string[])queryObj.Properties["HardwareID"].Value)[0][device.IdPrefix.Length..]; 48 | if (device.DeviceId.Equals(hardwareId)) 49 | { 50 | device.IsInstalled = true; 51 | string devName = device.GetDeviceFriendlyNameFromRegistry(); 52 | if (!string.IsNullOrEmpty(devName)) 53 | { 54 | device.DeviceName = devName; 55 | } 56 | 57 | if ((uint)queryObj.Properties["ConfigManagerErrorCode"].Value == (uint)DeviceState.OK) 58 | { 59 | device.IsEnabled = true; 60 | } 61 | else 62 | { 63 | device.ErrorCode = (uint)queryObj.Properties["ConfigManagerErrorCode"].Value; 64 | } 65 | break; 66 | } 67 | } 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /EmuController/Trace.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /*++ 16 | 17 | Module Name: 18 | 19 | Internal.h 20 | 21 | Abstract: 22 | 23 | This module contains the local type definitions for the 24 | driver. 25 | 26 | Environment: 27 | 28 | Windows User-Mode Driver Framework 2 29 | 30 | --*/ 31 | 32 | // 33 | // Define the tracing flags. 34 | // 35 | // Tracing GUID - 3afa687b-6cc9-4abd-b0ee-63f55365bc9b 36 | // 37 | 38 | #define WPP_CONTROL_GUIDS \ 39 | WPP_DEFINE_CONTROL_GUID( \ 40 | EmuControllerTraceGuid, (3afa687b,6cc9,4abd,b0ee,63f55365bc9b),\ 41 | \ 42 | WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \ 43 | WPP_DEFINE_BIT(TRACE_DRIVER) \ 44 | WPP_DEFINE_BIT(TRACE_DEVICE) \ 45 | WPP_DEFINE_BIT(TRACE_QUEUE) \ 46 | WPP_DEFINE_BIT(TRACE_IOCTL) \ 47 | WPP_DEFINE_BIT(TRACE_PIPE) \ 48 | ) 49 | 50 | #define WPP_FLAG_LEVEL_LOGGER(flag, level) \ 51 | WPP_LEVEL_LOGGER(flag) 52 | 53 | #define WPP_FLAG_LEVEL_ENABLED(flag, level) \ 54 | (WPP_LEVEL_ENABLED(flag) && \ 55 | WPP_CONTROL(WPP_BIT_ ## flag).Level >= level) 56 | 57 | #define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \ 58 | WPP_LEVEL_LOGGER(flags) 59 | 60 | #define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \ 61 | (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl) 62 | 63 | // 64 | // This comment block is scanned by the trace preprocessor to define our 65 | // Trace function. 66 | // 67 | // begin_wpp config 68 | // FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...); 69 | // FUNC TraceEvents(LEVEL, FLAGS, MSG, ...); 70 | // end_wpp 71 | 72 | // 73 | // 74 | // Driver specific #defines 75 | // 76 | 77 | 78 | #define WPP_ENABLED 0 79 | 80 | #if UMDF_VERSION_MAJOR == 2 && UMDF_VERSION_MINOR == 0 81 | #define MYDRIVER_TRACING_ID L"Microsoft\\UMDF2.0\\EmuController V1.0" 82 | #endif -------------------------------------------------------------------------------- /EmuController.Client.NETTests/Input/EmuInputStateTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using EmuController.Client.NET.Input; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace EmuController.Client.NET.Input.Tests 8 | { 9 | [TestClass()] 10 | public class EmuInputStateTests 11 | { 12 | [TestMethod()] 13 | public void GetInputReportMessageTest() 14 | { 15 | int headerSize = 2; 16 | EmuControllerInputState emu = new EmuControllerInputState(); 17 | byte[] message = emu.GetInputReportMessage(); 18 | Assert.IsTrue(message.Length == message[1] + headerSize); 19 | 20 | int totalLength = headerSize + 1; 21 | totalLength += emu.Axes.AllValues.Length * sizeof(ushort); 22 | totalLength += emu.Buttons.AllValues.Length * sizeof(ushort); 23 | totalLength += emu.DPads.AllValues.Length; 24 | 25 | Assert.IsTrue(message.Length == totalLength); 26 | } 27 | 28 | [TestMethod()] 29 | public void GetStateUpdateMessageTest() 30 | { 31 | Random rndVal = new Random(); 32 | int headerSize = 2; 33 | EmuControllerInputState emu = new EmuControllerInputState(); 34 | 35 | for (int i = 0; i < 100; i++) 36 | { 37 | 38 | AxisEnum ax1 = (AxisEnum)rndVal.Next(0, 8); 39 | 40 | ushort ax1Val = (ushort)rndVal.Next(0, 65536); 41 | 42 | int buttonIndex1 = rndVal.Next(0, 128); 43 | 44 | int dpad1 = rndVal.Next(0, 4); 45 | 46 | DPadDirectionEnum dpad1Val = (DPadDirectionEnum)rndVal.Next(-1, 8); 47 | 48 | emu.Axes.SetValue(ax1, ax1Val); 49 | 50 | emu.Buttons.SetValue(buttonIndex1, true); 51 | 52 | emu.DPads.SetValue(dpad1, dpad1Val); 53 | 54 | byte[] message = emu.GetStateUpdateMessage(); 55 | 56 | int expectedMessageLen = 2 * sizeof(ushort) + sizeof(byte) + 6 + headerSize; 57 | 58 | Assert.IsTrue(message.Length == expectedMessageLen); 59 | Assert.IsTrue(message[1] == message.Length - headerSize); 60 | Assert.IsTrue(message[2] == (byte)UsageId.Axis); 61 | Assert.IsTrue(Utils.IsBitSet(message[3], (byte)ax1)); 62 | Assert.IsTrue(BitConverter.ToUInt16(message, 4) == ax1Val); 63 | Assert.IsTrue(message[6] == (byte)UsageId.Button); 64 | Assert.IsTrue(Utils.IsBitSet(message[7], buttonIndex1 / 16)); 65 | Assert.IsTrue(Utils.IsBitSet(BitConverter.ToUInt16(message, 8), buttonIndex1 % 16)); 66 | Assert.IsTrue(message[10] == (byte)UsageId.DPad); 67 | Assert.IsTrue(Utils.IsBitSet(message[11], (byte)dpad1)); 68 | Assert.IsTrue(message[12] == (byte)dpad1Val); 69 | } 70 | 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /EmuController.DevManager/SingleInstanceApplicationLock.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Security.AccessControl; 16 | using System.Security.Principal; 17 | using System.Threading; 18 | 19 | namespace EmuController.DevManager 20 | { 21 | //https://codereview.stackexchange.com/a/141141 22 | sealed class SingleInstanceApplicationLock : IDisposable 23 | { 24 | ~SingleInstanceApplicationLock() 25 | { 26 | Dispose(false); 27 | } 28 | 29 | void IDisposable.Dispose() 30 | { 31 | Dispose(true); 32 | GC.SuppressFinalize(this); 33 | } 34 | 35 | public bool TryAcquireExclusiveLock() 36 | { 37 | try 38 | { 39 | if (!Mutex.WaitOne(1000, false)) 40 | return false; 41 | } 42 | catch (AbandonedMutexException) 43 | { 44 | // Multiple instances 45 | // may be executed in this condition... 46 | } 47 | 48 | return HasAcquiredExclusiveLock = true; 49 | } 50 | 51 | private const string MutexId = @"Local\{E03FD5E9-C97A-426E-BD6A-E56E5D7AC5B6}"; 52 | private readonly Mutex Mutex = CreateMutex(); 53 | private bool HasAcquiredExclusiveLock, Disposed; 54 | 55 | private void Dispose(bool disposing) 56 | { 57 | if (disposing && !Disposed && Mutex != null) 58 | { 59 | try 60 | { 61 | if (HasAcquiredExclusiveLock) 62 | Mutex.ReleaseMutex(); 63 | 64 | Mutex.Dispose(); 65 | } 66 | finally 67 | { 68 | Disposed = true; 69 | } 70 | } 71 | } 72 | 73 | private static Mutex CreateMutex() 74 | { 75 | var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null); 76 | var allowEveryoneRule = new MutexAccessRule(sid, 77 | MutexRights.FullControl, AccessControlType.Allow); 78 | 79 | var securitySettings = new MutexSecurity(); 80 | securitySettings.AddAccessRule(allowEveryoneRule); 81 | 82 | var mutex = new Mutex(false, MutexId); 83 | mutex.SetAccessControl(securitySettings); 84 | 85 | return mutex; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /EmuController/Device.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /*++ 16 | Module Name: 17 | device.h 18 | Abstract: 19 | This file contains the device definitions. 20 | Environment: 21 | User-mode Driver Framework 2 22 | --*/ 23 | 24 | #include "public.h" 25 | 26 | EXTERN_C_START 27 | 28 | typedef UCHAR HID_REPORT_DESCRIPTOR, * PHID_REPORT_DESCRIPTOR; 29 | 30 | #define HID_DEVICE_VID 0xDEED // VendorID 31 | #define HID_DEVICE_VERSION 0x0001 32 | 33 | #define MAXIMUM_STRING_LENGTH (126 * sizeof(WCHAR)) 34 | #define HID_DEVICE_STRING L"EmuController Device" 35 | #define HID_DEVICE_MANUFACTURER_STRING L"Maris Melbardis" 36 | #define HID_DEVICE_PRODUCT_STRING L"EmuController" 37 | #define HID_DEVICE_SERIAL_NUMBER_STRING L"23908912390812" 38 | #define HID_DEVICE_STRING_INDEX 5 39 | 40 | 41 | typedef struct _NAMED_PIPE_SERVER_ATTRIBUTES 42 | { 43 | WCHAR* InputPipePathName[48]; 44 | WCHAR* PidPipePathName[48]; 45 | HANDLE InputServerHandle; 46 | HANDLE PidServerHandle; 47 | HANDLE InputPipeHandle; 48 | HANDLE PidPipeHandle; 49 | BOOL InputPipeConnected; 50 | PSECURITY_ATTRIBUTES PipeSecurityAttr; 51 | } NAMED_PIPE_SERVER_ATTRIBUTES, * PNAMED_PIPE_SERVER_ATTRIBUTES; 52 | 53 | // 54 | // The device context performs the same job as 55 | // a WDM device extension in the driver frameworks 56 | // 57 | typedef struct _DEVICE_CONTEXT 58 | { 59 | WDFDEVICE Device; 60 | WDFQUEUE DefaultQueue; 61 | WDFQUEUE ManualQueue; 62 | HID_DESCRIPTOR HidDescriptor; 63 | PHID_REPORT_DESCRIPTOR ReportDescriptor; 64 | HID_DEVICE_ATTRIBUTES HidDeviceAttributes; 65 | HID_XFER_PACKET ReportPacket; 66 | JOYSTICK_INPUT_REPORT JoyInputReport; 67 | PID_STATE_REPORT JoyPidStateReport; 68 | ULONG64 SetEffectBlocks; 69 | NAMED_PIPE_SERVER_ATTRIBUTES PipeServerAttributes; 70 | } DEVICE_CONTEXT, * PDEVICE_CONTEXT; 71 | 72 | // 73 | // This macro will generate an inline function called DeviceGetContext 74 | // which will be used to get a pointer to the device context memory 75 | // in a type safe manner. 76 | // 77 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, DeviceGetContext) 78 | 79 | // 80 | // Function to initialize the device and its callbacks 81 | // 82 | NTSTATUS 83 | EmuControllerCreateDevice( 84 | _Inout_ PWDFDEVICE_INIT DeviceInit 85 | ); 86 | 87 | // 88 | // Function to retreive ProductId value from registry (under HKR hardware key) 89 | // 90 | 91 | NTSTATUS 92 | GetProductIdFromRegistry( 93 | _In_ WDFDEVICE Device, 94 | _Out_ PULONG ProductId); 95 | 96 | EXTERN_C_END -------------------------------------------------------------------------------- /EmuController/EmuController.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {8E41214B-6785-4CFE-B992-037D68949A14} 18 | inf;inv;inx;mof;mc; 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | Header Files 27 | 28 | 29 | Header Files 30 | 31 | 32 | Header Files 33 | 34 | 35 | Header Files 36 | 37 | 38 | Header Files 39 | 40 | 41 | Header Files 42 | 43 | 44 | Header Files 45 | 46 | 47 | Header Files 48 | 49 | 50 | Header Files 51 | 52 | 53 | 54 | 55 | Source Files 56 | 57 | 58 | Source Files 59 | 60 | 61 | Source Files 62 | 63 | 64 | Source Files 65 | 66 | 67 | Source Files 68 | 69 | 70 | Source Files 71 | 72 | 73 | 74 | 75 | Resource Files 76 | 77 | 78 | 79 | 80 | Driver Files 81 | 82 | 83 | -------------------------------------------------------------------------------- /EmuController.Client.NET/PID/FFBDataReceivedEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.Collections.Generic; 16 | using System.Collections.ObjectModel; 17 | using System.Linq; 18 | using System.Text; 19 | using System.Threading.Tasks; 20 | 21 | namespace EmuController.Client.NET.PID 22 | { 23 | 24 | public class FFBDataReceivedEventArgs : EventArgs 25 | { 26 | /// 27 | /// Type of FFB data. 28 | /// 29 | public PIDReportIdEnum ReportId { get; } 30 | 31 | /// 32 | /// FFB packet data. 33 | /// 34 | public FFBPacket FFBPacket { get; } 35 | 36 | /// 37 | /// Creates FFBDataReceivedEventArgs object and populates FFBPacket with data from received message from named pipe server. 38 | /// 39 | /// The message received from named pipe server 40 | public FFBDataReceivedEventArgs(byte[] buffer) 41 | { 42 | 43 | if (buffer == null) 44 | { 45 | throw new ArgumentNullException(nameof(buffer)); 46 | } 47 | 48 | ReportId = (PIDReportIdEnum)buffer[0]; 49 | 50 | 51 | FFBPacket = ReportId switch 52 | { 53 | PIDReportIdEnum.SetEffect => new PIDSetEffectReport(buffer), 54 | PIDReportIdEnum.SetEnvelope => new PIDSetEnvelopeReport(buffer), 55 | PIDReportIdEnum.SetCondition => new PIDSetConditionReport(buffer), 56 | PIDReportIdEnum.SetPeriodic => new PIDSetPeriodicReport(buffer), 57 | PIDReportIdEnum.SetConstant => new PIDSetConstantForce(buffer), 58 | PIDReportIdEnum.SetRamp => new PIDSetRampReport(buffer), 59 | PIDReportIdEnum.SetCustomForceData => new PIDSetCustomForceDataReport(buffer), 60 | PIDReportIdEnum.DownloadSample => new PIDDownloadSampleReport(buffer), 61 | PIDReportIdEnum.EffectOperation => new PIDEffectOperationReport(buffer), 62 | PIDReportIdEnum.DeviceControl => new PIDDeviceControlReport(buffer), 63 | PIDReportIdEnum.BlockFree => new PIDBlockFreeReport(buffer), 64 | PIDReportIdEnum.SetGain => new PIDSetGainReport(buffer), 65 | PIDReportIdEnum.SetCustomForce => new PIDSetCustomForceReport(buffer), 66 | PIDReportIdEnum.NewEffect => new PIDNewEffectReport(buffer), 67 | PIDReportIdEnum.BlockLoad => new PIDBloadLoadReport(buffer), 68 | _ => throw new NotSupportedException() 69 | }; 70 | 71 | } 72 | 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /EmuController.DevManager/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 59 | 60 | 61 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /EmuController.Client.NET/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace EmuController.Client.NET { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("EmuController.Client.NET.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to Message length exceeds MessageLengthMax!. 65 | /// 66 | internal static string ErrorMessageLengthMax { 67 | get { 68 | return ResourceManager.GetString("ErrorMessageLengthMax", resourceCulture); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /EmuController.Client.NET/EmuControllerInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Maris Melbardis 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | using System; 15 | using System.IO; 16 | using System.Management; 17 | 18 | namespace EmuController.Client.NET 19 | { 20 | public class EmuControllerInfo 21 | { 22 | /// 23 | /// HardwareId of the EmuController device 24 | /// 25 | public string HardwareId { get; } 26 | 27 | /// 28 | /// Name of the EmuController device. 29 | /// 30 | public string Name { get; } 31 | 32 | 33 | /// 34 | /// Creates a new EmuControllerInfo object. 35 | /// 36 | /// Provides ManageentObject data returned by ManagementObjectSearcher 37 | public EmuControllerInfo(ManagementObject queryObj) 38 | { 39 | 40 | string hwid = ((string[])queryObj.Properties["HardwareID"].Value)[0]; 41 | 42 | //Version driverVersion = new Version((string)queryObj.Properties["DriverVersion"].Value); 43 | //Version clientVersion = Assembly.GetExecutingAssembly().GetName().Version; 44 | 45 | //if (clientVersion.Major != driverVersion.Major || clientVersion.Minor != driverVersion.Minor) 46 | //{ 47 | // throw new EmuControllerException(string.Format("Version mismatch! Driver: {0}.{1}, Client: {2}.{3}", 48 | // driverVersion.Major, driverVersion.Minor, 49 | // clientVersion.Major, clientVersion.Minor)); 50 | //} 51 | 52 | // We need only the Vīd/Pid information about the device 53 | string prefix = "ROOT\\"; 54 | 55 | if (hwid != null) 56 | { 57 | HardwareId = hwid[prefix.Length..]; 58 | } 59 | else 60 | { 61 | // In case user installed the device manually through device manager (which should not be done), the hardwareId will be incorrect, 62 | // So we replace it with a predefined one. 63 | HardwareId = "VID_DEED&PID_FE00"; 64 | } 65 | 66 | Name = GetDeviceFriendlyName(HardwareId); 67 | } 68 | 69 | private static string GetDeviceFriendlyName(string hwId) 70 | { 71 | if (string.IsNullOrEmpty(hwId)) 72 | { 73 | return string.Empty; 74 | } 75 | 76 | const string regJoystickPath = @"System\CurrentControlSet\Control\MediaProperties\PrivateProperties\Joystick\OEM"; 77 | const string regKeyName = "OEMName"; 78 | string[] strArr = hwId.Split('&'); 79 | 80 | string path = Path.Combine(regJoystickPath, strArr[0] + "&" + strArr[1]); 81 | return Utils.GetStringFromRegistry(path, regKeyName); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /EmuController.DevManager/Views/SingleLineInputDialog.xaml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 23 | 32 | 33 | 34 | 35 | 36 | 37 | 41 |