示例#1
0
文件: Port.cs 项目: boblucas/Miller
        /// <summary>
        /// Open the current port
        /// </summary>
        /// <returns>true if successful, false if it fails</returns>
        public bool Open()
        {
            if(isOpen) return false;

            if(CommAPI.FullFramework)
            {
                // set up the overlapped tx IO
                //				AutoResetEvent are = new AutoResetEvent(false);
                OVERLAPPED o = new OVERLAPPED();
                txOverlapped = LocalAlloc(0x40, Marshal.SizeOf(o));
                o.Offset = 0;
                o.OffsetHigh = 0;
                o.hEvent = IntPtr.Zero;
                Marshal.StructureToPtr(o, txOverlapped, true);
            }

            hPort = m_CommAPI.CreateFile(portName);

            if(hPort == (IntPtr)CommAPI.INVALID_HANDLE_VALUE)
            {
                int e = Marshal.GetLastWin32Error();

                if(e == (int)APIErrors.ERROR_ACCESS_DENIED)
                {
                    // port is unavailable
                    return false;
                }

                // ClearCommError failed!
                string error = String.Format("CreateFile Failed: {0}", e);
                throw new CommPortException(error);
            }

            isOpen = true;

            // set queue sizes
            m_CommAPI.SetupComm(hPort, rxBufferSize, txBufferSize);

            // transfer the port settings to a DCB structure
            dcb.BaudRate = (uint)portSettings.BasicSettings.BaudRate;
            dcb.ByteSize = portSettings.BasicSettings.ByteSize;
            dcb.EofChar = (sbyte)portSettings.EOFChar;
            dcb.ErrorChar = (sbyte)portSettings.ErrorChar;
            dcb.EvtChar = (sbyte)portSettings.EVTChar;
            dcb.fAbortOnError = portSettings.AbortOnError;
            dcb.fBinary = true;
            dcb.fDsrSensitivity = portSettings.DSRSensitive;
            dcb.fDtrControl = (DCB.DtrControlFlags)portSettings.DTRControl;
            dcb.fErrorChar = portSettings.ReplaceErrorChar;
            dcb.fInX = portSettings.InX;
            dcb.fNull = portSettings.DiscardNulls;
            dcb.fOutX = portSettings.OutX;
            dcb.fOutxCtsFlow = portSettings.OutCTS;
            dcb.fOutxDsrFlow = portSettings.OutDSR;
            dcb.fParity = (portSettings.BasicSettings.Parity == Parity.none) ? false : true;
            dcb.fRtsControl = (DCB.RtsControlFlags)portSettings.RTSControl;
            dcb.fTXContinueOnXoff = portSettings.TxContinueOnXOff;
            dcb.Parity = (byte)portSettings.BasicSettings.Parity;

            dcb.StopBits = (byte)portSettings.BasicSettings.StopBits;
            dcb.XoffChar = (sbyte)portSettings.XoffChar;
            dcb.XonChar = (sbyte)portSettings.XonChar;

            dcb.XonLim = dcb.XoffLim = (ushort)(rxBufferSize / 10);

            m_CommAPI.SetCommState(hPort, dcb);

            // store some state values
            brk = 0;
            dtr = dcb.fDtrControl == DCB.DtrControlFlags.Enable ? 1 : 0;
            rts = dcb.fRtsControl == DCB.RtsControlFlags.Enable ? 1 : 0;

            // set the Comm timeouts
            CommTimeouts ct = new CommTimeouts();

            // reading we'll return immediately
            // this doesn't seem to work as documented
            ct.ReadIntervalTimeout = uint.MaxValue; // this = 0xffffffff
            ct.ReadTotalTimeoutConstant = 0;
            ct.ReadTotalTimeoutMultiplier = 0;

            // writing we'll give 5 seconds
            ct.WriteTotalTimeoutConstant = 5000;
            ct.WriteTotalTimeoutMultiplier = 0;

            m_CommAPI.SetCommTimeouts(hPort, ct);

            // read the ports capabilities
            bool status=GetPortProperties();

            // start the receive thread
            eventThread = new Thread(new ThreadStart(CommEventThread));
            eventThread.Priority = ThreadPriority.Highest;
            eventThread.Start();

            // wait for the thread to actually get spun up
            threadStarted.WaitOne();

            return true;
        }
