Пример #1
0
        protected override void RunScan()
        {
            try
            {
                // TODO this should scan in a loop on a timer until told to stop
                var controllers = new[]
                {
                    new Controller(UserIndex.One),
                    new Controller(UserIndex.Two),
                    new Controller(UserIndex.Three),
                    new Controller(UserIndex.Four),
                };
                foreach (var c in controllers)
                {
                    if (!c.IsConnected)
                    {
                        continue;
                    }

                    BpLogger.Debug($"Found connected XInput Gamepad for Index {c.UserIndex}");
                    var deviceImpl = new XInputGamepadDevice(LogManager, c);
                    var device     = new ButtplugDevice(LogManager, new XInputProtocol(LogManager, deviceImpl), deviceImpl);
                    InvokeDeviceAdded(new DeviceAddedEventArgs(device));
                    // Do not invoke ScanningFinished here, the parent class will handle that for us.
                }
            }
            catch (DllNotFoundException e)
            {
                // TODO Should we maybe try testing for this in construction instead of during scanning?
                BpLogger.Error($"Required DirectX DLL not found: {e.Message}\nThis probably means you need to install the DirectX Runtime from June 2010: https://www.microsoft.com/en-us/download/details.aspx?id=8109");
                throw e;
            }
        }
Пример #2
0
        public override void StartScanning()
        {
            BpLogger.Info("XInputGamepadManager start scanning");
            try
            {
                var controllers = new[]
                {
                    new Controller(UserIndex.One),
                    new Controller(UserIndex.Two),
                    new Controller(UserIndex.Three),
                    new Controller(UserIndex.Four),
                };
                foreach (var c in controllers)
                {
                    if (!c.IsConnected)
                    {
                        continue;
                    }

                    BpLogger.Debug($"Found connected XInput Gamepad for Index {c.UserIndex}");
                    var device = new XInputGamepadDevice(LogManager, c);
                    InvokeDeviceAdded(new DeviceAddedEventArgs(device));
                    InvokeScanningFinished();
                }
            }
            catch (DllNotFoundException e)
            {
                // TODO Should we maybe try testing for this in construction instead of during scanning?
                BpLogger.Error($"Required DirectX DLL not found: {e.Message}\nThis probably means you need to install the DirectX Runtime from June 2010: https://www.microsoft.com/en-us/download/details.aspx?id=8109");
                InvokeScanningFinished();
            }
        }
Пример #3
0
        private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg, CancellationToken aToken)
        {
            BpLogger.Debug("Stopping Device " + Name);
            await HandleSingleMotorVibrateCmd(new SingleMotorVibrateCmd(aMsg.DeviceIndex, 0, aMsg.Id), aToken).ConfigureAwait(false);
            await HandleRotateCmd(RotateCmd.Create(0, false, 1), aToken);

            return(new Ok(aMsg.Id));
        }
Пример #4
0
 private Task <ButtplugMessage> HandleStopDeviceCmd([NotNull] ButtplugDeviceMessage aMsg)
 {
     // Right now, this is a nop. The Onyx doesn't have any sort of permanent movement state,
     // and its longest movement is like 150ms or so. The Pearl is supposed to vibrate but I've
     // never gotten that to work. So for now, we just return ok.
     BpLogger.Debug("Stopping Device " + Name);
     return(Task.FromResult <ButtplugMessage>(new Ok(aMsg.Id)));
 }
Пример #5
0
        private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg, CancellationToken aToken)
        {
            BpLogger.Debug("Stopping Device " + Name);

            await Interface.WriteValueAsync(new byte[] { (byte)_deviceType, (byte)_commandType, 0 },
                                            aToken).ConfigureAwait(false);

            return(new Ok(aMsg.Id));
        }
Пример #6
0
        private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg, CancellationToken aToken)
        {
            BpLogger.Debug("Stopping Device " + Name);
            // Stop commands start with 0x01
            var cmd = GetCommandArray(new[] { (byte)0x01, (byte)RealTouchComponents.A });
            await Interface.WriteValueAsync(cmd, aToken);

            return(new Ok(aMsg.Id));
            //return await HandleRotateCmd(new RotateCmd(aMsg.DeviceIndex, 0, _clockwise, aMsg.Id), aToken).ConfigureAwait(false);
        }
