internal void Init(string devicePath) { IntPtr handle = NativeMethods.CreateFileFromDevice(devicePath, NativeMethods.EFileAccess.Read | NativeMethods.EFileAccess.Write, NativeMethods.EFileShare.None); if (handle == (IntPtr)(-1)) { int hr = Marshal.GetHRForLastWin32Error(); throw DeviceException.CreateIOException(Device, "Unable to open serial device (" + devicePath + ").", hr); } var timeouts = new NativeMethods.COMMTIMEOUTS(); timeouts.ReadIntervalTimeout = uint.MaxValue; timeouts.ReadTotalTimeoutConstant = uint.MaxValue - 1; // CP210x fails if this is set to uint.MaxValue. timeouts.ReadTotalTimeoutMultiplier = uint.MaxValue; if (!NativeMethods.SetCommTimeouts(handle, out timeouts)) { int hr = Marshal.GetHRForLastWin32Error(); NativeMethods.CloseHandle(handle); throw DeviceException.CreateIOException(Device, "Unable to set serial timeouts.", hr); } _handle = handle; HandleInitAndOpen(); }
/// <summary> /// Opens a new serial port connection. /// </summary> /// <exception cref="System.InvalidOperationException">Port is already open.</exception> /// <exception cref="System.IO.IOException">The port is in an invalid state. -or- An attempt to set the state of the underlying port failed.</exception> /// <exception cref="System.UnauthorizedAccessException">Access is denied to the port.</exception> public void Open() { if (this.IsOpen) { throw new InvalidOperationException("Port is already open."); } if (IsRunningOnMono == false) { var portName = (this.PortName.StartsWith(@"\\?\", StringComparison.Ordinal) ? "" : @"\\?\") + this.PortName; this.Handle = NativeMethods.CreateFileW( portName, NativeMethods.GENERIC_READ | NativeMethods.GENERIC_WRITE, 0, //exclusive access IntPtr.Zero, NativeMethods.OPEN_EXISTING, 0, IntPtr.Zero ); if (this.IsOpen == false) { throw new IOException("The port is in an invalid state."); } var config = new NativeMethods.COMMCONFIG(); config.dwSize = Marshal.SizeOf(config); config.wVersion = 1; config.wReserved = 0; config.dcb = new NativeMethods.DCB(); config.dcb.DCBlength = Marshal.SizeOf(config.dcb); config.dcb.BaudRate = this.BaudRate; config.dcb.fBinary = 1; config.dcb.fParity = 0; config.dcb.fOutxCtsFlow = 0; config.dcb.fOutxDsrFlow = 0; config.dcb.fDtrControl = NativeMethods.DTR_CONTROL_ENABLE; config.dcb.fDsrSensitivity = 0; config.dcb.fTXContinueOnXoff = 0; config.dcb.fOutX = 0; config.dcb.fInX = 0; config.dcb.fErrorChar = 0; config.dcb.fNull = 0; config.dcb.fRtsControl = NativeMethods.RTS_CONTROL_ENABLE; config.dcb.fAbortOnError = 0; config.dcb.fDummy2 = 0; config.dcb.wReserved = 0; config.dcb.XonLim = 0; config.dcb.XoffLim = 0; config.dcb.ByteSize = (byte)this.DataBits; switch (this.Parity) { case Parity.None: config.dcb.Parity = NativeMethods.NOPARITY; break; case Parity.Odd: config.dcb.Parity = NativeMethods.ODDPARITY; break; case Parity.Even: config.dcb.Parity = NativeMethods.EVENPARITY; break; case Parity.Mark: config.dcb.Parity = NativeMethods.MARKPARITY; break; case Parity.Space: config.dcb.Parity = NativeMethods.SPACEPARITY; break; default: throw new IOException("An attempt to set the state of the underlying port failed (invalid parity)."); } switch (this.StopBits) { case StopBits.One: config.dcb.StopBits = NativeMethods.ONESTOPBIT; break; case StopBits.OnePointFive: config.dcb.StopBits = NativeMethods.ONE5STOPBITS; break; case StopBits.Two: config.dcb.StopBits = NativeMethods.TWOSTOPBITS; break; default: throw new IOException("An attempt to set the state of the underlying port failed (invalid stop bit count)."); } config.dcb.XonChar = 0x11; config.dcb.XoffChar = 0x13; config.dcb.ErrorChar = 0x3F; config.dcb.EofChar = 0; config.dcb.EvtChar = 0; config.dcb.wReserved1 = 0; config.dwProviderSubType = NativeMethods.PST_RS232; config.dwProviderOffset = 0; config.dwProviderSize = 0; config.wcProviderData = null; var resultConfigSet = NativeMethods.SetCommConfig(this.Handle, ref config, config.dwSize); if (resultConfigSet != true) { throw new IOException("An attempt to set the state of the underlying port failed.", new Win32Exception()); } var commTimeouts = new NativeMethods.COMMTIMEOUTS(); commTimeouts.ReadIntervalTimeout = NativeMethods.MAXDWORD; commTimeouts.ReadTotalTimeoutMultiplier = (this.ReadTimeout == 0) ? 0 : -1; commTimeouts.ReadTotalTimeoutConstant = (this.ReadTimeout != InfiniteTimeout) ? this.ReadTimeout : -2; commTimeouts.WriteTotalTimeoutMultiplier = 0; commTimeouts.WriteTotalTimeoutConstant = (this.ReadTimeout != InfiniteTimeout) ? this.WriteTimeout : 0; var resultTimeouts = NativeMethods.SetCommTimeouts(this.Handle, ref commTimeouts); if (resultTimeouts != true) { throw new IOException("An attempt to set the state of the underlying port failed.", new Win32Exception()); } } else { var portName = (this.PortName.StartsWith(@"\\?\", StringComparison.Ordinal) ? this.PortName.Remove(0, 4).Trim() : this.PortName.Trim()); this.FrameworkSerialPort = new SerialPort(portName, this.BaudRate, this.Parity, this.DataBits, this.StopBits); this.FrameworkSerialPort.ReadTimeout = this.ReadTimeout; this.FrameworkSerialPort.WriteTimeout = this.WriteTimeout; this.FrameworkSerialPort.DtrEnable = true; this.FrameworkSerialPort.RtsEnable = true; this.FrameworkSerialPort.Open(); } this.Purge(); }