示例#2
0
文件: Port.cs 项目: boblucas/Miller
        private void CommEventThread()
        {
            CommEventFlags	eventFlags	= new CommEventFlags();
            byte[]			readbuffer	= new Byte[rxBufferSize];
            int				bytesread	= 0;
            AutoResetEvent	rxevent		= new AutoResetEvent(false);

            // specify the set of events to be monitored for the port.
            if(CommAPI.FullFramework)
            {
                m_CommAPI.SetCommMask(hPort, CommEventFlags.ALLPC);

                // set up the overlapped IO
                OVERLAPPED o = new OVERLAPPED();
                rxOverlapped = LocalAlloc(0x40, Marshal.SizeOf(o));
                o.Offset = 0;
                o.OffsetHigh = 0;
                o.hEvent = rxevent.Handle;
                Marshal.StructureToPtr(o, rxOverlapped, true);
            }
            else
            {
                m_CommAPI.SetCommMask(hPort, CommEventFlags.ALLCE);
            }

            try
            {
                // let Open() know we're started
                threadStarted.Set();

                #region >>>> thread loop <<<<
                while(hPort != (IntPtr)CommAPI.INVALID_HANDLE_VALUE)
                {
                    // wait for a Comm event
                    if(!m_CommAPI.WaitCommEvent(hPort, ref eventFlags))
                    {
                        int e = Marshal.GetLastWin32Error();

                        if(e == (int)APIErrors.ERROR_IO_PENDING)
                        {
                            // IO pending so just wait and try again
                            rxevent.WaitOne();
                            Thread.Sleep(0);
                            continue;
                        }

                        if(e == (int)APIErrors.ERROR_INVALID_HANDLE)
                        {
                            // Calling Port.Close() causes hPort to become invalid
                            // Since Thread.Abort() is unsupported in the CF, we must
                            // accept that calling Close will throw an error here.

                            // Close signals the closeEvent, so wait on it
                            // We wait 1 second, though Close should happen much sooner
                            int eventResult = m_CommAPI.WaitForSingleObject(closeEvent, 1000);

                            if(eventResult == (int)APIConstants.WAIT_OBJECT_0)
                            {
                                // the event was set so close was called
                                hPort = (IntPtr)CommAPI.INVALID_HANDLE_VALUE;

                                // reset our ResetEvent for the next call to Open
                                threadStarted.Reset();

                                if(isOpen) // this should not be the case...if so, throw an exception for the owner
                                {
                                    string error = String.Format("Wait Failed: {0}", e);
                                    throw new CommPortException(error);
                                }

                                return;
                            }
                        }

                        // WaitCommEvent failed
                        // 995 means an exit was requested (thread killed)
                        if(e == 995)
                        {
                            return;
                        }
                        else
                        {
                            string error = String.Format("Wait Failed: {0}", e);
                            throw new CommPortException(error);
                        }
                    }

                    // Re-specify the set of events to be monitored for the port.
                    if(CommAPI.FullFramework)
                    {
                        m_CommAPI.SetCommMask(hPort, CommEventFlags.ALLPC);
                    }
                    else
                    {
                        m_CommAPI.SetCommMask(hPort, CommEventFlags.ALLCE);
                    }

                    // check the event for errors
                    #region >>>> error checking <<<<
                    if(((uint)eventFlags & (uint)CommEventFlags.ERR) != 0)
                    {
                        CommErrorFlags errorFlags = new CommErrorFlags();
                        CommStat commStat = new CommStat();

                        // get the error status
                        if(!m_CommAPI.ClearCommError(hPort, ref errorFlags, commStat))
                        {
                            // ClearCommError failed!
                            string error = String.Format("ClearCommError Failed: {0}", Marshal.GetLastWin32Error());
                            throw new CommPortException(error);
                        }

                        if(((uint)errorFlags & (uint)CommErrorFlags.BREAK) != 0)
                        {
                            // BREAK can set an error, so make sure the BREAK bit is set an continue
                            eventFlags |= CommEventFlags.BREAK;
                        }
                        else
                        {
                            // we have an error.  Build a meaningful string and throw an exception
                            StringBuilder s = new StringBuilder("UART Error: ", 80);
                            if ((errorFlags & CommErrorFlags.FRAME) != 0)
                            { s = s.Append("Framing,");	}
                            if ((errorFlags & CommErrorFlags.IOE) != 0)
                            { s = s.Append("IO,"); }
                            if ((errorFlags & CommErrorFlags.OVERRUN) != 0)
                            { s = s.Append("Overrun,"); }
                            if ((errorFlags & CommErrorFlags.RXOVER) != 0)
                            { s = s.Append("Receive Overflow,"); }
                            if ((errorFlags & CommErrorFlags.RXPARITY) != 0)
                            { s = s.Append("Parity,"); }
                            if ((errorFlags & CommErrorFlags.TXFULL) != 0)
                            { s = s.Append("Transmit Overflow,"); }

                            // no known bits are set
                            if(s.Length == 12)
                            { s = s.Append("Unknown"); }

                            // raise an error event
                            if(OnError != null)
                                OnError(s.ToString());

                            continue;
                        }
                    } // if(((uint)eventFlags & (uint)CommEventFlags.ERR) != 0)
                    #endregion

                    #region >>>> Receive data subsection <<<<
                    // check for RXCHAR
                    if((eventFlags & CommEventFlags.RXCHAR) != 0)
                    {
                        do
                        {
                            // make sure the port handle is valid
                            if(hPort == (IntPtr)CommAPI.INVALID_HANDLE_VALUE)
                            {
                                bytesread = 0;
                                break;
                            }

                            // data came in, put it in the buffer and set the event
                            if (!m_CommAPI.ReadFile(hPort, readbuffer, rxBufferSize, ref bytesread, rxOverlapped))
                            {
                                string errString = String.Format("ReadFile Failed: {0}", Marshal.GetLastWin32Error());
                                if(OnError != null)
                                    OnError(errString);

                                return;
                            }
                            if (bytesread >= 1)
                            {
                                // take the mutex
                                rxBufferBusy.WaitOne();

                                // put the data into the fifo
                                // this *may*  be a perf problem and needs testing
                                for(int b = 0 ; b < bytesread ; b++)
                                    rxFIFO.Enqueue(readbuffer[b]);

                                // get the FIFO length
                                int fifoLength = rxFIFO.Count;

                                // release the mutex
                                rxBufferBusy.ReleaseMutex();

                                // fire the DataReceived event every RThreshold bytes
                                if((DataReceived != null) && (rthreshold != 0) && (fifoLength >= rthreshold))
                                {
                                    DataReceived();
                                }
                            }
                        } while (bytesread > 0);
                    } // if((eventFlags & CommEventFlags.RXCHAR) != 0)
                    #endregion

                    #region >>>> line status checking <<<<
                    // check for status changes
                    uint status = 0;
                    m_CommAPI.GetCommModemStatus(hPort, ref status);

                    // check the CTS
                    if(((uint)eventFlags & (uint)CommEventFlags.CTS) != 0)
                    {
                        if(CTSChange != null)
                            CTSChange((status & (uint)CommModemStatusFlags.MS_CTS_ON) != 0);
                    }

                    // check the DSR
                    if(((uint)eventFlags & (uint)CommEventFlags.DSR) != 0)
                    {
                        if(DSRChange != null)
                            DSRChange((status & (uint)CommModemStatusFlags.MS_DSR_ON) != 0);
                    }

                    // check for a RING
                    if(((uint)eventFlags & (uint)CommEventFlags.RING) != 0)
                    {
                        if(RingChange != null)
                            RingChange((status & (uint)CommModemStatusFlags.MS_RING_ON) != 0);
                    }

                    // check for a RLSD
                    if(((uint)eventFlags & (uint)CommEventFlags.RLSD) != 0)
                    {
                        if(RLSDChange != null)
                            RLSDChange((status & (uint)CommModemStatusFlags.MS_RLSD_ON) != 0);
                    }

                    // check for TXEMPTY
                    if(((uint)eventFlags & (uint)CommEventFlags.TXEMPTY) != 0)
                        if(TxDone != null) { TxDone(); }

                    // check for RXFLAG
                    if(((uint)eventFlags & (uint)CommEventFlags.RXFLAG) != 0)
                        if(FlagCharReceived != null) { FlagCharReceived(); }

                    // check for POWER
                    if(((uint)eventFlags & (uint)CommEventFlags.POWER) != 0)
                        if(PowerEvent != null) { PowerEvent(); }

                    // check for high-water state
                    if((eventFlags & CommEventFlags.RX80FULL) != 0)
                        if(HighWater != null) { HighWater(); }
                    #endregion
                } // while(true)
                #endregion
            } // try
            catch(Exception e)
            {
                if(rxOverlapped != IntPtr.Zero)
                    LocalFree(rxOverlapped);

                if(OnError != null)
                    OnError(e.Message);

                return;
            }
        }