Пример #7
0
 private Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg)
 {
     // This probably shouldn't be a nop, but right now we don't have a good way to know
     // if the launch is moving or not, and surprisingly enough, setting speed to 0 does not
     // actually stop movement. It just makes it move really slow.
     // However, since each move it makes is finite (unlike setting vibration on some devices),
     // so we can assume it will be a short move, similar to what we do for the Kiiroo toys.
     BpLogger.Debug("Stopping Device " + Name);
     return(Task.FromResult <ButtplugMessage>(new Ok(aMsg.Id)));
 }
Пример #8
0
        private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg, CancellationToken aToken)
        {
            BpLogger.Debug("Stopping Device " + Name);

            if (_deviceType == LovenseDeviceType.Nora)
            {
                await HandleRotateCmd(RotateCmd.Create(aMsg.DeviceIndex, aMsg.Id, 0, _clockwise, 1), aToken).ConfigureAwait(false);
            }

            return(await HandleSingleMotorVibrateCmd(new SingleMotorVibrateCmd(aMsg.DeviceIndex, 0, aMsg.Id), aToken).ConfigureAwait(false));
        }
Пример #9
0
        public override void StartScanning()
        {
            _scanning = true;
            var hidDevices = new HidEnumerator();

            foreach (var hid in hidDevices.Enumerate())
            {
                try
                {
                    hid.ReadProduct(out var product);
                    hid.ReadManufacturer(out var vendor);
                    var prod = Encoding.Unicode.GetString(product);
                    var vend = Encoding.Unicode.GetString(vendor);
                    prod = prod.Substring(0, prod.IndexOf('\0'));
                    vend = vend.Substring(0, vend.IndexOf('\0'));

                    BpLogger.Trace("Found HID device (" +
                                   hid.Attributes.VendorHexId + ":" + hid.Attributes.ProductHexId +
                                   "): " + vend + " - " + prod);

                    var factories = _deviceFactories.Where(x =>
                                                           x.MayBeDevice(hid.Attributes.VendorId, hid.Attributes.ProductId));
                    var buttplugHidDeviceFactories = factories as HidDeviceFactory[] ?? factories.ToArray();
                    if (buttplugHidDeviceFactories.Length != 1)
                    {
                        if (buttplugHidDeviceFactories.Any())
                        {
                            BpLogger.Warn($"Found multiple HID factories for {hid.Attributes.VendorHexId}:{hid.Attributes.ProductHexId}");
                            buttplugHidDeviceFactories.ToList().ForEach(x => BpLogger.Warn(x.GetType().Name));
                        }
                        else
                        {
                            // BpLogger.Trace("No BLE factories found for device.");
                        }

                        continue;
                    }

                    var factory = buttplugHidDeviceFactories.First();
                    BpLogger.Debug($"Found HID factory: {factory.GetType().Name}");

                    var d = factory.CreateDevice(hid);
                    InvokeDeviceAdded(new DeviceAddedEventArgs(d));
                }
                catch (Exception e)
                {
                    // TODO Figure out what exceptions can actually be thrown here.
                    BpLogger.Error(e.Message);
                }
            }

            _scanning = false;
            InvokeScanningFinished();
        }
Пример #10
0
 private async Task <ButtplugMessage> HandleStopDeviceCmd([NotNull] ButtplugDeviceMessage aMsg)
 {
     BpLogger.Debug("Stopping Device " + Name);
     return(await HandleVibrateCmd(new VibrateCmd(aMsg.DeviceIndex,
                                                  new List <VibrateCmd.VibrateSubcommand>()
     {
         new VibrateCmd.VibrateSubcommand(0, 0),
         new VibrateCmd.VibrateSubcommand(1, 0),
     },
                                                  aMsg.Id)));
 }
        private async Task <ButtplugMessage> HandleStopDeviceCmd([NotNull] ButtplugDeviceMessage aMsg, CancellationToken aToken)
        {
            BpLogger.Debug($"Stopping Device {Name}");

            if (_devInfo.VibeCount == 0)
            {
                return(new Ok(aMsg.Id));
            }

            return(await HandleVibrateCmd(VibrateCmd.Create(aMsg.DeviceIndex, aMsg.Id, 0, _devInfo.VibeCount), aToken).ConfigureAwait(false));
        }
