diff --git a/WheelAdapter.sln b/WheelAdapter.sln new file mode 100644 index 0000000..6e9f708 --- /dev/null +++ b/WheelAdapter.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30621.155 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WheelAdapter", "WheelAdapter\WheelAdapter.csproj", "{3E7E3973-6AEA-4B3D-86BC-CBAF8A8FDD76}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3E7E3973-6AEA-4B3D-86BC-CBAF8A8FDD76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3E7E3973-6AEA-4B3D-86BC-CBAF8A8FDD76}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3E7E3973-6AEA-4B3D-86BC-CBAF8A8FDD76}.Debug|x64.ActiveCfg = Debug|x64 + {3E7E3973-6AEA-4B3D-86BC-CBAF8A8FDD76}.Debug|x64.Build.0 = Debug|x64 + {3E7E3973-6AEA-4B3D-86BC-CBAF8A8FDD76}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3E7E3973-6AEA-4B3D-86BC-CBAF8A8FDD76}.Release|Any CPU.Build.0 = Release|Any CPU + {3E7E3973-6AEA-4B3D-86BC-CBAF8A8FDD76}.Release|x64.ActiveCfg = Release|x64 + {3E7E3973-6AEA-4B3D-86BC-CBAF8A8FDD76}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AD37DA4B-8F30-45CD-96C7-E2CA315CEC9E} + EndGlobalSection +EndGlobal diff --git a/WheelAdapter/App.config b/WheelAdapter/App.config new file mode 100644 index 0000000..193aecc --- /dev/null +++ b/WheelAdapter/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/WheelAdapter/IForceSerial.cs b/WheelAdapter/IForceSerial.cs new file mode 100644 index 0000000..dc3a8fc --- /dev/null +++ b/WheelAdapter/IForceSerial.cs @@ -0,0 +1,346 @@ +using System; +using System.IO.Ports; +using System.Threading; +using System.IO; +using System.Data; + +namespace WheelAdapter +{ + class IForceSerial + { + static readonly Byte SOP = 0x2B; + + SerialPort _serialPort; + bool _continue; + Thread _readThread; + + bool _open = false; + private Byte _lastRxQuery; + + public class DeviceInfo + { + public UInt16 manufacturer; + public UInt16 product; + public Byte[] version; + public int bufferSize; + public int numberOfEffects; + } + public DeviceInfo deviceInfo; + + public delegate void WheelHandler(InputWheel wheel); + public WheelHandler wheelHandler; + + public delegate void QueryHandler(Query query); + public QueryHandler queryHandler; + + public IForceSerial(string portName) + { + _serialPort = new SerialPort + { + PortName = portName, + BaudRate = 38400, + Parity = Parity.None, + DataBits = 8, + StopBits = StopBits.One, + Handshake = Handshake.None, + + ReadTimeout = 500, + WriteTimeout = 5000 + }; + + deviceInfo = new DeviceInfo(); + + _readThread = new Thread(ReadPacket); + + _serialPort.Open(); + _continue = true; + _readThread.Start(); + + for (int i = 0; i < 20 && !_open; i++) + { + WritePacket(IForceSerial.Type.QUERY, new Byte[] { (Byte)IForceSerial.Query.Type.Open }); + System.Threading.Thread.Sleep(1000); + } + + if (_open) + { + _waitForInitPacket(IForceSerial.Query.Type.Manufacturer); + _waitForInitPacket(IForceSerial.Query.Type.Product); + _waitForInitPacket(IForceSerial.Query.Type.Version); + _waitForInitPacket(IForceSerial.Query.Type.NumberOfEffects); + _waitForInitPacket(IForceSerial.Query.Type.BufferSize); + } + else + { + Shutdown(); + } + } + + private void _waitForInitPacket(Query.Type type) + { + _lastRxQuery = 0xFF; + while (_lastRxQuery != (Byte)type) + { + WritePacket(IForceSerial.Type.QUERY, new Byte[] { (Byte)type }); + System.Threading.Thread.Sleep(500); + } + } + + public void Shutdown() + { + if (_continue) + { + _continue = false; + _readThread.Join(); + _serialPort.Close(); + } + } + + ~IForceSerial() + { + Shutdown(); + } + Byte _readByte() + { + int d = _serialPort.ReadByte(); + if (d == -1) { throw new EndOfStreamException(); } + return (Byte)(d); + } + + public bool isOpen => _open && _serialPort.IsOpen; + public void WritePacket(Type type, Byte[] data) + { + Byte[] buf = new byte[4 + data.Length]; + buf[0] = SOP; + buf[1] = (Byte)type; + buf[2] = (Byte)data.Length; + data.CopyTo(buf, 3); + Byte cs = 0; + foreach (Byte b in buf) + { + cs ^= b; + } + buf[buf.Length - 1] = cs; + + _serialPort.Write(buf, 0, data.Length + 4); + } + + void ReadPacket() + { + _serialPort.RtsEnable = true; + while (_continue) + { + try + { + Byte cs = SOP; + Byte d = 0; + + // sync + while (d != SOP) { d = _readByte(); } + + // packet type + Type type = (Type)_readByte(); + cs ^= (Byte)type; + + // length + Byte length = _readByte(); + cs ^= length; + + // data + Byte[] data = new Byte[length]; + _serialPort.Read(data, 0, length); + foreach (Byte b in data) + { + cs ^= b; + } + + // checksum + cs ^= _readByte(); + + if (cs == 0) + { + HandlePacket(type, data); + } + } + catch (TimeoutException) { } + } + } + + void HandlePacket(Type type, Byte[] data) + { + switch (type) + { + case Type.INPUT_WHEEL: + { + if (wheelHandler != null) + { + InputWheel wheel = new InputWheel(data); + wheelHandler(wheel); + } + break; + } + case Type.EFFECT_STATES: + { + // ignored for now + break; + } + case Type.QUERY: + { + Query query = new Query(data); + if (queryHandler != null) + { + + queryHandler(query); + } + else + { + switch (query.type) + { + case Query.Type.Manufacturer: { deviceInfo.manufacturer = BitConverter.ToUInt16(query.data, 0); break; } + case Query.Type.Product: { deviceInfo.product = BitConverter.ToUInt16(query.data, 0); break; } + case Query.Type.Version: { deviceInfo.version = new byte[data.Length]; Buffer.BlockCopy(query.data, 0, deviceInfo.version, 0, query.data.Length); break; } + case Query.Type.NumberOfEffects: { deviceInfo.numberOfEffects = query.data[0]; break; } + case Query.Type.BufferSize: { deviceInfo.bufferSize = BitConverter.ToUInt16(query.data, 0); break; } + case Query.Type.Open: { _open = true; break; } + case Query.Type.Close: { _open = false; break; } + default: { Console.WriteLine("unknown query:" + query.type.ToString()); break; } + } + _lastRxQuery = (Byte)query.type; + } + break; + } + default: + { + Console.WriteLine("unknown packet:" + type.ToString()); + break; + } + } + } + + public enum Type : Byte + { + INPUT_JOYSTICK = 0x01, + INPUT_WHEEL = 0x03, + EFFECT_STATES = 0x02, + + SET_CONTROL = 0x40, + CONTROL = 0x41, + SET_DEVICE_STATE = 0x42, + SET_OVERALL = 0x43, + + QUERY = 0xFF + } + + public enum Control : Byte + { + DEAD_ZONE = 0x00, + IGNORE_DEADMAN_SWITCH = 0x01, + ENABLE_COMM_WATCHDOG = 0x02, + SET_SPRING_STRENGTH = 0x03, + ENABLE_SPRING = 0x04, + SET_AXIS_SATURATION = 0x05 + } + + public enum OverallControlType : Byte + { + GAIN = 0x00 + } + + public enum DeviceState : Byte + { + PAUSE_FFB = 0x08, + ENABLE_FFB = 0x04, + STOP_ALL = 0x01 + } + + public class InputWheel + { + public class Axis + { + public double wheel; + public double gas; + public double brake; + }; + + public class Buttons + { + public bool btnA; + public bool btnB; + public bool btn1; + public bool btn2; + public bool btn3; + public bool btn4; + }; + + public class PovHat + { + public bool center; + public bool north; + public bool east; + public bool south; + public bool west; + } + + public Axis axis; + public Buttons buttons; + public PovHat povHat; + + public InputWheel(Byte[] data) + { + axis = new Axis + { + wheel = BitConverter.ToInt16(data, 0) / 2048.0, + gas = 1.0 - data[2] / 255.0, + brake = 1.0 - data[3] / 255.0 + }; + + buttons = new Buttons + { + btn1 = (data[5] & 0x01) != 0, + btn2 = (data[5] & 0x02) != 0, + btn3 = (data[5] & 0x04) != 0, + btn4 = (data[5] & 0x08) != 0, + btnA = (data[5] & 0x10) != 0, + btnB = (data[5] & 0x20) != 0 + }; + + povHat = new PovHat + { + center = (data[6] & 0xF0) == 0xF0, + north = (data[6] & 0xF0) == 0x00, + south = (data[6] & 0xF0) == 0x40, + west = (data[6] & 0xF0) == 0x60, + east = (data[6] & 0xF0) == 0x20 + }; + } + } + public class Query + { + public enum Type : Byte + { + BufferSize = 0x42, // ('B'uffer size) + Manufacturer = 0x4d, // ('M'anufacturer) + Product = 0x50, // ('P'roduct) + Version = 0x56, // ('V'ersion) + NumberOfEffects = 0x4e, // ('N'umber of effects) + Effect = 0x45, // ('E')ffect + + Open = 0x4f, // ('O'pen) + Close = 0x43, // ('C')lose + } + + public Type type; + public Byte[] data; + + public Query(Byte[] data) + { + type = (Type)data[0]; + if (data.Length > 1) + { + this.data = new Byte[data.Length - 1]; + Buffer.BlockCopy(data, 1, this.data, 0, data.Length - 1); + } + } + } + } +} diff --git a/WheelAdapter/Program.cs b/WheelAdapter/Program.cs new file mode 100644 index 0000000..0abc92d --- /dev/null +++ b/WheelAdapter/Program.cs @@ -0,0 +1,122 @@ +using System; + +using vJoyInterfaceWrap; + +namespace WheelAdapter +{ + class Program + { + static uint VJ_ID = 1; + static string COM_PORT = "COM7"; + + static IForceSerial ifs; + static vJoy vj; + + static System.Threading.Mutex vj_mutex = new System.Threading.Mutex(true, "VJ access lock"); + + static int Main(string[] args) + { + AppDomain.CurrentDomain.ProcessExit += AppDomain_ProcessExit; + + #region vJoy init + vj = new vJoy(); + // check vJoy environment + UInt32 DllVer = 0, DrvVer = 0; + bool match = vj.DriverMatch(ref DllVer, ref DrvVer); + if (!match) + { + Console.WriteLine("Version of Driver ({0:X}) does NOT match DLL Version ({1:X})\n", DrvVer, DllVer); + return -1; + } + if (!vj.vJoyEnabled()) + { + Console.WriteLine("vJoy driver not enabled: Failed Getting vJoy attributes.\n"); + return -2; + } + VjdStat vjStatus = vj.GetVJDStatus(VJ_ID); + if (vjStatus != VjdStat.VJD_STAT_FREE) + { + Console.WriteLine("vJoy driver not free: " + vjStatus.ToString() + " \n"); + return -3; + } + vj.AcquireVJD(VJ_ID); + vj.ResetVJD(VJ_ID); + + vj_mutex.ReleaseMutex(); + #endregion + + #region serial init + ifs = new IForceSerial(COM_PORT); + + // setup wheel serial handling + IForceSerial.WheelHandler handleWheelDelegate = handleWheel; + ifs.wheelHandler = handleWheelDelegate; + + IForceSerial.QueryHandler handleQueryDelegate = handleQuery; + ifs.queryHandler = handleQueryDelegate; + + #endregion + + // activate wheel packets + + Console.WriteLine("Press Enter to exit."); + Console.ReadLine(); + + cleanup(); + return 0; + } + + private static void cleanup() + { + vj_mutex.WaitOne(); + + if (vj != null && vj.GetVJDStatus(VJ_ID) == VjdStat.VJD_STAT_OWN) + { + vj.RelinquishVJD(VJ_ID); + vj = null; + } + if (ifs != null) + { + ifs.wheelHandler = null; + ifs.Shutdown(); + ifs = null; + } + vj_mutex.ReleaseMutex(); + } + + private static void AppDomain_ProcessExit(object sender, EventArgs e) + { + cleanup(); + } + + private static void handleWheel(IForceSerial.InputWheel wheel) + { + vj_mutex.WaitOne(); + vj.SetAxis((int)(((double)0x4000) * (wheel.axis.wheel + 1)), VJ_ID, HID_USAGES.HID_USAGE_X); + vj.SetAxis((int)(((double)0x8000) * wheel.axis.gas), VJ_ID, HID_USAGES.HID_USAGE_Y); + vj.SetAxis((int)(((double)0x8000) * wheel.axis.brake), VJ_ID, HID_USAGES.HID_USAGE_Z); + + vj.SetBtn(wheel.buttons.btnA, VJ_ID, 1); + vj.SetBtn(wheel.buttons.btnB, VJ_ID, 2); + vj.SetBtn(wheel.buttons.btn1, VJ_ID, 3); + vj.SetBtn(wheel.buttons.btn2, VJ_ID, 4); + vj.SetBtn(wheel.buttons.btn3, VJ_ID, 5); + vj.SetBtn(wheel.buttons.btn4, VJ_ID, 6); + + vj.SetDiscPov( + wheel.povHat.center ? -1 : + wheel.povHat.north ? 0 : + wheel.povHat.east ? 1 : + wheel.povHat.south ? 2 : + wheel.povHat.west ? 3 : -1, + VJ_ID, 1); + vj_mutex.ReleaseMutex(); + } + + private static void handleQuery(IForceSerial.Query query) + { + Console.WriteLine("Query [" + query.type.ToString() + "]: " + BitConverter.ToString(query.data)); + } + + } +} diff --git a/WheelAdapter/Properties/AssemblyInfo.cs b/WheelAdapter/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..3100b79 --- /dev/null +++ b/WheelAdapter/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("WheelAdapter")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WheelAdapter")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("3e7e3973-6aea-4b3d-86bc-cbaf8a8fdd76")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/WheelAdapter/WheelAdapter.csproj b/WheelAdapter/WheelAdapter.csproj new file mode 100644 index 0000000..a3de0a1 --- /dev/null +++ b/WheelAdapter/WheelAdapter.csproj @@ -0,0 +1,83 @@ + + + + + Debug + AnyCPU + {3E7E3973-6AEA-4B3D-86BC-CBAF8A8FDD76} + Exe + WheelAdapter + WheelAdapter + v4.8 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + 7.3 + prompt + MinimumRecommendedRules.ruleset + true + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + 7.3 + prompt + MinimumRecommendedRules.ruleset + true + + + + + + + + + + + + False + dependencies\vJoyInterfaceWrap.dll + + + + + + + + + + + + + xcopy /y /d "$(ProjectDir)dependencies\*.dll" "$(TargetDir)" + + \ No newline at end of file diff --git a/WheelAdapter/dependencies/SDK/ReadMe.pdf b/WheelAdapter/dependencies/SDK/ReadMe.pdf new file mode 100644 index 0000000..4b249c5 Binary files /dev/null and b/WheelAdapter/dependencies/SDK/ReadMe.pdf differ diff --git a/WheelAdapter/dependencies/SDK/c#/FeederDemoCS/FeederDemoCS.csproj b/WheelAdapter/dependencies/SDK/c#/FeederDemoCS/FeederDemoCS.csproj new file mode 100644 index 0000000..8b55469 --- /dev/null +++ b/WheelAdapter/dependencies/SDK/c#/FeederDemoCS/FeederDemoCS.csproj @@ -0,0 +1,89 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {CCA62E05-B035-49F6-A3B4-ACD21CD562E4} + Exe + Properties + FeederDemoCS + FeederDemoCS + v2.0 + 512 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + False + ..\x64\vJoyInterfaceWrap.dll + + + + + + + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + + + + copy $(SolutionDir)..\x64\vJoyInterface.dll $(TargetDir). + + \ No newline at end of file diff --git a/WheelAdapter/dependencies/SDK/c#/FeederDemoCS/FeederDemoCS.sln b/WheelAdapter/dependencies/SDK/c#/FeederDemoCS/FeederDemoCS.sln new file mode 100644 index 0000000..438f834 --- /dev/null +++ b/WheelAdapter/dependencies/SDK/c#/FeederDemoCS/FeederDemoCS.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C# Express 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FeederDemoCS", "FeederDemoCS.csproj", "{CCA62E05-B035-49F6-A3B4-ACD21CD562E4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CCA62E05-B035-49F6-A3B4-ACD21CD562E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CCA62E05-B035-49F6-A3B4-ACD21CD562E4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CCA62E05-B035-49F6-A3B4-ACD21CD562E4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CCA62E05-B035-49F6-A3B4-ACD21CD562E4}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/WheelAdapter/dependencies/SDK/c#/FeederDemoCS/Program.cs b/WheelAdapter/dependencies/SDK/c#/FeederDemoCS/Program.cs new file mode 100644 index 0000000..5baceea --- /dev/null +++ b/WheelAdapter/dependencies/SDK/c#/FeederDemoCS/Program.cs @@ -0,0 +1,284 @@ +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// This project demonstrates how to write a simple vJoy feeder in C# +// +// You can compile it with either #define ROBUST OR #define EFFICIENT +// The fuctionality is similar - +// The ROBUST section demonstrate the usage of functions that are easy and safe to use but are less efficient +// The EFFICIENT ection demonstrate the usage of functions that are more efficient +// +// Functionality: +// The program starts with creating one joystick object. +// Then it petches the device id from the command-line and makes sure that it is within range +// After testing that the driver is enabled it gets information about the driver +// Gets information about the specified virtual device +// This feeder uses only a few axes. It checks their existence and +// checks the number of buttons and POV Hat switches. +// Then the feeder acquires the virtual device +// Here starts and endless loop that feedes data into the virtual device +// +///////////////////////////////////////////////////////////////////////////////////////////////////////// +#define ROBUST +//#define EFFICIENT + +using System; +using System.Collections.Generic; +using System.Text; + +// Don't forget to add this +using vJoyInterfaceWrap; + +namespace FeederDemoCS +{ + class Program + { + // Declaring one joystick (Device id 1) and a position structure. + static public vJoy joystick; + static public vJoy.JoystickState iReport; + static public uint id = 1; + + + static void Main(string[] args) + { + // Create one joystick object and a position structure. + joystick = new vJoy(); + iReport = new vJoy.JoystickState(); + + + // Device ID can only be in the range 1-16 + if (args.Length>0 && !String.IsNullOrEmpty(args[0])) + id = Convert.ToUInt32(args[0]); + if (id <= 0 || id > 16) + { + Console.WriteLine("Illegal device ID {0}\nExit!",id); + return; + } + + // Get the driver attributes (Vendor ID, Product ID, Version Number) + if (!joystick.vJoyEnabled()) + { + Console.WriteLine("vJoy driver not enabled: Failed Getting vJoy attributes.\n"); + return; + } + else + Console.WriteLine("Vendor: {0}\nProduct :{1}\nVersion Number:{2}\n", joystick.GetvJoyManufacturerString(), joystick.GetvJoyProductString(), joystick.GetvJoySerialNumberString()); + + // Get the state of the requested device + VjdStat status = joystick.GetVJDStatus(id); + switch (status) + { + case VjdStat.VJD_STAT_OWN: + Console.WriteLine("vJoy Device {0} is already owned by this feeder\n", id); + break; + case VjdStat.VJD_STAT_FREE: + Console.WriteLine("vJoy Device {0} is free\n", id); + break; + case VjdStat.VJD_STAT_BUSY: + Console.WriteLine("vJoy Device {0} is already owned by another feeder\nCannot continue\n", id); + return; + case VjdStat.VJD_STAT_MISS: + Console.WriteLine("vJoy Device {0} is not installed or disabled\nCannot continue\n", id); + return; + default: + Console.WriteLine("vJoy Device {0} general error\nCannot continue\n", id); + return; + }; + + // Check which axes are supported + bool AxisX = joystick.GetVJDAxisExist(id, HID_USAGES.HID_USAGE_X); + bool AxisY = joystick.GetVJDAxisExist(id, HID_USAGES.HID_USAGE_Y); + bool AxisZ = joystick.GetVJDAxisExist(id, HID_USAGES.HID_USAGE_Z); + bool AxisRX = joystick.GetVJDAxisExist(id, HID_USAGES.HID_USAGE_RX); + bool AxisRZ = joystick.GetVJDAxisExist(id, HID_USAGES.HID_USAGE_RZ); + // Get the number of buttons and POV Hat switchessupported by this vJoy device + int nButtons = joystick.GetVJDButtonNumber(id); + int ContPovNumber = joystick.GetVJDContPovNumber(id); + int DiscPovNumber = joystick.GetVJDDiscPovNumber(id); + + // Print results + Console.WriteLine("\nvJoy Device {0} capabilities:\n", id); + Console.WriteLine("Numner of buttons\t\t{0}\n", nButtons); + Console.WriteLine("Numner of Continuous POVs\t{0}\n", ContPovNumber); + Console.WriteLine("Numner of Descrete POVs\t\t{0}\n", DiscPovNumber); + Console.WriteLine("Axis X\t\t{0}\n", AxisX ? "Yes" : "No"); + Console.WriteLine("Axis Y\t\t{0}\n", AxisX ? "Yes" : "No"); + Console.WriteLine("Axis Z\t\t{0}\n", AxisX ? "Yes" : "No"); + Console.WriteLine("Axis Rx\t\t{0}\n", AxisRX ? "Yes" : "No"); + Console.WriteLine("Axis Rz\t\t{0}\n", AxisRZ ? "Yes" : "No"); + + // Test if DLL matches the driver + UInt32 DllVer = 0, DrvVer = 0; + bool match = joystick.DriverMatch(ref DllVer, ref DrvVer); + if (match) + Console.WriteLine("Version of Driver Matches DLL Version ({0:X})\n", DllVer); + else + Console.WriteLine("Version of Driver ({0:X}) does NOT match DLL Version ({1:X})\n", DrvVer, DllVer); + + + // Acquire the target + if ((status == VjdStat.VJD_STAT_OWN) || ((status == VjdStat.VJD_STAT_FREE) && (!joystick.AcquireVJD(id)))) + { + Console.WriteLine("Failed to acquire vJoy device number {0}.\n", id); + return ; + } + else + Console.WriteLine("Acquired: vJoy device number {0}.\n", id); + + Console.WriteLine("\npress enter to stat feeding"); + Console.ReadKey(true); + + int X, Y, Z, ZR, XR; + uint count = 0; + long maxval = 0; + + X = 20; + Y = 30; + Z = 40; + XR = 60; + ZR = 80; + + joystick.GetVJDAxisMax(id, HID_USAGES.HID_USAGE_X, ref maxval); + +#if ROBUST + bool res; + // Reset this device to default values + joystick.ResetVJD(id); + + // Feed the device in endless loop + while (true) + { + // Set position of 4 axes + res = joystick.SetAxis(X, id, HID_USAGES.HID_USAGE_X); + res = joystick.SetAxis(Y, id, HID_USAGES.HID_USAGE_Y); + res = joystick.SetAxis(Z, id, HID_USAGES.HID_USAGE_Z); + res = joystick.SetAxis(XR, id, HID_USAGES.HID_USAGE_RX); + res = joystick.SetAxis(ZR, id, HID_USAGES.HID_USAGE_RZ); + + // Press/Release Buttons + res = joystick.SetBtn(true, id, count / 50); + res = joystick.SetBtn(false, id, 1 + count / 50); + + // If Continuous POV hat switches installed - make them go round + // For high values - put the switches in neutral state + if (ContPovNumber>0) + { + if ((count * 70) < 30000) + { + res = joystick.SetContPov(((int)count * 70), id, 1); + res = joystick.SetContPov(((int)count * 70) + 2000, id, 2); + res = joystick.SetContPov(((int)count * 70) + 4000, id, 3); + res = joystick.SetContPov(((int)count * 70) + 6000, id, 4); + } + else + { + res = joystick.SetContPov(-1, id, 1); + res = joystick.SetContPov(-1, id, 2); + res = joystick.SetContPov(-1, id, 3); + res = joystick.SetContPov(-1, id, 4); + }; + }; + + // If Discrete POV hat switches installed - make them go round + // From time to time - put the switches in neutral state + if (DiscPovNumber>0) + { + if (count < 550) + { + joystick.SetDiscPov((((int)count / 20) + 0) % 4, id, 1); + joystick.SetDiscPov((((int)count / 20) + 1) % 4, id, 2); + joystick.SetDiscPov((((int)count / 20) + 2) % 4, id, 3); + joystick.SetDiscPov((((int)count / 20) + 3) % 4, id, 4); + } + else + { + joystick.SetDiscPov(-1, id, 1); + joystick.SetDiscPov(-1, id, 2); + joystick.SetDiscPov(-1, id, 3); + joystick.SetDiscPov(-1, id, 4); + }; + }; + + System.Threading.Thread.Sleep(20); + X += 150; if (X > maxval) X = 0; + Y += 250; if (Y > maxval) Y = 0; + Z += 350; if (Z > maxval) Z = 0; + XR += 220; if (XR > maxval) XR = 0; + ZR += 200; if (ZR > maxval) ZR = 0; + count++; + + if (count > 640) + count = 0; + + } // While (Robust) + +#endif // ROBUST +#if EFFICIENT + + byte[] pov = new byte[4]; + + while (true) + { + iReport.bDevice = (byte)id; + iReport.AxisX = X; + iReport.AxisY = Y; + iReport.AxisZ = Z; + iReport.AxisZRot = ZR; + iReport.AxisXRot = XR; + + // Set buttons one by one + iReport.Buttons = (uint)(0x1 << (int)(count / 20)); + + if (ContPovNumber>0) + { + // Make Continuous POV Hat spin + iReport.bHats = (count*70); + iReport.bHatsEx1 = (count*70)+3000; + iReport.bHatsEx2 = (count*70)+5000; + iReport.bHatsEx3 = 15000 - (count*70); + if ((count*70) > 36000) + { + iReport.bHats = 0xFFFFFFFF; // Neutral state + iReport.bHatsEx1 = 0xFFFFFFFF; // Neutral state + iReport.bHatsEx2 = 0xFFFFFFFF; // Neutral state + iReport.bHatsEx3 = 0xFFFFFFFF; // Neutral state + }; + } + else + { + // Make 5-position POV Hat spin + + pov[0] = (byte)(((count / 20) + 0)%4); + pov[1] = (byte)(((count / 20) + 1) % 4); + pov[2] = (byte)(((count / 20) + 2) % 4); + pov[3] = (byte)(((count / 20) + 3) % 4); + + iReport.bHats = (uint)(pov[3]<<12) | (uint)(pov[2]<<8) | (uint)(pov[1]<<4) | (uint)pov[0]; + if ((count) > 550) + iReport.bHats = 0xFFFFFFFF; // Neutral state + }; + + /*** Feed the driver with the position packet - is fails then wait for input then try to re-acquire device ***/ + if (!joystick.UpdateVJD(id, ref iReport)) + { + Console.WriteLine("Feeding vJoy device number {0} failed - try to enable device then press enter\n", id); + Console.ReadKey(true); + joystick.AcquireVJD(id); + } + + System.Threading.Thread.Sleep(20); + count++; + if (count > 640) count = 0; + + X += 150; if (X > maxval) X = 0; + Y += 250; if (Y > maxval) Y = 0; + Z += 350; if (Z > maxval) Z = 0; + XR += 220; if (XR > maxval) XR = 0; + ZR += 200; if (ZR > maxval) ZR = 0; + + }; // While + +#endif // EFFICIENT + + } // Main + } // class Program +} // namespace FeederDemoCS diff --git a/WheelAdapter/dependencies/SDK/c#/FeederDemoCS/Properties/AssemblyInfo.cs b/WheelAdapter/dependencies/SDK/c#/FeederDemoCS/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..adbaee7 --- /dev/null +++ b/WheelAdapter/dependencies/SDK/c#/FeederDemoCS/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("FeederDemoCS")] +[assembly: AssemblyDescription("C# Demo Feeder")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FeederDemoCS")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("05b30ba2-93f6-465e-bc70-0e01acc9ea17")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("2.0.1.0")] +[assembly: AssemblyFileVersion("2.0.1.0")] diff --git a/WheelAdapter/dependencies/SDK/c#/ReadMe.odt b/WheelAdapter/dependencies/SDK/c#/ReadMe.odt new file mode 100644 index 0000000..d84c4e2 Binary files /dev/null and b/WheelAdapter/dependencies/SDK/c#/ReadMe.odt differ diff --git a/WheelAdapter/dependencies/SDK/c#/ReadMe.pdf b/WheelAdapter/dependencies/SDK/c#/ReadMe.pdf new file mode 100644 index 0000000..0da1485 Binary files /dev/null and b/WheelAdapter/dependencies/SDK/c#/ReadMe.pdf differ diff --git a/WheelAdapter/dependencies/SDK/inc/public.h b/WheelAdapter/dependencies/SDK/inc/public.h new file mode 100644 index 0000000..57ff7e8 --- /dev/null +++ b/WheelAdapter/dependencies/SDK/inc/public.h @@ -0,0 +1,283 @@ +/*++ + +Copyright (c) Shaul Eizikovich. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + public.h + +Abstract: + + Public header file for the vJoy project + Developpers that need to interface with vJoy need to include this file + +Author: + + +Environment: + + kernel mode and User mode + +Notes: + + +Revision History: + + +--*/ +#ifndef _PUBLIC_H +#define _PUBLIC_H + +// Compilation directives +#define PPJOY_MODE +#undef PPJOY_MODE // Comment-out for compatibility mode + +#ifdef PPJOY_MODE +#include "PPJIoctl.h" +#endif + +#include // Definitions for controlling GUID initialization + +// Sideband comunication with vJoy Device +//{781EF630-72B2-11d2-B852-00C04FAD5101} +DEFINE_GUID(GUID_DEVINTERFACE_VJOY, 0x781EF630, 0x72B2, 0x11d2, 0xB8, 0x52, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x01); + +// +// Usage example: +// CreateFile(TEXT("\\\\.\\vJoy"), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); +#ifdef PPJOY_MODE +#define DEVICENAME_STRING "PPJoyIOCTL1" +#else +#define DEVICENAME_STRING "vJoy" +#endif +#define NTDEVICE_NAME_STRING "\\Device\\"DEVICENAME_STRING +#define SYMBOLIC_NAME_STRING "\\DosDevices\\"DEVICENAME_STRING +#define DOS_FILE_NAME "\\\\.\\"DEVICENAME_STRING +#define VJOY_INTERFACE L"Device_" + +// Version parts +#define VER_X_ 0 +#define VER_H_ 2 +#define VER_M_ 1 +#define VER_L_ 8 + +#define STRINGIFY_1(x) #x +#define STRINGIFY(x) STRINGIFY_1(x) +#define PASTE(x, y) x##y +#define MAKEWIDE(x) PASTE(L,x) + +// Device Attributes +// +#define VENDOR_N_ID 0x1234 +#define PRODUCT_N_ID 0xBEAD +#define VERSION_N (VER_L_ + 0x10*VER_M_ + 0x100*VER_H_ + 0x1000*VER_X_) + +// Device Strings +// +#define VENDOR_STR_ID L"Shaul Eizikovich" +#define PRODUCT_STR_ID L"vJoy - Virtual Joystick" +#define SERIALNUMBER_STR MAKEWIDE(STRINGIFY(VER_H_)) L"." MAKEWIDE(STRINGIFY(VER_M_)) L"." MAKEWIDE(STRINGIFY(VER_L_)) + +// Function codes; +//#define LOAD_POSITIONS 0x910 +//#define GETATTRIB 0x911 +// #define GET_FFB_DATA 0x00222912 // METHOD_OUT_DIRECT + FILE_DEVICE_UNKNOWN + FILE_ANY_ACCESS +//#define SET_FFB_STAT 0x913 // METHOD_NEITHER +//#define GET_FFB_STAT 0x916 + +#define F_LOAD_POSITIONS 0x910 +#define F_GETATTRIB 0x911 +#define F_GET_FFB_DATA 0x912 +#define F_SET_FFB_STAT 0x913 +#define F_GET_FFB_STAT 0x916 +#define F_GET_DEV_INFO 0x917 +#define F_IS_DRV_FFB_CAP 0x918 +#define F_IS_DRV_FFB_EN 0x919 +#define F_GET_DRV_DEV_MAX 0x91A +#define F_GET_DRV_DEV_EN 0x91B +#define F_IS_DEV_FFB_START 0x91C +#define F_GET_DEV_STAT 0x91D +#define F_GET_DRV_INFO 0x91E +#define F_RESET_DEV 0x91F +#define F_GET_POSITIONS 0x920 + +// IO Device Control codes; +#define IOCTL_VJOY_GET_ATTRIB CTL_CODE (FILE_DEVICE_UNKNOWN, GETATTRIB, METHOD_BUFFERED, FILE_WRITE_ACCESS) +#define LOAD_POSITIONS CTL_CODE (FILE_DEVICE_UNKNOWN, F_LOAD_POSITIONS, METHOD_BUFFERED, FILE_WRITE_ACCESS) +#define GET_POSITIONS CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_POSITIONS, METHOD_BUFFERED, FILE_READ_ACCESS) +#define GET_FFB_DATA CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_FFB_DATA, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) +#define SET_FFB_STAT CTL_CODE (FILE_DEVICE_UNKNOWN, F_SET_FFB_STAT, METHOD_NEITHER, FILE_ANY_ACCESS) +#define GET_FFB_STAT CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_FFB_STAT, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define GET_DEV_INFO CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_DEV_INFO, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IS_DRV_FFB_CAP CTL_CODE (FILE_DEVICE_UNKNOWN, F_IS_DRV_FFB_CAP, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IS_DRV_FFB_EN CTL_CODE (FILE_DEVICE_UNKNOWN, F_IS_DRV_FFB_EN, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define GET_DRV_DEV_MAX CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_DRV_DEV_MAX, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define GET_DRV_DEV_EN CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_DRV_DEV_EN, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IS_DEV_FFB_START CTL_CODE (FILE_DEVICE_UNKNOWN, F_IS_DEV_FFB_START, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define GET_DEV_STAT CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_DEV_STAT, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define GET_DRV_INFO CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_DRV_INFO, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define RESET_DEV CTL_CODE (FILE_DEVICE_UNKNOWN, F_RESET_DEV, METHOD_BUFFERED, FILE_WRITE_ACCESS) + +#ifndef __HIDPORT_H__ +// Copied from hidport.h +#define IOCTL_HID_SET_FEATURE 0xB0191 +#define IOCTL_HID_WRITE_REPORT 0xB000F + +#define MAX_N_DEVICES 16 // Maximum number of vJoy devices + + +typedef struct _HID_DEVICE_ATTRIBUTES { + + ULONG Size; + // + // sizeof (struct _HID_DEVICE_ATTRIBUTES) + // + + // + // Vendor ids of this hid device + // + USHORT VendorID; + USHORT ProductID; + USHORT VersionNumber; + USHORT Reserved[11]; + +} HID_DEVICE_ATTRIBUTES, * PHID_DEVICE_ATTRIBUTES; +#endif + +// Device Type +//enum DevType { vJoy, vXbox }; + +// Error levels for status report +enum ERRLEVEL {INFO, WARN, ERR, FATAL, APP}; +// Status report function prototype +#ifdef WINAPI +typedef BOOL (WINAPI *StatusMessageFunc)(void * output, TCHAR * buffer, enum ERRLEVEL level); +#endif + +/////////////////////////////////////////////////////////////// + +/////////////////////// Joystick Position /////////////////////// +// +// This structure holds data that is passed to the device from +// an external application such as SmartPropoPlus. +// +// Usage example: +// JOYSTICK_POSITION iReport; +// : +// DeviceIoControl (hDevice, 100, &iReport, sizeof(HID_INPUT_REPORT), NULL, 0, &bytes, NULL) +typedef struct _JOYSTICK_POSITION +{ + BYTE bDevice; // Index of device. 1-based. + LONG wThrottle; + LONG wRudder; + LONG wAileron; + LONG wAxisX; + LONG wAxisY; + LONG wAxisZ; + LONG wAxisXRot; + LONG wAxisYRot; + LONG wAxisZRot; + LONG wSlider; + LONG wDial; + LONG wWheel; + LONG wAxisVX; + LONG wAxisVY; + LONG wAxisVZ; + LONG wAxisVBRX; + LONG wAxisVBRY; + LONG wAxisVBRZ; + LONG lButtons; // 32 buttons: 0x00000001 means button1 is pressed, 0x80000000 -> button32 is pressed + DWORD bHats; // Lower 4 bits: HAT switch or 16-bit of continuous HAT switch + DWORD bHatsEx1; // 16-bit of continuous HAT switch + DWORD bHatsEx2; // 16-bit of continuous HAT switch + DWORD bHatsEx3; // 16-bit of continuous HAT switch +} JOYSTICK_POSITION, *PJOYSTICK_POSITION; + +// Superset of JOYSTICK_POSITION +// Extension of JOYSTICK_POSITION with Buttons 33-128 appended to the end of the structure. +typedef struct _JOYSTICK_POSITION_V2 +{ + /// JOYSTICK_POSITION + BYTE bDevice; // Index of device. 1-based. + LONG wThrottle; + LONG wRudder; + LONG wAileron; + LONG wAxisX; + LONG wAxisY; + LONG wAxisZ; + LONG wAxisXRot; + LONG wAxisYRot; + LONG wAxisZRot; + LONG wSlider; + LONG wDial; + LONG wWheel; + LONG wAxisVX; + LONG wAxisVY; + LONG wAxisVZ; + LONG wAxisVBRX; + LONG wAxisVBRY; + LONG wAxisVBRZ; + LONG lButtons; // 32 buttons: 0x00000001 means button1 is pressed, 0x80000000 -> button32 is pressed + DWORD bHats; // Lower 4 bits: HAT switch or 16-bit of continuous HAT switch + DWORD bHatsEx1; // Lower 4 bits: HAT switch or 16-bit of continuous HAT switch + DWORD bHatsEx2; // Lower 4 bits: HAT switch or 16-bit of continuous HAT switch + DWORD bHatsEx3; // Lower 4 bits: HAT switch or 16-bit of continuous HAT switch LONG lButtonsEx1; // Buttons 33-64 + + /// JOYSTICK_POSITION_V2 Extenssion + LONG lButtonsEx1; // Buttons 33-64 + LONG lButtonsEx2; // Buttons 65-96 + LONG lButtonsEx3; // Buttons 97-128 +} JOYSTICK_POSITION_V2, *PJOYSTICK_POSITION_V2; + + +// HID Descriptor definitions - Axes +#define HID_USAGE_X 0x30 +#define HID_USAGE_Y 0x31 +#define HID_USAGE_Z 0x32 +#define HID_USAGE_RX 0x33 +#define HID_USAGE_RY 0x34 +#define HID_USAGE_RZ 0x35 +#define HID_USAGE_SL0 0x36 +#define HID_USAGE_SL1 0x37 +#define HID_USAGE_WHL 0x38 +#define HID_USAGE_POV 0x39 + +// HID Descriptor definitions - FFB Effects +#define HID_USAGE_CONST 0x26 // Usage ET Constant Force +#define HID_USAGE_RAMP 0x27 // Usage ET Ramp +#define HID_USAGE_SQUR 0x30 // Usage ET Square +#define HID_USAGE_SINE 0x31 // Usage ET Sine +#define HID_USAGE_TRNG 0x32 // Usage ET Triangle +#define HID_USAGE_STUP 0x33 // Usage ET Sawtooth Up +#define HID_USAGE_STDN 0x34 // Usage ET Sawtooth Down +#define HID_USAGE_SPRNG 0x40 // Usage ET Spring +#define HID_USAGE_DMPR 0x41 // Usage ET Damper +#define HID_USAGE_INRT 0x42 // Usage ET Inertia +#define HID_USAGE_FRIC 0x43 // Usage ET Friction + + +// HID Descriptor definitions - FFB Report IDs +#define HID_ID_STATE 0x02 // Usage PID State report +#define HID_ID_EFFREP 0x01 // Usage Set Effect Report +#define HID_ID_ENVREP 0x02 // Usage Set Envelope Report +#define HID_ID_CONDREP 0x03 // Usage Set Condition Report +#define HID_ID_PRIDREP 0x04 // Usage Set Periodic Report +#define HID_ID_CONSTREP 0x05 // Usage Set Constant Force Report +#define HID_ID_RAMPREP 0x06 // Usage Set Ramp Force Report +#define HID_ID_CSTMREP 0x07 // Usage Custom Force Data Report +#define HID_ID_SMPLREP 0x08 // Usage Download Force Sample +#define HID_ID_EFOPREP 0x0A // Usage Effect Operation Report +#define HID_ID_BLKFRREP 0x0B // Usage PID Block Free Report +#define HID_ID_CTRLREP 0x0C // Usage PID Device Control +#define HID_ID_GAINREP 0x0D // Usage Device Gain Report +#define HID_ID_SETCREP 0x0E // Usage Set Custom Force Report +#define HID_ID_NEWEFREP 0x01 // Usage Create New Effect Report +#define HID_ID_BLKLDREP 0x02 // Usage Block Load Report +#define HID_ID_POOLREP 0x03 // Usage PID Pool Report + +#endif diff --git a/WheelAdapter/dependencies/SDK/inc/vjoyinterface.h b/WheelAdapter/dependencies/SDK/inc/vjoyinterface.h new file mode 100644 index 0000000..9cd4e25 --- /dev/null +++ b/WheelAdapter/dependencies/SDK/inc/vjoyinterface.h @@ -0,0 +1,366 @@ +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the VJOYINTERFACE_EXPORTS +// symbol defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// VJOYINTERFACE_API functions as being imported from a DLL, whereas this DLL sees symbols +// defined with this macro as being exported. +#ifdef VJOYINTERFACE_EXPORTS +#define VJOYINTERFACE_API __declspec(dllexport) +#else +#define VJOYINTERFACE_API __declspec(dllimport) +#endif + +#ifdef STATIC +#undef VJOYINTERFACE_API +#define VJOYINTERFACE_API +#endif + +///////////////////////////// vJoy device (collection) status //////////////////////////////////////////// +#ifndef VJDSTAT +#define VJDSTAT +enum VjdStat /* Declares an enumeration data type */ +{ + VJD_STAT_OWN, // The vJoy Device is owned by this application. + VJD_STAT_FREE, // The vJoy Device is NOT owned by any application (including this one). + VJD_STAT_BUSY, // The vJoy Device is owned by another application. It cannot be acquired by this application. + VJD_STAT_MISS, // The vJoy Device is missing. It either does not exist or the driver is down. + VJD_STAT_UNKN // Unknown +}; + +/* Error codes for some of the functions */ +#define NO_HANDLE_BY_INDEX -1 +#define BAD_PREPARSED_DATA -2 +#define NO_CAPS -3 +#define BAD_N_BTN_CAPS -4 +#define BAD_CALLOC -5 +#define BAD_BTN_CAPS -6 +#define BAD_BTN_RANGE -7 +#define BAD_N_VAL_CAPS -8 +#define BAD_ID_RANGE -9 +#define NO_SUCH_AXIS -10 +#define BAD_DEV_STAT -11 +#define NO_DEV_EXIST -12 +#define NO_FILE_EXIST -13 + +/* Registry Constants */ +#define REG_PARAM L"SYSTEM\\CurrentControlSet\\services\\vjoy\\Parameters" +#define REG_PARAM_DEV0 L"SYSTEM\\CurrentControlSet\\services\\vjoy\\Parameters\\Device0" +#define REG_PARAM_DEV L"SYSTEM\\CurrentControlSet\\services\\vjoy\\Parameters\\Device" +#define REG_DEVICE L"Device" +#define REG_INIT L"Init" +#define BTN_INIT L"BTNS" + +/* Environment Variables */ +#define INTERFACE_LOG_LEVEL "VJOYINTERFACELOGLEVEL" +#define INTERFACE_LOG_FILE "VJOYINTERFACELOGFILE" +#define INTERFACE_DEF_LOG_FILE "vJoyInterface.log" + +/* Compatibility definitions */ +#define FFB_EFF_CONST FFB_EFF_REPORT +#define PFFB_EFF_CONST PFFB_EFF_REPORT +#define Ffb_h_Eff_Const Ffb_h_Eff_Report + +// Device Axis/POVs/Buttons +struct DEVCTRLS { + BOOL Init; + BOOL Rudder; + BOOL Aileron; + BOOL AxisX; + BOOL AxisY; + BOOL AxisZ; + BOOL AxisXRot; + BOOL AxisYRot; + BOOL AxisZRot; + BOOL Slider; + BOOL Dial; + BOOL Wheel; + BOOL AxisVX; + BOOL AxisVY; + BOOL AxisVZ; + BOOL AxisVBRX; + BOOL AxisVBRY; + BOOL AxisVBRZ; + INT nButtons; + INT nDescHats; + INT nContHats; +}; + +struct DeviceStat { + HANDLE h; // Handle to the PDO interface that represents the virtual device + VjdStat stat; // Status of the device + JOYSTICK_POSITION_V2 position; // Current Position of the device + HDEVNOTIFY hDeviceNotifyHandle; // Device Notification Handle + DEVCTRLS DeviceControls; // Structure Holding the data about the device's controls + PVOID pPreParsedData; // structure contains a top-level collection's preparsed data. +}; + +struct DEV_INFO { + BYTE DeviceID; // Device ID: Valid values are 1-16 + BYTE nImplemented; // Number of implemented device: Valid values are 1-16 + BYTE isImplemented; // Is this device implemented? + BYTE MaxDevices; // Maximum number of devices that may be implemented (16) + BYTE DriverFFB; // Does this driver support FFB (False) + BYTE DeviceFFB; // Does this device support FFB (False) +} ; + + + +typedef void (CALLBACK *RemovalCB)(BOOL, BOOL, PVOID); + + +enum FFBEType // FFB Effect Type +{ + + // Effect Type + ET_NONE = 0, // No Force + ET_CONST = 1, // Constant Force + ET_RAMP = 2, // Ramp + ET_SQR = 3, // Square + ET_SINE = 4, // Sine + ET_TRNGL = 5, // Triangle + ET_STUP = 6, // Sawtooth Up + ET_STDN = 7, // Sawtooth Down + ET_SPRNG = 8, // Spring + ET_DMPR = 9, // Damper + ET_INRT = 10, // Inertia + ET_FRCTN = 11, // Friction + ET_CSTM = 12, // Custom Force Data +}; + +enum FFBPType // FFB Packet Type +{ + // Write + PT_EFFREP = HID_ID_EFFREP, // Usage Set Effect Report + PT_ENVREP = HID_ID_ENVREP, // Usage Set Envelope Report + PT_CONDREP = HID_ID_CONDREP, // Usage Set Condition Report + PT_PRIDREP = HID_ID_PRIDREP, // Usage Set Periodic Report + PT_CONSTREP = HID_ID_CONSTREP, // Usage Set Constant Force Report + PT_RAMPREP = HID_ID_RAMPREP, // Usage Set Ramp Force Report + PT_CSTMREP = HID_ID_CSTMREP, // Usage Custom Force Data Report + PT_SMPLREP = HID_ID_SMPLREP, // Usage Download Force Sample + PT_EFOPREP = HID_ID_EFOPREP, // Usage Effect Operation Report + PT_BLKFRREP = HID_ID_BLKFRREP, // Usage PID Block Free Report + PT_CTRLREP = HID_ID_CTRLREP, // Usage PID Device Control + PT_GAINREP = HID_ID_GAINREP, // Usage Device Gain Report + PT_SETCREP = HID_ID_SETCREP, // Usage Set Custom Force Report + + // Feature + PT_NEWEFREP = HID_ID_NEWEFREP+0x10, // Usage Create New Effect Report + PT_BLKLDREP = HID_ID_BLKLDREP+0x10, // Usage Block Load Report + PT_POOLREP = HID_ID_POOLREP+0x10, // Usage PID Pool Report +}; + +enum FFBOP +{ + EFF_START = 1, // EFFECT START + EFF_SOLO = 2, // EFFECT SOLO START + EFF_STOP = 3, // EFFECT STOP +}; + +enum FFB_CTRL +{ + CTRL_ENACT = 1, // Enable all device actuators. + CTRL_DISACT = 2, // Disable all the device actuators. + CTRL_STOPALL = 3, // Stop All Effects­ Issues a stop on every running effect. + CTRL_DEVRST = 4, // Device Reset– Clears any device paused condition, enables all actuators and clears all effects from memory. + CTRL_DEVPAUSE = 5, // Device Pause– The all effects on the device are paused at the current time step. + CTRL_DEVCONT = 6, // Device Continue– The all effects that running when the device was paused are restarted from their last time step. +}; + +enum FFB_EFFECTS { + Constant = 0x0001, + Ramp = 0x0002, + Square = 0x0004, + Sine = 0x0008, + Triangle = 0x0010, + Sawtooth_Up = 0x0020, + Sawtooth_Dn = 0x0040, + Spring = 0x0080, + Damper = 0x0100, + Inertia = 0x0200, + Friction = 0x0400, + Custom = 0x0800, +}; + +typedef struct _FFB_DATA { + ULONG size; + ULONG cmd; + UCHAR *data; +} FFB_DATA, * PFFB_DATA; + +typedef struct _FFB_EFF_CONSTANT { + BYTE EffectBlockIndex; + LONG Magnitude; // Constant force magnitude: -10000 - 10000 +} FFB_EFF_CONSTANT, *PFFB_EFF_CONSTANT; + +typedef struct _FFB_EFF_RAMP { + BYTE EffectBlockIndex; + LONG Start; // The Normalized magnitude at the start of the effect (-10000 - 10000) + LONG End; // The Normalized magnitude at the end of the effect (-10000 - 10000) +} FFB_EFF_RAMP, *PFFB_EFF_RAMP; + +//typedef struct _FFB_EFF_CONST { +typedef struct _FFB_EFF_REPORT { + BYTE EffectBlockIndex; + FFBEType EffectType; + WORD Duration;// Value in milliseconds. 0xFFFF means infinite + WORD TrigerRpt; + WORD SamplePrd; + BYTE Gain; + BYTE TrigerBtn; + BOOL Polar; // How to interpret force direction Polar (0-360°) or Cartesian (X,Y) + union + { + BYTE Direction; // Polar direction: (0x00-0xFF correspond to 0-360°) + BYTE DirX; // X direction: Positive values are To the right of the center (X); Negative are Two's complement + }; + BYTE DirY; // Y direction: Positive values are below the center (Y); Negative are Two's complement +} FFB_EFF_REPORT, *PFFB_EFF_REPORT; +//} FFB_EFF_CONST, *PFFB_EFF_CONST; + +typedef struct _FFB_EFF_OP { + BYTE EffectBlockIndex; + FFBOP EffectOp; + BYTE LoopCount; +} FFB_EFF_OP, *PFFB_EFF_OP; + +typedef struct _FFB_EFF_PERIOD { + BYTE EffectBlockIndex; + DWORD Magnitude; // Range: 0 - 10000 + LONG Offset; // Range: –10000 - 10000 + DWORD Phase; // Range: 0 - 35999 + DWORD Period; // Range: 0 - 32767 +} FFB_EFF_PERIOD, *PFFB_EFF_PERIOD; + +typedef struct _FFB_EFF_COND { + BYTE EffectBlockIndex; + BOOL isY; + LONG CenterPointOffset; // CP Offset: Range -­10000 ­- 10000 + LONG PosCoeff; // Positive Coefficient: Range -­10000 ­- 10000 + LONG NegCoeff; // Negative Coefficient: Range -­10000 ­- 10000 + DWORD PosSatur; // Positive Saturation: Range 0 – 10000 + DWORD NegSatur; // Negative Saturation: Range 0 – 10000 + LONG DeadBand; // Dead Band: : Range 0 – 1000 +} FFB_EFF_COND, *PFFB_EFF_COND; + +typedef struct _FFB_EFF_ENVLP { + BYTE EffectBlockIndex; + DWORD AttackLevel; // The Normalized magnitude of the stating point: 0 - 10000 + DWORD FadeLevel; // The Normalized magnitude of the stopping point: 0 - 10000 + DWORD AttackTime; // Time of the attack: 0 - 4294967295 + DWORD FadeTime; // Time of the fading: 0 - 4294967295 +} FFB_EFF_ENVLP, *PFFB_EFF_ENVLP; + +#define FFB_DATA_READY WM_USER+31 + +typedef void (CALLBACK *FfbGenCB)(PVOID, PVOID); +#endif + + +#ifndef STATIC + extern "C" { +#else +namespace vJoyNS { +#endif + ///////////////////////////// vJoy device (collection) Control interface ///////////////////////////////// + /* + These functions allow writing feeders and other applications that interface with vJoy + It is assumed that only one vJoy top-device (= Raw PDO) exists. + This top-level device can have up to 16 siblings (=top-level Reports/collections) + Each sibling is refered to as a "vJoy Device" and is attributed a unique Report ID (Range: 1-16). + + Naming convetion: + VJD = vJoy Device + rID = Report ID + */ +#pragma warning( push ) +#pragma warning( disable : 4995 ) + ///// General driver data + VJOYINTERFACE_API SHORT __cdecl GetvJoyVersion(void); + VJOYINTERFACE_API BOOL __cdecl vJoyEnabled(void); + VJOYINTERFACE_API PVOID __cdecl GetvJoyProductString(void); + VJOYINTERFACE_API PVOID __cdecl GetvJoyManufacturerString(void); + VJOYINTERFACE_API PVOID __cdecl GetvJoySerialNumberString(void); + VJOYINTERFACE_API BOOL __cdecl DriverMatch(WORD * DllVer, WORD * DrvVer); + VJOYINTERFACE_API VOID __cdecl RegisterRemovalCB(RemovalCB cb, PVOID data); + VJOYINTERFACE_API BOOL __cdecl vJoyFfbCap(BOOL * Supported); // Is this version of vJoy capable of FFB? + VJOYINTERFACE_API BOOL __cdecl GetvJoyMaxDevices(int * n); // What is the maximum possible number of vJoy devices + VJOYINTERFACE_API BOOL __cdecl GetNumberExistingVJD(int * n); // What is the number of vJoy devices currently enabled + + + ///// vJoy Device properties + VJOYINTERFACE_API int __cdecl GetVJDButtonNumber(UINT rID); // Get the number of buttons defined in the specified VDJ + VJOYINTERFACE_API int __cdecl GetVJDDiscPovNumber(UINT rID); // Get the number of descrete-type POV hats defined in the specified VDJ + VJOYINTERFACE_API int __cdecl GetVJDContPovNumber(UINT rID); // Get the number of descrete-type POV hats defined in the specified VDJ + VJOYINTERFACE_API BOOL __cdecl GetVJDAxisExist(UINT rID, UINT Axis); // Test if given axis defined in the specified VDJ + VJOYINTERFACE_API BOOL __cdecl GetVJDAxisMax(UINT rID, UINT Axis, LONG * Max); // Get logical Maximum value for a given axis defined in the specified VDJ + VJOYINTERFACE_API BOOL __cdecl GetVJDAxisMin(UINT rID, UINT Axis, LONG * Min); // Get logical Minimum value for a given axis defined in the specified VDJ + VJOYINTERFACE_API enum VjdStat __cdecl GetVJDStatus(UINT rID); // Get the status of the specified vJoy Device. + // Added in 2.1.6 + VJOYINTERFACE_API BOOL __cdecl isVJDExists(UINT rID); // TRUE if the specified vJoy Device exists + // Added in 2.1.8 + VJOYINTERFACE_API int __cdecl GetOwnerPid(UINT rID); // Reurn owner's Process ID if the specified vJoy Device exists + + + ///// Write access to vJoy Device - Basic + VJOYINTERFACE_API BOOL __cdecl AcquireVJD(UINT rID); // Acquire the specified vJoy Device. + VJOYINTERFACE_API VOID __cdecl RelinquishVJD(UINT rID); // Relinquish the specified vJoy Device. + VJOYINTERFACE_API BOOL __cdecl UpdateVJD(UINT rID, PVOID pData); // Update the position data of the specified vJoy Device. + + ///// Write access to vJoy Device - Modifyiers + // This group of functions modify the current value of the position data + // They replace the need to create a structure of position data then call UpdateVJD + + //// Reset functions + VJOYINTERFACE_API BOOL __cdecl ResetVJD(UINT rID); // Reset all controls to predefined values in the specified VDJ + VJOYINTERFACE_API VOID __cdecl ResetAll(void); // Reset all controls to predefined values in all VDJ + VJOYINTERFACE_API BOOL __cdecl ResetButtons(UINT rID); // Reset all buttons (To 0) in the specified VDJ + VJOYINTERFACE_API BOOL __cdecl ResetPovs(UINT rID); // Reset all POV Switches (To -1) in the specified VDJ + + // Write data + VJOYINTERFACE_API BOOL __cdecl SetAxis(LONG Value, UINT rID, UINT Axis); // Write Value to a given axis defined in the specified VDJ + VJOYINTERFACE_API BOOL __cdecl SetBtn(BOOL Value, UINT rID, UCHAR nBtn); // Write Value to a given button defined in the specified VDJ + VJOYINTERFACE_API BOOL __cdecl SetDiscPov(int Value, UINT rID, UCHAR nPov); // Write Value to a given descrete POV defined in the specified VDJ + VJOYINTERFACE_API BOOL __cdecl SetContPov(DWORD Value, UINT rID, UCHAR nPov); // Write Value to a given continuous POV defined in the specified VDJ + + +#pragma region FFB Function prototypes +// Force Feedback (FFB) functions + VJOYINTERFACE_API FFBEType __cdecl FfbGetEffect(); // Returns effect serial number if active, 0 if inactive + VJOYINTERFACE_API VOID __cdecl FfbRegisterGenCB(FfbGenCB cb, PVOID data); + __declspec(deprecated("** FfbStart function was deprecated - you can remove it from your code **")) \ + VJOYINTERFACE_API BOOL __cdecl FfbStart(UINT rID); // Start the FFB queues of the specified vJoy Device. + __declspec(deprecated("** FfbStop function was deprecated - you can remove it from your code **")) \ + VJOYINTERFACE_API VOID __cdecl FfbStop(UINT rID); // Stop the FFB queues of the specified vJoy Device. + + // Added in 2.1.6 + VJOYINTERFACE_API BOOL __cdecl IsDeviceFfb(UINT rID); + VJOYINTERFACE_API BOOL __cdecl IsDeviceFfbEffect(UINT rID, UINT Effect); + + // Force Feedback (FFB) helper functions + VJOYINTERFACE_API DWORD __cdecl Ffb_h_DeviceID(const FFB_DATA * Packet, int *DeviceID); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_Type(const FFB_DATA * Packet, FFBPType *Type); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_Packet(const FFB_DATA * Packet, WORD *Type, int *DataSize, BYTE *Data[]); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_EBI(const FFB_DATA * Packet, int *Index); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_Eff_Report(const FFB_DATA * Packet, FFB_EFF_REPORT* Effect); + __declspec(deprecated("** Ffb_h_Eff_Const function was deprecated - Use function Ffb_h_Eff_Report **")) \ + VJOYINTERFACE_API DWORD __cdecl Ffb_h_Eff_Const(const FFB_DATA * Packet, FFB_EFF_CONST* Effect); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_Eff_Ramp(const FFB_DATA * Packet, FFB_EFF_RAMP* RampEffect); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_EffOp(const FFB_DATA * Packet, FFB_EFF_OP* Operation); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_DevCtrl(const FFB_DATA * Packet, FFB_CTRL * Control); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_Eff_Period(const FFB_DATA * Packet, FFB_EFF_PERIOD* Effect); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_Eff_Cond(const FFB_DATA * Packet, FFB_EFF_COND* Condition); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_DevGain(const FFB_DATA * Packet, BYTE * Gain); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_Eff_Envlp(const FFB_DATA * Packet, FFB_EFF_ENVLP* Envelope); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_EffNew(const FFB_DATA * Packet, FFBEType * Effect); + + // Added in 2.1.6 + VJOYINTERFACE_API DWORD __cdecl Ffb_h_Eff_Constant(const FFB_DATA * Packet, FFB_EFF_CONSTANT * ConstantEffect); +#pragma endregion + +#pragma warning( pop ) +#ifndef STATIC + } // extern "C" +#else +} // Namespace vJoyNS +#endif diff --git a/WheelAdapter/dependencies/SDK/lib/amd64/vJoyInterface.dll b/WheelAdapter/dependencies/SDK/lib/amd64/vJoyInterface.dll new file mode 100644 index 0000000..0c5c3d9 Binary files /dev/null and b/WheelAdapter/dependencies/SDK/lib/amd64/vJoyInterface.dll differ diff --git a/WheelAdapter/dependencies/SDK/lib/amd64/vJoyInterface.lib b/WheelAdapter/dependencies/SDK/lib/amd64/vJoyInterface.lib new file mode 100644 index 0000000..4b005b9 Binary files /dev/null and b/WheelAdapter/dependencies/SDK/lib/amd64/vJoyInterface.lib differ diff --git a/WheelAdapter/dependencies/SDK/lib/vJoyInterface.dll b/WheelAdapter/dependencies/SDK/lib/vJoyInterface.dll new file mode 100644 index 0000000..68f36bd Binary files /dev/null and b/WheelAdapter/dependencies/SDK/lib/vJoyInterface.dll differ diff --git a/WheelAdapter/dependencies/SDK/lib/vJoyInterface.lib b/WheelAdapter/dependencies/SDK/lib/vJoyInterface.lib new file mode 100644 index 0000000..c205ae9 Binary files /dev/null and b/WheelAdapter/dependencies/SDK/lib/vJoyInterface.lib differ diff --git a/WheelAdapter/dependencies/SDK/src/stdafx.h b/WheelAdapter/dependencies/SDK/src/stdafx.h new file mode 100644 index 0000000..99dee4e --- /dev/null +++ b/WheelAdapter/dependencies/SDK/src/stdafx.h @@ -0,0 +1,21 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/WheelAdapter/dependencies/SDK/src/vJoyClient.cpp b/WheelAdapter/dependencies/SDK/src/vJoyClient.cpp new file mode 100644 index 0000000..68578bd --- /dev/null +++ b/WheelAdapter/dependencies/SDK/src/vJoyClient.cpp @@ -0,0 +1,571 @@ +// vJoyClient.cpp : Simple feeder application with a FFB demo +// + + +// Monitor Force Feedback (FFB) vJoy device +#include "stdafx.h" +//#include "Devioctl.h" +#include "public.h" +#include +#include +#include +#include "vjoyinterface.h" +#include "Math.h" + +// Default device ID (Used when ID not specified) +#define DEV_ID 1 + +// Prototypes +void CALLBACK FfbFunction(PVOID data); +void CALLBACK FfbFunction1(PVOID cb, PVOID data); + +BOOL PacketType2Str(FFBPType Type, LPTSTR Str); +BOOL EffectType2Str(FFBEType Ctrl, LPTSTR Str); +BOOL DevCtrl2Str(FFB_CTRL Type, LPTSTR Str); +BOOL EffectOpStr(FFBOP Op, LPTSTR Str); +int Polar2Deg(BYTE Polar); +int Byte2Percent(BYTE InByte); +int TwosCompByte2Int(BYTE in); + + +int ffb_direction = 0; +int ffb_strenght = 0; +int serial_result = 0; + + +JOYSTICK_POSITION_V2 iReport; // The structure that holds the full position data + +int +__cdecl +_tmain(int argc, _TCHAR* argv[]) +{ + int stat = 0; + UINT DevID = DEV_ID; + USHORT X = 0; + USHORT Y = 0; + USHORT Z = 0; + LONG Btns = 0; + + + PVOID pPositionMessage; + UINT IoCode = LOAD_POSITIONS; + UINT IoSize = sizeof(JOYSTICK_POSITION); + // HID_DEVICE_ATTRIBUTES attrib; + BYTE id = 1; + UINT iInterface = 1; + + // Define the effect names + static FFBEType FfbEffect= (FFBEType)-1; + LPCTSTR FfbEffectName[] = + {"NONE", "Constant Force", "Ramp", "Square", "Sine", "Triangle", "Sawtooth Up",\ + "Sawtooth Down", "Spring", "Damper", "Inertia", "Friction", "Custom Force"}; + + // Set the target Joystick - get it from the command-line + if (argc>1) + DevID = _tstoi(argv[1]); + + // Get the driver attributes (Vendor ID, Product ID, Version Number) + if (!vJoyEnabled()) + { + _tprintf("Function vJoyEnabled Failed - make sure that vJoy is installed and enabled\n"); + int dummy = getchar(); + stat = - 2; + goto Exit; + } + else + { + wprintf(L"Vendor: %s\nProduct :%s\nVersion Number:%s\n", static_cast (GetvJoyManufacturerString()), static_cast(GetvJoyProductString()), static_cast(GetvJoySerialNumberString())); + }; + + // Get the status of the vJoy device before trying to acquire it + VjdStat status = GetVJDStatus(DevID); + + switch (status) + { + case VJD_STAT_OWN: + _tprintf("vJoy device %d is already owned by this feeder\n", DevID); + break; + case VJD_STAT_FREE: + _tprintf("vJoy device %d is free\n", DevID); + break; + case VJD_STAT_BUSY: + _tprintf("vJoy device %d is already owned by another feeder\nCannot continue\n", DevID); + return -3; + case VJD_STAT_MISS: + _tprintf("vJoy device %d is not installed or disabled\nCannot continue\n", DevID); + return -4; + default: + _tprintf("vJoy device %d general error\nCannot continue\n", DevID); + return -1; + }; + + // Acquire the vJoy device + if (!AcquireVJD(DevID)) + { + _tprintf("Failed to acquire vJoy device number %d.\n", DevID); + int dummy = getchar(); + stat = -1; + goto Exit; + } + else + _tprintf("Acquired device number %d - OK\n", DevID); + + + + // Start FFB +#if 1 + BOOL Ffbstarted = FfbStart(DevID); + if (!Ffbstarted) + { + _tprintf("Failed to start FFB on vJoy device number %d.\n", DevID); + int dummy = getchar(); + stat = -3; + goto Exit; + } + else + _tprintf("Started FFB on vJoy device number %d - OK\n", DevID); + +#endif // 1 + + // Register Generic callback function + // At this point you instruct the Receptor which callback function to call with every FFB packet it receives + // It is the role of the designer to register the right FFB callback function + FfbRegisterGenCB(FfbFunction1, NULL); + + + + + // Start endless loop + // The loop injects position data to the vJoy device + // If it fails it let's the user try again + // + // FFB Note: + // All FFB activity is performed in a separate thread created when registered the callback function + while (1) + { + + // Set destenition vJoy device + id = (BYTE)DevID; + iReport.bDevice = id; + + // Set position data of 3 first axes + if (Z>35000) Z=0; + Z += 200; + iReport.wAxisZ = Z; + iReport.wAxisX = 32000-Z; + iReport.wAxisY = Z/2+7000; + + // Set position data of first 8 buttons + Btns = 1<<(Z/4000); + iReport.lButtons = Btns; + + // Send position data to vJoy device + pPositionMessage = (PVOID)(&iReport); + if (!UpdateVJD(DevID, pPositionMessage)) + { + printf("Feeding vJoy device number %d failed - try to enable device then press enter\n", DevID); + getchar(); + AcquireVJD(DevID); + } + Sleep(2); + } + +Exit: + RelinquishVJD(DevID); + return 0; +} + + +// Generic callback function +void CALLBACK FfbFunction(PVOID data) +{ + FFB_DATA * FfbData = (FFB_DATA *)data; + int size = FfbData->size; + _tprintf("\nFFB Size %d\n", size); + + _tprintf("Cmd:%08.8X ", FfbData->cmd); + _tprintf("ID:%02.2X ", FfbData->data[0]); + _tprintf("Size:%02.2d ", static_cast(FfbData->size - 8)); + _tprintf(" - "); + for (UINT i = 0; i < FfbData->size - 8; i++) + _tprintf(" %02.2X", (UINT)FfbData->data); + _tprintf("\n"); +} + +void CALLBACK FfbFunction1(PVOID data, PVOID userdata) +{ + // Packet Header + _tprintf("\n ============= FFB Packet size Size %d =============\n", static_cast(((FFB_DATA *)data)->size)); + + /////// Packet Device ID, and Type Block Index (if exists) +#pragma region Packet Device ID, and Type Block Index + int DeviceID, BlockIndex; + FFBPType Type; + TCHAR TypeStr[100]; + + if (ERROR_SUCCESS == Ffb_h_DeviceID((FFB_DATA *)data, &DeviceID)) + _tprintf("\n > Device ID: %d", DeviceID); + if (ERROR_SUCCESS == Ffb_h_Type((FFB_DATA *)data, &Type)) + { + if (!PacketType2Str(Type, TypeStr)) + _tprintf("\n > Packet Type: %d", Type); + else + _tprintf("\n > Packet Type: %s", TypeStr); + + } + if (ERROR_SUCCESS == Ffb_h_EBI((FFB_DATA *)data, &BlockIndex)) + _tprintf("\n > Effect Block Index: %d", BlockIndex); +#pragma endregion + + + /////// Effect Report +#pragma region Effect Report + FFB_EFF_CONST Effect; + if (ERROR_SUCCESS == Ffb_h_Eff_Report((FFB_DATA *)data, &Effect)) + { + if (!EffectType2Str(Effect.EffectType, TypeStr)) + _tprintf("\n >> Effect Report: %02x", Effect.EffectType); + else + _tprintf("\n >> Effect Report: %s", TypeStr); + + if (Effect.Polar) + { + _tprintf("\n >> Direction: %d deg (%02x)", Polar2Deg(Effect.Direction), Effect.Direction); + + + } + else + { + _tprintf("\n >> X Direction: %02x", Effect.DirX); + _tprintf("\n >> Y Direction: %02x", Effect.DirY); + }; + + if (Effect.Duration == 0xFFFF) + _tprintf("\n >> Duration: Infinit"); + else + _tprintf("\n >> Duration: %d MilliSec", static_cast(Effect.Duration)); + + if (Effect.TrigerRpt == 0xFFFF) + _tprintf("\n >> Trigger Repeat: Infinit"); + else + _tprintf("\n >> Trigger Repeat: %d", static_cast(Effect.TrigerRpt)); + + if (Effect.SamplePrd == 0xFFFF) + _tprintf("\n >> Sample Period: Infinit"); + else + _tprintf("\n >> Sample Period: %d", static_cast(Effect.SamplePrd)); + + + _tprintf("\n >> Gain: %d%%", Byte2Percent(Effect.Gain)); + + }; +#pragma endregion +#pragma region PID Device Control + FFB_CTRL Control; + TCHAR CtrlStr[100]; + if (ERROR_SUCCESS == Ffb_h_DevCtrl((FFB_DATA *)data, &Control) && DevCtrl2Str(Control, CtrlStr)) + _tprintf("\n >> PID Device Control: %s", CtrlStr); + +#pragma endregion +#pragma region Effect Operation + FFB_EFF_OP Operation; + TCHAR EffOpStr[100]; + if (ERROR_SUCCESS == Ffb_h_EffOp((FFB_DATA *)data, &Operation) && EffectOpStr(Operation.EffectOp, EffOpStr)) + { + _tprintf("\n >> Effect Operation: %s", EffOpStr); + if (Operation.LoopCount == 0xFF) + _tprintf("\n >> Loop until stopped"); + else + _tprintf("\n >> Loop %d times", static_cast(Operation.LoopCount)); + + }; +#pragma endregion +#pragma region Global Device Gain + BYTE Gain; + if (ERROR_SUCCESS == Ffb_h_DevGain((FFB_DATA *)data, &Gain)) + _tprintf("\n >> Global Device Gain: %d", Byte2Percent(Gain)); + +#pragma endregion +#pragma region Condition + FFB_EFF_COND Condition; + if (ERROR_SUCCESS == Ffb_h_Eff_Cond((FFB_DATA *)data, &Condition)) + { + if (Condition.isY) + _tprintf("\n >> Y Axis"); + else + _tprintf("\n >> X Axis"); + _tprintf("\n >> Center Point Offset: %d", TwosCompByte2Int(Condition.CenterPointOffset)*10000/127); + _tprintf("\n >> Positive Coefficient: %d", TwosCompByte2Int(Condition.PosCoeff)*10000/127); + _tprintf("\n >> Negative Coefficient: %d", TwosCompByte2Int(Condition.NegCoeff)*10000/127); + _tprintf("\n >> Positive Saturation: %d", Condition.PosSatur*10000/255); + _tprintf("\n >> Negative Saturation: %d", Condition.NegSatur*10000/255); + _tprintf("\n >> Dead Band: %d", Condition.DeadBand*10000/255); + } +#pragma endregion +#pragma region Envelope + FFB_EFF_ENVLP Envelope; + if (ERROR_SUCCESS == Ffb_h_Eff_Envlp((FFB_DATA *)data, &Envelope)) + { + _tprintf("\n >> Attack Level: %d", Envelope.AttackLevel*10000/255); + _tprintf("\n >> Fade Level: %d", Envelope.FadeLevel*10000/255); + _tprintf("\n >> Attack Time: %d", static_cast(Envelope.AttackTime)); + _tprintf("\n >> Fade Time: %d", static_cast(Envelope.FadeTime)); + }; + +#pragma endregion +#pragma region Periodic + FFB_EFF_PERIOD EffPrd; + if (ERROR_SUCCESS == Ffb_h_Eff_Period((FFB_DATA *)data, &EffPrd)) + { + _tprintf("\n >> Magnitude: %d", EffPrd.Magnitude * 10000 / 255); + _tprintf("\n >> Offset: %d", TwosCompByte2Int(EffPrd.Offset) * 10000 / 127); + _tprintf("\n >> Phase: %d", EffPrd.Phase * 3600 / 255); + _tprintf("\n >> Period: %d", static_cast(EffPrd.Period)); + }; +#pragma endregion + +#pragma region Effect Type + FFBEType EffectType; + if (ERROR_SUCCESS == Ffb_h_EffNew((FFB_DATA *)data, &EffectType)) + { + if (EffectType2Str(EffectType, TypeStr)) + _tprintf("\n >> Effect Type: %s", TypeStr); + else + _tprintf("\n >> Effect Type: Unknown"); + } + +#pragma endregion + +#pragma region Ramp Effect + FFB_EFF_RAMP RampEffect; + if (ERROR_SUCCESS == Ffb_h_Eff_Ramp((FFB_DATA *)data, &RampEffect)) + { + _tprintf("\n >> Ramp Start: %d", TwosCompByte2Int(RampEffect.Start) * 10000 / 127); + _tprintf("\n >> Ramp End: %d", TwosCompByte2Int(RampEffect.End) * 10000 / 127); + }; + +#pragma endregion + + _tprintf("\n"); + FfbFunction(data); + _tprintf("\n ====================================================\n"); + +} + + +// Convert Packet type to String +BOOL PacketType2Str(FFBPType Type, LPTSTR OutStr) +{ + BOOL stat = TRUE; + LPTSTR Str=""; + + switch (Type) + { + case PT_EFFREP: + Str = "Effect Report"; + break; + case PT_ENVREP: + Str = "Envelope Report"; + break; + case PT_CONDREP: + Str = "Condition Report"; + break; + case PT_PRIDREP: + Str = "Periodic Report"; + break; + case PT_CONSTREP: + Str = "Constant Force Report"; + break; + case PT_RAMPREP: + Str = "Ramp Force Report"; + break; + case PT_CSTMREP: + Str = "Custom Force Data Report"; + break; + case PT_SMPLREP: + Str = "Download Force Sample"; + break; + case PT_EFOPREP: + Str = "Effect Operation Report"; + break; + case PT_BLKFRREP: + Str = "PID Block Free Report"; + break; + case PT_CTRLREP: + Str = "PID Device Contro"; + break; + case PT_GAINREP: + Str = "Device Gain Report"; + break; + case PT_SETCREP: + Str = "Set Custom Force Report"; + break; + case PT_NEWEFREP: + Str = "Create New Effect Report"; + break; + case PT_BLKLDREP: + Str = "Block Load Report"; + break; + case PT_POOLREP: + Str = "PID Pool Report"; + break; + default: + stat = FALSE; + break; + } + + if (stat) + _tcscpy_s(OutStr, 100, Str); + + return stat; +} + +// Convert Effect type to String +BOOL EffectType2Str(FFBEType Type, LPTSTR OutStr) +{ + BOOL stat = TRUE; + LPTSTR Str=""; + + switch (Type) + { + case ET_NONE: + stat = FALSE; + break; + case ET_CONST: + Str="Constant Force"; + break; + case ET_RAMP: + Str="Ramp"; + break; + case ET_SQR: + Str="Square"; + break; + case ET_SINE: + Str="Sine"; + break; + case ET_TRNGL: + Str="Triangle"; + break; + case ET_STUP: + Str="Sawtooth Up"; + break; + case ET_STDN: + Str="Sawtooth Down"; + break; + case ET_SPRNG: + Str="Spring"; + break; + case ET_DMPR: + Str="Damper"; + break; + case ET_INRT: + Str="Inertia"; + break; + case ET_FRCTN: + Str="Friction"; + break; + case ET_CSTM: + Str="Custom Force"; + break; + default: + stat = FALSE; + break; + }; + + if (stat) + _tcscpy_s(OutStr, 100, Str); + + return stat; +} + +// Convert PID Device Control to String +BOOL DevCtrl2Str(FFB_CTRL Ctrl, LPTSTR OutStr) +{ + BOOL stat = TRUE; + LPTSTR Str=""; + + switch (Ctrl) + { + case CTRL_ENACT: + Str="Enable Actuators"; + break; + case CTRL_DISACT: + Str="Disable Actuators"; + break; + case CTRL_STOPALL: + Str="Stop All Effects"; + break; + case CTRL_DEVRST: + Str="Device Reset"; + break; + case CTRL_DEVPAUSE: + Str="Device Pause"; + break; + case CTRL_DEVCONT: + Str="Device Continue"; + break; + default: + stat = FALSE; + break; + } + if (stat) + _tcscpy_s(OutStr, 100, Str); + + return stat; +} + +// Convert Effect operation to string +BOOL EffectOpStr(FFBOP Op, LPTSTR OutStr) +{ + BOOL stat = TRUE; + LPTSTR Str=""; + + switch (Op) + { + case EFF_START: + Str="Effect Start"; + break; + case EFF_SOLO: + Str="Effect Solo Start"; + break; + case EFF_STOP: + Str="Effect Stop"; + break; + default: + stat = FALSE; + break; + } + + if (stat) + _tcscpy_s(OutStr, 100, Str); + + return stat; +} + +// Polar values (0x00-0xFF) to Degrees (0-360) +int Polar2Deg(BYTE Polar) +{ + return ((UINT)Polar*360)/255; +} + +// Convert range 0x00-0xFF to 0%-100% +int Byte2Percent(BYTE InByte) +{ + return ((UINT)InByte*100)/255; +} + +// Convert One-Byte 2's complement input to integer +int TwosCompByte2Int(BYTE in) +{ + int tmp; + BYTE inv = ~in; + BOOL isNeg = in>>7; + if (isNeg) + { + tmp = (int)(inv); + tmp = -1*tmp; + return tmp; + } + else + return (int)in; +} diff --git a/WheelAdapter/dependencies/SDK/src/vJoyClient.sln b/WheelAdapter/dependencies/SDK/src/vJoyClient.sln new file mode 100644 index 0000000..d0ac10b --- /dev/null +++ b/WheelAdapter/dependencies/SDK/src/vJoyClient.sln @@ -0,0 +1,32 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C++ Express 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vJoyClient", "vJoyClient.vcproj", "{A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Rel64|Win32 = Rel64|Win32 + Rel64|x64 = Rel64|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Debug|Win32.ActiveCfg = Debug|Win32 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Debug|Win32.Build.0 = Debug|Win32 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Debug|x64.ActiveCfg = Debug|x64 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Debug|x64.Build.0 = Debug|x64 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Rel64|Win32.ActiveCfg = Rel64|Win32 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Rel64|Win32.Build.0 = Rel64|Win32 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Rel64|x64.ActiveCfg = Rel64|x64 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Rel64|x64.Build.0 = Rel64|x64 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Release|Win32.ActiveCfg = Release|Win32 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Release|Win32.Build.0 = Release|Win32 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Release|x64.ActiveCfg = Release|x64 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/WheelAdapter/dependencies/SDK/src/vJoyClient.vcproj b/WheelAdapter/dependencies/SDK/src/vJoyClient.vcproj new file mode 100644 index 0000000..e673862 --- /dev/null +++ b/WheelAdapter/dependencies/SDK/src/vJoyClient.vcproj @@ -0,0 +1,529 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WheelAdapter/dependencies/SDK_218/CreateSdk.bat b/WheelAdapter/dependencies/SDK_218/CreateSdk.bat new file mode 100644 index 0000000..a73d1b1 --- /dev/null +++ b/WheelAdapter/dependencies/SDK_218/CreateSdk.bat @@ -0,0 +1,17 @@ +REM Automate the creation of an SDK package + +REM C# +COPY ..\X64\Release\vJoyInterface.dll ".\c#\x64\vJoyInterface.dll" +COPY ..\X64\Release\vJoyInterfaceWrap.dll ".\c#\x64\vJoyInterfaceWrap.dll" +COPY ..\Win32\Release\vJoyInterface.dll ".\c#\x86\vJoyInterface.dll" +COPY ..\Win32\Release\vJoyInterfaceWrap.dll ".\c#\x86\vJoyInterfaceWrap.dll" + +REM Include Files +COPY ..\Inc\public.h .\Inc\public.h +COPY ..\apps\common\vJoyInterface\vjoyinterface.h .\Inc\vjoyinterface.h + +REM Library Files +COPY ..\Win32\Release\vJoyInterface.dll .\LIB\vJoyInterface.dll +COPY ..\Win32\Release\vJoyInterface.lib .\LIB\vJoyInterface.lib +COPY ..\X64\Release\vJoyInterface.dll .\LIB\amd64\vJoyInterface.dll +COPY ..\X64\Release\vJoyInterface.lib .\LIB\amd64\vJoyInterface.lib diff --git a/WheelAdapter/dependencies/SDK_218/ReadMe.pdf b/WheelAdapter/dependencies/SDK_218/ReadMe.pdf new file mode 100644 index 0000000..4b249c5 Binary files /dev/null and b/WheelAdapter/dependencies/SDK_218/ReadMe.pdf differ diff --git a/WheelAdapter/dependencies/SDK_218/c#/FeederDemoCS/FeederDemoCS.csproj b/WheelAdapter/dependencies/SDK_218/c#/FeederDemoCS/FeederDemoCS.csproj new file mode 100644 index 0000000..8b55469 --- /dev/null +++ b/WheelAdapter/dependencies/SDK_218/c#/FeederDemoCS/FeederDemoCS.csproj @@ -0,0 +1,89 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {CCA62E05-B035-49F6-A3B4-ACD21CD562E4} + Exe + Properties + FeederDemoCS + FeederDemoCS + v2.0 + 512 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + False + ..\x64\vJoyInterfaceWrap.dll + + + + + + + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + + + + copy $(SolutionDir)..\x64\vJoyInterface.dll $(TargetDir). + + \ No newline at end of file diff --git a/WheelAdapter/dependencies/SDK_218/c#/FeederDemoCS/FeederDemoCS.sln b/WheelAdapter/dependencies/SDK_218/c#/FeederDemoCS/FeederDemoCS.sln new file mode 100644 index 0000000..438f834 --- /dev/null +++ b/WheelAdapter/dependencies/SDK_218/c#/FeederDemoCS/FeederDemoCS.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C# Express 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FeederDemoCS", "FeederDemoCS.csproj", "{CCA62E05-B035-49F6-A3B4-ACD21CD562E4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CCA62E05-B035-49F6-A3B4-ACD21CD562E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CCA62E05-B035-49F6-A3B4-ACD21CD562E4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CCA62E05-B035-49F6-A3B4-ACD21CD562E4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CCA62E05-B035-49F6-A3B4-ACD21CD562E4}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/WheelAdapter/dependencies/SDK_218/c#/FeederDemoCS/Program.cs b/WheelAdapter/dependencies/SDK_218/c#/FeederDemoCS/Program.cs new file mode 100644 index 0000000..5baceea --- /dev/null +++ b/WheelAdapter/dependencies/SDK_218/c#/FeederDemoCS/Program.cs @@ -0,0 +1,284 @@ +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// This project demonstrates how to write a simple vJoy feeder in C# +// +// You can compile it with either #define ROBUST OR #define EFFICIENT +// The fuctionality is similar - +// The ROBUST section demonstrate the usage of functions that are easy and safe to use but are less efficient +// The EFFICIENT ection demonstrate the usage of functions that are more efficient +// +// Functionality: +// The program starts with creating one joystick object. +// Then it petches the device id from the command-line and makes sure that it is within range +// After testing that the driver is enabled it gets information about the driver +// Gets information about the specified virtual device +// This feeder uses only a few axes. It checks their existence and +// checks the number of buttons and POV Hat switches. +// Then the feeder acquires the virtual device +// Here starts and endless loop that feedes data into the virtual device +// +///////////////////////////////////////////////////////////////////////////////////////////////////////// +#define ROBUST +//#define EFFICIENT + +using System; +using System.Collections.Generic; +using System.Text; + +// Don't forget to add this +using vJoyInterfaceWrap; + +namespace FeederDemoCS +{ + class Program + { + // Declaring one joystick (Device id 1) and a position structure. + static public vJoy joystick; + static public vJoy.JoystickState iReport; + static public uint id = 1; + + + static void Main(string[] args) + { + // Create one joystick object and a position structure. + joystick = new vJoy(); + iReport = new vJoy.JoystickState(); + + + // Device ID can only be in the range 1-16 + if (args.Length>0 && !String.IsNullOrEmpty(args[0])) + id = Convert.ToUInt32(args[0]); + if (id <= 0 || id > 16) + { + Console.WriteLine("Illegal device ID {0}\nExit!",id); + return; + } + + // Get the driver attributes (Vendor ID, Product ID, Version Number) + if (!joystick.vJoyEnabled()) + { + Console.WriteLine("vJoy driver not enabled: Failed Getting vJoy attributes.\n"); + return; + } + else + Console.WriteLine("Vendor: {0}\nProduct :{1}\nVersion Number:{2}\n", joystick.GetvJoyManufacturerString(), joystick.GetvJoyProductString(), joystick.GetvJoySerialNumberString()); + + // Get the state of the requested device + VjdStat status = joystick.GetVJDStatus(id); + switch (status) + { + case VjdStat.VJD_STAT_OWN: + Console.WriteLine("vJoy Device {0} is already owned by this feeder\n", id); + break; + case VjdStat.VJD_STAT_FREE: + Console.WriteLine("vJoy Device {0} is free\n", id); + break; + case VjdStat.VJD_STAT_BUSY: + Console.WriteLine("vJoy Device {0} is already owned by another feeder\nCannot continue\n", id); + return; + case VjdStat.VJD_STAT_MISS: + Console.WriteLine("vJoy Device {0} is not installed or disabled\nCannot continue\n", id); + return; + default: + Console.WriteLine("vJoy Device {0} general error\nCannot continue\n", id); + return; + }; + + // Check which axes are supported + bool AxisX = joystick.GetVJDAxisExist(id, HID_USAGES.HID_USAGE_X); + bool AxisY = joystick.GetVJDAxisExist(id, HID_USAGES.HID_USAGE_Y); + bool AxisZ = joystick.GetVJDAxisExist(id, HID_USAGES.HID_USAGE_Z); + bool AxisRX = joystick.GetVJDAxisExist(id, HID_USAGES.HID_USAGE_RX); + bool AxisRZ = joystick.GetVJDAxisExist(id, HID_USAGES.HID_USAGE_RZ); + // Get the number of buttons and POV Hat switchessupported by this vJoy device + int nButtons = joystick.GetVJDButtonNumber(id); + int ContPovNumber = joystick.GetVJDContPovNumber(id); + int DiscPovNumber = joystick.GetVJDDiscPovNumber(id); + + // Print results + Console.WriteLine("\nvJoy Device {0} capabilities:\n", id); + Console.WriteLine("Numner of buttons\t\t{0}\n", nButtons); + Console.WriteLine("Numner of Continuous POVs\t{0}\n", ContPovNumber); + Console.WriteLine("Numner of Descrete POVs\t\t{0}\n", DiscPovNumber); + Console.WriteLine("Axis X\t\t{0}\n", AxisX ? "Yes" : "No"); + Console.WriteLine("Axis Y\t\t{0}\n", AxisX ? "Yes" : "No"); + Console.WriteLine("Axis Z\t\t{0}\n", AxisX ? "Yes" : "No"); + Console.WriteLine("Axis Rx\t\t{0}\n", AxisRX ? "Yes" : "No"); + Console.WriteLine("Axis Rz\t\t{0}\n", AxisRZ ? "Yes" : "No"); + + // Test if DLL matches the driver + UInt32 DllVer = 0, DrvVer = 0; + bool match = joystick.DriverMatch(ref DllVer, ref DrvVer); + if (match) + Console.WriteLine("Version of Driver Matches DLL Version ({0:X})\n", DllVer); + else + Console.WriteLine("Version of Driver ({0:X}) does NOT match DLL Version ({1:X})\n", DrvVer, DllVer); + + + // Acquire the target + if ((status == VjdStat.VJD_STAT_OWN) || ((status == VjdStat.VJD_STAT_FREE) && (!joystick.AcquireVJD(id)))) + { + Console.WriteLine("Failed to acquire vJoy device number {0}.\n", id); + return ; + } + else + Console.WriteLine("Acquired: vJoy device number {0}.\n", id); + + Console.WriteLine("\npress enter to stat feeding"); + Console.ReadKey(true); + + int X, Y, Z, ZR, XR; + uint count = 0; + long maxval = 0; + + X = 20; + Y = 30; + Z = 40; + XR = 60; + ZR = 80; + + joystick.GetVJDAxisMax(id, HID_USAGES.HID_USAGE_X, ref maxval); + +#if ROBUST + bool res; + // Reset this device to default values + joystick.ResetVJD(id); + + // Feed the device in endless loop + while (true) + { + // Set position of 4 axes + res = joystick.SetAxis(X, id, HID_USAGES.HID_USAGE_X); + res = joystick.SetAxis(Y, id, HID_USAGES.HID_USAGE_Y); + res = joystick.SetAxis(Z, id, HID_USAGES.HID_USAGE_Z); + res = joystick.SetAxis(XR, id, HID_USAGES.HID_USAGE_RX); + res = joystick.SetAxis(ZR, id, HID_USAGES.HID_USAGE_RZ); + + // Press/Release Buttons + res = joystick.SetBtn(true, id, count / 50); + res = joystick.SetBtn(false, id, 1 + count / 50); + + // If Continuous POV hat switches installed - make them go round + // For high values - put the switches in neutral state + if (ContPovNumber>0) + { + if ((count * 70) < 30000) + { + res = joystick.SetContPov(((int)count * 70), id, 1); + res = joystick.SetContPov(((int)count * 70) + 2000, id, 2); + res = joystick.SetContPov(((int)count * 70) + 4000, id, 3); + res = joystick.SetContPov(((int)count * 70) + 6000, id, 4); + } + else + { + res = joystick.SetContPov(-1, id, 1); + res = joystick.SetContPov(-1, id, 2); + res = joystick.SetContPov(-1, id, 3); + res = joystick.SetContPov(-1, id, 4); + }; + }; + + // If Discrete POV hat switches installed - make them go round + // From time to time - put the switches in neutral state + if (DiscPovNumber>0) + { + if (count < 550) + { + joystick.SetDiscPov((((int)count / 20) + 0) % 4, id, 1); + joystick.SetDiscPov((((int)count / 20) + 1) % 4, id, 2); + joystick.SetDiscPov((((int)count / 20) + 2) % 4, id, 3); + joystick.SetDiscPov((((int)count / 20) + 3) % 4, id, 4); + } + else + { + joystick.SetDiscPov(-1, id, 1); + joystick.SetDiscPov(-1, id, 2); + joystick.SetDiscPov(-1, id, 3); + joystick.SetDiscPov(-1, id, 4); + }; + }; + + System.Threading.Thread.Sleep(20); + X += 150; if (X > maxval) X = 0; + Y += 250; if (Y > maxval) Y = 0; + Z += 350; if (Z > maxval) Z = 0; + XR += 220; if (XR > maxval) XR = 0; + ZR += 200; if (ZR > maxval) ZR = 0; + count++; + + if (count > 640) + count = 0; + + } // While (Robust) + +#endif // ROBUST +#if EFFICIENT + + byte[] pov = new byte[4]; + + while (true) + { + iReport.bDevice = (byte)id; + iReport.AxisX = X; + iReport.AxisY = Y; + iReport.AxisZ = Z; + iReport.AxisZRot = ZR; + iReport.AxisXRot = XR; + + // Set buttons one by one + iReport.Buttons = (uint)(0x1 << (int)(count / 20)); + + if (ContPovNumber>0) + { + // Make Continuous POV Hat spin + iReport.bHats = (count*70); + iReport.bHatsEx1 = (count*70)+3000; + iReport.bHatsEx2 = (count*70)+5000; + iReport.bHatsEx3 = 15000 - (count*70); + if ((count*70) > 36000) + { + iReport.bHats = 0xFFFFFFFF; // Neutral state + iReport.bHatsEx1 = 0xFFFFFFFF; // Neutral state + iReport.bHatsEx2 = 0xFFFFFFFF; // Neutral state + iReport.bHatsEx3 = 0xFFFFFFFF; // Neutral state + }; + } + else + { + // Make 5-position POV Hat spin + + pov[0] = (byte)(((count / 20) + 0)%4); + pov[1] = (byte)(((count / 20) + 1) % 4); + pov[2] = (byte)(((count / 20) + 2) % 4); + pov[3] = (byte)(((count / 20) + 3) % 4); + + iReport.bHats = (uint)(pov[3]<<12) | (uint)(pov[2]<<8) | (uint)(pov[1]<<4) | (uint)pov[0]; + if ((count) > 550) + iReport.bHats = 0xFFFFFFFF; // Neutral state + }; + + /*** Feed the driver with the position packet - is fails then wait for input then try to re-acquire device ***/ + if (!joystick.UpdateVJD(id, ref iReport)) + { + Console.WriteLine("Feeding vJoy device number {0} failed - try to enable device then press enter\n", id); + Console.ReadKey(true); + joystick.AcquireVJD(id); + } + + System.Threading.Thread.Sleep(20); + count++; + if (count > 640) count = 0; + + X += 150; if (X > maxval) X = 0; + Y += 250; if (Y > maxval) Y = 0; + Z += 350; if (Z > maxval) Z = 0; + XR += 220; if (XR > maxval) XR = 0; + ZR += 200; if (ZR > maxval) ZR = 0; + + }; // While + +#endif // EFFICIENT + + } // Main + } // class Program +} // namespace FeederDemoCS diff --git a/WheelAdapter/dependencies/SDK_218/c#/FeederDemoCS/Properties/AssemblyInfo.cs b/WheelAdapter/dependencies/SDK_218/c#/FeederDemoCS/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..adbaee7 --- /dev/null +++ b/WheelAdapter/dependencies/SDK_218/c#/FeederDemoCS/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("FeederDemoCS")] +[assembly: AssemblyDescription("C# Demo Feeder")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FeederDemoCS")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("05b30ba2-93f6-465e-bc70-0e01acc9ea17")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("2.0.1.0")] +[assembly: AssemblyFileVersion("2.0.1.0")] diff --git a/WheelAdapter/dependencies/SDK_218/c#/ReadMe.pdf b/WheelAdapter/dependencies/SDK_218/c#/ReadMe.pdf new file mode 100644 index 0000000..0da1485 Binary files /dev/null and b/WheelAdapter/dependencies/SDK_218/c#/ReadMe.pdf differ diff --git a/WheelAdapter/dependencies/SDK_218/inc/public.h b/WheelAdapter/dependencies/SDK_218/inc/public.h new file mode 100644 index 0000000..57ff7e8 --- /dev/null +++ b/WheelAdapter/dependencies/SDK_218/inc/public.h @@ -0,0 +1,283 @@ +/*++ + +Copyright (c) Shaul Eizikovich. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + public.h + +Abstract: + + Public header file for the vJoy project + Developpers that need to interface with vJoy need to include this file + +Author: + + +Environment: + + kernel mode and User mode + +Notes: + + +Revision History: + + +--*/ +#ifndef _PUBLIC_H +#define _PUBLIC_H + +// Compilation directives +#define PPJOY_MODE +#undef PPJOY_MODE // Comment-out for compatibility mode + +#ifdef PPJOY_MODE +#include "PPJIoctl.h" +#endif + +#include // Definitions for controlling GUID initialization + +// Sideband comunication with vJoy Device +//{781EF630-72B2-11d2-B852-00C04FAD5101} +DEFINE_GUID(GUID_DEVINTERFACE_VJOY, 0x781EF630, 0x72B2, 0x11d2, 0xB8, 0x52, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x01); + +// +// Usage example: +// CreateFile(TEXT("\\\\.\\vJoy"), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); +#ifdef PPJOY_MODE +#define DEVICENAME_STRING "PPJoyIOCTL1" +#else +#define DEVICENAME_STRING "vJoy" +#endif +#define NTDEVICE_NAME_STRING "\\Device\\"DEVICENAME_STRING +#define SYMBOLIC_NAME_STRING "\\DosDevices\\"DEVICENAME_STRING +#define DOS_FILE_NAME "\\\\.\\"DEVICENAME_STRING +#define VJOY_INTERFACE L"Device_" + +// Version parts +#define VER_X_ 0 +#define VER_H_ 2 +#define VER_M_ 1 +#define VER_L_ 8 + +#define STRINGIFY_1(x) #x +#define STRINGIFY(x) STRINGIFY_1(x) +#define PASTE(x, y) x##y +#define MAKEWIDE(x) PASTE(L,x) + +// Device Attributes +// +#define VENDOR_N_ID 0x1234 +#define PRODUCT_N_ID 0xBEAD +#define VERSION_N (VER_L_ + 0x10*VER_M_ + 0x100*VER_H_ + 0x1000*VER_X_) + +// Device Strings +// +#define VENDOR_STR_ID L"Shaul Eizikovich" +#define PRODUCT_STR_ID L"vJoy - Virtual Joystick" +#define SERIALNUMBER_STR MAKEWIDE(STRINGIFY(VER_H_)) L"." MAKEWIDE(STRINGIFY(VER_M_)) L"." MAKEWIDE(STRINGIFY(VER_L_)) + +// Function codes; +//#define LOAD_POSITIONS 0x910 +//#define GETATTRIB 0x911 +// #define GET_FFB_DATA 0x00222912 // METHOD_OUT_DIRECT + FILE_DEVICE_UNKNOWN + FILE_ANY_ACCESS +//#define SET_FFB_STAT 0x913 // METHOD_NEITHER +//#define GET_FFB_STAT 0x916 + +#define F_LOAD_POSITIONS 0x910 +#define F_GETATTRIB 0x911 +#define F_GET_FFB_DATA 0x912 +#define F_SET_FFB_STAT 0x913 +#define F_GET_FFB_STAT 0x916 +#define F_GET_DEV_INFO 0x917 +#define F_IS_DRV_FFB_CAP 0x918 +#define F_IS_DRV_FFB_EN 0x919 +#define F_GET_DRV_DEV_MAX 0x91A +#define F_GET_DRV_DEV_EN 0x91B +#define F_IS_DEV_FFB_START 0x91C +#define F_GET_DEV_STAT 0x91D +#define F_GET_DRV_INFO 0x91E +#define F_RESET_DEV 0x91F +#define F_GET_POSITIONS 0x920 + +// IO Device Control codes; +#define IOCTL_VJOY_GET_ATTRIB CTL_CODE (FILE_DEVICE_UNKNOWN, GETATTRIB, METHOD_BUFFERED, FILE_WRITE_ACCESS) +#define LOAD_POSITIONS CTL_CODE (FILE_DEVICE_UNKNOWN, F_LOAD_POSITIONS, METHOD_BUFFERED, FILE_WRITE_ACCESS) +#define GET_POSITIONS CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_POSITIONS, METHOD_BUFFERED, FILE_READ_ACCESS) +#define GET_FFB_DATA CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_FFB_DATA, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) +#define SET_FFB_STAT CTL_CODE (FILE_DEVICE_UNKNOWN, F_SET_FFB_STAT, METHOD_NEITHER, FILE_ANY_ACCESS) +#define GET_FFB_STAT CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_FFB_STAT, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define GET_DEV_INFO CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_DEV_INFO, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IS_DRV_FFB_CAP CTL_CODE (FILE_DEVICE_UNKNOWN, F_IS_DRV_FFB_CAP, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IS_DRV_FFB_EN CTL_CODE (FILE_DEVICE_UNKNOWN, F_IS_DRV_FFB_EN, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define GET_DRV_DEV_MAX CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_DRV_DEV_MAX, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define GET_DRV_DEV_EN CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_DRV_DEV_EN, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IS_DEV_FFB_START CTL_CODE (FILE_DEVICE_UNKNOWN, F_IS_DEV_FFB_START, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define GET_DEV_STAT CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_DEV_STAT, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define GET_DRV_INFO CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_DRV_INFO, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define RESET_DEV CTL_CODE (FILE_DEVICE_UNKNOWN, F_RESET_DEV, METHOD_BUFFERED, FILE_WRITE_ACCESS) + +#ifndef __HIDPORT_H__ +// Copied from hidport.h +#define IOCTL_HID_SET_FEATURE 0xB0191 +#define IOCTL_HID_WRITE_REPORT 0xB000F + +#define MAX_N_DEVICES 16 // Maximum number of vJoy devices + + +typedef struct _HID_DEVICE_ATTRIBUTES { + + ULONG Size; + // + // sizeof (struct _HID_DEVICE_ATTRIBUTES) + // + + // + // Vendor ids of this hid device + // + USHORT VendorID; + USHORT ProductID; + USHORT VersionNumber; + USHORT Reserved[11]; + +} HID_DEVICE_ATTRIBUTES, * PHID_DEVICE_ATTRIBUTES; +#endif + +// Device Type +//enum DevType { vJoy, vXbox }; + +// Error levels for status report +enum ERRLEVEL {INFO, WARN, ERR, FATAL, APP}; +// Status report function prototype +#ifdef WINAPI +typedef BOOL (WINAPI *StatusMessageFunc)(void * output, TCHAR * buffer, enum ERRLEVEL level); +#endif + +/////////////////////////////////////////////////////////////// + +/////////////////////// Joystick Position /////////////////////// +// +// This structure holds data that is passed to the device from +// an external application such as SmartPropoPlus. +// +// Usage example: +// JOYSTICK_POSITION iReport; +// : +// DeviceIoControl (hDevice, 100, &iReport, sizeof(HID_INPUT_REPORT), NULL, 0, &bytes, NULL) +typedef struct _JOYSTICK_POSITION +{ + BYTE bDevice; // Index of device. 1-based. + LONG wThrottle; + LONG wRudder; + LONG wAileron; + LONG wAxisX; + LONG wAxisY; + LONG wAxisZ; + LONG wAxisXRot; + LONG wAxisYRot; + LONG wAxisZRot; + LONG wSlider; + LONG wDial; + LONG wWheel; + LONG wAxisVX; + LONG wAxisVY; + LONG wAxisVZ; + LONG wAxisVBRX; + LONG wAxisVBRY; + LONG wAxisVBRZ; + LONG lButtons; // 32 buttons: 0x00000001 means button1 is pressed, 0x80000000 -> button32 is pressed + DWORD bHats; // Lower 4 bits: HAT switch or 16-bit of continuous HAT switch + DWORD bHatsEx1; // 16-bit of continuous HAT switch + DWORD bHatsEx2; // 16-bit of continuous HAT switch + DWORD bHatsEx3; // 16-bit of continuous HAT switch +} JOYSTICK_POSITION, *PJOYSTICK_POSITION; + +// Superset of JOYSTICK_POSITION +// Extension of JOYSTICK_POSITION with Buttons 33-128 appended to the end of the structure. +typedef struct _JOYSTICK_POSITION_V2 +{ + /// JOYSTICK_POSITION + BYTE bDevice; // Index of device. 1-based. + LONG wThrottle; + LONG wRudder; + LONG wAileron; + LONG wAxisX; + LONG wAxisY; + LONG wAxisZ; + LONG wAxisXRot; + LONG wAxisYRot; + LONG wAxisZRot; + LONG wSlider; + LONG wDial; + LONG wWheel; + LONG wAxisVX; + LONG wAxisVY; + LONG wAxisVZ; + LONG wAxisVBRX; + LONG wAxisVBRY; + LONG wAxisVBRZ; + LONG lButtons; // 32 buttons: 0x00000001 means button1 is pressed, 0x80000000 -> button32 is pressed + DWORD bHats; // Lower 4 bits: HAT switch or 16-bit of continuous HAT switch + DWORD bHatsEx1; // Lower 4 bits: HAT switch or 16-bit of continuous HAT switch + DWORD bHatsEx2; // Lower 4 bits: HAT switch or 16-bit of continuous HAT switch + DWORD bHatsEx3; // Lower 4 bits: HAT switch or 16-bit of continuous HAT switch LONG lButtonsEx1; // Buttons 33-64 + + /// JOYSTICK_POSITION_V2 Extenssion + LONG lButtonsEx1; // Buttons 33-64 + LONG lButtonsEx2; // Buttons 65-96 + LONG lButtonsEx3; // Buttons 97-128 +} JOYSTICK_POSITION_V2, *PJOYSTICK_POSITION_V2; + + +// HID Descriptor definitions - Axes +#define HID_USAGE_X 0x30 +#define HID_USAGE_Y 0x31 +#define HID_USAGE_Z 0x32 +#define HID_USAGE_RX 0x33 +#define HID_USAGE_RY 0x34 +#define HID_USAGE_RZ 0x35 +#define HID_USAGE_SL0 0x36 +#define HID_USAGE_SL1 0x37 +#define HID_USAGE_WHL 0x38 +#define HID_USAGE_POV 0x39 + +// HID Descriptor definitions - FFB Effects +#define HID_USAGE_CONST 0x26 // Usage ET Constant Force +#define HID_USAGE_RAMP 0x27 // Usage ET Ramp +#define HID_USAGE_SQUR 0x30 // Usage ET Square +#define HID_USAGE_SINE 0x31 // Usage ET Sine +#define HID_USAGE_TRNG 0x32 // Usage ET Triangle +#define HID_USAGE_STUP 0x33 // Usage ET Sawtooth Up +#define HID_USAGE_STDN 0x34 // Usage ET Sawtooth Down +#define HID_USAGE_SPRNG 0x40 // Usage ET Spring +#define HID_USAGE_DMPR 0x41 // Usage ET Damper +#define HID_USAGE_INRT 0x42 // Usage ET Inertia +#define HID_USAGE_FRIC 0x43 // Usage ET Friction + + +// HID Descriptor definitions - FFB Report IDs +#define HID_ID_STATE 0x02 // Usage PID State report +#define HID_ID_EFFREP 0x01 // Usage Set Effect Report +#define HID_ID_ENVREP 0x02 // Usage Set Envelope Report +#define HID_ID_CONDREP 0x03 // Usage Set Condition Report +#define HID_ID_PRIDREP 0x04 // Usage Set Periodic Report +#define HID_ID_CONSTREP 0x05 // Usage Set Constant Force Report +#define HID_ID_RAMPREP 0x06 // Usage Set Ramp Force Report +#define HID_ID_CSTMREP 0x07 // Usage Custom Force Data Report +#define HID_ID_SMPLREP 0x08 // Usage Download Force Sample +#define HID_ID_EFOPREP 0x0A // Usage Effect Operation Report +#define HID_ID_BLKFRREP 0x0B // Usage PID Block Free Report +#define HID_ID_CTRLREP 0x0C // Usage PID Device Control +#define HID_ID_GAINREP 0x0D // Usage Device Gain Report +#define HID_ID_SETCREP 0x0E // Usage Set Custom Force Report +#define HID_ID_NEWEFREP 0x01 // Usage Create New Effect Report +#define HID_ID_BLKLDREP 0x02 // Usage Block Load Report +#define HID_ID_POOLREP 0x03 // Usage PID Pool Report + +#endif diff --git a/WheelAdapter/dependencies/SDK_218/inc/vjoyinterface.h b/WheelAdapter/dependencies/SDK_218/inc/vjoyinterface.h new file mode 100644 index 0000000..9cd4e25 --- /dev/null +++ b/WheelAdapter/dependencies/SDK_218/inc/vjoyinterface.h @@ -0,0 +1,366 @@ +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the VJOYINTERFACE_EXPORTS +// symbol defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// VJOYINTERFACE_API functions as being imported from a DLL, whereas this DLL sees symbols +// defined with this macro as being exported. +#ifdef VJOYINTERFACE_EXPORTS +#define VJOYINTERFACE_API __declspec(dllexport) +#else +#define VJOYINTERFACE_API __declspec(dllimport) +#endif + +#ifdef STATIC +#undef VJOYINTERFACE_API +#define VJOYINTERFACE_API +#endif + +///////////////////////////// vJoy device (collection) status //////////////////////////////////////////// +#ifndef VJDSTAT +#define VJDSTAT +enum VjdStat /* Declares an enumeration data type */ +{ + VJD_STAT_OWN, // The vJoy Device is owned by this application. + VJD_STAT_FREE, // The vJoy Device is NOT owned by any application (including this one). + VJD_STAT_BUSY, // The vJoy Device is owned by another application. It cannot be acquired by this application. + VJD_STAT_MISS, // The vJoy Device is missing. It either does not exist or the driver is down. + VJD_STAT_UNKN // Unknown +}; + +/* Error codes for some of the functions */ +#define NO_HANDLE_BY_INDEX -1 +#define BAD_PREPARSED_DATA -2 +#define NO_CAPS -3 +#define BAD_N_BTN_CAPS -4 +#define BAD_CALLOC -5 +#define BAD_BTN_CAPS -6 +#define BAD_BTN_RANGE -7 +#define BAD_N_VAL_CAPS -8 +#define BAD_ID_RANGE -9 +#define NO_SUCH_AXIS -10 +#define BAD_DEV_STAT -11 +#define NO_DEV_EXIST -12 +#define NO_FILE_EXIST -13 + +/* Registry Constants */ +#define REG_PARAM L"SYSTEM\\CurrentControlSet\\services\\vjoy\\Parameters" +#define REG_PARAM_DEV0 L"SYSTEM\\CurrentControlSet\\services\\vjoy\\Parameters\\Device0" +#define REG_PARAM_DEV L"SYSTEM\\CurrentControlSet\\services\\vjoy\\Parameters\\Device" +#define REG_DEVICE L"Device" +#define REG_INIT L"Init" +#define BTN_INIT L"BTNS" + +/* Environment Variables */ +#define INTERFACE_LOG_LEVEL "VJOYINTERFACELOGLEVEL" +#define INTERFACE_LOG_FILE "VJOYINTERFACELOGFILE" +#define INTERFACE_DEF_LOG_FILE "vJoyInterface.log" + +/* Compatibility definitions */ +#define FFB_EFF_CONST FFB_EFF_REPORT +#define PFFB_EFF_CONST PFFB_EFF_REPORT +#define Ffb_h_Eff_Const Ffb_h_Eff_Report + +// Device Axis/POVs/Buttons +struct DEVCTRLS { + BOOL Init; + BOOL Rudder; + BOOL Aileron; + BOOL AxisX; + BOOL AxisY; + BOOL AxisZ; + BOOL AxisXRot; + BOOL AxisYRot; + BOOL AxisZRot; + BOOL Slider; + BOOL Dial; + BOOL Wheel; + BOOL AxisVX; + BOOL AxisVY; + BOOL AxisVZ; + BOOL AxisVBRX; + BOOL AxisVBRY; + BOOL AxisVBRZ; + INT nButtons; + INT nDescHats; + INT nContHats; +}; + +struct DeviceStat { + HANDLE h; // Handle to the PDO interface that represents the virtual device + VjdStat stat; // Status of the device + JOYSTICK_POSITION_V2 position; // Current Position of the device + HDEVNOTIFY hDeviceNotifyHandle; // Device Notification Handle + DEVCTRLS DeviceControls; // Structure Holding the data about the device's controls + PVOID pPreParsedData; // structure contains a top-level collection's preparsed data. +}; + +struct DEV_INFO { + BYTE DeviceID; // Device ID: Valid values are 1-16 + BYTE nImplemented; // Number of implemented device: Valid values are 1-16 + BYTE isImplemented; // Is this device implemented? + BYTE MaxDevices; // Maximum number of devices that may be implemented (16) + BYTE DriverFFB; // Does this driver support FFB (False) + BYTE DeviceFFB; // Does this device support FFB (False) +} ; + + + +typedef void (CALLBACK *RemovalCB)(BOOL, BOOL, PVOID); + + +enum FFBEType // FFB Effect Type +{ + + // Effect Type + ET_NONE = 0, // No Force + ET_CONST = 1, // Constant Force + ET_RAMP = 2, // Ramp + ET_SQR = 3, // Square + ET_SINE = 4, // Sine + ET_TRNGL = 5, // Triangle + ET_STUP = 6, // Sawtooth Up + ET_STDN = 7, // Sawtooth Down + ET_SPRNG = 8, // Spring + ET_DMPR = 9, // Damper + ET_INRT = 10, // Inertia + ET_FRCTN = 11, // Friction + ET_CSTM = 12, // Custom Force Data +}; + +enum FFBPType // FFB Packet Type +{ + // Write + PT_EFFREP = HID_ID_EFFREP, // Usage Set Effect Report + PT_ENVREP = HID_ID_ENVREP, // Usage Set Envelope Report + PT_CONDREP = HID_ID_CONDREP, // Usage Set Condition Report + PT_PRIDREP = HID_ID_PRIDREP, // Usage Set Periodic Report + PT_CONSTREP = HID_ID_CONSTREP, // Usage Set Constant Force Report + PT_RAMPREP = HID_ID_RAMPREP, // Usage Set Ramp Force Report + PT_CSTMREP = HID_ID_CSTMREP, // Usage Custom Force Data Report + PT_SMPLREP = HID_ID_SMPLREP, // Usage Download Force Sample + PT_EFOPREP = HID_ID_EFOPREP, // Usage Effect Operation Report + PT_BLKFRREP = HID_ID_BLKFRREP, // Usage PID Block Free Report + PT_CTRLREP = HID_ID_CTRLREP, // Usage PID Device Control + PT_GAINREP = HID_ID_GAINREP, // Usage Device Gain Report + PT_SETCREP = HID_ID_SETCREP, // Usage Set Custom Force Report + + // Feature + PT_NEWEFREP = HID_ID_NEWEFREP+0x10, // Usage Create New Effect Report + PT_BLKLDREP = HID_ID_BLKLDREP+0x10, // Usage Block Load Report + PT_POOLREP = HID_ID_POOLREP+0x10, // Usage PID Pool Report +}; + +enum FFBOP +{ + EFF_START = 1, // EFFECT START + EFF_SOLO = 2, // EFFECT SOLO START + EFF_STOP = 3, // EFFECT STOP +}; + +enum FFB_CTRL +{ + CTRL_ENACT = 1, // Enable all device actuators. + CTRL_DISACT = 2, // Disable all the device actuators. + CTRL_STOPALL = 3, // Stop All Effects­ Issues a stop on every running effect. + CTRL_DEVRST = 4, // Device Reset– Clears any device paused condition, enables all actuators and clears all effects from memory. + CTRL_DEVPAUSE = 5, // Device Pause– The all effects on the device are paused at the current time step. + CTRL_DEVCONT = 6, // Device Continue– The all effects that running when the device was paused are restarted from their last time step. +}; + +enum FFB_EFFECTS { + Constant = 0x0001, + Ramp = 0x0002, + Square = 0x0004, + Sine = 0x0008, + Triangle = 0x0010, + Sawtooth_Up = 0x0020, + Sawtooth_Dn = 0x0040, + Spring = 0x0080, + Damper = 0x0100, + Inertia = 0x0200, + Friction = 0x0400, + Custom = 0x0800, +}; + +typedef struct _FFB_DATA { + ULONG size; + ULONG cmd; + UCHAR *data; +} FFB_DATA, * PFFB_DATA; + +typedef struct _FFB_EFF_CONSTANT { + BYTE EffectBlockIndex; + LONG Magnitude; // Constant force magnitude: -10000 - 10000 +} FFB_EFF_CONSTANT, *PFFB_EFF_CONSTANT; + +typedef struct _FFB_EFF_RAMP { + BYTE EffectBlockIndex; + LONG Start; // The Normalized magnitude at the start of the effect (-10000 - 10000) + LONG End; // The Normalized magnitude at the end of the effect (-10000 - 10000) +} FFB_EFF_RAMP, *PFFB_EFF_RAMP; + +//typedef struct _FFB_EFF_CONST { +typedef struct _FFB_EFF_REPORT { + BYTE EffectBlockIndex; + FFBEType EffectType; + WORD Duration;// Value in milliseconds. 0xFFFF means infinite + WORD TrigerRpt; + WORD SamplePrd; + BYTE Gain; + BYTE TrigerBtn; + BOOL Polar; // How to interpret force direction Polar (0-360°) or Cartesian (X,Y) + union + { + BYTE Direction; // Polar direction: (0x00-0xFF correspond to 0-360°) + BYTE DirX; // X direction: Positive values are To the right of the center (X); Negative are Two's complement + }; + BYTE DirY; // Y direction: Positive values are below the center (Y); Negative are Two's complement +} FFB_EFF_REPORT, *PFFB_EFF_REPORT; +//} FFB_EFF_CONST, *PFFB_EFF_CONST; + +typedef struct _FFB_EFF_OP { + BYTE EffectBlockIndex; + FFBOP EffectOp; + BYTE LoopCount; +} FFB_EFF_OP, *PFFB_EFF_OP; + +typedef struct _FFB_EFF_PERIOD { + BYTE EffectBlockIndex; + DWORD Magnitude; // Range: 0 - 10000 + LONG Offset; // Range: –10000 - 10000 + DWORD Phase; // Range: 0 - 35999 + DWORD Period; // Range: 0 - 32767 +} FFB_EFF_PERIOD, *PFFB_EFF_PERIOD; + +typedef struct _FFB_EFF_COND { + BYTE EffectBlockIndex; + BOOL isY; + LONG CenterPointOffset; // CP Offset: Range -­10000 ­- 10000 + LONG PosCoeff; // Positive Coefficient: Range -­10000 ­- 10000 + LONG NegCoeff; // Negative Coefficient: Range -­10000 ­- 10000 + DWORD PosSatur; // Positive Saturation: Range 0 – 10000 + DWORD NegSatur; // Negative Saturation: Range 0 – 10000 + LONG DeadBand; // Dead Band: : Range 0 – 1000 +} FFB_EFF_COND, *PFFB_EFF_COND; + +typedef struct _FFB_EFF_ENVLP { + BYTE EffectBlockIndex; + DWORD AttackLevel; // The Normalized magnitude of the stating point: 0 - 10000 + DWORD FadeLevel; // The Normalized magnitude of the stopping point: 0 - 10000 + DWORD AttackTime; // Time of the attack: 0 - 4294967295 + DWORD FadeTime; // Time of the fading: 0 - 4294967295 +} FFB_EFF_ENVLP, *PFFB_EFF_ENVLP; + +#define FFB_DATA_READY WM_USER+31 + +typedef void (CALLBACK *FfbGenCB)(PVOID, PVOID); +#endif + + +#ifndef STATIC + extern "C" { +#else +namespace vJoyNS { +#endif + ///////////////////////////// vJoy device (collection) Control interface ///////////////////////////////// + /* + These functions allow writing feeders and other applications that interface with vJoy + It is assumed that only one vJoy top-device (= Raw PDO) exists. + This top-level device can have up to 16 siblings (=top-level Reports/collections) + Each sibling is refered to as a "vJoy Device" and is attributed a unique Report ID (Range: 1-16). + + Naming convetion: + VJD = vJoy Device + rID = Report ID + */ +#pragma warning( push ) +#pragma warning( disable : 4995 ) + ///// General driver data + VJOYINTERFACE_API SHORT __cdecl GetvJoyVersion(void); + VJOYINTERFACE_API BOOL __cdecl vJoyEnabled(void); + VJOYINTERFACE_API PVOID __cdecl GetvJoyProductString(void); + VJOYINTERFACE_API PVOID __cdecl GetvJoyManufacturerString(void); + VJOYINTERFACE_API PVOID __cdecl GetvJoySerialNumberString(void); + VJOYINTERFACE_API BOOL __cdecl DriverMatch(WORD * DllVer, WORD * DrvVer); + VJOYINTERFACE_API VOID __cdecl RegisterRemovalCB(RemovalCB cb, PVOID data); + VJOYINTERFACE_API BOOL __cdecl vJoyFfbCap(BOOL * Supported); // Is this version of vJoy capable of FFB? + VJOYINTERFACE_API BOOL __cdecl GetvJoyMaxDevices(int * n); // What is the maximum possible number of vJoy devices + VJOYINTERFACE_API BOOL __cdecl GetNumberExistingVJD(int * n); // What is the number of vJoy devices currently enabled + + + ///// vJoy Device properties + VJOYINTERFACE_API int __cdecl GetVJDButtonNumber(UINT rID); // Get the number of buttons defined in the specified VDJ + VJOYINTERFACE_API int __cdecl GetVJDDiscPovNumber(UINT rID); // Get the number of descrete-type POV hats defined in the specified VDJ + VJOYINTERFACE_API int __cdecl GetVJDContPovNumber(UINT rID); // Get the number of descrete-type POV hats defined in the specified VDJ + VJOYINTERFACE_API BOOL __cdecl GetVJDAxisExist(UINT rID, UINT Axis); // Test if given axis defined in the specified VDJ + VJOYINTERFACE_API BOOL __cdecl GetVJDAxisMax(UINT rID, UINT Axis, LONG * Max); // Get logical Maximum value for a given axis defined in the specified VDJ + VJOYINTERFACE_API BOOL __cdecl GetVJDAxisMin(UINT rID, UINT Axis, LONG * Min); // Get logical Minimum value for a given axis defined in the specified VDJ + VJOYINTERFACE_API enum VjdStat __cdecl GetVJDStatus(UINT rID); // Get the status of the specified vJoy Device. + // Added in 2.1.6 + VJOYINTERFACE_API BOOL __cdecl isVJDExists(UINT rID); // TRUE if the specified vJoy Device exists + // Added in 2.1.8 + VJOYINTERFACE_API int __cdecl GetOwnerPid(UINT rID); // Reurn owner's Process ID if the specified vJoy Device exists + + + ///// Write access to vJoy Device - Basic + VJOYINTERFACE_API BOOL __cdecl AcquireVJD(UINT rID); // Acquire the specified vJoy Device. + VJOYINTERFACE_API VOID __cdecl RelinquishVJD(UINT rID); // Relinquish the specified vJoy Device. + VJOYINTERFACE_API BOOL __cdecl UpdateVJD(UINT rID, PVOID pData); // Update the position data of the specified vJoy Device. + + ///// Write access to vJoy Device - Modifyiers + // This group of functions modify the current value of the position data + // They replace the need to create a structure of position data then call UpdateVJD + + //// Reset functions + VJOYINTERFACE_API BOOL __cdecl ResetVJD(UINT rID); // Reset all controls to predefined values in the specified VDJ + VJOYINTERFACE_API VOID __cdecl ResetAll(void); // Reset all controls to predefined values in all VDJ + VJOYINTERFACE_API BOOL __cdecl ResetButtons(UINT rID); // Reset all buttons (To 0) in the specified VDJ + VJOYINTERFACE_API BOOL __cdecl ResetPovs(UINT rID); // Reset all POV Switches (To -1) in the specified VDJ + + // Write data + VJOYINTERFACE_API BOOL __cdecl SetAxis(LONG Value, UINT rID, UINT Axis); // Write Value to a given axis defined in the specified VDJ + VJOYINTERFACE_API BOOL __cdecl SetBtn(BOOL Value, UINT rID, UCHAR nBtn); // Write Value to a given button defined in the specified VDJ + VJOYINTERFACE_API BOOL __cdecl SetDiscPov(int Value, UINT rID, UCHAR nPov); // Write Value to a given descrete POV defined in the specified VDJ + VJOYINTERFACE_API BOOL __cdecl SetContPov(DWORD Value, UINT rID, UCHAR nPov); // Write Value to a given continuous POV defined in the specified VDJ + + +#pragma region FFB Function prototypes +// Force Feedback (FFB) functions + VJOYINTERFACE_API FFBEType __cdecl FfbGetEffect(); // Returns effect serial number if active, 0 if inactive + VJOYINTERFACE_API VOID __cdecl FfbRegisterGenCB(FfbGenCB cb, PVOID data); + __declspec(deprecated("** FfbStart function was deprecated - you can remove it from your code **")) \ + VJOYINTERFACE_API BOOL __cdecl FfbStart(UINT rID); // Start the FFB queues of the specified vJoy Device. + __declspec(deprecated("** FfbStop function was deprecated - you can remove it from your code **")) \ + VJOYINTERFACE_API VOID __cdecl FfbStop(UINT rID); // Stop the FFB queues of the specified vJoy Device. + + // Added in 2.1.6 + VJOYINTERFACE_API BOOL __cdecl IsDeviceFfb(UINT rID); + VJOYINTERFACE_API BOOL __cdecl IsDeviceFfbEffect(UINT rID, UINT Effect); + + // Force Feedback (FFB) helper functions + VJOYINTERFACE_API DWORD __cdecl Ffb_h_DeviceID(const FFB_DATA * Packet, int *DeviceID); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_Type(const FFB_DATA * Packet, FFBPType *Type); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_Packet(const FFB_DATA * Packet, WORD *Type, int *DataSize, BYTE *Data[]); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_EBI(const FFB_DATA * Packet, int *Index); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_Eff_Report(const FFB_DATA * Packet, FFB_EFF_REPORT* Effect); + __declspec(deprecated("** Ffb_h_Eff_Const function was deprecated - Use function Ffb_h_Eff_Report **")) \ + VJOYINTERFACE_API DWORD __cdecl Ffb_h_Eff_Const(const FFB_DATA * Packet, FFB_EFF_CONST* Effect); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_Eff_Ramp(const FFB_DATA * Packet, FFB_EFF_RAMP* RampEffect); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_EffOp(const FFB_DATA * Packet, FFB_EFF_OP* Operation); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_DevCtrl(const FFB_DATA * Packet, FFB_CTRL * Control); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_Eff_Period(const FFB_DATA * Packet, FFB_EFF_PERIOD* Effect); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_Eff_Cond(const FFB_DATA * Packet, FFB_EFF_COND* Condition); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_DevGain(const FFB_DATA * Packet, BYTE * Gain); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_Eff_Envlp(const FFB_DATA * Packet, FFB_EFF_ENVLP* Envelope); + VJOYINTERFACE_API DWORD __cdecl Ffb_h_EffNew(const FFB_DATA * Packet, FFBEType * Effect); + + // Added in 2.1.6 + VJOYINTERFACE_API DWORD __cdecl Ffb_h_Eff_Constant(const FFB_DATA * Packet, FFB_EFF_CONSTANT * ConstantEffect); +#pragma endregion + +#pragma warning( pop ) +#ifndef STATIC + } // extern "C" +#else +} // Namespace vJoyNS +#endif diff --git a/WheelAdapter/dependencies/SDK_218/lib/amd64/vJoyInterface.dll b/WheelAdapter/dependencies/SDK_218/lib/amd64/vJoyInterface.dll new file mode 100644 index 0000000..ef7f0a7 Binary files /dev/null and b/WheelAdapter/dependencies/SDK_218/lib/amd64/vJoyInterface.dll differ diff --git a/WheelAdapter/dependencies/SDK_218/lib/amd64/vJoyInterface.lib b/WheelAdapter/dependencies/SDK_218/lib/amd64/vJoyInterface.lib new file mode 100644 index 0000000..83d5953 Binary files /dev/null and b/WheelAdapter/dependencies/SDK_218/lib/amd64/vJoyInterface.lib differ diff --git a/WheelAdapter/dependencies/SDK_218/lib/vJoyInterface.dll b/WheelAdapter/dependencies/SDK_218/lib/vJoyInterface.dll new file mode 100644 index 0000000..309de0e Binary files /dev/null and b/WheelAdapter/dependencies/SDK_218/lib/vJoyInterface.dll differ diff --git a/WheelAdapter/dependencies/SDK_218/lib/vJoyInterface.lib b/WheelAdapter/dependencies/SDK_218/lib/vJoyInterface.lib new file mode 100644 index 0000000..f158d45 Binary files /dev/null and b/WheelAdapter/dependencies/SDK_218/lib/vJoyInterface.lib differ diff --git a/WheelAdapter/dependencies/SDK_218/src/stdafx.h b/WheelAdapter/dependencies/SDK_218/src/stdafx.h new file mode 100644 index 0000000..99dee4e --- /dev/null +++ b/WheelAdapter/dependencies/SDK_218/src/stdafx.h @@ -0,0 +1,21 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/WheelAdapter/dependencies/SDK_218/src/vJoyClient.cpp b/WheelAdapter/dependencies/SDK_218/src/vJoyClient.cpp new file mode 100644 index 0000000..68578bd --- /dev/null +++ b/WheelAdapter/dependencies/SDK_218/src/vJoyClient.cpp @@ -0,0 +1,571 @@ +// vJoyClient.cpp : Simple feeder application with a FFB demo +// + + +// Monitor Force Feedback (FFB) vJoy device +#include "stdafx.h" +//#include "Devioctl.h" +#include "public.h" +#include +#include +#include +#include "vjoyinterface.h" +#include "Math.h" + +// Default device ID (Used when ID not specified) +#define DEV_ID 1 + +// Prototypes +void CALLBACK FfbFunction(PVOID data); +void CALLBACK FfbFunction1(PVOID cb, PVOID data); + +BOOL PacketType2Str(FFBPType Type, LPTSTR Str); +BOOL EffectType2Str(FFBEType Ctrl, LPTSTR Str); +BOOL DevCtrl2Str(FFB_CTRL Type, LPTSTR Str); +BOOL EffectOpStr(FFBOP Op, LPTSTR Str); +int Polar2Deg(BYTE Polar); +int Byte2Percent(BYTE InByte); +int TwosCompByte2Int(BYTE in); + + +int ffb_direction = 0; +int ffb_strenght = 0; +int serial_result = 0; + + +JOYSTICK_POSITION_V2 iReport; // The structure that holds the full position data + +int +__cdecl +_tmain(int argc, _TCHAR* argv[]) +{ + int stat = 0; + UINT DevID = DEV_ID; + USHORT X = 0; + USHORT Y = 0; + USHORT Z = 0; + LONG Btns = 0; + + + PVOID pPositionMessage; + UINT IoCode = LOAD_POSITIONS; + UINT IoSize = sizeof(JOYSTICK_POSITION); + // HID_DEVICE_ATTRIBUTES attrib; + BYTE id = 1; + UINT iInterface = 1; + + // Define the effect names + static FFBEType FfbEffect= (FFBEType)-1; + LPCTSTR FfbEffectName[] = + {"NONE", "Constant Force", "Ramp", "Square", "Sine", "Triangle", "Sawtooth Up",\ + "Sawtooth Down", "Spring", "Damper", "Inertia", "Friction", "Custom Force"}; + + // Set the target Joystick - get it from the command-line + if (argc>1) + DevID = _tstoi(argv[1]); + + // Get the driver attributes (Vendor ID, Product ID, Version Number) + if (!vJoyEnabled()) + { + _tprintf("Function vJoyEnabled Failed - make sure that vJoy is installed and enabled\n"); + int dummy = getchar(); + stat = - 2; + goto Exit; + } + else + { + wprintf(L"Vendor: %s\nProduct :%s\nVersion Number:%s\n", static_cast (GetvJoyManufacturerString()), static_cast(GetvJoyProductString()), static_cast(GetvJoySerialNumberString())); + }; + + // Get the status of the vJoy device before trying to acquire it + VjdStat status = GetVJDStatus(DevID); + + switch (status) + { + case VJD_STAT_OWN: + _tprintf("vJoy device %d is already owned by this feeder\n", DevID); + break; + case VJD_STAT_FREE: + _tprintf("vJoy device %d is free\n", DevID); + break; + case VJD_STAT_BUSY: + _tprintf("vJoy device %d is already owned by another feeder\nCannot continue\n", DevID); + return -3; + case VJD_STAT_MISS: + _tprintf("vJoy device %d is not installed or disabled\nCannot continue\n", DevID); + return -4; + default: + _tprintf("vJoy device %d general error\nCannot continue\n", DevID); + return -1; + }; + + // Acquire the vJoy device + if (!AcquireVJD(DevID)) + { + _tprintf("Failed to acquire vJoy device number %d.\n", DevID); + int dummy = getchar(); + stat = -1; + goto Exit; + } + else + _tprintf("Acquired device number %d - OK\n", DevID); + + + + // Start FFB +#if 1 + BOOL Ffbstarted = FfbStart(DevID); + if (!Ffbstarted) + { + _tprintf("Failed to start FFB on vJoy device number %d.\n", DevID); + int dummy = getchar(); + stat = -3; + goto Exit; + } + else + _tprintf("Started FFB on vJoy device number %d - OK\n", DevID); + +#endif // 1 + + // Register Generic callback function + // At this point you instruct the Receptor which callback function to call with every FFB packet it receives + // It is the role of the designer to register the right FFB callback function + FfbRegisterGenCB(FfbFunction1, NULL); + + + + + // Start endless loop + // The loop injects position data to the vJoy device + // If it fails it let's the user try again + // + // FFB Note: + // All FFB activity is performed in a separate thread created when registered the callback function + while (1) + { + + // Set destenition vJoy device + id = (BYTE)DevID; + iReport.bDevice = id; + + // Set position data of 3 first axes + if (Z>35000) Z=0; + Z += 200; + iReport.wAxisZ = Z; + iReport.wAxisX = 32000-Z; + iReport.wAxisY = Z/2+7000; + + // Set position data of first 8 buttons + Btns = 1<<(Z/4000); + iReport.lButtons = Btns; + + // Send position data to vJoy device + pPositionMessage = (PVOID)(&iReport); + if (!UpdateVJD(DevID, pPositionMessage)) + { + printf("Feeding vJoy device number %d failed - try to enable device then press enter\n", DevID); + getchar(); + AcquireVJD(DevID); + } + Sleep(2); + } + +Exit: + RelinquishVJD(DevID); + return 0; +} + + +// Generic callback function +void CALLBACK FfbFunction(PVOID data) +{ + FFB_DATA * FfbData = (FFB_DATA *)data; + int size = FfbData->size; + _tprintf("\nFFB Size %d\n", size); + + _tprintf("Cmd:%08.8X ", FfbData->cmd); + _tprintf("ID:%02.2X ", FfbData->data[0]); + _tprintf("Size:%02.2d ", static_cast(FfbData->size - 8)); + _tprintf(" - "); + for (UINT i = 0; i < FfbData->size - 8; i++) + _tprintf(" %02.2X", (UINT)FfbData->data); + _tprintf("\n"); +} + +void CALLBACK FfbFunction1(PVOID data, PVOID userdata) +{ + // Packet Header + _tprintf("\n ============= FFB Packet size Size %d =============\n", static_cast(((FFB_DATA *)data)->size)); + + /////// Packet Device ID, and Type Block Index (if exists) +#pragma region Packet Device ID, and Type Block Index + int DeviceID, BlockIndex; + FFBPType Type; + TCHAR TypeStr[100]; + + if (ERROR_SUCCESS == Ffb_h_DeviceID((FFB_DATA *)data, &DeviceID)) + _tprintf("\n > Device ID: %d", DeviceID); + if (ERROR_SUCCESS == Ffb_h_Type((FFB_DATA *)data, &Type)) + { + if (!PacketType2Str(Type, TypeStr)) + _tprintf("\n > Packet Type: %d", Type); + else + _tprintf("\n > Packet Type: %s", TypeStr); + + } + if (ERROR_SUCCESS == Ffb_h_EBI((FFB_DATA *)data, &BlockIndex)) + _tprintf("\n > Effect Block Index: %d", BlockIndex); +#pragma endregion + + + /////// Effect Report +#pragma region Effect Report + FFB_EFF_CONST Effect; + if (ERROR_SUCCESS == Ffb_h_Eff_Report((FFB_DATA *)data, &Effect)) + { + if (!EffectType2Str(Effect.EffectType, TypeStr)) + _tprintf("\n >> Effect Report: %02x", Effect.EffectType); + else + _tprintf("\n >> Effect Report: %s", TypeStr); + + if (Effect.Polar) + { + _tprintf("\n >> Direction: %d deg (%02x)", Polar2Deg(Effect.Direction), Effect.Direction); + + + } + else + { + _tprintf("\n >> X Direction: %02x", Effect.DirX); + _tprintf("\n >> Y Direction: %02x", Effect.DirY); + }; + + if (Effect.Duration == 0xFFFF) + _tprintf("\n >> Duration: Infinit"); + else + _tprintf("\n >> Duration: %d MilliSec", static_cast(Effect.Duration)); + + if (Effect.TrigerRpt == 0xFFFF) + _tprintf("\n >> Trigger Repeat: Infinit"); + else + _tprintf("\n >> Trigger Repeat: %d", static_cast(Effect.TrigerRpt)); + + if (Effect.SamplePrd == 0xFFFF) + _tprintf("\n >> Sample Period: Infinit"); + else + _tprintf("\n >> Sample Period: %d", static_cast(Effect.SamplePrd)); + + + _tprintf("\n >> Gain: %d%%", Byte2Percent(Effect.Gain)); + + }; +#pragma endregion +#pragma region PID Device Control + FFB_CTRL Control; + TCHAR CtrlStr[100]; + if (ERROR_SUCCESS == Ffb_h_DevCtrl((FFB_DATA *)data, &Control) && DevCtrl2Str(Control, CtrlStr)) + _tprintf("\n >> PID Device Control: %s", CtrlStr); + +#pragma endregion +#pragma region Effect Operation + FFB_EFF_OP Operation; + TCHAR EffOpStr[100]; + if (ERROR_SUCCESS == Ffb_h_EffOp((FFB_DATA *)data, &Operation) && EffectOpStr(Operation.EffectOp, EffOpStr)) + { + _tprintf("\n >> Effect Operation: %s", EffOpStr); + if (Operation.LoopCount == 0xFF) + _tprintf("\n >> Loop until stopped"); + else + _tprintf("\n >> Loop %d times", static_cast(Operation.LoopCount)); + + }; +#pragma endregion +#pragma region Global Device Gain + BYTE Gain; + if (ERROR_SUCCESS == Ffb_h_DevGain((FFB_DATA *)data, &Gain)) + _tprintf("\n >> Global Device Gain: %d", Byte2Percent(Gain)); + +#pragma endregion +#pragma region Condition + FFB_EFF_COND Condition; + if (ERROR_SUCCESS == Ffb_h_Eff_Cond((FFB_DATA *)data, &Condition)) + { + if (Condition.isY) + _tprintf("\n >> Y Axis"); + else + _tprintf("\n >> X Axis"); + _tprintf("\n >> Center Point Offset: %d", TwosCompByte2Int(Condition.CenterPointOffset)*10000/127); + _tprintf("\n >> Positive Coefficient: %d", TwosCompByte2Int(Condition.PosCoeff)*10000/127); + _tprintf("\n >> Negative Coefficient: %d", TwosCompByte2Int(Condition.NegCoeff)*10000/127); + _tprintf("\n >> Positive Saturation: %d", Condition.PosSatur*10000/255); + _tprintf("\n >> Negative Saturation: %d", Condition.NegSatur*10000/255); + _tprintf("\n >> Dead Band: %d", Condition.DeadBand*10000/255); + } +#pragma endregion +#pragma region Envelope + FFB_EFF_ENVLP Envelope; + if (ERROR_SUCCESS == Ffb_h_Eff_Envlp((FFB_DATA *)data, &Envelope)) + { + _tprintf("\n >> Attack Level: %d", Envelope.AttackLevel*10000/255); + _tprintf("\n >> Fade Level: %d", Envelope.FadeLevel*10000/255); + _tprintf("\n >> Attack Time: %d", static_cast(Envelope.AttackTime)); + _tprintf("\n >> Fade Time: %d", static_cast(Envelope.FadeTime)); + }; + +#pragma endregion +#pragma region Periodic + FFB_EFF_PERIOD EffPrd; + if (ERROR_SUCCESS == Ffb_h_Eff_Period((FFB_DATA *)data, &EffPrd)) + { + _tprintf("\n >> Magnitude: %d", EffPrd.Magnitude * 10000 / 255); + _tprintf("\n >> Offset: %d", TwosCompByte2Int(EffPrd.Offset) * 10000 / 127); + _tprintf("\n >> Phase: %d", EffPrd.Phase * 3600 / 255); + _tprintf("\n >> Period: %d", static_cast(EffPrd.Period)); + }; +#pragma endregion + +#pragma region Effect Type + FFBEType EffectType; + if (ERROR_SUCCESS == Ffb_h_EffNew((FFB_DATA *)data, &EffectType)) + { + if (EffectType2Str(EffectType, TypeStr)) + _tprintf("\n >> Effect Type: %s", TypeStr); + else + _tprintf("\n >> Effect Type: Unknown"); + } + +#pragma endregion + +#pragma region Ramp Effect + FFB_EFF_RAMP RampEffect; + if (ERROR_SUCCESS == Ffb_h_Eff_Ramp((FFB_DATA *)data, &RampEffect)) + { + _tprintf("\n >> Ramp Start: %d", TwosCompByte2Int(RampEffect.Start) * 10000 / 127); + _tprintf("\n >> Ramp End: %d", TwosCompByte2Int(RampEffect.End) * 10000 / 127); + }; + +#pragma endregion + + _tprintf("\n"); + FfbFunction(data); + _tprintf("\n ====================================================\n"); + +} + + +// Convert Packet type to String +BOOL PacketType2Str(FFBPType Type, LPTSTR OutStr) +{ + BOOL stat = TRUE; + LPTSTR Str=""; + + switch (Type) + { + case PT_EFFREP: + Str = "Effect Report"; + break; + case PT_ENVREP: + Str = "Envelope Report"; + break; + case PT_CONDREP: + Str = "Condition Report"; + break; + case PT_PRIDREP: + Str = "Periodic Report"; + break; + case PT_CONSTREP: + Str = "Constant Force Report"; + break; + case PT_RAMPREP: + Str = "Ramp Force Report"; + break; + case PT_CSTMREP: + Str = "Custom Force Data Report"; + break; + case PT_SMPLREP: + Str = "Download Force Sample"; + break; + case PT_EFOPREP: + Str = "Effect Operation Report"; + break; + case PT_BLKFRREP: + Str = "PID Block Free Report"; + break; + case PT_CTRLREP: + Str = "PID Device Contro"; + break; + case PT_GAINREP: + Str = "Device Gain Report"; + break; + case PT_SETCREP: + Str = "Set Custom Force Report"; + break; + case PT_NEWEFREP: + Str = "Create New Effect Report"; + break; + case PT_BLKLDREP: + Str = "Block Load Report"; + break; + case PT_POOLREP: + Str = "PID Pool Report"; + break; + default: + stat = FALSE; + break; + } + + if (stat) + _tcscpy_s(OutStr, 100, Str); + + return stat; +} + +// Convert Effect type to String +BOOL EffectType2Str(FFBEType Type, LPTSTR OutStr) +{ + BOOL stat = TRUE; + LPTSTR Str=""; + + switch (Type) + { + case ET_NONE: + stat = FALSE; + break; + case ET_CONST: + Str="Constant Force"; + break; + case ET_RAMP: + Str="Ramp"; + break; + case ET_SQR: + Str="Square"; + break; + case ET_SINE: + Str="Sine"; + break; + case ET_TRNGL: + Str="Triangle"; + break; + case ET_STUP: + Str="Sawtooth Up"; + break; + case ET_STDN: + Str="Sawtooth Down"; + break; + case ET_SPRNG: + Str="Spring"; + break; + case ET_DMPR: + Str="Damper"; + break; + case ET_INRT: + Str="Inertia"; + break; + case ET_FRCTN: + Str="Friction"; + break; + case ET_CSTM: + Str="Custom Force"; + break; + default: + stat = FALSE; + break; + }; + + if (stat) + _tcscpy_s(OutStr, 100, Str); + + return stat; +} + +// Convert PID Device Control to String +BOOL DevCtrl2Str(FFB_CTRL Ctrl, LPTSTR OutStr) +{ + BOOL stat = TRUE; + LPTSTR Str=""; + + switch (Ctrl) + { + case CTRL_ENACT: + Str="Enable Actuators"; + break; + case CTRL_DISACT: + Str="Disable Actuators"; + break; + case CTRL_STOPALL: + Str="Stop All Effects"; + break; + case CTRL_DEVRST: + Str="Device Reset"; + break; + case CTRL_DEVPAUSE: + Str="Device Pause"; + break; + case CTRL_DEVCONT: + Str="Device Continue"; + break; + default: + stat = FALSE; + break; + } + if (stat) + _tcscpy_s(OutStr, 100, Str); + + return stat; +} + +// Convert Effect operation to string +BOOL EffectOpStr(FFBOP Op, LPTSTR OutStr) +{ + BOOL stat = TRUE; + LPTSTR Str=""; + + switch (Op) + { + case EFF_START: + Str="Effect Start"; + break; + case EFF_SOLO: + Str="Effect Solo Start"; + break; + case EFF_STOP: + Str="Effect Stop"; + break; + default: + stat = FALSE; + break; + } + + if (stat) + _tcscpy_s(OutStr, 100, Str); + + return stat; +} + +// Polar values (0x00-0xFF) to Degrees (0-360) +int Polar2Deg(BYTE Polar) +{ + return ((UINT)Polar*360)/255; +} + +// Convert range 0x00-0xFF to 0%-100% +int Byte2Percent(BYTE InByte) +{ + return ((UINT)InByte*100)/255; +} + +// Convert One-Byte 2's complement input to integer +int TwosCompByte2Int(BYTE in) +{ + int tmp; + BYTE inv = ~in; + BOOL isNeg = in>>7; + if (isNeg) + { + tmp = (int)(inv); + tmp = -1*tmp; + return tmp; + } + else + return (int)in; +} diff --git a/WheelAdapter/dependencies/SDK_218/src/vJoyClient.sln b/WheelAdapter/dependencies/SDK_218/src/vJoyClient.sln new file mode 100644 index 0000000..d0ac10b --- /dev/null +++ b/WheelAdapter/dependencies/SDK_218/src/vJoyClient.sln @@ -0,0 +1,32 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C++ Express 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vJoyClient", "vJoyClient.vcproj", "{A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Rel64|Win32 = Rel64|Win32 + Rel64|x64 = Rel64|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Debug|Win32.ActiveCfg = Debug|Win32 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Debug|Win32.Build.0 = Debug|Win32 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Debug|x64.ActiveCfg = Debug|x64 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Debug|x64.Build.0 = Debug|x64 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Rel64|Win32.ActiveCfg = Rel64|Win32 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Rel64|Win32.Build.0 = Rel64|Win32 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Rel64|x64.ActiveCfg = Rel64|x64 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Rel64|x64.Build.0 = Rel64|x64 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Release|Win32.ActiveCfg = Release|Win32 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Release|Win32.Build.0 = Release|Win32 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Release|x64.ActiveCfg = Release|x64 + {A3C0D9FE-F4A3-45F9-874A-AC2E6806477C}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/WheelAdapter/dependencies/SDK_218/src/vJoyClient.vcproj b/WheelAdapter/dependencies/SDK_218/src/vJoyClient.vcproj new file mode 100644 index 0000000..e673862 --- /dev/null +++ b/WheelAdapter/dependencies/SDK_218/src/vJoyClient.vcproj @@ -0,0 +1,529 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WheelAdapter/dependencies/vJoyInterface.dll b/WheelAdapter/dependencies/vJoyInterface.dll new file mode 100644 index 0000000..8c67ef5 Binary files /dev/null and b/WheelAdapter/dependencies/vJoyInterface.dll differ diff --git a/WheelAdapter/dependencies/vJoyInterfaceWrap.dll b/WheelAdapter/dependencies/vJoyInterfaceWrap.dll new file mode 100644 index 0000000..3b9d8c7 Binary files /dev/null and b/WheelAdapter/dependencies/vJoyInterfaceWrap.dll differ