示例#3
0
        /// <summary>
        /// Open the current port
        /// </summary>
        /// <returns>true if successful, false if it fails</returns>
        public bool Open()
        {
            if (isOpen)
            {
                return(false);
            }

            if (CommAPI.FullFramework)
            {
                // set up the overlapped tx IO
                //				AutoResetEvent are = new AutoResetEvent(false);
                OVERLAPPED o = new OVERLAPPED();
                txOverlapped = LocalAlloc(0x40, Marshal.SizeOf(o));
                o.Offset     = 0;
                o.OffsetHigh = 0;
                o.hEvent     = IntPtr.Zero;
                Marshal.StructureToPtr(o, txOverlapped, true);
            }

            hPort = m_CommAPI.CreateFile(portName);

            if (hPort == (IntPtr)CommAPI.INVALID_HANDLE_VALUE)
            {
                int e = Marshal.GetLastWin32Error();

                if (e == (int)APIErrors.ERROR_ACCESS_DENIED)
                {
                    // port is unavailable
                    return(false);
                }

                // ClearCommError failed!
                string error = String.Format("CreateFile Failed: {0}", e);
                throw new CommPortException(error);
            }


            isOpen = true;

            // set queue sizes
            m_CommAPI.SetupComm(hPort, rxBufferSize, txBufferSize);

            // transfer the port settings to a DCB structure
            dcb.BaudRate          = (uint)portSettings.BasicSettings.BaudRate;
            dcb.ByteSize          = portSettings.BasicSettings.ByteSize;
            dcb.EofChar           = (sbyte)portSettings.EOFChar;
            dcb.ErrorChar         = (sbyte)portSettings.ErrorChar;
            dcb.EvtChar           = (sbyte)portSettings.EVTChar;
            dcb.fAbortOnError     = portSettings.AbortOnError;
            dcb.fBinary           = true;
            dcb.fDsrSensitivity   = portSettings.DSRSensitive;
            dcb.fDtrControl       = (byte)portSettings.DTRControl;
            dcb.fErrorChar        = portSettings.ReplaceErrorChar;
            dcb.fInX              = portSettings.InX;
            dcb.fNull             = portSettings.DiscardNulls;
            dcb.fOutX             = portSettings.OutX;
            dcb.fOutxCtsFlow      = portSettings.OutCTS;
            dcb.fOutxDsrFlow      = portSettings.OutDSR;
            dcb.fParity           = (portSettings.BasicSettings.Parity == Parity.none) ? false : true;
            dcb.fRtsControl       = (byte)portSettings.RTSControl;
            dcb.fTXContinueOnXoff = portSettings.TxContinueOnXOff;
            dcb.Parity            = (byte)portSettings.BasicSettings.Parity;

            dcb.StopBits = (byte)portSettings.BasicSettings.StopBits;
            dcb.XoffChar = (sbyte)portSettings.XoffChar;
            dcb.XonChar  = (sbyte)portSettings.XonChar;

            dcb.XonLim = dcb.XoffLim = (ushort)(rxBufferSize / 10);

            m_CommAPI.SetCommState(hPort, dcb);

            // store some state values
            brk = 0;
            dtr = dcb.fDtrControl == (byte)DCB.DtrControlFlags.Enable ? 1 : 0;
            rts = dcb.fRtsControl == (byte)DCB.RtsControlFlags.Enable ? 1 : 0;

            // set the Comm timeouts
            CommTimeouts ct = new CommTimeouts();

            // reading we'll return immediately
            // this doesn't seem to work as documented
            ct.ReadIntervalTimeout        = uint.MaxValue;      // this = 0xffffffff
            ct.ReadTotalTimeoutConstant   = 0;
            ct.ReadTotalTimeoutMultiplier = 0;

            // writing we'll give 5 seconds
            ct.WriteTotalTimeoutConstant   = 5000;
            ct.WriteTotalTimeoutMultiplier = 0;

            m_CommAPI.SetCommTimeouts(hPort, ct);

            // read the ports capabilities
            bool status = GetPortProperties();

            // start the receive thread
            eventThread          = new Thread(new ThreadStart(CommEventThread));
            eventThread.Priority = ThreadPriority.Highest;
            eventThread.Start();

            // wait for the thread to actually get spun up
            threadStarted.WaitOne();

            return(true);
        }