Пример #12
0
        private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg)
        {
            BpLogger.Debug("Stopping Device " + Name);

            if (_deviceType == LovenseDeviceType.Nora)
            {
                await HandleRotateCmd(RotateCmd.Create(aMsg.DeviceIndex, aMsg.Id, 0, _clockwise, 1));
            }

            return(await HandleSingleMotorVibrateCmd(new SingleMotorVibrateCmd(aMsg.DeviceIndex, 0, aMsg.Id)));
        }
Пример #13
0
        private async Task <ButtplugMessage> HandleStopDeviceCmd([NotNull] ButtplugDeviceMessage aMsg)
        {
            BpLogger.Debug("Stopping Device " + Name);
            var vCmds = new List <VibrateCmd.VibrateSubcommand>();

            for (uint i = 0; i < _devInfo.VibeCount; i++)
            {
                vCmds.Add(new VibrateCmd.VibrateSubcommand(i, 0));
            }

            return(await HandleVibrateCmd(new VibrateCmd(aMsg.DeviceIndex, vCmds, aMsg.Id)));
        }
Пример #14
0
        private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg, CancellationToken aToken)
        {
            BpLogger.Debug("Stopping Device " + Name);
            if (_speed == 0)
            {
                return(new Ok(aMsg.Id));
            }

            return(await Interface.WriteValueAsync(aMsg.Id,
                                                   (uint)VorzeSABluetoothInfo.Chrs.Tx,
                                                   new byte[] { (byte)_deviceType, (byte)_commandType, 0 }, false, aToken).ConfigureAwait(false));
        }
Пример #15
0
        private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg)
        {
            BpLogger.Debug("Stopping Device " + Name);

            if (FriendlyNames[Interface.Name] == "Nora")
            {
                await Interface.WriteValue(aMsg.Id,
                                           Info.Characteristics[(uint)LovenseRev1BluetoothInfo.Chrs.Tx],
                                           Encoding.ASCII.GetBytes($"Rotate:0;"));
            }

            return(await HandleSingleMotorVibrateCmd(new SingleMotorVibrateCmd(aMsg.DeviceIndex, 0, aMsg.Id)));
        }
Пример #16
0
        public UWPBluetoothManager(IButtplugLogManager aLogManager)
            : base(aLogManager)
        {
            BpLogger.Info("Loading UWP Bluetooth Manager");
            _currentlyConnecting = new List <ulong>();

            // Introspect the ButtplugDevices namespace for all Factory classes, then create
            // instances of all of them.
            _deviceFactories = new List <UWPBluetoothDeviceFactory>();
            BuiltinDevices.ForEach(aDeviceFactory =>
            {
                BpLogger.Debug($"Loading Bluetooth Device Factory: {aDeviceFactory.GetType().Name}");
                _deviceFactories.Add(new UWPBluetoothDeviceFactory(aLogManager, aDeviceFactory));
            });

            _bleWatcher = new BluetoothLEAdvertisementWatcher {
                ScanningMode = BluetoothLEScanningMode.Active
            };

            // We can't filter device advertisements because you can only add one LocalName filter at
            // a time, meaning we would have to set up multiple watchers for multiple devices. We'll
            // handle our own filtering via the factory classes whenever we receive a device.
            _bleWatcher.Received += OnAdvertisementReceived;
            _bleWatcher.Stopped  += OnWatcherStopped;
            var adapterTask = Task.Run(() => BluetoothAdapter.GetDefaultAsync().AsTask());

            adapterTask.Wait();
            var adapter = adapterTask.Result;

            if (adapter == null)
            {
                BpLogger.Warn("No bluetooth adapter available for UWP Bluetooth Manager Connection");
                return;
            }

            if (!adapter.IsLowEnergySupported)
            {
                BpLogger.Warn("Bluetooth adapter available but does not support Bluetooth Low Energy.");
                return;
            }

            BpLogger.Debug("UWP Manager found working Bluetooth LE Adapter");

            // Only run radio information lookup if we're actually logging at the level it will show.
            if (aLogManager.Level >= ButtplugLogLevel.Debug)
            {
                // Do radio lookup in a background task, as the search query is very slow.
                // TODO Should probably try and cancel this if it's still running on object destruction, but the Get() call is uninterruptable?
                _radioTask = Task.Run(() => LogBluetoothRadioInfo());
            }
        }
