예제 #1
0
        /// <summary>
        /// Closes and destroys the com port.
        /// </summary>
        protected void Destroy()
        {
            // Cancel I/O, kill receiver & close port.
            if (this.portOpen)
            {
                this.port.Cancel();
                if (this.rxThread != null)
                {
                    this.rxThread.Abort();
                    this.rxThread = null;
                }
                this.port.Close();
                this.portOpen = false;
            }

            // Reinit resources.
            this.dcb        = null;
            this.port       = null;
            this.stats      = null;
            this.props      = null;
            this.tmout      = null;
            this.rxOvr      = null;
            this.txOvr      = null;
            this.escape     = null;
            this.writeEvent = null;
            this.recvrEvent = null;
            return;
        }
예제 #2
0
        /// <summary>
        /// Write data to a comm object.
        /// </summary>
        /// <param name="buf">Buffer to write from</param>
        /// <param name="nToSend">Number to buyes to send.</param>
        /// <param name="nSent">Number of actually bytes sent.</param>
        /// <param name="olMem">Pointer to overlap struct.</param>
        /// <returns>True if executed successfully.</returns>
        internal bool Write(byte[] buf, uint nToSend, out uint nSent, Win32Ovrlap ovlap)
        {
            // Write done pre/post check.
            bool postCheck = true;

            // Wait until last write done.
            if (postCheck == false)
            {
                if (ovlap.MemPtr != IntPtr.Zero)
                {
                    while (this.nUnsent > 0)
                    {
                        if (ovlap.Get(out nSent, true))
                        {
                            this.nUnsent -= nSent;
                        }
                    }
                }
            }

            // Send data buffer.
            bool status = WriteFile(this.handle, buf, nToSend, out nSent, ovlap.MemPtr);

            this.nUnsent = nToSend - nSent;

            // Return status.
            if (status == false)
            {
                int error = Marshal.GetLastWin32Error();

                // Wait until this write done.
                if (postCheck == true)
                {
                    if (error == ERROR_IO_PENDING)
                    {
                        while (this.nUnsent > 0)
                        {
                            if (ovlap.Get(out nSent, true))
                            {
                                this.nUnsent -= nSent;
                            }
                        }
                    }
                    else
                    {
                        this.SetFault("WriteFile()", error);
                        return(false);
                    }
                }
                else
                {
                    if (error != ERROR_IO_PENDING)
                    {
                        this.SetFault("WriteFile()", error);
                        return(false);
                    }
                    nSent = nToSend;                     // assume write will pass.
                }
            }
            return(true);
        }
