public static uint InstallDualShock3Controllers(IEnumerable <WdiDeviceInfo> usbDevices, IntPtr hWnd = default(IntPtr), bool force = false) { // install compatible bluetooth dongles var ds3Drivers = IniConfig.Instance.Ds3Driver; uint installed = 0; foreach (var usbDevice in from usbDevice in usbDevices let result = WdiWrapper.Instance.InstallLibusbKDriver(usbDevice.DeviceId, ds3Drivers.DeviceGuid, DriverDirectory, string.Format("Ds3Controller_{0}.inf", Guid.NewGuid()), hWnd, force) where result == WdiErrorCode.WDI_SUCCESS select usbDevice) { usbDevice.DeviceType = WdiUsbDeviceType.DualShock3; using (var db = new ScpDb()) { db.Engine.PutDbEntity(ScpDb.TableDevices, usbDevice.DeviceId, usbDevice); } installed++; Log.InfoFormat("Installed driver for DualShock 3 controller {0}", usbDevice); } return(installed); }
/// <summary> /// Removes a given <see cref="DualShockProfile" />. /// </summary> /// <param name="profile">The <see cref="DualShockProfile" />to remove.</param> public void RemoveProfile(DualShockProfile profile) { lock (this) { using (var db = new ScpDb()) { db.Engine.DeleteDbEntity(ScpDb.TableProfiles, profile.Id.ToString()); } } LoadProfiles(); }
/// <summary> /// Stores a new <see cref="DualShockProfile" /> or overwrites an existing one. /// </summary> /// <param name="profile">The <see cref="DualShockProfile" /> to save.</param> public void SubmitProfile(DualShockProfile profile) { lock (this) { using (var db = new ScpDb()) { db.Engine.PutDbEntity(ScpDb.TableProfiles, profile.Id.ToString(), profile); } } LoadProfiles(); }
/// <summary> /// Reads all XML files from Profiles directory. /// </summary> private void LoadProfiles() { lock (this) { using (var db = new ScpDb()) { Profiles = db.Engine.GetAllDbEntities <DualShockProfile>(ScpDb.TableProfiles) .Select(p => p.Value) .ToList() .AsReadOnly(); } } }
public static WdiErrorCode InstallBluetoothHost(WdiDeviceInfo usbDevice, IntPtr hWnd = default(IntPtr), bool force = false) { usbDevice.InfFile = string.Format("BluetoothHost_{0:X4}_{1:X4}.inf", usbDevice.VendorId, usbDevice.ProductId); usbDevice.DeviceType = WdiUsbDeviceType.BluetoothHost; var result = WdiWrapper.Instance.InstallWinUsbDriver(usbDevice.DeviceId, BthDongle.DeviceClassGuid, DriverDirectory, usbDevice.InfFile, hWnd, force); if (result != WdiErrorCode.WDI_SUCCESS) { Log.ErrorFormat("Installing Bluetooth Host ({0}) failed: {1}", usbDevice.DeviceId, result); return(result); } using (var db = new ScpDb()) { db.Engine.PutDbEntity(ScpDb.TableDevices, usbDevice.DeviceId, usbDevice); } return(result); }
public static WdiErrorCode InstallDualShock4Controller(WdiDeviceInfo usbDevice, IntPtr hWnd = default(IntPtr)) { usbDevice.InfFile = string.Format("Ds4Controller_{0:X4}_{1:X4}.inf", usbDevice.VendorId, usbDevice.ProductId); usbDevice.DeviceType = WdiUsbDeviceType.DualShock4; var result = WdiWrapper.InstallWinUsbDriver(usbDevice, UsbDs4.DeviceClassGuid, DriverDirectory, usbDevice.InfFile, hWnd); if (result != WdiErrorCode.WDI_SUCCESS) { Log.ErrorFormat("Installing DualShock 4 Controller ({0}) failed: {1}", usbDevice.DeviceId, result); return(result); } using (var db = new ScpDb()) { db.Engine.PutDbEntity(ScpDb.TableDevices, usbDevice.DeviceId, usbDevice); } return(result); }
public override bool Start() { CanStartHid = false; State = DsState.Connected; byte[] eepromContents = null, statusContents = null; using (var db = new ScpDb()) { using (var tran = db.Engine.GetTransaction()) { var row = tran.Select <byte[], byte[]>(ScpDb.TableDS3Data, DeviceAddress.GetAddressBytes()); if (row.Exists) { eepromContents = new byte[49]; statusContents = new byte[49]; var rowData = row.Value; Array.Copy(rowData, 0, eepromContents, 0, eepromContents.Length); Array.Copy(rowData, eepromContents.Length, statusContents, 0, statusContents.Length); } } } if (eepromContents != null && statusContents != null) { _cal = new DS3CalInstance(DeviceAddress, eepromContents); _cal.InitialCal(statusContents); } if (!IsFake && _cal == null) { Log.WarnFormat("EEPROM data for DS3 controller {0} not present, please connect it via USB first!", DeviceAddress.AsFriendlyName()); } m_Queued = 1; m_Blocked = true; m_Last = DateTime.Now; BluetoothDevice.HID_Command(HciHandle.Bytes, Get_SCID(L2CAP.PSM.HID_Command), _hidCommandEnable); return(base.Start()); }
public override bool Open(string devicePath) { if (base.Open(devicePath)) { State = DsState.Reserved; GetDeviceInstance(ref m_Instance); var transfered = 0; if (SendTransfer(UsbHidRequestType.DeviceToHost, UsbHidRequest.GetReport, 0x03F5, m_Buffer, ref transfered)) { HostAddress = new PhysicalAddress(new[] { m_Buffer[2], m_Buffer[3], m_Buffer[4], m_Buffer[5], m_Buffer[6], m_Buffer[7] }); } else { Log.ErrorFormat("Couldn't request Bluetooth host address for device {0}, error: {1}", devicePath, new Win32Exception(Marshal.GetLastWin32Error())); State = DsState.Disconnected; return(false); } if (SendTransfer(UsbHidRequestType.DeviceToHost, UsbHidRequest.GetReport, 0x03F2, m_Buffer, ref transfered)) { DeviceAddress = new PhysicalAddress(new[] { m_Buffer[4], m_Buffer[5], m_Buffer[6], m_Buffer[7], m_Buffer[8], m_Buffer[9] }); } else { Log.ErrorFormat("Couldn't request Bluetooth device address for device {0}, error: {1}", devicePath, new Win32Exception(Marshal.GetLastWin32Error())); State = DsState.Disconnected; return(false); } Log.InfoFormat("Successfully opened device with MAC address {0}", DeviceAddress.AsFriendlyName()); if (!IniConfig.Instance.Hci.GenuineMacAddresses.Any(m => DeviceAddress.AsFriendlyName().StartsWith(m))) { Log.WarnFormat("Fake DualShock 3 detected [{0}]", DeviceAddress.AsFriendlyName()); var bthCompany = IniConfig.Instance.BthChipManufacturers.FirstOrDefault( m => DeviceAddress.AsFriendlyName().StartsWith(m.PartialMacAddress.ToUpper())); if (bthCompany != null && bthCompany.Name.Equals("AirohaTechnologyCorp")) { Log.WarnFormat("Controller uses Bluetooth chip by Airoha Technology Corp., suppressing workaround"); IsFake = false; } else { IsFake = true; } } else { Log.Info("Genuine Sony DualShock 3 detected"); //Switch to initial read (for eeprom and version) if (SendTransfer(UsbHidRequestType.HostToDevice, UsbHidRequest.SetReport, 0x03EF, _eepromSetReport, ref transfered)) { //read EEPROM var buffer = new byte[64]; //maybe this should be 49 as well, we only use first 49 bytes max transfered = buffer.Length; if (SendTransfer(UsbHidRequestType.DeviceToHost, UsbHidRequest.GetReport, 0x03EF, buffer, ref transfered) && transfered >= 49) { _cal = new DS3CalInstance(DeviceAddress, buffer); var eepromBuffer = buffer; //read version buffer = new byte[49]; transfered = buffer.Length; if (SendTransfer(UsbHidRequestType.DeviceToHost, UsbHidRequest.GetReport, 0x0301, buffer, ref transfered) && transfered >= 49) { _cal.InitialCal(buffer); var statusBuffer = buffer; var totalBuffer = new byte[49 + 49]; Array.Copy(eepromBuffer, 0, totalBuffer, 0, Math.Min(eepromBuffer.Length, 49)); Array.Copy(statusBuffer, 0, totalBuffer, 49, Math.Min(statusBuffer.Length, 49)); using (var db = new ScpDb()) { using (var tran = db.Engine.GetTransaction()) { tran.Insert(ScpDb.TableDS3Data, DeviceAddress.GetAddressBytes(), totalBuffer); tran.Commit(); } } } } } } } return(State == DsState.Reserved); }
protected override void OnStart(string[] args) { var sw = Stopwatch.StartNew(); Log.Info("Scarlet.Crush Productions DSx Service Started"); Log.DebugFormat("++ {0} {1}", Assembly.GetExecutingAssembly().Location, Assembly.GetExecutingAssembly().GetName().Version); Log.DebugFormat("Setting working directory to {0}", GlobalConfiguration.AppDirectory); Directory.SetCurrentDirectory(GlobalConfiguration.AppDirectory); _mControlHandler = ServiceControlHandler; _mServiceHandle = ScpDevice.RegisterServiceCtrlHandlerEx(ServiceName, _mControlHandler, IntPtr.Zero); var installTask = Task.Factory.StartNew(() => { using (var db = new ScpDb()) { var bthDevices = db.Engine.GetAllDbEntities <WdiDeviceInfo>(ScpDb.TableDevices) .Where(d => d.Value.DeviceType == WdiUsbDeviceType.BluetoothHost) .Select(d => d.Value); if (GlobalConfiguration.Instance.ForceBluetoothDriverReinstallation) { DriverInstaller.InstallBluetoothDongles(bthDevices); } var ds3Devices = db.Engine.GetAllDbEntities <WdiDeviceInfo>(ScpDb.TableDevices) .Where(d => d.Value.DeviceType == WdiUsbDeviceType.DualShock3) .Select(d => d.Value); if (GlobalConfiguration.Instance.ForceDs3DriverReinstallation) { DriverInstaller.InstallDualShock3Controllers(ds3Devices); } var ds4Devices = db.Engine.GetAllDbEntities <WdiDeviceInfo>(ScpDb.TableDevices) .Where(d => d.Value.DeviceType == WdiUsbDeviceType.DualSHock4) .Select(d => d.Value); if (GlobalConfiguration.Instance.ForceDs4DriverReinstallation) { DriverInstaller.InstallDualShock4Controllers(ds4Devices); } } }); installTask.ContinueWith(task => { Log.FatalFormat("Error during driver installation: {0}", task.Exception); Stop(); }, TaskContinuationOptions.OnlyOnFaulted); Log.DebugFormat("Time spent 'till Root Hub start: {0}", sw.Elapsed); var hubStartTask = Task.Factory.StartNew(() => { rootHub.Open(); rootHub.Start(); }); hubStartTask.ContinueWith(task => { Log.FatalFormat("Couldn't start the root hub: {0}", task.Exception); Stop(); }, TaskContinuationOptions.OnlyOnFaulted); Log.DebugFormat("Time spent 'till registering notifications: {0}", sw.Elapsed); ScpDevice.RegisterNotify(_mServiceHandle, UsbDs3.DeviceClassGuid, ref _ds3Notify, false); ScpDevice.RegisterNotify(_mServiceHandle, UsbDs4.DeviceClassGuid, ref _ds4Notify, false); ScpDevice.RegisterNotify(_mServiceHandle, BthDongle.DeviceClassGuid, ref _bthNotify, false); ScpDevice.RegisterNotify(_mServiceHandle, UsbGenericGamepad.DeviceClassGuid, ref _genericNotify, false); Log.DebugFormat("Total Time spent in Service Start method: {0}", sw.Elapsed); }
public void ApplyCalToInReport(byte[] inputReport, int startOffs = 0) { int idx = startOffs + 0x29; for (int i = 0; i < 3; i++) //accelerometer vals { uint axisVal = (uint)inputReport[idx + 1] + ((uint)inputReport[idx + 0] << 8); //its big endian in the report uint val1, val2; if (i == 0) { val1 = _calValues.X.val1; val2 = _calValues.X.val2; } else if (i == 1) { val1 = _calValues.Y.val1; val2 = _calValues.Y.val2; } else if (i == 2) { val1 = _calValues.Z.val1; val2 = _calValues.Z.val2; } else { val1 = 0; val2 = 0; } if (val1 != val2) { int valDiff = (int)val1 - (int)val2; int axisDiff = (int)axisVal - (int)val1; int acc = 113 * ((axisDiff * 1024) / valDiff) / 1024 + 512; axisVal = (uint)acc; } //put it back into the input report, also as big endian inputReport[idx + 0] = (byte)((axisVal >> 8) & 0x3F); inputReport[idx + 1] = (byte)((axisVal >> 0) & 0xFF); idx += 2; } uint gyroVal = (uint)inputReport[idx + 1] + ((uint)inputReport[idx + 0] << 8); //its big endian in the report if ((_setReportFlags & 0x10) != 0 && (_setReportFlags & 0x20) == 0) { int gVal = (int)_calValues.G.val1 - (int)gyroVal; gVal += 512; //back to unsigned //clamp if (gVal < 0) { gVal = 0; } else if (gVal > 1023) { gVal = 1023; } gyroVal = (uint)gVal; } if ((_setReportFlags & 0x10) == 0 || (_setReportFlags & 0x20) != 0) { ushort outGyroVal = (ushort)gyroVal; byte outCalByte = _setReportCalByte; if (DS3CalLibrary.Instance.RuntimeCal((ushort)gyroVal, out outGyroVal, out outCalByte, _gyroStruct) == 0) { _setReportCalByte = outCalByte; if (outCalByte != _lastCalByteSaved) //the calculated value isnt the same as the last stored one { bool calDataUpdated = false; using (var db = new ScpDb()) { var addrBytes = _deviceAddr.GetAddressBytes(); using (var tran = db.Engine.GetTransaction()) { var dataRow = tran.Select <byte[], byte[]>(ScpDb.TableDS3Data, addrBytes); if (dataRow.Exists) //dont save cal data if we dont have eeprom data, so we dont resume with false info { var calBytes = StateToBytes(); if (calBytes != null) { tran.Insert(ScpDb.TableDS3Cal, _deviceAddr.GetAddressBytes(), calBytes); tran.Commit(); calDataUpdated = true; } } } } if (calDataUpdated) { Log.InfoFormat("Stored cal data for {0} new cal byte is 0x{1}", _deviceAddr.AsFriendlyName(), outCalByte.ToString("X")); } _lastCalByteSaved = outCalByte; } } } if ((_setReportFlags & 0x20) != 0 || (_setReportFlags == 0x08)) //pre-dualshock sixaxis seem to need it inverted ? { //G needs sign inversion int gVal = 1023 - (int)gyroVal; //clamp if (gVal < 0) { gVal = 0; } else if (gVal > 1023) { gVal = 1023; } gyroVal = (uint)gVal; } //put it back into the input report, also as big endian inputReport[idx + 0] = (byte)((gyroVal >> 8) & 0x3F); inputReport[idx + 1] = (byte)((gyroVal >> 0) & 0xFF); idx += 2; }
public int InitialCal(byte[] buffer) { _setReportFlags = 0; if ((buffer[8] == 0x18 && buffer[9] == 0x18 && buffer[10] == 0x18 && buffer[11] == 0x18) || (buffer[8] == 0x17 && buffer[9] == 0x17 && buffer[10] == 0x17 && buffer[11] == 0x17)) { _setReportFlags |= 0x8; } const int idxCalibBytes = 0x26; if ((buffer[idxCalibBytes + 0] != 1 || buffer[idxCalibBytes + 1] != 2) && (buffer[idxCalibBytes + 1] != 1 || buffer[idxCalibBytes + 2] != 2)) { var retVal = DS3CalLibrary.Instance.InitialCal((ushort)_calValues.G.val2, (ushort)_calValues.G.val1, out _setReportCalByte, _gyroStruct); _lastCalByteSaved = _setReportCalByte; if (retVal != 0) { return(retVal); } } else { _setReportFlags |= 0x10; } int numCalibFields = buffer[idxCalibBytes - 1]; for (int i = 0; i < numCalibFields; i++) { int bufIdx = i + idxCalibBytes; if (bufIdx >= 49) //dont go outside buffer bounds { break; } if (buffer[bufIdx] == 7) { _setReportFlags |= 0x30; var retVal = DS3CalLibrary.Instance.InitialCal((ushort)_calValues.G.val2, (ushort)_calValues.G.val1, out _setReportCalByte, _gyroStruct); _lastCalByteSaved = _setReportCalByte; if (retVal != 0) { return(retVal); } break; } } //speed up calibration by loading existing cal state if it exists byte[] calBytes = null; using (var db = new ScpDb()) { using (var tran = db.Engine.GetTransaction()) { var dataRow = tran.Select <byte[], byte[]>(ScpDb.TableDS3Cal, _deviceAddr.GetAddressBytes()); if (dataRow.Exists) { calBytes = dataRow.Value; } } } if (calBytes != null) { byte loadedCalByte = 0; if (StateFromBytes(calBytes, out loadedCalByte)) { _setReportCalByte = loadedCalByte; _lastCalByteSaved = loadedCalByte; Log.InfoFormat("Loaded cal data for {0} cal byte now 0x{1}", _deviceAddr.AsFriendlyName(), loadedCalByte.ToString("X")); } } return(0); }