Beispiel #1
0
        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);
        }
Beispiel #2
0
        /// <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();
        }
Beispiel #3
0
        /// <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();
         }
     }
 }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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());
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
        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;
        }
Beispiel #11
0
        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);
        }