예제 #3
0
        /// <summary>
        /// Main receiver thread for this com port instance.
        /// </summary>
        private void ReceiveThread()
        {
            // Create locals.
            uint firedEvent = 0;
            uint nBytes     = 0;

            byte[] buf = new Byte[1];

            // Create thread signal (initial state is non-signaled).
            AutoResetEvent signal = new AutoResetEvent(false);

            // Create overlap memory pointer. Install signal.
            this.rxOvr = new Win32Ovrlap(port.Handle, signal.Handle);

            // Instantiate the event class.
            this.events = new Win32Events(rxOvr.MemPtr);

            // Instantiate the modem signal class.
            this.modem = new Win32Modem();

            // Set initial modem signal states.
            this.Signals();

            // Signal the main thread that
            // the receive thread is started.
            this.recvrEvent.Set();

            try
            {
                while (true)
                {
                    // Arm the event monitoring mask.
                    // if(this.events.Set(this.port.Handle, Win32Events.EV_DEFAULT))
                    if (this.events.Set(this.port.Handle, Win32Events.EV_TXEMPTY))
                    {
                        // Wait for any armed event to occur.
                        this.events.Wait(this.port.Handle, signal);

                        // Get mask of fired events.
                        firedEvent = this.events.GetMask;

                        // Error event (override).
                        if ((firedEvent & Win32Events.EV_ERR) != 0)
                        {
                            if (this.stats.Reset(this.port.Handle) == false)
                            {
                                if (this.stats.Status == Win32Status.CE_BREAK)
                                {
                                    firedEvent &= ~Win32Events.EV_BREAK;
                                }
                                else
                                {
                                    this.CommError(this.stats.Fault);
                                }
                            }
                        }
                        else
                        {
                            // Receive event (override).
                            if (((firedEvent & Win32Events.EV_RXCHAR) != 0) && (this.immediate))
                            {
                                do
                                {
                                    nBytes = 0;
                                    if (this.port.Read(buf, 1, out nBytes, this.rxOvr.MemPtr))
                                    {
                                        if (nBytes == 1)
                                        {
                                            this.OnRxChar(buf);
                                        }
                                    }
                                } while(nBytes > 0);
                            }

                            // TX queue empty event (override).
                            if ((firedEvent & Win32Events.EV_TXEMPTY) != 0)
                            {
                                this.OnTxDone();
                            }

                            // Line break event (override).
                            if ((firedEvent & Win32Events.EV_BREAK) != 0)
                            {
                                this.OnBreak();
                            }

                            // Modem signal change event(s) (override).
                            if ((firedEvent & Win32Events.EV_MODEM) > 0)
                            {
                                this.modem.Get(this.port.Handle);
                                if ((firedEvent & Win32Events.EV_CTS) > 0)
                                {
                                    this.OnCTS(this.modem.CtsState);
                                }
                                if ((firedEvent & Win32Events.EV_DSR) > 0)
                                {
                                    this.OnDSR(this.modem.DsrState);
                                }
                                if ((firedEvent & Win32Events.EV_RLSD) > 0)
                                {
                                    this.OnRLSD(this.modem.RlsdState);
                                }
                                if ((firedEvent & Win32Events.EV_RING) > 0)
                                {
                                    this.OnRING(this.modem.RingState);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                if ((e is ThreadAbortException))
                {
                    this.modem  = null;
                    this.events = null;
                    this.rxOvr  = null;
                }
                else
                {
                    this.CommError("Receiver Exception: " + e.Message);
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Create & opens the com port and configures it with the required settings.
        /// </summary>
        /// <param name="cfg">Reference to port user config.</param>
        /// <returns>True if port opened successfully.</returns>
        protected bool Create(SerialCnfg cfg)
        {
            // If port already open, return.
            if (portOpen)
            {
                this.CommError("Com Port Already Open.");
                return(false);
            }

            // Init members.
            this.fault      = "";
            this.rxThread   = null;
            this.writeEvent = new ManualResetEvent(false);
            this.recvrEvent = new ManualResetEvent(false);

            // Copy config to DCB.
            this.dcb = new Win32DCB(cfg);

            // Create handle to comm port.
            this.port = new Win32Com();
            if ((this.portOpen = this.port.Open(cfg.PortName, true)) == false)
            {
                this.CommError(this.port.Fault);
                return(false);
            }
            this.portName = cfg.PortName;

            // Instantiate support classes.
            this.stats  = new Win32Status();
            this.tmout  = new Win32Tmout();
            this.props  = new Win32Props();
            this.escape = new Win32Escape(port.Handle);

            // Set read/write timeouts.
            this.tmout.WriteConstant   = cfg.TxTmoConst;
            this.tmout.WriteMultiplier = cfg.TxTmoMulti;
            if (this.tmout.Set(this.port.Handle) == false)
            {
                this.Destroy();
                this.CommError(this.tmout.Fault);
                return(false);
            }

            // Overide OS default queue sizes.
            if ((cfg.RxQueLen != 0) || (cfg.TxQueLen != 0))
            {
                if (this.props.Set(this.port.Handle, (uint)cfg.RxQueLen, (uint)cfg.TxQueLen) == false)
                {
                    this.Destroy();
                    this.CommError(this.props.Fault);
                    return(false);
                }
            }

            // Get the current properties.
            if (this.props.Get(this.port.Handle) == false)
            {
                this.Destroy();
                this.CommError(this.props.Fault);
                return(false);
            }

            // Set flow control limits.
            this.dcb.Limits(cfg, this.props.RxCurSize);

            // Update the port settings.
            if (this.dcb.Set(this.port.Handle) == false)
            {
                this.Destroy();
                this.CommError(this.dcb.Fault);
                return(false);
            }

            // XON/OFF extended functionality.
            this.escape.XOFFavailable = true;

            // RTS extended functionality.
            if (cfg.RtsControl == PinState.Disable)
            {
                this.escape.RTS = false;
            }
            else if (cfg.RtsControl == PinState.Enable)
            {
                this.escape.RTS = true;
            }
            else if (cfg.RtsControl == PinState.Handshake)
            {
                this.escape.RTSavailable = false;
            }

            // DTR extended functionality.
            if (cfg.DtrControl == PinState.Disable)
            {
                this.escape.DTR = false;
            }
            else if (cfg.DtrControl == PinState.Enable)
            {
                this.escape.DTR = true;
            }
            else if (cfg.DtrControl == PinState.Toggle)
            {
                this.escape.DTR = false;
            }
            else if (cfg.DtrControl == PinState.Handshake)
            {
                this.escape.DTRavailable = false;
            }

            // Create TX overlap memory pointer.
            this.txOvr = new Win32Ovrlap(this.port.Handle, this.writeEvent.Handle);

            // Set the receiver mode.
            this.immediate = cfg.ReceiveMode;

            // Start the receiver thread.
            this.rxThread          = new Thread(new ThreadStart(ReceiveThread));
            this.rxThread.Name     = "COMReceiver";
            this.rxThread.Priority = ThreadPriority.AboveNormal;
            this.rxThread.Start();

            // Wait for receive thread to start.
            this.recvrEvent.WaitOne(500, false);

            // Port opened OK.
            return(true);
        }
예제 #5
0
		/// <summary>
		/// Write data to a comm object.
		/// </summary>
		/// <param name="buf">Buffer to write from</param>
		/// <param name="nToSend">Number to buyes to send.</param>
		/// <param name="nSent">Number of actually bytes sent.</param>
		/// <param name="olMem">Pointer to overlap struct.</param>
		/// <returns>True if executed successfully.</returns>
		internal bool Write(byte[] buf, uint nToSend, out uint nSent, Win32Ovrlap ovlap)
		{
			// Write done pre/post check.
			bool postCheck = true;

			// Wait until last write done.
			if(postCheck == false)
			{
				if(ovlap.MemPtr != IntPtr.Zero)
				{
					while(this.nUnsent > 0)
					{
						if(ovlap.Get(out nSent, true))
						{
							this.nUnsent -= nSent;
						}
					}
	
				}
			}

			// Send data buffer.
			bool status = WriteFile(this.handle, buf, nToSend, out nSent, ovlap.MemPtr);
			this.nUnsent = nToSend-nSent;

			// Return status.
			if(status == false) 
			{
				int error = Marshal.GetLastWin32Error();
				
				// Wait until this write done.
				if(postCheck == true)
				{
					if(error == ERROR_IO_PENDING)
					{
						while(this.nUnsent > 0)
						{
							if(ovlap.Get(out nSent, true))
							{
								this.nUnsent -= nSent;
							}
						}
					}
					else
					{
						this.SetFault("WriteFile()", error);
						return false;
					}
				}
				else
				{
					if(error != ERROR_IO_PENDING)
					{
						this.SetFault("WriteFile()", error);
						return false;
					}
					nSent = nToSend; // assume write will pass.
				}
			}
			return true;
		}
예제 #6
0
		/// <summary>
		/// Main receiver thread for this com port instance.
		/// </summary>
		private void ReceiveThread()
		{
			// Create locals.
			uint firedEvent = 0;
			uint nBytes = 0;
			byte[] buf = new Byte[1];

			// Create thread signal (initial state is non-signaled). 
			AutoResetEvent signal = new AutoResetEvent(false);

			// Create overlap memory pointer. Install signal.
			this.rxOvr = new Win32Ovrlap(port.Handle, signal.Handle);

			// Instantiate the event class.
			this.events = new Win32Events(rxOvr.MemPtr);

			// Instantiate the modem signal class.
			this.modem = new Win32Modem();

			// Set initial modem signal states.
			this.Signals();

			// Signal the main thread that 
			// the receive thread is started.
			this.recvrEvent.Set();

			try
			{
				while(true) 
				{
					// Arm the event monitoring mask.
					// if(this.events.Set(this.port.Handle, Win32Events.EV_DEFAULT))
					if(this.events.Set(this.port.Handle, Win32Events.EV_TXEMPTY))
					{
						// Wait for any armed event to occur.
						this.events.Wait(this.port.Handle, signal);

						// Get mask of fired events.
						firedEvent = this.events.GetMask;

						// Error event (override).
						if((firedEvent & Win32Events.EV_ERR) != 0)
						{
							if(this.stats.Reset(this.port.Handle) == false)
							{
								if(this.stats.Status == Win32Status.CE_BREAK)
								{
									firedEvent &= ~Win32Events.EV_BREAK;
								}
								else
								{
									this.CommError(this.stats.Fault);
								}
							}
						}
						else
						{
							// Receive event (override).
							if(((firedEvent & Win32Events.EV_RXCHAR) != 0) && (this.immediate))
							{
								do 
								{
									nBytes = 0;
									if(this.port.Read(buf, 1, out nBytes, this.rxOvr.MemPtr)) 
									{
										if(nBytes == 1)
											this.OnRxChar(buf);
									}
								} while(nBytes > 0);
							}

							// TX queue empty event (override).
							if((firedEvent & Win32Events.EV_TXEMPTY) != 0)
								this.OnTxDone();

							// Line break event (override).
							if((firedEvent & Win32Events.EV_BREAK) != 0)
								this.OnBreak();

							// Modem signal change event(s) (override).
							if((firedEvent & Win32Events.EV_MODEM) > 0)
							{
								this.modem.Get(this.port.Handle);
								if((firedEvent & Win32Events.EV_CTS) > 0)
									this.OnCTS(this.modem.CtsState);
								if((firedEvent & Win32Events.EV_DSR) > 0)
									this.OnDSR(this.modem.DsrState);
								if((firedEvent & Win32Events.EV_RLSD) > 0)
									this.OnRLSD(this.modem.RlsdState);
								if((firedEvent & Win32Events.EV_RING) > 0)
									this.OnRING(this.modem.RingState);
							}
						}
					}					
				}
			}
			catch(Exception e)
			{
				if((e is ThreadAbortException))
				{
					this.modem = null;
					this.events = null;
					this.rxOvr = null;
				}
				else
				{
					this.CommError("Receiver Exception: " + e.Message);
				}
			}
		}
예제 #7
0
		/// <summary>
		/// Closes and destroys the com port.
		/// </summary>
		protected void Destroy()
		{
			// Cancel I/O, kill receiver & close port.
			if(this.portOpen)
			{
				this.port.Cancel();
				if(this.rxThread != null)
				{
					this.rxThread.Abort();
					this.rxThread = null;
				}
				this.port.Close();
				this.portOpen = false;
			}

			// Reinit resources.
			this.dcb    = null;
			this.port   = null;
			this.stats  = null;
			this.props  = null;
			this.tmout  = null;
			this.rxOvr  = null;
			this.txOvr  = null;
			this.escape = null;
			this.writeEvent = null;
			this.recvrEvent = null;
			return;
		}
예제 #8
0
		/// <summary>
		/// Create & opens the com port and configures it with the required settings.
		/// </summary>
		/// <param name="cfg">Reference to port user config.</param>
		/// <returns>True if port opened successfully.</returns>
		protected bool Create(SerialCnfg cfg) 
		{
			// If port already open, return.
			if(portOpen)
			{
				this.CommError("Com Port Already Open.");
				return false;
			}

			// Init members.
			this.fault = "";
			this.rxThread = null;
			this.writeEvent = new ManualResetEvent(false);
			this.recvrEvent = new ManualResetEvent(false);

			// Copy config to DCB.
			this.dcb = new Win32DCB(cfg);

			// Create handle to comm port.
			this.port = new Win32Com();
			if((this.portOpen = this.port.Open(cfg.PortName, true)) == false)
			{
				this.CommError(this.port.Fault);
				return false;
			}
			this.portName = cfg.PortName;

			// Instantiate support classes.
			this.stats  = new Win32Status();
			this.tmout  = new Win32Tmout();
			this.props  = new Win32Props();
			this.escape = new Win32Escape(port.Handle);

			// Set read/write timeouts.
			this.tmout.WriteConstant = cfg.TxTmoConst;
			this.tmout.WriteMultiplier = cfg.TxTmoMulti;
			if(this.tmout.Set(this.port.Handle) == false)
			{
				this.Destroy();
				this.CommError(this.tmout.Fault);
				return false;
			}

			// Overide OS default queue sizes.
			if((cfg.RxQueLen != 0) || (cfg.TxQueLen != 0))
			{
				if(this.props.Set(this.port.Handle, (uint)cfg.RxQueLen, (uint)cfg.TxQueLen) == false)
				{
					this.Destroy();
					this.CommError(this.props.Fault);
					return false;
				}
			}

			// Get the current properties.
			if(this.props.Get(this.port.Handle) == false)
			{
				this.Destroy();
				this.CommError(this.props.Fault);
				return false;
			}

			// Set flow control limits.
			this.dcb.Limits(cfg, this.props.RxCurSize);

			// Update the port settings.
			if(this.dcb.Set(this.port.Handle) == false)
			{
				this.Destroy();
				this.CommError(this.dcb.Fault);
				return false;
			}

			// XON/OFF extended functionality.
			this.escape.XOFFavailable = true;

			// RTS extended functionality.
			if(cfg.RtsControl == PinState.Disable)
				this.escape.RTS = false;
			else if(cfg.RtsControl == PinState.Enable)
				this.escape.RTS = true;
			else if(cfg.RtsControl == PinState.Handshake)
				this.escape.RTSavailable = false;

			// DTR extended functionality.
			if(cfg.DtrControl == PinState.Disable)
				this.escape.DTR = false;
			else if(cfg.DtrControl == PinState.Enable)
				this.escape.DTR = true;
			else if(cfg.DtrControl == PinState.Toggle)
				this.escape.DTR = false;
			else if(cfg.DtrControl == PinState.Handshake)
				this.escape.DTRavailable = false;

			// Create TX overlap memory pointer.
			this.txOvr = new Win32Ovrlap(this.port.Handle, this.writeEvent.Handle);

			// Set the receiver mode.
			this.immediate = cfg.ReceiveMode;

			// Start the receiver thread.
			this.rxThread = new Thread(new ThreadStart(ReceiveThread));
			this.rxThread.Name = "COMReceiver";
			this.rxThread.Priority = ThreadPriority.AboveNormal;
			this.rxThread.Start();

			// Wait for receive thread to start.
			this.recvrEvent.WaitOne(500, false);

			// Port opened OK.
			return true;
		}