SerialPort.cs :  » 2.6.4-mono-.net-core » System.IO » System » IO » Ports » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » 2.6.4 mono .net core » System.IO 
System.IO » System » IO » Ports » SerialPort.cs
/* -*- Mode: Csharp; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
//
//
// This class has several problems:
//
//   * No buffering, the specification requires that there is buffering, this
//     matters because a few methods expose strings and chars and the reading
//     is encoding sensitive.   This means that when we do a read of a byte
//     sequence that can not be turned into a full string by the current encoding
//     we should keep a buffer with this data, and read from it on the next
//     iteration.
//
//   * Calls to read_serial from the unmanaged C do not check for errors,
//     like EINTR, that should be retried
//
//   * Calls to the encoder that do not consume all bytes because of partial
//     reads 
//

#if NET_2_0

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace System.IO.Ports{
  [MonitoringDescription ("")]
  public class SerialPort : Component
  {
    public const int InfiniteTimeout = -1;
    const int DefaultReadBufferSize = 4096;
    const int DefaultWriteBufferSize = 2048;
    const int DefaultBaudRate = 9600;
    const int DefaultDataBits = 8;
    const Parity DefaultParity = Parity.None;
    const StopBits DefaultStopBits = StopBits.One;

    bool is_open;
    int baud_rate;
    Parity parity;
    StopBits stop_bits;
    Handshake handshake;
    int data_bits;
    bool break_state = false;
    bool dtr_enable = false;
    bool rts_enable = false;
    ISerialStream stream;
    Encoding encoding = Encoding.ASCII;
    string new_line = Environment.NewLine;
    string port_name;
    int read_timeout = InfiniteTimeout;
    int write_timeout = InfiniteTimeout;
    int readBufferSize = DefaultReadBufferSize;
    int writeBufferSize = DefaultWriteBufferSize;
    object error_received = new object ();
    object data_received = new object ();
    object pin_changed = new object ();

    public SerialPort () : 
      this (GetDefaultPortName (), DefaultBaudRate, DefaultParity, DefaultDataBits, DefaultStopBits)
    {
    }

    public SerialPort (IContainer container) : this ()
    {
      // TODO: What to do here?
    }

    public SerialPort (string portName) :
      this (portName, DefaultBaudRate, DefaultParity, DefaultDataBits, DefaultStopBits)
    {
    }

    public SerialPort (string portName, int baudRate) :
      this (portName, baudRate, DefaultParity, DefaultDataBits, DefaultStopBits)
    {
    }

    public SerialPort (string portName, int baudRate, Parity parity) :
      this (portName, baudRate, parity, DefaultDataBits, DefaultStopBits)
    {
    }

    public SerialPort (string portName, int baudRate, Parity parity, int dataBits) :
      this (portName, baudRate, parity, dataBits, DefaultStopBits)
    {
    }

    public SerialPort (string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits) 
    {
      port_name = portName;
      baud_rate = baudRate;
      data_bits = dataBits;
      stop_bits = stopBits;
      this.parity = parity;
    }

    static string GetDefaultPortName ()
    {
      string[] ports = GetPortNames();
      if (ports.Length > 0) {
        return ports[0];
      } else {
        int p = (int)Environment.OSVersion.Platform;
        if (p == 4 || p == 128 || p == 6)
          return "ttyS0"; // Default for Unix
        else
          return "COM1"; // Default for Windows
      }
    }

    [Browsable (false)]
    [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
    public Stream BaseStream {
      get {
        CheckOpen ();
        return (Stream) stream;
      }
    }

    [DefaultValueAttribute (DefaultBaudRate)]
    [Browsable (true)]
    [MonitoringDescription ("")]
    public int BaudRate {
      get {
        return baud_rate;
      }
      set {
        if (value <= 0)
          throw new ArgumentOutOfRangeException ("value");
        
        if (is_open)
          stream.SetAttributes (value, parity, data_bits, stop_bits, handshake);
        
        baud_rate = value;
      }
    }

    [Browsable (false)]
    [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
    public bool BreakState {
      get {
        return break_state;
      }
      set {
        CheckOpen ();
        if (value == break_state)
          return; // Do nothing.

        stream.SetBreakState (value);
        break_state = value;
      }
    }

    [Browsable (false)]
    [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
    public int BytesToRead {
      get {
        CheckOpen ();
        return stream.BytesToRead;
      }
    }

    [Browsable (false)]
    [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
    public int BytesToWrite {
      get {
        CheckOpen ();
        return stream.BytesToWrite;
      }
    }

    [Browsable (false)]
    [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
    public bool CDHolding {
      get {
        CheckOpen ();
        return (stream.GetSignals () & SerialSignal.Cd) != 0;
      }
    }

    [Browsable (false)]
    [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
    public bool CtsHolding {
      get {
        CheckOpen ();
        return (stream.GetSignals () & SerialSignal.Cts) != 0;
      }
    }

    [DefaultValueAttribute(DefaultDataBits)]
    [Browsable (true)]
    [MonitoringDescription ("")]
    public int DataBits {
      get {
        return data_bits;
      }
      set {
        if (value < 5 || value > 8)
          throw new ArgumentOutOfRangeException ("value");

        if (is_open)
          stream.SetAttributes (baud_rate, parity, value, stop_bits, handshake);
        
        data_bits = value;
      }
    }

    [MonoTODO("Not implemented")]
    [Browsable (true)]
    [MonitoringDescription ("")]
    [DefaultValue (false)]
    public bool DiscardNull {
      get {
        throw new NotImplementedException ();
      }
      set {
        // LAMESPEC: Msdn states that an InvalidOperationException exception
        // is fired if the port is not open, which is *not* happening.

        throw new NotImplementedException ();
      }
    }

    [Browsable (false)]
    [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
    public bool DsrHolding {
      get {
        CheckOpen ();
        return (stream.GetSignals () & SerialSignal.Dsr) != 0;
      }
    }

    [DefaultValueAttribute(false)]
    [Browsable (true)]
    [MonitoringDescription ("")]
    public bool DtrEnable {
      get {
        return dtr_enable;
      }
      set {
        if (value == dtr_enable)
          return;
        if (is_open)
          stream.SetSignal (SerialSignal.Dtr, value);
        
        dtr_enable = value;
      }
    }

    [Browsable (false)]
    [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
    [MonitoringDescription ("")]
    public Encoding Encoding {
      get {
        return encoding;
      }
      set {
        if (value == null)
          throw new ArgumentNullException ("value");

        encoding = value;
      }
    }

    [DefaultValueAttribute(Handshake.None)]
    [Browsable (true)]
    [MonitoringDescription ("")]
    public Handshake Handshake {
      get {
        return handshake;
      }
      set {
        if (value < Handshake.None || value > Handshake.RequestToSendXOnXOff)
          throw new ArgumentOutOfRangeException ("value");

        if (is_open)
          stream.SetAttributes (baud_rate, parity, data_bits, stop_bits, value);
        
        handshake = value;
      }
    }

    [Browsable (false)]
    public bool IsOpen {
      get {
        return is_open;
      }
    }

    [DefaultValueAttribute("\n")]
    [Browsable (false)]
    [MonitoringDescription ("")]
    public string NewLine {
      get {
        return new_line;
      }
      set {
        if (value == null)
          throw new ArgumentNullException ("value");
        if (value.Length == 0)
          throw new ArgumentException ("NewLine cannot be null or empty.", "value");
        
        new_line = value;
      }
    }

    [DefaultValueAttribute(DefaultParity)]
    [Browsable (true)]
    [MonitoringDescription ("")]
    public Parity Parity {
      get {
        return parity;
      }
      set {
        if (value < Parity.None || value > Parity.Space)
          throw new ArgumentOutOfRangeException ("value");

        if (is_open)
          stream.SetAttributes (baud_rate, value, data_bits, stop_bits, handshake);
        
        parity = value;
      }
    }

    [MonoTODO("Not implemented")]
    [Browsable (true)]
    [MonitoringDescription ("")]
    [DefaultValue (63)]
    public byte ParityReplace {
      get {
        throw new NotImplementedException ();
      }
      set {
        throw new NotImplementedException ();
      }
    }

    
    [Browsable (true)]
    [MonitoringDescription ("")]
    [DefaultValue ("COM1")] // silly Windows-ism. We should ignore it.
    public string PortName {
      get {
        return port_name;
      }
      set {
        if (is_open)
          throw new InvalidOperationException ("Port name cannot be set while port is open.");
        if (value == null)
          throw new ArgumentNullException ("value");
        if (value.Length == 0 || value.StartsWith ("\\\\"))
          throw new ArgumentException ("value");

        port_name = value;
      }
    }

    [DefaultValueAttribute(DefaultReadBufferSize)]
    [Browsable (true)]
    [MonitoringDescription ("")]
    public int ReadBufferSize {
      get {
        return readBufferSize;
      }
      set {
        if (is_open)
          throw new InvalidOperationException ();
        if (value <= 0)
          throw new ArgumentOutOfRangeException ("value");
        if (value <= DefaultReadBufferSize)
          return;

        readBufferSize = value;
      }
    }

    [DefaultValueAttribute(InfiniteTimeout)]
    [Browsable (true)]
    [MonitoringDescription ("")]
    public int ReadTimeout {
      get {
        return read_timeout;
      }
      set {
        if (value <= 0 && value != InfiniteTimeout)
          throw new ArgumentOutOfRangeException ("value");

        if (is_open)
          stream.ReadTimeout = value;
        
        read_timeout = value;
      }
    }

    [MonoTODO("Not implemented")]
    [DefaultValueAttribute(1)]
    [Browsable (true)]
    [MonitoringDescription ("")]
    public int ReceivedBytesThreshold {
      get {
        throw new NotImplementedException ();
      }
      set {
        if (value <= 0)
          throw new ArgumentOutOfRangeException ("value");

        throw new NotImplementedException ();
      }
    }

    [DefaultValueAttribute(false)]
    [Browsable (true)]
    [MonitoringDescription ("")]
    public bool RtsEnable {
      get {
        return rts_enable;
      }
      set {
        if (value == rts_enable)
          return;
        if (is_open)
          stream.SetSignal (SerialSignal.Rts, value);
        
        rts_enable = value;
      }
    }

    [DefaultValueAttribute(DefaultStopBits)]
    [Browsable (true)]
    [MonitoringDescription ("")]
    public StopBits StopBits {
      get {
        return stop_bits;
      }
      set {
        if (value < StopBits.One || value > StopBits.OnePointFive)
          throw new ArgumentOutOfRangeException ("value");
        
        if (is_open)
          stream.SetAttributes (baud_rate, parity, data_bits, value, handshake);
        
        stop_bits = value;
      }
    }

    [DefaultValueAttribute(DefaultWriteBufferSize)]
    [Browsable (true)]
    [MonitoringDescription ("")]
    public int WriteBufferSize {
      get {
        return writeBufferSize;
      }
      set {
        if (is_open)
          throw new InvalidOperationException ();
        if (value <= 0)
          throw new ArgumentOutOfRangeException ("value");
        if (value <= DefaultWriteBufferSize)
          return;

        writeBufferSize = value;
      }
    }

    [DefaultValueAttribute(InfiniteTimeout)]
    [Browsable (true)]
    [MonitoringDescription ("")]
    public int WriteTimeout {
      get {
        return write_timeout;
      }
      set {
        if (value <= 0 && value != InfiniteTimeout)
          throw new ArgumentOutOfRangeException ("value");

        if (is_open)
          stream.WriteTimeout = value;
        
        write_timeout = value;
      }
    }

    // methods

    public void Close ()
    {
      Dispose (true);
    }

    protected override void Dispose (bool disposing)
    {
      if (!is_open)
        return;
      
      is_open = false;
      // Do not close the base stream when the finalizer is run; the managed code can still hold a reference to it.
      if (disposing)
        stream.Close ();
      stream = null;
    }

    public void DiscardInBuffer ()
    {
      CheckOpen ();
      stream.DiscardInBuffer ();
    }

    public void DiscardOutBuffer ()
    {
      CheckOpen ();
      stream.DiscardOutBuffer ();
    }

    public static string [] GetPortNames ()
    {
      int p = (int) Environment.OSVersion.Platform;
      List<string> serial_ports = new List<string>();
      
      // Are we on Unix?
      if (p == 4 || p == 128 || p == 6) {
        string[] ttys = Directory.GetFiles("/dev/", "tty*");
        bool linux_style = false;

        //
        // Probe for Linux-styled devices: /dev/ttyS* or /dev/ttyUSB*
        // 
        foreach (string dev in ttys) {
          if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB")){
            linux_style = true;
            break;
          }
        }

        foreach (string dev in ttys) {
          if (linux_style){
            if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB"))
              serial_ports.Add (dev);
          } else {
            if (dev != "/dev/tty" && dev.StartsWith ("/dev/tty") && !dev.StartsWith ("/dev/ttyC"))
              serial_ports.Add (dev);
          }
        }
      } else {
        using (RegistryKey subkey = Registry.LocalMachine.OpenSubKey("HARDWARE\\DEVICEMAP\\SERIALCOMM"))
        {
          if (subkey != null) {
            string[] names = subkey.GetValueNames();
            foreach (string value in names) {
              string port = subkey.GetValue(value, "").ToString();
              if (port != "")
                serial_ports.Add(port);
            }
          }
        }
      }
      return serial_ports.ToArray();
    }

    static bool IsWindows {
      get {
        PlatformID id =  Environment.OSVersion.Platform;
        return id == PlatformID.Win32Windows || id == PlatformID.Win32NT; // WinCE not supported
      }
    }

    public void Open ()
    {
      if (is_open)
        throw new InvalidOperationException ("Port is already open");
      
#if !TARGET_JVM
      if (IsWindows) // Use windows kernel32 backend
        stream = new WinSerialStream (port_name, baud_rate, data_bits, parity, stop_bits, dtr_enable,
          rts_enable, handshake, read_timeout, write_timeout, readBufferSize, writeBufferSize);
      else // Use standard unix backend
#endif
        stream = new SerialPortStream (port_name, baud_rate, data_bits, parity, stop_bits, dtr_enable,
          rts_enable, handshake, read_timeout, write_timeout, readBufferSize, writeBufferSize);
      
      is_open = true;
    }

    public int Read (byte[] buffer, int offset, int count)
    {
      CheckOpen ();
      if (buffer == null)
        throw new ArgumentNullException ("buffer");
      if (offset < 0 || count < 0)
        throw new ArgumentOutOfRangeException ("offset or count less than zero.");

      if (buffer.Length - offset < count )
        throw new ArgumentException ("offset+count",
                    "The size of the buffer is less than offset + count.");
      
      return stream.Read (buffer, offset, count);
    }

    [MonoTODO("Read of char buffers is currently broken")]
    public int Read (char[] buffer, int offset, int count)
    {
      CheckOpen ();
      if (buffer == null)
        throw new ArgumentNullException ("buffer");
      if (offset < 0 || count < 0)
        throw new ArgumentOutOfRangeException ("offset or count less than zero.");

      if (buffer.Length - offset < count )
        throw new ArgumentException ("offset+count",
                    "The size of the buffer is less than offset + count.");

      // The following code does not work, we nee to reintroduce a buffer stream somewhere
      // for this to work;  In addition the code is broken.
      byte [] bytes = encoding.GetBytes (buffer, offset, count);
      return stream.Read (bytes, 0, bytes.Length);
    }

    internal int read_byte ()
    {
      byte [] buff = new byte [1];
      if (stream.Read (buff, 0, 1) > 0)
        return buff [0];

      return -1;
    }
    
    public int ReadByte ()
    {
      CheckOpen ();
      return read_byte ();
    }

    public int ReadChar ()
    {
      CheckOpen ();
      
      byte [] buffer = new byte [16];
      int i = 0;

      do {
        int b = read_byte ();
        if (b == -1)
          return -1;
        buffer [i++] = (byte) b;
        char [] c = encoding.GetChars (buffer, 0, 1);
        if (c.Length > 0)
          return (int) c [0];
      } while (i < buffer.Length);

      return -1;
    }

    public string ReadExisting ()
    {
      CheckOpen ();
      
      int count = BytesToRead;
      byte [] bytes = new byte [count];
      
      int n = stream.Read (bytes, 0, count);
      return new String (encoding.GetChars (bytes, 0, n));
    }

    public string ReadLine ()
    {
      return ReadTo (new_line);
    }

    public string ReadTo (string value)
    {
      CheckOpen ();
      if (value == null)
        throw new ArgumentNullException ("value");
      if (value.Length == 0)
        throw new ArgumentException ("value");

      // Turn into byte array, so we can compare
      byte [] byte_value = encoding.GetBytes (value);
      int current = 0;
      List<byte> seen = new List<byte> ();

      while (true){
        int n = read_byte ();
        if (n == -1)
          break;
        seen.Add ((byte)n);
        if (n == byte_value [current]){
          current++;
          if (current == byte_value.Length)
            return encoding.GetString (seen.ToArray (), 0, seen.Count - byte_value.Length);
        } else {
          current = (byte_value [0] == n) ? 1 : 0;
        }
      }
      return encoding.GetString (seen.ToArray ());
    }

    public void Write (string str)
    {
      CheckOpen ();
      if (str == null)
        throw new ArgumentNullException ("str");
      
      byte [] buffer = encoding.GetBytes (str);
      Write (buffer, 0, buffer.Length);
    }

    public void Write (byte [] buffer, int offset, int count)
    {
      CheckOpen ();
      if (buffer == null)
        throw new ArgumentNullException ("buffer");

      if (offset < 0 || count < 0)
        throw new ArgumentOutOfRangeException ();

      if (buffer.Length - offset < count)
        throw new ArgumentException ("offset+count",
                   "The size of the buffer is less than offset + count.");

      stream.Write (buffer, offset, count);
    }

    public void Write (char [] buffer, int offset, int count)
    {
      CheckOpen ();
      if (buffer == null)
        throw new ArgumentNullException ("buffer");

      if (offset < 0 || count < 0)
        throw new ArgumentOutOfRangeException ();

      if (buffer.Length - offset < count)
        throw new ArgumentException ("offset+count",
                   "The size of the buffer is less than offset + count.");

      byte [] bytes = encoding.GetBytes (buffer, offset, count);
      stream.Write (bytes, 0, bytes.Length);
    }

    public void WriteLine (string str)
    {
      Write (str + new_line);
    }

    void CheckOpen ()
    {
      if (!is_open)
        throw new InvalidOperationException ("Specified port is not open.");
    }

    internal void OnErrorReceived (SerialErrorReceivedEventArgs args)
    {
      SerialErrorReceivedEventHandler handler =
        (SerialErrorReceivedEventHandler) Events [error_received];

      if (handler != null)
        handler (this, args);
    }

    internal void OnDataReceived (SerialDataReceivedEventArgs args)
    {
      SerialDataReceivedEventHandler handler =
        (SerialDataReceivedEventHandler) Events [data_received];

      if (handler != null)
        handler (this, args);
    }
    
    internal void OnDataReceived (SerialPinChangedEventArgs args)
    {
      SerialPinChangedEventHandler handler =
        (SerialPinChangedEventHandler) Events [pin_changed];

      if (handler != null)
        handler (this, args);
    }

    // events
    [MonitoringDescription ("")]
    public event SerialErrorReceivedEventHandler ErrorReceived {
      add { Events.AddHandler (error_received, value); }
      remove { Events.RemoveHandler (error_received, value); }
    }
    
    [MonitoringDescription ("")]
    public event SerialPinChangedEventHandler PinChanged {
      add { Events.AddHandler (pin_changed, value); }
      remove { Events.RemoveHandler (pin_changed, value); }
    }
    
    [MonitoringDescription ("")]
    public event SerialDataReceivedEventHandler DataReceived {
      add { Events.AddHandler (data_received, value); }
      remove { Events.RemoveHandler (data_received, value); }
    }
  }

  public delegate void SerialDataReceivedEventHandler (object sender, SerialDataReceivedEventArgs e);
  public delegate void SerialPinChangedEventHandler (object sender, SerialPinChangedEventArgs e);
  public delegate void SerialErrorReceivedEventHandler (object sender, SerialErrorReceivedEventArgs e);

}

#endif
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.