Пример #17
0
        private async Task <ButtplugMessage> HandleStopDeviceCmd([NotNull] ButtplugDeviceMessage aMsg, CancellationToken aToken)
        {
            // Right now, this is a nop. The Onyx doesn't have any sort of permanent movement state,
            // and its longest movement is like 150ms or so. The Pearl is supposed to vibrate but I've
            // never gotten that to work. So for now, we just return ok.
            BpLogger.Debug("Stopping Device " + Name);

            if (Interface.Name == "PEARL" && _deviceSpeed > 0)
            {
                return(await HandleKiirooRawCmd(new KiirooCmd(aMsg.DeviceIndex, 0, aMsg.Id), aToken).ConfigureAwait(false));
            }

            return(new Ok(aMsg.Id));
        }
Пример #18
0
        public XamarinBluetoothManager(IButtplugLogManager aLogManager)
            : base(aLogManager)
        {
            BpLogger.Info("Loading UWP Bluetooth Manager");

            _adapter = CrossBluetoothLE.Current.Adapter;
            if (_adapter == null)
            {
                BpLogger.Warn("No bluetooth adapter available for UWP Bluetooth Manager Connection");
                return;
            }
            _adapter.DeviceAdvertised += _adapter_DeviceAdvertised;

            BpLogger.Debug("UWP Manager found working Bluetooth LE Adapter");
        }
Пример #19
0
        private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg)
        {
            BpLogger.Debug("Stopping Device " + Name);

            if (FriendlyNames[Interface.Name] == "Nora")
            {
                await HandleRotateCmd(new RotateCmd(aMsg.DeviceIndex,
                                                    new List <RotateCmd.RotateSubcommand> {
                    new RotateCmd.RotateSubcommand(0, 0, _clockwise)
                },
                                                    aMsg.Id));
            }

            return(await HandleSingleMotorVibrateCmd(new SingleMotorVibrateCmd(aMsg.DeviceIndex, 0, aMsg.Id)));
        }
Пример #20
0
        private void LogBluetoothRadioInfo()
        {
            // Log all bluetooth radios on the system, in case we need the information from the user later.
            var objSearcher = new ManagementObjectSearcher("Select * from Win32_PnPSignedDriver where DeviceName like '%Bluetooth%'");

            var objCollection = objSearcher.Get();

            BpLogger.Debug("Bluetooth Radio Information:");
            foreach (var obj in objCollection)
            {
                var info =
                    $"Device='{obj["DeviceName"]}',Manufacturer='{obj["Manufacturer"]}',DriverVersion='{obj["DriverVersion"]}' ";
                BpLogger.Debug(info);
            }
        }
