Example #1
0
        private static void DownloadRom(AsyncTaskData taskData)
        {
            SingleInstanceApplication.Instance.IsBusy = true;
            var data    = (DownloadTaskData)taskData;
            var romPath = PrepareRom(data);

            data.UpdateTaskProgress(0, string.Format(CultureInfo.CurrentCulture, Resources.Strings.DownloadRom_Update_Format, romPath));
            var cancelled = data.AcceptCancelIfRequested();

            if (!cancelled)
            {
                using (var rom = FileUtilities.OpenFileStream(romPath))
                {
                    var configData = new Dictionary <string, object>()
                    {
                        { SerialPortConnection.PortNameConfigDataName, data.Intellicart.SerialPort }
                    };
                    using (var port = SerialPortConnection.Create(configData))
                    {
                        port.BaudRate     = data.Intellicart.BaudRate;
                        port.WriteTimeout = data.Intellicart.Timeout * 1000;

                        // default port settings are 8,N,1 with no handshaking
                        var bytesRemaining         = (int)rom.Length;
                        var totalBytes             = rom.Length;
                        var bytesPerSecond         = data.Intellicart.BaudRate / 8;
                        var bytesWritten           = 0;
                        var estimatedDownloadTime  = ((double)rom.Length / bytesPerSecond) + 4; // give it time to finish
                        var estimatedTimeRemaining = estimatedDownloadTime;
                        var percentDone            = 0.0;

                        // Would like to respond to cancel requests somewhat quickly. So, let's
                        // write out small enough chunks even at the slowest baud rate...
                        var bytesPerWrite = (data.Intellicart.BaudRate / 2400) * 128;
                        System.Diagnostics.Debug.Assert(bytesPerWrite > 0, "How did we get zero bytes to write?!");
                        port.Open();
                        var    stopwatch = System.Diagnostics.Stopwatch.StartNew();
                        byte[] buffer    = new byte[bytesPerWrite];
                        while (!cancelled && (bytesRemaining > 0))
                        {
                            var updateText = string.Format(CultureInfo.CurrentCulture, Resources.Strings.DownloadRom_UpdateTitle_Format, data.Name, Math.Max(0, (int)estimatedTimeRemaining));
                            data.UpdateTaskTitle(updateText);
                            bytesPerWrite = Math.Min(bytesPerWrite, bytesRemaining);
                            var bytesRead = rom.Read(buffer, 0, bytesPerWrite);
                            bytesWritten          += bytesRead;
                            bytesRemaining        -= bytesRead;
                            updateText             = string.Format(CultureInfo.CurrentCulture, Resources.Strings.DownloadRom_Update_Format, romPath);
                            estimatedTimeRemaining = estimatedDownloadTime - stopwatch.Elapsed.TotalSeconds;
                            percentDone            = stopwatch.Elapsed.TotalSeconds / estimatedDownloadTime;
                            data.UpdateTaskProgress(percentDone, updateText);
                            port.WriteStream.Write(buffer, 0, bytesRead);
                            cancelled = data.AcceptCancelIfRequested();
                        }

                        // If we close the port too soon after writing, the Intellicart will time out reading data from the stream.
                        // This is likely due to buffering, and that the streams get disposed when the port and file streams are
                        // disposed. On Mac in particular, the write out to the port may complete far more quickly than what the
                        // math would indicate, based on observation. This implies one of the following:
                        //  a) Even though the synchronous write was called, the underlying implementation is asynchronous
                        //  b) It could be that the driver itself is "lying" to the underlying implementation
                        //  c) Buffering, either in the driver, kernel, or other API layers, misleads the higher-level APIs
                        var timedOut = false;
                        while (!cancelled && !timedOut)
                        {
                            var message = string.Format(Resources.Strings.DownloadRom_UpdateTitle_Format, data.Name, Math.Max(0, (int)estimatedTimeRemaining));
                            data.UpdateTaskTitle(message);
                            System.Threading.Thread.Sleep(250);
                            cancelled = data.AcceptCancelIfRequested();
                            var updateText = string.Format(CultureInfo.CurrentCulture, Resources.Strings.DownloadRom_Update_Format, romPath);
                            estimatedTimeRemaining = estimatedDownloadTime - stopwatch.Elapsed.TotalSeconds;
                            percentDone            = Math.Max(100, stopwatch.Elapsed.TotalSeconds / estimatedDownloadTime);
                            data.UpdateTaskProgress(percentDone, updateText);
                            timedOut = estimatedTimeRemaining < 0;
                        }
                    }
                }
            }
        }