示例#4
0
        private void CommEventThread()
        {
            CommEventFlags eventFlags = new CommEventFlags();

            byte[]         readbuffer = new Byte[rxBufferSize];
            int            bytesread  = 0;
            AutoResetEvent rxevent    = new AutoResetEvent(false);

            // specify the set of events to be monitored for the port.
            if (CommAPI.FullFramework)
            {
                m_CommAPI.SetCommMask(hPort, CommEventFlags.ALLPC);

                // set up the overlapped IO
                OVERLAPPED o = new OVERLAPPED();
                rxOverlapped = LocalAlloc(0x40, Marshal.SizeOf(o));
                o.Offset     = 0;
                o.OffsetHigh = 0;
                o.hEvent     = rxevent.Handle;
                Marshal.StructureToPtr(o, rxOverlapped, true);
            }
            else
            {
                m_CommAPI.SetCommMask(hPort, CommEventFlags.ALLCE);
            }


            try
            {
                // let Open() know we're started
                threadStarted.Set();

                #region >>>> thread loop <<<<
                while (hPort != (IntPtr)CommAPI.INVALID_HANDLE_VALUE)
                {
                    // wait for a Comm event
                    if (!m_CommAPI.WaitCommEvent(hPort, ref eventFlags))
                    {
                        int e = Marshal.GetLastWin32Error();

                        if (e == (int)APIErrors.ERROR_IO_PENDING)
                        {
                            // IO pending so just wait and try again
                            rxevent.WaitOne();
                            Thread.Sleep(0);
                            continue;
                        }

                        if (e == (int)APIErrors.ERROR_INVALID_HANDLE)
                        {
                            // Calling Port.Close() causes hPort to become invalid
                            // Since Thread.Abort() is unsupported in the CF, we must
                            // accept that calling Close will throw an error here.

                            // Close signals the closeEvent, so wait on it
                            // We wait 1 second, though Close should happen much sooner
                            int eventResult = m_CommAPI.WaitForSingleObject(closeEvent, 1000);

                            if (eventResult == (int)APIConstants.WAIT_OBJECT_0)
                            {
                                // the event was set so close was called
                                hPort = (IntPtr)CommAPI.INVALID_HANDLE_VALUE;

                                // reset our ResetEvent for the next call to Open
                                threadStarted.Reset();

                                if (isOpen)                                // this should not be the case...if so, throw an exception for the owner
                                {
                                    string error = String.Format("Wait Failed: {0}", e);
                                    throw new CommPortException(error);
                                }

                                return;
                            }
                        }

                        // WaitCommEvent failed
                        // 995 means an exit was requested (thread killed)
                        if (e == 995)
                        {
                            return;
                        }
                        else
                        {
                            string error = String.Format("Wait Failed: {0}", e);
                            throw new CommPortException(error);
                        }
                    }

                    // Re-specify the set of events to be monitored for the port.
                    if (CommAPI.FullFramework)
                    {
                        m_CommAPI.SetCommMask(hPort, CommEventFlags.ALLPC);
                    }
                    else
                    {
                        m_CommAPI.SetCommMask(hPort, CommEventFlags.ALLCE);
                    }

                    // check the event for errors
                    #region >>>> error checking <<<<
                    if (((uint)eventFlags & (uint)CommEventFlags.ERR) != 0)
                    {
                        CommErrorFlags errorFlags = new CommErrorFlags();
                        CommStat       commStat   = new CommStat();

                        // get the error status
                        if (!m_CommAPI.ClearCommError(hPort, ref errorFlags, commStat))
                        {
                            // ClearCommError failed!
                            string error = String.Format("ClearCommError Failed: {0}", Marshal.GetLastWin32Error());
                            throw new CommPortException(error);
                        }

                        if (((uint)errorFlags & (uint)CommErrorFlags.BREAK) != 0)
                        {
                            // BREAK can set an error, so make sure the BREAK bit is set an continue
                            eventFlags |= CommEventFlags.BREAK;
                        }
                        else
                        {
                            // we have an error.  Build a meaningful string and throw an exception
                            StringBuilder s = new StringBuilder("UART Error: ", 80);
                            if ((errorFlags & CommErrorFlags.FRAME) != 0)
                            {
                                s = s.Append("Framing,");
                            }
                            if ((errorFlags & CommErrorFlags.IOE) != 0)
                            {
                                s = s.Append("IO,");
                            }
                            if ((errorFlags & CommErrorFlags.OVERRUN) != 0)
                            {
                                s = s.Append("Overrun,");
                            }
                            if ((errorFlags & CommErrorFlags.RXOVER) != 0)
                            {
                                s = s.Append("Receive Overflow,");
                            }
                            if ((errorFlags & CommErrorFlags.RXPARITY) != 0)
                            {
                                s = s.Append("Parity,");
                            }
                            if ((errorFlags & CommErrorFlags.TXFULL) != 0)
                            {
                                s = s.Append("Transmit Overflow,");
                            }

                            // no known bits are set
                            if (s.Length == 12)
                            {
                                s = s.Append("Unknown");
                            }

                            // raise an error event
                            if (OnError != null)
                            {
                                OnError(s.ToString());
                            }

                            continue;
                        }
                    }                     // if(((uint)eventFlags & (uint)CommEventFlags.ERR) != 0)
                    #endregion

                    #region >>>> Receive data subsection <<<<
                    // check for RXCHAR
                    if ((eventFlags & CommEventFlags.RXCHAR) != 0)
                    {
                        do
                        {
                            // make sure the port handle is valid
                            if (hPort == (IntPtr)CommAPI.INVALID_HANDLE_VALUE)
                            {
                                bytesread = 0;
                                break;
                            }

                            // data came in, put it in the buffer and set the event
                            if (!m_CommAPI.ReadFile(hPort, readbuffer, rxBufferSize, ref bytesread, rxOverlapped))
                            {
                                if (Marshal.GetLastWin32Error() == CommAPI.ERROR_IO_PENDING)
                                {
                                    // Thanks to Geoff McIlraith:
                                    // Read operation was not completed on ReadFile call...block until
                                    // complete, and grab result.
                                    if (!m_CommAPI.GetOverlappedResult(hPort, rxOverlapped, out bytesread, true))
                                    {
                                        string errString = String.Format("GetOverlappedResult Failed: {0}", Marshal.GetLastWin32Error());
                                        if (OnError != null)
                                        {
                                            OnError(errString);
                                        }

                                        return;
                                    }
                                }
                                else
                                {
                                    string errString = String.Format("ReadFile Failed: {0}", Marshal.GetLastWin32Error());
                                    if (OnError != null)
                                    {
                                        OnError(errString);
                                    }

                                    return;
                                }
                            }
                            if (bytesread >= 1)
                            {
                                // take the mutex
                                rxBufferBusy.WaitOne();

                                // put the data into the fifo
                                // this *may*  be a perf problem and needs testing
                                for (int b = 0; b < bytesread; b++)
                                {
                                    rxFIFO.Enqueue(readbuffer[b]);
                                }

                                // get the FIFO length
                                int fifoLength = rxFIFO.Count;

                                // release the mutex
                                rxBufferBusy.ReleaseMutex();

                                // fire the DataReceived event every RThreshold bytes
                                if ((DataReceived != null) && (rthreshold != 0) && (fifoLength >= rthreshold))
                                {
                                    DataReceived();
                                }
                            }
                        } while (bytesread > 0);
                    }                     // if((eventFlags & CommEventFlags.RXCHAR) != 0)
                    #endregion

                    #region >>>> line status checking <<<<
                    // check for status changes
                    uint status = 0;
                    m_CommAPI.GetCommModemStatus(hPort, ref status);

                    // check the CTS
                    if (((uint)eventFlags & (uint)CommEventFlags.CTS) != 0)
                    {
                        if (CTSChange != null)
                        {
                            CTSChange((status & (uint)CommModemStatusFlags.MS_CTS_ON) != 0);
                        }
                    }

                    // check the DSR
                    if (((uint)eventFlags & (uint)CommEventFlags.DSR) != 0)
                    {
                        if (DSRChange != null)
                        {
                            DSRChange((status & (uint)CommModemStatusFlags.MS_DSR_ON) != 0);
                        }
                    }

                    // check for a RING
                    if (((uint)eventFlags & (uint)CommEventFlags.RING) != 0)
                    {
                        if (RingChange != null)
                        {
                            RingChange((status & (uint)CommModemStatusFlags.MS_RING_ON) != 0);
                        }
                    }

                    // check for a RLSD
                    if (((uint)eventFlags & (uint)CommEventFlags.RLSD) != 0)
                    {
                        if (RLSDChange != null)
                        {
                            RLSDChange((status & (uint)CommModemStatusFlags.MS_RLSD_ON) != 0);
                        }
                    }

                    // check for TXEMPTY
                    if (((uint)eventFlags & (uint)CommEventFlags.TXEMPTY) != 0)
                    {
                        if (TxDone != null)
                        {
                            TxDone();
                        }
                    }

                    // check for RXFLAG
                    if (((uint)eventFlags & (uint)CommEventFlags.RXFLAG) != 0)
                    {
                        if (FlagCharReceived != null)
                        {
                            FlagCharReceived();
                        }
                    }

                    // check for POWER
                    if (((uint)eventFlags & (uint)CommEventFlags.POWER) != 0)
                    {
                        if (PowerEvent != null)
                        {
                            PowerEvent();
                        }
                    }

                    // check for high-water state
                    if ((eventFlags & CommEventFlags.RX80FULL) != 0)
                    {
                        if (HighWater != null)
                        {
                            HighWater();
                        }
                    }
                    #endregion
                }         // while(true)
                #endregion
            }             // try
            catch (Exception e)
            {
                if (rxOverlapped != IntPtr.Zero)
                {
                    LocalFree(rxOverlapped);
                }

                if (OnError != null)
                {
                    OnError(e.Message);
                }

                return;
            }
        }
