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); }
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)); }
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)); }
/// <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(); } } } }
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); }
/// <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); } } } }