2006-12-22 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System / System.IO.Ports / SerialPortStream.cs
1 //
2 // System.IO.Ports.SerialPortStream.cs
3 //
4 // Authors:
5 //      Chris Toshok (toshok@ximian.com)
6 //      Carlos Alberto Cortez (calberto.cortez@gmail.com)
7 //
8 // (c) Copyright 2006 Novell, Inc. (http://www.novell.com)
9 //
10
11
12 #if NET_2_0
13
14 using System;
15 using System.IO;
16 using System.Runtime.InteropServices;
17
18 namespace System.IO.Ports
19 {
20         class SerialPortStream : Stream, ISerialStream, IDisposable
21         {
22                 int fd;
23                 int read_timeout;
24                 int write_timeout;
25                 bool disposed;
26
27                 [DllImport ("MonoPosixHelper")]
28                 static extern int open_serial (string portName);
29
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)
33                 {
34                         fd = open_serial (portName);
35                         if (fd == -1)
36                                 throw new IOException ();
37                         
38                         if (!set_attributes (fd, baudRate, parity, dataBits, stopBits, handshake))
39                                 throw new IOException (); // Probably Win32Exc for compatibility
40
41                         read_timeout = readTimeout;
42                         write_timeout = writeTimeout;
43                         
44                         SetSignal (SerialSignal.Dtr, dtrEnable);
45                         
46                         if (handshake != Handshake.RequestToSend && 
47                                         handshake != Handshake.RequestToSendXOnXOff)
48                                 SetSignal (SerialSignal.Rts, rtsEnable);
49                 }
50
51                 public override bool CanRead {
52                         get {
53                                 return true;
54                         }
55                 }
56
57                 public override bool CanSeek {
58                         get {
59                                 return false;
60                         }
61                 }
62
63                 public override bool CanWrite {
64                         get {
65                                 return true;
66                         }
67                 }
68
69                 public override bool CanTimeout {
70                         get {
71                                 return true;
72                         }
73                 }
74
75                 public override int ReadTimeout {
76                         get {
77                                 return read_timeout;
78                         }
79                         set {
80                                 if (value < 0 && value != SerialPort.InfiniteTimeout)
81                                         throw new ArgumentOutOfRangeException ("value");
82
83                                 read_timeout = value;
84                         }
85                 }
86
87                 public override int WriteTimeout {
88                         get {
89                                 return write_timeout;
90                         }
91                         set {
92                                 if (value < 0 && value != SerialPort.InfiniteTimeout)
93                                         throw new ArgumentOutOfRangeException ("value");
94
95                                 write_timeout = value;
96                         }
97                 }
98
99                 public override long Length {
100                         get {
101                                 throw new NotSupportedException ();
102                         }
103                 }
104
105                 public override long Position {
106                         get {
107                                 throw new NotSupportedException ();
108                         }
109                         set {
110                                 throw new NotSupportedException ();
111                         }
112                 }
113
114                 public override void Flush ()
115                 {
116                         // If used, this _could_ flush the serial port
117                         // buffer (not the SerialPort class buffer)
118                 }
119
120                 [DllImport ("MonoPosixHelper")]
121                 static extern int read_serial (int fd, byte [] buffer, int offset, int count);
122                 
123
124                 [DllImport ("MonoPosixHelper")]
125                 static extern bool poll_serial (int fd, out int error, int timeout);
126
127                 public override int Read ([In,Out] byte[] buffer, int offset, int count)
128                 {
129                         CheckDisposed ();
130                         if (buffer == null)
131                                 throw new ArgumentNullException ("buffer");
132                         if (offset < 0 || count < 0)
133                                 throw new ArgumentOutOfRangeException ("offset or count less than zero.");
134
135                         if (buffer.Length - offset < count )
136                                 throw new ArgumentException ("offset+count",
137                                                               "The size of the buffer is less than offset + count.");
138                         
139                         int error;
140                         bool poll_result = poll_serial (fd, out error, read_timeout);
141                         if (error == -1)
142                                 throw new IOException ();
143
144                         if (!poll_result) {
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();
148                         }
149
150                         return read_serial (fd, buffer, offset, count);
151                 }
152
153                 public override long Seek (long offset, SeekOrigin origin)
154                 {
155                         throw new NotSupportedException ();
156                 }
157
158                 public override void SetLength (long value)
159                 {
160                         throw new NotSupportedException ();
161                 }
162
163                 [DllImport ("MonoPosixHelper")]
164                 static extern void write_serial (int fd, byte [] buffer, int offset, int count, int timeout);
165
166                 public override void Write (byte[] buffer, int offset, int count)
167                 {
168                         CheckDisposed ();
169                         if (buffer == null)
170                                 throw new ArgumentNullException ("buffer");
171
172                         if (offset < 0 || count < 0)
173                                 throw new ArgumentOutOfRangeException ();
174
175                         if (buffer.Length - offset < count)
176                                 throw new ArgumentException ("offset+count",
177                                                              "The size of the buffer is less than offset + count.");
178
179                         write_serial (fd, buffer, offset, count, write_timeout);
180                 }
181
182                 protected override void Dispose (bool disposing)
183                 {
184                         if (disposed)
185                                 return;
186                         
187                         disposed = true;
188                         close_serial (fd);
189                 }
190
191                 [DllImport ("MonoPosixHelper")]
192                 static extern void close_serial (int fd);
193
194                 public override void Close ()
195                 {
196                         ((IDisposable) this).Dispose ();
197                 }
198
199                 void IDisposable.Dispose ()
200                 {
201                         Dispose (true);
202                         GC.SuppressFinalize (this);
203                 }
204
205                 ~SerialPortStream ()
206                 {
207                         Dispose (false);
208                 }
209
210                 void CheckDisposed ()
211                 {
212                         if (disposed)
213                                 throw new ObjectDisposedException (GetType ().FullName);
214                 }
215
216                 [DllImport ("MonoPosixHelper")]
217                 static extern bool set_attributes (int fd, int baudRate, Parity parity, int dataBits, StopBits stopBits, Handshake handshake);
218
219                 public void SetAttributes (int baud_rate, Parity parity, int data_bits, StopBits sb, Handshake hs)
220                 {
221                         if (!set_attributes (fd, baud_rate, parity, data_bits, sb, hs))
222                                 throw new IOException ();
223                 }
224
225                 [DllImport("MonoPosixHelper")]
226                 static extern int get_bytes_in_buffer (int fd, int input);
227                 
228                 public int BytesToRead {
229                         get {
230                                 return get_bytes_in_buffer (fd, 1);
231                         }
232                 }
233
234                 public int BytesToWrite {
235                         get {
236                                 return get_bytes_in_buffer (fd, 0);
237                         }
238                 }
239
240                 [DllImport ("MonoPosixHelper")]
241                 static extern void discard_buffer (int fd, bool inputBuffer);
242
243                 public void DiscardInBuffer ()
244                 {
245                         discard_buffer (fd, true);
246                 }
247
248                 public void DiscardOutBuffer ()
249                 {
250                         discard_buffer (fd, false);
251                 }
252                 
253                 [DllImport ("MonoPosixHelper")]
254                 static extern SerialSignal get_signals (int fd, out int error);
255
256                 public SerialSignal GetSignals ()
257                 {
258                         int error;
259                         SerialSignal signals = get_signals (fd, out error);
260                         if (error == -1)
261                                 throw new IOException ();
262
263                         return signals;
264                 }
265
266                 [DllImport ("MonoPosixHelper")]
267                 static extern int set_signal (int fd, SerialSignal signal, bool value);
268
269                 public void SetSignal (SerialSignal signal, bool value)
270                 {
271                         if (signal < SerialSignal.Cd || signal > SerialSignal.Rts ||
272                                         signal == SerialSignal.Cd ||
273                                         signal == SerialSignal.Cts ||
274                                         signal == SerialSignal.Dsr)
275                                 throw new Exception ("Invalid internal value");
276
277                         if (set_signal (fd, signal, value) == -1)
278                                 throw new IOException ();
279                 }
280
281                 public void SetBreakState (bool value)
282                 {
283                         throw new NotImplementedException ();
284                 }
285
286         }
287 }
288
289 #endif
290
291