├── .gitignore ├── LICENSE ├── README.md ├── XOutput.sln ├── XOutput.v12.suo └── XOutput ├── App.config ├── ControllerDevice.cs ├── ControllerManager.cs ├── ControllerOptions.Designer.cs ├── ControllerOptions.cs ├── Logger.cs ├── MultiLevelComboBox.cs ├── Program.cs ├── Properties ├── AssemblyInfo.cs ├── Resources.Designer.cs ├── Resources.resx ├── Settings.Designer.cs └── Settings.settings ├── Resources ├── arrow_Down.png ├── arrow_Up.png └── gear.png ├── SaveManager.cs ├── ScpDevice.cs ├── XOut.Designer.cs ├── XOut.cs ├── XOut.resx ├── XOutput.csproj ├── XOutput.csproj.user └── XOutput_Icon.ico /.gitignore: -------------------------------------------------------------------------------- 1 | XOutput/bin/ 2 | XOutput/obj/ 3 | .vs/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | 167 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | XOutput is a simple DirectInput to XInput wrapper made in C#. It uses the SCPDriver has a backend. 2 | Now modified by me to take input from Steam Controller 3 | 4 | #Building 5 | 6 | XOutput can be built in Visual Studio 2013+. It depends on the SlimDX developer SDK which can be found [here](http://slimdx.org/) 7 | 8 | #How to Set Up 9 | 10 | 1. Download and install the official Xbox 360 Controller driver [here](http://www.microsoft.com/hardware/en-us/d/xbox-360-controller-for-windows) 11 | 2. Run ScpDriver.exe 12 | 3. Click install, wait until it finishes to close it 13 | 4. Run XOutput and set up your controller mappings 14 | 5. Click "Start" 15 | -------------------------------------------------------------------------------- /XOutput.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Express 14 for Windows Desktop 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XOutput", "XOutput\XOutput.csproj", "{3FA04C64-23DE-4294-B9D7-47BBFFB57539}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|x86 = Debug|x86 12 | Release|Any CPU = Release|Any CPU 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {3FA04C64-23DE-4294-B9D7-47BBFFB57539}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {3FA04C64-23DE-4294-B9D7-47BBFFB57539}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {3FA04C64-23DE-4294-B9D7-47BBFFB57539}.Debug|x86.ActiveCfg = Debug|x86 19 | {3FA04C64-23DE-4294-B9D7-47BBFFB57539}.Debug|x86.Build.0 = Debug|x86 20 | {3FA04C64-23DE-4294-B9D7-47BBFFB57539}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {3FA04C64-23DE-4294-B9D7-47BBFFB57539}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {3FA04C64-23DE-4294-B9D7-47BBFFB57539}.Release|x86.ActiveCfg = Release|x86 23 | {3FA04C64-23DE-4294-B9D7-47BBFFB57539}.Release|x86.Build.0 = Release|x86 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /XOutput.v12.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mintos5/XOutput/c878b3c3b6c5e1714d300f630c4fb2cddc32374a/XOutput.v12.suo -------------------------------------------------------------------------------- /XOutput/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /XOutput/ControllerDevice.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SlimDX.DirectInput; 3 | using SlimDX.XInput; 4 | 5 | namespace XOutput 6 | { 7 | 8 | public struct OutputState 9 | { 10 | public byte LX, LY, RX, RY, L2, R2; 11 | public bool A, B, X, Y, Start, Back, L1, R1, L3, R3, Home; 12 | public bool DpadUp, DpadRight, DpadDown, DpadLeft; 13 | } 14 | 15 | public class ControllerDevice 16 | { 17 | public Joystick joystick; 18 | int deviceNumber; 19 | public string name; 20 | public bool enabled = true; 21 | 22 | public OutputState cOutput; 23 | public byte[] mapping = new byte[42]; 24 | bool[] buttons; 25 | int[] dPads; 26 | int[] analogs; 27 | 28 | 29 | delegate byte input(byte subType, byte num); 30 | 31 | public ControllerDevice(Joystick joy, int num) 32 | { 33 | joystick = joy; 34 | deviceNumber = num; 35 | name = joystick.Information.InstanceName; 36 | cOutput = new OutputState(); 37 | for (int i = 0; i < 42; i++) 38 | { 39 | mapping[i] = 255; //Changed default mapping to blank 40 | } 41 | byte[] saveData = SaveManager.Load(joy.Information.ProductName.ToString()); 42 | if (saveData != null) 43 | mapping = saveData; 44 | } 45 | 46 | #region Utility Functions 47 | 48 | public void Save() 49 | { 50 | SaveManager.Save(joystick.Information.ProductName, mapping); 51 | } 52 | 53 | private int XinputLT() 54 | { 55 | byte lt = new Controller(0).GetState().Gamepad.LeftTrigger; 56 | return lt * 256; 57 | } 58 | 59 | private int XinputRT() 60 | { 61 | byte rt = new Controller(0).GetState().Gamepad.RightTrigger; 62 | return rt * 256; 63 | } 64 | 65 | private int[] GetAxes(JoystickState jstate) 66 | { 67 | return new int[] { jstate.X, jstate.Y, XinputLT(), jstate.RotationX, jstate.RotationY, XinputRT() }; 68 | } 69 | 70 | private unsafe byte toByte(bool n) 71 | { 72 | return *((byte*)(&n)); 73 | } 74 | 75 | private bool[] getPov(byte n) 76 | { 77 | bool[] b = new bool[4]; 78 | int i = dPads[n]; 79 | switch (i) 80 | { 81 | case -1: b[0] = false; b[1] = false; b[2] = false; b[3] = false; break; 82 | case 0: b[0] = true; b[1] = false; b[2] = false; b[3] = false; break; 83 | case 4500: b[0] = true; b[1] = false; b[2] = false; b[3] = true; break; 84 | case 9000: b[0] = false; b[1] = false; b[2] = false; b[3] = true; break; 85 | case 13500: b[0] = false; b[1] = true; b[2] = false; b[3] = true; break; 86 | case 18000: b[0] = false; b[1] = true; b[2] = false; b[3] = false; break; 87 | case 22500: b[0] = false; b[1] = true; b[2] = true; b[3] = false; break; 88 | case 27000: b[0] = false; b[1] = false; b[2] = true; b[3] = false; break; 89 | case 31500: b[0] = true; b[1] = false; b[2] = true; b[3] = false; break; 90 | } 91 | return b; 92 | } 93 | 94 | public void changeNumber(int n) 95 | { 96 | deviceNumber = n; 97 | } 98 | 99 | #endregion 100 | 101 | #region Input Types 102 | 103 | byte Button(byte subType, byte num) 104 | { 105 | int i = (int)toByte(buttons[num]) * 255; 106 | return (byte)i; 107 | } 108 | 109 | byte Analog(byte subType, byte num) 110 | { 111 | int p = analogs[num]; 112 | switch (subType) 113 | { 114 | case 0: //Normal 115 | return (byte)(p / 256); 116 | case 1: //Inverted 117 | return (byte)((65535 - p) / 256); 118 | case 2: //Half 119 | int m = (p - 32767) / 129; 120 | if (m < 0) 121 | { 122 | m = 0; 123 | } 124 | return (byte)m; 125 | case 3: //Inverted Half 126 | m = (p - 32767) / 129; 127 | if (-m < 0) 128 | { 129 | m = 0; 130 | } 131 | return (byte)-m; 132 | } 133 | return 0; 134 | } 135 | 136 | byte DPad(byte subType, byte num) 137 | { 138 | int i = (int)toByte(getPov(num)[subType]) * 255; 139 | return (byte)i; 140 | } 141 | 142 | #endregion 143 | 144 | private void updateInput() 145 | { 146 | joystick.Poll(); 147 | JoystickState jState = joystick.GetCurrentState(); 148 | buttons = jState.GetButtons(); 149 | dPads = jState.GetPointOfViewControllers(); 150 | analogs = GetAxes(jState); 151 | 152 | input funcButton = Button; 153 | input funcAnalog = Analog; 154 | input funcDPad = DPad; 155 | input[] funcArray = new input[] { funcButton, funcAnalog, funcDPad }; 156 | 157 | byte[] output = new byte[21]; 158 | for (int i = 0; i < 21; i++) 159 | { 160 | if (mapping[i * 2] == 255) 161 | { 162 | continue; 163 | } 164 | byte subtype = (byte)(mapping[i * 2] & 0x0F); 165 | byte type = (byte)((mapping[i * 2] & 0xF0) >> 4); 166 | byte num = mapping[(i * 2) + 1]; 167 | output[i] = funcArray[type](subtype, num); 168 | } 169 | 170 | cOutput.A = output[0] != 0; 171 | cOutput.B = output[1] != 0; 172 | cOutput.X = output[2] != 0; 173 | cOutput.Y = output[3] != 0; 174 | 175 | cOutput.DpadUp = output[4] != 0; 176 | cOutput.DpadDown = output[5] != 0; 177 | cOutput.DpadLeft = output[6] != 0; 178 | cOutput.DpadRight = output[7] != 0; 179 | 180 | cOutput.L2 = output[9]; 181 | cOutput.R2 = output[8]; 182 | 183 | cOutput.L1 = output[10] != 0; 184 | cOutput.R1 = output[11] != 0; 185 | 186 | cOutput.L3 = output[12] != 0; 187 | cOutput.R3 = output[13] != 0; 188 | 189 | cOutput.Home = output[14] != 0; 190 | cOutput.Start = output[15] != 0; 191 | cOutput.Back = output[16] != 0; 192 | 193 | cOutput.LY = output[17]; 194 | cOutput.LX = output[18]; 195 | cOutput.RY = output[19]; 196 | cOutput.RX = output[20]; 197 | 198 | } 199 | 200 | 201 | public byte[] getoutput() 202 | { 203 | updateInput(); 204 | byte[] Report = new byte[64]; 205 | Report[1] = 0x02; 206 | Report[2] = 0x05; 207 | Report[3] = 0x12; 208 | 209 | Report[10] = (byte)( 210 | ((cOutput.Back ? 1 : 0) << 0) | 211 | ((cOutput.L3 ? 1 : 0) << 1) | 212 | ((cOutput.R3 ? 1 : 0) << 2) | 213 | ((cOutput.Start ? 1 : 0) << 3) | 214 | ((cOutput.DpadUp ? 1 : 0) << 4) | 215 | ((cOutput.DpadRight ? 1 : 0) << 5) | 216 | ((cOutput.DpadDown ? 1 : 0) << 6) | 217 | ((cOutput.DpadLeft ? 1 : 0) << 7)); 218 | 219 | Report[11] = (byte)( 220 | ((cOutput.L1 ? 1 : 0) << 2) | 221 | ((cOutput.R1 ? 1 : 0) << 3) | 222 | ((cOutput.Y ? 1 : 0) << 4) | 223 | ((cOutput.B ? 1 : 0) << 5) | 224 | ((cOutput.A ? 1 : 0) << 6) | 225 | ((cOutput.X ? 1 : 0) << 7)); 226 | 227 | //Guide 228 | Report[12] = (byte)(cOutput.Home ? 0xFF : 0x00); 229 | 230 | 231 | Report[14] = cOutput.LX; //Left Stick X 232 | 233 | 234 | Report[15] = cOutput.LY; //Left Stick Y 235 | 236 | 237 | Report[16] = cOutput.RX; //Right Stick X 238 | 239 | 240 | Report[17] = cOutput.RY; //Right Stick Y 241 | 242 | Report[26] = cOutput.R2; 243 | Report[27] = cOutput.L2; 244 | 245 | return Report; 246 | } 247 | 248 | 249 | } 250 | } 251 | -------------------------------------------------------------------------------- /XOutput/ControllerManager.cs: -------------------------------------------------------------------------------- 1 | using SlimDX.DirectInput; 2 | using System; 3 | using System.Diagnostics; 4 | using System.Threading; 5 | using System.Windows.Forms; 6 | 7 | 8 | namespace XOutput 9 | { 10 | 11 | class ControllerManager : ScpDevice 12 | { 13 | private class ContData 14 | { 15 | public byte[] parsedData = new byte[28]; 16 | public byte[] output = new byte[8]; 17 | } 18 | 19 | private DirectInput directInput; 20 | private ControllerDevice[] devices; 21 | public bool running = false; 22 | private Thread[] workers = new Thread[4]; 23 | public const String BUS_CLASS_GUID = "{F679F562-3164-42CE-A4DB-E7DDBE723909}"; 24 | private ContData[] processingData = new ContData[4]; 25 | private Control handle; 26 | public bool isExclusive = false; 27 | 28 | 29 | private object[] ds4locks = new object[4]; 30 | 31 | public ControllerManager(Control _handle) 32 | : base(BUS_CLASS_GUID) 33 | { 34 | directInput = new DirectInput(); 35 | devices = new ControllerDevice[4]; 36 | handle = _handle; 37 | ds4locks[0] = new object(); 38 | ds4locks[1] = new object(); 39 | ds4locks[2] = new object(); 40 | ds4locks[3] = new object(); 41 | } 42 | 43 | #region Utility Functions 44 | 45 | public void changeExclusive(bool e) 46 | { 47 | isExclusive = e; 48 | for (int i = 0; i < 4; i++) 49 | { 50 | if (devices[i] != null) 51 | { 52 | if (isExclusive) 53 | { 54 | devices[i].joystick.Unacquire(); 55 | devices[i].joystick.SetCooperativeLevel(handle, CooperativeLevel.Exclusive | CooperativeLevel.Background); 56 | devices[i].joystick.Acquire(); 57 | } 58 | else 59 | { 60 | devices[i].joystick.Unacquire(); 61 | devices[i].joystick.SetCooperativeLevel(handle, CooperativeLevel.Nonexclusive | CooperativeLevel.Background); 62 | devices[i].joystick.Acquire(); 63 | } 64 | } 65 | } 66 | } 67 | 68 | public ControllerDevice getController(int n) 69 | { 70 | return devices[n]; 71 | 72 | } 73 | 74 | public void Swap(int i, int p) 75 | { 76 | if (true)//devices[i - 1] != null && devices[p - 1] != null) 77 | { 78 | 79 | ControllerDevice s = devices[i - 1]; 80 | devices[i - 1] = devices[p - 1]; 81 | devices[p - 1] = s; 82 | devices[p - 1].changeNumber(p); 83 | 84 | if (devices[i - 1] != null) 85 | devices[i - 1].changeNumber(i); 86 | 87 | } 88 | } 89 | 90 | public void setControllerEnable(int i, bool b) 91 | { 92 | devices[i].enabled = b; 93 | } 94 | 95 | private Int32 Scale(Int32 Value, Boolean Flip) 96 | { 97 | Value -= 0x80; 98 | 99 | if (Value == -128) Value = -127; 100 | if (Flip) Value *= -1; 101 | 102 | return (Int32)((float)Value * 258.00787401574803149606299212599f); 103 | } 104 | 105 | #endregion 106 | 107 | public override Boolean Open(int Instance = 0) 108 | { 109 | return base.Open(Instance); 110 | } 111 | 112 | public override Boolean Open(String DevicePath) 113 | { 114 | m_Path = DevicePath; 115 | m_WinUsbHandle = (IntPtr)INVALID_HANDLE_VALUE; 116 | 117 | if (GetDeviceHandle(m_Path)) 118 | { 119 | 120 | m_IsActive = true; 121 | 122 | } 123 | return true; 124 | } 125 | 126 | public override bool Start() 127 | { 128 | Console.WriteLine(Process.GetCurrentProcess().MainWindowHandle); 129 | Open(); 130 | detectControllers(); 131 | running = true; 132 | for (int i = 0; i < 4; i++) 133 | { 134 | if (devices[i] != null && devices[i].enabled) 135 | { 136 | running = true; 137 | processingData[i] = new ContData(); 138 | Console.WriteLine("Plug " + i); 139 | Plugin(i + 1); 140 | int t = i; 141 | workers[i] = new Thread(() => 142 | { ProcessData(t); }); 143 | workers[i].Start(); 144 | } 145 | } 146 | 147 | return running; 148 | } 149 | 150 | public ControllerDevice[] detectControllers() 151 | { 152 | //for (int i = 0; i < 4; i++) //Remove disconnected controllers 153 | //{ 154 | // if (devices[i] != null && !directInput.IsDeviceAttached(devices[i].joystick.Information.InstanceGuid)) 155 | // { 156 | // Console.WriteLine(devices[i].joystick.Properties.InstanceName + " Removed"); 157 | // devices[i] = null; 158 | // workers[i].Abort(); 159 | // workers[i] = null; 160 | // Unplug(i + 1); 161 | // } 162 | //} 163 | 164 | foreach (var deviceInstance in directInput.GetDevices(DeviceClass.GameController, DeviceEnumerationFlags.AttachedOnly)) 165 | { 166 | Joystick joystick = new Joystick(directInput, deviceInstance.InstanceGuid); 167 | 168 | if (joystick.Information.ProductGuid.ToString() == "028e045e-0000-0000-0000-504944564944") //If its an emulated controller skip it 169 | continue; 170 | 171 | if (joystick.Capabilities.ButtonCount < 1 && joystick.Capabilities.AxesCount < 1) //Skip if it doesn't have any button and axes 172 | continue; 173 | 174 | int spot = -1; 175 | for (int i = 0; i < 4; i++) 176 | { 177 | if (devices[i] == null) 178 | { 179 | if (spot == -1) 180 | { 181 | spot = i; 182 | Console.WriteLine("Open Spot " + i.ToString()); 183 | } 184 | } 185 | else if (devices[i] != null && devices[i].joystick.Information.InstanceGuid == deviceInstance.InstanceGuid) //If the device is already initialized skip it 186 | { 187 | Console.WriteLine("Controller Already Acquired " + i.ToString() + " " + deviceInstance.InstanceName); 188 | spot = -1; 189 | break; 190 | } 191 | } 192 | 193 | if (spot == -1) 194 | continue; 195 | 196 | if (isExclusive) 197 | { 198 | joystick.SetCooperativeLevel(handle, CooperativeLevel.Exclusive | CooperativeLevel.Background); 199 | } 200 | else 201 | { 202 | joystick.SetCooperativeLevel(handle, CooperativeLevel.Nonexclusive | CooperativeLevel.Background); 203 | } 204 | joystick.Properties.BufferSize = 128; 205 | joystick.Acquire(); 206 | 207 | devices[spot] = new ControllerDevice(joystick, spot + 1); 208 | if (IsActive) 209 | { 210 | processingData[spot] = new ContData(); 211 | Console.WriteLine("Plug " + spot); 212 | Plugin(spot + 1); 213 | int t = spot; 214 | workers[spot] = new Thread(() => 215 | { ProcessData(t); }); 216 | workers[spot].Start(); 217 | } 218 | } 219 | return devices; 220 | } 221 | 222 | public override bool Stop() 223 | { 224 | if (running) 225 | { 226 | running = false; 227 | for (int i = 0; i < 4; i++) 228 | { 229 | if (devices[i] != null && devices[i].enabled) 230 | { 231 | Console.WriteLine(i); 232 | workers[i].Abort(); 233 | workers[i] = null; 234 | Unplug(i + 1); 235 | } 236 | } 237 | 238 | } 239 | return base.Stop(); 240 | } 241 | 242 | public Boolean Plugin(Int32 Serial) 243 | { 244 | if (IsActive) 245 | { 246 | Int32 Transfered = 0; 247 | Byte[] Buffer = new Byte[16]; 248 | 249 | Buffer[0] = 0x10; 250 | Buffer[1] = 0x00; 251 | Buffer[2] = 0x00; 252 | Buffer[3] = 0x00; 253 | 254 | Buffer[4] = (Byte)((Serial >> 0) & 0xFF); 255 | Buffer[5] = (Byte)((Serial >> 8) & 0xFF); 256 | Buffer[6] = (Byte)((Serial >> 16) & 0xFF); 257 | Buffer[7] = (Byte)((Serial >> 24) & 0xFF); 258 | 259 | return DeviceIoControl(m_FileHandle, 0x2A4000, Buffer, Buffer.Length, null, 0, ref Transfered, IntPtr.Zero); 260 | } 261 | 262 | return false; 263 | } 264 | 265 | public Boolean Unplug(Int32 Serial) 266 | { 267 | if (IsActive) 268 | { 269 | Int32 Transfered = 0; 270 | Byte[] Buffer = new Byte[16]; 271 | 272 | Buffer[0] = 0x10; 273 | Buffer[1] = 0x00; 274 | Buffer[2] = 0x00; 275 | Buffer[3] = 0x00; 276 | 277 | Buffer[4] = (Byte)((Serial >> 0) & 0xFF); 278 | Buffer[5] = (Byte)((Serial >> 8) & 0xFF); 279 | Buffer[6] = (Byte)((Serial >> 16) & 0xFF); 280 | Buffer[7] = (Byte)((Serial >> 24) & 0xFF); 281 | 282 | return DeviceIoControl(m_FileHandle, 0x2A4004, Buffer, Buffer.Length, null, 0, ref Transfered, IntPtr.Zero); 283 | } 284 | 285 | return false; 286 | } 287 | 288 | private void ProcessData(int n) 289 | { 290 | while (IsActive) 291 | { 292 | lock (ds4locks[n]) 293 | { 294 | if (devices[n] == null) 295 | { 296 | //Console.WriteLine("die" + n.ToString()); 297 | //continue; 298 | } 299 | byte[] data = devices[n].getoutput(); 300 | if (data != null && devices[n].enabled) 301 | { 302 | 303 | data[0] = (byte)n; 304 | Parse(data, processingData[n].parsedData); 305 | Report(processingData[n].parsedData, processingData[n].output); 306 | } 307 | Thread.Sleep(1); 308 | } 309 | } 310 | } 311 | 312 | public Boolean Report(Byte[] Input, Byte[] Output) 313 | { 314 | if (IsActive) 315 | { 316 | Int32 Transfered = 0; 317 | 318 | 319 | bool result = DeviceIoControl(m_FileHandle, 0x2A400C, Input, Input.Length, Output, Output.Length, ref Transfered, IntPtr.Zero) && Transfered > 0; 320 | int deviceInd = Input[4] - 1; 321 | return result; 322 | 323 | } 324 | return false; 325 | } 326 | 327 | public void Parse(Byte[] Input, Byte[] Output) 328 | { 329 | Byte Serial = (Byte)(Input[0] + 1); 330 | 331 | for (Int32 Index = 0; Index < 28; Index++) Output[Index] = 0x00; 332 | 333 | Output[0] = 0x1C; 334 | Output[4] = (Byte)(Input[0] + 1); 335 | Output[9] = 0x14; 336 | 337 | if (true)//Input[1] == 0x02) // Pad is active 338 | { 339 | 340 | UInt32 Buttons = (UInt32)((Input[10] << 0) | (Input[11] << 8) | (Input[12] << 16) | (Input[13] << 24)); 341 | 342 | if ((Buttons & (0x1 << 0)) > 0) Output[10] |= (Byte)(1 << 5); // Back 343 | if ((Buttons & (0x1 << 1)) > 0) Output[10] |= (Byte)(1 << 6); // Left Thumb 344 | if ((Buttons & (0x1 << 2)) > 0) Output[10] |= (Byte)(1 << 7); // Right Thumb 345 | if ((Buttons & (0x1 << 3)) > 0) Output[10] |= (Byte)(1 << 4); // Start 346 | 347 | if ((Buttons & (0x1 << 4)) > 0) Output[10] |= (Byte)(1 << 0); // Up 348 | if ((Buttons & (0x1 << 5)) > 0) Output[10] |= (Byte)(1 << 3); // Down 349 | if ((Buttons & (0x1 << 6)) > 0) Output[10] |= (Byte)(1 << 1); // Right 350 | if ((Buttons & (0x1 << 7)) > 0) Output[10] |= (Byte)(1 << 2); // Left 351 | 352 | if ((Buttons & (0x1 << 10)) > 0) Output[11] |= (Byte)(1 << 0); // Left Shoulder 353 | if ((Buttons & (0x1 << 11)) > 0) Output[11] |= (Byte)(1 << 1); // Right Shoulder 354 | 355 | if ((Buttons & (0x1 << 12)) > 0) Output[11] |= (Byte)(1 << 7); // Y 356 | if ((Buttons & (0x1 << 13)) > 0) Output[11] |= (Byte)(1 << 5); // B 357 | if ((Buttons & (0x1 << 14)) > 0) Output[11] |= (Byte)(1 << 4); // A 358 | if ((Buttons & (0x1 << 15)) > 0) Output[11] |= (Byte)(1 << 6); // X 359 | 360 | if ((Buttons & (0x1 << 16)) > 16) Output[11] |= (Byte)(1 << 2); // Guide 361 | 362 | Output[12] = Input[26]; // Left Trigger 363 | Output[13] = Input[27]; // Right Trigger 364 | 365 | Int32 ThumbLX = Scale(Input[14], false); 366 | Int32 ThumbLY = -Scale(Input[15], false); 367 | Int32 ThumbRX = Scale(Input[16], false); 368 | Int32 ThumbRY = -Scale(Input[17], false); 369 | 370 | Output[14] = (Byte)((ThumbLX >> 0) & 0xFF); // LX 371 | Output[15] = (Byte)((ThumbLX >> 8) & 0xFF); 372 | 373 | Output[16] = (Byte)((ThumbLY >> 0) & 0xFF); // LY 374 | Output[17] = (Byte)((ThumbLY >> 8) & 0xFF); 375 | 376 | Output[18] = (Byte)((ThumbRX >> 0) & 0xFF); // RX 377 | Output[19] = (Byte)((ThumbRX >> 8) & 0xFF); 378 | 379 | Output[20] = (Byte)((ThumbRY >> 0) & 0xFF); // RY 380 | Output[21] = (Byte)((ThumbRY >> 8) & 0xFF); 381 | } 382 | } 383 | 384 | } 385 | } 386 | -------------------------------------------------------------------------------- /XOutput/ControllerOptions.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace XOutput 2 | { 3 | partial class ControllerOptions 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(XOut)); 32 | this.labelA = new System.Windows.Forms.Label(); 33 | this.labelB = new System.Windows.Forms.Label(); 34 | this.labelX = new System.Windows.Forms.Label(); 35 | this.labelY = new System.Windows.Forms.Label(); 36 | this.labelUp = new System.Windows.Forms.Label(); 37 | this.labelDown = new System.Windows.Forms.Label(); 38 | this.labelLeft = new System.Windows.Forms.Label(); 39 | this.labelRight = new System.Windows.Forms.Label(); 40 | this.dropRight = new XOutput.MultiLevelComboBox(); 41 | this.dropLeft = new XOutput.MultiLevelComboBox(); 42 | this.dropDown = new XOutput.MultiLevelComboBox(); 43 | this.dropUp = new XOutput.MultiLevelComboBox(); 44 | this.dropY = new XOutput.MultiLevelComboBox(); 45 | this.dropX = new XOutput.MultiLevelComboBox(); 46 | this.dropB = new XOutput.MultiLevelComboBox(); 47 | this.dropA = new XOutput.MultiLevelComboBox(); 48 | this.dropRT = new XOutput.MultiLevelComboBox(); 49 | this.dropLT = new XOutput.MultiLevelComboBox(); 50 | this.dropRB = new XOutput.MultiLevelComboBox(); 51 | this.dropLB = new XOutput.MultiLevelComboBox(); 52 | this.dropBack = new XOutput.MultiLevelComboBox(); 53 | this.dropStart = new XOutput.MultiLevelComboBox(); 54 | this.dropHome = new XOutput.MultiLevelComboBox(); 55 | this.labelRT = new System.Windows.Forms.Label(); 56 | this.labelLT = new System.Windows.Forms.Label(); 57 | this.labelRB = new System.Windows.Forms.Label(); 58 | this.labelLB = new System.Windows.Forms.Label(); 59 | this.labelBack = new System.Windows.Forms.Label(); 60 | this.labelStart = new System.Windows.Forms.Label(); 61 | this.labelHome = new System.Windows.Forms.Label(); 62 | this.dropRA = new XOutput.MultiLevelComboBox(); 63 | this.dropLA = new XOutput.MultiLevelComboBox(); 64 | this.dropRX = new XOutput.MultiLevelComboBox(); 65 | this.dropRY = new XOutput.MultiLevelComboBox(); 66 | this.dropLX = new XOutput.MultiLevelComboBox(); 67 | this.dropLY = new XOutput.MultiLevelComboBox(); 68 | this.labelRA = new System.Windows.Forms.Label(); 69 | this.labelLA = new System.Windows.Forms.Label(); 70 | this.labelLX = new System.Windows.Forms.Label(); 71 | this.labelRX = new System.Windows.Forms.Label(); 72 | this.labelLY = new System.Windows.Forms.Label(); 73 | this.labelRY = new System.Windows.Forms.Label(); 74 | this.SuspendLayout(); 75 | // 76 | // labelA 77 | // 78 | this.labelA.AutoSize = true; 79 | this.labelA.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 80 | this.labelA.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 81 | this.labelA.Location = new System.Drawing.Point(609, 290); 82 | this.labelA.Name = "labelA"; 83 | this.labelA.Size = new System.Drawing.Size(20, 20); 84 | this.labelA.TabIndex = 0; 85 | this.labelA.Text = "A"; 86 | // 87 | // labelB 88 | // 89 | this.labelB.AutoSize = true; 90 | this.labelB.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 91 | this.labelB.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 92 | this.labelB.Location = new System.Drawing.Point(609, 340); 93 | this.labelB.Name = "labelB"; 94 | this.labelB.Size = new System.Drawing.Size(20, 20); 95 | this.labelB.TabIndex = 7; 96 | this.labelB.Text = "B"; 97 | // 98 | // labelX 99 | // 100 | this.labelX.AutoSize = true; 101 | this.labelX.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 102 | this.labelX.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 103 | this.labelX.Location = new System.Drawing.Point(609, 390); 104 | this.labelX.Name = "labelX"; 105 | this.labelX.Size = new System.Drawing.Size(20, 20); 106 | this.labelX.TabIndex = 8; 107 | this.labelX.Text = "X"; 108 | // 109 | // labelY 110 | // 111 | this.labelY.AutoSize = true; 112 | this.labelY.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 113 | this.labelY.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 114 | this.labelY.Location = new System.Drawing.Point(609, 440); 115 | this.labelY.Name = "labelY"; 116 | this.labelY.Size = new System.Drawing.Size(20, 20); 117 | this.labelY.TabIndex = 9; 118 | this.labelY.Text = "Y"; 119 | // 120 | // labelUp 121 | // 122 | this.labelUp.AutoSize = true; 123 | this.labelUp.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 124 | this.labelUp.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 125 | this.labelUp.Location = new System.Drawing.Point(167, 290); 126 | this.labelUp.Name = "labelUp"; 127 | this.labelUp.Size = new System.Drawing.Size(30, 20); 128 | this.labelUp.TabIndex = 14; 129 | this.labelUp.Text = "Up"; 130 | // 131 | // labelDown 132 | // 133 | this.labelDown.AutoSize = true; 134 | this.labelDown.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 135 | this.labelDown.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 136 | this.labelDown.Location = new System.Drawing.Point(167, 340); 137 | this.labelDown.Name = "labelDown"; 138 | this.labelDown.Size = new System.Drawing.Size(50, 20); 139 | this.labelDown.TabIndex = 15; 140 | this.labelDown.Text = "Down"; 141 | // 142 | // labelLeft 143 | // 144 | this.labelLeft.AutoSize = true; 145 | this.labelLeft.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 146 | this.labelLeft.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 147 | this.labelLeft.Location = new System.Drawing.Point(167, 390); 148 | this.labelLeft.Name = "labelLeft"; 149 | this.labelLeft.Size = new System.Drawing.Size(37, 20); 150 | this.labelLeft.TabIndex = 16; 151 | this.labelLeft.Text = "Left"; 152 | // 153 | // labelRight 154 | // 155 | this.labelRight.AutoSize = true; 156 | this.labelRight.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 157 | this.labelRight.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 158 | this.labelRight.Location = new System.Drawing.Point(167, 440); 159 | this.labelRight.Name = "labelRight"; 160 | this.labelRight.Size = new System.Drawing.Size(47, 20); 161 | this.labelRight.TabIndex = 17; 162 | this.labelRight.Text = "Right"; 163 | // 164 | // dropRight 165 | // 166 | this.dropRight.FormattingEnabled = true; 167 | this.dropRight.ImeMode = System.Windows.Forms.ImeMode.NoControl; 168 | this.dropRight.Items.AddRange(new object[] { 169 | ""}); 170 | this.dropRight.Location = new System.Drawing.Point(40, 440); 171 | this.dropRight.Name = "dropRight"; 172 | this.dropRight.Size = new System.Drawing.Size(121, 21); 173 | this.dropRight.TabIndex = 13; 174 | // 175 | // dropLeft 176 | // 177 | this.dropLeft.FormattingEnabled = true; 178 | this.dropLeft.ImeMode = System.Windows.Forms.ImeMode.NoControl; 179 | this.dropLeft.Items.AddRange(new object[] { 180 | ""}); 181 | this.dropLeft.Location = new System.Drawing.Point(40, 390); 182 | this.dropLeft.Name = "dropLeft"; 183 | this.dropLeft.Size = new System.Drawing.Size(121, 21); 184 | this.dropLeft.TabIndex = 12; 185 | // 186 | // dropDown 187 | // 188 | this.dropDown.FormattingEnabled = true; 189 | this.dropDown.ImeMode = System.Windows.Forms.ImeMode.NoControl; 190 | this.dropDown.Items.AddRange(new object[] { 191 | ""}); 192 | this.dropDown.Location = new System.Drawing.Point(40, 340); 193 | this.dropDown.Name = "dropDown"; 194 | this.dropDown.Size = new System.Drawing.Size(121, 21); 195 | this.dropDown.TabIndex = 11; 196 | // 197 | // dropUp 198 | // 199 | this.dropUp.FormattingEnabled = true; 200 | this.dropUp.ImeMode = System.Windows.Forms.ImeMode.NoControl; 201 | this.dropUp.Items.AddRange(new object[] { 202 | ""}); 203 | this.dropUp.Location = new System.Drawing.Point(40, 290); 204 | this.dropUp.Name = "dropUp"; 205 | this.dropUp.Size = new System.Drawing.Size(121, 21); 206 | this.dropUp.TabIndex = 10; 207 | // 208 | // dropY 209 | // 210 | this.dropY.FormattingEnabled = true; 211 | this.dropY.ImeMode = System.Windows.Forms.ImeMode.NoControl; 212 | this.dropY.Items.AddRange(new object[] { 213 | ""}); 214 | this.dropY.Location = new System.Drawing.Point(482, 440); 215 | this.dropY.Name = "dropY"; 216 | this.dropY.Size = new System.Drawing.Size(121, 21); 217 | this.dropY.TabIndex = 6; 218 | // 219 | // dropX 220 | // 221 | this.dropX.FormattingEnabled = true; 222 | this.dropX.ImeMode = System.Windows.Forms.ImeMode.NoControl; 223 | this.dropX.Items.AddRange(new object[] { 224 | ""}); 225 | this.dropX.Location = new System.Drawing.Point(482, 390); 226 | this.dropX.Name = "dropX"; 227 | this.dropX.Size = new System.Drawing.Size(121, 21); 228 | this.dropX.TabIndex = 5; 229 | // 230 | // dropB 231 | // 232 | this.dropB.FormattingEnabled = true; 233 | this.dropB.ImeMode = System.Windows.Forms.ImeMode.NoControl; 234 | this.dropB.Items.AddRange(new object[] { 235 | ""}); 236 | this.dropB.Location = new System.Drawing.Point(482, 340); 237 | this.dropB.Name = "dropB"; 238 | this.dropB.Size = new System.Drawing.Size(121, 21); 239 | this.dropB.TabIndex = 4; 240 | // 241 | // dropA 242 | // 243 | this.dropA.FormattingEnabled = true; 244 | this.dropA.ImeMode = System.Windows.Forms.ImeMode.NoControl; 245 | this.dropA.Items.AddRange(new object[] { 246 | ""}); 247 | this.dropA.Location = new System.Drawing.Point(482, 290); 248 | this.dropA.Name = "dropA"; 249 | this.dropA.Size = new System.Drawing.Size(121, 21); 250 | this.dropA.TabIndex = 3; 251 | // 252 | // dropRT 253 | // 254 | this.dropRT.FormattingEnabled = true; 255 | this.dropRT.ImeMode = System.Windows.Forms.ImeMode.NoControl; 256 | this.dropRT.Items.AddRange(new object[] { 257 | ""}); 258 | this.dropRT.Location = new System.Drawing.Point(482, 40); 259 | this.dropRT.Name = "dropRT"; 260 | this.dropRT.Size = new System.Drawing.Size(121, 21); 261 | this.dropRT.TabIndex = 18; 262 | // 263 | // dropLT 264 | // 265 | this.dropLT.FormattingEnabled = true; 266 | this.dropLT.ImeMode = System.Windows.Forms.ImeMode.NoControl; 267 | this.dropLT.Items.AddRange(new object[] { 268 | ""}); 269 | this.dropLT.Location = new System.Drawing.Point(40, 40); 270 | this.dropLT.Name = "dropLT"; 271 | this.dropLT.Size = new System.Drawing.Size(121, 21); 272 | this.dropLT.TabIndex = 19; 273 | // 274 | // dropRB 275 | // 276 | this.dropRB.FormattingEnabled = true; 277 | this.dropRB.ImeMode = System.Windows.Forms.ImeMode.NoControl; 278 | this.dropRB.Items.AddRange(new object[] { 279 | ""}); 280 | this.dropRB.Location = new System.Drawing.Point(482, 90); 281 | this.dropRB.Name = "dropRB"; 282 | this.dropRB.Size = new System.Drawing.Size(121, 21); 283 | this.dropRB.TabIndex = 20; 284 | // 285 | // dropLB 286 | // 287 | this.dropLB.FormattingEnabled = true; 288 | this.dropLB.ImeMode = System.Windows.Forms.ImeMode.NoControl; 289 | this.dropLB.Items.AddRange(new object[] { 290 | ""}); 291 | this.dropLB.Location = new System.Drawing.Point(40, 90); 292 | this.dropLB.Name = "dropLB"; 293 | this.dropLB.Size = new System.Drawing.Size(121, 21); 294 | this.dropLB.TabIndex = 21; 295 | // 296 | // dropBack 297 | // 298 | this.dropBack.FormattingEnabled = true; 299 | this.dropBack.ImeMode = System.Windows.Forms.ImeMode.NoControl; 300 | this.dropBack.Items.AddRange(new object[] { 301 | ""}); 302 | this.dropBack.Location = new System.Drawing.Point(40, 490); 303 | this.dropBack.Name = "dropBack"; 304 | this.dropBack.Size = new System.Drawing.Size(121, 21); 305 | this.dropBack.TabIndex = 22; 306 | // 307 | // dropStart 308 | // 309 | this.dropStart.FormattingEnabled = true; 310 | this.dropStart.ImeMode = System.Windows.Forms.ImeMode.NoControl; 311 | this.dropStart.Items.AddRange(new object[] { 312 | ""}); 313 | this.dropStart.Location = new System.Drawing.Point(482, 490); 314 | this.dropStart.Name = "dropStart"; 315 | this.dropStart.Size = new System.Drawing.Size(121, 21); 316 | this.dropStart.TabIndex = 23; 317 | // 318 | // dropHome 319 | // 320 | this.dropHome.FormattingEnabled = true; 321 | this.dropHome.ImeMode = System.Windows.Forms.ImeMode.NoControl; 322 | this.dropHome.Items.AddRange(new object[] { 323 | ""}); 324 | this.dropHome.Location = new System.Drawing.Point(264, 490); 325 | this.dropHome.Name = "dropHome"; 326 | this.dropHome.Size = new System.Drawing.Size(121, 21); 327 | this.dropHome.TabIndex = 24; 328 | // 329 | // labelRT 330 | // 331 | this.labelRT.AutoSize = true; 332 | this.labelRT.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 333 | this.labelRT.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 334 | this.labelRT.Location = new System.Drawing.Point(609, 40); 335 | this.labelRT.Name = "labelRT"; 336 | this.labelRT.Size = new System.Drawing.Size(100, 20); 337 | this.labelRT.TabIndex = 25; 338 | this.labelRT.Text = "Right Trigger"; 339 | // 340 | // labelLT 341 | // 342 | this.labelLT.AutoSize = true; 343 | this.labelLT.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 344 | this.labelLT.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 345 | this.labelLT.Location = new System.Drawing.Point(167, 40); 346 | this.labelLT.Name = "labelLT"; 347 | this.labelLT.Size = new System.Drawing.Size(90, 20); 348 | this.labelLT.TabIndex = 26; 349 | this.labelLT.Text = "Left Trigger"; 350 | // 351 | // labelRB 352 | // 353 | this.labelRB.AutoSize = true; 354 | this.labelRB.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 355 | this.labelRB.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 356 | this.labelRB.Location = new System.Drawing.Point(609, 90); 357 | this.labelRB.Name = "labelRB"; 358 | this.labelRB.Size = new System.Drawing.Size(107, 20); 359 | this.labelRB.TabIndex = 27; 360 | this.labelRB.Text = "Right Bumper"; 361 | // 362 | // labelLB 363 | // 364 | this.labelLB.AutoSize = true; 365 | this.labelLB.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 366 | this.labelLB.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 367 | this.labelLB.Location = new System.Drawing.Point(167, 90); 368 | this.labelLB.Name = "labelLB"; 369 | this.labelLB.Size = new System.Drawing.Size(97, 20); 370 | this.labelLB.TabIndex = 28; 371 | this.labelLB.Text = "Left Bumper"; 372 | // 373 | // labelBack 374 | // 375 | this.labelBack.AutoSize = true; 376 | this.labelBack.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 377 | this.labelBack.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 378 | this.labelBack.Location = new System.Drawing.Point(167, 490); 379 | this.labelBack.Name = "labelBack"; 380 | this.labelBack.Size = new System.Drawing.Size(45, 20); 381 | this.labelBack.TabIndex = 29; 382 | this.labelBack.Text = "Back"; 383 | // 384 | // labelStart 385 | // 386 | this.labelStart.AutoSize = true; 387 | this.labelStart.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 388 | this.labelStart.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 389 | this.labelStart.Location = new System.Drawing.Point(609, 490); 390 | this.labelStart.Name = "labelStart"; 391 | this.labelStart.Size = new System.Drawing.Size(44, 20); 392 | this.labelStart.TabIndex = 30; 393 | this.labelStart.Text = "Start"; 394 | // 395 | // labelHome 396 | // 397 | this.labelHome.AutoSize = true; 398 | this.labelHome.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 399 | this.labelHome.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 400 | this.labelHome.Location = new System.Drawing.Point(391, 490); 401 | this.labelHome.Name = "labelHome"; 402 | this.labelHome.Size = new System.Drawing.Size(52, 20); 403 | this.labelHome.TabIndex = 31; 404 | this.labelHome.Text = "Home"; 405 | // 406 | // dropRA 407 | // 408 | this.dropRA.FormattingEnabled = true; 409 | this.dropRA.ImeMode = System.Windows.Forms.ImeMode.NoControl; 410 | this.dropRA.Items.AddRange(new object[] { 411 | ""}); 412 | this.dropRA.Location = new System.Drawing.Point(482, 140); 413 | this.dropRA.Name = "dropRA"; 414 | this.dropRA.Size = new System.Drawing.Size(121, 21); 415 | this.dropRA.TabIndex = 32; 416 | // 417 | // dropLA 418 | // 419 | this.dropLA.FormattingEnabled = true; 420 | this.dropLA.ImeMode = System.Windows.Forms.ImeMode.NoControl; 421 | this.dropLA.Items.AddRange(new object[] { 422 | ""}); 423 | this.dropLA.Location = new System.Drawing.Point(40, 140); 424 | this.dropLA.Name = "dropLA"; 425 | this.dropLA.Size = new System.Drawing.Size(121, 21); 426 | this.dropLA.TabIndex = 33; 427 | // 428 | // dropRX 429 | // 430 | this.dropRX.FormattingEnabled = true; 431 | this.dropRX.ImeMode = System.Windows.Forms.ImeMode.NoControl; 432 | this.dropRX.Items.AddRange(new object[] { 433 | ""}); 434 | this.dropRX.Location = new System.Drawing.Point(482, 190); 435 | this.dropRX.Name = "dropRX"; 436 | this.dropRX.Size = new System.Drawing.Size(121, 21); 437 | this.dropRX.TabIndex = 34; 438 | // 439 | // dropRY 440 | // 441 | this.dropRY.FormattingEnabled = true; 442 | this.dropRY.ImeMode = System.Windows.Forms.ImeMode.NoControl; 443 | this.dropRY.Items.AddRange(new object[] { 444 | ""}); 445 | this.dropRY.Location = new System.Drawing.Point(482, 240); 446 | this.dropRY.Name = "dropRY"; 447 | this.dropRY.Size = new System.Drawing.Size(121, 21); 448 | this.dropRY.TabIndex = 35; 449 | // 450 | // dropLX 451 | // 452 | this.dropLX.FormattingEnabled = true; 453 | this.dropLX.ImeMode = System.Windows.Forms.ImeMode.NoControl; 454 | this.dropLX.Items.AddRange(new object[] { 455 | ""}); 456 | this.dropLX.Location = new System.Drawing.Point(40, 190); 457 | this.dropLX.Name = "dropLX"; 458 | this.dropLX.Size = new System.Drawing.Size(121, 21); 459 | this.dropLX.TabIndex = 36; 460 | // 461 | // dropLY 462 | // 463 | this.dropLY.FormattingEnabled = true; 464 | this.dropLY.ImeMode = System.Windows.Forms.ImeMode.NoControl; 465 | this.dropLY.Items.AddRange(new object[] { 466 | ""}); 467 | this.dropLY.Location = new System.Drawing.Point(40, 240); 468 | this.dropLY.Name = "dropLY"; 469 | this.dropLY.Size = new System.Drawing.Size(121, 21); 470 | this.dropLY.TabIndex = 37; 471 | // 472 | // labelRA 473 | // 474 | this.labelRA.AutoSize = true; 475 | this.labelRA.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 476 | this.labelRA.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 477 | this.labelRA.Location = new System.Drawing.Point(609, 140); 478 | this.labelRA.Name = "labelRA"; 479 | this.labelRA.Size = new System.Drawing.Size(153, 20); 480 | this.labelRA.TabIndex = 38; 481 | this.labelRA.Text = "Right Analog Button"; 482 | // 483 | // labelLA 484 | // 485 | this.labelLA.AutoSize = true; 486 | this.labelLA.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 487 | this.labelLA.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 488 | this.labelLA.Location = new System.Drawing.Point(167, 140); 489 | this.labelLA.Name = "labelLA"; 490 | this.labelLA.Size = new System.Drawing.Size(143, 20); 491 | this.labelLA.TabIndex = 39; 492 | this.labelLA.Text = "Left Analog Button"; 493 | // 494 | // labelLX 495 | // 496 | this.labelLX.AutoSize = true; 497 | this.labelLX.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 498 | this.labelLX.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 499 | this.labelLX.Location = new System.Drawing.Point(167, 190); 500 | this.labelLX.Name = "labelLX"; 501 | this.labelLX.Size = new System.Drawing.Size(106, 20); 502 | this.labelLX.TabIndex = 40; 503 | this.labelLX.Text = "Left Analog X"; 504 | // 505 | // labelRX 506 | // 507 | this.labelRX.AutoSize = true; 508 | this.labelRX.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 509 | this.labelRX.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 510 | this.labelRX.Location = new System.Drawing.Point(609, 190); 511 | this.labelRX.Name = "labelRX"; 512 | this.labelRX.Size = new System.Drawing.Size(116, 20); 513 | this.labelRX.TabIndex = 41; 514 | this.labelRX.Text = "Right Analog X"; 515 | // 516 | // labelLY 517 | // 518 | this.labelLY.AutoSize = true; 519 | this.labelLY.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 520 | this.labelLY.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 521 | this.labelLY.Location = new System.Drawing.Point(167, 240); 522 | this.labelLY.Name = "labelLY"; 523 | this.labelLY.Size = new System.Drawing.Size(106, 20); 524 | this.labelLY.TabIndex = 42; 525 | this.labelLY.Text = "Left Analog Y"; 526 | // 527 | // labelRY 528 | // 529 | this.labelRY.AutoSize = true; 530 | this.labelRY.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 531 | this.labelRY.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 532 | this.labelRY.Location = new System.Drawing.Point(609, 240); 533 | this.labelRY.Name = "labelRY"; 534 | this.labelRY.Size = new System.Drawing.Size(116, 20); 535 | this.labelRY.TabIndex = 43; 536 | this.labelRY.Text = "Right Analog Y"; 537 | // 538 | // ControllerOptions 539 | // 540 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 541 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 542 | this.ClientSize = new System.Drawing.Size(814, 561); 543 | this.Controls.Add(this.labelRY); 544 | this.Controls.Add(this.labelLY); 545 | this.Controls.Add(this.labelRX); 546 | this.Controls.Add(this.labelLX); 547 | this.Controls.Add(this.labelLA); 548 | this.Controls.Add(this.labelRA); 549 | this.Controls.Add(this.labelHome); 550 | this.Controls.Add(this.labelStart); 551 | this.Controls.Add(this.labelBack); 552 | this.Controls.Add(this.labelLB); 553 | this.Controls.Add(this.labelRB); 554 | this.Controls.Add(this.labelLT); 555 | this.Controls.Add(this.labelRT); 556 | this.Controls.Add(this.labelRight); 557 | this.Controls.Add(this.labelLeft); 558 | this.Controls.Add(this.labelDown); 559 | this.Controls.Add(this.labelUp); 560 | this.Controls.Add(this.labelY); 561 | this.Controls.Add(this.labelX); 562 | this.Controls.Add(this.labelB); 563 | this.Controls.Add(this.labelA); 564 | this.Controls.Add(this.dropA); 565 | this.Controls.Add(this.dropB); 566 | this.Controls.Add(this.dropX); 567 | this.Controls.Add(this.dropY); 568 | this.Controls.Add(this.dropUp); 569 | this.Controls.Add(this.dropDown); 570 | this.Controls.Add(this.dropLeft); 571 | this.Controls.Add(this.dropRight); 572 | this.Controls.Add(this.dropLT); 573 | this.Controls.Add(this.dropRT); 574 | this.Controls.Add(this.dropLB); 575 | this.Controls.Add(this.dropRB); 576 | this.Controls.Add(this.dropLA); 577 | this.Controls.Add(this.dropRA); 578 | this.Controls.Add(this.dropHome); 579 | this.Controls.Add(this.dropStart); 580 | this.Controls.Add(this.dropBack); 581 | this.Controls.Add(this.dropLY); 582 | this.Controls.Add(this.dropLX); 583 | this.Controls.Add(this.dropRY); 584 | this.Controls.Add(this.dropRX); 585 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 586 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 587 | this.MaximizeBox = false; 588 | this.MinimizeBox = false; 589 | this.Name = "ControllerOptions"; 590 | this.Text = "Controller Options"; 591 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.onClose); 592 | this.ResumeLayout(false); 593 | this.PerformLayout(); 594 | 595 | } 596 | 597 | #endregion 598 | 599 | private System.Windows.Forms.Label labelA; 600 | private MultiLevelComboBox dropA; 601 | private MultiLevelComboBox dropB; 602 | private MultiLevelComboBox dropX; 603 | private MultiLevelComboBox dropY; 604 | private System.Windows.Forms.Label labelB; 605 | private System.Windows.Forms.Label labelX; 606 | private System.Windows.Forms.Label labelY; 607 | private MultiLevelComboBox dropUp; 608 | private MultiLevelComboBox dropDown; 609 | private MultiLevelComboBox dropLeft; 610 | private MultiLevelComboBox dropRight; 611 | private System.Windows.Forms.Label labelUp; 612 | private System.Windows.Forms.Label labelDown; 613 | private System.Windows.Forms.Label labelLeft; 614 | private System.Windows.Forms.Label labelRight; 615 | private MultiLevelComboBox dropRT; 616 | private MultiLevelComboBox dropLT; 617 | private MultiLevelComboBox dropRB; 618 | private MultiLevelComboBox dropLB; 619 | private MultiLevelComboBox dropBack; 620 | private MultiLevelComboBox dropStart; 621 | private MultiLevelComboBox dropHome; 622 | private System.Windows.Forms.Label labelRT; 623 | private System.Windows.Forms.Label labelLT; 624 | private System.Windows.Forms.Label labelRB; 625 | private System.Windows.Forms.Label labelLB; 626 | private System.Windows.Forms.Label labelBack; 627 | private System.Windows.Forms.Label labelStart; 628 | private System.Windows.Forms.Label labelHome; 629 | private MultiLevelComboBox dropRA; 630 | private MultiLevelComboBox dropLA; 631 | private MultiLevelComboBox dropRX; 632 | private MultiLevelComboBox dropRY; 633 | private MultiLevelComboBox dropLX; 634 | private MultiLevelComboBox dropLY; 635 | private System.Windows.Forms.Label labelRA; 636 | private System.Windows.Forms.Label labelLA; 637 | private System.Windows.Forms.Label labelLX; 638 | private System.Windows.Forms.Label labelRX; 639 | private System.Windows.Forms.Label labelLY; 640 | private System.Windows.Forms.Label labelRY; 641 | 642 | } 643 | } -------------------------------------------------------------------------------- /XOutput/ControllerOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading; 4 | using System.Windows.Forms; 5 | 6 | namespace XOutput 7 | { 8 | public partial class ControllerOptions : Form 9 | { 10 | ControllerDevice dev; 11 | private Thread detectThread; 12 | public ControllerOptions(ControllerDevice device) 13 | { 14 | InitializeComponent(); 15 | dev = device; 16 | int ind = 0; 17 | 18 | foreach (MultiLevelComboBox m in this.Controls.OfType()) { 19 | //Tag structure: [Type, Number, Index] 20 | m.Items[0] = getBindingText(ind); //Change combobox text according to saved binding 21 | m.addOption("Disabled", 22 | tag: new byte[] { 255, 0, (byte)ind }); 23 | m.addOption("Detect", 24 | tag: new byte[] { 254, 0, (byte)ind }); 25 | ToolStripMenuItem axes = m.addMenu("Axes"); 26 | ToolStripMenuItem buttons = m.addMenu("Buttons"); 27 | ToolStripMenuItem dpads = m.addMenu("D-Pads"); 28 | ToolStripMenuItem iaxes = m.addMenu("Inverted Axes", axes); 29 | ToolStripMenuItem haxes = m.addMenu("Half Axes", axes); 30 | ToolStripMenuItem ihaxes = m.addMenu("Inverted Half Axes", axes); 31 | for (int i = 1; i <= dev.joystick.Capabilities.ButtonCount; i++) 32 | { 33 | m.addOption("Button " + i.ToString(), buttons, 34 | new byte[] { 0, (byte)(i - 1), (byte)ind }); 35 | } 36 | for (int i = 1; i <= dev.joystick.Capabilities.PovCount; i++) 37 | { 38 | m.addOption("D-Pad " + i.ToString() + " Up", dpads, 39 | new byte[] { 32, (byte)(i - 1), (byte)ind }); 40 | m.addOption("D-Pad " + i.ToString() + " Down", dpads, 41 | new byte[] { 33, (byte)(i - 1), (byte)ind }); 42 | m.addOption("D-Pad " + i.ToString() + " Left", dpads, 43 | new byte[] { 34, (byte)(i - 1), (byte)ind }); 44 | m.addOption("D-Pad " + i.ToString() + " Right", dpads, 45 | new byte[] { 35, (byte)(i - 1), (byte)ind }); 46 | } 47 | for (int i = 1; i <= dev.joystick.Capabilities.AxesCount; i++) 48 | { 49 | m.addOption("Axis " + i.ToString(), axes, 50 | new byte[] { 16, (byte)(i - 1), (byte)ind }); 51 | m.addOption("IAxis " + i.ToString(), iaxes, 52 | new byte[] { 17, (byte)(i - 1), (byte)ind }); 53 | m.addOption("HAxis" + i.ToString(), haxes, 54 | new byte[] { 18, (byte)(i - 1), (byte)ind }); 55 | m.addOption("IHAxis" + i.ToString(), ihaxes, 56 | new byte[] { 19, (byte)(i - 1), (byte)ind }); 57 | } 58 | m.SelectionChangeCommitted += new System.EventHandler(SelectionChanged); 59 | ind++; 60 | } 61 | } 62 | 63 | private string getBindingText(int i) 64 | { 65 | if (dev.mapping[i * 2] == 255) { 66 | return "Disabled"; 67 | } 68 | byte subType = (byte)(dev.mapping[i * 2] & 0x0F); 69 | byte type = (byte)((dev.mapping[i * 2] & 0xF0) >> 4); 70 | byte num = (byte)(dev.mapping[(i * 2) + 1] + 1); 71 | string[] typeString = new string[] { "Button {0}", "{1}Axis {0}", "D-Pad {0} {2}" }; 72 | string[] axesString = new string[] { "", "I", "H", "IH" }; 73 | string[] dpadString = new string[] { "Up", "Down", "Left", "Right" }; 74 | return string.Format(typeString[type], num, axesString[subType], dpadString[subType]); 75 | } 76 | 77 | private void SelectionChanged(object sender, EventArgs e) { 78 | ToolStripMenuItem i = (ToolStripMenuItem)sender; 79 | byte[] b = (byte[])i.Tag; 80 | if (b[0] == 254) { 81 | //start thread 82 | return; 83 | } 84 | dev.mapping[b[2] * 2] = b[0]; 85 | dev.mapping[(b[2] * 2) + 1] = b[1]; 86 | dev.Save(); 87 | } 88 | 89 | private void onClose(object sender, EventArgs e) { 90 | dev.Save(); 91 | } 92 | 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /XOutput/Logger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | 5 | namespace XOutput { 6 | static class Logger { 7 | static private string fileName = @"XOutput.log"; 8 | 9 | public static void Log(string s) { 10 | Console.WriteLine(s); 11 | if (File.Exists(fileName)) { 12 | string l = File.ReadAllText(fileName); 13 | l += "\r\n" + s; 14 | File.WriteAllText(fileName, l); 15 | } else { 16 | File.Create(fileName); // If the file doesn't exist create it 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /XOutput/MultiLevelComboBox.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Drawing; 4 | using System.Windows.Forms; 5 | 6 | namespace XOutput 7 | { 8 | class MultiLevelComboBox : ComboBox { 9 | ContextMenuStrip menu; 10 | 11 | public new event EventHandler DropDown; 12 | public new event EventHandler DropDownClosed; 13 | public new event EventHandler SelectionChangeCommitted; 14 | 15 | private bool _DroppedDown; 16 | 17 | public MultiLevelComboBox() 18 | : base() 19 | { 20 | base.DropDownStyle = ComboBoxStyle.DropDownList; 21 | menu = new ContextMenuStrip(); 22 | base.Items.Add(""); 23 | base.SelectedItem = ""; 24 | } 25 | 26 | public ToolStripMenuItem addMenu(string name, ToolStripMenuItem parent = null) { 27 | ToolStripMenuItem item = new ToolStripMenuItem(); 28 | item.Text = name; 29 | if (parent != null) { 30 | parent.DropDownItems.Add(item); 31 | } else { 32 | menu.Items.Add(item); 33 | } 34 | return item; 35 | } 36 | 37 | public ToolStripMenuItem addOption(string name, ToolStripMenuItem parent = null, object tag = null) { 38 | ToolStripMenuItem item = new ToolStripMenuItem(); 39 | item.Text = name; 40 | item.Tag = tag; 41 | item.Click += (sender, e) => selectValue(item); 42 | if (parent != null) 43 | { 44 | parent.DropDownItems.Add(item); 45 | } 46 | else 47 | { 48 | menu.Items.Add(item); 49 | } 50 | return parent; 51 | } 52 | 53 | private void selectValue(ToolStripMenuItem m) { 54 | Items[0] = m.Text; 55 | DroppedDown = false; 56 | if (SelectionChangeCommitted != null) 57 | SelectionChangeCommitted(m, EventArgs.Empty); 58 | } 59 | 60 | private void showDropDown() { 61 | menu.Show(this, new Point(0, Height)); 62 | menu.AutoSize = false; 63 | menu.Width = Width; 64 | if (DropDown != null) 65 | DropDown(this, EventArgs.Empty); 66 | } 67 | 68 | private void hideDropDown() { 69 | menu.Hide(); 70 | if (DropDownClosed != null) 71 | DropDownClosed(this, EventArgs.Empty); 72 | } 73 | 74 | protected override void WndProc(ref Message m) 75 | { 76 | switch (m.Msg) 77 | { 78 | case 0x87: //WM_GETDLGCODE 79 | break;//Block key down messages 80 | case 0x201: //WM_LBUTTONDOWN 81 | DroppedDown = !DroppedDown; 82 | break; 83 | case 0x203: //WM_LBUTTONDBLCLK 84 | DroppedDown = !DroppedDown; 85 | break; 86 | default: 87 | base.WndProc(ref m); 88 | break; 89 | } 90 | } 91 | 92 | public new bool DroppedDown { 93 | get { return _DroppedDown; } 94 | set { _DroppedDown = value; 95 | if (value) { showDropDown(); } else { hideDropDown(); } 96 | } 97 | } 98 | 99 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 100 | [Browsable(false), ReadOnly(true)] 101 | public new ComboBoxStyle DropDownStyle 102 | { 103 | get { return base.DropDownStyle; } 104 | set { } 105 | } 106 | 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /XOutput/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace XOutput 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Application.EnableVisualStyles(); 18 | Application.SetCompatibleTextRenderingDefault(false); 19 | Application.Run(new XOut()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /XOutput/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("XOutput")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Eric Barrett")] 12 | [assembly: AssemblyProduct("XOutput")] 13 | [assembly: AssemblyCopyright("Copyright © Eric Barrett 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("e39d3ad7-5d65-44e9-b0c1-58c1dc2e5f5f")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("0.1.0.0")] 36 | [assembly: AssemblyFileVersion("0.1.0.0")] 37 | -------------------------------------------------------------------------------- /XOutput/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34014 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace XOutput.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("XOutput.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap arrow_Down { 67 | get { 68 | object obj = ResourceManager.GetObject("arrow_Down", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Bitmap. 75 | /// 76 | internal static System.Drawing.Bitmap arrow_Up { 77 | get { 78 | object obj = ResourceManager.GetObject("arrow_Up", resourceCulture); 79 | return ((System.Drawing.Bitmap)(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// Looks up a localized resource of type System.Drawing.Bitmap. 85 | /// 86 | internal static System.Drawing.Bitmap gear { 87 | get { 88 | object obj = ResourceManager.GetObject("gear", resourceCulture); 89 | return ((System.Drawing.Bitmap)(obj)); 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /XOutput/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Resources\arrow_Down.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | 125 | ..\Resources\arrow_Up.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 126 | 127 | 128 | ..\Resources\gear.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 129 | 130 | -------------------------------------------------------------------------------- /XOutput/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34014 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace XOutput.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /XOutput/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /XOutput/Resources/arrow_Down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mintos5/XOutput/c878b3c3b6c5e1714d300f630c4fb2cddc32374a/XOutput/Resources/arrow_Down.png -------------------------------------------------------------------------------- /XOutput/Resources/arrow_Up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mintos5/XOutput/c878b3c3b6c5e1714d300f630c4fb2cddc32374a/XOutput/Resources/arrow_Up.png -------------------------------------------------------------------------------- /XOutput/Resources/gear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mintos5/XOutput/c878b3c3b6c5e1714d300f630c4fb2cddc32374a/XOutput/Resources/gear.png -------------------------------------------------------------------------------- /XOutput/SaveManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace XOutput 5 | { 6 | static class SaveManager { 7 | static string[] properties = new string[] {"button_a", "button_b", "button_x", "button_y", 8 | "dpad_up", "dpad_down", "dpad_left", "dpad_right", 9 | "left_trigger", "right_trigger", "left_bumper", "right_bumper", "left_axebutton", "right_axebutton", 10 | "home", "start", "back", "left_y", "left_x", "right_y", "right_x"}; 11 | static private string dirName = @"configs"; 12 | 13 | private static byte[] parseLine(string line) { //This needs better error hadnling 14 | int i; //The index of the control in the map array 15 | byte type = 255, subType = 255, num = 255; 16 | for (i = 0; i < 21; i++) { //find which button this is for 17 | if (line.StartsWith(properties[i])) { 18 | break; 19 | } 20 | if (i == 20) { 21 | Logger.Log("Error parsing: Could not identify property"); 22 | return new byte[] { 255, 255, 255}; 23 | } 24 | } 25 | if (properties[i].Length + 1 > line.Length) { 26 | Logger.Log("Error parsing: No assignment"); 27 | return new byte[] { 255, 255, 255 }; 28 | } 29 | string val = line.Remove(0, properties[i].Length + 1); //remove up to the = sign 30 | if (val.StartsWith("btn")) { 31 | type = 0; 32 | subType = 0; 33 | num = byte.Parse(val.Remove(0, 3)); 34 | } else if (val.Contains("axis")) { 35 | type = 1; 36 | if (val.StartsWith("ih")) { 37 | num = byte.Parse(val.Remove(0, 6)); 38 | subType = 3; 39 | } else if (val.StartsWith("h")) { 40 | subType = 2; 41 | num = byte.Parse(val.Remove(0, 5)); 42 | } else if (val.StartsWith("i")) { 43 | subType = 1; 44 | num = byte.Parse(val.Remove(0, 5)); 45 | } else { 46 | subType = 0; 47 | num = byte.Parse(val.Remove(0, 4)); 48 | } 49 | } else if (val.StartsWith("dpad")) { 50 | type = 2; 51 | val = val.Remove(0, 4); 52 | if (val.EndsWith("up")) { 53 | subType = 0; 54 | num = byte.Parse(val.Remove(val.Length - 2)); 55 | } else if (val.EndsWith("down")) { 56 | subType = 1; 57 | num = byte.Parse(val.Remove(val.Length - 4)); 58 | } else if (val.EndsWith("left")) { 59 | subType = 2; 60 | num = byte.Parse(val.Remove(val.Length - 4)); 61 | } else if (val.EndsWith("right")) { 62 | subType = 3; 63 | num = byte.Parse(val.Remove(val.Length - 5)); 64 | } 65 | } else if (val == "disabled") { 66 | } else { 67 | Logger.Log("Error parsing: Could not identify value"); 68 | return new byte[] { 255, 255, 255 }; 69 | } 70 | num -= 1; 71 | byte l = (byte)(type << 4 | subType); 72 | return new byte[] { (byte)(i * 2), l, num}; 73 | } 74 | 75 | public static byte[] Load(string devName) { 76 | if (!Directory.Exists(dirName)) { 77 | Directory.CreateDirectory(dirName); 78 | return null; 79 | } 80 | string path = dirName + "\\" + devName + ".ini"; 81 | if (!File.Exists(path)) { 82 | File.Create(path); 83 | return null; 84 | } 85 | byte[] mapping = new byte[42]; 86 | string[] config = File.ReadAllLines(path); 87 | for (int i = 0; i < config.Length; i++) { 88 | byte[] data = parseLine(config[i]); 89 | Console.Write(data[0]); 90 | if (data[0] > 40) { 91 | continue; 92 | } 93 | mapping[data[0]] = data[1]; 94 | mapping[data[0] + 1] = data[2]; 95 | } 96 | return mapping; 97 | } 98 | 99 | public static void Save(string devName, byte[] mapping) { 100 | if (!Directory.Exists(dirName)) { 101 | Directory.CreateDirectory(dirName); 102 | } 103 | string path = dirName + "\\" + devName + ".ini"; 104 | if (!File.Exists(path)) { 105 | File.Create(path); 106 | } 107 | File.WriteAllText(path, generateSaveString(mapping)); 108 | } 109 | 110 | private static string generateSaveString(byte[] Mapping) { 111 | string[] typeString = new string[] { "btn{0}", "{1}axis{0}", "dpad{0}{2}" }; 112 | string[] axesString = new string[] { "", "i", "h", "ih" }; 113 | string[] dpadString = new string[] { "up", "down", "left", "right" }; 114 | 115 | string saveString = ""; 116 | for (int i = 0; i < 21; i++) { 117 | saveString += properties[i] + "="; 118 | if (Mapping[i * 2] == 255) { 119 | saveString += "disabled\r\n"; 120 | continue; 121 | } 122 | byte subType = (byte)(Mapping[i * 2] & 0x0F); 123 | byte type = (byte)((Mapping[i * 2] & 0xF0) >> 4); 124 | byte num = (byte)(Mapping[i * 2 + 1] + 1); 125 | saveString += string.Format(typeString[type], num, axesString[subType], dpadString[subType]) + "\r\n"; 126 | } 127 | return saveString; 128 | } 129 | 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /XOutput/ScpDevice.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Windows.Forms; 5 | 6 | using System.Runtime.InteropServices; 7 | using Microsoft.Win32.SafeHandles; 8 | 9 | namespace XOutput 10 | { 11 | public partial class ScpDevice 12 | { 13 | public virtual Boolean IsActive 14 | { 15 | get { return m_IsActive; } 16 | } 17 | 18 | public virtual String Path 19 | { 20 | get { return m_Path; } 21 | } 22 | 23 | public ScpDevice(String Class) 24 | { 25 | this.m_Class = new Guid(Class); 26 | } 27 | 28 | 29 | public virtual Boolean Open(Int32 Instance = 0) 30 | { 31 | String DevicePath = String.Empty; 32 | m_WinUsbHandle = (IntPtr)INVALID_HANDLE_VALUE; 33 | 34 | if (Find(m_Class, ref DevicePath, Instance)) 35 | { 36 | Open(DevicePath); 37 | } 38 | 39 | return m_IsActive; 40 | } 41 | 42 | public virtual Boolean Open(String DevicePath) 43 | { 44 | m_Path = DevicePath.ToUpper(); 45 | m_WinUsbHandle = (IntPtr)INVALID_HANDLE_VALUE; 46 | 47 | if (GetDeviceHandle(m_Path)) 48 | { 49 | if (WinUsb_Initialize(m_FileHandle, ref m_WinUsbHandle)) 50 | { 51 | if (InitializeDevice()) 52 | { 53 | 54 | m_IsActive = true; 55 | } 56 | else 57 | { 58 | WinUsb_Free(m_WinUsbHandle); 59 | m_WinUsbHandle = (IntPtr)INVALID_HANDLE_VALUE; 60 | } 61 | } 62 | else 63 | { 64 | m_FileHandle.Close(); 65 | } 66 | } 67 | 68 | return m_IsActive; 69 | } 70 | 71 | public virtual Boolean Start() 72 | { 73 | return m_IsActive; 74 | } 75 | 76 | public virtual Boolean Stop() 77 | { 78 | m_IsActive = false; 79 | 80 | if (!(m_WinUsbHandle == (IntPtr)INVALID_HANDLE_VALUE)) 81 | { 82 | WinUsb_AbortPipe(m_WinUsbHandle, m_IntIn); 83 | WinUsb_AbortPipe(m_WinUsbHandle, m_BulkIn); 84 | WinUsb_AbortPipe(m_WinUsbHandle, m_BulkOut); 85 | 86 | WinUsb_Free(m_WinUsbHandle); 87 | m_WinUsbHandle = (IntPtr)INVALID_HANDLE_VALUE; 88 | } 89 | 90 | if (m_FileHandle != null && !m_FileHandle.IsInvalid && !m_FileHandle.IsClosed) 91 | { 92 | m_FileHandle.Close(); 93 | m_FileHandle = null; 94 | } 95 | 96 | return true; 97 | } 98 | 99 | public virtual Boolean Close() 100 | { 101 | return Stop(); 102 | } 103 | 104 | 105 | 106 | 107 | #region Constant and Structure Definitions 108 | public const Int32 SERVICE_CONTROL_STOP = 0x00000001; 109 | public const Int32 SERVICE_CONTROL_SHUTDOWN = 0x00000005; 110 | public const Int32 SERVICE_CONTROL_DEVICEEVENT = 0x0000000B; 111 | public const Int32 SERVICE_CONTROL_POWEREVENT = 0x0000000D; 112 | 113 | public const Int32 DBT_DEVICEARRIVAL = 0x8000; 114 | public const Int32 DBT_DEVICEQUERYREMOVE = 0x8001; 115 | public const Int32 DBT_DEVICEREMOVECOMPLETE = 0x8004; 116 | public const Int32 DBT_DEVTYP_DEVICEINTERFACE = 0x0005; 117 | public const Int32 DBT_DEVTYP_HANDLE = 0x0006; 118 | 119 | public const Int32 PBT_APMRESUMEAUTOMATIC = 0x0012; 120 | public const Int32 PBT_APMSUSPEND = 0x0004; 121 | 122 | public const Int32 DEVICE_NOTIFY_WINDOW_HANDLE = 0x0000; 123 | public const Int32 DEVICE_NOTIFY_SERVICE_HANDLE = 0x0001; 124 | public const Int32 DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = 0x0004; 125 | 126 | public const Int32 WM_DEVICECHANGE = 0x0219; 127 | 128 | public const Int32 DIGCF_PRESENT = 0x0002; 129 | public const Int32 DIGCF_DEVICEINTERFACE = 0x0010; 130 | 131 | public delegate Int32 ServiceControlHandlerEx(Int32 Control, Int32 Type, IntPtr Data, IntPtr Context); 132 | 133 | [StructLayout(LayoutKind.Sequential)] 134 | public class DEV_BROADCAST_DEVICEINTERFACE 135 | { 136 | internal Int32 dbcc_size; 137 | internal Int32 dbcc_devicetype; 138 | internal Int32 dbcc_reserved; 139 | internal Guid dbcc_classguid; 140 | internal Int16 dbcc_name; 141 | } 142 | 143 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 144 | public class DEV_BROADCAST_DEVICEINTERFACE_M 145 | { 146 | public Int32 dbcc_size; 147 | public Int32 dbcc_devicetype; 148 | public Int32 dbcc_reserved; 149 | 150 | [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 16)] 151 | public Byte[] dbcc_classguid; 152 | 153 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 255)] 154 | public Char[] dbcc_name; 155 | } 156 | 157 | [StructLayout(LayoutKind.Sequential)] 158 | public class DEV_BROADCAST_HDR 159 | { 160 | public Int32 dbch_size; 161 | public Int32 dbch_devicetype; 162 | public Int32 dbch_reserved; 163 | } 164 | 165 | [StructLayout(LayoutKind.Sequential)] 166 | protected struct SP_DEVICE_INTERFACE_DATA 167 | { 168 | internal Int32 cbSize; 169 | internal Guid InterfaceClassGuid; 170 | internal Int32 Flags; 171 | internal IntPtr Reserved; 172 | } 173 | 174 | protected const UInt32 FILE_ATTRIBUTE_NORMAL = 0x80; 175 | protected const UInt32 FILE_FLAG_OVERLAPPED = 0x40000000; 176 | protected const UInt32 FILE_SHARE_READ = 1; 177 | protected const UInt32 FILE_SHARE_WRITE = 2; 178 | protected const UInt32 GENERIC_READ = 0x80000000; 179 | protected const UInt32 GENERIC_WRITE = 0x40000000; 180 | protected const Int32 INVALID_HANDLE_VALUE = -1; 181 | protected const UInt32 OPEN_EXISTING = 3; 182 | protected const UInt32 DEVICE_SPEED = 1; 183 | protected const Byte USB_ENDPOINT_DIRECTION_MASK = 0x80; 184 | 185 | protected enum POLICY_TYPE 186 | { 187 | SHORT_PACKET_TERMINATE = 1, 188 | AUTO_CLEAR_STALL = 2, 189 | PIPE_TRANSFER_TIMEOUT = 3, 190 | IGNORE_SHORT_PACKETS = 4, 191 | ALLOW_PARTIAL_READS = 5, 192 | AUTO_FLUSH = 6, 193 | RAW_IO = 7, 194 | } 195 | 196 | protected enum USBD_PIPE_TYPE 197 | { 198 | UsbdPipeTypeControl = 0, 199 | UsbdPipeTypeIsochronous = 1, 200 | UsbdPipeTypeBulk = 2, 201 | UsbdPipeTypeInterrupt = 3, 202 | } 203 | 204 | protected enum USB_DEVICE_SPEED 205 | { 206 | UsbLowSpeed = 1, 207 | UsbFullSpeed = 2, 208 | UsbHighSpeed = 3, 209 | } 210 | 211 | [StructLayout(LayoutKind.Sequential)] 212 | protected struct USB_CONFIGURATION_DESCRIPTOR 213 | { 214 | internal Byte bLength; 215 | internal Byte bDescriptorType; 216 | internal UInt16 wTotalLength; 217 | internal Byte bNumInterfaces; 218 | internal Byte bConfigurationValue; 219 | internal Byte iConfiguration; 220 | internal Byte bmAttributes; 221 | internal Byte MaxPower; 222 | } 223 | 224 | [StructLayout(LayoutKind.Sequential)] 225 | protected struct USB_INTERFACE_DESCRIPTOR 226 | { 227 | internal Byte bLength; 228 | internal Byte bDescriptorType; 229 | internal Byte bInterfaceNumber; 230 | internal Byte bAlternateSetting; 231 | internal Byte bNumEndpoints; 232 | internal Byte bInterfaceClass; 233 | internal Byte bInterfaceSubClass; 234 | internal Byte bInterfaceProtocol; 235 | internal Byte iInterface; 236 | } 237 | 238 | [StructLayout(LayoutKind.Sequential)] 239 | protected struct WINUSB_PIPE_INFORMATION 240 | { 241 | internal USBD_PIPE_TYPE PipeType; 242 | internal Byte PipeId; 243 | internal UInt16 MaximumPacketSize; 244 | internal Byte Interval; 245 | } 246 | 247 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 248 | protected struct WINUSB_SETUP_PACKET 249 | { 250 | internal Byte RequestType; 251 | internal Byte Request; 252 | internal UInt16 Value; 253 | internal UInt16 Index; 254 | internal UInt16 Length; 255 | } 256 | 257 | protected const Int32 DIF_PROPERTYCHANGE = 0x12; 258 | protected const Int32 DICS_ENABLE = 1; 259 | protected const Int32 DICS_DISABLE = 2; 260 | protected const Int32 DICS_PROPCHANGE = 3; 261 | protected const Int32 DICS_FLAG_GLOBAL = 1; 262 | 263 | [StructLayout(LayoutKind.Sequential)] 264 | protected struct SP_CLASSINSTALL_HEADER 265 | { 266 | internal Int32 cbSize; 267 | internal Int32 InstallFunction; 268 | } 269 | 270 | [StructLayout(LayoutKind.Sequential)] 271 | protected struct SP_PROPCHANGE_PARAMS 272 | { 273 | internal SP_CLASSINSTALL_HEADER ClassInstallHeader; 274 | internal Int32 StateChange; 275 | internal Int32 Scope; 276 | internal Int32 HwProfile; 277 | } 278 | #endregion 279 | 280 | #region Protected Data Members 281 | protected Guid m_Class = Guid.Empty; 282 | protected String m_Path = String.Empty; 283 | 284 | protected SafeFileHandle m_FileHandle = null; 285 | protected IntPtr m_WinUsbHandle = IntPtr.Zero; 286 | 287 | protected Byte m_IntIn = 0xFF; 288 | protected Byte m_IntOut = 0xFF; 289 | protected Byte m_BulkIn = 0xFF; 290 | protected Byte m_BulkOut = 0xFF; 291 | 292 | protected Boolean m_IsActive = false; 293 | #endregion 294 | 295 | #region Static Helper Methods 296 | public enum Notified { Ignore = 0x0000, Arrival = 0x8000, QueryRemove = 0x8001, Removal = 0x8004 }; 297 | 298 | public static Boolean RegisterNotify(IntPtr Form, Guid Class, ref IntPtr Handle, Boolean Window = true) 299 | { 300 | IntPtr devBroadcastDeviceInterfaceBuffer = IntPtr.Zero; 301 | 302 | try 303 | { 304 | DEV_BROADCAST_DEVICEINTERFACE devBroadcastDeviceInterface = new DEV_BROADCAST_DEVICEINTERFACE(); 305 | Int32 Size = Marshal.SizeOf(devBroadcastDeviceInterface); 306 | 307 | devBroadcastDeviceInterface.dbcc_size = Size; 308 | devBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; 309 | devBroadcastDeviceInterface.dbcc_reserved = 0; 310 | devBroadcastDeviceInterface.dbcc_classguid = Class; 311 | 312 | devBroadcastDeviceInterfaceBuffer = Marshal.AllocHGlobal(Size); 313 | Marshal.StructureToPtr(devBroadcastDeviceInterface, devBroadcastDeviceInterfaceBuffer, true); 314 | 315 | Handle = RegisterDeviceNotification(Form, devBroadcastDeviceInterfaceBuffer, Window ? DEVICE_NOTIFY_WINDOW_HANDLE : DEVICE_NOTIFY_SERVICE_HANDLE); 316 | 317 | Marshal.PtrToStructure(devBroadcastDeviceInterfaceBuffer, devBroadcastDeviceInterface); 318 | 319 | return Handle != IntPtr.Zero; 320 | } 321 | catch (Exception ex) 322 | { 323 | Console.WriteLine("{0} {1}", ex.HelpLink, ex.Message); 324 | throw; 325 | } 326 | finally 327 | { 328 | if (devBroadcastDeviceInterfaceBuffer != IntPtr.Zero) 329 | { 330 | Marshal.FreeHGlobal(devBroadcastDeviceInterfaceBuffer); 331 | } 332 | } 333 | } 334 | 335 | public static Boolean UnregisterNotify(IntPtr Handle) 336 | { 337 | try 338 | { 339 | return UnregisterDeviceNotification(Handle); 340 | } 341 | catch (Exception ex) 342 | { 343 | Console.WriteLine("{0} {1}", ex.HelpLink, ex.Message); 344 | throw; 345 | } 346 | } 347 | #endregion 348 | 349 | #region Protected Methods 350 | protected virtual Boolean Find(Guid Target, ref String Path, Int32 Instance = 0) 351 | { 352 | IntPtr detailDataBuffer = IntPtr.Zero; 353 | IntPtr deviceInfoSet = IntPtr.Zero; 354 | 355 | try 356 | { 357 | SP_DEVICE_INTERFACE_DATA DeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA(), da = new SP_DEVICE_INTERFACE_DATA(); 358 | Int32 bufferSize = 0, memberIndex = 0; 359 | 360 | deviceInfoSet = SetupDiGetClassDevs(ref Target, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); 361 | 362 | DeviceInterfaceData.cbSize = da.cbSize = Marshal.SizeOf(DeviceInterfaceData); 363 | 364 | while (SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref Target, memberIndex, ref DeviceInterfaceData)) 365 | { 366 | SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref DeviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, ref da); 367 | { 368 | detailDataBuffer = Marshal.AllocHGlobal(bufferSize); 369 | 370 | Marshal.WriteInt32(detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8); 371 | 372 | if (SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref DeviceInterfaceData, detailDataBuffer, bufferSize, ref bufferSize, ref da)) 373 | { 374 | IntPtr pDevicePathName = new IntPtr(IntPtr.Size == 4 ? detailDataBuffer.ToInt32() + 4 : detailDataBuffer.ToInt64() + 4); 375 | 376 | Path = Marshal.PtrToStringAuto(pDevicePathName).ToUpper(); 377 | Marshal.FreeHGlobal(detailDataBuffer); 378 | 379 | if (memberIndex == Instance) return true; 380 | } 381 | else Marshal.FreeHGlobal(detailDataBuffer); 382 | } 383 | 384 | memberIndex++; 385 | } 386 | } 387 | catch (Exception ex) 388 | { 389 | Console.WriteLine("{0} {1}", ex.HelpLink, ex.Message); 390 | throw; 391 | } 392 | finally 393 | { 394 | if (deviceInfoSet != IntPtr.Zero) 395 | { 396 | SetupDiDestroyDeviceInfoList(deviceInfoSet); 397 | } 398 | } 399 | 400 | return false; 401 | } 402 | 403 | 404 | protected virtual Boolean GetDeviceHandle(String Path) 405 | { 406 | m_FileHandle = CreateFile(Path, (GENERIC_WRITE | GENERIC_READ), FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0); 407 | 408 | return !m_FileHandle.IsInvalid; 409 | } 410 | 411 | protected virtual Boolean UsbEndpointDirectionIn(Int32 addr) 412 | { 413 | return (addr & 0x80) == 0x80; 414 | } 415 | 416 | protected virtual Boolean UsbEndpointDirectionOut(Int32 addr) 417 | { 418 | return (addr & 0x80) == 0x00; 419 | } 420 | 421 | protected virtual Boolean InitializeDevice() 422 | { 423 | try 424 | { 425 | USB_INTERFACE_DESCRIPTOR ifaceDescriptor = new USB_INTERFACE_DESCRIPTOR(); 426 | WINUSB_PIPE_INFORMATION pipeInfo = new WINUSB_PIPE_INFORMATION(); 427 | 428 | if (WinUsb_QueryInterfaceSettings(m_WinUsbHandle, 0, ref ifaceDescriptor)) 429 | { 430 | for (Int32 i = 0; i < ifaceDescriptor.bNumEndpoints; i++) 431 | { 432 | WinUsb_QueryPipe(m_WinUsbHandle, 0, System.Convert.ToByte(i), ref pipeInfo); 433 | 434 | if (((pipeInfo.PipeType == USBD_PIPE_TYPE.UsbdPipeTypeBulk) & UsbEndpointDirectionIn(pipeInfo.PipeId))) 435 | { 436 | m_BulkIn = pipeInfo.PipeId; 437 | WinUsb_FlushPipe(m_WinUsbHandle, m_BulkIn); 438 | } 439 | else if (((pipeInfo.PipeType == USBD_PIPE_TYPE.UsbdPipeTypeBulk) & UsbEndpointDirectionOut(pipeInfo.PipeId))) 440 | { 441 | m_BulkOut = pipeInfo.PipeId; 442 | WinUsb_FlushPipe(m_WinUsbHandle, m_BulkOut); 443 | } 444 | else if ((pipeInfo.PipeType == USBD_PIPE_TYPE.UsbdPipeTypeInterrupt) & UsbEndpointDirectionIn(pipeInfo.PipeId)) 445 | { 446 | m_IntIn = pipeInfo.PipeId; 447 | WinUsb_FlushPipe(m_WinUsbHandle, m_IntIn); 448 | } 449 | else if ((pipeInfo.PipeType == USBD_PIPE_TYPE.UsbdPipeTypeInterrupt) & UsbEndpointDirectionOut(pipeInfo.PipeId)) 450 | { 451 | m_IntOut = pipeInfo.PipeId; 452 | WinUsb_FlushPipe(m_WinUsbHandle, m_IntOut); 453 | } 454 | } 455 | 456 | return true; 457 | } 458 | 459 | return false; 460 | } 461 | catch (Exception ex) 462 | { 463 | Console.WriteLine("{0} {1}", ex.HelpLink, ex.Message); 464 | throw; 465 | } 466 | } 467 | 468 | #endregion 469 | 470 | #region Interop Definitions 471 | [DllImport("setupapi.dll", SetLastError = true)] 472 | protected static extern Int32 SetupDiCreateDeviceInfoList(ref System.Guid ClassGuid, Int32 hwndParent); 473 | 474 | [DllImport("setupapi.dll", SetLastError = true)] 475 | protected static extern Int32 SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet); 476 | 477 | [DllImport("setupapi.dll", SetLastError = true)] 478 | protected static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr DeviceInfoSet, IntPtr DeviceInfoData, ref System.Guid InterfaceClassGuid, Int32 MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData); 479 | 480 | [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)] 481 | protected static extern IntPtr SetupDiGetClassDevs(ref System.Guid ClassGuid, IntPtr Enumerator, IntPtr hwndParent, Int32 Flags); 482 | 483 | [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)] 484 | protected static extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, IntPtr DeviceInfoData); 485 | 486 | [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)] 487 | protected static extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, ref SP_DEVICE_INTERFACE_DATA DeviceInfoData); 488 | 489 | [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 490 | protected static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, IntPtr NotificationFilter, Int32 Flags); 491 | 492 | [DllImport("user32.dll", SetLastError = true)] 493 | protected static extern Boolean UnregisterDeviceNotification(IntPtr Handle); 494 | 495 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] 496 | protected static extern SafeFileHandle CreateFile(String lpFileName, UInt32 dwDesiredAccess, UInt32 dwShareMode, IntPtr lpSecurityAttributes, UInt32 dwCreationDisposition, UInt32 dwFlagsAndAttributes, UInt32 hTemplateFile); 497 | 498 | [DllImport("winusb.dll", SetLastError = true)] 499 | protected static extern Boolean WinUsb_Initialize(SafeFileHandle DeviceHandle, ref IntPtr InterfaceHandle); 500 | 501 | [DllImport("winusb.dll", SetLastError = true)] 502 | protected static extern Boolean WinUsb_QueryInterfaceSettings(IntPtr InterfaceHandle, Byte AlternateInterfaceNumber, ref USB_INTERFACE_DESCRIPTOR UsbAltInterfaceDescriptor); 503 | 504 | [DllImport("winusb.dll", SetLastError = true)] 505 | protected static extern Boolean WinUsb_QueryPipe(IntPtr InterfaceHandle, Byte AlternateInterfaceNumber, Byte PipeIndex, ref WINUSB_PIPE_INFORMATION PipeInformation); 506 | 507 | [DllImport("winusb.dll", SetLastError = true)] 508 | protected static extern Boolean WinUsb_AbortPipe(IntPtr InterfaceHandle, Byte PipeID); 509 | 510 | [DllImport("winusb.dll", SetLastError = true)] 511 | protected static extern Boolean WinUsb_FlushPipe(IntPtr InterfaceHandle, Byte PipeID); 512 | 513 | [DllImport("winusb.dll", SetLastError = true)] 514 | protected static extern Boolean WinUsb_ControlTransfer(IntPtr InterfaceHandle, WINUSB_SETUP_PACKET SetupPacket, Byte[] Buffer, Int32 BufferLength, ref Int32 LengthTransferred, IntPtr Overlapped); 515 | 516 | [DllImport("winusb.dll", SetLastError = true)] 517 | protected static extern Boolean WinUsb_ReadPipe(IntPtr InterfaceHandle, Byte PipeID, Byte[] Buffer, Int32 BufferLength, ref Int32 LengthTransferred, IntPtr Overlapped); 518 | 519 | [DllImport("winusb.dll", SetLastError = true)] 520 | protected static extern Boolean WinUsb_WritePipe(IntPtr InterfaceHandle, Byte PipeID, Byte[] Buffer, Int32 BufferLength, ref Int32 LengthTransferred, IntPtr Overlapped); 521 | 522 | [DllImport("winusb.dll", SetLastError = true)] 523 | protected static extern Boolean WinUsb_Free(IntPtr InterfaceHandle); 524 | 525 | [DllImport("advapi32.dll", SetLastError = true)] 526 | public static extern IntPtr RegisterServiceCtrlHandlerEx(String ServiceName, ServiceControlHandlerEx Callback, IntPtr Context); 527 | 528 | [DllImport("kernel32.dll", SetLastError = true)] 529 | protected static extern Boolean DeviceIoControl(SafeFileHandle DeviceHandle, Int32 IoControlCode, Byte[] InBuffer, Int32 InBufferSize, Byte[] OutBuffer, Int32 OutBufferSize, ref Int32 BytesReturned, IntPtr Overlapped); 530 | 531 | [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)] 532 | protected static extern Int32 CM_Get_Device_ID(Int32 dnDevInst, IntPtr Buffer, Int32 BufferLen, Int32 ulFlags); 533 | 534 | [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)] 535 | protected static extern Boolean SetupDiOpenDeviceInfo(IntPtr DeviceInfoSet, String DeviceInstanceId, IntPtr hwndParent, Int32 Flags, ref SP_DEVICE_INTERFACE_DATA DeviceInfoData); 536 | 537 | [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)] 538 | protected static extern Boolean SetupDiChangeState(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData); 539 | 540 | [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)] 541 | protected static extern Boolean SetupDiSetClassInstallParams(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, ref SP_PROPCHANGE_PARAMS ClassInstallParams, Int32 ClassInstallParamsSize); 542 | #endregion 543 | } 544 | } 545 | -------------------------------------------------------------------------------- /XOutput/XOut.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace XOutput 2 | { 3 | partial class XOut 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(XOut)); 32 | this.StartStopBtn = new System.Windows.Forms.Button(); 33 | this.controllerBoxOne = new System.Windows.Forms.GroupBox(); 34 | this.optionsOne = new System.Windows.Forms.Button(); 35 | this.moveOneDown = new System.Windows.Forms.Button(); 36 | this.enabledTwo = new System.Windows.Forms.CheckBox(); 37 | this.enabledOne = new System.Windows.Forms.CheckBox(); 38 | this.controllerBoxTwo = new System.Windows.Forms.GroupBox(); 39 | this.optionsTwo = new System.Windows.Forms.Button(); 40 | this.moveTwoUp = new System.Windows.Forms.Button(); 41 | this.moveTwoDown = new System.Windows.Forms.Button(); 42 | this.controllerBoxThree = new System.Windows.Forms.GroupBox(); 43 | this.optionsThree = new System.Windows.Forms.Button(); 44 | this.moveThreeUp = new System.Windows.Forms.Button(); 45 | this.moveThreeDown = new System.Windows.Forms.Button(); 46 | this.enabledThree = new System.Windows.Forms.CheckBox(); 47 | this.controllerBoxFour = new System.Windows.Forms.GroupBox(); 48 | this.optionsFour = new System.Windows.Forms.Button(); 49 | this.moveFourUp = new System.Windows.Forms.Button(); 50 | this.enabledFour = new System.Windows.Forms.CheckBox(); 51 | this.isExclusive = new System.Windows.Forms.CheckBox(); 52 | this.controllerBoxOne.SuspendLayout(); 53 | this.controllerBoxTwo.SuspendLayout(); 54 | this.controllerBoxThree.SuspendLayout(); 55 | this.controllerBoxFour.SuspendLayout(); 56 | this.SuspendLayout(); 57 | // 58 | // StartStopBtn 59 | // 60 | this.StartStopBtn.Location = new System.Drawing.Point(397, 316); 61 | this.StartStopBtn.Name = "StartStopBtn"; 62 | this.StartStopBtn.Size = new System.Drawing.Size(75, 23); 63 | this.StartStopBtn.TabIndex = 0; 64 | this.StartStopBtn.Text = "Start"; 65 | this.StartStopBtn.UseVisualStyleBackColor = true; 66 | this.StartStopBtn.Click += new System.EventHandler(this.StartStopBtn_Click); 67 | // 68 | // controllerBoxOne 69 | // 70 | this.controllerBoxOne.Controls.Add(this.optionsOne); 71 | this.controllerBoxOne.Controls.Add(this.moveOneDown); 72 | this.controllerBoxOne.Location = new System.Drawing.Point(12, 12); 73 | this.controllerBoxOne.Name = "controllerBoxOne"; 74 | this.controllerBoxOne.Size = new System.Drawing.Size(460, 70); 75 | this.controllerBoxOne.TabIndex = 1; 76 | this.controllerBoxOne.TabStop = false; 77 | this.controllerBoxOne.Text = "`"; 78 | // 79 | // optionsOne 80 | // 81 | this.optionsOne.Image = global::XOutput.Properties.Resources.gear; 82 | this.optionsOne.Location = new System.Drawing.Point(6, 41); 83 | this.optionsOne.Name = "optionsOne"; 84 | this.optionsOne.Size = new System.Drawing.Size(27, 23); 85 | this.optionsOne.TabIndex = 7; 86 | this.optionsOne.UseVisualStyleBackColor = true; 87 | // 88 | // moveOneDown 89 | // 90 | this.moveOneDown.Image = global::XOutput.Properties.Resources.arrow_Down; 91 | this.moveOneDown.Location = new System.Drawing.Point(427, 41); 92 | this.moveOneDown.Name = "moveOneDown"; 93 | this.moveOneDown.Size = new System.Drawing.Size(27, 23); 94 | this.moveOneDown.TabIndex = 1; 95 | this.moveOneDown.UseVisualStyleBackColor = true; 96 | // 97 | // enabledTwo 98 | // 99 | this.enabledTwo.AutoSize = true; 100 | this.enabledTwo.Checked = true; 101 | this.enabledTwo.CheckState = System.Windows.Forms.CheckState.Checked; 102 | this.enabledTwo.Location = new System.Drawing.Point(51, 133); 103 | this.enabledTwo.Name = "enabledTwo"; 104 | this.enabledTwo.Size = new System.Drawing.Size(65, 17); 105 | this.enabledTwo.TabIndex = 8; 106 | this.enabledTwo.Text = "Enabled"; 107 | this.enabledTwo.UseVisualStyleBackColor = true; 108 | // 109 | // enabledOne 110 | // 111 | this.enabledOne.AutoSize = true; 112 | this.enabledOne.Checked = true; 113 | this.enabledOne.CheckState = System.Windows.Forms.CheckState.Checked; 114 | this.enabledOne.Location = new System.Drawing.Point(51, 56); 115 | this.enabledOne.Name = "enabledOne"; 116 | this.enabledOne.Size = new System.Drawing.Size(65, 17); 117 | this.enabledOne.TabIndex = 6; 118 | this.enabledOne.Text = "Enabled"; 119 | this.enabledOne.UseVisualStyleBackColor = true; 120 | // 121 | // controllerBoxTwo 122 | // 123 | this.controllerBoxTwo.Controls.Add(this.optionsTwo); 124 | this.controllerBoxTwo.Controls.Add(this.moveTwoUp); 125 | this.controllerBoxTwo.Controls.Add(this.moveTwoDown); 126 | this.controllerBoxTwo.Location = new System.Drawing.Point(12, 88); 127 | this.controllerBoxTwo.Name = "controllerBoxTwo"; 128 | this.controllerBoxTwo.Size = new System.Drawing.Size(460, 70); 129 | this.controllerBoxTwo.TabIndex = 2; 130 | this.controllerBoxTwo.TabStop = false; 131 | // 132 | // optionsTwo 133 | // 134 | this.optionsTwo.Image = global::XOutput.Properties.Resources.gear; 135 | this.optionsTwo.Location = new System.Drawing.Point(6, 41); 136 | this.optionsTwo.Name = "optionsTwo"; 137 | this.optionsTwo.Size = new System.Drawing.Size(27, 23); 138 | this.optionsTwo.TabIndex = 7; 139 | this.optionsTwo.UseVisualStyleBackColor = true; 140 | // 141 | // moveTwoUp 142 | // 143 | this.moveTwoUp.Image = global::XOutput.Properties.Resources.arrow_Up; 144 | this.moveTwoUp.Location = new System.Drawing.Point(427, 12); 145 | this.moveTwoUp.Name = "moveTwoUp"; 146 | this.moveTwoUp.Size = new System.Drawing.Size(27, 23); 147 | this.moveTwoUp.TabIndex = 3; 148 | this.moveTwoUp.UseVisualStyleBackColor = true; 149 | // 150 | // moveTwoDown 151 | // 152 | this.moveTwoDown.Image = global::XOutput.Properties.Resources.arrow_Down; 153 | this.moveTwoDown.Location = new System.Drawing.Point(427, 41); 154 | this.moveTwoDown.Name = "moveTwoDown"; 155 | this.moveTwoDown.Size = new System.Drawing.Size(27, 23); 156 | this.moveTwoDown.TabIndex = 2; 157 | this.moveTwoDown.UseVisualStyleBackColor = true; 158 | // 159 | // controllerBoxThree 160 | // 161 | this.controllerBoxThree.Controls.Add(this.optionsThree); 162 | this.controllerBoxThree.Controls.Add(this.moveThreeUp); 163 | this.controllerBoxThree.Controls.Add(this.moveThreeDown); 164 | this.controllerBoxThree.Location = new System.Drawing.Point(12, 164); 165 | this.controllerBoxThree.Name = "controllerBoxThree"; 166 | this.controllerBoxThree.Size = new System.Drawing.Size(460, 70); 167 | this.controllerBoxThree.TabIndex = 3; 168 | this.controllerBoxThree.TabStop = false; 169 | // 170 | // optionsThree 171 | // 172 | this.optionsThree.Image = global::XOutput.Properties.Resources.gear; 173 | this.optionsThree.Location = new System.Drawing.Point(6, 41); 174 | this.optionsThree.Name = "optionsThree"; 175 | this.optionsThree.Size = new System.Drawing.Size(27, 23); 176 | this.optionsThree.TabIndex = 6; 177 | this.optionsThree.UseVisualStyleBackColor = true; 178 | // 179 | // moveThreeUp 180 | // 181 | this.moveThreeUp.Image = global::XOutput.Properties.Resources.arrow_Up; 182 | this.moveThreeUp.Location = new System.Drawing.Point(427, 12); 183 | this.moveThreeUp.Name = "moveThreeUp"; 184 | this.moveThreeUp.Size = new System.Drawing.Size(27, 23); 185 | this.moveThreeUp.TabIndex = 4; 186 | this.moveThreeUp.UseVisualStyleBackColor = true; 187 | // 188 | // moveThreeDown 189 | // 190 | this.moveThreeDown.Image = global::XOutput.Properties.Resources.arrow_Down; 191 | this.moveThreeDown.Location = new System.Drawing.Point(427, 41); 192 | this.moveThreeDown.Name = "moveThreeDown"; 193 | this.moveThreeDown.Size = new System.Drawing.Size(27, 23); 194 | this.moveThreeDown.TabIndex = 3; 195 | this.moveThreeDown.UseVisualStyleBackColor = true; 196 | // 197 | // enabledThree 198 | // 199 | this.enabledThree.AutoSize = true; 200 | this.enabledThree.Checked = true; 201 | this.enabledThree.CheckState = System.Windows.Forms.CheckState.Checked; 202 | this.enabledThree.Location = new System.Drawing.Point(51, 209); 203 | this.enabledThree.Name = "enabledThree"; 204 | this.enabledThree.Size = new System.Drawing.Size(65, 17); 205 | this.enabledThree.TabIndex = 7; 206 | this.enabledThree.Text = "Enabled"; 207 | this.enabledThree.UseVisualStyleBackColor = true; 208 | // 209 | // controllerBoxFour 210 | // 211 | this.controllerBoxFour.Controls.Add(this.optionsFour); 212 | this.controllerBoxFour.Controls.Add(this.moveFourUp); 213 | this.controllerBoxFour.Location = new System.Drawing.Point(12, 240); 214 | this.controllerBoxFour.Name = "controllerBoxFour"; 215 | this.controllerBoxFour.Size = new System.Drawing.Size(460, 70); 216 | this.controllerBoxFour.TabIndex = 4; 217 | this.controllerBoxFour.TabStop = false; 218 | // 219 | // optionsFour 220 | // 221 | this.optionsFour.Image = global::XOutput.Properties.Resources.gear; 222 | this.optionsFour.Location = new System.Drawing.Point(6, 41); 223 | this.optionsFour.Name = "optionsFour"; 224 | this.optionsFour.Size = new System.Drawing.Size(27, 23); 225 | this.optionsFour.TabIndex = 5; 226 | this.optionsFour.UseVisualStyleBackColor = true; 227 | // 228 | // moveFourUp 229 | // 230 | this.moveFourUp.Image = global::XOutput.Properties.Resources.arrow_Up; 231 | this.moveFourUp.Location = new System.Drawing.Point(427, 12); 232 | this.moveFourUp.Name = "moveFourUp"; 233 | this.moveFourUp.Size = new System.Drawing.Size(27, 23); 234 | this.moveFourUp.TabIndex = 4; 235 | this.moveFourUp.UseVisualStyleBackColor = true; 236 | // 237 | // enabledFour 238 | // 239 | this.enabledFour.AutoSize = true; 240 | this.enabledFour.Checked = true; 241 | this.enabledFour.CheckState = System.Windows.Forms.CheckState.Checked; 242 | this.enabledFour.Location = new System.Drawing.Point(51, 285); 243 | this.enabledFour.Name = "enabledFour"; 244 | this.enabledFour.Size = new System.Drawing.Size(65, 17); 245 | this.enabledFour.TabIndex = 7; 246 | this.enabledFour.Text = "Enabled"; 247 | this.enabledFour.UseVisualStyleBackColor = true; 248 | // 249 | // isExclusive 250 | // 251 | this.isExclusive.AutoSize = true; 252 | this.isExclusive.Location = new System.Drawing.Point(18, 320); 253 | this.isExclusive.Name = "isExclusive"; 254 | this.isExclusive.Size = new System.Drawing.Size(75, 17); 255 | this.isExclusive.TabIndex = 9; 256 | this.isExclusive.Text = "Exclusivity"; 257 | this.isExclusive.UseVisualStyleBackColor = true; 258 | this.isExclusive.CheckedChanged += new System.EventHandler(this.isExclusive_CheckedChanged); 259 | // 260 | // XOut 261 | // 262 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 263 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 264 | this.ClientSize = new System.Drawing.Size(484, 351); 265 | this.Controls.Add(this.isExclusive); 266 | this.Controls.Add(this.enabledOne); 267 | this.Controls.Add(this.enabledTwo); 268 | this.Controls.Add(this.enabledThree); 269 | this.Controls.Add(this.enabledFour); 270 | this.Controls.Add(this.controllerBoxOne); 271 | this.Controls.Add(this.controllerBoxTwo); 272 | this.Controls.Add(this.controllerBoxThree); 273 | this.Controls.Add(this.controllerBoxFour); 274 | this.Controls.Add(this.StartStopBtn); 275 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 276 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 277 | this.MaximizeBox = false; 278 | this.Name = "XOut"; 279 | this.Text = "XOutput"; 280 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.XOut_Closing); 281 | this.Load += new System.EventHandler(this.XOut_Load); 282 | this.Shown += new System.EventHandler(this.XOut_Shown); 283 | this.controllerBoxOne.ResumeLayout(false); 284 | this.controllerBoxTwo.ResumeLayout(false); 285 | this.controllerBoxThree.ResumeLayout(false); 286 | this.controllerBoxFour.ResumeLayout(false); 287 | this.ResumeLayout(false); 288 | this.PerformLayout(); 289 | 290 | } 291 | 292 | #endregion 293 | 294 | private System.Windows.Forms.Button StartStopBtn; 295 | 296 | private System.Windows.Forms.GroupBox[] boxes; 297 | private System.Windows.Forms.CheckBox[] checks; 298 | private System.Windows.Forms.Button[] options; 299 | private ControllerOptions optionsWindow; 300 | private ControllerManager controllerManager; 301 | private System.Windows.Forms.GroupBox controllerBoxOne; 302 | private System.Windows.Forms.GroupBox controllerBoxTwo; 303 | private System.Windows.Forms.GroupBox controllerBoxThree; 304 | private System.Windows.Forms.GroupBox controllerBoxFour; 305 | private System.Windows.Forms.Button moveOneDown; 306 | private System.Windows.Forms.Button moveTwoUp; 307 | private System.Windows.Forms.Button moveTwoDown; 308 | private System.Windows.Forms.Button moveThreeUp; 309 | private System.Windows.Forms.Button moveThreeDown; 310 | private System.Windows.Forms.Button moveFourUp; 311 | private System.Windows.Forms.Button optionsOne; 312 | private System.Windows.Forms.Button optionsTwo; 313 | private System.Windows.Forms.Button optionsThree; 314 | private System.Windows.Forms.Button optionsFour; 315 | private System.Windows.Forms.CheckBox enabledOne; 316 | private System.Windows.Forms.CheckBox enabledTwo; 317 | private System.Windows.Forms.CheckBox enabledThree; 318 | private System.Windows.Forms.CheckBox enabledFour; 319 | private System.Windows.Forms.CheckBox isExclusive; 320 | } 321 | } -------------------------------------------------------------------------------- /XOutput/XOut.cs: -------------------------------------------------------------------------------- 1 | using SlimDX.DirectInput; 2 | using System; 3 | using System.Windows.Forms; 4 | 5 | namespace XOutput 6 | { 7 | public partial class XOut : Form 8 | { 9 | 10 | public XOut() 11 | { 12 | InitializeComponent(); 13 | this.moveOneDown.Click += (sender, e) => Swap(1, 2); 14 | this.moveTwoUp.Click += (sender, e) => Swap(2, 1); 15 | this.moveTwoDown.Click += (sender, e) => Swap(2, 3); 16 | this.moveThreeUp.Click += (sender, e) => Swap(3, 2); 17 | this.moveThreeDown.Click += (sender, e) => Swap(3, 4); 18 | this.moveFourUp.Click += (sender, e) => Swap(4, 3); 19 | this.enabledOne.CheckedChanged += (sender, e) => enabledChanged(0); 20 | this.enabledTwo.CheckedChanged += (sender, e) => enabledChanged(1); 21 | this.enabledThree.CheckedChanged += (sender, e) => enabledChanged(2); 22 | this.enabledFour.CheckedChanged += (sender, e) => enabledChanged(3); 23 | this.optionsOne.Click += (sender, e) => openOptions(0); 24 | this.optionsTwo.Click += (sender, e) => openOptions(1); 25 | this.optionsThree.Click += (sender, e) => openOptions(2); 26 | this.optionsFour.Click += (sender, e) => openOptions(3); 27 | 28 | boxes = new System.Windows.Forms.GroupBox[4] { controllerBoxOne, controllerBoxTwo, controllerBoxThree, controllerBoxFour }; 29 | checks = new System.Windows.Forms.CheckBox[4] { enabledOne, enabledTwo, enabledThree, enabledFour }; 30 | options = new System.Windows.Forms.Button[4] { optionsOne, optionsTwo, optionsThree, optionsFour }; 31 | } 32 | 33 | private void XOut_Load(object sender, EventArgs e) 34 | { 35 | controllerManager = new ControllerManager(this); 36 | } 37 | 38 | private void XOut_Shown(object sender, EventArgs e) 39 | { 40 | UpdateInfo(controllerManager.detectControllers()); 41 | } 42 | 43 | private void XOut_Closing(object sender, FormClosingEventArgs e) 44 | { 45 | if (controllerManager.IsActive) 46 | { 47 | controllerManager.Stop(); 48 | } 49 | } 50 | 51 | private void StartStopBtn_Click(object sender, EventArgs e) 52 | { 53 | if (StartStopBtn.Text == "Start") 54 | { 55 | if (optionsWindow != null) 56 | { 57 | System.Media.SystemSounds.Asterisk.Play(); 58 | optionsWindow.Focus(); 59 | return; 60 | } 61 | if (controllerManager.Start()) 62 | { 63 | StartStopBtn.Text = "Stop"; 64 | for (int i = 0; i < 4; i++) 65 | { 66 | checks[i].Enabled = false; 67 | isExclusive.Enabled = false; 68 | foreach (Control con in boxes[i].Controls) 69 | { 70 | con.Enabled = false; 71 | } 72 | } 73 | } 74 | } 75 | else 76 | { 77 | if (controllerManager.Stop()) 78 | { 79 | StartStopBtn.Text = "Start"; 80 | for (int i = 0; i < 4; i++) 81 | { 82 | checks[i].Enabled = true; 83 | isExclusive.Enabled = true; 84 | foreach (Control con in boxes[i].Controls) 85 | { 86 | con.Enabled = true; 87 | } 88 | } 89 | } 90 | } 91 | } 92 | 93 | private void UpdateInfo(ControllerDevice[] dev) 94 | { 95 | for (int i = 0; i < 4; i++) 96 | { 97 | if (dev[i] != null) 98 | { 99 | boxes[i].Visible = true; 100 | boxes[i].Text = (i + 1).ToString() + ": " + dev[i].name; 101 | checks[i].Visible = true; 102 | } 103 | else 104 | { 105 | boxes[i].Visible = false; 106 | checks[i].Visible = false; 107 | } 108 | } 109 | } 110 | 111 | private void Swap(int i, int p) 112 | { 113 | bool s = checks[i - 1].Checked; 114 | checks[i- 1].Checked = checks[p - 1].Checked; 115 | checks[p - 1].Checked = s; 116 | controllerManager.Swap(i, p); 117 | 118 | UpdateInfo(controllerManager.detectControllers()); 119 | } 120 | 121 | 122 | 123 | private void enabledChanged(int i) 124 | { 125 | boxes[i].Enabled = checks[i].Checked; 126 | controllerManager.setControllerEnable(i, checks[i].Checked); 127 | } 128 | 129 | private void openOptions(int i) 130 | { 131 | if (optionsWindow == null) 132 | { 133 | optionsWindow = new ControllerOptions(controllerManager.getController(i)); 134 | optionsWindow.Show(); 135 | optionsWindow.Activate(); 136 | optionsWindow.FormClosed += (sender, e) => { optionsWindow = null; }; 137 | } 138 | else 139 | { 140 | System.Media.SystemSounds.Asterisk.Play(); 141 | optionsWindow.Focus(); 142 | } 143 | } 144 | 145 | protected override void WndProc(ref Message m) 146 | { 147 | try 148 | { 149 | if (m.Msg == 0x0219) 150 | { 151 | lock (this) 152 | { 153 | UpdateInfo(controllerManager.detectControllers()); 154 | } 155 | } 156 | } 157 | catch { } 158 | 159 | base.WndProc(ref m); 160 | } 161 | 162 | private void isExclusive_CheckedChanged(object sender, EventArgs e) 163 | { 164 | controllerManager.changeExclusive(!controllerManager.isExclusive); 165 | } 166 | 167 | 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /XOutput/XOutput.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {3FA04C64-23DE-4294-B9D7-47BBFFB57539} 8 | WinExe 9 | Properties 10 | XOutput 11 | XOutput 12 | v4.5 13 | 512 14 | false 15 | publish\ 16 | true 17 | Disk 18 | false 19 | Foreground 20 | 7 21 | Days 22 | false 23 | false 24 | true 25 | 0 26 | 1.0.0.%2a 27 | false 28 | true 29 | 30 | 31 | x86 32 | true 33 | full 34 | false 35 | bin\Debug\ 36 | DEBUG;TRACE 37 | prompt 38 | 4 39 | true 40 | 41 | 42 | AnyCPU 43 | pdbonly 44 | true 45 | bin\Release\ 46 | TRACE 47 | prompt 48 | 4 49 | true 50 | 51 | 52 | 53 | 54 | 55 | 56 | XOutput_Icon.ico 57 | 58 | 59 | true 60 | 61 | 62 | false 63 | 64 | 65 | x86 66 | bin\x86\Debug\ 67 | 68 | 69 | x86 70 | bin\x86\Release\ 71 | 72 | 73 | 74 | False 75 | ..\..\..\..\..\..\..\Windows\Microsoft.NET\assembly\GAC_32\SlimDX\v4.0_4.0.13.43__b1b0c32fd1ffe4f9\SlimDX.dll 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | Form 93 | 94 | 95 | ControllerOptions.cs 96 | 97 | 98 | 99 | Component 100 | 101 | 102 | 103 | 104 | 105 | 106 | Form 107 | 108 | 109 | XOut.cs 110 | 111 | 112 | ResXFileCodeGenerator 113 | Resources.Designer.cs 114 | Designer 115 | 116 | 117 | True 118 | Resources.resx 119 | True 120 | 121 | 122 | XOut.cs 123 | 124 | 125 | SettingsSingleFileGenerator 126 | Settings.Designer.cs 127 | 128 | 129 | True 130 | Settings.settings 131 | True 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | False 140 | Microsoft .NET Framework 4.5 %28x86 and x64%29 141 | true 142 | 143 | 144 | False 145 | .NET Framework 3.5 SP1 Client Profile 146 | false 147 | 148 | 149 | False 150 | .NET Framework 3.5 SP1 151 | false 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 177 | -------------------------------------------------------------------------------- /XOutput/XOutput.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | publish\ 5 | 6 | 7 | 8 | 9 | 10 | en-US 11 | false 12 | 13 | -------------------------------------------------------------------------------- /XOutput/XOutput_Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mintos5/XOutput/c878b3c3b6c5e1714d300f630c4fb2cddc32374a/XOutput/XOutput_Icon.ico --------------------------------------------------------------------------------