Example #1
0
        private async Task <bool> ConnectSerialDeviceAsync(SerialDeviceInformation serialDeviceInfo)
        {
            // try to determine if we already have this device opened.
            if (EventHandlerForSerialDevice.Current.Device != null)
            {
                // device matches
                if (EventHandlerForSerialDevice.Current.DeviceInformation == serialDeviceInfo.DeviceInformation)
                {
                    return(true);
                }
            }

            bool openDeviceResult = await EventHandlerForSerialDevice.Current.OpenDeviceAsync(serialDeviceInfo.DeviceInformation, serialDeviceInfo.DeviceSelector);

            if (openDeviceResult)
            {
                OnLogMessageAvailable(NanoDevicesEventSource.Log.OpenDevice(serialDeviceInfo.DeviceInformation.Id));
            }
            else
            {
                // Most likely the device is opened by another app, but cannot be sure
                OnLogMessageAvailable(NanoDevicesEventSource.Log.CriticalError($"Unknown error opening {serialDeviceInfo.DeviceInformation.Id}, possibly opened by another app"));
            }

            return(openDeviceResult);
        }
Example #2
0
        private async Task <bool> ConnectSerialDeviceAsync(SerialDeviceInformation serialDeviceInfo)
        {
            // try to determine if we already have this device opened.
            if (EventHandlerForSerialDevice.Current != null)
            {
                // device matches
                if (EventHandlerForSerialDevice.Current.DeviceInformation == serialDeviceInfo.DeviceInformation)
                {
                    return(true);
                }
            }

            // Create an EventHandlerForDevice to watch for the device we are connecting to
            EventHandlerForSerialDevice.CreateNewEventHandlerForDevice();

            return(await EventHandlerForSerialDevice.Current.OpenDeviceAsync(serialDeviceInfo.DeviceInformation, serialDeviceInfo.DeviceSelector).ConfigureAwait(false));
        }
Example #3
0
        private async Task <bool> ConnectSerialDeviceAsync(SerialDeviceInformation serialDeviceInfo)
        {
            // try to determine if we already have this device opened.
            if (EventHandlerForSerialDevice.Current != null)
            {
                // device matches
                if (EventHandlerForSerialDevice.Current.DeviceInformation == serialDeviceInfo.DeviceInformation)
                {
                    return(true);
                }
            }

            inputStreamReader  = null;
            outputStreamWriter = null;

            // access the Current in EventHandlerForDevice to create a watcher for the device we are connecting to
            var isConnected = EventHandlerForSerialDevice.Current.IsDeviceConnected;

            return(await EventHandlerForSerialDevice.Current.OpenDeviceAsync(serialDeviceInfo.DeviceInformation, serialDeviceInfo.DeviceSelector));
        }
Example #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="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();
                    }
                }
            }
        }
Example #5
0
        private async Task <bool> CheckValidNanoFrameworkSerialDeviceAsync(SerialDeviceInformation deviceInformation)
        {
            // get name
            var name         = deviceInformation.DeviceInformation.Name;
            var serialNumber = GetSerialNumber(deviceInformation.DeviceInformation.Id);

            OnLogMessageAvailable(NanoDevicesEventSource.Log.CheckingValidDevice(deviceInformation.DeviceInformation.Id));

            var tentativeDevice = await SerialDevice.FromIdAsync(deviceInformation.DeviceInformation.Id);

            try
            {
                // Device could have been blocked by user or the device has already been opened by another app.
                if (tentativeDevice != null)
                {
                    // adjust settings for serial port
                    tentativeDevice.BaudRate = 115200;
                    tentativeDevice.DataBits = 8;

                    /////////////////////////////////////////////////////////////
                    // need to FORCE the parity setting to _NONE_ because
                    // the default on the current ST Link is different causing
                    // the communication to fail
                    /////////////////////////////////////////////////////////////
                    tentativeDevice.Parity = SerialParity.None;

                    tentativeDevice.WriteTimeout = TimeSpan.FromMilliseconds(1000);
                    tentativeDevice.ReadTimeout  = TimeSpan.FromMilliseconds(1000);

                    if (serialNumber != null && serialNumber.Contains("NANO_"))
                    {
                        var device = FindNanoFrameworkDevice(deviceInformation.DeviceInformation.Id);

                        if (device != null)
                        {
                            device.Description = serialNumber + " @ " + tentativeDevice.PortName;

                            // should be a valid nanoFramework device, done here
                            return(true);
                        }
                        else
                        {
                            OnLogMessageAvailable(NanoDevicesEventSource.Log.CriticalError($"Couldn't find nano device {EventHandlerForSerialDevice.Current.DeviceInformation.Id} with serial {serialNumber}"));
                        }
                    }
                    else
                    {
                        // need an extra check on this because this can be 'just' a regular COM port without any nanoFramework device behind

                        // fill in description for this device
                        var device = FindNanoFrameworkDevice(deviceInformation.DeviceInformation.Id);

                        // need an extra check on this because this can be 'just' a regular COM port without any nanoFramework device behind
                        var connectionResult = await PingDeviceLocalAsync(tentativeDevice);

                        if (connectionResult)
                        {
                            // should be a valid nanoFramework device
                            device.Description = name + " @ " + tentativeDevice.PortName;

                            // done here
                            return(true);
                        }
                        else
                        {
                            // doesn't look like a nanoFramework device
                            return(false);
                        }
                    }
                }
                else
                {
                    // Most likely the device is opened by another app, but cannot be sure
                    OnLogMessageAvailable(NanoDevicesEventSource.Log.CriticalError($"Unknown error, possibly opened by another app : {deviceInformation.DeviceInformation.Id}"));
                }
            }
            // catch all because the device open might fail for a number of reasons
            catch (Exception ex)
            {
            }
            finally
            {
                // dispose on a Task to perform the Dispose()
                // this is required to be able to actually close devices that get stuck with pending tasks on the in/output streams
                var closeTask = Task.Factory.StartNew(() =>
                {
                    // This closes the handle to the device
                    tentativeDevice?.Dispose();
                    tentativeDevice = null;
                });
            }

            // default to false
            return(false);
        }
Example #6
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);
                    }
                }
            }
        }