Пример #21
0
        private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg, CancellationToken aToken)
        {
            BpLogger.Debug("Stopping Device " + Name);

            if (_deviceType == DeviceType.Piston)
            {
                // Forced transition to the front
                await Interface.WriteValueAsync(new byte[] { (byte)_deviceType, 0, 60 }, aToken).ConfigureAwait(false);
            }
            else
            {
                await Interface.WriteValueAsync(new byte[] { (byte)_deviceType, (byte)_commandType, 0 }, aToken).ConfigureAwait(false);
            }
            isEnable = false;

            return(new Ok(aMsg.Id));
        }
        public UWPBluetoothManager(IButtplugLogManager aLogManager)
            : base(aLogManager)
        {
            BpLogger.Info("Loading UWP Bluetooth Manager");
            _currentlyConnecting = new List <ulong>();

            // Introspect the ButtplugDevices namespace for all Factory classes, then create instances of all of them.
            _deviceFactories = new List <UWPBluetoothDeviceFactory>();
            BuiltinDevices.ForEach(aDeviceFactory =>
            {
                BpLogger.Debug($"Loading Bluetooth Device Factory: {aDeviceFactory.GetType().Name}");
                _deviceFactories.Add(new UWPBluetoothDeviceFactory(aLogManager, aDeviceFactory));
            });

            _bleWatcher = new BluetoothLEAdvertisementWatcher {
                ScanningMode = BluetoothLEScanningMode.Active
            };

            // We can't filter device advertisements because you can only add one LocalName filter at a time, meaning we
            // would have to set up multiple watchers for multiple devices. We'll handle our own filtering via the factory
            // classes whenever we receive a device.
            _bleWatcher.Received += OnAdvertisementReceived;
            _bleWatcher.Stopped  += OnWatcherStopped;
            var adapterTask = Task.Run(() => BluetoothAdapter.GetDefaultAsync().AsTask());

            adapterTask.Wait();
            var adapter = adapterTask.Result;

            if (adapter == null)
            {
                BpLogger.Warn("No bluetooth adapter available for UWP Bluetooth Manager Connection");
                return;
            }

            if (!adapter.IsLowEnergySupported)
            {
                BpLogger.Warn("Bluetooth adapter available but does not support Bluetooth Low Energy.");
                return;
            }

            BpLogger.Debug("UWP Manager found working Bluetooth LE Adapter");
        }
Пример #23
0
        public UWPBluetoothManager(IButtplugLogManager aLogManager)
            : base(aLogManager)
        {
            BpLogger.Info("Loading UWP Bluetooth Manager");

            // We can't filter device advertisements because you can only add one LocalName filter at
            // a time, meaning we would have to set up multiple watchers for multiple devices. We'll
            // handle our own filtering via the factory classes whenever we receive a device.
            _bleWatcher.Received += OnAdvertisementReceived;
            _bleWatcher.Stopped  += OnWatcherStopped;
            var adapterTask = Task.Run(() => BluetoothAdapter.GetDefaultAsync().AsTask());

            adapterTask.Wait();
            var adapter = adapterTask.Result;

            if (adapter == null)
            {
                BpLogger.Warn("No bluetooth adapter available for UWP Bluetooth Manager Connection");
                return;
            }

            if (!adapter.IsLowEnergySupported)
            {
                BpLogger.Warn("Bluetooth adapter available but does not support Bluetooth Low Energy.");
                return;
            }

            BpLogger.Debug("UWP Manager found working Bluetooth LE Adapter");

            // Only run radio information lookup if we're actually logging at the level it will show.
            if (aLogManager.MaxLevel >= ButtplugLogLevel.Debug)
            {
                // Do radio lookup in a background task, as the search query is very slow. TODO
                // Should probably try and cancel this if it's still running on object destruction,
                // but the Get() call is uninterruptable?
                _radioTask = Task.Run(() => LogBluetoothRadioInfo());
            }
        }
