예제 #1
0
        /// <summary>
        /// Creates a DeviceListEntry for a device and adds it to the list of devices
        /// </summary>
        /// <param name="deviceInformation">DeviceInformation on the device to be added to the list</param>
        /// <param name="deviceSelector">The AQS used to find this device</param>
        private async void AddDeviceToList(DeviceInformation deviceInformation, String deviceSelector)
        {
            // search the device list for a device with a matching interface ID
            var usbMatch = FindDevice(deviceInformation.Id);

            OnLogMessageAvailable(NanoDevicesEventSource.Log.CandidateDevice(deviceInformation.Id));

            // Add the device if it's new
            if (usbMatch == null)
            {
                UsbDevices.Add(new UsbDeviceInformation(deviceInformation, deviceSelector));

                // search the NanoFramework device list for a device with a matching interface ID
                var nanoFrameworkDeviceMatch = FindNanoFrameworkDevice(deviceInformation.Id);

                if (nanoFrameworkDeviceMatch == null)
                {
                    //     Create a new element for this device interface, and queue up the query of its
                    //     device information

                    var newNanoFrameworkDevice = new NanoDevice <NanoUsbDevice>();
                    //newMFDevice.DeviceInformation = new UsbDeviceInformation(deviceInformation, deviceSelector);
                    newNanoFrameworkDevice.Device.DeviceInformation = new UsbDeviceInformation(deviceInformation, deviceSelector);
                    newNanoFrameworkDevice.Parent    = this;
                    newNanoFrameworkDevice.Transport = TransportType.Usb;

                    // Add the new element to the end of the list of devices
                    NanoFrameworkDevices.Add(newNanoFrameworkDevice as NanoDeviceBase);

                    // now fill in the description
                    // try opening the device to read the descriptor
                    if (await ConnectUsbDeviceAsync(newNanoFrameworkDevice.Device.DeviceInformation))
                    {
                        // the device description format is kept to maintain backwards compatibility
                        newNanoFrameworkDevice.Description = EventHandlerForUsbDevice.Current.DeviceInformation.Name + "_" + await GetDeviceDescriptor(5);

                        NanoDevicesEventSource.Log.ValidDevice(newNanoFrameworkDevice.Description + " @ " + newNanoFrameworkDevice.Device.DeviceInformation.DeviceSelector);

                        // done here, close device
                        EventHandlerForUsbDevice.Current.CloseDevice();
                    }
                    else
                    {
                        // couldn't open device, better remove it from the lists
                        NanoFrameworkDevices.Remove(newNanoFrameworkDevice as NanoDeviceBase);
                        UsbDevices.Remove(newNanoFrameworkDevice.Device.DeviceInformation);

                        NanoDevicesEventSource.Log.QuitDevice(deviceInformation.Id);

                        // can't do anything with this one, better dispose it
                        newNanoFrameworkDevice.Dispose();
                    }
                }
                else
                {
                    // this NanoFramework device is already on the list
                }
            }
        }
예제 #2
0
        private void OnPortNanoFrameworkDevicesOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
            case NotifyCollectionChangedAction.Reset:
                NanoFrameworkDevices.Clear();
                break;

            case NotifyCollectionChangedAction.Add:
                e.NewItems.Cast <NanoDeviceBase>().ToList().ForEach(d => NanoFrameworkDevices.Add(d));
                break;

            case NotifyCollectionChangedAction.Remove:
                e.OldItems.Cast <NanoDeviceBase>().ToList().ForEach(d => NanoFrameworkDevices.Remove(d));
                break;
            }
        }
