2 // System.IO.Ports.SerialPortStream.cs
5 // Chris Toshok (toshok@ximian.com)
6 // Carlos Alberto Cortez (calberto.cortez@gmail.com)
8 // (c) Copyright 2006 Novell, Inc. (http://www.novell.com)
16 using System.Runtime.InteropServices;
18 namespace System.IO.Ports
20 class SerialPortStream : Stream, ISerialStream, IDisposable
27 [DllImport ("MonoPosixHelper", SetLastError = true)]
28 static extern int open_serial (string portName);
30 public SerialPortStream (string portName, int baudRate, int dataBits, Parity parity, StopBits stopBits,
31 bool dtrEnable, bool rtsEnable, Handshake handshake, int readTimeout, int writeTimeout,
32 int readBufferSize, int writeBufferSize)
34 fd = open_serial (portName);
38 if (!set_attributes (fd, baudRate, parity, dataBits, stopBits, handshake))
39 ThrowIOException (); // Probably Win32Exc for compatibility
41 read_timeout = readTimeout;
42 write_timeout = writeTimeout;
44 SetSignal (SerialSignal.Dtr, dtrEnable);
46 if (handshake != Handshake.RequestToSend &&
47 handshake != Handshake.RequestToSendXOnXOff)
48 SetSignal (SerialSignal.Rts, rtsEnable);
51 public override bool CanRead {
57 public override bool CanSeek {
63 public override bool CanWrite {
69 public override bool CanTimeout {
75 public override int ReadTimeout {
80 if (value < 0 && value != SerialPort.InfiniteTimeout)
81 throw new ArgumentOutOfRangeException ("value");
87 public override int WriteTimeout {
92 if (value < 0 && value != SerialPort.InfiniteTimeout)
93 throw new ArgumentOutOfRangeException ("value");
95 write_timeout = value;
99 public override long Length {
101 throw new NotSupportedException ();
105 public override long Position {
107 throw new NotSupportedException ();
110 throw new NotSupportedException ();
114 public override void Flush ()
116 // If used, this _could_ flush the serial port
117 // buffer (not the SerialPort class buffer)
120 [DllImport ("MonoPosixHelper", SetLastError = true)]
121 static extern int read_serial (int fd, byte [] buffer, int offset, int count);
124 [DllImport ("MonoPosixHelper", SetLastError = true)]
125 static extern bool poll_serial (int fd, out int error, int timeout);
127 public override int Read ([In,Out] byte[] buffer, int offset, int count)
131 throw new ArgumentNullException ("buffer");
132 if (offset < 0 || count < 0)
133 throw new ArgumentOutOfRangeException ("offset or count less than zero.");
135 if (buffer.Length - offset < count )
136 throw new ArgumentException ("offset+count",
137 "The size of the buffer is less than offset + count.");
140 bool poll_result = poll_serial (fd, out error, read_timeout);
145 // see bug 79735 http://bugzilla.ximian.com/show_bug.cgi?id=79735
146 // should the next line read: return -1;
147 throw new TimeoutException();
150 int result = read_serial (fd, buffer, offset, count);
156 public override long Seek (long offset, SeekOrigin origin)
158 throw new NotSupportedException ();
161 public override void SetLength (long value)
163 throw new NotSupportedException ();
166 [DllImport ("MonoPosixHelper", SetLastError = true)]
167 static extern int write_serial (int fd, byte [] buffer, int offset, int count, int timeout);
169 public override void Write (byte[] buffer, int offset, int count)
173 throw new ArgumentNullException ("buffer");
175 if (offset < 0 || count < 0)
176 throw new ArgumentOutOfRangeException ();
178 if (buffer.Length - offset < count)
179 throw new ArgumentException ("offset+count",
180 "The size of the buffer is less than offset + count.");
182 // FIXME: this reports every write error as timeout
183 if (write_serial (fd, buffer, offset, count, write_timeout) < 0)
184 throw new TimeoutException("The operation has timed-out");
187 protected override void Dispose (bool disposing)
193 if (close_serial (fd) != 0)
197 [DllImport ("MonoPosixHelper", SetLastError = true)]
198 static extern int close_serial (int fd);
200 public override void Close ()
202 ((IDisposable) this).Dispose ();
205 void IDisposable.Dispose ()
208 GC.SuppressFinalize (this);
216 void CheckDisposed ()
219 throw new ObjectDisposedException (GetType ().FullName);
222 [DllImport ("MonoPosixHelper", SetLastError = true)]
223 static extern bool set_attributes (int fd, int baudRate, Parity parity, int dataBits, StopBits stopBits, Handshake handshake);
225 public void SetAttributes (int baud_rate, Parity parity, int data_bits, StopBits sb, Handshake hs)
227 if (!set_attributes (fd, baud_rate, parity, data_bits, sb, hs))
231 [DllImport("MonoPosixHelper", SetLastError = true)]
232 static extern int get_bytes_in_buffer (int fd, int input);
234 public int BytesToRead {
236 int result = get_bytes_in_buffer (fd, 1);
243 public int BytesToWrite {
245 int result = get_bytes_in_buffer (fd, 0);
252 [DllImport ("MonoPosixHelper", SetLastError = true)]
253 static extern int discard_buffer (int fd, bool inputBuffer);
255 public void DiscardInBuffer ()
257 if (discard_buffer (fd, true) != 0)
261 public void DiscardOutBuffer ()
263 if (discard_buffer (fd, false) != 0)
267 [DllImport ("MonoPosixHelper", SetLastError = true)]
268 static extern SerialSignal get_signals (int fd, out int error);
270 public SerialSignal GetSignals ()
273 SerialSignal signals = get_signals (fd, out error);
280 [DllImport ("MonoPosixHelper", SetLastError = true)]
281 static extern int set_signal (int fd, SerialSignal signal, bool value);
283 public void SetSignal (SerialSignal signal, bool value)
285 if (signal < SerialSignal.Cd || signal > SerialSignal.Rts ||
286 signal == SerialSignal.Cd ||
287 signal == SerialSignal.Cts ||
288 signal == SerialSignal.Dsr)
289 throw new Exception ("Invalid internal value");
291 if (set_signal (fd, signal, value) == -1)
295 [DllImport ("MonoPosixHelper", SetLastError = true)]
296 static extern int breakprop (int fd);
298 public void SetBreakState (bool value)
301 if (breakprop (fd) == -1)
306 static extern IntPtr strerror (int errnum);
308 static void ThrowIOException ()
310 int errnum = Marshal.GetLastWin32Error ();
311 string error_message = Marshal.PtrToStringAnsi (strerror (errnum));
313 throw new IOException (error_message);