Пример #24
0
        public UWPBluetoothManager(IButtplugLogManager aLogManager)
            : base(aLogManager)
        {
            BpLogger.Debug("Loading UWP Bluetooth Manager");
            _currentlyConnecting = new List <ulong>();

            // Introspect the ButtplugDevices namespace for all Factory classes, then create instances of all of them.
            _deviceFactories = new List <UWPBluetoothDeviceFactory>();
            BuiltinDevices.ForEach(aDeviceFactory =>
            {
                BpLogger.Debug($"Loading Bluetooth Device Factory: {aDeviceFactory.GetType().Name}");
                _deviceFactories.Add(new UWPBluetoothDeviceFactory(aLogManager, aDeviceFactory));
            });

            _bleWatcher = new BluetoothLEAdvertisementWatcher {
                ScanningMode = BluetoothLEScanningMode.Active
            };

            // We can't filter device advertisements because you can only add one LocalName filter at a time, meaning we
            // would have to set up multiple watchers for multiple devices. We'll handle our own filtering via the factory
            // classes whenever we receive a device.
            _bleWatcher.Received += OnAdvertisementReceived;
            _bleWatcher.Stopped  += OnWatcherStopped;
        }
        public override void StartScanning()
        {
            BpLogger.Info("XInputGamepadManager start scanning");
            var controllers = new[]
            {
                new Controller(UserIndex.One),
                new Controller(UserIndex.Two),
                new Controller(UserIndex.Three),
                new Controller(UserIndex.Four),
            };

            foreach (var c in controllers)
            {
                if (!c.IsConnected)
                {
                    continue;
                }

                BpLogger.Debug($"Found connected XInput Gamepad for Index {c.UserIndex}");
                var device = new XInputGamepadDevice(LogManager, c);
                InvokeDeviceAdded(new DeviceAddedEventArgs(device));
                InvokeScanningFinished();
            }
        }
Пример #26
0
        public override async Task <ButtplugMessage> Initialize()
        {
            BpLogger.Trace($"Initializing {Name}");

            // Subscribing to read updates
            await Interface.SubscribeToUpdates();

            Interface.BluetoothNotifyReceived += NotifyReceived;

            // Retreiving device type info for identification.
            var writeMsg = await Interface.WriteValue(ButtplugConsts.SystemMsgId, Encoding.ASCII.GetBytes($"DeviceType;"), true);

            if (writeMsg is Error)
            {
                BpLogger.Error($"Error requesting device info from Lovense {Name}");
                return(writeMsg);
            }

            var(msg, result) = await Interface.ReadValue(ButtplugConsts.SystemMsgId);

            string deviceInfoString = string.Empty;

            if (msg is Ok)
            {
                deviceInfoString = Encoding.ASCII.GetString(result);
            }
            else
            {
                // The device info notification isn't available immediately.
                // TODO Turn this into a task semaphore with cancellation/timeout, let system handle check timing.
                int timeout = 500;
                while (timeout > 0)
                {
                    if (_lastNotifyReceived != string.Empty)
                    {
                        deviceInfoString = _lastNotifyReceived;
                        break;
                    }

                    timeout -= 5;
                    await Task.Delay(5);
                }
            }

            if (deviceInfoString != string.Empty)
            {
                BpLogger.Debug($"Received device query return for {Interface.Name}");
                // Expected Format X:YY:ZZZZZZZZZZZZ X is device type leter YY is firmware version Z
                // is bluetooth address
                var deviceInfo = deviceInfoString.Split(':');

                // If we don't get back the amount of tokens we expect, identify as unknown, log, bail.
                if (deviceInfo.Length != 3 || deviceInfo[0].Length != 1)
                {
                    return(BpLogger.LogErrorMsg(ButtplugConsts.SystemMsgId, Error.ErrorClass.ERROR_DEVICE,
                                                $"Unknown Lovense DeviceType of {deviceInfoString} found. Please report to B******g Developers by filing an issue at https://github.com/metafetish/b******g/"));
                }

                var deviceTypeLetter = deviceInfo[0][0];
                if (deviceTypeLetter == 'C')
                {
                    deviceTypeLetter = 'A';
                }
                int.TryParse(deviceInfo[1], out var deviceVersion);
                BpLogger.Trace($"Lovense DeviceType Return: {deviceTypeLetter}");
                if (!Enum.IsDefined(typeof(LovenseDeviceType), (uint)deviceTypeLetter))
                {
                    // If we don't know what device this is, just assume it has a single vibrator,
                    // call it unknown, log something.
                    return(BpLogger.LogErrorMsg(ButtplugConsts.SystemMsgId, Error.ErrorClass.ERROR_DEVICE,
                                                $"Unknown Lovense Device of Type {deviceTypeLetter} found. Please report to B******g Developers by filing an issue at https://github.com/metafetish/b******g/"));
                }

                Name = $"Lovense {Enum.GetName(typeof(LovenseDeviceType), (uint)deviceTypeLetter)} v{deviceVersion}";

                _deviceType = (LovenseDeviceType)deviceTypeLetter;
            }
            else
            {
                // If we for some reason don't get a device info query back, use fallback method.
                //
                // TODO Remove this branch at some point? Not sure we'll need it now since device queries seem stable.
                BpLogger.Warn($"Error retreiving device info from Lovense {Name}, using fallback method");

                // Some of the older devices seem to have issues with info lookups? Not sure why, so
                // for now use fallback method.
                switch (Interface.Name.Substring(0, 6))
                {
                case "LVS-B0":
                    _deviceType = LovenseDeviceType.Max;
                    break;

                case "LVS-A0":
                case "LVS-C0":
                    _deviceType = LovenseDeviceType.Nora;
                    break;

                case "LVS-L0":
                    _deviceType = LovenseDeviceType.Ambi;
                    break;

                default:
                    _deviceType = LovenseDeviceType.Unknown;
                    break;
                }

                Name = $"Lovense {Enum.GetName(typeof(LovenseDeviceType), (uint)_deviceType)} v{Interface.Name.Substring(Interface.Name.Length - 2)}";
            }

            if (_deviceType == LovenseDeviceType.Unknown)
            {
                BpLogger.Error("Lovense device type unknown, treating as single vibrator device. Please contact developers for more info.");
            }

            switch (_deviceType)
            {
            case LovenseDeviceType.Edge:

                // Edge has 2 vibrators
                _vibratorCount++;
                MsgFuncs.Remove(typeof(VibrateCmd));
                MsgFuncs.Add(typeof(VibrateCmd), new ButtplugDeviceWrapper(HandleVibrateCmd, new MessageAttributes()
                {
                    FeatureCount = _vibratorCount
                }));
                break;

            case LovenseDeviceType.Nora:

                // Nora has a rotator
                MsgFuncs.Add(typeof(RotateCmd), new ButtplugDeviceWrapper(HandleRotateCmd, new MessageAttributes()
                {
                    FeatureCount = 1
                }));
                break;
            }

            return(new Ok(ButtplugConsts.SystemMsgId));
        }
