using System; using System.Collections.Generic; using System.ComponentModel; using System.Windows.Forms; using DS4Library; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; namespace DS4Control { public partial class X360Device : ScpDevice { public const String DS3_BUS_CLASS_GUID = "{F679F562-3164-42CE-A4DB-E7DDBE723909}"; protected virtual Int32 Scale(Int32 Value, Boolean Flip) { Value -= 0x80; if (Value == -128) Value = -127; if (Flip) Value *= -1; return (Int32)((float)Value * 258.00787401574803149606299212599f); } public X360Device() : base(DS3_BUS_CLASS_GUID) { InitializeComponent(); } public X360Device(IContainer container) : base(DS3_BUS_CLASS_GUID) { container.Add(this); InitializeComponent(); } public override Boolean Open(int Instance = 0) { if (base.Open(Instance)) { } return true; } public override Boolean Open(String DevicePath) { m_Path = DevicePath; m_WinUsbHandle = (IntPtr)INVALID_HANDLE_VALUE; if (GetDeviceHandle(m_Path)) { m_IsActive = true; } return true; } public override Boolean Start() { if (IsActive) { } return true; } public override Boolean Stop() { if (IsActive) { //Unplug(0); } return base.Stop(); } public override Boolean Close() { if (IsActive) { Unplug(0); } return base.Close(); } public virtual void Parse(DS4State state, Byte[] Output, int device) { Output[0] = 0x1C; Output[4] = (Byte)(device + 1); Output[9] = 0x14; for (int i = 10; i < Output.Length; i++) { Output[i] = 0; } if (state.Share) Output[10] |= (Byte)(1 << 5); // Back if (state.L3) Output[10] |= (Byte)(1 << 6); // Left Thumb if (state.R3) Output[10] |= (Byte)(1 << 7); // Right Thumb if (state.Options) Output[10] |= (Byte)(1 << 4); // Start if (state.DpadUp) Output[10] |= (Byte)(1 << 0); // Up if (state.DpadRight) Output[10] |= (Byte)(1 << 3); // Down if (state.DpadDown) Output[10] |= (Byte)(1 << 1); // Right if (state.DpadLeft) Output[10] |= (Byte)(1 << 2); // Left if (state.L1) Output[11] |= (Byte)(1 << 0); // Left Shoulder if (state.R1) Output[11] |= (Byte)(1 << 1); // Right Shoulder if (state.Triangle) Output[11] |= (Byte)(1 << 7); // Y if (state.Circle) Output[11] |= (Byte)(1 << 5); // B if (state.Cross) Output[11] |= (Byte)(1 << 4); // A if (state.Square) Output[11] |= (Byte)(1 << 6); // X if (state.PS) Output[11] |= (Byte)(1 << 2); // Guide Output[12] = state.L2; // Left Trigger Output[13] = state.R2; // Right Trigger Int32 ThumbLX = Scale(state.LX, false); Int32 ThumbLY = -Scale(state.LY, false); Int32 ThumbRX = Scale(state.RX, false); Int32 ThumbRY = -Scale(state.RY, false); Output[14] = (Byte)((ThumbLX >> 0) & 0xFF); // LX Output[15] = (Byte)((ThumbLX >> 8) & 0xFF); Output[16] = (Byte)((ThumbLY >> 0) & 0xFF); // LY Output[17] = (Byte)((ThumbLY >> 8) & 0xFF); Output[18] = (Byte)((ThumbRX >> 0) & 0xFF); // RX Output[19] = (Byte)((ThumbRX >> 8) & 0xFF); Output[20] = (Byte)((ThumbRY >> 0) & 0xFF); // RY Output[21] = (Byte)((ThumbRY >> 8) & 0xFF); } public virtual Boolean Plugin(Int32 Serial) { if (IsActive) { Int32 Transfered = 0; Byte[] Buffer = new Byte[16]; Buffer[0] = 0x10; Buffer[1] = 0x00; Buffer[2] = 0x00; Buffer[3] = 0x00; Buffer[4] = (Byte)((Serial >> 0) & 0xFF); Buffer[5] = (Byte)((Serial >> 8) & 0xFF); Buffer[6] = (Byte)((Serial >> 16) & 0xFF); Buffer[7] = (Byte)((Serial >> 24) & 0xFF); return DeviceIoControl(m_FileHandle, 0x2A4000, Buffer, Buffer.Length, null, 0, ref Transfered, IntPtr.Zero); } return false; } public virtual Boolean Unplug(Int32 Serial) { if (IsActive) { Int32 Transfered = 0; Byte[] Buffer = new Byte[16]; Buffer[0] = 0x10; Buffer[1] = 0x00; Buffer[2] = 0x00; Buffer[3] = 0x00; Buffer[4] = (Byte)((Serial >> 0) & 0xFF); Buffer[5] = (Byte)((Serial >> 8) & 0xFF); Buffer[6] = (Byte)((Serial >> 16) & 0xFF); Buffer[7] = (Byte)((Serial >> 24) & 0xFF); return DeviceIoControl(m_FileHandle, 0x2A4004, Buffer, Buffer.Length, null, 0, ref Transfered, IntPtr.Zero); } return false; } public virtual Boolean Report(Byte[] Input, Byte[] Output) { if (IsActive) { Int32 Transfered = 0; return DeviceIoControl(m_FileHandle, 0x2A400C, Input, Input.Length, Output, Output.Length, ref Transfered, IntPtr.Zero) && Transfered > 0; } return false; } } }