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)
10 // Slightly modified by Konrad M. Kruczynski (added baud rate value checking)
15 using System.Runtime.InteropServices;
17 namespace System.IO.Ports
19 class SerialPortStream : Stream, ISerialStream, IDisposable
26 [DllImport ("MonoPosixHelper", SetLastError = true)]
27 static extern int open_serial (string portName);
29 public SerialPortStream (string portName, int baudRate, int dataBits, Parity parity, StopBits stopBits,
30 bool dtrEnable, bool rtsEnable, Handshake handshake, int readTimeout, int writeTimeout,
31 int readBufferSize, int writeBufferSize)
33 fd = open_serial (portName);
37 TryBaudRate (baudRate);
39 if (!set_attributes (fd, baudRate, parity, dataBits, stopBits, handshake))
40 ThrowIOException (); // Probably Win32Exc for compatibility
42 read_timeout = readTimeout;
43 write_timeout = writeTimeout;
45 SetSignal (SerialSignal.Dtr, dtrEnable);
47 if (handshake != Handshake.RequestToSend &&
48 handshake != Handshake.RequestToSendXOnXOff)
49 SetSignal (SerialSignal.Rts, rtsEnable);
52 public override bool CanRead {
58 public override bool CanSeek {
64 public override bool CanWrite {
70 public override bool CanTimeout {
76 public override int ReadTimeout {
81 if (value < 0 && value != SerialPort.InfiniteTimeout)
82 throw new ArgumentOutOfRangeException ("value");
88 public override int WriteTimeout {
93 if (value < 0 && value != SerialPort.InfiniteTimeout)
94 throw new ArgumentOutOfRangeException ("value");
96 write_timeout = value;
100 public override long Length {
102 throw new NotSupportedException ();
106 public override long Position {
108 throw new NotSupportedException ();
111 throw new NotSupportedException ();
115 public override void Flush ()
117 // If used, this _could_ flush the serial port
118 // buffer (not the SerialPort class buffer)
121 [DllImport ("MonoPosixHelper", SetLastError = true)]
122 static extern int read_serial (int fd, byte [] buffer, int offset, int count);
125 [DllImport ("MonoPosixHelper", SetLastError = true)]
126 static extern bool poll_serial (int fd, out int error, int timeout);
128 public override int Read ([In,Out] byte[] buffer, int offset, int count)
132 throw new ArgumentNullException ("buffer");
133 if (offset < 0 || count < 0)
134 throw new ArgumentOutOfRangeException ("offset or count less than zero.");
136 if (buffer.Length - offset < count )
137 throw new ArgumentException ("offset+count",
138 "The size of the buffer is less than offset + count.");
141 bool poll_result = poll_serial (fd, out error, read_timeout);
146 // see bug 79735 http://bugzilla.ximian.com/show_bug.cgi?id=79735
147 // should the next line read: return -1;
148 throw new TimeoutException();
151 int result = read_serial (fd, buffer, offset, count);
157 public override long Seek (long offset, SeekOrigin origin)
159 throw new NotSupportedException ();
162 public override void SetLength (long value)
164 throw new NotSupportedException ();
167 [DllImport ("MonoPosixHelper", SetLastError = true)]
168 static extern int write_serial (int fd, byte [] buffer, int offset, int count, int timeout);
170 public override void Write (byte[] buffer, int offset, int count)
174 throw new ArgumentNullException ("buffer");
176 if (offset < 0 || count < 0)
177 throw new ArgumentOutOfRangeException ();
179 if (buffer.Length - offset < count)
180 throw new ArgumentException ("offset+count",
181 "The size of the buffer is less than offset + count.");
183 // FIXME: this reports every write error as timeout
184 if (write_serial (fd, buffer, offset, count, write_timeout) < 0)
185 throw new TimeoutException("The operation has timed-out");
188 protected override void Dispose (bool disposing)
194 if (close_serial (fd) != 0)
198 [DllImport ("MonoPosixHelper", SetLastError = true)]
199 static extern int close_serial (int fd);
201 public override void Close ()
203 ((IDisposable) this).Dispose ();
206 void IDisposable.Dispose ()
209 GC.SuppressFinalize (this);
216 } catch (IOException) {
220 void CheckDisposed ()
223 throw new ObjectDisposedException (GetType ().FullName);
226 [DllImport ("MonoPosixHelper", SetLastError = true)]
227 static extern bool set_attributes (int fd, int baudRate, Parity parity, int dataBits, StopBits stopBits, Handshake handshake);
229 public void SetAttributes (int baud_rate, Parity parity, int data_bits, StopBits sb, Handshake hs)
231 if (!set_attributes (fd, baud_rate, parity, data_bits, sb, hs))
235 [DllImport("MonoPosixHelper", SetLastError = true)]
236 static extern int get_bytes_in_buffer (int fd, int input);
238 public int BytesToRead {
240 int result = get_bytes_in_buffer (fd, 1);
247 public int BytesToWrite {
249 int result = get_bytes_in_buffer (fd, 0);
256 [DllImport ("MonoPosixHelper", SetLastError = true)]
257 static extern int discard_buffer (int fd, bool inputBuffer);
259 public void DiscardInBuffer ()
261 if (discard_buffer (fd, true) != 0)
265 public void DiscardOutBuffer ()
267 if (discard_buffer (fd, false) != 0)
271 [DllImport ("MonoPosixHelper", SetLastError = true)]
272 static extern SerialSignal get_signals (int fd, out int error);
274 public SerialSignal GetSignals ()
277 SerialSignal signals = get_signals (fd, out error);
284 [DllImport ("MonoPosixHelper", SetLastError = true)]
285 static extern int set_signal (int fd, SerialSignal signal, bool value);
287 public void SetSignal (SerialSignal signal, bool value)
289 if (signal < SerialSignal.Cd || signal > SerialSignal.Rts ||
290 signal == SerialSignal.Cd ||
291 signal == SerialSignal.Cts ||
292 signal == SerialSignal.Dsr)
293 throw new Exception ("Invalid internal value");
295 if (set_signal (fd, signal, value) == -1)
299 [DllImport ("MonoPosixHelper", SetLastError = true)]
300 static extern int breakprop (int fd);
302 public void SetBreakState (bool value)
305 if (breakprop (fd) == -1)
310 static extern IntPtr strerror (int errnum);
312 static void ThrowIOException ()
314 int errnum = Marshal.GetLastWin32Error ();
315 string error_message = Marshal.PtrToStringAnsi (strerror (errnum));
317 throw new IOException (error_message);
320 [DllImport ("MonoPosixHelper")]
321 static extern bool is_baud_rate_legal (int baud_rate);
323 private void TryBaudRate (int baudRate)
325 if (!is_baud_rate_legal (baudRate))
327 // this kind of exception to be compatible with MSDN API
328 throw new ArgumentOutOfRangeException ("baudRate",
329 "Given baud rate is not supported on this platform.");