Beispiel #1
0
        /// <summary>
        /// Gets the status of the modem control input signals.
        /// </summary>
        /// <returns>Modem status object</returns>
        protected ModemStatus GetModemStatus()
        {
            uint f;

            CheckOnline();
            if (!Win32Com.GetCommModemStatus(_hPort, out f))
            {
                ThrowException("Unexpected failure");
            }
            return(new ModemStatus(f));
        }
Beispiel #2
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);
                }
            }
        }
Beispiel #3
0
        private void ReceiveSendThreadSerial()
        {
            var buffer           = new byte[64];
            var restart          = false;
            var sendMessageBytes = new byte[0];
            int sentBytes        = 0;
            var sendTimeout      = new Stopwatch();
            var portHandle       = IntPtr.Zero;

            Thread.Sleep(1000);
            _receivedBytes.Clear();
            var resetEvent    = new AutoResetEvent(false);
            var overlapped    = new OVERLAPPED();
            var ptrOverlapped = Marshal.AllocHGlobal(Marshal.SizeOf(overlapped));

            overlapped.Offset     = 0;
            overlapped.OffsetHigh = 0;
            overlapped.hEvent     = resetEvent.SafeWaitHandle.DangerousGetHandle();
            Marshal.StructureToPtr(overlapped, ptrOverlapped, true);
            bool waitingRead        = false;
            var  writeResetEvent    = new AutoResetEvent(false);
            var  writeOverlapped    = new OVERLAPPED();
            var  ptrWriteOverlapped = Marshal.AllocHGlobal(Marshal.SizeOf(writeOverlapped));

            writeOverlapped.Offset     = 0;
            writeOverlapped.OffsetHigh = 0;
            writeOverlapped.hEvent     = writeResetEvent.SafeWaitHandle.DangerousGetHandle();;
            Marshal.StructureToPtr(writeOverlapped, ptrWriteOverlapped, true);
            bool waitingWrite = false;

            while (!_receiveSendThreadStopped)
            {
                try
                {
                    if (portHandle == IntPtr.Zero)
                    {
                        int    portnumber = Int32.Parse(_comPort.Replace("COM", String.Empty));
                        string comPort    = _comPort;
                        if (portnumber > 9)
                        {
                            comPort = String.Format("\\\\.\\{0}", _comPort);
                        }
                        portHandle = Win32Com.CreateFile(comPort, Win32Com.GENERIC_READ | Win32Com.GENERIC_WRITE, 0, IntPtr.Zero,
                                                         Win32Com.OPEN_EXISTING, Win32Com.FILE_FLAG_OVERLAPPED, IntPtr.Zero);

                        if (portHandle == (IntPtr)Win32Com.INVALID_HANDLE_VALUE)
                        {
                            if (Marshal.GetLastWin32Error() == Win32Com.ERROR_ACCESS_DENIED)
                            {
                                throw new Exception(String.Format("Access denied for port {0}", _comPort));
                            }
                            else
                            {
                                throw new Exception(String.Format("Failed to open port {0}", _comPort));
                            }
                        }

                        COMMTIMEOUTS commTimeouts = new COMMTIMEOUTS
                        {
                            ReadIntervalTimeout         = 5,
                            ReadTotalTimeoutConstant    = 0,
                            ReadTotalTimeoutMultiplier  = 0,
                            WriteTotalTimeoutConstant   = 0,
                            WriteTotalTimeoutMultiplier = 0
                        };
                        DCB dcb = new DCB();
                        dcb.Init(false, false, false, 0, false, false, false, false, 0);
                        dcb.BaudRate = _baudRate;
                        dcb.ByteSize = 8;
                        dcb.Parity   = 0;
                        dcb.StopBits = 0;
                        if (!Win32Com.SetupComm(portHandle, 8192, 4096))
                        {
                            throw new Exception(String.Format("Failed to set queue settings for port {0}", _comPort));
                        }
                        if (!Win32Com.SetCommState(portHandle, ref dcb))
                        {
                            throw new Exception(String.Format("Failed to set comm settings for port {0}", _comPort));
                        }
                        if (!Win32Com.SetCommTimeouts(portHandle, ref commTimeouts))
                        {
                            throw new Exception(String.Format("Failed to set comm timeouts for port {0}", _comPort));
                        }
                        if (_rtsCts)
                        {
                            if (!Win32Com.EscapeCommFunction(portHandle, Win32Com.CLRRTS))
                            {
                                throw new Exception(String.Format("Failed to reset RTS pin{0}", _comPort));
                            }
                        }
                        Thread.Sleep(1000);
                    }

                    if (!Win32Com.GetHandleInformation(portHandle, out uint lpdwFlags))
                    {
                        throw new Exception(String.Format("Port {0} went offline", _comPort));
                    }

                    if (!waitingRead)
                    {
                        waitingRead = true;
                        if (!Win32Com.ReadFile(portHandle, buffer, (uint)buffer.Length, out uint readBytes, ptrOverlapped))
                        {
                            if (Marshal.GetLastWin32Error() != Win32Com.ERROR_IO_PENDING)
                            {
                                throw new Exception(String.Format("Failed to read port {0}", _comPort));
                            }
                        }
                    }
                    else
                    {
                        if (resetEvent.WaitOne(10))
                        {
                            waitingRead = false;
                            if (!Win32Com.GetOverlappedResult(portHandle, ptrOverlapped, out uint readBytes, false))
                            {
                                throw new Exception(String.Format("Failed to read port {0}", _comPort));
                            }

                            for (int i = 0; i < readBytes; i++)
                            {
                                _receivedBytes.Add(buffer[i]);
                            }
                        }
                    }

                    if (_sendMessageQueue.Count > 0 && sendMessageBytes.Length == 0)
                    {
                        lock (_syncobject)
                            sendMessageBytes = _sendMessageQueue.Dequeue();
                        sentBytes = 0;
                    }

                    if (sendMessageBytes.Length > 0)
                    {
                        if (_rtsCts)
                        {
                            if (!Win32Com.EscapeCommFunction(portHandle, Win32Com.SETRTS))
                            {
                                lock (_syncobject)
                                    _sendExceptionQueue.Enqueue(new SBPSendExceptionEventArgs(new Exception(String.Format("Failed to set RTS pin{0}", _comPort))));
                            }
                        }

                        uint lpmodemstat = 0;
                        if (_rtsCts)
                        {
                            if (!Win32Com.GetCommModemStatus(portHandle, out lpmodemstat))
                            {
                                _sendExceptionQueue.Enqueue(new SBPSendExceptionEventArgs(new Exception(String.Format("Failed to get RTS pin{0}", _comPort))));
                            }
                        }

                        if ((lpmodemstat & Win32Com.MS_CTS_ON) > 0 || !_rtsCts)
                        {
                            if (!waitingWrite)
                            {
                                waitingWrite = true;
                                sendTimeout.Restart();
                                if (!Win32Com.WriteFile(portHandle, sendMessageBytes, (uint)sendMessageBytes.Length, out uint sent, ptrWriteOverlapped))
                                {
                                    if (Marshal.GetLastWin32Error() != Win32Com.ERROR_IO_PENDING)
                                    {
                                        _sendExceptionQueue.Enqueue(new SBPSendExceptionEventArgs(new Exception(String.Format("Failed to write to port {0}", _comPort))));
                                    }
                                }
                            }
                            else
                            {
                                if (writeResetEvent.WaitOne(0))
                                {
                                    if (!Win32Com.GetOverlappedResult(portHandle, ptrWriteOverlapped, out uint sent, false))
                                    {
                                        _sendExceptionQueue.Enqueue(new SBPSendExceptionEventArgs(new Exception(String.Format("Failed to write to port {0}", _comPort))));
                                    }

                                    sentBytes += (int)sent;
                                }
                            }

                            if (sentBytes == sendMessageBytes.Length || sendTimeout.ElapsedMilliseconds > 200)
                            {
                                if (sendTimeout.ElapsedMilliseconds > 100)
                                {
                                    lock (_syncobject)
                                        _sendExceptionQueue.Enqueue(new SBPSendExceptionEventArgs(new Exception(String.Format("Failed to write all bytes to port {0}", _comPort))));
                                }

                                if (_rtsCts)
                                {
                                    if (!Win32Com.EscapeCommFunction(portHandle, Win32Com.CLRRTS))
                                    {
                                        lock (_syncobject)
                                            _sendExceptionQueue.Enqueue(new SBPSendExceptionEventArgs(new Exception(String.Format("Failed to reset RTS pin{0}", _comPort))));
                                    }
                                }

                                sendMessageBytes = new byte[0];
                                waitingWrite     = false;
                            }
                        }
                    }

                    ProcessReading(restart);
                    restart = false;
                }
                catch (Exception e)
                {
                    _receivedBytes.Clear();
                    Win32Com.CancelIo(portHandle);
                    Win32Com.CloseHandle(portHandle);
                    portHandle = IntPtr.Zero;
                    restart    = true;
                    lock (_syncobject)
                        _readExceptionQueue.Enqueue(new SBPReadExceptionEventArgs(e));

                    Thread.Sleep(5000);
                }
            }

            Win32Com.CancelIo(portHandle);
            Win32Com.CloseHandle(portHandle);
            Marshal.FreeHGlobal(ptrOverlapped);
            Marshal.FreeHGlobal(ptrWriteOverlapped);
        }