示例#5
0
		/// <summary>
		/// Opens a new serial port connection.
		/// </summary>
		public void Open() {
			if(this.mIsOpen) throw new InvalidOperationException("Comm Port is already open!");

			if(CommAPI.FullFramework) {
				// set up the overlapped tx IO
				OVERLAPPED o = new OVERLAPPED();
				this.mTxOverlapped = LocalAlloc(0x40, Marshal.SizeOf(o));
				o.Offset = 0; 
				o.OffsetHigh = 0;
				o.hEvent = IntPtr.Zero;
				Marshal.StructureToPtr(o, this.mTxOverlapped, true);
			}

			hPort = m_CommAPI.CreateFile(this.mPortName);

			if(hPort == (IntPtr)CommAPI.INVALID_HANDLE_VALUE) {
				int e = Marshal.GetLastWin32Error();

				if(e == (int)APIErrors.ERROR_ACCESS_DENIED) {
					// port is unavailable
					throw new ApplicationException("ERROR_ACCESS_DENIED");
				}

				// ClearCommError failed!
				string error = String.Format("CreateFile Failed: {0}", e);
				throw new ApplicationException(error);
			}

			
			this.mIsOpen = true;

			// clear errors
			CommErrorFlags errorFlags = new CommErrorFlags();
			CommStat commStat = new CommStat();				
			if(!m_CommAPI.ClearCommError(hPort, ref errorFlags, commStat)) {
				throw new ApplicationException("Failed to clear error/read");
			}

			// set queue sizes
			m_CommAPI.SetupComm(hPort, this.mRxBufferSize, this.mTxBufferSize);

			// update dcb
			this.UpdateSettings();

			// store some state values
			this.mInBreak = false;

			// read/write timeouts
			this.UpdateTimeouts();

			// start the receive thread
			this.mEventThread = new Thread(new ThreadStart(CommEventThread));
			this.mEventThread.Priority = ThreadPriority.Normal; //by design
			this.mEventThread.Start();

			// wait for the thread to actually get spun up
			this.mThreadStarted.WaitOne();
		}