Пример #27
0
 private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg)
 {
     BpLogger.Debug("Stopping Device " + Name);
     return(await HandleVorzeA10CycloneCmd(new VorzeA10CycloneCmd(aMsg.DeviceIndex, 0, _clockwise, aMsg.Id)));
 }
        private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher aObj,
                                                   BluetoothLEAdvertisementReceivedEventArgs aEvent)
        {
            if (aEvent?.Advertisement == null)
            {
                BpLogger.Debug("Null BLE advertisement recieved: skipping");
                return;
            }

            var advertName  = aEvent.Advertisement.LocalName ?? string.Empty;
            var advertGUIDs = new List <Guid>();

            advertGUIDs.AddRange(aEvent.Advertisement.ServiceUuids ?? new Guid[] { });
            var btAddr = aEvent.BluetoothAddress;

            // BpLogger.Trace($"Got BLE Advertisement for device: {aEvent.Advertisement.LocalName} / {aEvent.BluetoothAddress}");
            if (_currentlyConnecting.Contains(btAddr))
            {
                // BpLogger.Trace($"Ignoring advertisement for already connecting device: {aEvent.Advertisement.LocalName} / {aEvent.BluetoothAddress}");
                return;
            }

            BpLogger.Trace("BLE device found: " + advertName);
            var factories = from x in _deviceFactories
                            where x.MayBeDevice(advertName, advertGUIDs)
                            select x;

            // We should always have either 0 or 1 factories.
            var buttplugBluetoothDeviceFactories = factories as UWPBluetoothDeviceFactory[] ?? factories.ToArray();

            if (buttplugBluetoothDeviceFactories.Length != 1)
            {
                if (buttplugBluetoothDeviceFactories.Any())
                {
                    BpLogger.Warn($"Found multiple BLE factories for {advertName} {btAddr}:");
                    buttplugBluetoothDeviceFactories.ToList().ForEach(x => BpLogger.Warn(x.GetType().Name));
                }
                else
                {
                    // BpLogger.Trace("No BLE factories found for device.");
                }

                return;
            }

            _currentlyConnecting.Add(btAddr);
            var factory = buttplugBluetoothDeviceFactories.First();

            BpLogger.Debug($"Found BLE factory: {factory.GetType().Name}");

            // If we actually have a factory for this device, go ahead and create the device
            var fromBluetoothAddressAsync = BluetoothLEDevice.FromBluetoothAddressAsync(btAddr);

            if (fromBluetoothAddressAsync != null)
            {
                var dev = await fromBluetoothAddressAsync;

                // If a device is turned on after scanning has started, windows seems to lose the
                // device handle the first couple of times it tries to deal with the advertisement.
                // Just log the error and hope it reconnects on a later retry.
                try
                {
                    var d = await factory.CreateDeviceAsync(dev);

                    InvokeDeviceAdded(new DeviceAddedEventArgs(d));
                }
                catch (Exception ex)
                {
                    BpLogger.Error(
                        $"Cannot connect to device {advertName} {btAddr}: {ex.Message}");
                    _currentlyConnecting.Remove(btAddr);
                    return;
                }
            }

            _currentlyConnecting.Remove(btAddr);
        }
        protected async Task InitializeDevice(BluetoothLEProtocolConfiguration aConfig)
        {
            foreach (var serviceInfo in aConfig.Services)
            {
                // If we don't have any characteristic configuration, assume we're using
                // characteristic detection.
                if (serviceInfo.Value == null || serviceInfo.Value.Count == 0)
                {
                    await AddDefaultCharacteristics(serviceInfo.Key).ConfigureAwait(false);
                }
                else
                {
                    var serviceGuid = serviceInfo.Key;


                    IService service;

                    try
                    {
                        service = await GetService(serviceGuid).ConfigureAwait(false);
                    }
                    catch (ButtplugDeviceException)
                    {
                        // In this case, we may have a whole bunch of services that aren't valid for
                        // a device and only one that is. We can ignore the exception here, and throw
                        // later if we don't get anything from any service in the list.
                        continue;
                    }

                    var chrResult = await service.GetCharacteristicsAsync();

                    if (service.Device.State != DeviceState.Connected)
                    {
                        throw new ButtplugDeviceException(BpLogger,
                                                          $"Cannot connect to characteristics for {serviceGuid} of {_bleDevice.Name}: {service.Device.State}");
                    }

                    foreach (var chr in chrResult)
                    {
                        foreach (var indexChr in serviceInfo.Value)
                        {
                            if (Guid.Parse(chr.Uuid) != indexChr.Value)
                            {
                                continue;
                            }

                            if (_indexedChars.ContainsKey(indexChr.Key))
                            {
                                // We've somehow doubled up endpoint names. Freak out.
                                throw new ButtplugDeviceException(BpLogger, $"Found repeated endpoint name {indexChr.Key} on {Name}");
                            }

                            BpLogger.Debug($"Found characteristic {indexChr.Key} {chr.Uuid} ({_bleDevice.Name})");
                            _indexedChars.Add(indexChr.Key, chr);
                        }
                    }
                }
            }

            // If we've exited characteristic finding without any characteristics to use, something
            // is wrong with our configuration and we won't be able to talk to the device. Don't
            // continue connection.
            if (!_indexedChars.Any())
            {
                throw new ButtplugDeviceException(BpLogger, $"No characteristics to connect to for device {Name}");
            }
        }
Пример #30
0
 private async Task <ButtplugMessage> HandleStopDeviceCmd(ButtplugDeviceMessage aMsg)
 {
     BpLogger.Debug("Stopping Device " + Name);
     return(await HandleSingleMotorVibrateCmd(new SingleMotorVibrateCmd(aMsg.DeviceIndex, 0, aMsg.Id)));
 }