using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using LibUsbDotNet; using LibUsbDotNet.Main; using USBSimulator; namespace Salamax { public class SimulatedController : USBSimulator.IUSBDevice { private USBSimulator.USBSimulatorDevice _device; private Xbox360Controller _realController; private bool _configured = false; public byte[] KeyData = null; public List Endpoints { get; set; } public void OnInitialize(USBSimulator.USBSimulatorDevice device) { _device = device; _realController = new Xbox360Controller(); Endpoints = new List(); Endpoints.Add(new EndpointInformation(0x01, EndpointInformation.EndpointDirection.Incoming, EndpointInformation.EndpointType.Interrupt, 0x20)); Endpoints.Add(new EndpointInformation(0x02, EndpointInformation.EndpointDirection.Outgoing, EndpointInformation.EndpointType.Interrupt, 0x20)); KeyData = new byte[] { 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x09, 0x42, 0x06, 0x00, 0x00, 0x8D, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; var th = new Thread(new ThreadStart(_SendStatusMessages)); th.IsBackground = true; th.Start(); } private void _SendStatusMessages() { while (true) { if (_configured) { _device.WriteOutgoingData(0x01, KeyData); } Thread.Sleep(10); } } public void Stop() { _configured = false; } public void OnShutdown() { if (_realController != null) { _realController.Disconnect(); _realController = null; } } public void OnIncomingDataReceived(USBSimulator.IncomingDataEventArgs e) { } public void OnDescriptorRequested(USBSimulator.DescriptorRequestedEventArgs e) { if (_realController != null) { var data = new byte[0x400]; var buffer = new byte[0x400]; var setup = new UsbSetupPacket(0x80, 0x06, (short)e.wValue, (short)e.wIndex, (short)data.Length); int transferred; _realController.DoControlTransfer(ref setup, ref buffer, data.Length, out transferred); e.DescriptorData = new byte[transferred]; Array.Copy(buffer, 0, e.DescriptorData, 0, transferred); } if (((e.wValue >> 8) & 0xFF) == 0x01) { //Device descriptor, fix the max packet size if (e.DescriptorData != null && e.DescriptorData.Length >= 7) e.DescriptorData[7] = 0x40; } /* switch ((e.wValue >> 8) & 0xFF) { case 0x01: //Device descriptor { e.DescriptorData = _deviceDescriptor; break; } case 0x02: //Configuration descriptor { e.DescriptorData = _configDescriptor; e.DescriptorData[2] = (byte)(e.DescriptorData.Length & 0xFF); e.DescriptorData[3] = (byte)((e.DescriptorData.Length >> 8) & 0xFF); break; } case 0x03: //String descriptor { if ((e.wValue & 0xFF) == 0x04) { e.DescriptorData = new byte[] { 0xB2, 0x03, 0x58, 0x00, 0x62, 0x00, 0x6F, 0x00, 0x78, 0x00, 0x20, 0x00, 0x53, 0x00, 0x65, 0x00, 0x63, 0x00, 0x75, 0x00, 0x72, 0x00, 0x69, 0x00, 0x74, 0x00, 0x79, 0x00, 0x20, 0x00, 0x4D, 0x00, 0x65, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x20, 0x00, 0x33, 0x00, 0x2C, 0x00, 0x20, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x20, 0x00, 0x31, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x30, 0x00, 0x2C, 0x00, 0x20, 0x00, 0xA9, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x35, 0x00, 0x20, 0x00, 0x4D, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x73, 0x00, 0x6F, 0x00, 0x66, 0x00, 0x74, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x70, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x2E, 0x00, 0x20, 0x00, 0x41, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x20, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x64, 0x00, 0x2E, 0x00 }; } break; } default: { //Uh? break; } } */ } static bool stall87 = false; public void OnControlRequestReceived(ControlRequestEventArgs e) { bool forward = false; switch (e.bmRequestType) { case 0x00: { switch (e.bRequest) { case 0x09: { stall87 = false; break; } } break; } case 0xC0: { switch (e.bRequest) { case 0x01: { e.ReturnData = new byte[] { 0x06, 0x33, 0x45, 0x7B }; e.Ignore = false; break; } default: break; } break; } case 0xC1: { switch (e.bRequest) { case 0x01: { e.ReturnData = new byte[] { 0x00, 0x14, 0xFF, 0xF7, 0xFF, 0xFF, 0xC0, 0xFF, 0xC0, 0xFF, 0xC0, 0xFF, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; e.Ignore = false; //_device.WriteOutgoingData(0x01, new byte[] { 0x02, 0x03, 0x00 }); _configured = true; break; } case 0x81: //Request static data case 0x83: //Get response case 0x86: //Get response status { forward = true; break; } default: break; } if (forward) { if (_realController != null) { var setup = new UsbSetupPacket((byte)e.bmRequestType, (byte)e.bRequest, (short)e.wValue, (short)e.wIndex, (short)e.wLength); var buffer = new byte[e.wLength]; int transferred; _realController.DoControlTransfer(ref setup, ref buffer, buffer.Length, out transferred); e.ReturnData = buffer; e.Ignore = false; } } break; } case 0x41: { switch (e.bRequest) { case 0x00: { e.Ignore = false; break; } case 0x82: //Send challenge 1 case 0x84: //Unknown { forward = true; break; } case 0x87: //Send challenge 2 { if (!stall87) forward = true; else e.Stall = true; stall87 = !stall87; break; } default: break; } if (forward) { if (_realController != null) { var setup = new UsbSetupPacket((byte)e.bmRequestType, (byte)e.bRequest, (short)e.wValue, (short)e.wIndex, (short)e.wLength); int transferred; byte[] attached = null; if (e.AttachedData != null) { attached = new byte[e.AttachedData.Length]; Array.Copy(e.AttachedData, 0, attached, 0, e.AttachedData.Length); } _realController.DoControlTransfer(ref setup, ref attached, e.AttachedData.Length, out transferred); e.Ignore = false; } } break; } default: break; } } } }