예제 #3
0
        private void OnDeviceEnumerationComplete(DeviceWatcher sender, object args)
        {
            // add another device watcher completed
            _deviceWatchersCompletedCount++;

            if (_deviceWatchersCompletedCount == _mapDeviceWatchersToDeviceSelector.Count)
            {
                Task.Factory.StartNew(async() =>
                {
                    // prepare a list of devices that are to be removed if they are deemed as not valid nanoFramework devices
                    var devicesToRemove = new List <NanoDeviceBase>();

                    foreach (NanoDeviceBase device in _tentativeNanoFrameworkDevices)
                    {
                        var nFDeviceIsValid = await CheckValidNanoFrameworkSerialDeviceAsync(((NanoDevice <NanoSerialDevice>)device).Device.DeviceInformation).ConfigureAwait(true);

                        if (nFDeviceIsValid)
                        {
                            OnLogMessageAvailable(NanoDevicesEventSource.Log.ValidDevice($"{device.Description} {(((NanoDevice<NanoSerialDevice>)device).Device.DeviceInformation.DeviceInformation.Id)}"));

                            NanoFrameworkDevices.Add(device);
                        }
                        else
                        {
                            OnLogMessageAvailable(NanoDevicesEventSource.Log.QuitDevice(((NanoDevice <NanoSerialDevice>)device).Device.DeviceInformation.DeviceInformation.Id));
                        }
                    }

                    // all watchers have completed enumeration
                    IsDevicesEnumerationComplete = true;

                    // clean list of tentative nanoFramework Devices
                    _tentativeNanoFrameworkDevices.Clear();

                    OnLogMessageAvailable(NanoDevicesEventSource.Log.SerialDeviceEnumerationCompleted(NanoFrameworkDevices.Count));

                    // fire event that Serial enumeration is complete
                    OnDeviceEnumerationCompleted();
                }).FireAndForget();
            }
        }
