2014-08-13 10:39:27 +01:00
|
|
|
/* -*- 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
|
|
|
|
//
|
|
|
|
|
|
|
|
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) {
|
2015-01-13 10:44:36 +00:00
|
|
|
if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB") || dev.StartsWith("/dev/ttyACM")) {
|
2014-08-13 10:39:27 +01:00
|
|
|
linux_style = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach (string dev in ttys) {
|
|
|
|
if (linux_style){
|
2015-01-13 10:44:36 +00:00
|
|
|
if (dev.StartsWith("/dev/ttyS") || dev.StartsWith("/dev/ttyUSB") || dev.StartsWith("/dev/ttyACM"))
|
2014-08-13 10:39:27 +01:00
|
|
|
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 (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
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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.");
|
|
|
|
|
|
|
|
int c, i;
|
|
|
|
for (i = 0; i < count && (c = ReadChar ()) != -1; i++)
|
|
|
|
buffer[offset + i] = (char) c;
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 ());
|
|
|
|
}
|
|
|
|
|
2017-06-07 13:16:24 +00:00
|
|
|
public void Write (string text)
|
2014-08-13 10:39:27 +01:00
|
|
|
{
|
|
|
|
CheckOpen ();
|
2017-06-07 13:16:24 +00:00
|
|
|
if (text == null)
|
|
|
|
throw new ArgumentNullException ("text");
|
2014-08-13 10:39:27 +01:00
|
|
|
|
2017-06-07 13:16:24 +00:00
|
|
|
byte [] buffer = encoding.GetBytes (text);
|
2014-08-13 10:39:27 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2017-06-07 13:16:24 +00:00
|
|
|
public void WriteLine (string text)
|
2014-08-13 10:39:27 +01:00
|
|
|
{
|
2017-06-07 13:16:24 +00:00
|
|
|
Write (text + new_line);
|
2014-08-13 10:39:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
}
|
|
|
|
|