示例#6
0
		private void CommEventThread() {
			CommEventFlags eventFlags = new CommEventFlags();
			AutoResetEvent rxevent = new AutoResetEvent(false);

			// specify the set of events to be monitored for the port.
			bool b;
			if(CommAPI.FullFramework) {
				b = m_CommAPI.SetCommMask(hPort, CommEventFlags.ALLPC);

				// set up the overlapped IO
				OVERLAPPED o = new OVERLAPPED();
				this.mRxOverlapped = LocalAlloc(0x40, Marshal.SizeOf(o));
				o.Offset = 0; 
				o.OffsetHigh = 0;
				o.hEvent = rxevent.Handle;
				Marshal.StructureToPtr(o, this.mRxOverlapped, true);
			}
			else {
				b = m_CommAPI.SetCommMask(hPort, CommEventFlags.ALLCE_2);
			}
			

			try {
				// let Open() know we're started
				this.mThreadStarted.Set();

				#region >>>> thread loop <<<<
				while(hPort != (IntPtr)CommAPI.INVALID_HANDLE_VALUE) {
					// wait for a Comm event
					if(!m_CommAPI.WaitCommEvent(hPort, ref eventFlags)) {
						int e = Marshal.GetLastWin32Error();

						if(e == (int)APIErrors.ERROR_IO_PENDING) {
							// IO pending so just wait and try again
							rxevent.WaitOne();
							Thread.Sleep(0);
							continue;
						}

						if(e == (int)APIErrors.ERROR_INVALID_HANDLE) {
							// Calling Port.Close() causes hPort to become invalid
							// Since Thread.Abort() is unsupported in the CF, we must
							// accept that calling Close will throw an error here.

							// Close signals the this.mCloseEvent, so wait on it
							// We wait 1 second, though Close should happen much sooner
							int eventResult = m_CommAPI.WaitForSingleObject(this.mCloseEvent, 1000);

							if(eventResult == (int)APIConstants.WAIT_OBJECT_0) {
								// the event was set so close was called
								hPort = (IntPtr)CommAPI.INVALID_HANDLE_VALUE;
					
								// reset our ResetEvent for the next call to Open
								this.mThreadStarted.Reset();

								if(this.mIsOpen) { // this should not be the case...if so, throw an exception for the owner
									string error = String.Format("Wait Failed: {0}", e);
									throw new ApplicationException(error);
								}

								return;
							}
						}

						// WaitCommEvent failed
						// 995 means an exit was requested (thread killed)
						if(e == 995) {
							return;
						}
						else {
							string error = String.Format("Wait Failed: {0}", e);
							throw new ApplicationException(error);
						}
					}

					// Re-specify the set of events to be monitored for the port.
					if(CommAPI.FullFramework) {
						m_CommAPI.SetCommMask(hPort, CommEventFlags.ALLPC);
					}
					else {
						m_CommAPI.SetCommMask(hPort, CommEventFlags.ALLCE);
					}
					// Process the flag - extracted main handling into its own method
					//ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessEvents), eventFlags);					
					this.ProcessEvents(eventFlags);

				} // while(not invalid handle)
				#endregion
			} // try
			catch{
				if(this.mRxOverlapped != IntPtr.Zero) 
					LocalFree(this.mRxOverlapped);

				throw;
			}
		}
