private SerialPortFixer(string portName) { const int dwFlagsAndAttributes = 0x40000000; const FileAccess dwAccess = FileAccess.Read | FileAccess.Write; if ((portName == null) || !portName.StartsWith("COM", StringComparison.OrdinalIgnoreCase)) { throw new ArgumentException("Invalid Serial Port", "portName"); } SafeFileHandle hFile = GWin32.CreateFile(@"\\.\" + portName, dwAccess, 0, IntPtr.Zero, FileMode.Open, dwFlagsAndAttributes, IntPtr.Zero); if (hFile.IsInvalid) { WinIoError(); } try { int fileType = GetFileType(hFile); if ((fileType != 2) && (fileType != 0)) { throw new ArgumentException("Invalid Serial Port", "portName"); } m_Handle = hFile; InitializeDcb(); } catch { hFile.Close(); m_Handle = null; throw; } }
private void SetCommStateNative(ref GWin32.DCB lpDcb) { int commErrors = 0; GWin32.Comstat comStat = new GWin32.Comstat(); for (int i = 0; i < CommStateRetries; i++) { if (!GWin32.ClearCommError(m_Handle, ref commErrors, ref comStat)) { WinIoError(); } if (GWin32.SetCommState(m_Handle, ref lpDcb)) { break; } if (i == CommStateRetries - 1) { WinIoError(); } } }
public void Open(string comPortName = "COM3", int baudRate = 128000) { if (m_hCommPort != null) { return; } SerialPort comm = new SerialPort(); comm.BaudRate = baudRate; m_hCommPort = GWin32.CreateFile(comPortName, FileAccess.Read | FileAccess.Write, //GENERIC_READ | GENERIC_WRITE,//access ( read and write) FileShare.None, //0, //(share) 0:cannot share the COM port IntPtr.Zero, //0, //security (None) FileMode.Open, //OPEN_EXISTING,// creation : open_existing 0x20000000 | 0x40000000, //FILE_FLAG_OVERLAPPED,// we want overlapped operation IntPtr.Zero //0// no templates file for COM port... ); if (m_hCommPort == null || m_hCommPort.IsInvalid) { m_hCommPort = null; int err = Marshal.GetLastWin32Error(); string errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message; if (onErr != null) { onErr.OnError("Open com failed " + errorMessage, true); } throwWinErr("Open com failed "); } const uint EV_RXCHAR = 1, EV_TXEMPTY = 4; if (!GWin32.SetCommMask(m_hCommPort, EV_RXCHAR | EV_TXEMPTY)) { if (onErr != null) { onErr.OnError("Failed to Set Comm Mask", true); } throwWinErr("Failed to Set Comm Mask"); } GWin32.DCB dcb = new GWin32.DCB(); dcb.DCBLength = (uint)Marshal.SizeOf(dcb); if (!GWin32.GetCommState(m_hCommPort, ref dcb)) { if (onErr != null) { onErr.OnError("CSerialCommHelper : Failed to Get Comm State", true); } throwWinErr("CSerialCommHelper : Failed to Get Comm State"); } dcb.BaudRate = (uint)comm.BaudRate; dcb.ByteSize = (byte)comm.DataBits; dcb.Parity = comm.Parity; dcb.StopBits = comm.StopBits; dcb.DsrSensitivity = false; dcb.DtrControl = GWin32.DtrControl.Enable; dcb.OutxDsrFlow = false; dcb.OutxCtsFlow = false; dcb.InX = false; dcb.RtsControl = GWin32.RtsControl.Disable; dcb.Binary = true; if (!GWin32.SetCommState(m_hCommPort, ref dcb)) { if (onErr != null) { onErr.OnError("CSerialCommHelper : Failed to Get Comm State", true); } throwWinErr("CSerialCommHelper : Failed to Set Comm State"); } GWin32.COMMTIMEOUTS commTimeouts = new GWin32.COMMTIMEOUTS(); commTimeouts.ReadIntervalTimeout = 0; // Never timeout, always wait for data. commTimeouts.ReadTotalTimeoutMultiplier = 0; // Do not allow big read timeout when big read buffer used commTimeouts.ReadTotalTimeoutConstant = 0; // Total read timeout (period of read loop) commTimeouts.WriteTotalTimeoutConstant = 0; // Const part of write timeout commTimeouts.WriteTotalTimeoutMultiplier = 0; // Variable part of write timeout (per byte) GWin32.SetCommTimeouts(m_hCommPort, ref commTimeouts); }
protected void gwait() { GWin32.SleepEx(GWin32.INFINITE, true); }
public void Start(IComApp app) { GWin32.PurgeComm(m_hCommPort, 0x0004 | 0x0008); app.OnStart(this); if (_thread != null) { return; } threadStarted = true; new Thread(() => { bool inWrite = false; uint writeErr = 0; uint writeOk = 0; NativeOverlapped ov = new System.Threading.NativeOverlapped(); while (threadStarted) { if (m_hCommPort == null || m_hCommPort.IsInvalid) { break; } SerWriteInfo wi = null; lock (_writeQueueLock) { if (_writeQueue.Count == 0) { Monitor.Wait(_writeQueueLock); } while (inWrite) { Thread.Sleep(100); Console.WriteLine("in write wait"); } wi = _writeQueue[0]; _writeQueue.RemoveAt(0); } //if (wi.Done != null) try { wi.Done(0, "no buf"); } catch { }; //continue; if (wi == null || wi.buf == null || wi.buf.Length == 0) { if (wi.Done != null) { try { wi.Done(0, "no buf"); } catch { } } ; continue; } inWrite = true; ResetOverlapped(ov); var writeRes = GWin32.WriteFileEx(m_hCommPort, wi.buf, (uint)wi.buf.Length, ref ov, (uint err, uint b, ref NativeOverlapped c) => { writeErr = err; writeOk = b; inWrite = false; }); if (!writeRes) { //Console.WriteLine("failed write comm " + getWinErr()); if (wi.Done != null) { try { wi.Done(255, "failed write comm " + getWinErr()); } catch { } } ; inWrite = false; } // IOCompletion routine is only called once this thread is in an alertable wait state. gwait(); //only with thread if (writeRes) { if (wi.Done != null) { try { wi.Done(writeErr, writeErr == 0 ? writeOk.ToString() : "WriteError"); } catch { } } } } Console.WriteLine("Com Write Queue done"); }).Start(); _thread = new Thread(() => { var tbuf = new byte[2048]; var buf1 = new byte[1]; NativeOverlapped ovo = new System.Threading.NativeOverlapped(); try { while (threadStarted) { SetTimeout(0); //set always wait GWin32.SetLastError(0); ResetOverlapped(ovo); GWin32.ReadFileEx(m_hCommPort, buf1, (uint)buf1.Length, ref ovo, (uint err, uint len, ref NativeOverlapped ovoo) => { if (err != 0) { Console.WriteLine("read got err " + err); } else { SetTimeout(); uint numRead; NativeOverlapped ov = new System.Threading.NativeOverlapped(); ov.EventHandle = GWin32.CreateEvent(IntPtr.Zero, true, false, null); if (!GWin32.ReadFile(m_hCommPort, tbuf, (uint)tbuf.Length, out numRead, ref ov)) { if (GWin32.GetLastError() == 997) //IO Pending { GWin32.WaitForSingleObject(ov.EventHandle, GWin32.INFINITE); } else { Console.WriteLine("read got err " + getWinErr()); } GWin32.GetOverlappedResult(m_hCommPort, ref ov, out numRead, true); } GWin32.CloseHandle(ov.EventHandle); ov.EventHandle = IntPtr.Zero; //Console.WriteLine("got data " + numRead); var buf = new byte[1 + numRead]; buf[0] = buf1[0]; if (numRead > 0) { Array.Copy(tbuf, 0, buf, 1, numRead); app.OnData(buf); } //Console.WriteLine(BitConverter.ToString(buf)); } }); var le = GWin32.GetLastError(); if (le != 0) { _thread = null; Console.WriteLine("Read Error " + le); break; } gwait(); } } catch (InvalidOperationException iv) { _thread = null; threadStarted = false; if (onErr != null) { onErr.OnError("InvalidOperationException " + iv.Message, true); return; } Console.WriteLine("InvalidOperationException " + iv.Message); } Close(); onErr.OnError("thread done", true); Console.WriteLine("thread done"); }); _thread.Start(); }
protected void SetTimeout(uint tm = GWin32.INFINITE) { GWin32.COMMTIMEOUTS commTimeouts = new GWin32.COMMTIMEOUTS(); commTimeouts.ReadIntervalTimeout = tm; GWin32.SetCommTimeouts(m_hCommPort, ref commTimeouts); }