Example #2
0
        private static void CheckDevices(AsyncTaskData taskData)
        {
            var data       = (CheckForDevicesTaskData)taskData;
            var validPorts = new HashSet <string>();

            data.ValidDevicePorts = validPorts;
            var potentialPorts = data.LtoFlashViewModel.AvailableDevicePorts.Except(data.CurrentDevices).ToList();

            if (!string.IsNullOrWhiteSpace(data.LastKnownPort) && (potentialPorts.Count > 1) && potentialPorts.Remove(data.LastKnownPort))
            {
                potentialPorts.Insert(0, data.LastKnownPort);
            }

            foreach (var portName in potentialPorts)
            {
                var maxRetries = 1;
                for (var retry = 0; retry < maxRetries; ++retry)
                {
                    if (data.AcceptCancelIfRequested())
                    {
                        break;
                    }
                    var errorLogger = Properties.Settings.Default.EnablePortLogging ? new Logger(Configuration.Instance.GetPortLogPath(portName)) : null;
                    try
                    {
                        var isValidDevicePort = false;
                        var configData        = new Dictionary <string, object>()
                        {
                            { SerialPortConnection.PortNameConfigDataName, portName }
                        };
                        using (var port = SerialPortConnection.Create(configData))
                        {
                            if (Properties.Settings.Default.EnablePortLogging)
                            {
                                port.EnableLogging(Configuration.Instance.GetPortLogPath(portName));
                            }
                            port.LogPortMessage("CheckForDevices: BEGIN");
                            data.UpdateTaskProgress(0, string.Format(Resources.Strings.DeviceSearch_Task_Progress_Format, portName));
                            port.BaudRate  = Device.DefaultBaudRate;
                            port.Handshake = Device.Handshake;
                            port.Open();
                            var numRetry = 4;
                            var timeout  = 1100;
                            for (var i = 0; !data.AcceptCancelIfRequested() && (i < numRetry); ++i)
                            {
                                if (!data.AcceptCancelIfRequested())
                                {
                                    if (port.IsOpen && port.WaitForBeacon(timeout))
                                    {
                                        isValidDevicePort = true;
                                    }
                                }
                            }
                            port.LogPortMessage("CheckForDevices: END");
                        }
                        if (!data.AcceptCancelIfRequested() && isValidDevicePort)
                        {
                            if (Properties.Settings.Default.AutomaticallyConnectToDevices && data.AutoConnect)
                            {
                                data.ReportedAnyAutoConnectDevices |= true;
                                var creationInfo = new Dictionary <string, object>()
                                {
                                    { DeviceCreationInfo.ConfigName, new DeviceCreationInfo(true, true, ActivationMode.ActivateIfFirst) }
                                };
                                INTV.Shared.Interop.DeviceManagement.DeviceChange.ReportDeviceAdded(data, portName, Core.Model.Device.ConnectionType.Serial, creationInfo);
                                data.Task.CancelTask();
                            }
                            else
                            {
                                validPorts.Add(portName);
                            }
                        }
                    }
                    catch (UnauthorizedAccessException)
                    {
                        // Access is denied to the port or the current process, or another process on the system,
                        // already has the specified COM port open either by a SerialPort instance or in unmanaged code.
                        if (errorLogger != null)
                        {
                            errorLogger.Log("CheckForDevices: UnauthorizedAccessException on port " + portName);
                        }
                        maxRetries = RetryCount;
                        System.Threading.Thread.Sleep(500);
                    }
                    catch (ArgumentOutOfRangeException)
                    {
                        // One or more of the properties for this instance are invalid. For example, the Parity, DataBits,
                        // or Handshake properties are not valid values; the BaudRate is less than or equal to zero; the
                        // ReadTimeout or WriteTimeout property is less than zero and is not InfiniteTimeout.
                        if (errorLogger != null)
                        {
                            errorLogger.Log("CheckForDevices: ArgumentOutOfRangeException on port " + portName);
                        }
                    }
                    catch (ArgumentException)
                    {
                        // The port name does not begin with "COM", or the file type of the port is not supported.
                        if (errorLogger != null)
                        {
                            errorLogger.Log("CheckForDevices: ArgumentException on port " + portName);
                        }
                    }
                    catch (System.IO.IOException)
                    {
                        // The port is in an invalid state, or an attempt to set the state of the underlying port failed.
                        // For example, the parameters passed from this SerialPort object were invalid.
                        if (errorLogger != null)
                        {
                            errorLogger.Log("CheckForDevices: IOException on port " + portName);
                        }
                    }
                    catch (InvalidOperationException)
                    {
                        // The specified port on the current instance of the SerialPort is already open.
                        if (errorLogger != null)
                        {
                            errorLogger.Log("CheckForDevices: InvalidOperationException on port " + portName);
                        }
                    }
                    catch (Exception e)
                    {
                        // Caught some unexpected exception.
                        if (errorLogger != null)
                        {
                            errorLogger.Log("CheckForDevices: Exception on port " + portName + " with message: " + e.Message);
                        }
                        throw;
                    }
                }
            }
            if (data.CancelRequsted)
            {
                validPorts.Clear();
            }
        }