示例#7
0
文件: Port.cs 项目: katadam/wockets
        public void SetDCB()
        {
            if (isOpen) return;

            if (CommAPI.FullFramework)
            {
                // set up the overlapped tx IO
                //				AutoResetEvent are = new AutoResetEvent(false);
                OVERLAPPED o = new OVERLAPPED();
                txOverlapped = LocalAlloc(0x40, Marshal.SizeOf(o));
                o.Offset = 0;
                o.OffsetHigh = 0;
                o.hEvent = IntPtr.Zero;
                Marshal.StructureToPtr(o, txOverlapped, true);
            }

            hPort = m_CommAPI.CreateFile(portName);

            if (hPort == (IntPtr)CommAPI.INVALID_HANDLE_VALUE)
            {
                int e = Marshal.GetLastWin32Error();

                if (e == (int)APIErrors.ERROR_ACCESS_DENIED)
                {
                    // port is unavailable
                    return;
                }

                // ClearCommError failed!
                string error = String.Format("CreateFile Failed: {0}", e);
                throw new CommPortException(error);
            }

            isOpen = true;

            // set queue sizes
            m_CommAPI.SetupComm(hPort, rxBufferSize, txBufferSize);

            // transfer the port settings to a DCB structure
            dcb.BaudRate = (uint)portSettings.BasicSettings.BaudRate;
            dcb.ByteSize = portSettings.BasicSettings.ByteSize;
            dcb.EofChar = (sbyte)portSettings.EOFChar;
            dcb.ErrorChar = (sbyte)portSettings.ErrorChar;
            dcb.EvtChar = (sbyte)portSettings.EVTChar;
            dcb.fAbortOnError = portSettings.AbortOnError;
            dcb.fBinary = true;
            dcb.fDsrSensitivity = portSettings.DSRSensitive;
            dcb.fDtrControl = (DCB.DtrControlFlags)portSettings.DTRControl;
            dcb.fErrorChar = portSettings.ReplaceErrorChar;
            dcb.fInX = portSettings.InX;
            dcb.fNull = portSettings.DiscardNulls;
            dcb.fOutX = portSettings.OutX;
            dcb.fOutxCtsFlow = portSettings.OutCTS;
            dcb.fOutxDsrFlow = portSettings.OutDSR;
            dcb.fParity = (portSettings.BasicSettings.Parity == Parity.none) ? false : true;
            dcb.fRtsControl = (DCB.RtsControlFlags)portSettings.RTSControl;
            dcb.fTXContinueOnXoff = portSettings.TxContinueOnXOff;
            dcb.Parity = (byte)portSettings.BasicSettings.Parity;

            dcb.StopBits = (byte)portSettings.BasicSettings.StopBits;
            dcb.XoffChar = (sbyte)portSettings.XoffChar;
            dcb.XonChar = (sbyte)portSettings.XonChar;

            dcb.XonLim = dcb.XoffLim = (ushort)(rxBufferSize / 10);

            m_CommAPI.SetCommState(hPort, dcb);
        }
