Esempio n. 1
0
        private void ReceiveThread()
        {
            var buf = new Byte[1];

            var sg = new AutoResetEvent(false);
            var ov = new OVERLAPPED();
            var unmanagedOv = Marshal.AllocHGlobal(Marshal.SizeOf(ov));
            ov.Offset = 0; ov.OffsetHigh = 0;
            ov.hEvent = sg.Handle;
            Marshal.StructureToPtr(ov, unmanagedOv, true);

            uint eventMask = 0;
            var uMask = Marshal.AllocHGlobal(Marshal.SizeOf(eventMask));

            try
            {
                while (true)
                {
                    if (!Win32Com.SetCommMask(_hPort, Win32Com.EV_RXCHAR | Win32Com.EV_TXEMPTY | Win32Com.EV_CTS | Win32Com.EV_DSR
                        | Win32Com.EV_BREAK | Win32Com.EV_RLSD | Win32Com.EV_RING | Win32Com.EV_ERR))
                    {
                        throw new CommPortException("IO Error [001]");
                    }
                    Marshal.WriteInt32(uMask, 0);
                    if (!Win32Com.WaitCommEvent(_hPort, uMask, unmanagedOv))
                    {
                        if (Marshal.GetLastWin32Error() == Win32Com.ERROR_IO_PENDING)
                        {
                            sg.WaitOne();
                        }
                        else
                        {
                            throw new CommPortException("IO Error [002]");
                        }
                    }
                    eventMask = (uint)Marshal.ReadInt32(uMask);
                    if ((eventMask & Win32Com.EV_ERR) != 0)
                    {
                        UInt32 errs;
                        if (Win32Com.ClearCommError(_hPort, out errs, IntPtr.Zero))
                        {
                            var s = new StringBuilder("UART Error: ", 40);
                            if ((errs & Win32Com.CE_FRAME) != 0) s = s.Append("Framing,");
                            if ((errs & Win32Com.CE_IOE) != 0) s = s.Append("IO,");
                            if ((errs & Win32Com.CE_OVERRUN) != 0) s = s.Append("Overrun,");
                            if ((errs & Win32Com.CE_RXOVER) != 0) s = s.Append("Receive Cverflow,");
                            if ((errs & Win32Com.CE_RXPARITY) != 0) s = s.Append("Parity,");
                            if ((errs & Win32Com.CE_TXFULL) != 0) s = s.Append("Transmit Overflow,");
                            s.Length = s.Length - 1;
                            throw new CommPortException(s.ToString());
                        }
                        throw new CommPortException("IO Error [003]");
                    }
                    if ((eventMask & Win32Com.EV_RXCHAR) != 0)
                    {
                        uint gotbytes;
                        do
                        {
                            if (!Win32Com.ReadFile(_hPort, buf, 1, out gotbytes, unmanagedOv))
                            {
                                if (Marshal.GetLastWin32Error() == Win32Com.ERROR_IO_PENDING)
                                {
                                    Win32Com.CancelIo(_hPort);
                                    gotbytes = 0;
                                }
                                else
                                {
                                    throw new CommPortException("IO Error [004]");
                                }
                            }
                            if (gotbytes == 1) OnRxChar(buf[0]);

                        } while (gotbytes > 0);
                    }
                    if ((eventMask & Win32Com.EV_TXEMPTY) != 0)
                    {
                        OnTxDone();
                    }
                    if ((eventMask & Win32Com.EV_BREAK) != 0) OnBreak();

                    uint i = 0;
                    if ((eventMask & Win32Com.EV_CTS) != 0) i |= Win32Com.MS_CTS_ON;
                    if ((eventMask & Win32Com.EV_DSR) != 0) i |= Win32Com.MS_DSR_ON;
                    if ((eventMask & Win32Com.EV_RLSD) != 0) i |= Win32Com.MS_RLSD_ON;
                    if ((eventMask & Win32Com.EV_RING) != 0) i |= Win32Com.MS_RING_ON;
                    if (i != 0)
                    {
                        uint f;
                        if (!Win32Com.GetCommModemStatus(_hPort, out f)) throw new CommPortException("IO Error [005]");
                        OnStatusChange(new ModemStatus(i), new ModemStatus(f));
                    }
                }
            }
            catch (Exception e)
            {
                if (uMask != IntPtr.Zero) Marshal.FreeHGlobal(uMask);
                if (unmanagedOv != IntPtr.Zero) Marshal.FreeHGlobal(unmanagedOv);
                if (!(e is ThreadAbortException))
                {
                    _rxException = e;
                    OnRxException(e);
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Opens the com port and configures it with the required settings
        /// </summary>
        /// <returns>false if the port could not be opened</returns>
        public bool Open()
        {
            var portDcb = new DCB();
            var commTimeouts = new COMMTIMEOUTS();
            var wo = new OVERLAPPED();

            if (_online) return false;

            _hPort = Win32Com.CreateFile(PortName, Win32Com.GENERIC_READ | Win32Com.GENERIC_WRITE, 0, IntPtr.Zero,
                Win32Com.OPEN_EXISTING, Win32Com.FILE_FLAG_OVERLAPPED, IntPtr.Zero);
            if (_hPort == (IntPtr)Win32Com.INVALID_HANDLE_VALUE)
            {
                if (Marshal.GetLastWin32Error() == Win32Com.ERROR_ACCESS_DENIED)
                {
                    return false;
                }
                throw new CommPortException("Port Open Failure");
            }

            _online = true;

            commTimeouts.ReadIntervalTimeout = 0;
            commTimeouts.ReadTotalTimeoutConstant = 0;
            commTimeouts.ReadTotalTimeoutMultiplier = 0;
            commTimeouts.WriteTotalTimeoutConstant = SendTimeoutConstant;
            commTimeouts.WriteTotalTimeoutMultiplier = SendTimeoutMultiplier;
            portDcb.Init(((Parity == Parity.Odd) || (Parity == Parity.Even)), TxFlowCts, TxFlowDsr,
                (int)UseDtr, RxGateDsr, !TxWhenRxXoff, TxFlowX, RxFlowX, (int)UseRts);
            portDcb.BaudRate = BaudRate;
            portDcb.ByteSize = (byte)DataBits;
            portDcb.Parity = (byte)Parity;
            portDcb.StopBits = (byte)StopBits;
            portDcb.XoffChar = (byte)XoffChar;
            portDcb.XonChar = (byte)XonChar;
            portDcb.XoffLim = (short)RxHighWater;
            portDcb.XonLim = (short)RxLowWater;
            if ((RxQueue != 0) || (TxQueue != 0))
                if (!Win32Com.SetupComm(_hPort, (uint)RxQueue, (uint)TxQueue)) ThrowException("Bad queue settings");
            if (!Win32Com.SetCommState(_hPort, ref portDcb)) ThrowException("Bad com settings");
            if (!Win32Com.SetCommTimeouts(_hPort, ref commTimeouts)) ThrowException("Bad timeout settings");

            _stateBrk = 0;
            if (UseDtr == HsOutput.None) _stateDtr = 0;
            if (UseDtr == HsOutput.Online) _stateDtr = 1;
            if (UseRts == HsOutput.None) _stateRts = 0;
            if (UseRts == HsOutput.Online) _stateRts = 1;

            _checkSends = CheckAllSends;
            wo.Offset = 0;
            wo.OffsetHigh = 0;
            wo.hEvent = _checkSends ? _writeEvent.Handle : IntPtr.Zero;
            _ptrUwo = Marshal.AllocHGlobal(Marshal.SizeOf(wo));
            Marshal.StructureToPtr(wo, _ptrUwo, true);
            _writeCount = 0;

            _rxException = null;
            _rxExceptionReported = false;
            _rxThread = new Thread(ReceiveThread)
                            {
                                Name = "CommBaseRx",
                                Priority = ThreadPriority.AboveNormal
                            };
            _rxThread.Start();
            Thread.Sleep(1); //Give rx thread time to start. By documentation, 0 should work, but it does not!

            _auto = false;
            if (AfterOpen())
            {
                _auto = AutoReopen;
                return true;
            }
            Close();
            return false;
        }