예제 #4
0
        /// <summary>
        /// Creates a DeviceListEntry for a device and adds it to the list of devices
        /// </summary>
        /// <param name="deviceInformation">DeviceInformation on the device to be added to the list</param>
        /// <param name="deviceSelector">The AQS used to find this device</param>
        private async void AddDeviceToList(DeviceInformation deviceInformation, String deviceSelector)
        {
            // search the device list for a device with a matching interface ID
            var usbMatch = FindDevice(deviceInformation.Id);

            Debug.WriteLine("New USB device: " + deviceInformation.Id);

            // Add the device if it's new
            if (usbMatch == null)
            {
                UsbDevices.Add(new UsbDeviceInformation(deviceInformation, deviceSelector));

                // search the NanoFramework device list for a device with a matching interface ID
                var nanoFrameworkDeviceMatch = FindNanoFrameworkDevice(deviceInformation.Id);

                if (nanoFrameworkDeviceMatch == null)
                {
                    //     Create a new element for this device interface, and queue up the query of its
                    //     device information

                    var newNanoFrameworkDevice = new NanoDevice <NanoUsbDevice>();
                    //newMFDevice.DeviceInformation = new UsbDeviceInformation(deviceInformation, deviceSelector);
                    newNanoFrameworkDevice.Device.DeviceInformation = new UsbDeviceInformation(deviceInformation, deviceSelector);
                    newNanoFrameworkDevice.Parent      = this;
                    newNanoFrameworkDevice.DebugEngine = new Engine(this, newNanoFrameworkDevice);
                    newNanoFrameworkDevice.Transport   = TransportType.Usb;

                    // Add the new element to the end of the list of devices
                    NanoFrameworkDevices.Add(newNanoFrameworkDevice as NanoDeviceBase);

                    // now fill in the description
                    // try opening the device to read the descriptor
                    if (await ConnectUsbDeviceAsync(newNanoFrameworkDevice.Device.DeviceInformation).ConfigureAwait(false))
                    {
                        // the device description format is kept to maintain backwards compatibility
                        newNanoFrameworkDevice.Description = EventHandlerForUsbDevice.Current.DeviceInformation.Name + "_" + await GetDeviceDescriptor(5).ConfigureAwait(false);

                        Debug.WriteLine("Add new nanoFramework device to list: " + newNanoFrameworkDevice.Description + " @ " + newNanoFrameworkDevice.Device.DeviceInformation.DeviceSelector);

                        // done here, close device
                        EventHandlerForUsbDevice.Current.CloseDevice();
                    }
                    else
                    {
                        // couldn't open device, better remove it from the lists
                        NanoFrameworkDevices.Remove(newNanoFrameworkDevice as NanoDeviceBase);
                        UsbDevices.Remove(newNanoFrameworkDevice.Device.DeviceInformation);
                    }
                }
                else
                {
                    // this NanoFramework device is already on the list
                    // stop the dispose countdown!
                    nanoFrameworkDeviceMatch.StopCountdownForDispose();

                    // set port parent
                    //(mfDeviceMatch as MFDevice<MFUsbDevice>).Device.Parent = this;
                    //// instantiate a debug engine
                    //(mfDeviceMatch as MFDevice<MFUsbDevice>).Device.DebugEngine = new Engine(this, (mfDeviceMatch as MFDevice<MFUsbDevice>));
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Creates a DeviceListEntry for a device and adds it to the list of devices
        /// </summary>
        /// <param name="deviceInformation">DeviceInformation on the device to be added to the list</param>
        /// <param name="deviceSelector">The AQS used to find this device</param>
        private async void AddDeviceToList(DeviceInformation deviceInformation, String deviceSelector)
        {
            // search the device list for a device with a matching interface ID
            var serialMatch = FindDevice(deviceInformation.Id);

            // Add the device if it's new
            if (serialMatch == null)
            {
                SerialDevices.Add(new SerialDeviceInformation(deviceInformation, deviceSelector));

                // search the NanoFramework device list for a device with a matching interface ID
                var nanoFrameworkDeviceMatch = FindNanoFrameworkDevice(deviceInformation.Id);

                if (nanoFrameworkDeviceMatch == null)
                {
                    //     Create a new element for this device interface, and queue up the query of its
                    //     device information

                    var newNanoFrameworkDevice = new NanoDevice <NanoSerialDevice>();
                    newNanoFrameworkDevice.Device.DeviceInformation = new SerialDeviceInformation(deviceInformation, deviceSelector);
                    newNanoFrameworkDevice.Parent      = this;
                    newNanoFrameworkDevice.DebugEngine = new Engine(this, newNanoFrameworkDevice);
                    newNanoFrameworkDevice.Transport   = TransportType.Serial;

                    // Add the new element to the end of the list of devices
                    NanoFrameworkDevices.Add(newNanoFrameworkDevice as NanoDeviceBase);

                    // perform check for valid nanoFramework device is this is not the initial enumeration
                    if (isAllDevicesEnumerated)
                    {
                        // try opening the device to check for a valid nanoFramework device
                        if (await ConnectSerialDeviceAsync(newNanoFrameworkDevice.Device.DeviceInformation).ConfigureAwait(false))
                        {
                            Debug.WriteLine("New Serial device: " + deviceInformation.Id);

                            var name = EventHandlerForSerialDevice.Current.DeviceInformation?.Properties["System.ItemNameDisplay"] as string;

                            // acceptable names
                            if (name == "STM32 STLink")
                            {
                                // now fill in the description
                                newNanoFrameworkDevice.Description = name + " @ " + EventHandlerForSerialDevice.Current.Device.PortName;


                                Debug.WriteLine("Add new nanoFramework device to list: " + newNanoFrameworkDevice.Description + " @ " + newNanoFrameworkDevice.Device.DeviceInformation.DeviceSelector);
                            }

                            // done here, close the device
                            EventHandlerForSerialDevice.Current.CloseDevice();

                            return;
                        }

                        // couldn't open device better remove it from the collection right away
                        NanoFrameworkDevices.Remove(newNanoFrameworkDevice as NanoDeviceBase);
                    }
                }
                else
                {
                    // this NanoFramework device is already on the list
                    // stop the dispose countdown!
                    nanoFrameworkDeviceMatch.StopCountdownForDispose();
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Creates a DeviceListEntry for a device and adds it to the list of devices
        /// </summary>
        private void AddDeviceToListAsync(NetworkDeviceInformation networkDevice)
        {
            // search the device list for a device with a matching interface ID
            var networkMatch = FindDevice(networkDevice.DeviceId);

            // Add the device if it's new
            if (networkMatch != null)
            {
                return;
            }

            OnLogMessageAvailable(NanoDevicesEventSource.Log.CandidateDevice(networkDevice.DeviceId));

            // search the nanoFramework device list for a device with a matching interface ID
            var nanoFrameworkDeviceMatch = FindNanoFrameworkDevice(networkDevice.DeviceId);

            if (nanoFrameworkDeviceMatch != null)
            {
                return;
            }

            // Create a new element for this device and...
            var newNanoFrameworkDevice = new NanoDevice <NanoNetworkDevice>();

            newNanoFrameworkDevice.DeviceId       = networkDevice.DeviceId;
            newNanoFrameworkDevice.ConnectionPort = new PortTcpIp(this, newNanoFrameworkDevice, networkDevice);
            newNanoFrameworkDevice.Transport      = TransportType.TcpIp;

            var connectResult = newNanoFrameworkDevice.ConnectionPort.ConnectDevice();

            if (connectResult == ConnectPortResult.Unauthorized)
            {
                OnLogMessageAvailable(
                    NanoDevicesEventSource.Log.UnauthorizedAccessToDevice(networkDevice.DeviceId));
            }
            else if (connectResult == ConnectPortResult.Connected)
            {
                if (CheckValidNanoFrameworkNetworkDevice(newNanoFrameworkDevice))
                {
                    //add device to the collection
                    NanoFrameworkDevices.Add(newNanoFrameworkDevice);

                    _networkDevices.Add(networkDevice);

                    OnLogMessageAvailable(
                        NanoDevicesEventSource.Log.ValidDevice($"{newNanoFrameworkDevice.Description}"));
                }
                else
                {
                    // disconnect
                    newNanoFrameworkDevice.Disconnect();
                }
            }
            else
            {
                OnLogMessageAvailable(NanoDevicesEventSource.Log.QuitDevice(networkDevice.DeviceId));
            }

            // subtract devices count
            _newDevicesCount--;

            // check if we are done processing arriving devices
            if (_newDevicesCount == 0)
            {
                ProcessDeviceEnumerationComplete();
            }
        }
예제 #7
0
        /// <summary>
        /// Creates a DeviceListEntry for a device and adds it to the list of devices
        /// </summary>
        /// <param name="deviceInformation">DeviceInformation on the device to be added to the list</param>
        /// <param name="deviceId">The AQS used to find this device</param>
        private void AddDeviceToListAsync(String deviceId)
        {
            // search the device list for a device with a matching interface ID
            var serialMatch = FindDevice(deviceId);

            // Add the device if it's new
            if (serialMatch == null)
            {
                var serialDevice = new SerialDeviceInformation(deviceId);

                OnLogMessageAvailable(NanoDevicesEventSource.Log.CandidateDevice(deviceId));

                // search the nanoFramework device list for a device with a matching interface ID
                var nanoFrameworkDeviceMatch = FindNanoFrameworkDevice(deviceId);

                if (nanoFrameworkDeviceMatch == null)
                {
                    // Create a new element for this device and...
                    var newNanoFrameworkDevice = new NanoDevice <NanoSerialDevice>();
                    newNanoFrameworkDevice.DeviceId       = deviceId;
                    newNanoFrameworkDevice.ConnectionPort = new PortSerial(this, newNanoFrameworkDevice);
                    newNanoFrameworkDevice.Transport      = TransportType.Serial;

                    var connectResult = newNanoFrameworkDevice.ConnectionPort.ConnectDevice();

                    if (connectResult == ConnectPortResult.Unauthorized)
                    {
                        OnLogMessageAvailable(NanoDevicesEventSource.Log.UnauthorizedAccessToDevice(deviceId));
                    }
                    else if (connectResult == ConnectPortResult.Connected)
                    {
                        if (CheckValidNanoFrameworkSerialDevice(newNanoFrameworkDevice))
                        {
                            //add device to the collection
                            NanoFrameworkDevices.Add(newNanoFrameworkDevice);

                            _serialDevices.Add(serialDevice);

                            OnLogMessageAvailable(NanoDevicesEventSource.Log.ValidDevice($"{newNanoFrameworkDevice.Description}"));
                        }
                        else
                        {
                            // disconnect
                            newNanoFrameworkDevice.Disconnect();

                            // devices powered by the USB cable and that feature a serial converter (like an FTDI chip)
                            // are still booting when the USB enumeration event raises
                            // so need to give them enough time for the boot sequence to complete before trying to communicate with them

                            // Failing to connect to debugger engine on first attempt occurs frequently on dual USB devices like ESP32 WROVER KIT.
                            // Seems to be something related with both devices using the same USB endpoint
                            // Another reason is that an ESP32 takes around 3 seconds to complete the boot sequence and launch the CLR.
                            // Until then the device will look non responsive or invalid to the detection mechanism that we're using.
                            // A nice workaround for this seems to be adding an extra random wait so the comms are not simultaneous.

                            int delay;
                            lock (_delay)
                            {
                                delay = _delay.Next(200, 600);
                            }

                            Thread.Sleep(BootTime + delay);

                            OnLogMessageAvailable(NanoDevicesEventSource.Log.CheckingValidDevice($" {newNanoFrameworkDevice.DeviceId} *** 2nd attempt ***"));

                            connectResult = newNanoFrameworkDevice.ConnectionPort.ConnectDevice();

                            if (connectResult == ConnectPortResult.Unauthorized)
                            {
                                OnLogMessageAvailable(NanoDevicesEventSource.Log.UnauthorizedAccessToDevice(deviceId));
                            }
                            else if (connectResult == ConnectPortResult.Connected)
                            {
                                if (CheckValidNanoFrameworkSerialDevice(newNanoFrameworkDevice, true))
                                {
                                    //add device to the collection
                                    NanoFrameworkDevices.Add(newNanoFrameworkDevice);

                                    _serialDevices.Add(serialDevice);

                                    OnLogMessageAvailable(NanoDevicesEventSource.Log.ValidDevice($"{newNanoFrameworkDevice.Description}"));
                                }
                                else
                                {
                                    OnLogMessageAvailable(NanoDevicesEventSource.Log.QuitDevice(deviceId));
                                }
                            }
                            else
                            {
                                OnLogMessageAvailable(NanoDevicesEventSource.Log.QuitDevice(deviceId));
                            }
                        }
                    }
                    else
                    {
                        OnLogMessageAvailable(NanoDevicesEventSource.Log.QuitDevice(deviceId));
                    }

                    // subtract devices count
                    lock (_newDevicesCountLock)
                    {
                        _newDevicesCount--;
                    }


                    // check if we are done processing arriving devices
                    if (_newDevicesCount == 0)
                    {
                        ProcessDeviceEnumerationComplete();
                    }
                }
            }
        }
예제 #8
0
        /// <summary>
        /// Creates a DeviceListEntry for a device and adds it to the list of devices
        /// </summary>
        /// <param name="deviceInformation">DeviceInformation on the device to be added to the list</param>
        /// <param name="deviceSelector">The AQS used to find this device</param>
        private async void AddDeviceToList(DeviceInformation deviceInformation, String deviceSelector)
        {
            // search the device list for a device with a matching interface ID
            var serialMatch = FindDevice(deviceInformation.Id);

            // Add the device if it's new
            if (serialMatch == null)
            {
                SerialDevices.Add(new SerialDeviceInformation(deviceInformation, deviceSelector));

                // search the NanoFramework device list for a device with a matching interface ID
                var nanoFrameworkDeviceMatch = FindNanoFrameworkDevice(deviceInformation.Id);

                if (nanoFrameworkDeviceMatch == null)
                {
                    //     Create a new element for this device interface, and queue up the query of its
                    //     device information

                    var newNanoFrameworkDevice = new NanoDevice <NanoSerialDevice>();
                    newNanoFrameworkDevice.Device.DeviceInformation = new SerialDeviceInformation(deviceInformation, deviceSelector);
                    newNanoFrameworkDevice.Parent      = this;
                    newNanoFrameworkDevice.DebugEngine = new Engine(this, newNanoFrameworkDevice);
                    newNanoFrameworkDevice.Transport   = TransportType.Serial;

                    // Add the new element to the end of the list of devices
                    NanoFrameworkDevices.Add(newNanoFrameworkDevice as NanoDeviceBase);

                    // perform check for valid nanoFramework device is this is not the initial enumeration
                    if (isAllDevicesEnumerated)
                    {
                        // try opening the device to check for a valid nanoFramework device
                        if (await ConnectSerialDeviceAsync(newNanoFrameworkDevice.Device.DeviceInformation))
                        {
                            Debug.WriteLine("New Serial device: " + deviceInformation.Id);

                            if (await CheckValidNanoFrameworkSerialDeviceAsync())
                            {
                                // done here, close the device
                                EventHandlerForSerialDevice.Current.CloseDevice();

                                // remove it from collection...
                                NanoFrameworkDevices.Remove(newNanoFrameworkDevice as NanoDeviceBase);

                                //... and add it again, otherwise the bindings might fail
                                NanoFrameworkDevices.Add(newNanoFrameworkDevice as NanoDeviceBase);

                                Debug.WriteLine("Add new nanoFramework device to list: " + newNanoFrameworkDevice.Description + " @ " + newNanoFrameworkDevice.Device.DeviceInformation.DeviceSelector);

                                return;
                            }
                        }

                        Debug.WriteLine($"Removing { deviceInformation.Id } from collection...");

                        // couldn't open device better remove it from the collection right away
                        NanoFrameworkDevices.Remove(newNanoFrameworkDevice as NanoDeviceBase);

                        // can't do anything with this one, better dispose it
                        newNanoFrameworkDevice.Dispose();
                    }
                }
                else
                {
                    // this NanoFramework device is already on the list
                    // stop the dispose countdown!
                    nanoFrameworkDeviceMatch.StopCountdownForDispose();
                }
            }
        }
예제 #9
0
        /// <summary>
        /// Creates a DeviceListEntry for a device and adds it to the list of devices
        /// </summary>
        /// <param name="deviceInformation">DeviceInformation on the device to be added to the list</param>
        /// <param name="deviceSelector">The AQS used to find this device</param>
        private async void AddDeviceToList(DeviceInformation deviceInformation, String deviceSelector)
        {
            // device black listed
            // discard known system and unusable devices
            //
            if (
                deviceInformation.Id.StartsWith(@"\\?\ACPI") ||

                // reported in https://github.com/nanoframework/Home/issues/332
                // COM ports from Broadcom 20702 Bluetooth adapter
                deviceInformation.Id.Contains(@"VID_0A5C+PID_21E1") ||

                // reported in https://nanoframework.slack.com/archives/C4MGGBH1P/p1531660736000055?thread_ts=1531659631.000021&cid=C4MGGBH1P
                // COM ports from Broadcom 20702 Bluetooth adapter
                deviceInformation.Id.Contains(@"VID&00010057_PID&0023")
                )
            {
                OnLogMessageAvailable(NanoDevicesEventSource.Log.DroppingBlackListedDevice(deviceInformation.Id));

                // don't even bother with these
                return;
            }

            OnLogMessageAvailable(NanoDevicesEventSource.Log.DeviceArrival(deviceInformation.Id));

            // search the device list for a device with a matching interface ID
            var serialMatch = FindDevice(deviceInformation.Id);

            // Add the device if it's new
            if (serialMatch == null)
            {
                var serialDevice = new SerialDeviceInformation(deviceInformation, deviceSelector);
                _serialDevices.Add(serialDevice);

                OnLogMessageAvailable(NanoDevicesEventSource.Log.CandidateDevice(deviceInformation.Id));

                // search the nanoFramework device list for a device with a matching interface ID
                var nanoFrameworkDeviceMatch = FindNanoFrameworkDevice(deviceInformation.Id);

                if (nanoFrameworkDeviceMatch == null)
                {
                    // Create a new element for this device and...
                    var newNanoFrameworkDevice = new NanoDevice <NanoSerialDevice>();
                    newNanoFrameworkDevice.Device.DeviceInformation = new SerialDeviceInformation(deviceInformation, deviceSelector);
                    newNanoFrameworkDevice.Parent    = this;
                    newNanoFrameworkDevice.Transport = TransportType.Serial;

                    // ... add it to the collection of tentative devices
                    _tentativeNanoFrameworkDevices.Add(newNanoFrameworkDevice as NanoDeviceBase);

                    // perform check for valid nanoFramework device is this is not the initial enumeration
                    if (IsDevicesEnumerationComplete)
                    {
                        if (await CheckValidNanoFrameworkSerialDeviceAsync(newNanoFrameworkDevice.Device.DeviceInformation))
                        {
                            // the device info was updated above, need to get it from the tentative devices collection

                            //add device to the collection
                            NanoFrameworkDevices.Add(FindNanoFrameworkDevice(newNanoFrameworkDevice.Device.DeviceInformation.DeviceInformation.Id));

                            OnLogMessageAvailable(NanoDevicesEventSource.Log.ValidDevice($"{newNanoFrameworkDevice.Description} {newNanoFrameworkDevice.Device.DeviceInformation.DeviceInformation.Id}"));

                            // done here, clear tentative list
                            _tentativeNanoFrameworkDevices.Clear();

                            // done here
                            return;
                        }

                        // clear tentative list
                        _tentativeNanoFrameworkDevices.Clear();

                        OnLogMessageAvailable(NanoDevicesEventSource.Log.QuitDevice(deviceInformation.Id));

                        _serialDevices.Remove(serialDevice);
                    }
                }
            }
        }