示例#8
0
文件: Port.cs 项目: katadam/wockets
        /// <summary>
        /// Open the current port 
        /// </summary>
        /// <param name="isThreaded">Set to true to use threading. Otherwise poll</param>
        /// <returns></returns>
        public bool OpenThreaded(bool isThreaded)
        {
            this.isThreaded = isThreaded;

            if(isOpen) return false;

            if(CommAPI.FullFramework)
            {
                // set up the overlapped tx IO
                //				AutoResetEvent are = new AutoResetEvent(false);
                OVERLAPPED o = new OVERLAPPED();
                txOverlapped = LocalAlloc(0x40, Marshal.SizeOf(o));
                o.Offset = 0;
                o.OffsetHigh = 0;
                o.hEvent = IntPtr.Zero;
                Marshal.StructureToPtr(o, txOverlapped, true);
            }

            hPort = m_CommAPI.CreateFile(portName);

            if(hPort == (IntPtr)CommAPI.INVALID_HANDLE_VALUE)
            {
                int e = Marshal.GetLastWin32Error();

                if(e == (int)APIErrors.ERROR_ACCESS_DENIED)
                {
                    // port is unavailable
                    return false;
                }

                // ClearCommError failed!
                string error = String.Format("CreateFile Failed: {0}", e);
                throw new CommPortException(error);
            }

            isOpen = true;

            // set queue sizes
            m_CommAPI.SetupComm(hPort, rxBufferSize, txBufferSize);

            // transfer the port settings to a DCB structure
            dcb.BaudRate = (uint)portSettings.BasicSettings.BaudRate;
            dcb.ByteSize = portSettings.BasicSettings.ByteSize;
            dcb.EofChar = (sbyte)portSettings.EOFChar;
            dcb.ErrorChar = (sbyte)portSettings.ErrorChar;
            dcb.EvtChar = (sbyte)portSettings.EVTChar;
            dcb.fAbortOnError = portSettings.AbortOnError;
            dcb.fBinary = true;
            dcb.fDsrSensitivity = portSettings.DSRSensitive;
            dcb.fDtrControl = (DCB.DtrControlFlags)portSettings.DTRControl;
            dcb.fErrorChar = portSettings.ReplaceErrorChar;
            dcb.fInX = portSettings.InX;
            dcb.fNull = portSettings.DiscardNulls;
            dcb.fOutX = portSettings.OutX;
            dcb.fOutxCtsFlow = portSettings.OutCTS;
            dcb.fOutxDsrFlow = portSettings.OutDSR;
            dcb.fParity = (portSettings.BasicSettings.Parity == Parity.none) ? false : true;
            dcb.fRtsControl = (DCB.RtsControlFlags)portSettings.RTSControl;
            dcb.fTXContinueOnXoff = portSettings.TxContinueOnXOff;
            dcb.Parity = (byte)portSettings.BasicSettings.Parity;

            dcb.StopBits = (byte)portSettings.BasicSettings.StopBits;
            dcb.XoffChar = (sbyte)portSettings.XoffChar;
            dcb.XonChar = (sbyte)portSettings.XonChar;

            dcb.XonLim = dcb.XoffLim = (ushort)(rxBufferSize / 10);

            m_CommAPI.SetCommState(hPort, dcb);

            // store some state values
            brk = 0;
            dtr = dcb.fDtrControl == DCB.DtrControlFlags.Enable ? 1 : 0;
            rts = dcb.fRtsControl == DCB.RtsControlFlags.Enable ? 1 : 0;

            // set the Comm timeouts
            CommTimeouts ct = new CommTimeouts();

            /*
            If an application sets ReadIntervalTimeout and ReadTotalTimeoutMultiplier to MAXDWORD and sets ReadTotalTimeoutConstant to a value greater than zero and less than MAXDWORD, one of the following occurs when the ReadFile function is called:

              a.. If there are any characters in the input buffer, ReadFile returns immediately with the characters in the buffer.
              b.. If there are no characters in the input buffer, ReadFile waits until a character arrives and then returns immediately.
              c.. If no character arrives within the time specified by ReadTotalTimeoutConstant, ReadFile times out.
            */

            // reading we'll return immediately
            // this doesn't seem to work as documented
            #if PPC
            ct.ReadIntervalTimeout = uint.MaxValue; // On the Smartphone, MaxValue blocks, so set to 1 instead but this doesn't work either
            ct.ReadTotalTimeoutConstant = 0;
            ct.ReadTotalTimeoutMultiplier = 0;
            #else
            ct.ReadIntervalTimeout = uint.MaxValue; // On the PC definitely needs to be this, doesn't block. On PPC and SP, this blocks
            ct.ReadTotalTimeoutConstant = 0;
            ct.ReadTotalTimeoutMultiplier = 0;
            #endif

            // writing we'll give 5 seconds
            ct.WriteTotalTimeoutConstant = 5000;
            ct.WriteTotalTimeoutMultiplier = 0;

            m_CommAPI.SetCommTimeouts(hPort, ct);

            // read the ports capabilities
            bool status=GetPortProperties();

            if (isThreaded)
            {
                // start the receive thread
                eventThread = new Thread(new ThreadStart(CommEventThread));
                eventThread.Priority = ThreadPriority.AboveNormal; //SSI changed from highest
                eventThread.Start();

                // wait for the thread to actually get spun up
                threadStarted.WaitOne();
            }
            else
            {
                GrabDataSetup();
            }
            return true;
        }
示例#9
0
文件: Port.cs 项目: katadam/wockets
        /// <summary>
        /// 
        /// </summary>
        public void GrabDataSetup()
        {
            if (isThreaded)
            {
                Console.WriteLine ("SHOULD NOT BE CALLING THIS BECAUSE NOT DIRECT READ");
            }

            grabRxevent		= new AutoResetEvent(false);

            // specify the set of events to be monitored for the port.
            if(CommAPI.FullFramework)
            {
                m_CommAPI.SetCommMask(hPort, CommEventFlags.ALLPC);

                // set up the overlapped IO
                OVERLAPPED o = new OVERLAPPED();
                rxOverlapped = LocalAlloc(0x40, Marshal.SizeOf(o));
                o.Offset = 0;
                o.OffsetHigh = 0;
            #if (PocketPC)
                o.hEvent = grabRxevent.Handle;
            #else
                o.hEvent = grabRxevent.SafeWaitHandle.DangerousGetHandle();
            #endif
                Marshal.StructureToPtr(o, rxOverlapped, true);
            }
            else
            {
                m_CommAPI.SetCommMask(hPort, CommEventFlags.ALLCE);
            }
        }